diff --git a/.github/release_steps.md b/.github/release_steps.md index 1ffd3cb291..b08c8e892a 100644 --- a/.github/release_steps.md +++ b/.github/release_steps.md @@ -104,8 +104,8 @@ with a future release) from the `lammps-static` folder. rm -rf release-packages mkdir release-packages cd release-packages -wget https://download.lammps.org/static/fedora41_musl.sif -apptainer shell fedora41_musl.sif +wget https://download.lammps.org/static/fedora41_musl_mingw.sif +apptainer shell fedora41_musl_mingw.sif git clone -b release --depth 10 https://github.com/lammps/lammps.git lammps-release cmake -S lammps-release/cmake -B build-release -G Ninja -D CMAKE_INSTALL_PREFIX=$PWD/lammps-static -D CMAKE_TOOLCHAIN_FILE=/usr/musl/share/cmake/linux-musl.cmake -C lammps-release/cmake/presets/most.cmake -C lammps-release/cmake/presets/kokkos-openmp.cmake -D DOWNLOAD_POTENTIALS=OFF -D BUILD_MPI=OFF -D BUILD_TESTING=OFF -D CMAKE_BUILD_TYPE=Release -D PKG_ATC=ON -D PKG_AWPMD=ON -D PKG_MANIFOLD=ON -D PKG_MESONT=ON -D PKG_MGPT=ON -D PKG_ML-PACE=ON -D PKG_ML-RANN=ON -D PKG_MOLFILE=ON -D PKG_PTM=ON -D PKG_QTB=ON -D PKG_SMTBQ=ON cmake --build build-release --target all @@ -204,7 +204,7 @@ cd .. rm -r release-packages ``` -#### Build Multi-arch App-bundle for macOS +#### Build Multi-arch App-bundle with GUI for macOS Building app-bundles for macOS is not as easily automated and portable as some of the other steps. It requires a machine actually running @@ -251,7 +251,7 @@ 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 +#### Build Linux x86_64 binary tarball with GUI 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 diff --git a/.github/workflows/check-cpp23.yml b/.github/workflows/check-cpp23.yml index 2cd53f2208..15b16e71e4 100644 --- a/.github/workflows/check-cpp23.yml +++ b/.github/workflows/check-cpp23.yml @@ -1,4 +1,4 @@ -# GitHub action to build LAMMPS on Linux with gcc and C++23 +# GitHub action to build LAMMPS on Linux with gcc or clang and C++23 name: "Check for C++23 Compatibility" on: @@ -11,11 +11,19 @@ on: workflow_dispatch: +concurrency: + group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{github.event_name == 'pull_request'}} + jobs: build: name: Build with C++23 support enabled if: ${{ github.repository == 'lammps/lammps' }} runs-on: ubuntu-latest + strategy: + max-parallel: 2 + matrix: + idx: [ gcc, clang ] env: CCACHE_DIR: ${{ github.workspace }}/.ccache @@ -29,8 +37,11 @@ jobs: run: | sudo apt-get update sudo apt-get install -y ccache \ - libeigen3-dev \ + clang \ libcurl4-openssl-dev \ + libeigen3-dev \ + libfftw3-dev \ + libomp-dev \ mold \ mpi-default-bin \ mpi-default-dev \ @@ -58,14 +69,14 @@ jobs: cmake -S cmake -B build \ -C cmake/presets/most.cmake \ -C cmake/presets/kokkos-openmp.cmake \ + -C cmake/presets/${{ matrix.idx }}.cmake \ -D CMAKE_CXX_STANDARD=23 \ - -D CMAKE_CXX_COMPILER=g++ \ - -D CMAKE_C_COMPILER=gcc \ -D CMAKE_CXX_COMPILER_LAUNCHER=ccache \ -D CMAKE_C_COMPILER_LAUNCHER=ccache \ -D CMAKE_BUILD_TYPE=Debug \ -D CMAKE_CXX_FLAGS_DEBUG="-Og -g" \ -D DOWNLOAD_POTENTIALS=off \ + -D FFT=KISS \ -D BUILD_MPI=on \ -D BUILD_SHARED_LIBS=on \ -D BUILD_TOOLS=off \ diff --git a/README b/README index 6477eb41d3..3820353408 100644 --- a/README +++ b/README @@ -34,6 +34,7 @@ lib additional provided or external libraries potentials interatomic potential files python Python module for LAMMPS src source files +third_party Copies of thirdparty software bundled with LAMMPS tools pre- and post-processing tools unittest test programs for use with CTest .github Git and GitHub related files and tools diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index f22fa401a2..954bd7b4ac 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -7,6 +7,10 @@ if(CMAKE_VERSION VERSION_LESS 3.20) message(WARNING "LAMMPS is planning to require at least CMake version 3.20 by Summer 2025. Please upgrade!") endif() ######################################## +# initialize version variables with project command +if(POLICY CMP0048) + cmake_policy(SET CMP0048 NEW) +endif() # set policy to silence warnings about ignoring _ROOT but use it if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) @@ -27,7 +31,10 @@ endif() ######################################## -project(lammps CXX) +project(lammps + DESCRIPTION "The LAMMPS Molecular Dynamics Simulator" + HOMEPAGE_URL "https://www.lammps.org" + LANGUAGES CXX C) set(SOVERSION 0) get_property(BUILD_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -44,6 +51,7 @@ set(LAMMPS_DOC_DIR ${LAMMPS_DIR}/doc) set(LAMMPS_TOOLS_DIR ${LAMMPS_DIR}/tools) set(LAMMPS_PYTHON_DIR ${LAMMPS_DIR}/python) set(LAMMPS_POTENTIALS_DIR ${LAMMPS_DIR}/potentials) +set(LAMMPS_THIRDPARTY_DIR ${LAMMPS_DIR}/third_party) set(LAMMPS_DOWNLOADS_URL "https://download.lammps.org" CACHE STRING "Base URL for LAMMPS downloads") set(LAMMPS_POTENTIALS_URL "${LAMMPS_DOWNLOADS_URL}/potentials") @@ -105,46 +113,35 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Qrestrict") endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) - set(CMAKE_TUNE_DEFAULT "/QxCOMMON-AVX512") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /QxCOMMON-AVX512") else() - set(CMAKE_TUNE_DEFAULT "/QxHost") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /QxHost") endif() else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict") if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) - set(CMAKE_TUNE_DEFAULT "-xCOMMON-AVX512") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -xCOMMON-AVX512") else() - set(CMAKE_TUNE_DEFAULT "-xHost -fp-model fast=2 -no-prec-div -qoverride-limits -diag-disable=10441 -diag-disable=11074 -diag-disable=11076 -diag-disable=2196") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -xHost -fp-model fast=2 -no-prec-div -qoverride-limits -diag-disable=10441 -diag-disable=11074 -diag-disable=11076 -diag-disable=2196") endif() endif() endif() # silence excessive warnings for new Intel Compilers if(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") - set(CMAKE_TUNE_DEFAULT "-fp-model precise -Wno-tautological-constant-compare -Wno-unused-command-line-argument") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fp-model precise -Wno-tautological-constant-compare -Wno-unused-command-line-argument") endif() # silence excessive warnings for PGI/NVHPC compilers if((CMAKE_CXX_COMPILER_ID STREQUAL "NVHPC") OR (CMAKE_CXX_COMPILER_ID STREQUAL "PGI")) - set(CMAKE_TUNE_DEFAULT "-Minform=severe") -endif() - -# this hack is required to compile fmt lib with CrayClang version 15.0.2 -# CrayClang is only directly recognized by version 3.28 and later -if(CMAKE_VERSION VERSION_LESS 3.28) - get_filename_component(_exe "${CMAKE_CXX_COMPILER}" NAME) - if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (_exe STREQUAL "crayCC")) - set(CMAKE_TUNE_DEFAULT "-DFMT_STATIC_THOUSANDS_SEPARATOR") - endif() -else() - if(CMAKE_CXX_COMPILER_ID STREQUAL "CrayClang") - set(CMAKE_TUNE_DEFAULT "-DFMT_STATIC_THOUSANDS_SEPARATOR") - endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Minform=severe") endif() # silence nvcc warnings -if((PKG_KOKKOS) AND (Kokkos_ENABLE_CUDA) AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) - set(CMAKE_TUNE_DEFAULT "${CMAKE_TUNE_DEFAULT}" "-Xcudafe --diag_suppress=unrecognized_pragma,--diag_suppress=128") +if((PKG_KOKKOS) AND (Kokkos_ENABLE_CUDA) AND NOT + ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") + OR (CMAKE_CXX_COMPILER_ID STREQUAL "XLClang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "CrayClang"))) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xcudafe --diag_suppress=unrecognized_pragma,--diag_suppress=128") endif() # we *require* C++11 without extensions but prefer C++17. @@ -206,6 +203,10 @@ if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND BUILD_SHARED_LIBS) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) endif() +# do not include the (obsolete) MPI C++ bindings which makes for leaner object files +# and avoids namespace conflicts. Put this early to increase its visbility. +set(MPI_CXX_SKIP_MPICXX TRUE CACHE BOOL "Skip MPI C++ Bindings" FORCE) + ######################################################################## # User input options # ######################################################################## @@ -383,12 +384,12 @@ endforeach() # packages with special compiler needs or external libs ###################################################### target_include_directories(lammps PUBLIC $) +target_include_directories(lammps PUBLIC $) if(PKG_ADIOS) # The search for ADIOS2 must come before MPI because # it includes its own MPI search with the latest FindMPI.cmake # script that defines the MPI::MPI_C target - enable_language(C) find_package(ADIOS2 REQUIRED) if(BUILD_MPI) if(NOT ADIOS2_HAVE_MPI) @@ -403,21 +404,18 @@ if(PKG_ADIOS) endif() if(NOT CMAKE_CROSSCOMPILING) - find_package(MPI QUIET) + find_package(MPI QUIET COMPONENTS CXX) option(BUILD_MPI "Build MPI version" ${MPI_FOUND}) else() option(BUILD_MPI "Build MPI version" OFF) endif() if(BUILD_MPI) - # do not include the (obsolete) MPI C++ bindings which makes - # for leaner object files and avoids namespace conflicts - set(MPI_CXX_SKIP_MPICXX TRUE) # We use a non-standard procedure to cross-compile with MPI on Windows if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND CMAKE_CROSSCOMPILING) include(MPI4WIN) else() - find_package(MPI REQUIRED) + find_package(MPI REQUIRED COMPONENTS CXX) option(LAMMPS_LONGLONG_TO_LONG "Workaround if your system or MPI version does not recognize 'long long' data types" OFF) if(LAMMPS_LONGLONG_TO_LONG) target_compile_definitions(lammps PRIVATE -DLAMMPS_LONGLONG_TO_LONG) @@ -450,6 +448,19 @@ if(NOT ${LAMMPS_MEMALIGN} STREQUAL "0") target_compile_definitions(lammps PRIVATE -DLAMMPS_MEMALIGN=${LAMMPS_MEMALIGN}) endif() +# this hack is required to compile fmt lib with CrayClang version 15.0.2 +# CrayClang is only directly recognized by CMake version 3.28 and later +if(CMAKE_VERSION VERSION_LESS 3.28) + get_filename_component(_exe "${CMAKE_CXX_COMPILER}" NAME) + if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (_exe STREQUAL "crayCC")) + target_compile_definitions(lammps PRIVATE -DFMT_STATIC_THOUSANDS_SEPARATOR) + endif() +else() + if(CMAKE_CXX_COMPILER_ID STREQUAL "CrayClang") + target_compile_definitions(lammps PRIVATE -DFMT_STATIC_THOUSANDS_SEPARATOR) + endif() +endif() + # "hard" dependencies between packages resulting # in an error instead of skipping over files pkg_depends(ML-IAP ML-SNAP) @@ -507,13 +518,13 @@ if(BUILD_OMP) if(CMAKE_VERSION VERSION_LESS 3.28) get_filename_component(_exe "${CMAKE_CXX_COMPILER}" NAME) if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (_exe STREQUAL "crayCC")) - set(CMAKE_SHARED_LINKER_FLAGS_${BTYPE} "${CMAKE_SHARED_LINKER_FLAGS_${BTYPE}} -fopenmp") - set(CMAKE_STATIC_LINKER_FLAGS_${BTYPE} "${CMAKE_STATIC_LINKER_FLAGS_${BTYPE}} -fopenmp") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fopenmp") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -fopenmp") endif() else() if(CMAKE_CXX_COMPILER_ID STREQUAL "CrayClang") - set(CMAKE_SHARED_LINKER_FLAGS_${BTYPE} "${CMAKE_SHARED_LINKER_FLAGS_${BTYPE}} -fopenmp") - set(CMAKE_STATIC_LINKER_FLAGS_${BTYPE} "${CMAKE_STATIC_LINKER_FLAGS_${BTYPE}} -fopenmp") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fopenmp") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -fopenmp") endif() endif() endif() @@ -531,7 +542,6 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "Intel") AND (CMAKE_CXX_STANDARD GREATER_EQUA endif() if(PKG_ATC OR PKG_AWPMD OR PKG_ML-QUIP OR PKG_ML-POD OR PKG_ELECTRODE OR PKG_RHEO OR BUILD_TOOLS) - enable_language(C) if (NOT USE_INTERNAL_LINALG) find_package(LAPACK) find_package(BLAS) @@ -628,10 +638,6 @@ if(WITH_SWIG) add_subdirectory(${LAMMPS_SWIG_DIR} swig) endif() -set(CMAKE_TUNE_FLAGS "${CMAKE_TUNE_DEFAULT}" CACHE STRING "Compiler and machine specific optimization flags (compilation only)") -separate_arguments(CMAKE_TUNE_FLAGS) -target_compile_options(lammps PRIVATE ${CMAKE_TUNE_FLAGS}) -target_compile_options(lmp PRIVATE ${CMAKE_TUNE_FLAGS}) ######################################################################## # Basic system tests (standard libraries, headers, functions, types) # ######################################################################## diff --git a/cmake/Modules/LAMMPSInterfacePlugin.cmake b/cmake/Modules/LAMMPSInterfacePlugin.cmake index 5b7444f62c..a449f5b3dd 100644 --- a/cmake/Modules/LAMMPSInterfacePlugin.cmake +++ b/cmake/Modules/LAMMPSInterfacePlugin.cmake @@ -62,6 +62,9 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") endif() set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) +# skip over obsolete MPI-2 C++ bindings +set(MPI_CXX_SKIP_MPICXX TRUE) + ####### # helper functions from LAMMPSUtils.cmake function(validate_option name values) @@ -128,8 +131,7 @@ endif() ################################################################################ # MPI configuration if(NOT CMAKE_CROSSCOMPILING) - set(MPI_CXX_SKIP_MPICXX TRUE) - find_package(MPI QUIET) + find_package(MPI QUIET COMPONENTS CXX) option(BUILD_MPI "Build MPI version" ${MPI_FOUND}) else() option(BUILD_MPI "Build MPI version" OFF) @@ -141,78 +143,38 @@ if(BUILD_MPI) set(MPI_CXX_SKIP_MPICXX TRUE) # We use a non-standard procedure to cross-compile with MPI on Windows if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND CMAKE_CROSSCOMPILING) - # Download and configure MinGW compatible MPICH development files for Windows - option(USE_MSMPI "Use Microsoft's MS-MPI SDK instead of MPICH2-1.4.1" OFF) - if(USE_MSMPI) - message(STATUS "Downloading and configuring MS-MPI 10.1 for Windows cross-compilation") - set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/msmpi-win64-devel.tar.gz" CACHE STRING "URL for MS-MPI (win64) tarball") - set(MPICH2_WIN64_DEVEL_MD5 "86314daf1bffb809f1fcbefb8a547490" CACHE STRING "MD5 checksum of MS-MPI (win64) tarball") - mark_as_advanced(MPICH2_WIN64_DEVEL_URL) - mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) + message(STATUS "Downloading and configuring MS-MPI 10.1 for Windows cross-compilation") + set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/msmpi-win64-devel.tar.gz" CACHE STRING "URL for MS-MPI (win64) tarball") + set(MPICH2_WIN64_DEVEL_MD5 "86314daf1bffb809f1fcbefb8a547490" CACHE STRING "MD5 checksum of MS-MPI (win64) tarball") + mark_as_advanced(MPICH2_WIN64_DEVEL_URL) + mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) - include(ExternalProject) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN64_DEVEL_URL} - URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmsmpi.a) - else() - message(FATAL_ERROR "Only x86 64-bit builds are supported with MS-MPI") - endif() - - ExternalProject_get_property(mpi4win_build SOURCE_DIR) - file(MAKE_DIRECTORY "${SOURCE_DIR}/include") - add_library(MPI::MPI_CXX UNKNOWN IMPORTED) - set_target_properties(MPI::MPI_CXX PROPERTIES - IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmsmpi.a" - INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" - INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - add_dependencies(MPI::MPI_CXX mpi4win_build) - - # set variables for status reporting at the end of CMake run - set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") - set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmsmpi.a") + include(ExternalProject) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + ExternalProject_Add(mpi4win_build + URL ${MPICH2_WIN64_DEVEL_URL} + URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} + CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" + BUILD_BYPRODUCTS /lib/libmsmpi.a) else() - # Download and configure custom MPICH files for Windows - message(STATUS "Downloading and configuring MPICH-1.4.1 for Windows") - set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/mpich2-win64-devel.tar.gz" CACHE STRING "URL for MPICH2 (win64) tarball") - set(MPICH2_WIN64_DEVEL_MD5 "4939fdb59d13182fd5dd65211e469f14" CACHE STRING "MD5 checksum of MPICH2 (win64) tarball") - mark_as_advanced(MPICH2_WIN64_DEVEL_URL) - mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) - - include(ExternalProject) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN64_DEVEL_URL} - URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmpi.a) - else() - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN32_DEVEL_URL} - URL_MD5 ${MPICH2_WIN32_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmpi.a) - endif() - - ExternalProject_get_property(mpi4win_build SOURCE_DIR) - file(MAKE_DIRECTORY "${SOURCE_DIR}/include") - add_library(MPI::MPI_CXX UNKNOWN IMPORTED) - set_target_properties(MPI::MPI_CXX PROPERTIES - IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmpi.a" - INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" - INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - add_dependencies(MPI::MPI_CXX mpi4win_build) - - # set variables for status reporting at the end of CMake run - set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") - set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmpi.a") + message(FATAL_ERROR "Only x86 64-bit builds are supported with MS-MPI") endif() + + ExternalProject_get_property(mpi4win_build SOURCE_DIR) + file(MAKE_DIRECTORY "${SOURCE_DIR}/include") + add_library(MPI::MPI_CXX UNKNOWN IMPORTED) + set_target_properties(MPI::MPI_CXX PROPERTIES + IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmsmpi.a" + INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" + INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX=1") + add_dependencies(MPI::MPI_CXX mpi4win_build) + + # set variables for status reporting at the end of CMake run + set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") + set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX=1") + set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmsmpi.a") else() - find_package(MPI REQUIRED) + find_package(MPI REQUIRED COMPONENTS CXX) option(LAMMPS_LONGLONG_TO_LONG "Workaround if your system or MPI version does not recognize 'long long' data types" OFF) if(LAMMPS_LONGLONG_TO_LONG) target_compile_definitions(lammps INTERFACE -DLAMMPS_LONGLONG_TO_LONG) diff --git a/cmake/Modules/LAMMPSUtils.cmake b/cmake/Modules/LAMMPSUtils.cmake index 223577fe31..93f541f921 100644 --- a/cmake/Modules/LAMMPSUtils.cmake +++ b/cmake/Modules/LAMMPSUtils.cmake @@ -30,7 +30,7 @@ function(check_omp_h_include) if(OpenMP_CXX_FOUND) set(CMAKE_REQUIRED_FLAGS ${OpenMP_CXX_FLAGS}) set(CMAKE_REQUIRED_INCLUDES ${OpenMP_CXX_INCLUDE_DIRS}) - set(CMAKE_REQUIRED_LINK_OPTIONS ${OpenMP_CXX_FLAGS}) + separate_arguments(CMAKE_REQUIRED_LINK_OPTIONS NATIVE_COMMAND ${OpenMP_CXX_FLAGS}) # needs to be a list set(CMAKE_REQUIRED_LIBRARIES ${OpenMP_CXX_LIBRARIES}) # there are all kinds of problems with finding omp.h # for Clang and derived compilers so we pretend it is there. @@ -75,13 +75,25 @@ function(get_lammps_version version_header variable) list(FIND MONTHS "${month}" month) string(LENGTH ${day} day_length) string(LENGTH ${month} month_length) - if(day_length EQUAL 1) - set(day "0${day}") + # no leading zero needed for new version string with dots + # if(day_length EQUAL 1) + # set(day "0${day}") + # endif() + # if(month_length EQUAL 1) + # set(month "0${month}") + #endif() + file(STRINGS ${version_header} line REGEX LAMMPS_UPDATE) + string(REGEX REPLACE "#define LAMMPS_UPDATE \"Update ([0-9]+)\"" "\\1" tweak "${line}") + if (line MATCHES "#define LAMMPS_UPDATE \"(Maintenance|Development)\"") + set(tweak "99") endif() - if(month_length EQUAL 1) - set(month "0${month}") + if(NOT tweak) + set(tweak "0") endif() - set(${variable} "${year}${month}${day}" PARENT_SCOPE) + # new version string with dots + set(${variable} "${year}.${month}.${day}.${tweak}" PARENT_SCOPE) + # old version string without dots + # set(${variable} "${year}${month}${day}" PARENT_SCOPE) endfunction() function(check_for_autogen_files source_dir) diff --git a/cmake/Modules/MPI4WIN.cmake b/cmake/Modules/MPI4WIN.cmake index 02db6d4744..cd48ab279e 100644 --- a/cmake/Modules/MPI4WIN.cmake +++ b/cmake/Modules/MPI4WIN.cmake @@ -1,74 +1,31 @@ -# Download and configure MinGW compatible MPICH development files for Windows -option(USE_MSMPI "Use Microsoft's MS-MPI SDK instead of MPICH2-1.4.1" OFF) +# set-up MS-MPI library for Windows with MinGW compatibility +message(STATUS "Downloading and configuring MS-MPI 10.1 for Windows cross-compilation") +set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/msmpi-win64-devel.tar.gz" CACHE STRING "URL for MS-MPI (win64) tarball") +set(MPICH2_WIN64_DEVEL_MD5 "86314daf1bffb809f1fcbefb8a547490" CACHE STRING "MD5 checksum of MS-MPI (win64) tarball") +mark_as_advanced(MPICH2_WIN64_DEVEL_URL) +mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) -if(USE_MSMPI) - message(STATUS "Downloading and configuring MS-MPI 10.1 for Windows cross-compilation") - set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/msmpi-win64-devel.tar.gz" CACHE STRING "URL for MS-MPI (win64) tarball") - set(MPICH2_WIN64_DEVEL_MD5 "86314daf1bffb809f1fcbefb8a547490" CACHE STRING "MD5 checksum of MS-MPI (win64) tarball") - mark_as_advanced(MPICH2_WIN64_DEVEL_URL) - mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) - - include(ExternalProject) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN64_DEVEL_URL} - URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmsmpi.a) - else() - message(FATAL_ERROR "Only x86 64-bit builds are supported with MS-MPI") - endif() - - ExternalProject_get_property(mpi4win_build SOURCE_DIR) - file(MAKE_DIRECTORY "${SOURCE_DIR}/include") - add_library(MPI::MPI_CXX UNKNOWN IMPORTED) - set_target_properties(MPI::MPI_CXX PROPERTIES - IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmsmpi.a" - INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" - INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - add_dependencies(MPI::MPI_CXX mpi4win_build) - - # set variables for status reporting at the end of CMake run - set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") - set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmsmpi.a") +include(ExternalProject) +if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + ExternalProject_Add(mpi4win_build + URL ${MPICH2_WIN64_DEVEL_URL} + URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} + CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" + BUILD_BYPRODUCTS /lib/libmsmpi.a) else() - message(STATUS "Downloading and configuring MPICH2-1.4.1 for Windows cross-compilation") - set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/mpich2-win64-devel.tar.gz" CACHE STRING "URL for MPICH2 (win64) tarball") - set(MPICH2_WIN32_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/mpich2-win32-devel.tar.gz" CACHE STRING "URL for MPICH2 (win32) tarball") - set(MPICH2_WIN64_DEVEL_MD5 "4939fdb59d13182fd5dd65211e469f14" CACHE STRING "MD5 checksum of MPICH2 (win64) tarball") - set(MPICH2_WIN32_DEVEL_MD5 "a61d153500dce44e21b755ee7257e031" CACHE STRING "MD5 checksum of MPICH2 (win32) tarball") - mark_as_advanced(MPICH2_WIN64_DEVEL_URL) - mark_as_advanced(MPICH2_WIN32_DEVEL_URL) - mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) - mark_as_advanced(MPICH2_WIN32_DEVEL_MD5) - - include(ExternalProject) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN64_DEVEL_URL} - URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmpi.a) - else() - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN32_DEVEL_URL} - URL_MD5 ${MPICH2_WIN32_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmpi.a) - endif() - - ExternalProject_get_property(mpi4win_build SOURCE_DIR) - file(MAKE_DIRECTORY "${SOURCE_DIR}/include") - add_library(MPI::MPI_CXX UNKNOWN IMPORTED) - set_target_properties(MPI::MPI_CXX PROPERTIES - IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmpi.a" - INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" - INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - add_dependencies(MPI::MPI_CXX mpi4win_build) - - # set variables for status reporting at the end of CMake run - set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") - set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmpi.a") + message(FATAL_ERROR "Only x86 64-bit builds are supported with MS-MPI") endif() + +ExternalProject_get_property(mpi4win_build SOURCE_DIR) +file(MAKE_DIRECTORY "${SOURCE_DIR}/include") +add_library(MPI::MPI_CXX UNKNOWN IMPORTED) +set_target_properties(MPI::MPI_CXX PROPERTIES + IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmsmpi.a" + INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" + INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX=1") +add_dependencies(MPI::MPI_CXX mpi4win_build) + +# set variables for status reporting at the end of CMake run +set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") +set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX=1") +set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmsmpi.a") diff --git a/cmake/Modules/Packages/COLVARS.cmake b/cmake/Modules/Packages/COLVARS.cmake index b943a0345e..afef315120 100644 --- a/cmake/Modules/Packages/COLVARS.cmake +++ b/cmake/Modules/Packages/COLVARS.cmake @@ -14,10 +14,6 @@ endif() add_library(colvars STATIC ${COLVARS_SOURCES}) target_compile_definitions(colvars PRIVATE -DCOLVARS_LAMMPS) -separate_arguments(CMAKE_TUNE_FLAGS) -foreach(_FLAG ${CMAKE_TUNE_FLAGS}) - target_compile_options(colvars PRIVATE ${_FLAG}) -endforeach() set_target_properties(colvars PROPERTIES OUTPUT_NAME lammps_colvars${LAMMPS_MACHINE}) target_include_directories(colvars PUBLIC ${LAMMPS_LIB_SOURCE_DIR}/colvars) # The line below is needed to locate math_eigen_impl.h @@ -30,6 +26,10 @@ if(BUILD_OMP) target_link_libraries(colvars PRIVATE OpenMP::OpenMP_CXX) endif() +if(BUILD_MPI) + target_link_libraries(colvars PUBLIC MPI::MPI_CXX) +endif() + if(COLVARS_DEBUG) # Need to export the define publicly to be valid in interface code target_compile_definitions(colvars PUBLIC -DCOLVARS_DEBUG) diff --git a/cmake/Modules/Packages/GPU.cmake b/cmake/Modules/Packages/GPU.cmake index 6d0ce303a5..dd4ac31025 100644 --- a/cmake/Modules/Packages/GPU.cmake +++ b/cmake/Modules/Packages/GPU.cmake @@ -189,7 +189,7 @@ if(GPU_API STREQUAL "CUDA") endif() add_executable(nvc_get_devices ${LAMMPS_LIB_SOURCE_DIR}/gpu/geryon/ucl_get_devices.cpp) - target_compile_definitions(nvc_get_devices PRIVATE -DUCL_CUDADR) + target_compile_definitions(nvc_get_devices PRIVATE -DUCL_CUDADR -DLAMMPS_${LAMMPS_SIZES}) target_link_libraries(nvc_get_devices PRIVATE ${CUDA_LIBRARIES} ${CUDA_CUDA_LIBRARY}) target_include_directories(nvc_get_devices PRIVATE ${CUDA_INCLUDE_DIRS}) @@ -489,7 +489,7 @@ else() target_link_libraries(gpu PRIVATE mpi_stubs) endif() -target_compile_definitions(gpu PRIVATE -DLAMMPS_${LAMMPS_SIZES}) set_target_properties(gpu PROPERTIES OUTPUT_NAME lammps_gpu${LAMMPS_MACHINE}) +target_compile_definitions(gpu PRIVATE -DLAMMPS_${LAMMPS_SIZES}) target_sources(lammps PRIVATE ${GPU_SOURCES}) target_include_directories(lammps PRIVATE ${GPU_SOURCES_DIR}) diff --git a/cmake/Modules/Packages/MC.cmake b/cmake/Modules/Packages/MC.cmake index f162254558..2a72a895cf 100644 --- a/cmake/Modules/Packages/MC.cmake +++ b/cmake/Modules/Packages/MC.cmake @@ -7,3 +7,13 @@ if(NOT PKG_MANYBODY) list(REMOVE_ITEM LAMMPS_SOURCES ${LAMMPS_SOURCE_DIR}/MC/fix_sgcmc.cpp) set_property(TARGET lammps PROPERTY SOURCES "${LAMMPS_SOURCES}") endif() + +# fix neighbor/swap may only be installed if also the VORONOI package is installed +if(NOT PKG_VORONOI) + get_property(LAMMPS_FIX_HEADERS GLOBAL PROPERTY FIX) + list(REMOVE_ITEM LAMMPS_FIX_HEADERS ${LAMMPS_SOURCE_DIR}/MC/fix_neighbor_swap.h) + set_property(GLOBAL PROPERTY FIX "${LAMMPS_FIX_HEADERS}") + get_target_property(LAMMPS_SOURCES lammps SOURCES) + list(REMOVE_ITEM LAMMPS_SOURCES ${LAMMPS_SOURCE_DIR}/MC/fix_neighbor_swap.cpp) + set_property(TARGET lammps PROPERTY SOURCES "${LAMMPS_SOURCES}") +endif() diff --git a/cmake/Modules/Packages/SCAFACOS.cmake b/cmake/Modules/Packages/SCAFACOS.cmake index 9a5580163f..2905a207b0 100644 --- a/cmake/Modules/Packages/SCAFACOS.cmake +++ b/cmake/Modules/Packages/SCAFACOS.cmake @@ -14,27 +14,16 @@ endif() option(DOWNLOAD_SCAFACOS "Download ScaFaCoS library instead of using an already installed one" ${DOWNLOAD_SCAFACOS_DEFAULT}) if(DOWNLOAD_SCAFACOS) message(STATUS "ScaFaCoS download requested - we will build our own") - set(SCAFACOS_URL "https://github.com/scafacos/scafacos/releases/download/v1.0.1/scafacos-1.0.1.tar.gz" CACHE STRING "URL for SCAFACOS tarball") - set(SCAFACOS_MD5 "bd46d74e3296bd8a444d731bb10c1738" CACHE STRING "MD5 checksum of SCAFACOS tarball") + set(SCAFACOS_URL "https://github.com/scafacos/scafacos/releases/download/v1.0.4/scafacos-1.0.4.tar.gz" CACHE STRING "URL for SCAFACOS tarball") + set(SCAFACOS_MD5 "23867540ec32e63ce71d6ecc105278d2" CACHE STRING "MD5 checksum of SCAFACOS tarball") mark_as_advanced(SCAFACOS_URL) mark_as_advanced(SCAFACOS_MD5) GetFallbackURL(SCAFACOS_URL SCAFACOS_FALLBACK) - - # version 1.0.1 needs a patch to compile and linke cleanly with GCC 10 and later. - file(DOWNLOAD ${LAMMPS_THIRDPARTY_URL}/scafacos-1.0.1-fix.diff ${CMAKE_CURRENT_BINARY_DIR}/scafacos-1.0.1.fix.diff - EXPECTED_HASH MD5=4baa1333bb28fcce102d505e1992d032) - - find_program(HAVE_PATCH patch) - if(NOT HAVE_PATCH) - message(FATAL_ERROR "The 'patch' program is required to build the ScaFaCoS library") - endif() - include(ExternalProject) ExternalProject_Add(scafacos_build URL ${SCAFACOS_URL} ${SCAFACOS_FALLBACK} URL_MD5 ${SCAFACOS_MD5} - PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_BINARY_DIR}/scafacos-1.0.1.fix.diff CONFIGURE_COMMAND /configure --prefix= --disable-doc --enable-fcs-solvers=fmm,p2nfft,direct,ewald,p3m --with-internal-fftw --with-internal-pfft diff --git a/cmake/Modules/Testing.cmake b/cmake/Modules/Testing.cmake index a72ce17e1b..7aa3506642 100644 --- a/cmake/Modules/Testing.cmake +++ b/cmake/Modules/Testing.cmake @@ -21,11 +21,11 @@ if(ENABLE_TESTING) # also only verified with Fedora Linux > 30 and Ubuntu 18.04 or 22.04+(Ubuntu 20.04 fails) if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))) - if(((CMAKE_LINUX_DISTRO STREQUAL "Ubuntu") AND - ((CMAKE_DISTRO_VERSION VERSION_LESS_EQUAL 18.04) OR (CMAKE_DISTRO_VERSION VERSION_GREATER_EQUAL 22.04))) + if(((CMAKE_LINUX_DISTRO STREQUAL "Ubuntu") AND (CMAKE_DISTRO_VERSION VERSION_GREATER_EQUAL 22.04)) OR ((CMAKE_LINUX_DISTRO STREQUAL "Fedora") AND (CMAKE_DISTRO_VERSION VERSION_GREATER 30))) include(CheckCXXCompilerFlag) set(CMAKE_CUSTOM_LINKER_DEFAULT default) + check_cxx_compiler_flag(--ld-path=${CMAKE_LINKER} HAVE_LD_PATH_FLAG) check_cxx_compiler_flag(-fuse-ld=mold HAVE_MOLD_LINKER_FLAG) check_cxx_compiler_flag(-fuse-ld=lld HAVE_LLD_LINKER_FLAG) check_cxx_compiler_flag(-fuse-ld=gold HAVE_GOLD_LINKER_FLAG) @@ -50,6 +50,17 @@ if(ENABLE_TESTING) if(NOT "${CMAKE_CUSTOM_LINKER}" STREQUAL "default") target_link_options(lammps PUBLIC -fuse-ld=${CMAKE_CUSTOM_LINKER}) endif() + if(HAVE_LD_PATH_FLAG) + if("${CMAKE_CUSTOM_LINKER}" STREQUAL "mold") + target_link_options(lammps PUBLIC --ld-path=${HAVE_MOLD_LINKER_BIN}) + elseif("${CMAKE_CUSTOM_LINKER}" STREQUAL "lld") + target_link_options(lammps PUBLIC --ld-path=${HAVE_LLD_LINKER_BIN}) + elseif("${CMAKE_CUSTOM_LINKER}" STREQUAL "gold") + target_link_options(lammps PUBLIC --ld-path=${HAVE_GOLD_LINKER_BIN}) + elseif("${CMAKE_CUSTOM_LINKER}" STREQUAL "bfd") + target_link_options(lammps PUBLIC --ld-path=${HAVE_BFD_LINKER_BIN}) + endif() + endif() endif() endif() diff --git a/cmake/presets/hip_amd.cmake b/cmake/presets/hip_amd.cmake index 4b8945e0c7..2cf28c05c4 100644 --- a/cmake/presets/hip_amd.cmake +++ b/cmake/presets/hip_amd.cmake @@ -19,12 +19,19 @@ set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "" FORCE) set(MPI_CXX "hipcc" CACHE STRING "" FORCE) set(MPI_CXX_COMPILER "mpicxx" CACHE STRING "" FORCE) +set(MPI_C "hipcc" CACHE STRING "" FORCE) +set(MPI_C_COMPILER "mpicc" CACHE STRING "" FORCE) + +# change as needed. This is for Fedora Linux 41 and 42 +set(_libomp_root "/usr/lib/clang/18") +# we need to explicitly specify the include dir, since hipcc will +# compile each file twice and doesn't find omp.h the second time unset(HAVE_OMP_H_INCLUDE CACHE) set(OpenMP_C "hipcc" CACHE STRING "" FORCE) -set(OpenMP_C_FLAGS "-fopenmp" CACHE STRING "" FORCE) +set(OpenMP_C_FLAGS "-fopenmp=libomp -I${_libomp_root}/include" CACHE STRING "" FORCE) set(OpenMP_C_LIB_NAMES "omp" CACHE STRING "" FORCE) set(OpenMP_CXX "hipcc" CACHE STRING "" FORCE) -set(OpenMP_CXX_FLAGS "-fopenmp" CACHE STRING "" FORCE) +set(OpenMP_CXX_FLAGS "-fopenmp=libomp -I${_libomp_root}/include" CACHE STRING "" FORCE) set(OpenMP_CXX_LIB_NAMES "omp" CACHE STRING "" FORCE) set(OpenMP_omp_LIBRARY "libomp.so" CACHE PATH "" FORCE) diff --git a/cmake/presets/kokkos-hip.cmake b/cmake/presets/kokkos-hip.cmake index 38bf27092f..58b09020fb 100644 --- a/cmake/presets/kokkos-hip.cmake +++ b/cmake/presets/kokkos-hip.cmake @@ -1,22 +1,21 @@ -# preset that enables KOKKOS and selects HIP compilation with OpenMP -# enabled as well. Also sets some performance related compiler flags. +# preset that enables KOKKOS and selects HIP compilation withOUT OpenMP. +# Kokkos OpenMP is not compatible with the second pass of hipcc. set(PKG_KOKKOS ON CACHE BOOL "" FORCE) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "" FORCE) -set(Kokkos_ENABLE_OPENMP ON CACHE BOOL "" FORCE) +set(Kokkos_ENABLE_OPENMP OFF CACHE BOOL "" FORCE) set(Kokkos_ENABLE_CUDA OFF CACHE BOOL "" FORCE) set(Kokkos_ENABLE_HIP ON CACHE BOOL "" FORCE) set(Kokkos_ARCH_VEGA90A on CACHE BOOL "" FORCE) set(Kokkos_ENABLE_HIP_MULTIPLE_KERNEL_INSTANTIATIONS ON CACHE BOOL "" FORCE) set(BUILD_OMP ON CACHE BOOL "" FORCE) -set(CMAKE_CXX_COMPILER hipcc CACHE STRING "" FORCE) -set(CMAKE_TUNE_FLAGS "-munsafe-fp-atomics" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -munsafe-fp-atomics" CACHE STRING "" FORCE) -# If KSPACE is also enabled, use CUFFT for FFTs +# If KSPACE is also enabled, use HIPFFT for FFTs set(FFT_KOKKOS "HIPFFT" CACHE STRING "" FORCE) # hide deprecation warnings temporarily for stable release -set(Kokkos_ENABLE_DEPRECATION_WARNINGS OFF CACHE BOOL "" FORCE) +#set(Kokkos_ENABLE_DEPRECATION_WARNINGS OFF CACHE BOOL "" FORCE) # these flags are needed to build with Cray MPICH on OLCF Crusher #-D CMAKE_CXX_FLAGS="-I/${MPICH_DIR}/include" diff --git a/cmake/presets/kokkos-sycl-intel.cmake b/cmake/presets/kokkos-sycl-intel.cmake index eba386564d..586df85177 100644 --- a/cmake/presets/kokkos-sycl-intel.cmake +++ b/cmake/presets/kokkos-sycl-intel.cmake @@ -21,9 +21,10 @@ set(CMAKE_C_COMPILER icx CACHE STRING "" FORCE) set(CMAKE_Fortran_COMPILER "" CACHE STRING "" FORCE) set(MPI_CXX_COMPILER "mpicxx" CACHE STRING "" FORCE) set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE) -# Silence everything -set(CMAKE_CXX_FLAGS "-w" CACHE STRING "" FORCE) + +# set(_intel_sycl_flags " -w -fsycl -flink-huge-device-code -fsycl-targets=spir64_gen " +set(_intel_sycl_flags " -w -fsycl -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen ") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_intel_sycl_flags}" CACHE STRING "" FORCE) + #set(CMAKE_EXE_LINKER_FLAGS "-fsycl -flink-huge-device-code -fsycl-targets=spir64_gen " CACHE STRING "" FORCE) -#set(CMAKE_TUNE_FLAGS "-O3 -fsycl -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen" CACHE STRING "" FORCE) -set(CMAKE_EXE_LINKER_FLAGS "-fsycl -flink-huge-device-code " CACHE STRING "" FORCE) -set(CMAKE_TUNE_FLAGS "-O3 -fsycl -fsycl-device-code-split=per_kernel " CACHE STRING "" FORCE) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsycl -flink-huge-device-code " CACHE STRING "" FORCE) diff --git a/cmake/presets/kokkos-sycl-nvidia.cmake b/cmake/presets/kokkos-sycl-nvidia.cmake index c706aca7d8..bf4dfba225 100644 --- a/cmake/presets/kokkos-sycl-nvidia.cmake +++ b/cmake/presets/kokkos-sycl-nvidia.cmake @@ -14,5 +14,7 @@ set(Kokkos_ENABLE_DEPRECATION_WARNINGS OFF CACHE BOOL "" FORCE) set(CMAKE_CXX_COMPILER clang++ CACHE STRING "" FORCE) set(MPI_CXX_COMPILER "mpicxx" CACHE STRING "" FORCE) set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE) -set(CMAKE_SHARED_LINKER_FLAGS "-Xsycl-target-frontend -O3" CACHE STRING "" FORCE) -set(CMAKE_TUNE_FLAGS "-fgpu-inline-threshold=100000 -Xsycl-target-frontend -O3 -Xsycl-target-frontend -ffp-contract=on -Wno-unknown-cuda-version" CACHE STRING "" FORCE) +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xsycl-target-frontend -O3 " CACHE STRING "" FORCE) + +set(_intel_sycl_flags "-fgpu-inline-threshold=100000 -Xsycl-target-frontend -O3 -Xsycl-target-frontend -ffp-contract=on -Wno-unknown-cuda-version") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_intel_sycl_flags}" CACHE STRING "" FORCE) diff --git a/cmake/presets/mingw-cross.cmake b/cmake/presets/mingw-cross.cmake index 413744b078..b5c5adb1f6 100644 --- a/cmake/presets/mingw-cross.cmake +++ b/cmake/presets/mingw-cross.cmake @@ -91,7 +91,7 @@ endif() set(DOWNLOAD_VORO ON CACHE BOOL "" FORCE) set(DOWNLOAD_EIGEN3 ON CACHE BOOL "" FORCE) set(LAMMPS_MEMALIGN "0" CACHE STRING "" FORCE) -set(CMAKE_TUNE_FLAGS "-Wno-missing-include-dirs" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-include-dirs" CACHE STRING "" FORCE) set(CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-stdcall-fixup,--as-needed,-lssp" CACHE STRING "" FORCE) set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-stdcall-fixup,--as-needed,-lssp" CACHE STRING "" FORCE) set(BUILD_TOOLS ON CACHE BOOL "" FORCE) diff --git a/cmake/presets/windows-intel-llvm.cmake b/cmake/presets/windows-intel-llvm.cmake index e9d88d22fe..ead4fbcfb5 100644 --- a/cmake/presets/windows-intel-llvm.cmake +++ b/cmake/presets/windows-intel-llvm.cmake @@ -5,4 +5,4 @@ set(CMAKE_C_COMPILER "icx" CACHE STRING "" FORCE) set(CMAKE_Fortran_COMPILER "ifx" CACHE STRING "" FORCE) set(INTEL_LRT_MODE "C++11" CACHE STRING "" FORCE) unset(HAVE_OMP_H_INCLUDE CACHE) -set(CMAKE_TUNE_FLAGS -Wno-unused-command-line-argument) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) diff --git a/doc/graphviz/lammps-releases.dot b/doc/graphviz/lammps-releases.dot index f641cac029..fb11f4bd68 100644 --- a/doc/graphviz/lammps-releases.dot +++ b/doc/graphviz/lammps-releases.dot @@ -5,13 +5,13 @@ digraph releases { github -> develop [label="Merge commits"]; { rank = "same"; - work [shape="none" label="Development branches:"] + work [shape="none" label="Development branches:" fontname="bold"] develop [label="'develop' branch" height=0.75]; maintenance [label="'maintenance' branch" height=0.75]; }; { rank = "same"; - upload [shape="none" label="Release branches:"] + upload [shape="none" label="Release branches:" fontname="bold"] release [label="'release' branch" height=0.75]; stable [label="'stable' branch" height=0.75]; }; @@ -22,7 +22,7 @@ digraph releases { maintenance -> stable [label="Updates to stable release"]; { rank = "same"; - tag [shape="none" label="Applied tags:"]; + tag [shape="none" label="Applied tags:" fontname="bold"]; patchtag [shape="box" label="patch_"]; stabletag [shape="box" label="stable_"]; updatetag [shape="box" label="stable__update"]; diff --git a/doc/src/Build.rst b/doc/src/Build.rst index ff09ee5678..c76ce2f434 100644 --- a/doc/src/Build.rst +++ b/doc/src/Build.rst @@ -14,32 +14,10 @@ As an alternative, you can download a package with pre-built executables or automated build trees, as described in the :doc:`Install ` section of the manual. -Prerequisites -------------- - -Which software you need to compile and use LAMMPS strongly depends on -which :doc:`features and settings ` and which -:doc:`optional packages ` 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 -` for more details. - .. toctree:: :maxdepth: 1 + Build_prerequisites Build_cmake Build_make Build_link diff --git a/doc/src/Build_basics.rst b/doc/src/Build_basics.rst index be4b312578..f9cf251688 100644 --- a/doc/src/Build_basics.rst +++ b/doc/src/Build_basics.rst @@ -212,11 +212,7 @@ LAMMPS. You can tell CMake to look for a specific compiler with setting CMake variables (listed below) during configuration. For a few common choices, there are also presets in the ``cmake/presets`` - folder. For convenience, there is a ``CMAKE_TUNE_FLAGS`` variable - that can be set to apply global compiler options (applied to - compilation only), to be used for adding compiler or host specific - optimization flags in addition to the "flags" variables listed - below. You may also specify the corresponding ``CMAKE_*_FLAGS`` + folder. You may also specify the corresponding ``CMAKE_*_FLAGS`` variables individually, if you want to experiment with alternate optimization flags. You should specify all 3 compilers, so that the (few) LAMMPS source files written in C or Fortran are built @@ -266,10 +262,6 @@ LAMMPS. ``-C ../cmake/presets/pgi.cmake`` will switch the compiler to the PGI compilers, and ``-C ../cmake/presets/nvhpc.cmake`` will switch to the NVHPC compilers. - Furthermore, you can set ``CMAKE_TUNE_FLAGS`` to specifically add - compiler flags to tune for optimal performance on given hosts. - This variable is empty by default. - .. note:: When the cmake command completes, it prints a summary to the diff --git a/doc/src/Build_prerequisites.rst b/doc/src/Build_prerequisites.rst new file mode 100644 index 0000000000..105de35102 --- /dev/null +++ b/doc/src/Build_prerequisites.rst @@ -0,0 +1,22 @@ +Prerequisites +------------- + +Which software you need to compile and use LAMMPS strongly depends on +which :doc:`features and settings ` and which +:doc:`optional packages ` 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 +` for more details. diff --git a/doc/src/Build_settings.rst b/doc/src/Build_settings.rst index 226e19bfc3..7c16409995 100644 --- a/doc/src/Build_settings.rst +++ b/doc/src/Build_settings.rst @@ -18,7 +18,6 @@ explains how to do this for building both with CMake and make. * `Memory allocation alignment`_ * `Workaround for long long integers`_ * `Exception handling when using LAMMPS as a library`_ to capture errors -* `Trigger selected floating-point exceptions`_ ---------- @@ -659,40 +658,3 @@ code has to be set up to *catch* exceptions thrown from within LAMMPS. throw an exception and thus other MPI ranks may get stuck waiting for messages from the ones with errors. ----------- - -.. _trap_fpe: - -Trigger selected floating-point exceptions ------------------------------------------- - -Many kinds of CPUs have the capability to detect when a calculation -results in an invalid math operation, like a division by zero or calling -the square root with a negative argument. The default behavior on -most operating systems is to continue and have values for ``NaN`` (= not -a number) or ``Inf`` (= infinity). This allows software to detect and -recover from such conditions. This behavior can be changed, however, -often through use of compiler flags. On Linux systems (or more general -on systems using the GNU C library), these so-called floating-point traps -can also be selectively enabled through library calls. LAMMPS supports -that by setting the ``-DLAMMPS_TRAP_FPE`` pre-processor define. As it is -done in the ``main()`` function, this applies only to the standalone -executable, not the library. - -.. tabs:: - - .. tab:: CMake build - - .. code-block:: bash - - -D CMAKE_TUNE_FLAGS=-DLAMMPS_TRAP_FPE - - .. tab:: Traditional make - - .. code-block:: make - - LMP_INC = -DLAMMPS_TRAP_FPE - -After compilation with this flag set, the LAMMPS executable will stop -and produce a core dump when a division by zero, overflow, illegal math -function argument or other invalid floating point operation is encountered. diff --git a/doc/src/Commands_fix.rst b/doc/src/Commands_fix.rst index 35c3804969..700abe0c2b 100644 --- a/doc/src/Commands_fix.rst +++ b/doc/src/Commands_fix.rst @@ -29,6 +29,7 @@ OPT. * :doc:`ave/grid ` * :doc:`ave/histo ` * :doc:`ave/histo/weight ` + * :doc:`ave/moments ` * :doc:`ave/time ` * :doc:`aveforce ` * :doc:`balance ` @@ -77,6 +78,7 @@ OPT. * :doc:`flow/gauss ` * :doc:`freeze (k) ` * :doc:`gcmc ` + * :doc:`gjf ` * :doc:`gld ` * :doc:`gle ` * :doc:`gravity (ko) ` @@ -111,6 +113,7 @@ OPT. * :doc:`mvv/tdpd ` * :doc:`neb ` * :doc:`neb/spin ` + * :doc:`neighbor/swap ` * :doc:`nonaffine/displacement ` * :doc:`nph (ko) ` * :doc:`nph/asphere (o) ` @@ -216,6 +219,7 @@ OPT. * :doc:`rigid/small (o) ` * :doc:`rx (k) ` * :doc:`saed/vtk ` + * :doc:`set ` * :doc:`setforce (k) ` * :doc:`setforce/spin ` * :doc:`sgcmc ` diff --git a/doc/src/Commands_pair.rst b/doc/src/Commands_pair.rst index 048a54ed37..362bccb9e4 100644 --- a/doc/src/Commands_pair.rst +++ b/doc/src/Commands_pair.rst @@ -179,6 +179,7 @@ OPT. * :doc:`lj/long/dipole/long ` * :doc:`lj/long/tip4p/long (o) ` * :doc:`lj/mdf ` + * :doc:`lj/pirani (o) ` * :doc:`lj/relres (o) ` * :doc:`lj/spica (gko) ` * :doc:`lj/spica/coul/long (gko) ` diff --git a/doc/src/Commands_removed.rst b/doc/src/Commands_removed.rst index cea964fe79..c92d3d9064 100644 --- a/doc/src/Commands_removed.rst +++ b/doc/src/Commands_removed.rst @@ -1,7 +1,7 @@ Removed commands and packages ============================= -.. contents:: \ +.. contents:: ------ @@ -12,10 +12,21 @@ stop LAMMPS and print a suitable error message in most cases, when a style/command is used that has been removed or will replace the command with the direct alternative (if available) and print a warning. +GJF formulation in fix langevin +------------------------------- + +.. deprecated:: TBD + +The *gjf* keyword in fix langevin is deprecated and will be removed +soon. The GJF functionality has been moved to its own fix style +:doc:`fix gjf ` and it is strongly recommended to use that +fix instead. + + LAMMPS shell ------------ -.. versionchanged:: 29Aug2024 +.. deprecated:: 29Aug2024 The LAMMPS shell has been removed from the LAMMPS distribution. Users are encouraged to use the :ref:`LAMMPS-GUI ` tool instead. @@ -23,7 +34,7 @@ are encouraged to use the :ref:`LAMMPS-GUI ` tool instead. i-PI tool --------- -.. versionchanged:: 27Jun2024 +.. deprecated:: 27Jun2024 The i-PI tool has been removed from the LAMMPS distribution. Instead, instructions to install i-PI from PyPI via pip are provided. diff --git a/doc/src/Developer_updating.rst b/doc/src/Developer_updating.rst index 21980be3d8..ff914b2777 100644 --- a/doc/src/Developer_updating.rst +++ b/doc/src/Developer_updating.rst @@ -29,6 +29,7 @@ Available topics in mostly chronological order are: - `Rename of fix STORE/PERATOM to fix STORE/ATOM and change of arguments`_ - `Use Output::get_dump_by_id() instead of Output::find_dump()`_ - `Refactored grid communication using Grid3d/Grid2d classes instead of GridComm`_ +- `FLERR as first argument to minimum image functions in Domain class`_ ---- @@ -610,3 +611,47 @@ KSpace solvers which use distributed FFT grids: - ``src/KSPACE/pppm.cpp`` This change is **required** or else the code will not compile. + +FLERR as first argument to minimum image functions in Domain class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionchanged:: TBD + +The ``Domain::minimum_image()`` and ``Domain::minimum_image_big()`` +functions were changed to take the ``FLERR`` macros as first argument. +This way the error message indicates *where* the function was called +instead of pointing to the implementation of the function. Example: + +Old: + +.. code-block:: c++ + + double delx1 = x[i1][0] - x[i2][0]; + double dely1 = x[i1][1] - x[i2][1]; + double delz1 = x[i1][2] - x[i2][2]; + domain->minimum_image(delx1, dely1, delz1); + double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); + + double delx2 = x[i3][0] - x[i2][0]; + double dely2 = x[i3][1] - x[i2][1]; + double delz2 = x[i3][2] - x[i2][2]; + domain->minimum_image_big(delx2, dely2, delz2); + double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); + +New: + +.. code-block:: c++ + + double delx1 = x[i1][0] - x[i2][0]; + double dely1 = x[i1][1] - x[i2][1]; + double delz1 = x[i1][2] - x[i2][2]; + domain->minimum_image(FLERR, delx1, dely1, delz1); + double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); + + double delx2 = x[i3][0] - x[i2][0]; + double dely2 = x[i3][1] - x[i2][1]; + double delz2 = x[i3][2] - x[i2][2]; + domain->minimum_image_big(FLERR, delx2, dely2, delz2); + double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); + +This change is **required** or else the code will not compile. diff --git a/doc/src/Errors_details.rst b/doc/src/Errors_details.rst index f2728321e6..4b510f4902 100644 --- a/doc/src/Errors_details.rst +++ b/doc/src/Errors_details.rst @@ -159,13 +159,17 @@ angle, dihedral, or improper with just one atom in the actual sub-domain. Typically, this cutoff is set to the largest cutoff from the :doc:`pair style(s) ` plus the :doc:`neighbor list skin distance ` and will typically be sufficient for all bonded -interactions. But if the pair style cutoff is small, this may not be -enough. LAMMPS will print a warning in this case using some heuristic -based on the equilibrium bond length, but that still may not be -sufficient for cases where the force constants are small and thus bonds -may be stretched very far. The communication cutoff can be adjusted -with :doc:`comm_modify cutoff \ `, but setting this -too large will waste CPU time and memory. +interactions. But if the pair style cutoff is small (e.g. with a +repulsive-only Lennard-Jones potential) this may not be enough. It is +even worse if there is no pair style defined (or the pair style is set +to "none"), since then there will be no ghost atoms created at all. + +The communication cutoff can be set or adjusted with :doc:`comm_modify +cutoff \ `, but setting this too large will waste +CPU time and memory. LAMMPS will print warnings in these cases. For +bonds it uses some heuristic based on the equilibrium bond length, but +that still may not be sufficient for cases where the force constants are +small and thus bonds may be stretched very far. .. _hint09: @@ -982,3 +986,59 @@ order of preference there are: - Send an email to ``developers@lammps.org`` - Send an email to an :doc:`individual LAMMPS developer ` that you know and trust + +.. _err0036: + +Neighbor list overflow, boost neigh_modify one +---------------------------------------------- + +The neighbor list code in LAMMPS uses a special memory allocation strategy +to speed up building and accessing neighbor lists. + +Instead of making a memory allocation for each list of neighbors of the atoms +LAMMPS allocates "pages" that have room for several neighbor lists. This has +two main advantages: + +#. It is not needed to first count how many neighbors there are for an + atom to determine the storage required. Since the pages are much + larger than individual lists, LAMMPS just "fills up" the page until + there is not enough space left and then allocates a new page. + +#. There are fewer calls to the memory allocator functions (which can be + time consuming for long-running jobs and fragmented memory space) and + the resulting neighbor lists are close to each other physically which + improves cache efficiency. + +This is controlled by the two parameters "one" and "page", respectively, +that can be set via the :doc:`neigh_modify command `. The +parameter "one" is the maximum number of entries in a list of neighbors +for a single atom. If an atom has more neighbors as the "one" parameter +allows, the "overflow" error message is triggered. The parameter "page" +sets the size of the page. The neighbor list code checks, if there are +"one" entries left in the current page. If not, a new page is allocated. + +The default settings are suitable for most systems. They need to be +changed, for instance, when simulating a system with a very high density +or when setting a very long cutoff (e.g. :math:`\gtrapprox 15 \AA` with +:doc:`units real `). The value of "page" **must** be at least +10x the value of "one", but 50x to 100x are recommended to avoid wasting +memory. The neighbor list storage is typically the largest amount of +RAM required by a LAMMPS calculation. + +Even though the LAMMPS error message recommends to increase the "one" +parameter, this may not always be the correct solution. The neighbor +list overflow can also be a symptom for some other error that cannot be +easily detected. For example, a frequent reason for an (unexpected) +high density are incorrect box boundaries (since LAMMPS wraps atoms back +into the principal box with periodic boundaries) or coordinates provided +as fractional coordinates. In both cases, LAMMPS cannot easily know +whether the input geometry has such a high density (and thus requiring +more neighbor list storage per atom) by intention. Rather than blindly +increasing the "one" parameter, it is thus worth checking if this is +justified by the combination of density and cutoff. + +When boosting (= increasing) the "one" parameter, it is recommended to +also increase the value for the "page" parameter to maintain the ratio +between "one" and "page" to reduce waste of memory. For some more +details, please check out the documentation for the :doc:`neigh_modify +command `. diff --git a/doc/src/Howto.rst b/doc/src/Howto.rst index ec90472c27..cdc4efd737 100644 --- a/doc/src/Howto.rst +++ b/doc/src/Howto.rst @@ -66,6 +66,7 @@ Force fields howto :name: force_howto :maxdepth: 1 + Howto_FFgeneral Howto_bioFF Howto_amoeba Howto_tip3p diff --git a/doc/src/Howto_FFgeneral.rst b/doc/src/Howto_FFgeneral.rst new file mode 100644 index 0000000000..1b96ae1119 --- /dev/null +++ b/doc/src/Howto_FFgeneral.rst @@ -0,0 +1,55 @@ +Some general force field considerations +======================================= + +A compact summary of the concepts, definitions, and properties of force +fields with explicit bonded interactions (like the ones discussed in +this HowTo) is given in :ref:`(Gissinger) `. + +A force field has 2 parts: the formulas that define its potential +functions and the coefficients used for a particular system. To assign +parameters it is first required to assign atom types. Those are not +only based on the elements, but also on the chemical environment due to +the atoms bound to them. This often follows the chemical concept of +*functional groups*. Example: a carbon atom bound with a single bond to +a single OH-group (alcohol) would be a different atom type than a carbon +atom bound to a methyl CH3 group (aliphatic carbon). The atom types +usually then determine the non-bonded Lennard-Jones parameters and the +parameters for bonds, angles, dihedrals, and impropers. On top of that, +partial charges have to be applied. Those are usually independent of +the atom types and are determined either for groups of atoms called +residues with some fitting procedure based on quantum mechanical +calculations, or based on some increment system that add or subtract +increments from the partial charge of an atom based on the types of +the neighboring atoms. + +Force fields differ in the strategies they employ to determine the +parameters and charge distribution in how generic or specific they are +which in turn has an impact on the accuracy (compare for example +CGenFF to CHARMM and GAFF to Amber). Because of the different +strategies, it is not a good idea to use a mix of parameters from +different force field *families* (like CHARMM, Amber, or GROMOS) +and that extends to the parameters for the solvent, especially +water. The publication describing the parameterization of a force +field will describe which water model to use. Changing the water +model usually leads to overall worse results (even if it may improve +on the water itself). + +In addition, one has to consider that *families* of force fields like +CHARMM, Amber, OPLS, or GROMOS have evolved over time and thus provide +different *revisions* of the force field parameters. These often +corresponds to changes in the functional form or the parameterization +strategies. This may also result in changes required for simulation +settings like the preferred cutoff or how Coulomb interactions are +computed (cutoff, smoothed/shifted cutoff, or long-range with Ewald +summation or equivalent). Unless explicitly stated in the publication +describing the force field, the Coulomb interaction cannot be chosen at +will but must match the revision of the force field. That said, +liberties may be taken during the initial equilibration of a system to +speed up the process, but not for production simulations. + +---------- + +.. _Typelabel2: + +**(Gissinger)** J. R. Gissinger, I. Nikiforov, Y. Afshar, B. Waters, M. Choi, D. S. Karls, A. Stukowski, W. Im, H. Heinz, A. Kohlmeyer, and E. B. Tadmor, J Phys Chem B, 128, 3282-3297 (2024). + diff --git a/doc/src/Howto_bioFF.rst b/doc/src/Howto_bioFF.rst index 92dd45b9b6..cf8e4ab13e 100644 --- a/doc/src/Howto_bioFF.rst +++ b/doc/src/Howto_bioFF.rst @@ -1,22 +1,16 @@ CHARMM, AMBER, COMPASS, DREIDING, and OPLS force fields ======================================================= -A compact summary of the concepts, definitions, and properties of -force fields with explicit bonded interactions (like the ones discussed -in this HowTo) is given in :ref:`(Gissinger) `. - -A force field has 2 parts: the formulas that define it and the -coefficients used for a particular system. Here we only discuss -formulas implemented in LAMMPS that correspond to formulas commonly used -in the CHARMM, AMBER, COMPASS, and DREIDING force fields. Setting -coefficients is done either from special sections in an input data file -via the :doc:`read_data ` command or in the input script with -commands like :doc:`pair_coeff ` or :doc:`bond_coeff -` and so on. See the :doc:`Tools ` doc page for -additional tools that can use CHARMM, AMBER, or Materials Studio -generated files to assign force field coefficients and convert their -output into LAMMPS input. LAMMPS input scripts can also be generated by -`charmm-gui.org `_. +Here we only discuss formulas implemented in LAMMPS that correspond to +formulas commonly used in the CHARMM, AMBER, COMPASS, and DREIDING force +fields. Setting coefficients is done either from special sections in an +input data file via the :doc:`read_data ` command or in the +input script with commands like :doc:`pair_coeff ` or +:doc:`bond_coeff ` and so on. See the :doc:`Tools ` +doc page for additional tools that can use CHARMM, AMBER, or Materials +Studio generated files to assign force field coefficients and convert +their output into LAMMPS input. LAMMPS input scripts can also be +generated by `charmm-gui.org `_. CHARMM and AMBER ---------------- @@ -203,9 +197,11 @@ rather than individual force constants and geometric parameters that depend on the particular combinations of atoms involved in the bond, angle, or torsion terms. DREIDING has an :doc:`explicit hydrogen bond term ` to describe interactions involving a -hydrogen atom on very electronegative atoms (N, O, F). Unlike CHARMM -or AMBER, the DREIDING force field has not been parameterized for -considering solvents (like water). +hydrogen atom on very electronegative atoms (N, O, F). Unlike CHARMM or +AMBER, the DREIDING force field has not been parameterized for +considering solvents (like water) and has no rules for assigning +(partial) charges. That will seriously limit its accuracy when used for +simulating systems where those matter. See :ref:`(Mayo) ` for a description of the DREIDING force field @@ -272,10 +268,6 @@ compatible with a subset of OPLS interactions. ---------- -.. _Typelabel2: - -**(Gissinger)** J. R. Gissinger, I. Nikiforov, Y. Afshar, B. Waters, M. Choi, D. S. Karls, A. Stukowski, W. Im, H. Heinz, A. Kohlmeyer, and E. B. Tadmor, J Phys Chem B, 128, 3282-3297 (2024). - .. _howto-MacKerell: **(MacKerell)** MacKerell, Bashford, Bellott, Dunbrack, Evanseck, Field, Fischer, Gao, Guo, Ha, et al (1998). J Phys Chem, 102, 3586 . https://doi.org/10.1021/jp973084f diff --git a/doc/src/Howto_cmake.rst b/doc/src/Howto_cmake.rst index 6b8fc82bad..64acee47dd 100644 --- a/doc/src/Howto_cmake.rst +++ b/doc/src/Howto_cmake.rst @@ -285,7 +285,7 @@ when used before the CMake directory, there may be a space between the can have boolean values (on/off, yes/no, or 1/0 are all valid) or are strings representing a choice, or a path, or are free format. If the string would contain whitespace, it must be put in quotes, for example -``-D CMAKE_TUNE_FLAGS="-ftree-vectorize -ffast-math"``. +``-D CMAKE_CXX_FLAGS="-O3 -Wall -ftree-vectorize -ffast-math"``. CMake variables fall into two categories: 1) common CMake variables that are used by default for any CMake configuration setup and 2) project @@ -341,8 +341,6 @@ Some common LAMMPS specific variables - compile some additional executables from the ``tools`` folder (default: ``off``) * - ``BUILD_DOC`` - include building the HTML format documentation for packaging/installing (default: ``off``) - * - ``CMAKE_TUNE_FLAGS`` - - common compiler flags, for optimization or instrumentation (default:) * - ``LAMMPS_MACHINE`` - when set to ``name`` the LAMMPS executable and library will be called ``lmp_name`` and ``liblammps_name.a`` * - ``FFT`` diff --git a/doc/src/Howto_github.rst b/doc/src/Howto_github.rst index b53a2edbc7..e95e1cca9d 100644 --- a/doc/src/Howto_github.rst +++ b/doc/src/Howto_github.rst @@ -498,3 +498,7 @@ systems. Some unit and regression testing is applied as well. A detailed discussion of the LAMMPS developer GitHub workflow can be found in the file `doc/github-development-workflow.md `_ + +.. raw:: latex + + \clearpage diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index adf0c836fb..f6cfdefc81 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -1,36 +1,25 @@ Using LAMMPS-GUI ================ +LAMMPS-GUI is a graphical text editor programmed using the `Qt Framework +`_ and customized for editing LAMMPS input files. It +is linked to the :ref:`LAMMPS library ` and thus can run +LAMMPS directly using the contents of the editor's text buffer as input. + +It *differs* from other known interfaces to LAMMPS in that it can +retrieve and display information from LAMMPS *while it is running*, +display visualizations created with the :doc:`dump image command +`, can launch the online LAMMPS documentation for known +LAMMPS commands and styles, and directly integrates with a collection +of LAMMPS tutorials (:ref:`Gravelle1 `). + This document describes **LAMMPS-GUI version 1.6**. ----- -LAMMPS-GUI is a graphical text editor customized for editing LAMMPS -input files that is linked to the :ref:`LAMMPS library ` -and thus can run LAMMPS directly using the contents of the editor's text -buffer as input. It can retrieve and display information from LAMMPS -while it is running, display visualizations created with the :doc:`dump -image command `, and is adapted specifically for editing -LAMMPS input files through text completion and reformatting, and linking -to the online LAMMPS documentation for known LAMMPS commands and styles. +.. contents:: -.. note:: - - Pre-compiled, ready-to-use LAMMPS-GUI executables for Linux x86\_64 - (Ubuntu 20.04LTS or later and compatible), macOS (version 11 aka Big - Sur or later), and Windows (version 10 or later) :ref:`are available - ` for download. Non-MPI LAMMPS executables (as - ``lmp``) for running LAMMPS from the command-line and :doc:`some - LAMMPS tools ` compiled executables are also included. Also, - the pre-compiled LAMMPS-GUI packages include the WHAM executables - from http://membrane.urmc.rochester.edu/content/wham/ for use with - LAMMPS tutorials documented in this paper (:ref:`Gravelle1 - `). - - The source code for LAMMPS-GUI is included in the LAMMPS source code - distribution and can be found in the ``tools/lammps-gui`` folder. It - can be compiled alongside LAMMPS when :doc:`compiling with CMake - `. +---- LAMMPS-GUI tries to provide an experience similar to what people traditionally would have running LAMMPS using a command-line window and @@ -65,8 +54,8 @@ simple LAMMPS simulations. It is very suitable for tutorials on LAMMPS since you only need to learn how to use a single program for most tasks and thus time can be saved and people can focus on learning LAMMPS. The tutorials at https://lammpstutorials.github.io/ are specifically -updated for use with LAMMPS-GUI and can their tutorial materials can -be downloaded and loaded directly from the GUI. +updated for use with LAMMPS-GUI and their tutorial materials can +be downloaded and edited directly from the GUI. Another design goal is to keep the barrier low when replacing part of the functionality of LAMMPS-GUI with external tools. That said, LAMMPS-GUI @@ -79,10 +68,31 @@ has some unique functionality that is not found elsewhere: - monitoring of simulation progress - interactive visualization using the :doc:`dump image ` command with the option to copy-paste the resulting settings -- automatic slide show generation from dump image out at runtime -- automatic plotting of thermodynamics data at runtime +- automatic slide show generation from dump image output at runtime +- automatic plotting of thermodynamic data at runtime - inspection of binary restart files +.. admonition:: Download LAMMPS-GUI for your platform + :class: Hint + + Pre-compiled, ready-to-use LAMMPS-GUI executables for Linux x86\_64 + (Ubuntu 20.04LTS or later and compatible), macOS (version 11 aka Big + Sur or later), and Windows (version 10 or later) :ref:`are available + ` for download. Non-MPI LAMMPS executables (as + ``lmp``) for running LAMMPS from the command-line and :doc:`some + LAMMPS tools ` compiled executables are also included. Also, + the pre-compiled LAMMPS-GUI packages include the WHAM executables + from http://membrane.urmc.rochester.edu/content/wham/ for use with + LAMMPS tutorials documented in this paper (:ref:`Gravelle1 + `). + + The source code for LAMMPS-GUI is included in the LAMMPS source code + distribution and can be found in the ``tools/lammps-gui`` folder. It + can be compiled alongside LAMMPS when :doc:`compiling with CMake + `. + +----- + The following text provides a detailed tour of the features and functionality of LAMMPS-GUI. Suggestions for new features and reports of bugs are always welcome. You can use the :doc:`the same @@ -93,9 +103,12 @@ channels as for LAMMPS itself ` for that purpose. Installing Pre-compiled LAMMPS-GUI Packages ------------------------------------------- -LAMMPS-GUI is available as pre-compiled binary packages for Linux -x86\_64, macOS 11 and later, and Windows 10 and later. Alternately, it -can be compiled from source. +LAMMPS-GUI is available for download as pre-compiled binary packages for +Linux x86\_64 (Ubuntu 20.04LTS or later and compatible), macOS (version +11 aka Big Sur or later), and Windows (version 10 or later) from the +`LAMMPS release pages on GitHub `_. +A backup download location is at https://download.lammps.org/static/ +Alternately, LAMMPS-GUI can be compiled from source when building LAMMPS. Windows 10 and later ^^^^^^^^^^^^^^^^^^^^ @@ -295,7 +308,10 @@ of the *Output* window showing how many warnings and errors were detected and how many lines the entire output has. By clicking on the button on the right with the warning symbol or by using the keyboard shortcut `Ctrl-N` (`Command-N` on macOS), you can jump to the next -line with a warning or error. +line with a warning or error. If there is a URL pointing to additional +explanations in the online manual, that URL will be highlighted and +double-clicking on it shall open the corresponding manual page in +the web browser. The option is also available from the context menu. By default, the *Output* window is replaced each time a run is started. The runs are counted and the run number for the current run is displayed @@ -350,8 +366,13 @@ data or both. The smoothing uses a `Savitzky-Golay convolution filter window width (left) and order (right) parameters can be set in the boxes next to the drop down menu. Default settings are 10 and 4 which means that the smoothing window includes 10 points each to the left and the -right of the current data point and a fourth order polynomial is fit to -the data in the window. +right of the current data point for a total of 21 points and a fourth +order polynomial is fitted to the data in the window. + +The "Title:" and "Y:" input boxes allow to edit the text shown as the +plot title and the y-axis label, respectively. The text entered in the +"Title:" box is applied to *all* charts, while the "Y:" text changes +only the y-axis label of the currently *selected* plot. You can use the mouse to zoom into the graph (hold the left button and drag to mark an area) or zoom out (right click) and you can reset the @@ -383,6 +404,11 @@ here you get the compounded data set starting with the last change of output fields or timestep setting, while the export from the log will contain *all* YAML output but *segmented* into individual runs. +The *Preferences* dialog has a *Charts* tab, where you can configure +multiple chart-related settings, like the default title, colors for the +graphs, default choice of the raw / smooth graph selection, and the +default chart graph size. + Image Slide Show ---------------- @@ -462,11 +488,11 @@ correspond to (via their mass) and then colorize them in the image and set their atom diameters accordingly. If this is not possible, for instance when using reduced (= 'lj') :doc:`units `, then LAMMPS-GUI will check the current pair style and if it is a -Lennard-Jones type potential, it will extract the *sigma* parameter -for each atom type and assign atom diameters from those numbers. -For cases where atom diameters are not auto-detected, the *Atom size* field -can be edited and a suitable value set manually. The default value -is inferred from the x-direction lattice spacing. +Lennard-Jones type potential, it will extract the *sigma* parameter for +each atom type and assign atom diameters from those numbers. For cases +where atom diameters are not auto-detected, the *Atom size* field can be +edited and a suitable value set manually. The default value is inferred +from the x-direction lattice spacing. If elements cannot be detected the default sequence of colors of the :doc:`dump image ` command is assigned to the different atom @@ -481,22 +507,31 @@ types. |gui-image1| |gui-image2| The default image size, some default image quality settings, the view -style and some colors can be changed in the *Preferences* dialog -window. From the image viewer window further adjustments can be made: -actual image size, high-quality (SSAO) rendering, anti-aliasing, view -style, display of box or axes, zoom factor. The view of the system can -be rotated horizontally and vertically. It is also possible to only -display the atoms within a group defined in the input script (default is -"all"). The image can also be re-centered on the center of mass of the -selected group. After each change, the image is rendered again and the -display updated. The small palette icon on the top left is colored -while LAMMPS is running to render the new image; it is grayed out when -LAMMPS is finished. When there are many atoms to render and high -quality images with anti-aliasing are requested, re-rendering may take -several seconds. From the *File* menu of the image window, the -current image can be saved to a file (keyboard shortcut `Ctrl-S`) or -copied to the clipboard (keyboard shortcut `Ctrl-C`) for pasting the -image into another application. +style and some colors can be changed in the *Preferences* dialog window. +From the image viewer window further adjustments can be made: actual +image size, high-quality (SSAO) rendering, anti-aliasing, view style, +display of box or axes, zoom factor. The view of the system can be +rotated horizontally and vertically. + +It is also possible to display only the atoms within a :doc:`group +defined in the input script ` (default is "all"). The available +groups can be selected from the drop down list next to the "Group:" +label. Similarly, if there are :doc:`molecules defined in the input +`, it is possible to select one of them (default is "none") +and visualize it (it will be shown at the center of the simulation box). +While a molecule is selected, the group selection is disabled. It can +be restored by selecting the molecule "none". + +The image can also be re-centered on the center of mass of the selected +group. After each change, the image is rendered again and the display +updated. The small palette icon on the top left is colored while LAMMPS +is running to render the new image; it is grayed out when LAMMPS is +finished. When there are many atoms to render and high quality images +with anti-aliasing are requested, re-rendering may take several seconds. +From the *File* menu of the image window, the current image can be saved +to a file (keyboard shortcut `Ctrl-S`) or copied to the clipboard +(keyboard shortcut `Ctrl-C`) for pasting the image into another +application. From the *File* menu it is also possible to copy the current :doc:`dump image ` and :doc:`dump_modify ` @@ -726,13 +761,16 @@ Tutorials The *Tutorials* menu is to support the set of LAMMPS tutorials for beginners and intermediate LAMMPS users documented in (:ref:`Gravelle1 -`). From the drop down menu you can select which of the eight -currently available tutorial sessions you want to start and then will be -taken to a 'wizard' dialog where you can choose in which folder you want -to work, whether you want that folder to be cleared, and also whether -you want to download the solutions files (can be large). The dialog -will then start downloading the files requested and load the first input -file for the selected session into LAMMPS-GUI. +`). From the drop down menu you can select which of the +eight currently available tutorial sessions you want to begin. This +opens a 'wizard' dialog where you can choose in which folder you want to +work, whether you want that folder to be wiped from *any* files, whether +you want to download the solutions files (which can be large) to a +``solution`` sub-folder, and whether you want the corresponding +tutorial's online version opened in your web browser. The dialog will +then start downloading the files requested (download progress is +reported in the status line) and load the first input file for the +selected session into LAMMPS-GUI. About ^^^^^ @@ -797,18 +835,21 @@ look of LAMMPS-GUI. The settings are grouped and each group is displayed within a tab. .. |guiprefs1| image:: JPG/lammps-gui-prefs-general.png - :width: 24% + :width: 19% .. |guiprefs2| image:: JPG/lammps-gui-prefs-accel.png - :width: 24% + :width: 19% .. |guiprefs3| image:: JPG/lammps-gui-prefs-image.png - :width: 24% + :width: 19% .. |guiprefs4| image:: JPG/lammps-gui-prefs-editor.png - :width: 24% + :width: 19% -|guiprefs1| |guiprefs2| |guiprefs3| |guiprefs4| +.. |guiprefs5| image:: JPG/lammps-gui-prefs-charts.png + :width: 19% + +|guiprefs1| |guiprefs2| |guiprefs3| |guiprefs4| |guiprefs5| General Settings: ^^^^^^^^^^^^^^^^^ @@ -903,7 +944,7 @@ lists to select the background and box colors. Editor Settings: ^^^^^^^^^^^^^^^^ -This tab allows tweaking settings of the editor window. Specifically +This tab allows tweaking settings of the editor window. Specifically, the amount of padding to be added to LAMMPS commands, types or type ranges, IDs (e.g. for fixes), and names (e.g. for groups). The value set is the minimum width for the text element and it can be chosen in @@ -915,6 +956,16 @@ the completion pop-up window, and whether auto-save mode is enabled. In auto-save mode the editor buffer is saved before a run or before exiting LAMMPS-GUI. +Charts Settings: +---------------- + +This tab allows tweaking settings of the *Charts* window. Specifically, +one can set the default chart title (if the title contains '%f' it will +be replaced with the name of the current input file), one can select +whether by default the raw data, the smoothed data or both will be +plotted, one can set the colors for the two lines, the default smoothing +parameters, and the default size of the chart graph in pixels. + ----------- Keyboard Shortcuts @@ -1013,3 +1064,7 @@ Window), and `Ctrl-Q` (Quit Application) are supported. .. _Gravelle2: **(Gravelle2)** Gravelle https://lammpstutorials.github.io/ + +.. raw:: latex + + \clearpage diff --git a/doc/src/Howto_spc.rst b/doc/src/Howto_spc.rst index 00bd8a1b10..f84d7797d2 100644 --- a/doc/src/Howto_spc.rst +++ b/doc/src/Howto_spc.rst @@ -1,5 +1,5 @@ -SPC water model -=============== +SPC and SPC/E water model +========================= The SPC water model specifies a 3-site rigid water molecule with charges and Lennard-Jones parameters assigned to each of the three atoms. diff --git a/doc/src/Howto_thermostat.rst b/doc/src/Howto_thermostat.rst index fe53fff540..bda3bc6cb4 100644 --- a/doc/src/Howto_thermostat.rst +++ b/doc/src/Howto_thermostat.rst @@ -21,9 +21,14 @@ can be invoked via the *dpd/tstat* pair style: * :doc:`fix nvt/sllod ` * :doc:`fix temp/berendsen ` * :doc:`fix temp/csvr ` +* :doc:`fix ffl ` +* :doc:`fix gjf ` +* :doc:`fix gld ` +* :doc:`fix gle ` * :doc:`fix langevin ` * :doc:`fix temp/rescale ` * :doc:`pair_style dpd/tstat ` +* :doc:`pair_style dpd/ext/tstat ` :doc:`Fix nvt ` only thermostats the translational velocity of particles. :doc:`Fix nvt/sllod ` also does this, @@ -82,10 +87,10 @@ that: .. note:: - Only the nvt fixes perform time integration, meaning they update + Not all thermostat fixes perform time integration, meaning they update the velocities and positions of particles due to forces and velocities respectively. The other thermostat fixes only adjust velocities; they - do NOT perform time integration updates. Thus they should be used in + do NOT perform time integration updates. Thus, they should be used in conjunction with a constant NVE integration fix such as these: * :doc:`fix nve ` diff --git a/doc/src/Howto_tip4p.rst b/doc/src/Howto_tip4p.rst index 47a1b9b578..76c470d615 100644 --- a/doc/src/Howto_tip4p.rst +++ b/doc/src/Howto_tip4p.rst @@ -1,5 +1,5 @@ -TIP4P water model -================= +TIP4P and OPC water models +========================== The four-point TIP4P rigid water model extends the traditional :doc:`three-point TIP3P ` model by adding an additional @@ -9,9 +9,11 @@ the oxygen along the bisector of the HOH bond angle. A bond style of :doc:`harmonic ` and an angle style of :doc:`harmonic ` or :doc:`charmm ` should also be used. In case of rigid bonds also bond style :doc:`zero ` and angle -style :doc:`zero ` can be used. +style :doc:`zero ` can be used. Very similar to the TIP4P +model is the OPC water model. It can be realized the same way as TIP4P +but has different geometry and force field parameters. -There are two ways to implement TIP4P water in LAMMPS: +There are two ways to implement TIP4P-like water in LAMMPS: #. Use a specially written pair style that uses the :ref:`TIP3P geometry ` without the point M. The point M location is then @@ -21,7 +23,10 @@ There are two ways to implement TIP4P water in LAMMPS: computationally very efficient, but the charge distribution in space is only correct within the tip4p labeled styles. So all other computations using charges will "see" the negative charge incorrectly - on the oxygen atom. + located on the oxygen atom unless they are specially written for using + the TIP4P geometry internally as well, e.g. :doc:`compute dipole/tip4p + `, :doc:`fix efield/tip4p `, or + :doc:`kspace_style pppm/tip4p `. This can be done with the following pair styles for Coulomb with a cutoff: @@ -68,77 +73,90 @@ TIP4P/2005 model :ref:`(Abascal2) ` and a version of TIP4P parameters adjusted for use with a long-range Coulombic solver (e.g. Ewald or PPPM in LAMMPS). Note that for implicit TIP4P models the OM distance is specified in the :doc:`pair_style ` command, -not as part of the pair coefficients. +not as part of the pair coefficients. Also parameters for the OPC +model (:ref:`Izadi `) are provided. .. list-table:: :header-rows: 1 - :widths: 36 19 13 15 17 + :widths: 40 12 12 14 11 11 * - Parameter - TIP4P (original) - TIP4P/Ice - TIP4P/2005 - TIP4P (Ewald) + - OPC * - O mass (amu) - 15.9994 - 15.9994 - 15.9994 - 15.9994 + - 15.9994 * - H mass (amu) - 1.008 - 1.008 - 1.008 - 1.008 + - 1.008 * - O or M charge (:math:`e`) - -1.040 - -1.1794 - -1.1128 - -1.04844 + - -1.3582 * - H charge (:math:`e`) - 0.520 - 0.5897 - 0.5564 - 0.52422 + - 0.6791 * - LJ :math:`\epsilon` of OO (kcal/mole) - 0.1550 - 0.21084 - 0.1852 - 0.16275 + - 0.21280 * - LJ :math:`\sigma` of OO (:math:`\AA`) - 3.1536 - 3.1668 - 3.1589 - 3.16435 + - 3.1660 * - LJ :math:`\epsilon` of HH, MM, OH, OM, HM (kcal/mole) - 0.0 - 0.0 - 0.0 - 0.0 + - 0.0 * - LJ :math:`\sigma` of HH, MM, OH, OM, HM (:math:`\AA`) - 1.0 - 1.0 - 1.0 - 1.0 + - 1.0 * - :math:`r_0` of OH bond (:math:`\AA`) - 0.9572 - 0.9572 - 0.9572 - 0.9572 + - 0.8724 * - :math:`\theta_0` of HOH angle - 104.52\ :math:`^{\circ}` - 104.52\ :math:`^{\circ}` - 104.52\ :math:`^{\circ}` - 104.52\ :math:`^{\circ}` + - 103.60\ :math:`^{\circ}` * - OM distance (:math:`\AA`) - 0.15 - 0.1577 - 0.1546 - 0.1250 + - 0.1594 -Note that the when using the TIP4P pair style, the neighbor list cutoff +Note that the when using a TIP4P pair style, the neighbor list cutoff for Coulomb interactions is effectively extended by a distance 2 \* (OM distance), to account for the offset distance of the fictitious charges -on O atoms in water molecules. Thus it is typically best in an +on O atoms in water molecules. Thus, it is typically best in an efficiency sense to use a LJ cutoff >= Coulomb cutoff + 2\*(OM distance), to shrink the size of the neighbor list. This leads to slightly larger cost for the long-range calculation, so you can test the @@ -192,6 +210,94 @@ file changed): run 20000 write_data tip4p-implicit.data nocoeff +When constructing an OPC model, we cannot use the ``tip3p.mol`` file due +to the different geometry. Below is a molecule file providing the 3 +sites of an implicit OPC geometry for use with TIP4P styles. Note, that +the "Shake" and "Special" sections are missing here. Those will be +auto-generated by LAMMPS when the molecule file is loaded *after* the +simulation box has been created. These sections are required only when +the molecule file is loaded *before*. + +.. _opc3p_molecule: +.. code-block:: + + # Water molecule. 3 point geometry for OPC model + + 3 atoms + 2 bonds + 1 angles + + Coords + + 1 0.00000 -0.06037 0.00000 + 2 0.68558 0.50250 0.00000 + 3 -0.68558 0.50250 0.00000 + + Types + + 1 1 # O + 2 2 # H + 3 2 # H + + Charges + + 1 -1.3582 + 2 0.6791 + 3 0.6791 + + Bonds + + 1 1 1 2 + 2 1 1 3 + + Angles + + 1 1 2 1 3 + +Below is a LAMMPS input file using the implicit method to implement +the OPC model using the molecule file from above and including the +PPPM long-range Coulomb solver. + +.. code-block:: LAMMPS + + units real + atom_style full + region box block -5 5 -5 5 -5 5 + create_box 2 box bond/types 1 angle/types 1 & + extra/bond/per/atom 2 extra/angle/per/atom 1 extra/special/per/atom 2 + + mass 1 15.9994 + mass 2 1.008 + + pair_style lj/cut/tip4p/long 1 2 1 1 0.1594 12.0 + pair_coeff 1 1 0.2128 3.166 + pair_coeff 2 2 0.0 1.0 + + bond_style zero + bond_coeff 1 0.8724 + + angle_style zero + angle_coeff 1 103.6 + + kspace_style pppm/tip4p 1.0e-5 + + molecule water opc3p.mol # this file has the OPC geometry but is without M + create_atoms 0 random 33 34564 NULL mol water 25367 overlap 1.33 + + fix rigid all shake 0.001 10 10000 b 1 a 1 + minimize 0.0 0.0 1000 10000 + + reset_timestep 0 + timestep 1.0 + velocity all create 300.0 5463576 + fix integrate all nvt temp 300 300 100.0 + + thermo_style custom step temp press etotal pe + + thermo 1000 + run 20000 + write_data opc-implicit.data nocoeff + Below is the code for a LAMMPS input file using the explicit method and a TIP4P molecule file. Because of using :doc:`fix rigid/small ` no bonds need to be defined and thus no extra storage needs @@ -279,3 +385,8 @@ Phys, 79, 926 (1983). **(Abascal2)** Abascal, J Chem Phys, 123, 234505 (2005) https://doi.org/10.1063/1.2121687 + +.. _Izadi: + +**(Izadi)** Izadi, Anandakrishnan, Onufriev, J. Phys. Chem. Lett., 5, 21, 3863 (2014) + https://doi.org/10.1021/jz501780a diff --git a/doc/src/Install_git.rst b/doc/src/Install_git.rst index d01bc6a4c5..717c7b3a9e 100644 --- a/doc/src/Install_git.rst +++ b/doc/src/Install_git.rst @@ -12,19 +12,10 @@ several advantages: LAMMPS. For that, you should first create your own :doc:`fork on GitHub `, though. -You must have `git `_ installed on your system to use the -commands explained below to communicate with the git servers on -GitHub. For people still using subversion (svn), GitHub also -provides `limited support for subversion clients `_. - -.. note:: - - As of October 2016, the official home of public LAMMPS development is - on GitHub. The previously advertised LAMMPS git repositories on - git.lammps.org and bitbucket.org are now offline or deprecated. +You must have `git `_ installed on your system to use the commands +explained below to communicate with the git servers on GitHub. .. _git: https://git-scm.com -.. _svn: https://help.github.com/en/github/importing-your-projects-to-github/working-with-subversion-on-github You can follow the LAMMPS development on 4 different git branches: diff --git a/doc/src/Intro_authors.rst b/doc/src/Intro_authors.rst index 38f1102595..730cd2e336 100644 --- a/doc/src/Intro_authors.rst +++ b/doc/src/Intro_authors.rst @@ -84,8 +84,9 @@ lammps.org". General questions about LAMMPS should be posted in the \normalsize -Past developers include Paul Crozier and Mark Stevens, both at SNL, -and Ray Shan, now at Materials Design. +Past core developers include Paul Crozier and Mark Stevens, both at SNL, +and Ray Shan while at SNL and later at Materials Design, now at Thermo +Fisher Scientific. ---------- diff --git a/doc/src/Intro_portability.rst b/doc/src/Intro_portability.rst index 63ae147b8c..564cdc47f4 100644 --- a/doc/src/Intro_portability.rst +++ b/doc/src/Intro_portability.rst @@ -28,8 +28,9 @@ Build systems LAMMPS can be compiled from source code using a (traditional) build system based on shell scripts, a few shell utilities (grep, sed, cat, tr) and the GNU make program. This requires running within a Bourne -shell (``/bin/sh``). Alternatively, a build system with different back -ends can be created using CMake. CMake must be at least version 3.16. +shell (``/bin/sh`` or ``/bin/bash``). Alternatively, a build system +with different back ends can be created using CMake. CMake must be +at least version 3.16. Operating systems ^^^^^^^^^^^^^^^^^ @@ -40,11 +41,18 @@ Also, compilation and correct execution on macOS and Windows (using Microsoft Visual C++) is checked automatically for the largest part of the source code. Some (optional) features are not compatible with all operating systems, either through limitations of the corresponding -LAMMPS source code or through incompatibilities of source code or -build system of required external libraries or packages. +LAMMPS source code or through incompatibilities or build system +limitations of required external libraries or packages. -Executables for Windows may be created natively using either Cygwin or -Visual Studio or with a Linux to Windows MinGW cross-compiler. +Executables for Windows may be created either natively using Cygwin, +MinGW, Intel, Clang, or Microsoft Visual C++ compilers, or with a Linux +to Windows MinGW cross-compiler. Native compilation is supported using +Microsoft Visual Studio or a terminal window (using the CMake build +system). + +Executables for macOS may be created either using Xcode or GNU compilers +installed with Homebrew. In the latter case, building of LAMMPS through +Homebrew instead of a manual compile is also possible. Additionally, FreeBSD and Solaris have been tested successfully to run LAMMPS and produce results consistent with those on Linux. @@ -61,8 +69,9 @@ CPU architectures ^^^^^^^^^^^^^^^^^ The primary CPU architecture for running LAMMPS is 64-bit x86, but also -32-bit x86, and 64-bit ARM and PowerPC (64-bit, Little Endian) are -regularly tested. +64-bit ARM and PowerPC (64-bit, Little Endian) are currently regularly +tested. Further architectures are tested by Linux distributions that +bundle LAMMPS. Portability compliance ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/src/JPG/lammps-gui-chart.png b/doc/src/JPG/lammps-gui-chart.png index 5a926a721b..ee57be6cdd 100644 Binary files a/doc/src/JPG/lammps-gui-chart.png and b/doc/src/JPG/lammps-gui-chart.png differ diff --git a/doc/src/JPG/lammps-gui-prefs-accel.png b/doc/src/JPG/lammps-gui-prefs-accel.png index 392861e40b..ed0673c0e5 100644 Binary files a/doc/src/JPG/lammps-gui-prefs-accel.png and b/doc/src/JPG/lammps-gui-prefs-accel.png differ diff --git a/doc/src/JPG/lammps-gui-prefs-charts.png b/doc/src/JPG/lammps-gui-prefs-charts.png new file mode 100644 index 0000000000..9e9e42134c Binary files /dev/null and b/doc/src/JPG/lammps-gui-prefs-charts.png differ diff --git a/doc/src/JPG/lammps-gui-prefs-editor.png b/doc/src/JPG/lammps-gui-prefs-editor.png index b3cf059583..7c2c120121 100644 Binary files a/doc/src/JPG/lammps-gui-prefs-editor.png and b/doc/src/JPG/lammps-gui-prefs-editor.png differ diff --git a/doc/src/JPG/lammps-gui-prefs-general.png b/doc/src/JPG/lammps-gui-prefs-general.png index 7f161284c8..15fefdc96d 100644 Binary files a/doc/src/JPG/lammps-gui-prefs-general.png and b/doc/src/JPG/lammps-gui-prefs-general.png differ diff --git a/doc/src/JPG/lammps-gui-prefs-image.png b/doc/src/JPG/lammps-gui-prefs-image.png index 2f830c85f3..3d9277f16a 100644 Binary files a/doc/src/JPG/lammps-gui-prefs-image.png and b/doc/src/JPG/lammps-gui-prefs-image.png differ diff --git a/doc/src/JPG/lammps-gui-screen.png b/doc/src/JPG/lammps-gui-screen.png new file mode 100644 index 0000000000..cae0ae9fe9 Binary files /dev/null and b/doc/src/JPG/lammps-gui-screen.png differ diff --git a/doc/src/JPG/lammps-releases.png b/doc/src/JPG/lammps-releases.png index d5c317088f..b81039c007 100644 Binary files a/doc/src/JPG/lammps-releases.png and b/doc/src/JPG/lammps-releases.png differ diff --git a/doc/src/Modify_pair.rst b/doc/src/Modify_pair.rst index 64831e726f..84f06a3acd 100644 --- a/doc/src/Modify_pair.rst +++ b/doc/src/Modify_pair.rst @@ -46,6 +46,8 @@ Here is a brief list of some the class methods in the Pair class that +---------------------------------+------------------------------------------------------------------------+ | compute_inner/middle/outer | versions of compute used by rRESPA | +---------------------------------+------------------------------------------------------------------------+ +| compute_atomic_energy | energy of one atom, equivalent to per-atom energy | ++---------------------------------+------------------------------------------------------------------------+ | memory_usage | return estimated amount of memory used by the pair style | +---------------------------------+------------------------------------------------------------------------+ | modify_params | process arguments to pair_modify command | @@ -122,3 +124,5 @@ setting. +---------------------------------+-------------------------------------------------------------+---------+ | spinflag | 1 if compatible with spin kspace_style | 0 | +---------------------------------+-------------------------------------------------------------+---------+ +| atomic_energy_enable | 1 if compute_atomic_energy() routine exists | 0 | ++---------------------------------+-------------------------------------------------------------+---------+ diff --git a/doc/src/PDF/colvars-refman-lammps.pdf b/doc/src/PDF/colvars-refman-lammps.pdf index b8f049ce01..76d94f8e3a 100644 Binary files a/doc/src/PDF/colvars-refman-lammps.pdf and b/doc/src/PDF/colvars-refman-lammps.pdf differ diff --git a/doc/src/Python_launch.rst b/doc/src/Python_launch.rst index f9bd9c1c98..046edccfbc 100644 --- a/doc/src/Python_launch.rst +++ b/doc/src/Python_launch.rst @@ -1,7 +1,7 @@ Running LAMMPS and Python in serial ----------------------------------- -To run a LAMMPS in serial, type these lines into Python +To run a LAMMPS input in serial, type these lines into Python interactively from the ``bench`` directory: .. code-block:: python diff --git a/doc/src/Speed_compare.rst b/doc/src/Speed_compare.rst index 3f72e5d715..d59c37c34d 100644 --- a/doc/src/Speed_compare.rst +++ b/doc/src/Speed_compare.rst @@ -75,15 +75,34 @@ section below for examples where this has been done. **Differences between the GPU and KOKKOS packages:** * The GPU package accelerates only pair force, neighbor list, and (parts - of) PPPM calculations. The KOKKOS package attempts to run most of the + of) PPPM calculations (and runs the remaining force computations on + the CPU concurrently). The KOKKOS package attempts to run most of the calculation on the GPU, but can transparently support non-accelerated code (with a performance penalty due to having data transfers between host and GPU). +* The list of which styles are accelerated by the GPU or KOKKOS package + differs with some overlap. * The GPU package requires neighbor lists to be built on the CPU when using hybrid pair styles, exclusion lists, or a triclinic simulation box. -* The GPU package can be compiled for CUDA, HIP, or OpenCL and thus supports - NVIDIA, AMD, and Intel GPUs well. On NVIDIA hardware, using CUDA is - typically resulting in equal or better performance over OpenCL. -* OpenCL in the GPU package does theoretically also support Intel CPUs or - Intel Xeon Phi, but the native support for those in KOKKOS (or INTEL) - is superior. +* The GPU package benefits from running multiple MPI processes (2-8) per + GPU to parallelize the non-GPU accelerated styles. The KOKKOS package + usually not, especially when all parts of the calculation have KOKKOS + support. +* The GPU package can be compiled for CUDA, HIP, or OpenCL and thus + supports NVIDIA, AMD, and Intel GPUs well. On NVIDIA or AMD hardware, + using native CUDA or HIP compilation, respectively, with either GPU or + KOKKOS results in equal or better performance over OpenCL. +* OpenCL in the GPU package supports NVIDIA, AMD, and Intel GPUs at the + *same time* and with the *same executable*. KOKKOS currently does not + support OpenCL. +* The GPU package supports single precision floating point, mixed + precision floating point, and double precision floating point math on + the GPU. This must be chosen at compile time. KOKKOS currently only + supports double precision floating point math. Using single or mixed + precision (recommended) results in significantly improved performance + on consumer GPUs for some loss in accuracy (which is rather small with + mixed precision). Single and mixed precision support for KOKKOS is in + development (no ETA yet). +* Some pair styles (for example :doc:`snap `, :doc:`mliap + ` or :doc:`reaxff ` in the KOKKOS package have + seen extensive optimizations and specializations for GPUs and CPUs. diff --git a/doc/src/Speed_measure.rst b/doc/src/Speed_measure.rst index 888e8d9790..2fe838cb22 100644 --- a/doc/src/Speed_measure.rst +++ b/doc/src/Speed_measure.rst @@ -1,16 +1,218 @@ Measuring performance ===================== -Before trying to make your simulation run faster, you should -understand how it currently performs and where the bottlenecks are. +Factors that influence performance +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The best way to do this is run the your system (actual number of -atoms) for a modest number of timesteps (say 100 steps) on several -different processor counts, including a single processor if possible. -Do this for an equilibrium version of your system, so that the -100-step timings are representative of a much longer run. There is -typically no need to run for 1000s of timesteps to get accurate -timings; you can simply extrapolate from short runs. +Before trying to make your simulation run faster, you should understand +how it currently performs and where the bottlenecks are. We generally +distinguish between serial performance (how fast can a single process do +the calculations?) and parallel efficiency (how much faster does a +calculation get by using more processes?). There are many factors +affecting either and below are some lists discussing some commonly +known but also some less known factors. + +Factors affecting serial performance (in no specific order): + +* CPU hardware: clock rate, cache sizes, CPU architecture (instructions + per clock, vectorization support, fused multiply-add support and more) +* RAM speed and number of channels that the CPU can use to access RAM +* Cooling: CPUs can change the CPU clock based on thermal load, thus the + degree of cooling can affect the speed of a CPU. Sometimes even the + temperature of neighboring compute nodes in a cluster can make a + difference. +* Compiler optimization: most of LAMMPS is written to be easy to modify + and thus compiler optimization can speed up calculations. However, too + aggressive compiler optimization can produce incorrect results or + crashes (during compilation or at runtime). +* Source code improvements: styles in the OPT, OPENMP, and INTEL package + can be faster than their base implementation due to improved data + access patterns, cache efficiency, or vectorization. Compiler optimization + is required to take full advantage of these. +* Number and kind of fixes, computes, or variables used during a simulation, + especially if they result in collective communication operations +* Pair style cutoffs and system density: calculations get slower the more + neighbors are in the neighbor list and thus for which interactions need + to be computed. Force fields with pair styles that compute interactions + between triples or quadruples of atoms or that use embedding energies or + charge equilibration will need to walk the neighbor lists multiple times. +* Neighbor list settings: tradeoff between neighbor list skin (larger + skin = more neighbors, more distances to compute before applying the + cutoff) and frequency of neighbor list builds (larger skin = fewer + neighbor list builds). +* Proximity of per-atom data in physical memory that for atoms that are + close in space improves cache efficiency (thus LAMMPS will by default + sort atoms in local storage accordingly) +* Using r-RESPA multi-timestepping or a SHAKE or RATTLE fix to constrain + bonds with higher-frequency vibrations may allow a larger (outer) timestep + and thus fewer force evaluations (usually the most time consuming step in + MD) for the same simulated time (with some tradeoff in accuracy). + +Factors affecting parallel efficiency (in no specific order): + +* Bandwidth and latency of communication between processes. This can vary a + lot between processes on the same CPU or physical node and processes + on different physical nodes and there vary between different + communication technologies (like Ethernet or InfiniBand or other + high-speed interconnects) +* Frequency and complexity of communication patterns required +* Number of "work units" (usually correlated with the number of atoms + and choice of force field) per MPI-process required for one time step + (if this number becomes too small, the cost of communication becomes + dominant). +* Choice of parallelization method (MPI-only, OpenMP-only, MPI+OpenMP, + MPI+GPU, MPI+GPU+OpenMP) +* Algorithmic complexity of the chosen force field (pair-wise vs. many-body + potential, Ewald vs. PPPM vs. (compensated or smoothed) cutoff-Coulomb) +* Communication cutoff: a larger cutoff results in more ghost atoms and + thus more data that needs to be communicated +* Frequency of neighbor list builds: during a neighbor list build the + domain decomposition is updated and the list of ghost atoms rebuilt + which requires multiple global communication steps +* FFT-grid settings and number of MPI processes for kspace style PPPM: + PPPM uses parallel 3d FFTs which will drop much faster in parallel + efficiency with respect to the number of MPI processes than other + parts of the force computation. Thus using MPI+OpenMP parallelization + or :doc:`run style verlet/split ` can improve parallel + efficiency by limiting the number of MPI processes used for the FFTs. +* Load (im-)balance: LAMMPS' domain decomposition assumes that atoms are + evenly distributed across the entire simulation box. If there are + areas of vacuum, this may lead to different amounts of work for + different MPI processes. Using the :doc:`processors command + ` to change the spatial decomposition, or MPI+OpenMP + parallelization instead of only-MPI to have larger sub-domains, or the + (fix) balance command (without or with switching to communication style + tiled) to change the sub-domain volumes are all methods that + can help to avoid load imbalances. + +Examples comparing serial performance +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Before looking at your own input deck(s), you should get some reference +data from a known input so that you know what kind of performance you +should expect from your input. For the following we therefore use the +``in.rhodo.scaled`` input file and ``data.rhodo`` data file from the +``bench`` folder. This is a system of 32000 atoms using the CHARMM force +field and long-range electrostatics running for 100 MD steps. The +performance data is printed at the end of a run and only measures the +performance during propagation and excludes the setup phase. + +Running with a single MPI process on an AMD Ryzen Threadripper PRO +9985WX CPU (64 cores, 128 threads, base clock: 3.2GHz, max. clock +5.4GHz, L1/L2/L3 cache 5MB/64MB/256MB, 8 DDR5-6400 memory channels) one +gets the following performance report: + +.. code-block:: + + Performance: 1.232 ns/day, 19.476 hours/ns, 7.131 timesteps/s, 228.197 katom-step/s + 99.2% CPU use with 1 MPI tasks x 1 OpenMP threads + +The %CPU value should be at 100% or very close. Lower values would +be an indication that there are *other* processes also using the same +CPU core and thus invalidating the performance data. The katom-step/s +value is best suited for comparisons, since it is fairly independent +from the system size. The `in.rhodo.scaled` input can be easily made +larger through replication in the three dimensions by settings variables +"x", "y", "z" to values other than 1 from the command line with the +"-var" flag. Example: + +- 32000 atoms: 228.8 katom-step/s +- 64000 atoms: 231.6 katom-step/s +- 128000 atoms: 231.1 katom-step/s +- 256000 atoms: 226.4 katom-step/s +- 864000 atoms: 229.6 katom-step/s + +Comparing to an AMD Ryzen 7 7840HS CPU (8 cores, 16 threads, base clock +3.8GHz, max. clock 5.1GHz, L1/L2/L3 cache 512kB/8MB/16MB, 2 DDR5-5600 +memory channels), we get similar single core performance (~220 +katom-step/s vs. ~230 katom-step/s) due to the similar clock and +architecture: + +- 32000 atoms: 219.8 katom-step/s +- 64000 atoms: 222.5 katom-step/s +- 128000 atoms: 216.8 katom-step/s +- 256000 atoms: 221.0 katom-step/s +- 864000 atoms: 221.1 katom-step/s + +Switching to an older Intel Xeon E5-2650 v4 CPU (12 cores, 12 threads, +base clock 2.2GHz, max. clock 2.9GHz, L1/L2/L3 cache (64kB/256kB/30MB, 4 +DDR4-2400 memory channels) leads to a lower performance of approximately +109 katom-step/s due to differences in architecture and clock. In all +cases, when looking at multiple runs, the katom-step/s property +fluctuates by approximately 1% around the average. + +From here on we are looking at the performance for the 256000 atom system only +and change several settings incrementally: + +#. No compiler optimization GCC (-Og -g): 183.8 katom-step/s +#. Moderate optimization with debug info GCC (-O2 -g): 231.1 katom-step/s +#. Full compiler optimization GCC (-DNDEBUG -O3): 236.0 katom-step/s +#. Aggressive compiler optimization GCC (-O3 -ffast-math -march=native): 239.9 katom-step/s +#. Source code optimization in OPENMP package (1 thread): 266.7 katom-step/s +#. Use *fix nvt* instead of *fix npt* (compute virial only every 50 steps): 272.9 katom-step/s +#. Increase pair style cutoff by 2 :math:`\AA`: 181.2 katom-step/s +#. Use tight PPPM convergence (1.0e-6 instead of 1.0e-4): 161.9 katom-step/s +#. Use Ewald summation instead of PPPM (at 1.0e-4 convergence): 19.9 katom-step/s + +The numbers show that gains from aggressive compiler optimizations are +rather small in LAMMPS, the data access optimizations in the OPENMP (and +OPT) packages are more prominent. On the other side, using more +accurate force field settings causes, not unexpectedly, a significant +slowdown (to about half the speed). Finally, using regular Ewald +summation causes a massive slowdown due to the bad algorithmic scaling +with system size. + +Examples comparing parallel performance +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The parallel performance usually goes on top of the serial performance. +Using twice as many processors should increase the performance metric +by up to a factor of two. With the number of processors *N* and the +serial performance :math:`p_1` and the performance for *N* processors +:math:`p_N` we can define a *parallel efficiency* in percent as follows: + +.. math:: + + P_{eff} = \frac{p_N}{p_1 \cdot N} \cdot 100\% + +For the AMD Ryzen Threadripper PRO 9985WX CPU and the serial +simulation settings of point 6. from above, we get the following +parallel efficiency data for the 256000 atom system: + +- 1 MPI task: 273.6 katom-step/s, :math:`P_{eff} = 100\%` +- 2 MPI tasks: 530.6 katom-step/s, :math:`P_{eff} = 97\%` +- 4 MPI tasks: 1.021 Matom-step/s, :math:`P_{eff} = 93\%` +- 8 MPI tasks: 1.837 Matom-step/s, :math:`P_{eff} = 84\%` +- 16 MPI tasks: 3.574 Matom-step/s, :math:`P_{eff} = 82\%` +- 32 MPI tasks: 6.479 Matom-step/s, :math:`P_{eff} = 74\%` +- 64 MPI tasks: 9.032 Matom-step/s, :math:`P_{eff} = 52\%` +- 128 MPI tasks: 12.03 Matom-step/s, :math:`P_{eff} = 34\%` + +The 128 MPI tasks run uses CPU cores from hyper-threading. + +For a small system with only 32000 atoms the parallel efficiency +drops off earlier when the number of work units is too small relative +to the communication overhead: + +- 1 MPI task: 270.8 katom-step/s, :math:`P_{eff} = 100\%` +- 2 MPI tasks: 529.3 katom-step/s, :math:`P_{eff} = 98\%` +- 4 MPI tasks: 989.8 katom-step/s, :math:`P_{eff} = 91\%` +- 8 MPI tasks: 1.832 Matom-step/s, :math:`P_{eff} = 85\%` +- 16 MPI tasks: 3.463 Matom-step/s, :math:`P_{eff} = 80\%` +- 32 MPI tasks: 5.970 Matom-step/s, :math:`P_{eff} = 69\%` +- 64 MPI tasks: 7.477 Matom-step/s, :math:`P_{eff} = 42\%` +- 128 MPI tasks: 8.069 Matom-step/s, :math:`P_{eff} = 23\%` + +Measuring performance of your input deck +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The best way to do this is run the your system (actual number of atoms) +for a modest number of timesteps (say 100 steps) on several different +processor counts, including a single processor if possible. Do this for +an equilibrium version of your system, so that the 100-step timings are +representative of a much longer run. There is typically no need to run +for 1000s of timesteps to get accurate timings; you can simply +extrapolate from short runs. For the set of runs, look at the timing data printed to the screen and log file at the end of each LAMMPS run. The @@ -28,12 +230,15 @@ breakdown and relative percentages. For example, trying different options for speeding up the long-range solvers will have little impact if they only consume 10% of the run time. If the pairwise time is dominating, you may want to look at GPU or OMP versions of the pair -style, as discussed below. Comparing how the percentages change as -you increase the processor count gives you a sense of how different -operations within the timestep are scaling. Note that if you are -running with a Kspace solver, there is additional output on the -breakdown of the Kspace time. For PPPM, this includes the fraction -spent on FFTs, which can be communication intensive. +style, as discussed below. Comparing how the percentages change as you +increase the processor count gives you a sense of how different +operations within the timestep are scaling. If you are using PPPM as +Kspace solver, you can turn on an additional output with +:doc:`kspace_modify fftbench yes ` which measures the +time spent during PPPM on the 3d FFTs, which can be communication +intensive for larger processor counts. This provides an indication +whether it is worth trying out alternatives to the default FFT settings +for additional performance. Another important detail in the timing info are the histograms of atoms counts and neighbor counts. If these vary widely across diff --git a/doc/src/Tools.rst b/doc/src/Tools.rst index e502480ce5..521cfe5f16 100644 --- a/doc/src/Tools.rst +++ b/doc/src/Tools.rst @@ -475,9 +475,13 @@ beginners to start with LAMMPS, it is also the expectation that LAMMPS-GUI users will eventually transition to workflows that most experienced LAMMPS users employ. -All features have been extensively exposed to keyboard shortcuts, so -that there is also appeal for experienced LAMMPS users for prototyping -and testing simulation setups. +.. image:: JPG/lammps-gui-screen.png + :align: center + :scale: 50% + +Features have been extensively exposed to keyboard shortcuts, so that +there is also appeal for experienced LAMMPS users for prototyping and +testing simulation setups. Features ^^^^^^^^ @@ -502,7 +506,7 @@ Here are a few highlights of LAMMPS-GUI - Visualization of current state in Image Viewer (via calling :doc:`write_dump image `) - Capture of images created via :doc:`dump image ` in Slide show window - Dialog to set variables, similar to the LAMMPS command-line flag '-v' / '-var' -- Support for GPU, INTEL, KOKKOS/OpenMP, OPENMAP, and OPT and accelerator packages +- Support for GPU, INTEL, KOKKOS/OpenMP, OPENMP, and OPT accelerator packages Parallelization ^^^^^^^^^^^^^^^ @@ -523,8 +527,8 @@ with CMake is required. The LAMMPS-GUI has been successfully compiled and tested on: - Ubuntu Linux 20.04LTS x86_64 using GCC 9, Qt version 5.12 -- Fedora Linux 40 x86\_64 using GCC 14 and Clang 17, Qt version 5.15LTS -- Fedora Linux 40 x86\_64 using GCC 14, Qt version 6.7 +- Fedora Linux 41 x86\_64 using GCC 14 and Clang 17, Qt version 5.15LTS +- Fedora Linux 41 x86\_64 using GCC 14, Qt version 6.8 - Apple macOS 12 (Monterey) and macOS 13 (Ventura) with Xcode on arm64 and x86\_64, Qt version 5.15LTS - Windows 10 and 11 x86_64 with Visual Studio 2022 and Visual C++ 14.36, Qt version 5.15LTS - Windows 10 and 11 x86_64 with Visual Studio 2022 and Visual C++ 14.40, Qt version 6.7 @@ -1250,10 +1254,10 @@ tabulate tool .. versionadded:: 22Dec2022 -The ``tabulate`` folder contains Python scripts scripts to generate tabulated -potential files for LAMMPS. The bulk of the code is in the ``tabulate`` module -in the ``tabulate.py`` file. Some example files demonstrating its use are -included. See the README file for more information. +The ``tabulate`` folder contains Python scripts scripts to generate and +visualize tabulated potential files for LAMMPS. The bulk of the code is in the +``tabulate`` module in the ``tabulate.py`` file. Some example files +demonstrating its use are included. See the README file for more information. ---------- @@ -1276,7 +1280,7 @@ Those scripts were written by Steve Plimpton sjplimp at gmail.com valgrind tool ------------- -The ``valgrind`` folder contains additional suppressions fur LAMMPS when +The ``valgrind`` folder contains additional suppressions for LAMMPS when using `valgrind's `_ ` `memcheck tool `_ to search for memory access violation and memory leaks. These suppressions are automatically diff --git a/doc/src/compute_bond_local.rst b/doc/src/compute_bond_local.rst index e070d507b1..7ce6f9b15a 100644 --- a/doc/src/compute_bond_local.rst +++ b/doc/src/compute_bond_local.rst @@ -64,20 +64,32 @@ All these properties are computed for the pair of atoms in a bond, whether the two atoms represent a simple diatomic molecule, or are part of some larger molecule. -The value *dist* is the current length of the bond. -The values *dx*, *dy*, and *dz* are the xyz components of the -*distance* between the pair of atoms. This value is always the -distance from the atom of lower to the one with the higher id. +.. versionchanged:: TBD + + The sign of *dx*, *dy*, *dz* is no longer determined by the atom IDs + of the bonded atoms but by their order in the bond list to be + consistent with *fx*, *fy*, and *fz*. + +The value *dist* is the current length of the bond. The values *dx*, +*dy*, and *dz* are the :math:`(x,y,z)` components of the distance vector +:math:`\vec{x_i} - \vec{x_j}` between the atoms in the bond. The order +of the atoms is determined by the bond list and the respective atom-IDs +can be output with :doc:`compute property/local +`. The value *engpot* is the potential energy for the bond, based on the current separation of the pair of atoms in the bond. -The value *force* is the magnitude of the force acting between the -pair of atoms in the bond. +The value *force* is the magnitude of the force acting between the pair +of atoms in the bond, which is positive for a repulsive force and +negative for an attractive force. -The values *fx*, *fy*, and *fz* are the xyz components of -*force* between the pair of atoms in the bond. For bond styles that apply -non-central forces, such as :doc:`bond_style bpm/rotational +The values *fx*, *fy*, and *fz* are the :math:`(x,y,z)` components of +the force on the first atom *i* in the bond due to the second atom *j*. +Mathematically, they are obtained by multiplying the value of *force* +from above with a unit vector created from the *dx*, *dy*, and *dz* +components of the distance vector also described above. For bond styles +that apply non-central forces, such as :doc:`bond_style bpm/rotational `, these values only include the :math:`(x,y,z)` components of the normal force component. diff --git a/doc/src/compute_pair_local.rst b/doc/src/compute_pair_local.rst index 31209f63f4..605bfc8e9e 100644 --- a/doc/src/compute_pair_local.rst +++ b/doc/src/compute_pair_local.rst @@ -56,19 +56,33 @@ force cutoff distance for that interaction, as defined by the :doc:`pair_style ` and :doc:`pair_coeff ` commands. -The value *dist* is the distance between the pair of atoms. -The values *dx*, *dy*, and *dz* are the :math:`(x,y,z)` components of the -*distance* between the pair of atoms. This value is always the -distance from the atom of higher to the one with the lower atom ID. +.. versionchanged:: TBD + + The sign of *dx*, *dy*, *dz* is no longer determined by the value of + their atom-IDs but by their order in the neighbor list to be + consistent with *fx*, *fy*, and *fz*. + +The value *dist* is the distance between the pair of atoms. The values +*dx*, *dy*, and *dz* are the :math:`(x,y,z)` components of the distance +vector :math:`\vec{x_i} - \vec{x_j}` between the pair of atoms. The +order of the atoms is determined by the neighbor list and the respective +atom-IDs can be output with :doc:`compute property/local +`. The value *eng* is the interaction energy for the pair of atoms. The value *force* is the force acting between the pair of atoms, which is positive for a repulsive force and negative for an attractive -force. The values *fx*, *fy*, and *fz* are the :math:`(x,y,z)` components of -*force* on atom I. For pair styles that apply non-central forces, -such as :doc:`granular pair styles `, these values only include -the :math:`(x,y,z)` components of the normal force component. +force. + +The values *fx*, *fy*, and *fz* are the :math:`(x,y,z)` components of +the force vector on the first atom *i* of a pair in the neighbor list +due to the second atom *j*. Mathematically, they are obtained by +multiplying the value of *force* from above with a unit vector created +from the *dx*, *dy*, and *dz* components of the distance vector also +described above. For pair styles that apply non-central forces, such as +:doc:`granular pair styles `, these values only include the +:math:`(x,y,z)` components of the normal force component. A pair style may define additional pairwise quantities which can be accessed as *p1* to *pN*, where :math:`N` is defined by the pair style. diff --git a/doc/src/create_atoms.rst b/doc/src/create_atoms.rst index 2addd89fcb..6d3604215c 100644 --- a/doc/src/create_atoms.rst +++ b/doc/src/create_atoms.rst @@ -28,7 +28,7 @@ Syntax region-ID = create atoms within this region, use NULL for entire simulation box * zero or more keyword/value pairs may be appended -* keyword = *mol* or *basis* or *ratio* or *subset* or *remap* or *var* or *set* or *radscale* or *meshmode* or *rotate* or *overlap* or *maxtry* or *units* +* keyword = *mol* or *basis* or *ratio* or *subset* or *group* or *remap* or *var* or *set* or *radscale* or *meshmode* or *rotate* or *overlap* or *maxtry* or *units* .. parsed-literal:: @@ -44,6 +44,7 @@ Syntax *subset* values = Nsubset seed Nsubset = # of lattice sites to populate randomly seed = random # seed (positive integer) + *group* value = group name *remap* value = *yes* or *no* *var* value = name = variable name to evaluate for test of atom creation *set* values = dim name @@ -83,7 +84,7 @@ Examples create_atoms 3 region regsphere basis 2 3 create_atoms 3 region regsphere basis 2 3 ratio 0.5 74637 - create_atoms 3 single 0 0 5 + create_atoms 3 single 0 0 5 group newatom create_atoms 1 box var v set x xpos set y ypos create_atoms 2 random 50 12345 NULL overlap 2.0 maxtry 50 create_atoms 1 mesh open_box.stl meshmode qrand 0.1 units box @@ -395,6 +396,14 @@ correct number of particles are inserted, in a perfectly random fashion. Which lattice sites are selected will change with the number of processors used. +.. versionadded:: TBD + +The *group* keyword adds the newly created atoms to the named +:doc:`group `. If the group does not yet exist it will be +created. There can be only one such group, thus if the *group* keyword +is used multiple times, only the last one will be used. All created +atoms are always added to the group "all". + The *remap* keyword only applies to the *single* style. If it is set to *yes*, then if the specified position is outside the simulation box, it will mapped back into the box, assuming the relevant diff --git a/doc/src/fix.rst b/doc/src/fix.rst index 3b1bc4a75c..bb0545e406 100644 --- a/doc/src/fix.rst +++ b/doc/src/fix.rst @@ -208,6 +208,7 @@ accelerated styles exist. * :doc:`ave/grid ` - compute per-grid time-averaged quantities * :doc:`ave/histo ` - compute/output time-averaged histograms * :doc:`ave/histo/weight ` - weighted version of fix ave/histo +* :doc:`ave/moments ` - compute moments of scalar quantities * :doc:`ave/time ` - compute/output global time-averaged quantities * :doc:`aveforce ` - add an averaged force to each atom * :doc:`balance ` - perform dynamic load-balancing @@ -256,6 +257,7 @@ accelerated styles exist. * :doc:`flow/gauss ` - Gaussian dynamics for constant mass flux * :doc:`freeze ` - freeze atoms in a granular simulation * :doc:`gcmc ` - grand canonical insertions/deletions +* :doc:`gjf ` - statistically correct Langevin temperature control using the GJ methods * :doc:`gld ` - generalized Langevin dynamics integrator * :doc:`gle ` - generalized Langevin equation thermostat * :doc:`gravity ` - add gravity to atoms in a granular simulation @@ -290,6 +292,7 @@ accelerated styles exist. * :doc:`mvv/tdpd ` - constant temperature DPD using the modified velocity-Verlet algorithm * :doc:`neb ` - nudged elastic band (NEB) spring forces * :doc:`neb/spin ` - nudged elastic band (NEB) spring forces for spins +* :doc:`neighbor/swap ` - kinetic Monte Carlo (kMC) atom swapping * :doc:`nonaffine/displacement ` - calculate nonaffine displacement of atoms * :doc:`nph ` - constant NPH time integration via Nose/Hoover * :doc:`nph/asphere ` - NPH for aspherical particles @@ -395,6 +398,7 @@ accelerated styles exist. * :doc:`rigid/small ` - constrain many small clusters of atoms to move as a rigid body with NVE integration * :doc:`rx ` - solve reaction kinetic ODEs for a defined reaction set * :doc:`saed/vtk ` - time-average the intensities from :doc:`compute saed ` +* :doc:`set ` - reset an atom property via an atom-style variable every N steps * :doc:`setforce ` - set the force on each atom * :doc:`setforce/spin ` - set magnetic precession vectors on each atom * :doc:`sgcmc ` - fix for hybrid semi-grand canonical MD/MC simulations diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index 2eec2eb457..f737fc750f 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -14,7 +14,7 @@ Syntax * adapt = style name of this fix command * N = adapt simulation settings every this many timesteps * one or more attribute/arg pairs may be appended -* attribute = *pair* or *bond* or *angle* or *improper* or *kspace* or *atom* +* attribute = *pair* or *bond* or *angle* or *dihedral* or *improper* or *kspace* or *atom* .. parsed-literal:: @@ -33,6 +33,11 @@ Syntax aparam = parameter to adapt over time I = type angle to set parameter for (integer or type label) v_name = variable with name that calculates value of aparam + *dihedral* args = dstyle dparam I v_name + dstyle = dihedral style name (e.g., quadratic) + dparam = parameter to adapt over time + I = type dihedral to set parameter for (integer or type label) + v_name = variable with name that calculates value of iparam *improper* args = istyle iparam I v_name istyle = improper style name (e.g., cvff) iparam = parameter to adapt over time @@ -209,6 +214,8 @@ formulas for the meaning of these parameters: +------------------------------------------------------------------------------+--------------------------------------------------+-------------+ | :doc:`lj/mdf ` | epsilon,sigma | type pairs | +------------------------------------------------------------------------------+--------------------------------------------------+-------------+ +| :doc:`lj/pirani ` | alpha, beta, gamma, rm, epsilon | type pairs | ++------------------------------------------------------------------------------+--------------------------------------------------+-------------+ | :doc:`lj/sf/dipole/sf ` | epsilon,sigma,scale | type pairs | +------------------------------------------------------------------------------+--------------------------------------------------+-------------+ | :doc:`lubricate ` | mu | global | @@ -433,6 +440,48 @@ this fix uses to reset theta0 needs to generate values in radians. ---------- +.. versionadded:: TBD + +The *dihedral* keyword uses the specified variable to change the value of +a dihedral coefficient over time, very similar to how the *angle* keyword +operates. The only difference is that now a dihedral coefficient for a +given dihedral type is adapted. + +A wild-card asterisk can be used in place of or in conjunction with the +dihedral type argument to set the coefficients for multiple dihedral types. +This takes the form "\*" or "\*n" or "m\*" or "m\*n". If :math:`N` is +the number of dihedral types, then an asterisk with no numeric values means +all types from 1 to :math:`N`. A leading asterisk means all types from +1 to n (inclusive). A trailing asterisk means all types from m to +:math:`N` (inclusive). A middle asterisk means all types from m to n +(inclusive). + +If :doc:`dihedral_style hybrid ` is used, *dstyle* should be a +sub-style name. The dihedral styles that currently work with fix adapt are: + ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`charmm ` | k,n,d | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`charmmfsw ` | k,n,d | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`class2 ` | k1,k2,k3,phi1,phi2,phi3 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`cosine/squared/restricted ` | k,phi0 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`helix ` | a,b,c | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`multi/harmonic ` | a1,a2,a3,a4,a5 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`opls ` | k1,k2,k3,k4 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`quadratic ` | k,phi0 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ + +Note that internally, phi0 is stored in radians, so the variable +this fix use to reset phi0 needs to generate values in radians. + +---------- + .. versionadded:: 2Apr2025 The *improper* keyword uses the specified variable to change the value of diff --git a/doc/src/fix_ave_correlate_long.rst b/doc/src/fix_ave_correlate_long.rst index 22fac89706..97b68fe14f 100644 --- a/doc/src/fix_ave_correlate_long.rst +++ b/doc/src/fix_ave_correlate_long.rst @@ -82,10 +82,9 @@ specified values may represent calculations performed by computes and fixes which store their own "group" definitions. Each listed value can be the result of a compute or fix or the -evaluation of an equal-style or vector-style variable. For -vector-style variables, the specified indices can include a wildcard -character. See the :doc:`fix ave/correlate ` page -for details. +evaluation of an equal-style or vector-style variable. The specified +indices can include a wildcard string. See the +:doc:`fix ave/correlate ` page for details on that. The *Nevery* and *Nfreq* arguments specify on what time steps the input values will be used to calculate correlation data and the frequency diff --git a/doc/src/fix_ave_moments.rst b/doc/src/fix_ave_moments.rst new file mode 100644 index 0000000000..b80cdf5db9 --- /dev/null +++ b/doc/src/fix_ave_moments.rst @@ -0,0 +1,296 @@ +.. index:: fix ave/moments + +fix ave/moments command +======================= + +Syntax +"""""" + +.. code-block:: LAMMPS + + fix ID group-ID ave/moments Nevery Nrepeat Nfreq value1 value2 ... moment1 moment2 ... keyword args ... + +* ID, group-ID are documented in :doc:`fix ` command +* ave/moments = style name of this fix command +* Nevery = use input values every this many time steps +* Nrepeat = # of times to use input values for calculating averages +* Nfreq = calculate averages every this many time steps +* one or more input variables can be listed +* value = v_name + + .. parsed-literal:: + + c_ID = global scalar calculated by a compute with ID + c_ID[I] = Ith component of global vector calculated by a compute with ID, I can include wildcard (see below) + f_ID = global scalar calculated by a fix with ID + f_ID[I] = Ith component of global vector calculated by a fix with ID, I can include wildcard (see below) + v_name = value calculated by an equal-style variable with name + v_name[I] = value calculated by a vector-style variable with name, I can include wildcard (see below) + +* one or more moments to compute can be listed +* moment = *mean* or *stddev* or *variance* or *skew* or *kurtosis*, see exact definitions below. +* zero or more keyword/arg pairs may be appended +* keyword = *start* or *history* + + .. parsed-literal:: + + *start* args = Nstart + Nstart = invoke first after this time step + *history* args = Nrecent + Nrecent = keep a history of up to Nrecent outputs + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 1 all ave/moments 1 1000 100 v_volume mean stddev + fix 1 all ave/moments 1 200 1000 v_volume variance kurtosis history 10 + +Description +""""""""""" + +.. versionadded:: TBD + +Using one or more values as input, calculate the moments of the underlying +(population) distributions based on samples collected every few time +steps over a time step window. The definitions of the moments calculated +are given below. + +The group specified with this command is ignored. However, note that +specified values may represent calculations performed by computes and +fixes which store their own "group" definitions. + +Each listed value can be the result of a :doc:`compute ` or +:doc:`fix ` or the evaluation of an equal-style or vector-style +:doc:`variable `. In each case, the compute, fix, or variable +must produce a global quantity, not a per-atom or local quantity. +If you wish to spatial- or time-average or histogram per-atom +quantities from a compute, fix, or variable, then see the :doc:`fix +ave/chunk `, :doc:`fix ave/atom `, or +:doc:`fix ave/histo ` commands. If you wish to sum a +per-atom quantity into a single global quantity, see the :doc:`compute +reduce ` command. + +Many :doc:`computes ` and :doc:`fixes ` produce global +quantities. See their doc pages for details. :doc:`Variables ` +of style *equal* and *vector* are the only ones that can be used with +this fix. Variables of style *atom* cannot be used, since they produce +per-atom values. + +The input values must all be scalars or vectors with a bracketed term +appended, indicating the :math:`I^\text{th}` value of the vector is +used. + +The result of this fix can be accessed as a vector, containing the +interleaved moments of each input in order. If M moments are requested, +then the moments of input 1 will be the first M values in the vector +output by this fix. The moments of input 2 will the next M values, etc. +If there are N values, the vector length will be N*M. + +---------- + +For input values from a compute or fix or variable, the bracketed index +I can be specified using a wildcard asterisk with the index to +effectively specify multiple values. This takes the form "\*" or "\*n" +or "m\*" or "m\*n". If :math:`N` is the size of the vector, then an +asterisk with no numeric values means all indices from 1 to :math:`N`. +A leading asterisk means all indices from 1 to n (inclusive). A +trailing asterisk means all indices from n to :math:`N` (inclusive). A +middle asterisk means all indices from m to n (inclusive). + +Using a wildcard is the same as if the individual elements of the vector +or cells of the array had been listed one by one. For examples, see the +description of this capability in :doc:`fix ave/time `. + +---------- + +The :math:`N_\text{every}`, :math:`N_\text{repeat}`, and +:math:`N_\text{freq}` arguments specify on what time steps the input +values will be used in order to contribute to the average. The final +statistics are generated on time steps that are a multiple of +:math:`N_\text{freq}`\ . The average is over a window of up to +:math:`N_\text{repeat}` quantities, computed in the preceding portion of +the simulation once every :math:`N_\text{every}` time steps. + +.. note:: + + Contrary to most fix ave/* commands, it is not required that Nevery * + Nrepeat <= Nfreq. This is to allow the user to choose the time + window and number of samples contributing to the output at each + Nfreq interval. + +For example, if :math:`N_\text{freq}=100` and :math:`N_\text{repeat}=5` +(and :math:`N_\text{every}=1`), then on step 100 values from time steps +96, 97, 98, 99, and 100 will be used. The fix does not compute its +inputs on steps that are not required. If :math:`N_\text{freq}=5`, +:math:`N_\text{repeat}=8` and :math:`N_\text{every}=1`, then values +will first be calculated on step 5 from steps 1-5, on step 10 from 3-10, +on step 15 from 8-15 and so on, forming a rolling average over +timesteps that span a time window larger than Nfreq. + +---------- + +If a value begins with "c\_", a compute ID must follow which has been +previously defined in the input script. If no bracketed term is +appended, the global scalar calculated by the compute is used. If a +bracketed term is appended, the Ith element of the global vector +calculated by the compute is used. See the discussion above for how I +can be specified with a wildcard asterisk to effectively specify +multiple values. + +If a value begins with "f\_", a fix ID must follow which has been +previously defined in the input script. If no bracketed term is +appended, the global scalar calculated by the fix is used. If a +bracketed term is appended, the Ith element of the global vector +calculated by the fix is used. See the discussion above for how I can +be specified with a wildcard asterisk to effectively specify multiple +values. + +Note that some fixes only produce their values on certain time steps, +which must be compatible with *Nevery*, else an error will result. +Users can also write code for their own fix styles and :doc:`add them to +LAMMPS `. + +If a value begins with "v\_", a variable name must follow which has been +previously defined in the input script. Only equal-style or vector-style +variables can be used, which both produce global values. Vector-style +variables require a bracketed term to specify the Ith element of the +vector calculated by the variable. + +Note that variables of style *equal* and *vector* define a formula which +can reference individual atom properties or thermodynamic keywords, or +they can invoke other computes, fixes, or variables when they are +evaluated, so this is a very general means of specifying quantities to +time average. + +---------- + +The moments are output in the order requested in the arguments following +the last input. Any number and order of moments can be specified, +although it does not make much sense to specify the same moment multiple +times. All moments are computed using a correction of the sample estimators +used to obtain unbiased cumulants :math:`k_{1..4}` (see :ref:`(Cramer) +`). The correction for variance is the standard Bessel +correction. For other moments, see :ref:`(Joanes)`. + +For *mean*, the arithmetic mean :math:`\bar{x} = \frac{1}{n} +\sum_{i=1}^{n} x_i` is calculated. + +For *variance*, the Bessel-corrected sample variance :math:`var = k_2 = +\frac{1}{n - 1} \sum_{i=1}^{n} (x_i - \bar{x})^2` is calculated. + +For *stddev*, the Bessel-corrected sample standard deviation +:math:`stddev = \sqrt{k_2}` is calculated. + +For *skew*, the adjusted Fisher--Pearson standardized moment :math:`G_1 += \frac{k_3}{k_2^{3/2}} = \frac{k_3}{stddev^3}` is calculated. + +For *kurtosis*, the adjusted Fisher--Pearson standardized moment +:math:`G_2 = \frac{k_4}{k_2^2}` is calculated. + +---------- + +Fix invocation and output can be modified by optional keywords. + +The *start* keyword specifies that the first computation should be no +earlier than the step number given (but will still occur on a multiple +of *Nfreq*). The default is step 0. Often input values can be 0.0 at +time 0, so setting *start* to a larger value can avoid including a 0.0 +in a longer series. + +The *history* keyword stores the Nrecent most recent outputs on Nfreq +timesteps, so they can be accessed as global outputs of the fix. Nrecent +must be >= 1. The default is 1, meaning only the most recent output is +accessible. For example, if history 10 is specified and Nfreq = 1000, +then on timestep 20000, the Nfreq outputs from steps 20000, 19000, ... +11000 are available for access. See below for details on how to access +the history values. + +For example, this will store the outputs of the previous 10 Nfreq +time steps, i.e. a window of 10000 time steps: + +.. code-block:: LAMMPS + + fix 1 all ave/moments 1 200 1000 v_volume mean history 10 + +The previous results can be accessed as values in a global array output +by this fix. Each column of the array is the vector output of the N-th +preceding Nfreq timestep. For example, assuming a single moment is +calculated, the most recent result corresponding to the third input +value would be accessed as "f_name[3][1]", "f_name[3][4]" is the 4th +most recent and so on. The current vector output is always the first +column of the array, corresponding to the most recent result. + +To illustrate the utility of keeping output history, consider using +this fix in conjunction with :doc:`fix halt ` to stop a run +automatically if a quantity is converged to within some desired tolerance: + +.. code-block:: LAMMPS + + variable target equal etot + fix aveg all ave/moments 1 200 1000 v_target mean stddev history 10 + variable stopcond equal "abs(f_aveg[1]-f_aveg[1][10])`. + +This fix produces a global vector and global array which can be accessed +by various :doc:`output commands `. The values can be +accessed on any time step, but may not be current. + +A global vector is produced with the # of elements = number of moments * +number of inputs. The moments are output in the order given in the fix +definition. An array is produced having # of rows = length of vector +output (with an ordering which matches the vector) and # of columns = +value of *history*. There is always at least one column. + +Each element of the global vector or array can be either "intensive" or +"extensive", depending on whether the values contributing to the element +are "intensive" or "extensive". If a compute or fix provides the value +being time averaged, then the compute or fix determines whether the value +is intensive or extensive; see the page for that compute or fix for +further info. Values produced by a variable are treated as intensive. + +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during +:doc:`energy minimization `. + +Restrictions +"""""""""""" + +This compute is part of the EXTRA-FIX package. It is only enabled if +LAMMPS was built with that package. See the :doc:`Build package +` page for more info. + +Related commands +"""""""""""""""" + +:doc:`fix ave/time `, + +Default +""""""" + +The option defaults are history = 1, start = 0. + +---------- + +.. _Cramer1: + +**(Cramer)** Cramer, Mathematical Methods of Statistics, Princeton University Press (1946). + +.. _Joanes1: + +**(Joanes)** Joanes, Gill, The Statistician, 47, 183--189 (1998). diff --git a/doc/src/fix_gjf.rst b/doc/src/fix_gjf.rst new file mode 100644 index 0000000000..82d283db34 --- /dev/null +++ b/doc/src/fix_gjf.rst @@ -0,0 +1,208 @@ +.. index:: fix gjf + +fix gjf command +======================== + +Syntax +"""""" + +.. code-block:: LAMMPS + + fix ID group-ID gjf Tstart Tstop damp seed keyword values ... + +* ID, group-ID are documented in :doc:`fix ` command +* gjf = style name of this fix command +* Tstart,Tstop = desired temperature at start/end of run (temperature units) +* Tstart can be a variable (see below) +* damp = damping parameter (time units) +* seed = random number seed to use for white noise (positive integer) +* zero or more keyword/value pairs may be appended +* keyword = *vel* or *method* + + .. parsed-literal:: + + *vel* value = *vfull* or *vhalf* + *vfull* = use on-site velocity + *vhalf* = use half-step velocity + *method* value = *1-8* + *1-8* = choose one of the many GJ formulations + *7* = requires input of additional scalar between 0 and 1 + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 3 boundary gjf 10.0 10.0 1.0 699483 + fix 1 all gjf 10.0 100.0 100.0 48279 vel vfull method 4 + fix 2 all gjf 10.0 10.0 1.0 26488 method 7 0.95 + +Description +""""""""""" +.. versionadded:: TBD + +Apply a Langevin thermostat as described in :ref:`(Gronbech-Jensen-2020) ` +to a group of atoms which models an interaction with a background +implicit solvent. As described in the papers cited below, the GJ methods +provide exact diffusion, drift, and Boltzmann sampling for linear systems for +any time step within the stability limit. The purpose of this set of methods +is therefore to significantly improve statistical accuracy at longer time steps +compared to other thermostats. + +The current implementation provides the user with the option to output +the velocity in one of two forms: *vfull* or *vhalf*. The option *vhalf* +outputs the 2GJ half-step velocity given in :ref:`Gronbech Jensen/Gronbech-Jensen +`; for linear systems, this velocity is shown to not +have any statistical errors for any stable time step. The option *vfull* +outputs the on-site velocity given in :ref:`Gronbech-Jensen/Farago +`; this velocity is shown to be systematically lower +than the target temperature by a small amount, which grows +quadratically with the timestep. An overview of statistically correct Boltzmann +and Maxwell-Boltzmann sampling of true on-site and true half-step velocities is +given in :ref:`Gronbech-Jensen-2020 `. + +This fix allows the use of several GJ methods as listed in :ref:`Gronbech-Jensen-2020 `. +The GJ-VII method is described in :ref:`Finkelstein ` and GJ-VIII +is described in :ref:`Gronbech-Jensen-2024 `. +The implementation follows the splitting form provided in Eqs. (24) and (25) +in :ref:`Gronbech-Jensen-2024 `, including the application +of Gaussian noise values, per the description in +:ref:`Gronbech-Jensen-2023 `. + + +.. note:: + + Unlike the :doc:`fix langevin ` command which performs force + modifications only, this fix performs thermostatting and time integration. + Thus you no longer need a separate time integration fix, like :doc:`fix nve `. + +See the :doc:`Howto thermostat ` page for +a discussion of different ways to compute temperature and perform +thermostatting. + +The desired temperature at each timestep is a ramped value during the +run from *Tstart* to *Tstop*\ . + +*Tstart* can be specified as an equal-style or atom-style +:doc:`variable `. In this case, the *Tstop* setting is +ignored. If the value is a variable, it should be specified as +v_name, where name is the variable name. In this case, the variable +will be evaluated each timestep, and its value used to determine the +target temperature. + +Equal-style variables can specify formulas with various mathematical +functions, and include :doc:`thermo_style ` command +keywords for the simulation box parameters and timestep and elapsed +time. Thus it is easy to specify a time-dependent temperature. + +Atom-style variables can specify the same formulas as equal-style +variables but can also include per-atom values, such as atom +coordinates. Thus it is easy to specify a spatially-dependent +temperature with optional time-dependence as well. + +Like other fixes that perform thermostatting, this fix can be used +with :doc:`compute commands ` that remove a "bias" from the +atom velocities. E.g. to apply the thermostat only to atoms within a +spatial :doc:`region `, or to remove the center-of-mass +velocity from a group of atoms, or to remove the x-component of +velocity from the calculation. + +This is not done by default, but only if the :doc:`fix_modify +` command is used to assign a temperature compute to this +fix that includes such a bias term. See the doc pages for individual +:doc:`compute temp commands ` to determine which ones include +a bias. + +The *damp* parameter is specified in time units and determines how +rapidly the temperature is relaxed. For example, a value of 100.0 means +to relax the temperature in a timespan of (roughly) 100 time units +(:math:`\tau` or fs or ps - see the :doc:`units ` command). The +damp factor can be thought of as inversely related to the viscosity of +the solvent. I.e. a small relaxation time implies a high-viscosity +solvent and vice versa. See the discussion about :math:`\gamma` and +viscosity in the documentation for the :doc:`fix viscous ` +command for more details. + +The random # *seed* must be a positive integer. A Marsaglia random +number generator is used. Each processor uses the input seed to +generate its own unique seed and its own stream of random numbers. +Thus the dynamics of the system will not be identical on two runs on +different numbers of processors. + +---------- + +The keyword/value option pairs are used in the following ways. + +The keyword *vel* determines which velocity is used to determine +quantities of interest in the simulation. + +The keyword *method* selects one of the eight GJ-methods implemented in LAMMPS. + +---------- + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files `. +Because the state of the random number generator is not saved in restart files, +this means you cannot do "exact" restarts with this fix, where the simulation +continues on the same as if no restart had taken place. However, in a +statistical sense, a restarted simulation should produce the same behavior. +Additionally, the GJ methods implement noise exclusively within each time step +(unlike the BBK thermostat of the fix-langevin). The restart is done with +either vfull or vhalf velocity output for as long as the choice of vfull/vhalf +is the same for the simulation as it is in the restart file. + +The :doc:`fix_modify ` *temp* option is supported by this +fix. You can use it to assign a temperature :doc:`compute ` +you have defined to this fix which will be used in its thermostatting +procedure, as described above. For consistency, the group used by +this fix and by the compute should be the same. + +This fix can ramp its target temperature over multiple runs, using the +*start* and *stop* keywords of the :doc:`run ` command. See the +:doc:`run ` command for details of how to do this. + +This fix is not invoked during :doc:`energy minimization `. + +Restrictions +"""""""""""" + +This fix is not compatible with run_style respa. It is not compatible with +accelerated packages such as KOKKOS. + +Related commands +"""""""""""""""" + +:doc:`fix langevin `, :doc:`fix nvt ` + +Default +""""""" + +The option defaults are vel = vhalf, method = 1. + +---------- + +.. _Gronbech-Jensen-2020: + +**(Gronbech-Jensen-2020)** Gronbech-Jensen, Mol Phys 118, e1662506 (2020). + +.. _Gronbech-Jensen-2019: + +**(Gronbech Jensen/Gronbech-Jensen)** Gronbech Jensen and Gronbech-Jensen, Mol Phys, 117, 2511 (2019) + +.. _Gronbech-Jensen-Farago: + +**(Gronbech-Jensen/Farago)** Gronbech-Jensen and Farago, Mol Phys, 111, 983 (2013). + +.. _Finkelstein: + +**(Finkelstein)** Finkelstein, Cheng, Florin, Seibold, Gronbech-Jensen, J. Chem. Phys., 155, 18 (2021) + +.. _Gronbech-Jensen-2024: + +**(Gronbech-Jensen-2024)** Gronbech-Jensen, J. Stat. Phys. 191, 137 (2024). + +.. _Gronbech-Jensen-2023: + +**(Gronbech-Jensen-2023)** Gronbech-Jensen, J. Stat. Phys. 190, 96 (2023). diff --git a/doc/src/fix_langevin.rst b/doc/src/fix_langevin.rst index 30e4c48270..b8be16e16d 100644 --- a/doc/src/fix_langevin.rst +++ b/doc/src/fix_langevin.rst @@ -56,7 +56,7 @@ Examples Description """"""""""" -Apply a Langevin thermostat as described in :ref:`(Schneider) ` +Apply a Langevin thermostat as described in :ref:`(Bruenger) ` to a group of atoms which models an interaction with a background implicit solvent. Used with :doc:`fix nve `, this command performs Brownian dynamics (BD), since the total force on each atom @@ -241,6 +241,13 @@ to zero by subtracting off an equal part of it from each atom in the group. As a result, the center-of-mass of a system with zero initial momentum will not drift over time. +.. deprecated:: TDB + +The *gjf* keyword in fix langevin is deprecated and will be removed +soon. The GJF functionality has been moved to its own fix style +:doc:`fix gjf ` and it is strongly recommended to use that +fix instead. + The keyword *gjf* can be used to run the :ref:`Gronbech-Jensen/Farago ` time-discretization of the Langevin model. As described in the papers cited below, the purpose of this method is to @@ -324,14 +331,16 @@ types, tally = no, zero = no, gjf = no. ---------- +.. _Bruenger1: + +**(Bruenger)** Bruenger, Brooks, and Karplus, Chem. Phys. Lett. 105, 495 (1982). +[Previously attributed to Schneider and Stoll, Phys. Rev. B 17, 1302 (1978). +Implementation remains unchanged.] + .. _Dunweg1: **(Dunweg)** Dunweg and Paul, Int J of Modern Physics C, 2, 817-27 (1991). -.. _Schneider1: - -**(Schneider)** Schneider and Stoll, Phys Rev B, 17, 1302 (1978). - .. _Gronbech-Jensen: **(Gronbech-Jensen)** Gronbech-Jensen and Farago, Mol Phys, 111, 983 diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst new file mode 100644 index 0000000000..dffbc93217 --- /dev/null +++ b/doc/src/fix_neighbor_swap.rst @@ -0,0 +1,264 @@ +.. index:: fix neighbor/swap + +fix neighbor/swap command +========================= + +Syntax +"""""" + +.. code-block:: LAMMPS + + fix ID group-ID neighbor/swap N X seed T R0 voro-ID keyword values ... + +* ID, group-ID are documented in :doc:`fix ` command +* neighbor/swap = style name of this fix command +* N = invoke this fix every N steps +* X = number of swaps to attempt every N steps +* seed = random # seed (positive integer) +* T = scaling temperature of the MC swaps (temperature units) +* R0 = scaling swap probability of the MC swaps (distance units) +* voro-ID = valid voronoi compute id (compute voronoi/atom) +* one or more keyword/value pairs may be appended to args +* keywords *types* and *diff* are mutually exclusive, but one must be specified +* keyword = *types* or *diff* or *ke* or *region* or *rates* + + .. parsed-literal:: + + *types* values = two or more atom types (Integers in range [1,Ntypes] or type labels) + *diff* values = one atom type + *ke* value = *yes* or *no* + *yes* = kinetic energy is conserved after atom swaps + *no* = no conservation of kinetic energy after atom swaps + *region* value = region-ID + region-ID = ID of region to use as an exchange/move volume + *rates* values = V1 V2 . . . Vntypes values to conduct variable diffusion for different atom types (unitless) + +Examples +"""""""" + +.. code-block:: LAMMPS + + compute voroN all voronoi/atom neighbors yes + fix mc all neighbor/swap 10 160 15238 1000.0 3.0 voroN diff 2 + fix myFix all neighbor/swap 100 1 12345 298.0 3.0 voroN region my_swap_region types 5 6 + fix kmc all neighbor/swap 1 100 345 1.0 3.0 voroN diff 3 rates 3 1 6 + +Description +""""""""""" + +.. versionadded:: TBD + +This fix performs Monte-Carlo (MC) evaluations to enable kinetic +Monte Carlo (kMC)-type behavior during MD simulation by allowing +neighboring atoms to swap their positions. In contrast to the :doc:`fix +atom/swap ` command which swaps pairs of atoms anywhere +in the simulation domain, the restriction of the MC swapping to +neighbors enables a hybrid MD/kMC-like simulation. + +Neighboring atoms are defined by using a Voronoi tesselation performed +by the :doc:`compute voronoi/atom ` command. +Two atoms are neighbors if their Voronoi cells share a common face +(3d) or edge (2d). + +The selection of a swap neighbor is made using a distance-based +criterion for weighting the selection probability of each swap, in the +same manner as kMC selects a next event using relative probabilities. +The acceptance or rejection of each swap is determined via the +Metropolis criterion after evaluating the change in system energy due +to the swap. + +A detailed explanation of the original implementation of this +algorithm can be found in :ref:`(Tavenner 2023) ` +where it was used to simulated accelerated diffusion in an MD context. + +Simulating inherently kinetically-limited behaviors which rely on rare +events (such as atomic diffusion in a solid) is challenging for +traditional MD since its relatively short timescale will not naturally +sample many events. This fix addresses this challenge by allowing rare +neighbor hopping events to be sampled in a kMC-like fashion at a much +faster rate (set by the specified *N* and *X* parameters). This enables +the processes of atomic diffusion to be approximated during an MD +simulation, effectively decoupling the MD atomic vibrational timescale +and the atomic hopping (kMC event) timescale. + +The algorithm implemented by this fix is as follows: + + - The MD simulation is paused every *N* steps + - A Voronoi tesselation is performed for the current atom configuration. + - Then *X* atom swaps are attempted, one after the other. + - For each swap, an atom *I* is selected randomly from the list of + atom types specified by either the *types* or *diff* keywords. + - One of *I*'s Voronoi neighbors *J* is selected using the + distance-weighted probability for each neighbor detailed below. + - The *I,J* atom IDs are communicated to all processors so that a + global energy evaluation can be performed for the post-swap state + of the system. + - The swap is accepted or rejected based on the Metropolis criterion + using the energy change of the system and the specified temperature + *T*. + +Here are a few comments on the computational cost of the swapping +algorithm. + + 1. The cost of a global energy evaluation is similar to that of an MD + timestep. + + 2. Similar to other MC algorithms in LAMMPS, improved parallel + efficiency is achieved with a smaller number of atoms per + processor than would typically be used in an standard MD + simulation. This is because the per-energy evaluation cost + increases relative to the balance of MD/MC steps as indicated by + 1., but the communication cost remains relatively constant for a + given number of MD steps. + + 3. The MC portion of the simulation will run dramatically slower if + the pair style uses different cutoffs for different atom types (or + type pairs). This is because each atom swap then requires a + rebuild of the neighbor list to ensure the post-swap global energy + can be computed correctly. + +Limitations are imposed on selection of *I,J* atom pairs to avoid +swapping of atoms which are outside of a reasonable cutoff (e.g. due to +a Voronoi tesselation near free surfaces) though the use of a +distance-weighted probability scaling. + +---------- + +This section gives more details on other arguments and keywords. + +The random number generator (RNG) used by all the processors for MC +operations is initialized with the specified *seed*. + +The distance-based probability is weighted by the specified *R0* which +sets the radius :math:`r_0` in this formula + +.. math:: + + p_{ij} = e^{(\frac{r_{ij}}{r_0})^2} + +where :math:`p_{ij}` is the probability of selecting atom :math:`j` to +swap with atom :math:`i`. Typically, a value for *R0* around the +average nearest-neighbor spacing is appropriate. Since this is simply a +probability weighting, the swapping behavior is not very sensitive to +the exact value of *R0*. + +The required *voro-ID* value is the compute-ID of a +:doc:`compute voronoi/atom ` command like +this: + +.. code-block:: LAMMPS + + compute compute-ID group-ID voronoi/atom neighbors yes + +It must return per-atom list of valid neighbor IDs as in the +:doc:`compute voronoi/atom ` command. + +The keyword *types* takes two or more atom types as its values. Only +atoms *I* of the first atom type will be selected. Only atoms *J* of the +remaining atom types will be considered as potential swap partners. + +The keyword *diff* take a single atom type as its value. Only atoms +*I* of the that atom type will be selected. Atoms *J* of all +remaining atom types will be considered as potential swap partners. +This includes the atom type specified with the *diff* keyword to +account for self-diffusive hops between two atoms of the same type. + +Note that the *neighbors yes* option must be enabled for use with this +fix. The group-ID should include all the atoms which this fix will +potentially select. I.e. the group-ID used in the voronoi compute should +include the same atoms as that indicated by the *types* keyword. If the +*diff* keyword is used, the group-ID should include atoms of all types +in the simulation. + +The keyword *ke* takes *yes* (default) or *no* as its value. It two +atoms are swapped with different masses, then a value of *yes* will +rescale their respective velocities to conserve the kinetic energy of +the system. A value of *no* will perform no rescaling, so that +kinetic energy is not conserved. See the restriction on this keyword +below. + +The *region* keyword takes a *region-ID* as its value. If specified, +then only atoms *I* and *J* within the geometric region will be +considered as swap partners. See the :doc:`region ` command +for details. This means the group-ID for the :doc:`compute +voronoi/atom ` command also need only contain +atoms within the region. + +The keyword *rates* can modify the swap rate based on the type of atom +*J*. Ntype values must be specified, where Ntype = the number of atom +types in the system. Each value is used to scale the probability +weighting given by the equation above. In the third example command +above, a simulation has 3 atoms types. Atom *I*s of type 1 are +eligible for swapping. Swaps may occur with atom *J*s of all 3 types. +Assuming all *J* atoms are equidistant from an atom *I*, *J* atoms of +type 1 will be 3x more likely to be selected as a swap partner than +atoms of type 2. And *J* atoms of type 3 will be 6.5x more likely to +be selected than atoms of type 2. If the *rates* keyword is not used, +all atom types will be treated with the same probability during selection +of swap attempts. + + +Restart, fix_modify, output, run start/stop, minimize info +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +This fix writes the state of the fix to :doc:`binary restart files +`. This includes information about the random number generator +seed, the next timestep for MC exchanges, and the number of exchange +attempts and successes. See the :doc:`read_restart ` +command for info on how to re-specify a fix in an input script that +reads a restart file, so that the operation of the fix continues in an +uninterrupted fashion. + +None of the :doc:`fix_modify ` options are relevant to this +fix. + +This fix computes a global vector of length 2, which can be accessed +by various :doc:`output commands `. The vector values are +the following global cumulative quantities: + + #. swap attempts + #. swap accepts + +The vector values calculated by this fix are "intensive". + +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during +:doc:`energy minimization `. + +Restrictions +"""""""""""" + +This fix is part of the MC package. It is only enabled if LAMMPS was +built with that package. See the :doc:`Build package ` +doc page for more info. Also this fix requires that the :ref:`VORONOI +package ` is installed, otherwise the fix will not be +compiled. + +The :doc:`compute voronoi/atom ` command +referenced by the required voro-ID must return neighboring atoms as +illustrated in the examples above. + +If this fix is used with systems that do not have per-type masses +(e.g. atom style sphere), the *ke* keyword must be set to *off* since +the implemented algorithm will not be able to re-scale velocities +properly. + +Related commands +"""""""""""""""" + +:doc:`fix nvt `, :doc:`compute voronoi/atom ` +:doc:`delete_atoms `, :doc:`fix gcmc `, +:doc:`fix atom/swap `, :doc:`fix mol/swap `, +:doc:`fix sgcmc ` + +Default +""""""" + +The option defaults are *ke* = yes and *rates* = 1 for all atom types. + +---------- + +.. _TavennerMDkMC: + +**(Tavenner 2023)** J Tavenner, M Mendelev, J Lawson, Computational + Materials Science, 218, 111929 (2023). diff --git a/doc/src/fix_qeq_rel_reaxff.rst b/doc/src/fix_qeq_rel_reaxff.rst index 012980e230..98023ab51a 100644 --- a/doc/src/fix_qeq_rel_reaxff.rst +++ b/doc/src/fix_qeq_rel_reaxff.rst @@ -37,18 +37,18 @@ Examples Description """"""""""" -.. versionadded:: 19Nov2024 +.. versionadded:: 2Apr2025 -This fix implements the QEqR method for charge equilibration, which -differs from the QEq charge equilibration method :ref:`(Rappe and -Goddard) ` only in how external electric fields are accounted -for. This fix therefore raises a warning when used without :doc:`fix -efield ` since :doc:`fix qeq/reaxff ` should -be used without an external electric field. Charges are computed with -the QEqR method by minimizing the electrostatic energy of the system in -the same way as the QEq method but where the absolute electronegativity, -:math:`\chi_i`, of each atom in the QEq method is replaced with an -effective electronegativity given by +This fix implements the QEqR method :ref:`(Lalli) ` for charge +equilibration, which differs from the QEq charge equilibration method +:ref:`(Rappe and Goddard) ` only in how external electric fields +are accounted for. This fix therefore raises a warning when used without +:doc:`fix efield ` since :doc:`fix qeq/reaxff ` +should be used when no external electric field is present. Charges are +computed with the QEqR method by minimizing the electrostatic energy of +the system in the same way as the QEq method but where the absolute +electronegativity, :math:`\chi_i`, of each atom in the QEq method is +replaced with an effective electronegativity given by .. math:: \chi_{\mathrm{r}i} = \chi_i + \frac{\sum_{j=1}^{N} \beta(\phi_i - \phi_j) S_{ij}} @@ -61,8 +61,9 @@ external electric field and :math:`S_{ij}` is the overlap integral between atoms :math:`i` and :math:`j`. This formulation is advantageous over the method used by :doc:`fix qeq/reaxff ` to account for an external electric field in that it permits periodic -boundaries in the direction of an external electric field and in that it -does not worsen long-range charge transfer seen with QEq. +boundaries in the direction of an external electric field and in +that it does not worsen long-range charge transfer seen with +QEq. See :ref:`Lalli ` for further details. This fix is typically used in conjunction with the ReaxFF force field model as implemented in the :doc:`pair_style reaxff ` @@ -184,6 +185,10 @@ scale = 1.0 and maxiter = 200 ---------- +.. _lalli2: + +**(Lalli)** Lalli and Giusti, Journal of Chemical Physics, 162, 174311 (2025). + .. _Rappe4: **(Rappe)** Rappe and Goddard III, Journal of Physical Chemistry, 95, diff --git a/doc/src/fix_qtpie_reaxff.rst b/doc/src/fix_qtpie_reaxff.rst index 08ae24e164..643295dba4 100644 --- a/doc/src/fix_qtpie_reaxff.rst +++ b/doc/src/fix_qtpie_reaxff.rst @@ -59,8 +59,7 @@ and atom :math:`j`. The effect of an external electric field can be incorporated into the QTPIE method by modifying the absolute or effective electronegativities of each atom :ref:`(Chen) `. This fix models the effect of an external -electric field by using the effective electronegativity given in -:ref:`(Gergs) `: +electric field by using the effective electronegativity :ref:`(Lalli) ` .. math:: \tilde{\chi}_{\mathrm{r}i} = \frac{\sum_{j=1}^{N} (\chi_i - \chi_j + \beta(\phi_i - \phi_j)) S_{ij}} @@ -68,7 +67,8 @@ electric field by using the effective electronegativity given in where :math:`\beta` is a scaling factor and :math:`\phi_i` and :math:`\phi_j` are the electric potentials at the positions of atoms :math:`i` and :math:`j` -due to the external electric field. +due to the external electric field. Additional details regarding the +implementation and performance of this fix are provided in :ref:`Lalli `. This fix is typically used in conjunction with the ReaxFF force field model as implemented in the :doc:`pair_style reaxff ` @@ -206,10 +206,9 @@ scale = 1.0 and maxiter = 200 **(Chen)** Chen, Jiahao. Theory and applications of fluctuating-charge models. University of Illinois at Urbana-Champaign, 2009. -.. _Gergs: +.. _lalli: -**(Gergs)** Gergs, Dirkmann and Mussenbrock. -Journal of Applied Physics 123.24 (2018). +**(Lalli)** Lalli and Giusti, Journal of Chemical Physics, 162, 174311 (2025). .. _qeq-Aktulga2: diff --git a/doc/src/fix_set.rst b/doc/src/fix_set.rst new file mode 100644 index 0000000000..cfa8231ccd --- /dev/null +++ b/doc/src/fix_set.rst @@ -0,0 +1,173 @@ +.. index:: fix set + +fix set command +=============== + +Syntax +"""""" + +.. code-block:: LAMMPS + + fix ID group-ID set Nfreq rnflag set-args + +* ID, group-ID are documented in :doc:`fix ` command +* set = style name of this fix command +* Nfreq = reset per-atom properties every this many timesteps +* rnflag = 1 to reneighbor on next timestep, 0 to not +* set-args = identical to args for the :doc:`set ` command + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 10 all set 1 0 group all i_dump v_new + fix 10 all set 1 0 group all i_dump v_turnoff + +Description +""""""""""" + +Reset one or more properties of one or more atoms once every *Nfreq* +steps during a simulation. + +If the *rnflag* for reneighboring is set to 1, then a reneighboring +will be triggered on the next timestep (since the fix set operation +occurs at the end of the current timestep). This is important to do +if this command changes per-atom properties that need to be +communicated to ghost atoms. If this is not the case, an *rnflag* +setting of 0 can be used; reneighboring will only be triggered on +subsequent timesteps by the usual neighbor list criteria; see the +:doc:`neigh_modify command `. + +Here are two examples where an *rnflag* setting of 1 are needed. If a +custom per-atom property is changed and the :doc:`fix property/atom +` command to create the property used the *ghost +yes* keyword. Or if per-atom charges are changed, all pair styles +which compute Coulombic interactions require charge values for ghost +atoms. In both these examples, the re-neighboring will trigger the +changes in the owned atom properties to be immediately communicated to +ghost atoms. + +The arguments following *Nfreq* and *rnflag* are identical to those +allowed for the :doc:`set ` command, as in the examples above and +below. + +Note that the group-ID setting for this command is ignored. The +syntax for the :doc:`set ` arguments allows selection of which +atoms have their properties reset. + +This command can only be used to reset an atom property using a +per-atom variable. This option in allowed by many, but not all, of +the keyword/value pairs supported by the :doc:`set ` command. +The reason for this restriction is that if a per-atom variable is not +used, this command will typically not change atom properties during +the simulation. + +The :doc:`set ` command can be used with similar syntax to this +command to reset atom properties once before or between simulations. + +---------- + +Here is an example of input script commands which will output atoms +into a dump file only when their x-velocity crosses a threshold value +*vthresh* for the first time. Their position and x-velocity will then +be output every step for *twindow* timesteps. + +.. code-block:: LAMMPS + + variable vthresh equal 2 # threshold velocity + variable twindow equal 10 # dump for this many steps + # + # define custom property i_dump to store timestep threshold is crossed + # + fix 2 all property/atom i_dump + set group all i_dump -1 + # + # fix set command checks for threshold crossings every step + # resets i_dump from -1 to current timestep when crossing occurs + # + variable start atom "vx > v_vthresh && i_dump == -1" + variable new atom ternary(v_start,step,i_dump) + fix 3 all set 1 0 group all i_dump v_new + # + # dump command with thresh which enforces twindow + # + dump 1 all custom 1 tmp.dump id x y vx i_dump + variable dumpflag atom "i_dump >= 0 && (step-i_dump) < v_twindow" + dump_modify 1 thresh v_dumpflag == 1 + # + # run the simulation + # final dump with all atom IDs which crossed threshold on which timestep + # + run 1000 + write_dump all custom tmp.dump.final id i_dump modify thresh i_dump >= 0 + +The tmp.dump.final file lists which atoms crossed the velocity +threshold. This command will print the *twindow* timesteps when a +specific atom ID (104 in this case) was output in the tmp.dump file: + +.. code-block:: LAMMPS + + % grep "^104 " tmp.dump + +If these commands are used instead of the above, then an atom can +cross the velocity threshold multiple times, and will be output for +*twindow* timesteps each time. However the write_dump command is no +longer useful. + +.. code-block:: LAMMPS + + variable vthresh equal 2 # threshold velocity + variable twindow equal 10 # dump for this many steps + # + # define custom property i_dump to store timestep threshold is crossed + # + fix 2 all property/atom i_dump + set group all i_dump -1 + # + # fix set command checks for threshold crossings every step + # resets i_dump from -1 to current timestep when crossing occurs + # + variable start atom "vx > v_vthresh && i_dump == -1" + variable turnon atom ternary(v_start,step,i_dump) + variable stop atom "v_turnon >= 0 && (step-v_turnon) < v_twindow" + variable turnoff atom ternary(v_stop,v_turnon,-1) + fix 3 all set 1 0 group all i_dump v_turnoff + # + # dump command with thresh which enforces twindow + # + dump 1 all custom 1 tmp.dump id x y vx i_dump + variable dumpflag atom "i_dump >= 0 && (step-i_dump) < v_twindow" + dump_modify 1 thresh v_dumpflag == 1 + # + # run the simulation + # + run 1000 + +---------- + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files +`. None of the :doc:`fix_modify ` options are +relevant to this fix. No global or per-atom quantities are stored by +this fix for access by various :doc:`output commands `. +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during +:doc:`energy minimization `. + +Restrictions +"""""""""""" + +none + +Related commands +"""""""""""""""" + +:doc:`set ` + +Default +""""""" + +none diff --git a/doc/src/fix_sgcmc.rst b/doc/src/fix_sgcmc.rst index b9d933cec3..0a4156a886 100644 --- a/doc/src/fix_sgcmc.rst +++ b/doc/src/fix_sgcmc.rst @@ -30,7 +30,9 @@ Syntax N = number of times sampling window is moved during one MC cycle *window_size* frac frac = size of sampling window (must be between 0.5 and 1.0) - + *atomic/energy* yes/no + yes = use the atomic energy method to calculate energy changes + no = use the default method to calculate energy changes Examples """""""" @@ -127,6 +129,14 @@ The number of times the window is moved during a MC cycle is set using the parameter *window_moves* (see Sect. III.B in :ref:`Sadigh1 ` for details). +The *atomic/energy* keyword controls which method is used for calculating +the energy change when atom types are swapped. A value of *no* +uses the default method, see discussion below in Restrictions section. +A value of *yes* uses the atomic energy method, +if the method has been implemented for the LAMMPS energy model, +otherwise LAMMPS will exit with an error message. +So far this has only been implemented for EAM type potentials. + ------------ Restart, fix_modify, output, run start/stop, minimize info @@ -159,16 +169,26 @@ page for more info. This fix style requires an :doc:`atom style ` with per atom type masses. -At present the fix provides optimized subroutines for EAM type -potentials (see above) that calculate potential energy changes due to -*local* atom type swaps very efficiently. Other potentials are -supported by using the generic potential functions. This, however, will -lead to exceedingly slow simulations since it implies that the -energy of the *entire* system is recomputed at each MC trial step. If -other potentials are to be used it is strongly recommended to modify and -optimize the existing generic potential functions for this purpose. -Also, the generic energy calculation can not be used for parallel -execution i.e. it only works with a single MPI process. +The fix provides three methods for calculating the potential energy +change due to atom type swaps. For EAM type potentials, the default +method is a carefully optimized local energy change calculation that +is part of the source code for this fix. It takes advantage of the +specific computational and communication requirements of EAM. Customizing +the local method to handle other energy models such as Tersoff has been done, +but these cases are not supported in the public LAMMPS code. +For all other LAMMPS energy models, the default method calculates +the *total* potential energy of the system before and after each +atom type swap. This method does not depend on the details of the +energy model and so is guaranteed to be correct. It is also +orders of magnitude slower than the custom EAM calculation. +In addition, it can not be used with parallel execution i.e. only +a single MPI process is allowed. +The third method uses the *atomic/energy* keyword described above. +This allows parallel execution and it is also a local calculation, +making it only a bit slower than a fully-optimized local calculation. +So far, this has been implemented for EAM type potentials. +It is straightforward to extend this to other potentials, +requiring adding an atomic energy method to the pair style. ------------ @@ -180,6 +200,7 @@ The optional parameters default to the following values: * *randseed* = 324234 * *window_moves* = 8 * *window_size* = automatic +* *atomic/energy* = no ------------ diff --git a/doc/src/pair_granular.rst b/doc/src/pair_granular.rst index 4ae59a587f..4d8753a7a1 100644 --- a/doc/src/pair_granular.rst +++ b/doc/src/pair_granular.rst @@ -44,7 +44,7 @@ Examples pair_coeff * * hertz 1000.0 50.0 tangential mindlin 1000.0 1.0 0.4 heat area 0.1 pair_style granular - pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 0.0 0.7 rolling sds 2.7e5 0.0 0.6 damping none + pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 1.0 0.7 rolling sds 2.7e5 0.0 0.6 damping mdr 1 Description """"""""""" @@ -88,7 +88,8 @@ and their required arguments are: 3. *hertz/material* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu` 4. *dmt* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` 5. *jkr* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` -6. *mdr* : :math:`E`, :math:`\nu`, :math:`Y`, :math:`\Delta\gamma`, :math:`\psi_b`, :math:`e` +6. *mdr* : :math:`E`, :math:`\nu`, :math:`Y`, :math:`\Delta\gamma`, + :math:`\psi_b`, :math:`\eta_{n0}` Here, :math:`k_n` is spring stiffness (with units that depend on model choice, see below); :math:`\eta_{n0}` is a damping prefactor (or, in its @@ -177,6 +178,8 @@ two-part series :ref:`Zunker and Kamrin Part I ` and :ref:`Zunker and Kamrin Part II `. Further development and demonstrations of its application to industrially relevant powder compaction processes are presented in :ref:`Zunker et al. `. +If you use the *mdr* normal model the only supported damping option is +the *mdr* damping class described below. The model requires the following inputs: @@ -200,8 +203,8 @@ The model requires the following inputs: triggered. Lower values of :math:`\psi_b` delay the onset of the bulk elastic response. - 6. *Coefficient of restitution* :math:`0 \le e \le 1` : The coefficient of - restitution is a tunable parameter that controls damping in the normal direction. + 6. *Damping coefficent* :math:`\eta_{n0} \ge 0` : The damping coefficient + is a tunable parameter that controls damping in the normal direction. .. note:: @@ -213,18 +216,12 @@ The *mdr* model produces a nonlinear force-displacement response, therefore the critical timestep :math:`\Delta t` depends on the inputs and level of deformation. As a conservative starting point the timestep can be assumed to be dictated by the bulk elastic response such that -:math:`\Delta t = 0.35\sqrt{m/k_\textrm{bulk}}`, where :math:`m` is the mass of +:math:`\Delta t = 0.08\sqrt{m/k_\textrm{bulk}}`, where :math:`m` is the mass of the smallest particle and :math:`k_\textrm{bulk} = \kappa R_\textrm{min}` is an effective stiffness related to the bulk elastic response. Here, :math:`\kappa = E/(3(1-2\nu))` is the bulk modulus and :math:`R_\textrm{min}` is the radius of the smallest particle. -.. note:: - - The *mdr* model requires some specific settings to function properly, - please read the following text carefully to ensure all requirements are - followed. - The *atom_style* must be set to *sphere 1* to enable dynamic particle radii. The *mdr* model is designed to respect the incompressibility of plastic deformation and inherently tracks free surface displacements @@ -253,13 +250,6 @@ algorithm see :ref:`Zunker et al. `. newton off -The damping model must be set to *none*. The *mdr* model already has a built -in damping model. - -.. code-block:: LAMMPS - - pair_coeff * * mdr 5e6 0.4 1.9e5 2 0.5 0.5 damping none - The definition of multiple *mdr* models in the *pair_style* is currently not supported. Similarly, the *mdr* model cannot be combined with a different normal model in the *pair_style*. Physically this means that only one homogeneous @@ -270,7 +260,7 @@ The *mdr* model currently only supports *fix wall/gran/region*, not any *fix wall/gran/region* commands must also use the *mdr* model. Additionally, the following *mdr* inputs must match between the *pair_style* and *fix wall/gran/region* definitions: :math:`E`, -:math:`\nu`, :math:`Y`, :math:`\psi_b`, and :math:`e`. The exception +:math:`\nu`, :math:`Y`, :math:`\psi_b`, and :math:`\eta_{n0}`. The exception is :math:`\Delta\gamma`, which may vary, permitting different adhesive behaviors between particle-particle and particle-wall interactions. @@ -336,6 +326,7 @@ for the damping model currently supported are: 3. *viscoelastic* 4. *tsuji* 5. *coeff_restitution* +6. *mdr* (class) : :math:`d_{type}` If the *damping* keyword is not specified, the *viscoelastic* model is used by default. @@ -425,6 +416,37 @@ the damping coefficient, it accurately reproduces the specified coefficient of restitution for both monodisperse and polydisperse particle pairs. This damping model is not compatible with cohesive normal models such as *JKR* or *DMT*. +The *mdr* damping class contains multiple damping models that can be toggled between +by specifying different integer values for the :math:`d_{type}` input parameter. This +damping option is only compatible with the normal *mdr* contact model. + +Setting :math:`d_{type} = 1` is the suggested damping option. This specifies a damping +model that takes into account the contact stiffness :math:`k_{mdr}` calculated +by the normal *mdr* contact model to determine the damping coefficient: + +.. math:: + + \eta_n = \eta_{n0} (m_{eff}k_{mdr})^{1/2}, + +where :math:`k_{mdr}` is proportional to contact radius :math:`a_{mdr}` tracked by the +normal *mdr* contact model: + +.. math:: + + k_{mdr} = 2 E_{eff} a_{mdr}. + +In this case, :math:`\eta_{n0}` is simply a dimensionless coefficient that scales the +the overall damping coefficient. + +The other supported option is :math:`d_{type} = 2`, which defines a simple damping model +similar to the *velocity* option + +.. math:: + + \eta_n = \eta_{n0}, + +but has additional checks to avoid non-physical damping after plastic deformation. + The total normal force is computed as the sum of the elastic and damping components: @@ -1068,8 +1090,8 @@ a bulk elastic response. Journal of the Mechanics and Physics of Solids, **(Zunker et al, 2025)** Zunker, W., Dunatunga, S., Thakur, S., Tang, P., & Kamrin, K. (2025). Experimentally validated DEM for large -deformation powder compaction: mechanically-derived contact model and -screening of non-physical contacts. +deformation powder compaction: Mechanically-derived contact model and +screening of non-physical contacts. Powder Technology, 120972. .. _Luding2008: diff --git a/doc/src/pair_hybrid.rst b/doc/src/pair_hybrid.rst index 93e5621736..05cc8ddf24 100644 --- a/doc/src/pair_hybrid.rst +++ b/doc/src/pair_hybrid.rst @@ -100,6 +100,56 @@ first is assigned to intra-molecular interactions (i.e. both atoms have the same molecule ID), the second to inter-molecular interactions (i.e. interacting atoms have different molecule IDs). +.. admonition:: When **NOT** to use a hybrid pair style + :class: warning + + Using pair style *hybrid* can be very tempting to use if you need a + **many-body potential** supporting a mix of elements for which you + cannot find a potential file that covers *all* of them. Regardless + of how this is set up, there will be *errors*. The major use case + where the error is *small*, is when the many-body sub-styles are used + on different objects (for example a slab and a liquid, a metal and a + nano-machining work piece). In that case the *mixed* terms + **should** be provided by a pair-wise additive potential (like + Lennard-Jones or Morse) to avoid unexpected behavior and reduce + errors. LAMMPS cannot easily check for this condition and thus will + accept good and bad choices alike. + + Outside of this, we *strongly* recommend *against* using pair style + hybrid with many-body potentials for the following reasons: + + 1. When trying to combine EAM or MEAM potentials, there is a *large* + error in the embedding term, since it is computed separately for + each sub-style only. + + 2. When trying to combine many-body potentials like Stillinger-Weber, + Tersoff, AIREBO, Vashishta, or similar, you have to understand + that the potential of a sub-style cannot be applied in a pair-wise + fashion but will need to be applied to multiples of atoms + (e.g. a Tersoff potential of elements A and B includes the + interactions A-A, B-B, A-B, A-A-A, A-A-B, A-B-B, A-B-A, B-A-A, + B-A-B, B-B-A, B-B-B; AIREBO also considers all quadruples of + atom elements). + + 3. When one of the sub-styles uses charge-equilibration (= QEq; like + in ReaxFF or COMB) you have inconsistent QEq behavior because + either you try to apply QEq to *all* atoms but then you are + missing the QEq parameters for the non-QEq pair style (and it + would be inconsistent to apply QEq for pair styles that are not + parameterized for QEq) or else you would have either no charges or + fixed charges interacting with the QEq which also leads to + inconsistent behavior between two sub-styles. When attempting to + use multiple ReaxFF instances to combine different potential + files, you might be able to work around the QEq limitations, but + point 2. still applies. + + We understand that it is frustrating to not be able to run simulations + due to lack of available potential files, but that does not justify + combining potentials in a broken way via pair style hybrid. This is + not what the hybrid pair styles are designed for. + +---------- + Here are two examples of hybrid simulations. The *hybrid* style could be used for a simulation of a metal droplet on a LJ surface. The metal atoms interact with each other via an *eam* potential, the surface atoms @@ -374,12 +424,11 @@ selected sub-style. ---------- -.. note:: - - Several of the potentials defined via the pair_style command in - LAMMPS are really many-body potentials, such as Tersoff, AIREBO, MEAM, - ReaxFF, etc. The way to think about using these potentials in a - hybrid setting is as follows. +Even though the command name "pair_style" would suggest that these are +pair-wise interactions, several of the potentials defined via the +pair_style command in LAMMPS are really many-body potentials, such as +Tersoff, AIREBO, MEAM, ReaxFF, etc. The way to think about using these +potentials in a hybrid setting is as follows. A subset of atom types is assigned to the many-body potential with a single :doc:`pair_coeff ` command, using "\* \*" to include diff --git a/doc/src/pair_lj_pirani.rst b/doc/src/pair_lj_pirani.rst new file mode 100644 index 0000000000..822d277a1b --- /dev/null +++ b/doc/src/pair_lj_pirani.rst @@ -0,0 +1,163 @@ +.. index:: pair_style lj/pirani +.. index:: pair_style lj/pirani/omp + +pair_style lj/pirani command +============================ + +Accelerator Variants: *lj/pirani/omp* + +Syntax +"""""" + +.. code-block:: LAMMPS + + pair_style lj/pirani cutoff + +* lj/pirani = name of the pair style +* cutoff = global cutoff (distance units) + +Examples +"""""""" + +.. code-block:: LAMMPS + + pair_style lj/pirani 10.0 + pair_coeff 1 1 4.0 7.0 6.0 3.5 0.0045 + +Description +""""""""""" + +.. versionadded:: TBD + +Pair style *lj/pirani* computes pairwise interactions from an Improved +Lennard-Jones (ILJ) potential according to :ref:`(Pirani) `. +The ILJ force field is adequate to model both equilibrium and +non-equilibrium properties of matter, in gaseous and condensed phases, +and at gas-surface interfaces. In particular, its use improves the +description of elementary process dynamics where the traditional +Lennard-Jones (LJ) formulation is usually applied. + + +.. math:: + + x = r/R_m \\ + n_x = \alpha*x^2 + \beta \\ + \gamma \equiv m \\ + + V(x) = \varepsilon \cdot \left( \frac{\gamma}{ n_x - \gamma} \left(\frac{1}{x} \right)^{n_x} + - \frac{n_x}{n_x - \gamma} \left(\frac{1}{x} \right)^{\gamma} \right) \qquad r < r_c + +:math:`r_c` is the cutoff. + + +An additional parameter, :math:`\alpha`, has been introduced in order to +be able to recover the traditional Lennard-Jones 12-6 with a specific +choice of parameters. With :math:`R_m \equiv r_0 = \sigma \cdot 2^{1 / +6}`, :math:`\alpha = 0`, :math:`\beta = 12` and :math:`\gamma = 6` it is +straightforward to prove that LJ 12-6 is obtained. Also, it can be +verified that using :math:`\alpha= 4`, :math:`\beta= 8` and +:math:`\gamma = 6`, at the equilibrium distance, the first and second +derivatives of ILJ match those of LJ 12-6. The parameter :math:`R_m` +corresponds to the equilibrium distance and :math:`\epsilon` to the well +depth. + + +This potential provides some advantages with respect to the standard LJ +potential, as explained in :ref:`(Pirani) `: it provides a more +realistic description of the long range behavior and an attenuation of +the hardness of the repulsive wall. + +This force field can be used for neutral-neutral (:math:`\gamma = 6`), +ion-neutral (:math:`\gamma = 4`) or ion-ion systems (:math:`\gamma = +1`). Notice that this implementation does not include explicit +electrostatic interactions. If these are desired, this pair style +should be used along with a Coulomb pair style like +:doc:`pair styles coul/cut or coul/long ` by using +:doc:`pair style hybrid/overlay ` and a suitable +:doc:`kspace style `, if needed. + +As discussed in :ref:`(Pirani) `, analysis of a variety of +systems showed that :math:`\alpha= 4` generally works very well. In +some special cases (e.g. those involving very small multiple charged +ions) this factor may take a slightly different value. The parameter +:math:`\beta` codifies the hardness (polarizability) of the interacting +partners, and for neutral-neutral systems it usually ranges from 6 +to 11. Moreover, the modulation of :math:`\beta` can model additional +interaction effects, such as charge transfer in the perturbative limit, +and can mitigate the effect of some uncertainty in the data used to +build up the potential function. + +The following coefficients must be defined for each pair of atoms +types via the :doc:`pair_coeff ` command as in the examples +above, or in the data file or restart files read by the +:doc:`read_data ` or :doc:`read_restart ` +commands: + +* :math:`\alpha` (dimensionless) +* :math:`\beta` (dimensionless) +* :math:`\gamma` (dimensionless) +* :math:`R_m` (distance units) +* :math:`\epsilon` (energy units) +* cutoff (distance units) + +The last coefficient is optional. If not specified, the global cutoff is used. + +---------- + +.. include:: accel_styles.rst + +---------- + +Mixing, shift, table, tail correction, restart, rRESPA info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +This pair style does not support mixing. Thus, coefficients for all I,J +pairs must be specified explicitly. + +This pair style supports the :doc:`pair_modify ` shift +option for the energy of the pair interaction. + +The :doc:`pair_modify ` table options are not relevant for +this pair style. + +This pair style does not support the :doc:`pair_modify ` +tail option for adding long-range tail corrections to energy and +pressure. + +This pair style writes its information to :doc:`binary restart files +`, so pair_style and pair_coeff commands do not need to be +specified in an input script that reads a restart file. + +This pair style supports the use of the *inner*, *middle*, and +*outer* keywords of the :doc:`run_style respa ` command, +meaning the pairwise forces can be partitioned by distance at different +levels of the rRESPA hierarchy. See the :doc:`run_style ` +command for details. + + +---------- + +Restrictions +"""""""""""" + +This pair style is only enabled if LAMMPS was built with the EXTRA-PAIR +package. See the :doc:`Build package ` page for more +info. + +Related commands +"""""""""""""""" + +* :doc:`pair_coeff ` +* :doc:`pair_style lj/cut ` + +Default +""""""" + +none + +-------------- + +.. _Pirani: + +**(Pirani)** F. Pirani, S. Brizi, L. Roncaratti, P. Casavecchia, D. Cappelletti and F. Vecchiocattivi, +Phys. Chem. Chem. Phys., 2008, 10, 5489-5503. diff --git a/doc/src/pair_lj_smooth.rst b/doc/src/pair_lj_smooth.rst index 4799ca3277..d6b266d932 100644 --- a/doc/src/pair_lj_smooth.rst +++ b/doc/src/pair_lj_smooth.rst @@ -48,13 +48,19 @@ At the inner cutoff the force and its first derivative will match the non-smoothed LJ formula. At the outer cutoff the force and its first derivative will be 0.0. The inner cutoff cannot be 0.0. +Explicit expressions for the coefficients C1, C2, C3, C4, as well as the +energy discontinuity at the cutoff can be found here :ref:`(Leoni_1) ` +and here :ref:`(Leoni_2) ` + .. note:: this force smoothing causes the energy to be discontinuous both in its values and first derivative. This can lead to poor energy - conservation and may require the use of a thermostat. Plot the energy - and force resulting from this formula via the - :doc:`pair_write ` command to see the effect. + conservation and may require the use of a thermostat. The energy + value discontinuity can be eliminated by shifting the potential + energy to be zero at the outer cutoff using the pair_modify shift + option. With or without shifting, you can plot the resulting energy + and force via the :doc:`pair_write ` command to see the effect. The following coefficients must be defined for each pair of atoms types via the :doc:`pair_coeff ` command as in the examples @@ -122,3 +128,14 @@ Default """"""" none + +---------- + +.. _Leoni_1: + +**(Leoni_1)** F. Leoni et al., Phys Rev Lett, 134, 128201 (2025). + +.. _Leoni_2: + +**(Leoni_2)** F. Leoni et al., Phys Rev Lett, 134, Supplementary Material (2025). + diff --git a/doc/src/pair_style.rst b/doc/src/pair_style.rst index bdf06d6b66..fd826d350d 100644 --- a/doc/src/pair_style.rst +++ b/doc/src/pair_style.rst @@ -272,6 +272,7 @@ accelerated styles exist. * :doc:`lj/long/dipole/long ` - long-range LJ and long-range point dipoles * :doc:`lj/long/tip4p/long ` - long-range LJ and long-range Coulomb for TIP4P water * :doc:`lj/mdf ` - LJ potential with a taper function +* :doc:`lj/pirani ` - Improved LJ potential * :doc:`lj/relres ` - LJ using multiscale Relative Resolution (RelRes) methodology :ref:`(Chaimovich) `. * :doc:`lj/spica ` - LJ for SPICA coarse-graining * :doc:`lj/spica/coul/long ` - LJ for SPICA coarse-graining with long-range Coulomb diff --git a/doc/src/run.rst b/doc/src/run.rst index c3dd171f6b..95e2f037db 100644 --- a/doc/src/run.rst +++ b/doc/src/run.rst @@ -103,14 +103,16 @@ must be done. .. note:: - If your input script changes the system between 2 runs, then the - initial setup must be performed to ensure the change is recognized by - all parts of the code that are affected. Examples are adding a - :doc:`fix ` or :doc:`dump ` or :doc:`compute `, changing - a :doc:`neighbor ` list parameter, or writing restart file - which can migrate atoms between processors. LAMMPS has no easy way to - check if this has happened, but it is an error to use the *pre no* - option in this case. + If your input script "changes" the system between 2 runs, then the + initial setup typically needs to be performed to ensure the change + is recognized by all parts of the code that are affected. Examples + are adding a :doc:`fix ` or :doc:`dump ` or + :doc:`compute `, changing a :doc:`neighbor ` + list parameter, using the :doc:`set ` command, or writing a + restart file via the :doc:`write_restart ` command, + which can migrate atoms between processors. LAMMPS has no easy way + to check if this has happened, but it is an error to use the *pre + no* option in these cases. If *post* is specified as "no", the full timing summary is skipped; only a one-line summary timing is printed. diff --git a/doc/src/set.rst b/doc/src/set.rst index 6be590e9b6..d2c865dfbb 100644 --- a/doc/src/set.rst +++ b/doc/src/set.rst @@ -22,21 +22,110 @@ Syntax for style = *region*, ID = a region ID * one or more keyword/value pairs may be appended -* keyword = *type* or *type/fraction* or *type/ratio* or *type/subset* - or *mol* or *x* or *y* or *z* or *vx* or *vy* or *vz* or *charge* or - *dipole* or *dipole/random* or *quat* or *spin/atom* or *spin/atom/random* or - *spin/electron* or *radius/electron* or - *quat* or *quat/random* or *diameter* or *shape* or *length* or *tri* or - *theta* or *theta/random* or *angmom* or *omega* or - *mass* or *density* or *density/disc* or *temperature* or - *volume* or *image* or *bond* or *angle* or *dihedral* or - *improper* or *sph/e* or *sph/cv* or *sph/rho* or - *smd/contact/radius* or *smd/mass/density* or *dpd/theta* or - *edpd/temp* or *edpd/cv* or *cc* or *epsilon* or - *i_name* or *d_name* or *i2_name* or *d2_name* + +* keyword = *angle* or *angmom* or *bond* or *cc* or *charge* or + *density* or *density/disc* or *diameter* or *dihedral* or *dipole* + or *dipole/random* or *dpd/theta* or *edpd/cv* or *edpd/temp* or + *epsilon* or *image* or *improper* or *length* or *mass* or *mol* or + *omega* or *quat* or *quat/random* or *radius/electron* or *shape* or + *smd/contact/radius* or *smd/mass/density* or *sph/cv* or *sph/e* or + *sph/rho* or *spin/atom* or *spin/atom/random* or *spin/electron* or + *temperature* or *theta* or *theta/random* or *tri* or *type* or + *type/fraction* or *type/ratio* or *type/subset* or *volume* or *vx* + or *vy* or *vz* or *x* or *y* or *z* or *i_name* or *d_name* or + *i2_name* or *d2_name* .. parsed-literal:: + *angle* value = numeric angle type or angle type label, for all angles between selected atoms + *angmom* values = Lx Ly Lz + Lx,Ly,Lz = components of angular momentum vector (distance-mass-velocity units) + any of Lx,Ly,Lz can be an atom-style variable (see below) + *bond* value = numeric bond type or bond type label, for all bonds between selected atoms + *cc* values = index cc + index = index of a chemical species (1 to Nspecies) + cc = chemical concentration of tDPD particles for a species (mole/volume units) + cc can be an atom-style variable (see below) + *charge* value = atomic charge (charge units) + value can be an atom-style variable (see below) + *density* value = particle density for a sphere or ellipsoid (mass/distance\^3 units), or for a triangle (mass/distance\^2 units) or line (mass/distance units) particle + value can be an atom-style variable (see below) + *density/disc* value = particle density for a 2d disc or ellipse (mass/distance\^2 units) + value can be an atom-style variable (see below) + *diameter* value = diameter of spherical particle (distance units) + value can be an atom-style variable (see below) + *dihedral* value = numeric dihedral type or dihedral type label, for all dihedrals between selected atoms + *dipole* values = x y z + x,y,z = orientation of dipole moment vector + any of x,y,z can be an atom-style variable (see below) + *dipole/random* values = seed Dlen + seed = random # seed (positive integer) for dipole moment orientations + Dlen = magnitude of dipole moment (dipole units) + *dpd/theta* value = internal temperature of DPD particles (temperature units) + value can be an atom-style variable (see below) + value can be NULL which sets internal temp of each particle to KE temp + *edpd/cv* value = volumetric heat capacity of eDPD particles (energy/temperature/volume units) + value can be an atom-style variable (see below) + *edpd/temp* value = temperature of eDPD particles (temperature units) + value can be an atom-style variable (see below) + *epsilon* value = dielectric constant of the medium where the atoms reside + value can be an atom-style variable (see below) + *image* values = nx ny nz + nx,ny,nz = which periodic image of the simulation box the atom is in + any of nx,ny,nz can be an atom-style variable (see below) + *improper* value = numeric improper type or improper type label, for all impropers between selected atoms + *length* value = len + len = length of line segment (distance units) + len can be an atom-style variable (see below) + *mass* value = per-atom mass (mass units) + value can be an atom-style variable (see below) + *mol* value = molecule ID + the moleclue ID can be an atom-style variable (see below) + *omega* values = Wx Wy Wz + Wx,Wy,Wz = components of angular velocity vector (radians/time units) + any of Wx,Wy,Wz can be an atom-style variable (see below) + *quat* values = a b c theta + a,b,c = unit vector to rotate particle around via right-hand rule + theta = rotation angle (degrees) + any of a,b,c,theta values can be an atom-style variable (see below) + *quat/random* value = seed + seed = random # seed (positive integer) for quaternion orientations + *radius/electron* value = eradius + eradius = electron radius (or fixed-core radius) (distance units) + value can be an atom-style variable (see below) + *shape* values = Sx Sy Sz + Sx,Sy,Sz = 3 diameters of ellipsoid (distance units) + any of Sx,Sy,Sz can be an atom-style variable (see below) + *smd/contact/radius* value = radius for short range interactions, i.e. contact and friction + value can be an atom-style variable (see below) + *smd/mass/density* value = set particle mass based on volume by providing a mass density + value can be an atom-style variable (see below) + *sph/cv* value = heat capacity of SPH particles (need units) + value can be an atom-style variable (see below) + *sph/e* value = energy of SPH particles (need units) + value can be an atom-style variable (see below) + *sph/rho* value = density of SPH particles (need units) + value can be an atom-style variable (see below) + *spin/atom* values = g x y z + g = magnitude of magnetic spin vector (in Bohr magneton's unit) + x,y,z = orientation of magnetic spin vector + any of x,y,z can be an atom-style variable (see below) + *spin/atom/random* values = seed Dlen + seed = random # seed (positive integer) for magnetic spin orientations + Dlen = magnitude of magnetic spin vector (in Bohr magneton's unit) + *spin/electron* value = espin + espin = electron spin (+1/-1), 0 = nuclei, 2 = fixed-core, 3 = pseudo-cores (i.e. ECP) + value can be an atom-style variable (see below) + *temperature* value = temperature for finite-size particles (temperature units) + value can be an atom-style variable (see below) + *theta* value = angle (degrees) + angle = orientation of line segment with respect to x-axis + value can be an atom-style variable (see below) + *theta/random* value = seed + seed = random # seed (positive integer) for line segment orienations + *tri* value = side + side = side length of equilateral triangle (distance units) + value can be an atom-style variable (see below) *type* value = numeric atom type or type label value can be an atom-style variable (see below) *type/fraction* values = type fraction seed @@ -51,104 +140,22 @@ Syntax type = numeric atom type or type label Nsubset = exact number of selected atoms to set to new atom type seed = random # seed (positive integer) - *mol* value = molecule ID - value can be an atom-style variable (see below) - *x*,\ *y*,\ *z* value = atom coordinate (distance units) + *volume* value = particle volume for Peridynamic particle (distance\^3 units) value can be an atom-style variable (see below) *vx*,\ *vy*,\ *vz* value = atom velocity (velocity units) value can be an atom-style variable (see below) - *charge* value = atomic charge (charge units) + *x*,\ *y*,\ *z* value = atom coordinate (distance units) value can be an atom-style variable (see below) - *dipole* values = x y z - x,y,z = orientation of dipole moment vector - any of x,y,z can be an atom-style variable (see below) - *dipole/random* value = seed Dlen - seed = random # seed (positive integer) for dipole moment orientations - Dlen = magnitude of dipole moment (dipole units) - *spin/atom* values = g x y z - g = magnitude of magnetic spin vector (in Bohr magneton's unit) - x,y,z = orientation of magnetic spin vector - any of x,y,z can be an atom-style variable (see below) - *spin/atom/random* value = seed Dlen - seed = random # seed (positive integer) for magnetic spin orientations - Dlen = magnitude of magnetic spin vector (in Bohr magneton's unit) - *radius/electron* values = eradius - eradius = electron radius (or fixed-core radius) (distance units) - *spin/electron* value = espin - espin = electron spin (+1/-1), 0 = nuclei, 2 = fixed-core, 3 = pseudo-cores (i.e. ECP) - *quat* values = a b c theta - a,b,c = unit vector to rotate particle around via right-hand rule - theta = rotation angle (degrees) - any of a,b,c,theta can be an atom-style variable (see below) - *quat/random* value = seed - seed = random # seed (positive integer) for quaternion orientations - *diameter* value = diameter of spherical particle (distance units) - value can be an atom-style variable (see below) - *shape* value = Sx Sy Sz - Sx,Sy,Sz = 3 diameters of ellipsoid (distance units) - *length* value = len - len = length of line segment (distance units) - len can be an atom-style variable (see below) - *tri* value = side - side = side length of equilateral triangle (distance units) - side can be an atom-style variable (see below) - *theta* value = angle (degrees) - angle = orientation of line segment with respect to x-axis - angle can be an atom-style variable (see below) - *theta/random* value = seed - seed = random # seed (positive integer) for line segment orienations - *angmom* values = Lx Ly Lz - Lx,Ly,Lz = components of angular momentum vector (distance-mass-velocity units) - any of Lx,Ly,Lz can be an atom-style variable (see below) - *omega* values = Wx Wy Wz - Wx,Wy,Wz = components of angular velocity vector (radians/time units) - any of wx,wy,wz can be an atom-style variable (see below) - *mass* value = per-atom mass (mass units) - value can be an atom-style variable (see below) - *density* value = particle density for a sphere or ellipsoid (mass/distance\^3 units), or for a triangle (mass/distance\^2 units) or line (mass/distance units) particle - value can be an atom-style variable (see below) - *density/disc* value = particle density for a 2d disc or ellipse (mass/distance\^2 units) - value can be an atom-style variable (see below) - *temperature* value = temperature for finite-size particles (temperature units) - value can be an atom-style variable (see below) - *volume* value = particle volume for Peridynamic particle (distance\^3 units) - value can be an atom-style variable (see below) - *image* nx ny nz - nx,ny,nz = which periodic image of the simulation box the atom is in - any of nx,ny,nz can be an atom-style variable (see below) - *bond* value = numeric bond type or bond type label, for all bonds between selected atoms - *angle* value = numeric angle type or angle type label, for all angles between selected atoms - *dihedral* value = numeric dihedral type or dihedral type label, for all dihedrals between selected atoms - *improper* value = numeric improper type or improper type label, for all impropers between selected atoms - *rheo/rho* value = density of RHEO particles (mass/distance\^3) - *rheo/status* value = status or phase of RHEO particles (unitless) - *sph/e* value = energy of SPH particles (need units) - value can be an atom-style variable (see below) - *sph/cv* value = heat capacity of SPH particles (need units) - value can be an atom-style variable (see below) - *sph/rho* value = density of SPH particles (need units) - value can be an atom-style variable (see below) - *smd/contact/radius* = radius for short range interactions, i.e. contact and friction - value can be an atom-style variable (see below) - *smd/mass/density* = set particle mass based on volume by providing a mass density - value can be an atom-style variable (see below) - *dpd/theta* value = internal temperature of DPD particles (temperature units) - value can be an atom-style variable (see below) - value can be NULL which sets internal temp of each particle to KE temp - *edpd/temp* value = temperature of eDPD particles (temperature units) - value can be an atom-style variable (see below) - *edpd/cv* value = volumetric heat capacity of eDPD particles (energy/temperature/volume units) - value can be an atom-style variable (see below) - *cc* values = index cc - index = index of a chemical species (1 to Nspecies) - cc = chemical concentration of tDPD particles for a species (mole/volume units) - *epsilon* value = dielectric constant of the medium where the atoms reside *i_name* value = custom integer vector with name + value can be an atom-style variable (see below) *d_name* value = custom floating-point vector with name - *i2_name* value = column of a custom integer array with name + value can be an atom-style variable (see below) + *i2_name* value = custom integer array with name column specified as i2_name[N] where N is 1 to Ncol - *d2_name* value = column of a custom floating-point array with name + value can be an atom-style variable (see below) + *d2_name* value = custom floating-point array with name column specified as d2_name[N] where N is 1 to Ncol + value can be an atom-style variable (see below) Examples """""""" @@ -177,22 +184,26 @@ Description Set one or more properties of one or more atoms. Since atom properties are initially assigned by the :doc:`read_data `, -:doc:`read_restart ` or :doc:`create_atoms ` -commands, this command changes those assignments. This can be useful -for overriding the default values assigned by the -:doc:`create_atoms ` command (e.g. charge = 0.0). It can -be useful for altering pairwise and molecular force interactions, +:doc:`read_restart ` or :doc:`create_atoms +` commands, this command changes those assignments. +This can be useful for overriding the default values assigned by the +:doc:`create_atoms ` command (e.g. charge = 0.0). It +can be useful for altering pairwise and molecular force interactions, since force-field coefficients are defined in terms of types. It can be used to change the labeling of atoms by atom type or molecule ID -when they are output in :doc:`dump ` files. It can also be useful -for debugging purposes; i.e. positioning an atom at a precise location -to compute subsequent forces or energy. +when they are output in :doc:`dump ` files. It can also be +useful for debugging purposes; i.e. positioning an atom at a precise +location to compute subsequent forces or energy. Note that the *style* and *ID* arguments determine which atoms have their properties reset. The remaining keywords specify which properties to reset and what the new values are. Some strings like *type* or *mol* can be used as a style and/or a keyword. +The :doc:`fix set ` command can be used with similar syntax +to this command to reset atom properties once every *N* steps during a +simulation using via atom-style variables. + ---------- This section describes how to select which atoms to change @@ -211,8 +222,8 @@ can be specified, e.g. "C". The style *mol* selects all the atoms in a range of molecule IDs. In each of the range cases, the range can be specified as a single -numeric value, or a wildcard asterisk can be used to specify a range -of values. This takes the form "\*" or "\*n" or "n\*" or "m\*n". For +numeric value, or with a wildcard asterisk to specify a range of +values. This takes the form "\*" or "\*n" or "n\*" or "m\*n". For example, for the style *type*, if N = the number of atom types, then an asterisk with no numeric values means all types from 1 to N. A leading asterisk means all types from 1 to n (inclusive). A trailing @@ -222,25 +233,25 @@ means all types from m to n (inclusive). For all the styles except The style *group* selects all the atoms in the specified group. The style *region* selects all the atoms in the specified geometric -region. See the :doc:`group ` and :doc:`region ` commands -for details of how to specify a group or region. +region. See the :doc:`group ` and :doc:`region ` +commands for details of how to specify a group or region. ---------- -This section describes the keyword options for which properties to +The next section describes the keyword options for which properties to change, for the selected atoms. Note that except where explicitly prohibited below, all of the keywords allow an :doc:`atom-style or atomfile-style variable ` to be used as the specified value(s). If the value is a -variable, it should be specified as v_name, where name is the -variable name. In this case, the variable will be evaluated, and its -resulting per-atom value used to determine the value assigned to each -selected atom. Note that the per-atom value from the variable will be -ignored for atoms that are not selected via the *style* and *ID* -settings explained above. A simple way to use per-atom values from -the variable to reset a property for all atoms is to use style *atom* -with *ID* = "\*"; this selects all atom IDs. +variable, it should be specified as v_name, where name is the variable +name. In this case, the variable will be evaluated, and its resulting +per-atom value used to determine the value assigned to each selected +atom. Note that the per-atom value from the variable will be ignored +for atoms that are not selected via the *style* and *ID* settings +explained above. A simple way to use per-atom values from the +variable to reset a property for all atoms is to use style *atom* with +*ID* = "\*"; this selects all atom IDs. Atom-style variables can specify formulas with various mathematical functions, and include :doc:`thermo_style ` command @@ -256,52 +267,110 @@ from a file. .. note:: Atom-style and atomfile-style variables return floating point - per-atom values. If the values are assigned to an integer variable, - such as the molecule ID, then the floating point value is truncated to - its integer portion, e.g. a value of 2.6 would become 2. + per-atom values. If the values are assigned to an integer + variable, such as the molecule ID, then the floating point value is + truncated to its integer portion, e.g. a value of 2.6 would + become 2. + +---------- .. versionchanged:: 28Mar2023 - Support for type labels was added for setting atom, bond, angle, - dihedral, and improper types + Support for type labels was added for setting angle types -Keyword *type* sets the atom type for all selected atoms. A specified -value can be either a numeric atom type or an atom type label. When -using a numeric type, the specified value must be from 1 to ntypes, -where ntypes was set by the :doc:`create_box ` command or -the *atom types* field in the header of the data file read by the -:doc:`read_data ` command. When using a type label it must -have been defined previously. See the :doc:`Howto type labels -` doc page for the allowed syntax of type labels -and a general discussion of how type labels can be used. +Keyword *angle* sets the angle type of all angles of selected atoms to +the specified value. The value can be a numeric type from 1 to +nangletypes. Or it can be a angle type label. See the :doc:`Howto +type labels ` doc page for the allowed syntax of +type labels and a general discussion of how type labels can be used. +All atoms in a particular angle must be selected atoms in order for +the change to be made. The value of nangletypes was set by the *angle +types* field in the header of the data file read by the +:doc:`read_data ` command. This keyword does NOT allow use +of an atom-style variable. -Keyword *type/fraction* sets the atom type for a fraction of the selected -atoms. The actual number of atoms changed is not guaranteed -to be exactly the specified fraction (0 <= *fraction* <= 1), but -should be statistically close. Random numbers are used in such a way -that a particular atom is changed or not changed, regardless of how -many processors are being used. This keyword does not allow use of an -atom-style variable. +Keyword *angmom* sets the angular momentum of selected atoms. The +particles must be ellipsoids as defined by the :doc:`atom_style +ellipsoid ` command or triangles as defined by the +:doc:`atom_style tri ` command. The angular momentum +vector of the particles is set to the 3 specified components. -Keywords *type/ratio* and *type/subset* also set the atom type for a -fraction of the selected atoms. The actual number of atoms changed -will be exactly the requested number. For *type/ratio* the specified -fraction (0 <= *fraction* <= 1) determines the number. For -*type/subset*, the specified *Nsubset* is the number. An iterative -algorithm is used which ensures the correct number of atoms are -selected, in a perfectly random fashion. Which atoms are selected -will change with the number of processors used. These keywords do not -allow use of an atom-style variable. +.. versionchanged:: 28Mar2023 -Keyword *mol* sets the molecule ID for all selected atoms. The -:doc:`atom style ` being used must support the use of -molecule IDs. + Support for type labels was added for setting bond types -Keywords *x*, *y*, *z*, and *charge* set the coordinates or -charge of all selected atoms. For *charge*, the :doc:`atom style -` being used must support the use of atomic -charge. Keywords *vx*, *vy*, and *vz* set the velocities of all -selected atoms. +Keyword *bond* sets the bond type of all bonds of selected atoms to +the specified value. The value can be a numeric type from 1 to +nbondtypes. Or it can be a bond type label. See the :doc:`Howto type +labels ` doc page for the allowed syntax of type +labels and a general discussion of how type labels can be used. All +atoms in a particular bond must be selected atoms in order for the +change to be made. The value of nbondtypes was set by the *bond +types* field in the header of the data file read by the +:doc:`read_data ` command. This keyword does NOT allow use +of an atom-style variable. + +Keyword *cc* sets the chemical concentration of a tDPD particle for a +specified species as defined by the DPD-MESO package. Currently, only +:doc:`atom_style tdpd ` defines particles with this +attribute. An integer for "index" selects a chemical species (1 to +Nspecies) where Nspecies is set by the atom_style command. The value +for the chemical concentration must be >= 0.0. + +Keyword *charge* set the charge of all selected atoms. The :doc:`atom +style ` being used must support the use of atomic charge. + +Keyword *density* or *density/disc* also sets the mass of all selected +particles, but in a different way. The particles must have a per-atom +mass attribute, as defined by the :doc:`atom_style ` +command. If the atom has a radius attribute (see :doc:`atom_style +sphere `) and its radius is non-zero, its mass is set from +the density and particle volume for 3d systems (the input density is +assumed to be in mass/distance\^3 units). For 2d, the default is for +LAMMPS to model particles with a radius attribute as spheres. +However, if the *density/disc* keyword is used, then they can be +modeled as 2d discs (circles). Their mass is set from the density and +particle area (the input density is assumed to be in mass/distance\^2 +units). + +If the atom has a shape attribute (see :doc:`atom_style ellipsoid +`) and its 3 shape parameters are non-zero, then its mass +is set from the density and particle volume (the input density is +assumed to be in mass/distance\^3 units). The *density/disc* keyword +has no effect; it does not (yet) treat 3d ellipsoids as 2d ellipses. + +If the atom has a length attribute (see :doc:`atom_style line +`) and its length is non-zero, then its mass is set from +the density and line segment length (the input density is assumed to +be in mass/distance units). If the atom has an area attribute (see +:doc:`atom_style tri `) and its area is non-zero, then its +mass is set from the density and triangle area (the input density is +assumed to be in mass/distance\^2 units). + +If none of these cases are valid, then the mass is set to the density +value directly (the input density is assumed to be in mass units). + +Keyword *diameter* sets the size of the selected atoms. The particles +must be finite-size spheres as defined by the :doc:`atom_style sphere +` command. The diameter of a particle can be set to 0.0, +which means they will be treated as point particles. Note that this +command does not adjust the particle mass, even if it was defined with +a density, e.g. via the :doc:`read_data ` command. + +.. versionchanged:: 28Mar2023 + + Support for type labels was added for setting dihedral types + +Keyword *dihedral* sets the dihedral type of all dihedrals of selected +atoms to the specified value. The value can be a numeric type from 1 +to ndihedraltypes. Or it can be a dihedral type label. See the +:doc:`Howto type labels ` doc page for the allowed +syntax of type labels and a general discussion of how type labels can +be used. All atoms in a particular dihedral must be selected atoms in +order for the change to be made. The value of ndihedraltypes was set +by the *dihedral types* field in the header of the data file read by +the :doc:`read_data ` command. This keyword does NOT allow +use of an atom-style variable. Keyword *dipole* uses the specified x,y,z values as components of a vector to set as the orientation of the dipole moment vectors of the @@ -313,40 +382,106 @@ moment vectors for the selected atoms and sets the magnitude of each to the specified *Dlen* value. For 2d systems, the z component of the orientation is set to 0.0. Random numbers are used in such a way that the orientation of a particular atom is the same, regardless of how -many processors are being used. This keyword does not allow use of an +many processors are being used. This keyword does NOT allow use of an atom-style variable. -.. versionchanged:: 15Sep2022 +Keyword *dpd/theta* sets the internal temperature of a DPD particle as +defined by the DPD-REACT package. If the specified value is a number +it must be >= 0.0. If the specified value is NULL, then the kinetic +temperature Tkin of each particle is computed as 3/2 k Tkin = KE = 1/2 +m v\^2 = 1/2 m (vx\*vx+vy\*vy+vz\*vz). Each particle's internal +temperature is set to Tkin. If the specified value is an atom-style +variable, then the variable is evaluated for each particle. If a +value >= 0.0, the internal temperature is set to that value. If it is +< 0.0, the computation of Tkin is performed and the internal +temperature is set to that value. -Keyword *spin/atom* uses the specified g value to set the magnitude of the -magnetic spin vectors, and the x,y,z values as components of a vector -to set as the orientation of the magnetic spin vectors of the selected -atoms. This keyword was previously called *spin*. +Keywords *edpd/temp* and *edpd/cv* set the temperature and volumetric +heat capacity of an eDPD particle as defined by the DPD-MESO package. +Currently, only :doc:`atom_style edpd ` defines particles +with these attributes. The values for the temperature and heat +capacity must be positive. -.. versionchanged:: 15Sep2022 +Keyword *epsilon* sets the dielectric constant of a particle to be +that of the medium where the particle resides as defined by the +DIELECTRIC package. Currently, only :doc:`atom_style dielectric +` defines particles with this attribute. The value for the +dielectric constant must be >= 0.0. Note that the set command with +this keyword will rescale the particle charge accordingly so that the +real charge (e.g., as read from a data file) stays intact. To change +the real charges, one needs to use the set command with the *charge* +keyword. Care must be taken to ensure that the real and scaled charges +and the dielectric constants are consistent. -Keyword *spin/atom/random* randomizes the orientation of the magnetic spin -vectors for the selected atoms and sets the magnitude of each to the -specified *Dlen* value. This keyword was previously called *spin/random*. +Keyword *image* sets which image of the simulation box the atom is +considered to be in. An image of 0 means it is inside the box as +defined. A value of 2 means add 2 box lengths to get the true value. +A value of -1 means subtract 1 box length to get the true value. +LAMMPS updates these flags as atoms cross periodic boundaries during +the simulation. The flags can be output with atom snapshots via the +:doc:`dump ` command. If a value of NULL is specified for any +of nx,ny,nz, then the current image value for that dimension is +unchanged. For non-periodic dimensions only a value of 0 can be +specified. This command can be useful after a system has been +equilibrated and atoms have diffused one or more box lengths in +various directions. This command can then reset the image values for +atoms so that they are effectively inside the simulation box, e.g if a +diffusion coefficient is about to be measured via the :doc:`compute +msd ` command. Care should be taken not to reset the +image flags of two atoms in a bond to the same value if the bond +straddles a periodic boundary (rather they should be different by +/- +1). This will not affect the dynamics of a simulation, but may mess +up analysis of the trajectories if a LAMMPS diagnostic or your own +analysis relies on the image flags to unwrap a molecule which +straddles the periodic box. -.. versionadded:: 15Sep2022 +.. versionchanged:: 28Mar2023 -Keyword *radius/electron* uses the specified value to set the radius of -electrons or fixed cores. + Support for type labels was added for setting improper types -.. versionadded:: 15Sep2022 +Keyword *improper* sets the improper type of all impropers of selected +atoms to the specified value. The value can be a numeric type from 1 +to nimpropertypes. Or it can be a improper type label. See the +:doc:`Howto type labels ` doc page for the allowed +syntax of type labels and a general discussion of how type labels can +be used. All atoms in a particular improper must be selected atoms in +order for the change to be made. The value of nimpropertypes was set +by the *improper types* field in the header of the data file read by +the :doc:`read_data ` command. This keyword does NOT allow +use of an atom-style variable. -Keyword *spin/electron* sets the spin of an electron (+/- 1) or indicates -nuclei (=0), fixed-cores (=2), or pseudo-cores (= 3). +Keyword *length* sets the length of selected atoms. The particles +must be line segments as defined by the :doc:`atom_style line +` command. If the specified value is non-zero the line +segment is (re)set to a length = the specified value, centered around +the particle position, with an orientation along the x-axis. If the +specified value is 0.0, the particle will become a point particle. +Note that this command does not adjust the particle mass, even if it +was defined with a density, e.g. via the :doc:`read_data ` +command. + +Keyword *mass* sets the mass of all selected particles. The particles +must have a per-atom mass attribute, as defined by the +:doc:`atom_style ` command. See the "mass" command for +how to set mass values on a per-type basis. + +Keyword *mol* sets the molecule ID for all selected atoms. The +:doc:`atom style ` being used must support the use of +molecule IDs. + +Keyword *omega* sets the angular velocity of selected atoms. The +particles must be spheres as defined by the :doc:`atom_style sphere +` command. The angular velocity vector of the particles +is set to the 3 specified components. Keyword *quat* uses the specified values to create a quaternion (4-vector) that represents the orientation of the selected atoms. The particles must define a quaternion for their orientation (e.g. ellipsoids, triangles, body particles) as defined by the -:doc:`atom_style ` command. Note that particles defined by -:doc:`atom_style ellipsoid ` have 3 shape parameters. The 3 -values must be non-zero for each particle set by this command. They -are used to specify the aspect ratios of an ellipsoidal particle, +:doc:`atom_style ` command. Note that particles defined +by :doc:`atom_style ellipsoid ` have 3 shape parameters. +The 3 values must be non-zero for each particle set by this command. +They are used to specify the aspect ratios of an ellipsoidal particle, which is oriented by default with its x-axis along the simulation box's x-axis, and similarly for y and z. If this body is rotated (via the right-hand rule) by an angle theta around a unit rotation vector @@ -360,51 +495,77 @@ ignored, since a rotation vector of (0,0,1) is the only valid choice. Keyword *quat/random* randomizes the orientation of the quaternion for the selected atoms. The particles must define a quaternion for their orientation (e.g. ellipsoids, triangles, body particles) as defined by -the :doc:`atom_style ` command. Random numbers are used in -such a way that the orientation of a particular atom is the same, +the :doc:`atom_style ` command. Random numbers are used +in such a way that the orientation of a particular atom is the same, regardless of how many processors are being used. For 2d systems, only orientations in the xy plane are generated. As with keyword *quat*, for ellipsoidal particles, the 3 shape values must be non-zero -for each particle set by this command. This keyword does not allow +for each particle set by this command. This keyword does NOT allow use of an atom-style variable. -Keyword *diameter* sets the size of the selected atoms. The particles -must be finite-size spheres as defined by the :doc:`atom_style sphere -` command. The diameter of a particle can be set to 0.0, -which means they will be treated as point particles. Note that this -command does not adjust the particle mass, even if it was defined with -a density, e.g. via the :doc:`read_data ` command. +.. versionadded:: 15Sep2022 + +Keyword *radius/electron* uses the specified value to set the radius +of electrons or fixed cores. Keyword *shape* sets the size and shape of the selected atoms. The particles must be ellipsoids as defined by the :doc:`atom_style -ellipsoid ` command. The *Sx*, *Sy*, *Sz* settings -are the 3 diameters of the ellipsoid in each direction. All 3 can be -set to the same value, which means the ellipsoid is effectively a -sphere. They can also all be set to 0.0 which means the particle will -be treated as a point particle. Note that this command does not -adjust the particle mass, even if it was defined with a density, -e.g. via the :doc:`read_data ` command. +ellipsoid ` command. The *Sx*, *Sy*, *Sz* settings are +the 3 diameters of the ellipsoid in each direction. All 3 can be set +to the same value, which means the ellipsoid is effectively a sphere. +They can also all be set to 0.0 which means the particle will be +treated as a point particle. Note that this command does not adjust +the particle mass, even if it was defined with a density, e.g. via the +:doc:`read_data ` command. -Keyword *length* sets the length of selected atoms. The particles -must be line segments as defined by the :doc:`atom_style line -` command. If the specified value is non-zero the line -segment is (re)set to a length = the specified value, centered around -the particle position, with an orientation along the x-axis. If the -specified value is 0.0, the particle will become a point particle. -Note that this command does not adjust the particle mass, even if it -was defined with a density, e.g. via the :doc:`read_data ` -command. +Keyword *smd/contact/radius* only applies to simulations with the +Smooth Mach Dynamics package MACHDYN. Itsets an interaction radius +for computing short-range interactions, e.g. repulsive forces to +prevent different individual physical bodies from penetrating each +other. Note that the SPH smoothing kernel diameter used for computing +long range, nonlocal interactions, is set using the *diameter* +keyword. -Keyword *tri* sets the size of selected atoms. The particles must be -triangles as defined by the :doc:`atom_style tri ` command. -If the specified value is non-zero the triangle is (re)set to be an -equilateral triangle in the xy plane with side length = the specified -value, with a centroid at the particle position, with its base -parallel to the x axis, and the y-axis running from the center of the -base to the top point of the triangle. If the specified value is 0.0, -the particle will become a point particle. Note that this command -does not adjust the particle mass, even if it was defined with a -density, e.g. via the :doc:`read_data ` command. +Keyword *smd/mass/density* sets the mass of all selected particles, +but it is only applicable to the Smooth Mach Dynamics package MACHDYN. +It assumes that the particle volume has already been correctly set and +calculates particle mass from the provided mass density value. + +Keywords *sph/cv*, *sph/e*, and *sph/rho* set the heat capacity, +energy, and density of smoothed particle hydrodynamics (SPH) +particles. See `this PDF guide `_ to +using SPH in LAMMPS. + +.. note:: + + Note that the SPH PDF guide file has not been updated for many + years and thus does not reflect the current *syntax* of the SPH + package commands. For that, please refer to the LAMMPS manual. + +.. versionchanged:: 15Sep2022 + +Keyword *spin/atom* uses the specified g value to set the magnitude of +the magnetic spin vectors, and the x,y,z values as components of a +vector to set as the orientation of the magnetic spin vectors of the +selected atoms. This keyword was previously called *spin*. + +.. versionchanged:: 15Sep2022 + +Keyword *spin/atom/random* randomizes the orientation of the magnetic +spin vectors for the selected atoms and sets the magnitude of each to +the specified *Dlen* value. This keyword does NOT allow use of an +atom-style variable. This keyword was previously called +*spin/random*. + +.. versionadded:: 15Sep2022 + +Keyword *spin/electron* sets the spin of an electron (+/- 1) or +indicates nuclei (=0), fixed-cores (=2), or pseudo-cores (= 3). + +Keyword *temperature* sets the temperature of a finite-size particle. +Currently, only the GRANULAR package supports this attribute. The +temperature must be added using an instance of :doc:`fix property/atom +` The values for the temperature must be positive. Keyword *theta* sets the orientation of selected atoms. The particles must be line segments as defined by the :doc:`atom_style line @@ -413,169 +574,71 @@ orientation angle of the line segments with respect to the x axis. Keyword *theta/random* randomizes the orientation of theta for the selected atoms. The particles must be line segments as defined by the -:doc:`atom_style line ` command. Random numbers are used in -such a way that the orientation of a particular atom is the same, +:doc:`atom_style line ` command. Random numbers are used +in such a way that the orientation of a particular atom is the same, regardless of how many processors are being used. This keyword does -not allow use of an atom-style variable. +NOT allow use of an atom-style variable. -Keyword *angmom* sets the angular momentum of selected atoms. The -particles must be ellipsoids as defined by the :doc:`atom_style -ellipsoid ` command or triangles as defined by the -:doc:`atom_style tri ` command. The angular momentum -vector of the particles is set to the 3 specified components. +Keyword *tri* sets the size of selected atoms. The particles must be +triangles as defined by the :doc:`atom_style tri ` +command. If the specified value is non-zero the triangle is (re)set +to be an equilateral triangle in the xy plane with side length = the +specified value, with a centroid at the particle position, with its +base parallel to the x axis, and the y-axis running from the center of +the base to the top point of the triangle. If the specified value is +0.0, the particle will become a point particle. Note that this +command does not adjust the particle mass, even if it was defined with +a density, e.g. via the :doc:`read_data ` command. -Keyword *omega* sets the angular velocity of selected atoms. The -particles must be spheres as defined by the :doc:`atom_style sphere -` command. The angular velocity vector of the particles is -set to the 3 specified components. +.. versionchanged:: 28Mar2023 -Keyword *mass* sets the mass of all selected particles. The particles -must have a per-atom mass attribute, as defined by the :doc:`atom_style -` command. See the "mass" command for how to set mass -values on a per-type basis. + Support for type labels was added for setting atom types -Keyword *density* or *density/disc* also sets the mass of all selected -particles, but in a different way. The particles must have a per-atom -mass attribute, as defined by the :doc:`atom_style ` -command. If the atom has a radius attribute (see :doc:`atom_style -sphere `) and its radius is non-zero, its mass is set from -the density and particle volume for 3d systems (the input density is -assumed to be in mass/distance\^3 units). For 2d, the default is for -LAMMPS to model particles with a radius attribute as spheres. However, -if the *density/disc* keyword is used, then they can be modeled as 2d -discs (circles). Their mass is set from the density and particle area -(the input density is assumed to be in mass/distance\^2 units). - -If the atom has a shape attribute (see :doc:`atom_style ellipsoid -`) and its 3 shape parameters are non-zero, then its mass is -set from the density and particle volume (the input density is assumed -to be in mass/distance\^3 units). The *density/disc* keyword has no -effect; it does not (yet) treat 3d ellipsoids as 2d ellipses. - -If the atom has a length attribute (see :doc:`atom_style line -`) and its length is non-zero, then its mass is set from the -density and line segment length (the input density is assumed to be in -mass/distance units). If the atom has an area attribute (see -:doc:`atom_style tri `) and its area is non-zero, then its -mass is set from the density and triangle area (the input density is -assumed to be in mass/distance\^2 units). - -If none of these cases are valid, then the mass is set to the density -value directly (the input density is assumed to be in mass units). - -Keyword *temperature* sets the temperature of a finite-size particle. -Currently, only the GRANULAR package supports this attribute. The -temperature must be added using an instance of -:doc:`fix property/atom ` The values for the -temperature must be positive. - -Keyword *volume* sets the volume of all selected particles. Currently, -only the :doc:`atom_style peri ` command defines particles -with a volume attribute. Note that this command does not adjust the -particle mass. - -Keyword *image* sets which image of the simulation box the atom is -considered to be in. An image of 0 means it is inside the box as -defined. A value of 2 means add 2 box lengths to get the true value. A -value of -1 means subtract 1 box length to get the true value. LAMMPS -updates these flags as atoms cross periodic boundaries during the -simulation. The flags can be output with atom snapshots via the -:doc:`dump ` command. If a value of NULL is specified for any of -nx,ny,nz, then the current image value for that dimension is unchanged. -For non-periodic dimensions only a value of 0 can be specified. This -command can be useful after a system has been equilibrated and atoms -have diffused one or more box lengths in various directions. This -command can then reset the image values for atoms so that they are -effectively inside the simulation box, e.g if a diffusion coefficient is -about to be measured via the :doc:`compute msd ` command. -Care should be taken not to reset the image flags of two atoms in a bond -to the same value if the bond straddles a periodic boundary (rather they -should be different by +/- 1). This will not affect the dynamics of a -simulation, but may mess up analysis of the trajectories if a LAMMPS -diagnostic or your own analysis relies on the image flags to unwrap a -molecule which straddles the periodic box. - -Keywords *bond*, *angle*, *dihedral*, and *improper*, set the bond -type (angle type, etc) of all bonds (angles, etc) of selected atoms to -the specified value. The value can be a numeric type from 1 to -nbondtypes (nangletypes, etc). Or it can be a type label (bond type -label, angle type label, etc). See the :doc:`Howto type labels +Keyword *type* sets the atom type for all selected atoms. A specified +value can be either a numeric atom type or an atom type label. When +using a numeric type, the specified value must be from 1 to ntypes, +where ntypes was set by the :doc:`create_box ` command or +the *atom types* field in the header of the data file read by the +:doc:`read_data ` command. When using a type label it must +have been defined previously. See the :doc:`Howto type labels ` doc page for the allowed syntax of type labels -and a general discussion of how type labels can be used. All atoms in -a particular bond (angle, etc) must be selected atoms in order for the -change to be made. The value of nbondtypes (nangletypes, etc) was set -by the *bond types* (\ *angle types*, etc) field in the header of the -data file read by the :doc:`read_data ` command. These -keywords do not allow use of an atom-style variable. +and a general discussion of how type labels can be used. -Keywords *rheo/rho* and *rheo/status* set the density and the status of -rheo particles. In particular, one can only set the phase in the status -as described by the :doc:`RHEO howto page `. +Keyword *type/fraction* sets the atom type for a fraction of the +selected atoms. The actual number of atoms changed is not guaranteed +to be exactly the specified fraction (0 <= *fraction* <= 1), but +should be statistically close. Random numbers are used in such a way +that a particular atom is changed or not changed, regardless of how +many processors are being used. This keyword does NOT allow use of an +atom-style variable. -Keywords *sph/e*, *sph/cv*, and *sph/rho* set the energy, heat capacity, -and density of smoothed particle hydrodynamics (SPH) particles. See -`this PDF guide `_ to using SPH in LAMMPS. +Keywords *type/ratio* and *type/subset* also set the atom type for a +fraction of the selected atoms. The actual number of atoms changed +will be exactly the requested number. For *type/ratio* the specified +fraction (0 <= *fraction* <= 1) determines the number. For +*type/subset*, the specified *Nsubset* is the number. An iterative +algorithm is used which ensures the correct number of atoms are +selected, in a perfectly random fashion. Which atoms are selected +will change with the number of processors used. These keywords do not +allow use of an atom-style variable. -.. note:: +Keyword *volume* sets the volume of all selected particles. +Currently, only the :doc:`atom_style peri ` command +defines particles with a volume attribute. Note that this command +does not adjust the particle mass. - Please note that the SPH PDF guide file has not been updated for - many years and thus does not reflect the current *syntax* of the - SPH package commands. For that please refer to the LAMMPS manual. +Keywords *vx*, *vy*, and *vz* set the velocities of all selected +atoms. -Keyword *smd/mass/density* sets the mass of all selected particles, but -it is only applicable to the Smooth Mach Dynamics package MACHDYN. It -assumes that the particle volume has already been correctly set and -calculates particle mass from the provided mass density value. - -Keyword *smd/contact/radius* only applies to simulations with the Smooth -Mach Dynamics package MACHDYN. Itsets an interaction radius for -computing short-range interactions, e.g. repulsive forces to prevent -different individual physical bodies from penetrating each other. Note -that the SPH smoothing kernel diameter used for computing long range, -nonlocal interactions, is set using the *diameter* keyword. - -Keyword *dpd/theta* sets the internal temperature of a DPD particle as -defined by the DPD-REACT package. If the specified value is a number it -must be >= 0.0. If the specified value is NULL, then the kinetic -temperature Tkin of each particle is computed as 3/2 k Tkin = KE = 1/2 m -v\^2 = 1/2 m (vx\*vx+vy\*vy+vz\*vz). Each particle's internal -temperature is set to Tkin. If the specified value is an atom-style -variable, then the variable is evaluated for each particle. If a value ->= 0.0, the internal temperature is set to that value. If it is < 0.0, -the computation of Tkin is performed and the internal temperature is set -to that value. - -Keywords *edpd/temp* and *edpd/cv* set the temperature and volumetric -heat capacity of an eDPD particle as defined by the DPD-MESO package. -Currently, only :doc:`atom_style edpd ` defines particles -with these attributes. The values for the temperature and heat capacity -must be positive. - -Keyword *cc* sets the chemical concentration of a tDPD particle for a -specified species as defined by the DPD-MESO package. Currently, only -:doc:`atom_style tdpd ` defines particles with this -attribute. An integer for "index" selects a chemical species (1 to -Nspecies) where Nspecies is set by the atom_style command. The value for -the chemical concentration must be >= 0.0. - -Keyword *epsilon* sets the dielectric constant of a particle, precisely -of the medium where the particle resides as defined by the DIELECTRIC -package. Currently, only :doc:`atom_style dielectric ` -defines particles with this attribute. The value for the dielectric -constant must be >= 0.0. Note that the set command with this keyword -will rescale the particle charge accordingly so that the real charge -(e.g., as read from a data file) stays intact. To change the real -charges, one needs to use the set command with the *charge* -keyword. Care must be taken to ensure that the real and scaled charges, -and dielectric constants are consistent. +Keywords *x*, *y*, *z* set the coordinates of all selected atoms. Keywords *i_name*, *d_name*, *i2_name*, *d2_name* refer to custom per-atom integer and floating-point vectors or arrays that have been added via the :doc:`fix property/atom ` command. When that command is used specific names are given to each attribute which are the "name" portion of these keywords. For arrays *i2_name* -and *d2_name*, the column of the array must also be included following -the name in brackets: e.g. d2_xyz[2], i2_mySpin[3]. +and *d2_name*, the column of the array to set must also be included +following the name in brackets: e.g. d2_xyz[2] or i2_mySpin[3]. Restrictions """""""""""" @@ -584,7 +647,7 @@ You cannot set an atom attribute (e.g. *mol* or *q* or *volume*\ ) if the :doc:`atom_style ` does not have that attribute. This command requires inter-processor communication to coordinate the -setting of bond types (angle types, etc). This means that your system +setting of bond types (angle types, etc). This means that the system must be ready to perform a simulation before using one of these keywords (force fields set, atom mass set, etc). This is not necessary for other keywords. @@ -599,7 +662,7 @@ Related commands """""""""""""""" :doc:`create_box `, :doc:`create_atoms `, -:doc:`read_data ` +:doc:`read_data `, :doc:`fix set ` Default """"""" diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 577d2c23de..668ad913ba 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -82,6 +82,7 @@ Alessandro Alexey ali aliceblue +aliphatic Allera Allinger allocatable @@ -103,6 +104,7 @@ Amit amsmath amu Amzallag +Anandakrishnan analytical Anders Andric @@ -110,6 +112,7 @@ Andrienko Andzelm Ang anglegrad +anglelist angleoffset angletangrad angmom @@ -347,6 +350,7 @@ Bomont BondAngle BondBond bondchk +bondlist bondmax bondscreened bondscreenedspin @@ -389,11 +393,13 @@ Bretonnet Briels Brien Brilliantov +Brizi Broadwell Broglie brownian brownw Broyden +Bruenger Bruskin Brusselle Bryantsev @@ -431,10 +437,12 @@ Camiloni Campana Cangi Cao +Cappelletti Capolungo Caro cartesian Cas +Casavecchia CasP Caswell Cates @@ -623,6 +631,7 @@ cp cpp cpu cradius +Cramer createatoms createAtoms CreateIDs @@ -663,6 +672,7 @@ cuFFT CuH Cui Cummins +cumulants Cundall cundall Curk @@ -816,6 +826,7 @@ diffusively diffusivities diffusivity dihedral +dihedrallist dihedrals Dihedrals dihydride @@ -1166,6 +1177,7 @@ Fermionic Ferrand fexternal Fexternal +ffast ffield ffl fflush @@ -1194,6 +1206,7 @@ filesystem filesystems Fily Fincham +Finkelstein Fint fingerprintconstants fingerprintsperelement @@ -1320,7 +1333,6 @@ Geocomputing georg Georg Geotechnica -Gergs germain Germann Germano @@ -1348,6 +1360,8 @@ Gillan Gingold Gissinger github +Giusti +GJ gjf gjwagne gl @@ -1606,6 +1620,7 @@ imagename imd Impey impl +improperlist impropers Impropers imulator @@ -1722,6 +1737,7 @@ Iyz iz izcm ized +Izadi Izrailev Izumi Izvekov @@ -1758,6 +1774,7 @@ jik JIK jku jN +Joanes Joannopoulos Jochim Jonsson @@ -1802,6 +1819,7 @@ Karniadakis Karplus Karttunen kate +katom Katsnelson Katsura Kaufmann @@ -1850,6 +1868,7 @@ Kloss Kloza kmax Kmax +kMC KMP kmu Knizhnik @@ -1914,6 +1933,7 @@ Lachet Lackmann Ladd lagrangian +Lalli lambdai LambdaLanczos Lambrecht @@ -1976,6 +1996,7 @@ lennard Lennard Lenosky Lenz +Leoni Lett Leuven Leven @@ -2177,6 +2198,7 @@ Materias mathbf mathjax matlab +Matom Matous matplotlib Matsubara @@ -2474,6 +2496,7 @@ namespaces nan NaN Nandor +nanglelist nangles Nangletype nangletypes @@ -2510,6 +2533,7 @@ nbodies nbody Nbody nbond +nbondlist nbonds nbondtype Nbondtype @@ -2531,6 +2555,7 @@ ncount nd ndactrung ndescriptors +ndihedrallist ndihedrals Ndihedraltype ndihedraltypes @@ -2588,6 +2613,7 @@ NiAlH Nicklas Niklasson Nikolskiy +nimproperlist nimpropers Nimpropertype nimpropertypes @@ -2682,6 +2708,7 @@ Nprocs npt nr Nr +Nrecent Nrecompute Nrepeat nreset @@ -2760,6 +2787,7 @@ ocl octahedral octants Odegard +Og Ohara O'Hearn ohenrich @@ -2792,6 +2820,7 @@ oneMKL oneway onlysalt ons +Onufriev OO Oord opencl @@ -2922,6 +2951,7 @@ perp Perram persp Persp +perturbative peru Peskin Pettifor @@ -2960,6 +2990,8 @@ pimdb Piola pIp pipelining +Pirani +pirani Pisarev Pishevar Pitera @@ -3337,6 +3369,7 @@ Rmin RMS rmsd rnage +rnflag rng rNEMD ro @@ -3346,6 +3379,7 @@ Rockett rocksalt Rodrigues Rohart +Roncaratti Ronchetti Ronevich Rosati @@ -3391,6 +3425,7 @@ ry Ryckaert Rycroft Rydbergs +Ryzen rz Rz Sabry @@ -3456,6 +3491,7 @@ sectoring sed Seddon segmental +Seibold Seifert Seleson sellerio @@ -3809,6 +3845,7 @@ Thiaville Thibaudeau Thijsse Thirumalai +Threadripper threebody thrid ThunderX @@ -4058,6 +4095,7 @@ vdW vdwl vec Vecchio +Vecchiocattivi vectorial vectorization Vectorization @@ -4074,9 +4112,11 @@ versa Verstraelen ves vf +vfull vflag vflow vfrac +vhalf vhi vibrational Vij @@ -4108,6 +4148,7 @@ volpress volumetric von Voro +voro Vorobyov voronoi Voronoi diff --git a/examples/COUPLE/plugin/CMakeLists.txt b/examples/COUPLE/plugin/CMakeLists.txt index 00f86058fb..4f7ab41847 100644 --- a/examples/COUPLE/plugin/CMakeLists.txt +++ b/examples/COUPLE/plugin/CMakeLists.txt @@ -27,10 +27,7 @@ if(MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() -find_package(MPI REQUIRED) -# do not include the (obsolete) MPI C++ bindings which makes -# for leaner object files and avoids namespace conflicts -set(MPI_CXX_SKIP_MPICXX TRUE) +find_package(MPI REQUIRED COMPONENTS C) ########################## diff --git a/examples/COUPLE/plugin/liblammpsplugin.c b/examples/COUPLE/plugin/liblammpsplugin.c index 87cf58729c..5003b3826b 100644 --- a/examples/COUPLE/plugin/liblammpsplugin.c +++ b/examples/COUPLE/plugin/liblammpsplugin.c @@ -144,6 +144,7 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib) ADDSYM(find_pair_neighlist); ADDSYM(find_fix_neighlist); ADDSYM(find_compute_neighlist); + ADDSYM(request_single_neighlist); ADDSYM(neighlist_num_elements); ADDSYM(neighlist_element_neighbors); diff --git a/examples/COUPLE/plugin/liblammpsplugin.h b/examples/COUPLE/plugin/liblammpsplugin.h index 3732b3a5c0..73cef7bc19 100644 --- a/examples/COUPLE/plugin/liblammpsplugin.h +++ b/examples/COUPLE/plugin/liblammpsplugin.h @@ -94,6 +94,17 @@ enum _LMP_VAR_CONST { LMP_VAR_STRING = 3 /*!< return value will be a string (catch-all) */ }; +/** Neighbor list settings constants + * + * Must be kept in sync with the equivalent constants in ``python/lammps/constants.py``, + * ``fortran/lammps.f90``, ``tools/swig/lammps.i``, and + * ``examples/COUPLE/plugin/liblammpsplugin.h`` */ + +enum _LMP_NEIGH_CONST { + LMP_NEIGH_HALF = 0, /*!< request (default) half neighbor list */ + LMP_NEIGH_FULL = 1, /*!< request full neighbor list */ +}; + #ifdef __cplusplus extern "C" { #endif @@ -189,14 +200,17 @@ struct _liblammpsplugin { * caller must match to how LAMMPS library is built */ #if !defined(LAMMPS_BIGBIG) - int (*create_atoms)(void *, int, int *, int *, double *, double *, int *, int); + int (*create_atoms)(void *, int, const int *, const int *, const double *, const double *, + const int *, int); #else - int (*create_atoms)(void *, int, int64_t *, int *, double *, double *, int64_t *, int); + int (*create_atoms)(void *, int, const int64_t *, const int *, const double *, const double *, + const int64_t *, int); #endif int (*find_pair_neighlist)(void *, const char *, int, int, int); int (*find_fix_neighlist)(void *, const char *, int); int (*find_compute_neighlist)(void *, const char *, int); + int (*request_single_neighlist)(void *, const char *, int, double); int (*neighlist_num_elements)(void *, int); void (*neighlist_element_neighbors)(void *, int, int, int *, int *, int **); diff --git a/examples/COUPLE/simple/CMakeLists.txt b/examples/COUPLE/simple/CMakeLists.txt index c09b372183..8396e5fb72 100644 --- a/examples/COUPLE/simple/CMakeLists.txt +++ b/examples/COUPLE/simple/CMakeLists.txt @@ -25,10 +25,10 @@ if(MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() -find_package(MPI QUIET) # do not include the (obsolete) MPI C++ bindings which makes # for leaner object files and avoids namespace conflicts set(MPI_CXX_SKIP_MPICXX TRUE) +find_package(MPI QUIET COMPONENTS C CXX) ########################## diff --git a/examples/PACKAGES/imd/in.bucky-plus-cnt b/examples/PACKAGES/imd/in.bucky-plus-cnt index b3eeff3cc1..af511fe11f 100644 --- a/examples/PACKAGES/imd/in.bucky-plus-cnt +++ b/examples/PACKAGES/imd/in.bucky-plus-cnt @@ -46,8 +46,8 @@ fix integrate mobile nve fix thermostat mobile langevin 300.0 300.0 2000.0 234624 # IMD setup. -fix comm all imd 6789 unwrap on trate 10 -#fix comm all imd 6789 unwrap on trate 10 nowait on +#fix comm all imd 6789 unwrap on trate 10 +fix comm all imd 6789 unwrap on trate 10 nowait on # temperature is based on mobile atoms only compute mobtemp mobile temp diff --git a/examples/PACKAGES/imd/in.bucky-plus-cnt-gpu b/examples/PACKAGES/imd/in.bucky-plus-cnt-gpu index 5762ec68c8..f3e4b32cdc 100644 --- a/examples/PACKAGES/imd/in.bucky-plus-cnt-gpu +++ b/examples/PACKAGES/imd/in.bucky-plus-cnt-gpu @@ -1,16 +1,20 @@ # stick a buckyball into a nanotube + +# enable GPU package from within the input: +package gpu 0 pair/only on +suffix gpu + units real dimension 3 boundary f f f atom_style molecular -newton off processors * * 1 # read topology read_data data.bucky-plus-cnt -pair_style lj/cut/gpu 10.0 +pair_style lj/cut 10.0 bond_style harmonic angle_style charmm dihedral_style charmm @@ -29,9 +33,6 @@ neigh_modify delay 0 every 1 check yes timestep 2.0 -# required for GPU acceleration -fix gpu all gpu force 0 0 1.0 - # we only move some atoms. group mobile type 1 @@ -49,8 +50,8 @@ fix integrate mobile nve fix thermostat mobile langevin 300.0 300.0 2000.0 234624 # IMD setup. -fix comm all imd 6789 unwrap on trate 10 -#fix comm all imd 6789 unwrap on trate 10 nowait on +#fix comm all imd 6789 unwrap on trate 10 +fix comm all imd 6789 unwrap on trate 10 nowait on # temperature is based on mobile atoms only compute mobtemp mobile temp diff --git a/examples/PACKAGES/imd/in.deca-ala_imd-gpu b/examples/PACKAGES/imd/in.deca-ala_imd-gpu index 72c3f4aae9..9470f7c213 100644 --- a/examples/PACKAGES/imd/in.deca-ala_imd-gpu +++ b/examples/PACKAGES/imd/in.deca-ala_imd-gpu @@ -1,8 +1,12 @@ -# +# + +# enable GPU package from within the input: +package gpu 0 pair/only on +suffix gpu + units real neighbor 2.5 bin neigh_modify delay 1 every 1 -newton off atom_style full bond_style harmonic @@ -10,20 +14,18 @@ angle_style charmm dihedral_style charmm improper_style harmonic -pair_style lj/charmm/coul/long/gpu 8 10 +pair_style lj/charmm/coul/long 8 10 pair_modify mix arithmetic special_bonds charmm read_data data.deca-ala-solv -fix 0 all gpu force/neigh 0 0 1.0 - group peptide id <= 103 fix rigidh all shake 1e-6 100 1000 t 1 2 3 4 5 a 23 thermo 100 thermo_style multi timestep 2.0 -kspace_style pppm/gpu 1e-5 +kspace_style pppm 1e-5 fix ensemble all npt temp 300.0 300.0 100.0 iso 1.0 1.0 1000.0 drag 0.2 diff --git a/examples/PACKAGES/imd/in.melt_imd-gpu b/examples/PACKAGES/imd/in.melt_imd-gpu index 24904eb832..f1406befa6 100644 --- a/examples/PACKAGES/imd/in.melt_imd-gpu +++ b/examples/PACKAGES/imd/in.melt_imd-gpu @@ -1,30 +1,32 @@ -# 3d Lennard-Jones melt +# 3d Lennard-Jones melt with GPU package acceleration -units lj -atom_style atomic -newton off +# enable GPU package from within the input: +package gpu 0 +suffix gpu -lattice fcc 0.8442 -region box block 0 10 0 10 0 10 -create_box 1 box -create_atoms 1 box -mass 1 1.0 +units lj +atom_style atomic -velocity all create 3.0 87287 +lattice fcc 0.8442 +region box block 0 10 0 10 0 10 +create_box 1 box +create_atoms 1 box +mass 1 1.0 -pair_style lj/cut/gpu 2.5 -pair_coeff 1 1 1.0 1.0 2.5 +velocity all create 3.0 87287 -neighbor 0.3 bin -neigh_modify every 5 delay 10 check yes +pair_style lj/cut 2.5 +pair_coeff 1 1 1.0 1.0 2.5 + +neighbor 0.3 bin +neigh_modify every 5 delay 10 check yes thermo_style custom step pe ke spcpu -fix 0 all gpu force/neigh 0 0 1.0 -fix 1 all nve +fix 1 all nve # IMD setup. fix comm all imd 5678 unwrap off fscale 20.0 trate 20 nowait on -thermo 500 -run 5000000 +thermo 500 +run 5000000 diff --git a/examples/PACKAGES/moments/in.converge b/examples/PACKAGES/moments/in.converge new file mode 100644 index 0000000000..4c77f249c2 --- /dev/null +++ b/examples/PACKAGES/moments/in.converge @@ -0,0 +1,35 @@ +# Detect convergence in a simulation using the relative change in +# moments. This demonstrates the "history" option. +# --------------------------------------------------------------------- + +# create pure copper system +units metal +lattice fcc 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box + +timestep 0.002 +create_atoms 1 box + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) + +# compute mean and stddev over the preceding 5000 steps, every 20 steps +variable toteng equal "etotal" +fix 2 all ave/moments 10 500 200 v_toteng mean stddev history 5 + +# Convergence criterion: stddev is smaller than threshold and was previously larger +# This avoids issues with system oscillations in the order of the averaging window +# that would otherwise lead to "nodes" in the stddev. +variable conv equal "(f_2[2] < 2.0) && (f_2[2][1] < f_2[2][5])" +fix 3 all halt 100 v_conv == 1 + +thermo_style custom step temp press etotal f_2[*][1] f_2[*][5] v_conv + +thermo 100 +run 10000 + diff --git a/examples/PACKAGES/moments/in.simple b/examples/PACKAGES/moments/in.simple new file mode 100644 index 0000000000..d82b8438c6 --- /dev/null +++ b/examples/PACKAGES/moments/in.simple @@ -0,0 +1,27 @@ +# Perform a simple simulation and output the moments of the total energy +# --------------------------------------------------------------------- + +# create pure copper system +units metal +lattice fcc 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box + +timestep 0.002 +create_atoms 1 box + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) + +variable toteng equal "etotal" +fix 2 all ave/moments 5 200 100 v_toteng mean stddev variance skew kurtosis + +thermo_style custom step temp press etotal f_2[*] + +thermo 100 +run 10000 + diff --git a/examples/PACKAGES/moments/in.valtest b/examples/PACKAGES/moments/in.valtest new file mode 100644 index 0000000000..214391909b --- /dev/null +++ b/examples/PACKAGES/moments/in.valtest @@ -0,0 +1,28 @@ +# Output raw and computed data. This can be used to perform the moment +# calculation in some external tool and validate our results +# --------------------------------------------------------------------- + +# create pure copper system +units metal +lattice fcc 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box + +timestep 0.002 +create_atoms 1 box + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) + +variable toteng equal "etotal" +fix 2 all ave/moments 1 10 10 v_toteng mean variance skew kurtosis + +thermo_style custom step etotal f_2[*] +thermo_modify format float %14.8f + +thermo 1 +run 100 diff --git a/examples/PACKAGES/moments/log.02May2025.converge.g++.1 b/examples/PACKAGES/moments/log.02May2025.converge.g++.1 new file mode 100644 index 0000000000..c6781927b2 --- /dev/null +++ b/examples/PACKAGES/moments/log.02May2025.converge.g++.1 @@ -0,0 +1,171 @@ +LAMMPS (2 Apr 2025 - Development - patch_4Feb2025-645-gba166d42e1-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# create pure copper system +units metal +lattice fcc 3.75 +Lattice spacing in x,y,z = 3.75 3.75 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box +Created orthogonal box = (0 0 0) to (22.5 22.5 22.5) + 1 by 1 by 1 MPI processor grid + +timestep 0.002 +create_atoms 1 box +Created 864 atoms + using lattice units in orthogonal box = (0 0 0) to (22.5 22.5 22.5) + create_atoms CPU = 0.001 seconds + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 0.2000000000000000111 + +variable toteng equal "etotal" +fix 2 all ave/moments 10 500 200 v_toteng mean stddev history 5 + +variable conv equal "(f_2[2] < 2) && (f_2[2][1] < f_2[2][5])" +fix 3 all halt 1000 v_conv == 1 + +thermo_style custom step temp press etotal f_2[*][1] f_2[*][5] v_conv + +thermo 100 +run 10000 +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 8.6825 + ghost atom cutoff = 8.6825 + binsize = 4.34125, bins = 6 6 6 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair eam/alloy, perpetual + attributes: half, newton on + pair build: half/bin/atomonly/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 3.484 | 3.484 | 3.484 Mbytes + Step Temp Press TotEng f_2[1][1] f_2[2][1] f_2[1][5] f_2[2][5] v_conv + 0 1000 -107410.22 -2884.9159 0 0 0 0 0 + 100 512.04214 -124.66263 -2928.6 0 0 0 0 0 + 200 479.34328 -136.26635 -2931.3905 -2928.6251 2.1584834 0 0 0 + 300 480.05298 128.92946 -2933.9233 -2928.6251 2.1584834 0 0 0 + 400 471.83641 -29.253334 -2936.8631 -2931.3742 3.3668783 0 0 0 + 500 456.96309 -274.69336 -2939.9081 -2931.3742 3.3668783 0 0 0 + 600 450.32413 14.606227 -2942.973 -2934.277 5.0681849 0 0 0 + 700 431.71192 -45.641261 -2946.006 -2934.277 5.0681849 0 0 0 + 800 436.4217 589.91981 -2948.8885 -2937.2386 6.823233 0 0 0 + 900 407.84688 -3728.1499 -2951.6643 -2937.2386 6.823233 0 0 0 + 1000 401.69178 6695.3653 -2954.2959 -2940.1463 8.4728269 -2928.6251 2.1584834 0 + 1100 370.87469 -2294.843 -2956.9413 -2940.1463 8.4728269 -2928.6251 2.1584834 0 + 1200 375.15562 704.6568 -2959.3841 -2942.9613 10.001542 -2931.3742 3.3668783 0 + 1300 371.09077 -493.04016 -2961.6803 -2942.9613 10.001542 -2931.3742 3.3668783 0 + 1400 365.88512 490.98174 -2963.8365 -2945.6475 11.378724 -2934.277 5.0681849 0 + 1500 358.42655 -218.94911 -2965.8652 -2945.6475 11.378724 -2934.277 5.0681849 0 + 1600 329.08402 56.411923 -2967.7662 -2948.1844 12.597017 -2937.2386 6.823233 0 + 1700 317.74207 1192.918 -2969.557 -2948.1844 12.597017 -2937.2386 6.823233 0 + 1800 331.98966 -2205.7213 -2971.1465 -2950.559 13.653575 -2940.1463 8.4728269 0 + 1900 330.96814 1401.3066 -2972.6923 -2950.559 13.653575 -2940.1463 8.4728269 0 + 2000 315.41816 -909.41909 -2974.0785 -2952.7764 14.568194 -2942.9613 10.001542 0 + 2100 320.4269 1226.2006 -2975.3676 -2952.7764 14.568194 -2942.9613 10.001542 0 + 2200 302.88235 -1238.8052 -2976.5099 -2954.8327 15.341787 -2945.6475 11.378724 0 + 2300 300.4349 2667.202 -2977.5329 -2954.8327 15.341787 -2945.6475 11.378724 0 + 2400 292.94691 -5532.1854 -2978.3724 -2956.7266 15.978754 -2948.1844 12.597017 0 + 2500 286.12064 4647.3841 -2979.2217 -2956.7266 15.978754 -2948.1844 12.597017 0 + 2600 290.74305 -1950.526 -2979.9142 -2958.4592 16.485773 -2950.559 13.653575 0 + 2700 281.51347 937.60472 -2980.4808 -2958.4592 16.485773 -2950.559 13.653575 0 + 2800 279.71836 -801.62498 -2980.8899 -2960.032 16.869365 -2952.7764 14.568194 0 + 2900 277.41241 609.21495 -2981.1721 -2960.032 16.869365 -2952.7764 14.568194 0 + 3000 281.31161 -760.27203 -2981.3003 -2961.4399 17.128547 -2954.8327 15.341787 0 + 3100 284.72904 315.53038 -2981.297 -2961.4399 17.128547 -2954.8327 15.341787 0 + 3200 278.39445 516.25074 -2981.1224 -2962.6768 17.263037 -2956.7266 15.978754 0 + 3300 294.46998 -655.06212 -2980.8266 -2962.6768 17.263037 -2956.7266 15.978754 0 + 3400 290.04647 788.30424 -2980.3963 -2963.7417 17.280979 -2958.4592 16.485773 0 + 3500 283.218 -844.33188 -2979.8504 -2963.7417 17.280979 -2958.4592 16.485773 0 + 3600 288.76031 1339.2734 -2979.2382 -2964.6345 17.192698 -2960.032 16.869365 0 + 3700 289.44519 -3015.7161 -2978.5394 -2964.6345 17.192698 -2960.032 16.869365 0 + 3800 309.04206 5579.3265 -2977.8282 -2965.3649 17.01845 -2961.4399 17.128547 0 + 3900 309.34588 -4255.5213 -2977.1281 -2965.3649 17.01845 -2961.4399 17.128547 0 + 4000 305.79444 2358.1383 -2976.5251 -2965.9537 16.784519 -2962.6768 17.263037 0 + 4100 309.12957 -1401.6484 -2975.9173 -2965.9537 16.784519 -2962.6768 17.263037 0 + 4200 309.41928 1180.4111 -2975.3857 -2966.4277 16.516135 -2963.7417 17.280979 0 + 4300 299.88949 -1549.6591 -2974.927 -2966.4277 16.516135 -2963.7417 17.280979 0 + 4400 319.09918 1937.7006 -2974.5598 -2966.8138 16.232551 -2964.6345 17.192698 0 + 4500 326.48719 -1489.2073 -2974.311 -2966.8138 16.232551 -2964.6345 17.192698 0 + 4600 310.93392 37.586899 -2974.1959 -2967.1394 15.948448 -2965.3649 17.01845 0 + 4700 314.28994 317.12347 -2974.1763 -2967.1394 15.948448 -2965.3649 17.01845 0 + 4800 309.88756 -698.72705 -2974.2892 -2967.4334 15.675606 -2965.9537 16.784519 0 + 4900 309.53444 962.42921 -2974.5261 -2967.4334 15.675606 -2965.9537 16.784519 0 + 5000 316.06666 -1869.3275 -2974.8492 -2967.7182 15.421633 -2966.4277 16.516135 0 + 5100 304.82485 4042.6797 -2975.2715 -2967.7182 15.421633 -2966.4277 16.516135 0 + 5200 307.75342 -5058.4814 -2975.7195 -2969.5853 13.236776 -2966.8138 16.232551 0 + 5300 298.83511 3096.4566 -2976.3329 -2969.5853 13.236776 -2966.8138 16.232551 0 + 5400 296.85413 -1929.1654 -2976.8797 -2971.2747 11.121537 -2967.1394 15.948448 0 + 5500 295.88343 1449.3005 -2977.4488 -2971.2747 11.121537 -2967.1394 15.948448 0 + 5600 305.59328 -1504.0321 -2977.9573 -2972.77 9.1579616 -2967.4334 15.675606 0 + 5700 293.40683 2579.0134 -2978.4364 -2972.77 9.1579616 -2967.4334 15.675606 0 + 5800 297.93644 -2742.705 -2978.8276 -2974.0625 7.4101102 -2967.7182 15.421633 0 + 5900 290.39408 1189.4042 -2979.2224 -2974.0625 7.4101102 -2967.7182 15.421633 0 + 6000 293.73148 -232.54292 -2979.503 -2975.1594 5.8959922 -2969.5853 13.236776 0 + 6100 292.04933 -168.30971 -2979.6898 -2975.1594 5.8959922 -2969.5853 13.236776 0 + 6200 299.23747 839.17828 -2979.7883 -2976.0647 4.6378408 -2971.2747 11.121537 0 + 6300 294.92201 -1597.9426 -2979.7975 -2976.0647 4.6378408 -2971.2747 11.121537 0 + 6400 291.7185 3411.2916 -2979.6978 -2976.7848 3.643826 -2972.77 9.1579616 0 + 6500 285.34227 -4280.7968 -2979.4874 -2976.7848 3.643826 -2972.77 9.1579616 0 + 6600 295.53838 2138.7496 -2979.2799 -2977.3265 2.9178925 -2974.0625 7.4101102 0 + 6700 288.54718 -1818.7662 -2978.9379 -2977.3265 2.9178925 -2974.0625 7.4101102 0 + 6800 290.41342 2175.3559 -2978.543 -2977.7009 2.4532223 -2975.1594 5.8959922 0 + 6900 296.34456 -4782.08 -2978.0362 -2977.7009 2.4532223 -2975.1594 5.8959922 0 + 7000 303.74314 5905.219 -2977.577 -2977.9137 2.2279716 -2976.0647 4.6378408 0 + 7100 303.90284 -3291.7627 -2977.1308 -2977.9137 2.2279716 -2976.0647 4.6378408 0 + 7200 296.13966 2209.574 -2976.7001 -2977.9829 2.1708943 -2976.7848 3.643826 0 + 7300 295.79694 -1609.1898 -2976.2816 -2977.9829 2.1708943 -2976.7848 3.643826 0 + 7400 306.53289 988.50902 -2975.8992 -2977.931 2.1935882 -2977.3265 2.9178925 0 + 7500 303.89992 -631.22838 -2975.5597 -2977.931 2.1935882 -2977.3265 2.9178925 0 + 7600 303.83684 -348.48744 -2975.3074 -2977.7831 2.2226664 -2977.7009 2.4532223 0 + 7700 309.67313 1350.9414 -2975.1279 -2977.7831 2.2226664 -2977.7009 2.4532223 0 + 7800 309.74314 -1182.8905 -2975.0174 -2977.5683 2.2106484 -2977.9137 2.2279716 0 + 7900 309.42429 999.08033 -2975.0089 -2977.5683 2.2106484 -2977.9137 2.2279716 0 + 8000 315.51872 -1337.8894 -2975.0791 -2977.3233 2.1379295 -2977.9829 2.1708943 0 + 8100 314.80533 2392.3424 -2975.25 -2977.3233 2.1379295 -2977.9829 2.1708943 0 + 8200 303.80236 -3224.5976 -2975.4744 -2977.0851 2.0176342 -2977.931 2.1935882 0 + 8300 295.0505 3296.6912 -2975.8196 -2977.0851 2.0176342 -2977.931 2.1935882 0 + 8400 302.4154 -3314.5096 -2976.1586 -2976.8877 1.883051 -2977.7831 2.2226664 1 + 8500 300.95491 2971.1291 -2976.5859 -2976.8877 1.883051 -2977.7831 2.2226664 1 + 8600 301.68919 -2297.6673 -2976.9953 -2976.7596 1.785401 -2977.5683 2.2106484 1 + 8700 291.21002 1477.5703 -2977.4323 -2976.7596 1.785401 -2977.5683 2.2106484 1 + 8800 305.87126 -1085.459 -2977.8247 -2976.7169 1.7541517 -2977.3233 2.1379295 1 + 8900 296.17567 777.95805 -2978.2081 -2976.7169 1.7541517 -2977.3233 2.1379295 1 +Fix halt condition for fix-id 3 met on step 9000 with value 1 (src/fix_halt.cpp:310) + 9000 295.71917 -425.00708 -2978.5264 -2976.7595 1.7755885 -2977.0851 2.0176342 1 +Loop time of 42.1758 on 1 procs for 9000 steps with 864 atoms + +Performance: 36.874 ns/day, 0.651 hours/ns, 213.393 timesteps/s, 184.371 katom-step/s +99.9% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 41.126 | 41.126 | 41.126 | 0.0 | 97.51 +Neigh | 0.0078787 | 0.0078787 | 0.0078787 | 0.0 | 0.02 +Comm | 0.26508 | 0.26508 | 0.26508 | 0.0 | 0.63 +Output | 0.0096224 | 0.0096224 | 0.0096224 | 0.0 | 0.02 +Modify | 0.65597 | 0.65597 | 0.65597 | 0.0 | 1.56 +Other | | 0.1108 | | | 0.26 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 3767 ave 3767 max 3767 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 96746 ave 96746 max 96746 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 96746 +Ave neighs/atom = 111.97454 +Neighbor list builds = 1 +Dangerous builds = 0 + +Total wall time: 0:00:42 diff --git a/examples/PACKAGES/moments/log.02May2025.converge.g++.4 b/examples/PACKAGES/moments/log.02May2025.converge.g++.4 new file mode 100644 index 0000000000..172f14d4f4 --- /dev/null +++ b/examples/PACKAGES/moments/log.02May2025.converge.g++.4 @@ -0,0 +1,171 @@ +LAMMPS (2 Apr 2025 - Development - patch_4Feb2025-645-gba166d42e1-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# create pure copper system +units metal +lattice fcc 3.75 +Lattice spacing in x,y,z = 3.75 3.75 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box +Created orthogonal box = (0 0 0) to (22.5 22.5 22.5) + 1 by 2 by 2 MPI processor grid + +timestep 0.002 +create_atoms 1 box +Created 864 atoms + using lattice units in orthogonal box = (0 0 0) to (22.5 22.5 22.5) + create_atoms CPU = 0.001 seconds + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 0.2000000000000000111 + +variable toteng equal "etotal" +fix 2 all ave/moments 10 500 200 v_toteng mean stddev history 5 + +variable conv equal "(f_2[2] < 2) && (f_2[2][1] < f_2[2][5])" +fix 3 all halt 1000 v_conv == 1 + +thermo_style custom step temp press etotal f_2[*][1] f_2[*][5] v_conv + +thermo 100 +run 10000 +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 8.6825 + ghost atom cutoff = 8.6825 + binsize = 4.34125, bins = 6 6 6 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair eam/alloy, perpetual + attributes: half, newton on + pair build: half/bin/atomonly/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 3.42 | 3.42 | 3.42 Mbytes + Step Temp Press TotEng f_2[1][1] f_2[2][1] f_2[1][5] f_2[2][5] v_conv + 0 1000 -107410.22 -2884.9159 0 0 0 0 0 + 100 492.38014 -134.33622 -2928.6874 0 0 0 0 0 + 200 484.82396 -214.26318 -2931.4603 -2928.6979 2.1805063 0 0 0 + 300 476.69743 15.78678 -2934.0022 -2928.6979 2.1805063 0 0 0 + 400 482.51415 141.67184 -2936.9347 -2931.4437 3.3715811 0 0 0 + 500 455.45411 2.4424602 -2939.9649 -2931.4437 3.3715811 0 0 0 + 600 455.20054 -6.8170934 -2943.0454 -2934.339 5.0598781 0 0 0 + 700 429.81168 -75.812923 -2946.0438 -2934.339 5.0598781 0 0 0 + 800 428.22097 604.18705 -2948.9285 -2937.2965 6.813037 0 0 0 + 900 399.10914 -3622.6904 -2951.7252 -2937.2965 6.813037 0 0 0 + 1000 394.62543 7905.9041 -2954.2925 -2940.2044 8.4668749 -2928.6979 2.1805063 0 + 1100 404.27007 -2565.5508 -2956.9736 -2940.2044 8.4668749 -2928.6979 2.1805063 0 + 1200 368.47178 741.43707 -2959.4264 -2943.0151 9.9914785 -2931.4437 3.3715811 0 + 1300 360.91266 -267.08372 -2961.69 -2943.0151 9.9914785 -2931.4437 3.3715811 0 + 1400 356.74405 158.09093 -2963.8501 -2945.696 11.36357 -2934.339 5.0598781 0 + 1500 335.45696 -71.007783 -2965.8817 -2945.696 11.36357 -2934.339 5.0598781 0 + 1600 331.01199 -454.90004 -2967.7708 -2948.2278 12.577884 -2937.2965 6.813037 0 + 1700 329.223 2428.4284 -2969.5452 -2948.2278 12.577884 -2937.2965 6.813037 0 + 1800 327.61481 -4757.648 -2971.1105 -2950.5985 13.632251 -2940.2044 8.4668749 0 + 1900 318.18741 2226.7765 -2972.6906 -2950.5985 13.632251 -2940.2044 8.4668749 0 + 2000 308.79313 -1089.8603 -2974.0899 -2952.8123 14.545164 -2943.0151 9.9914785 0 + 2100 303.32047 757.53534 -2975.3597 -2952.8123 14.545164 -2943.0151 9.9914785 0 + 2200 307.41102 -837.97246 -2976.4966 -2954.8654 15.317558 -2945.696 11.36357 0 + 2300 303.01088 1618.29 -2977.5454 -2954.8654 15.317558 -2945.696 11.36357 0 + 2400 297.59385 -3233.8282 -2978.4064 -2956.7565 15.953758 -2948.2278 12.577884 0 + 2500 288.72232 5209.2099 -2979.1999 -2956.7565 15.953758 -2948.2278 12.577884 0 + 2600 298.92201 -2193.618 -2979.8873 -2958.4845 16.457635 -2950.5985 13.632251 0 + 2700 282.61818 765.88178 -2980.4563 -2958.4845 16.457635 -2950.5985 13.632251 0 + 2800 273.63104 -389.49749 -2980.8636 -2960.0533 16.839029 -2952.8123 14.545164 0 + 2900 274.12166 -9.2552992 -2981.1421 -2960.0533 16.839029 -2952.8123 14.545164 0 + 3000 279.43592 212.25445 -2981.2716 -2961.4578 17.096628 -2954.8654 15.317558 0 + 3100 291.10071 -1139.205 -2981.2475 -2961.4578 17.096628 -2954.8654 15.317558 0 + 3200 281.53171 3124.6411 -2981.0818 -2962.6921 17.230604 -2956.7565 15.953758 0 + 3300 277.0223 -2795.9494 -2980.7825 -2962.6921 17.230604 -2956.7565 15.953758 0 + 3400 284.8443 1587.8876 -2980.3701 -2963.754 17.247489 -2958.4845 16.457635 0 + 3500 281.19 -1143.0785 -2979.8374 -2963.754 17.247489 -2958.4845 16.457635 0 + 3600 296.58287 1156.4706 -2979.2182 -2964.645 17.159411 -2960.0533 16.839029 0 + 3700 297.24517 -1888.4993 -2978.5352 -2964.645 17.159411 -2960.0533 16.839029 0 + 3800 290.81586 3843.3483 -2977.8509 -2965.3746 16.985916 -2961.4578 17.096628 0 + 3900 300.39456 -5584.8386 -2977.0837 -2965.3746 16.985916 -2961.4578 17.096628 0 + 4000 306.15811 3310.0105 -2976.5086 -2965.9619 16.752214 -2962.6921 17.230604 0 + 4100 295.907 -1475.0458 -2975.9096 -2965.9619 16.752214 -2962.6921 17.230604 0 + 4200 322.70162 933.76586 -2975.3867 -2966.4348 16.484219 -2963.754 17.247489 0 + 4300 306.69631 -512.7048 -2974.9324 -2966.4348 16.484219 -2963.754 17.247489 0 + 4400 309.23776 226.77219 -2974.5791 -2966.8208 16.201471 -2964.645 17.159411 0 + 4500 313.15783 508.29785 -2974.3263 -2966.8208 16.201471 -2964.645 17.159411 0 + 4600 316.26151 -2043.7571 -2974.1697 -2967.1463 15.918137 -2965.3746 16.985916 0 + 4700 312.27329 1831.682 -2974.1732 -2967.1463 15.918137 -2965.3746 16.985916 0 + 4800 307.61066 -1476.0019 -2974.2885 -2967.4397 15.645834 -2965.9619 16.752214 0 + 4900 305.73489 1303.4848 -2974.5506 -2967.4397 15.645834 -2965.9619 16.752214 0 + 5000 309.3774 -1574.6812 -2974.8687 -2967.7249 15.392787 -2966.4348 16.484219 0 + 5100 304.8602 2679.7476 -2975.3082 -2967.7249 15.392787 -2966.4348 16.484219 0 + 5200 297.54226 -5008.0905 -2975.7443 -2969.5904 13.211657 -2966.8208 16.201471 0 + 5300 306.18872 4840.4175 -2976.324 -2969.5904 13.211657 -2966.8208 16.201471 0 + 5400 299.57661 -2513.1706 -2976.8842 -2971.2774 11.099846 -2967.1463 15.918137 0 + 5500 302.30844 1301.3525 -2977.4539 -2971.2774 11.099846 -2967.1463 15.918137 0 + 5600 302.11038 -760.79712 -2977.9764 -2972.7712 9.1381778 -2967.4397 15.645834 0 + 5700 294.49825 718.67318 -2978.4584 -2972.7712 9.1381778 -2967.4397 15.645834 0 + 5800 305.97636 -478.64224 -2978.8638 -2974.0628 7.3929182 -2967.7249 15.392787 0 + 5900 291.93868 -419.74179 -2979.2292 -2974.0628 7.3929182 -2967.7249 15.392787 0 + 6000 289.50667 859.85085 -2979.5018 -2975.1575 5.8837236 -2969.5904 13.211657 0 + 6100 305.70118 -933.35917 -2979.6877 -2975.1575 5.8837236 -2969.5904 13.211657 0 + 6200 284.37805 1526.0707 -2979.806 -2976.062 4.6281363 -2971.2774 11.099846 0 + 6300 291.08863 -2156.6708 -2979.8064 -2976.062 4.6281363 -2971.2774 11.099846 0 + 6400 295.99073 2819.8245 -2979.7378 -2976.7827 3.6358684 -2972.7712 9.1381778 0 + 6500 298.06769 -3396.3504 -2979.5428 -2976.7827 3.6358684 -2972.7712 9.1381778 0 + 6600 301.78514 5496.6525 -2979.2768 -2977.3261 2.9112079 -2974.0628 7.3929182 0 + 6700 290.80665 -5229.4989 -2978.9177 -2977.3261 2.9112079 -2974.0628 7.3929182 0 + 6800 296.75761 2401.7807 -2978.5996 -2977.7014 2.4473856 -2975.1575 5.8837236 0 + 6900 295.77553 -1521.6269 -2978.1619 -2977.7014 2.4473856 -2975.1575 5.8837236 0 + 7000 303.59015 1530.7255 -2977.7097 -2977.9176 2.2219164 -2976.062 4.6281363 0 + 7100 297.51038 -3016.4426 -2977.2025 -2977.9176 2.2219164 -2976.062 4.6281363 0 + 7200 293.53789 2705.9808 -2976.7651 -2977.9894 2.1638143 -2976.7827 3.6358684 0 + 7300 301.78809 -1042.1076 -2976.3388 -2977.9894 2.1638143 -2976.7827 3.6358684 0 + 7400 307.50053 214.56923 -2975.9581 -2977.9394 2.1852009 -2977.3261 2.9112079 0 + 7500 301.98985 281.86495 -2975.6146 -2977.9394 2.1852009 -2977.3261 2.9112079 0 + 7600 318.37347 -1145.7795 -2975.3473 -2977.7949 2.2136707 -2977.7014 2.4473856 0 + 7700 314.94512 4536.9887 -2975.1351 -2977.7949 2.2136707 -2977.7014 2.4473856 0 + 7800 312.91485 -2980.6408 -2975.0156 -2977.5818 2.2038198 -2977.9176 2.2219164 0 + 7900 310.06854 2244.3877 -2975.0094 -2977.5818 2.2038198 -2977.9176 2.2219164 0 + 8000 308.55007 -2427.1464 -2975.0491 -2977.3378 2.1348358 -2977.9894 2.1638143 0 + 8100 323.02796 3187.4728 -2975.2081 -2977.3378 2.1348358 -2977.9894 2.1638143 0 + 8200 327.05029 -6447.7875 -2975.3162 -2977.0986 2.0196599 -2977.9394 2.1852009 0 + 8300 311.194 4273.1174 -2975.7217 -2977.0986 2.0196599 -2977.9394 2.1852009 0 + 8400 290.61931 -2301.019 -2976.0963 -2976.8989 1.8918948 -2977.7949 2.2136707 1 + 8500 314.00559 1966.1297 -2976.5206 -2976.8989 1.8918948 -2977.7949 2.2136707 1 + 8600 288.26541 -1608.4524 -2976.9304 -2976.7685 1.7971228 -2977.5818 2.2038198 1 + 8700 298.92083 1353.9988 -2977.355 -2976.7685 1.7971228 -2977.5818 2.2038198 1 + 8800 299.97274 -638.68301 -2977.766 -2976.722 1.7650747 -2977.3378 2.1348358 1 + 8900 300.66443 -279.62514 -2978.1476 -2976.722 1.7650747 -2977.3378 2.1348358 1 +Fix halt condition for fix-id 3 met on step 9000 with value 1 (src/fix_halt.cpp:310) + 9000 290.44715 489.06352 -2978.4892 -2976.7631 1.7846181 -2977.0986 2.0196599 1 +Loop time of 14.7347 on 4 procs for 9000 steps with 864 atoms + +Performance: 105.547 ns/day, 0.227 hours/ns, 610.804 timesteps/s, 527.735 katom-step/s +92.8% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 10.565 | 11.474 | 12.015 | 16.1 | 77.87 +Neigh | 0.0020313 | 0.0020966 | 0.002163 | 0.1 | 0.01 +Comm | 2.008 | 2.5374 | 3.4278 | 33.5 | 17.22 +Output | 0.0030284 | 0.0036299 | 0.0051776 | 1.5 | 0.02 +Modify | 0.42442 | 0.43307 | 0.44329 | 1.0 | 2.94 +Other | | 0.2849 | | | 1.93 + +Nlocal: 216 ave 224 max 204 min +Histogram: 1 0 0 0 0 0 0 2 0 1 +Nghost: 2147 ave 2159 max 2139 min +Histogram: 1 0 0 2 0 0 0 0 0 1 +Neighs: 24185.8 ave 26045 max 21309 min +Histogram: 1 0 0 0 0 1 0 0 0 2 + +Total # of neighbors = 96743 +Ave neighs/atom = 111.97106 +Neighbor list builds = 1 +Dangerous builds = 0 + +Total wall time: 0:00:14 diff --git a/examples/PACKAGES/moments/log.02May2025.simple.g++.1 b/examples/PACKAGES/moments/log.02May2025.simple.g++.1 new file mode 100644 index 0000000000..3a2fe80beb --- /dev/null +++ b/examples/PACKAGES/moments/log.02May2025.simple.g++.1 @@ -0,0 +1,177 @@ +LAMMPS (2 Apr 2025 - Development - patch_4Feb2025-645-gba166d42e1-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# create pure copper system +units metal +lattice fcc 3.75 +Lattice spacing in x,y,z = 3.75 3.75 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box +Created orthogonal box = (0 0 0) to (22.5 22.5 22.5) + 1 by 1 by 1 MPI processor grid + +timestep 0.002 +create_atoms 1 box +Created 864 atoms + using lattice units in orthogonal box = (0 0 0) to (22.5 22.5 22.5) + create_atoms CPU = 0.001 seconds + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 0.2000000000000000111 + +variable toteng equal "etotal" +fix 2 all ave/moments 5 200 100 v_toteng mean stddev variance skew kurtosis + +thermo_style custom step temp press etotal f_2[*] + +thermo 100 +run 10000 +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 8.6825 + ghost atom cutoff = 8.6825 + binsize = 4.34125, bins = 6 6 6 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair eam/alloy, perpetual + attributes: half, newton on + pair build: half/bin/atomonly/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 3.484 | 3.484 | 3.484 Mbytes + Step Temp Press TotEng f_2[1] f_2[2] f_2[3] f_2[4] f_2[5] + 0 1000 -107410.22 -2884.9159 0 0 0 0 0 + 100 512.04214 -124.66263 -2928.6 -2927.1688 1.6797138 2.8214386 2.5218138 6.164012 + 200 479.34328 -136.26635 -2931.3905 -2928.6374 1.9791406 3.9169976 1.3377745 3.2426285 + 300 480.05298 128.92946 -2933.9233 -2929.9825 2.5401119 6.4521682 0.66415393 0.77130236 + 400 471.83641 -29.253334 -2936.8631 -2931.346 3.2640831 10.654239 0.29075579 -0.26904542 + 500 456.96309 -274.69336 -2939.9081 -2932.7721 4.1077082 16.873267 0.094954709 -0.72240572 + 600 450.32413 14.606227 -2942.973 -2934.2328 4.9928765 24.928816 0.0090731063 -0.93757177 + 700 431.71192 -45.641261 -2946.006 -2935.7111 5.8871117 34.658084 -0.024573652 -1.0540107 + 800 436.4217 589.91981 -2948.8885 -2937.1871 6.762411 45.730202 -0.028553126 -1.1275153 + 900 407.84688 -3728.1499 -2951.6643 -2938.652 7.6129868 57.957569 -0.020186137 -1.172618 + 1000 401.69178 6695.3653 -2954.2959 -2940.0921 8.423174 70.949861 -0.0018224075 -1.2051609 + 1100 370.87469 -2294.843 -2956.9413 -2942.9469 8.384346 70.297257 0.016964628 -1.2643199 + 1200 375.15562 704.6568 -2959.3841 -2945.7589 8.3201293 69.224551 0.070500644 -1.2400262 + 1300 371.09077 -493.04016 -2961.6803 -2948.5516 8.1425118 66.300499 0.11183042 -1.2099873 + 1400 365.88512 490.98174 -2963.8365 -2951.2897 7.8673969 61.895934 0.13639588 -1.198071 + 1500 358.42655 -218.94911 -2965.8652 -2953.9337 7.5491659 56.989906 0.15564307 -1.1896984 + 1600 329.08402 56.411923 -2967.7662 -2956.467 7.2016413 51.863637 0.17198437 -1.186472 + 1700 317.74207 1192.918 -2969.557 -2958.8765 6.8379658 46.757776 0.19041811 -1.1812241 + 1800 331.98966 -2205.7213 -2971.1465 -2961.1601 6.4614065 41.749774 0.20925197 -1.1714131 + 1900 330.96814 1401.3066 -2972.6923 -2963.3191 6.0867317 37.048302 0.22552163 -1.1523125 + 2000 315.41816 -909.41909 -2974.0785 -2965.3567 5.7020261 32.513101 0.2328316 -1.1454375 + 2100 320.4269 1226.2006 -2975.3676 -2967.2609 5.3260556 28.366869 0.24130517 -1.1432352 + 2200 302.88235 -1238.8052 -2976.5099 -2969.0355 4.9584282 24.58601 0.25200271 -1.141699 + 2300 300.4349 2667.202 -2977.5329 -2970.6815 4.5986371 21.147463 0.26764984 -1.1380521 + 2400 292.94691 -5532.1854 -2978.3724 -2972.201 4.2403749 17.980779 0.28797864 -1.1357902 + 2500 286.12064 4647.3841 -2979.2217 -2973.5946 3.8875889 15.113348 0.31556585 -1.1249025 + 2600 290.74305 -1950.526 -2979.9142 -2974.8686 3.5422986 12.547879 0.34719546 -1.0987558 + 2700 281.51347 937.60472 -2980.4808 -2976.0235 3.1955646 10.211633 0.38268676 -1.0664838 + 2800 279.71836 -801.62498 -2980.8899 -2977.0588 2.844105 8.0889331 0.41930147 -1.0460672 + 2900 277.41241 609.21495 -2981.1721 -2977.9673 2.4956133 6.2280855 0.47337432 -1.0140054 + 3000 281.31161 -760.27203 -2981.3003 -2978.7489 2.1466012 4.6078967 0.55325134 -0.95161956 + 3100 284.72904 315.53038 -2981.297 -2979.4023 1.7929581 3.2146986 0.66481771 -0.84726207 + 3200 278.39445 516.25074 -2981.1224 -2979.9226 1.4369984 2.0649644 0.82583409 -0.63830994 + 3300 294.46998 -655.06212 -2980.8266 -2980.3134 1.0905211 1.1892364 1.0357766 -0.22841943 + 3400 290.04647 788.30424 -2980.3963 -2980.5732 0.77030961 0.59337689 1.1867647 0.34447355 + 3500 283.218 -844.33188 -2979.8504 -2980.6995 0.54590076 0.29800764 0.78163948 -0.42619888 + 3600 288.76031 1339.2734 -2979.2382 -2980.6921 0.56032295 0.31396181 0.83603869 -0.30853278 + 3700 289.44519 -3015.7161 -2978.5394 -2980.5581 0.77708069 0.60385439 1.0796997 -0.022962365 + 3800 309.04206 5579.3265 -2977.8282 -2980.3052 1.0531468 1.1091181 0.890018 -0.56034495 + 3900 309.34588 -4255.5213 -2977.1281 -2979.9487 1.3153981 1.7302721 0.65242676 -0.95498589 + 4000 305.79444 2358.1383 -2976.5251 -2979.5068 1.5325477 2.3487025 0.44420123 -1.1839975 + 4100 309.12957 -1401.6484 -2975.9173 -2978.9985 1.6923829 2.86416 0.26850538 -1.3006942 + 4200 309.41928 1180.4111 -2975.3857 -2978.4446 1.7941259 3.2188877 0.11443933 -1.3365167 + 4300 299.88949 -1549.6591 -2974.927 -2977.8616 1.8268192 3.3372683 -0.018659059 -1.3293426 + 4400 319.09918 1937.7006 -2974.5598 -2977.273 1.7942266 3.219249 -0.13743367 -1.2958767 + 4500 326.48719 -1489.2073 -2974.311 -2976.7017 1.7042328 2.9044096 -0.25309558 -1.2385503 + 4600 310.93392 37.586899 -2974.1959 -2976.1697 1.5590672 2.4306905 -0.3757949 -1.1641151 + 4700 314.28994 317.12347 -2974.1763 -2975.6978 1.3661244 1.8662958 -0.51792367 -1.0609001 + 4800 309.88756 -698.72705 -2974.2892 -2975.3021 1.1422822 1.3048085 -0.69587053 -0.87319738 + 4900 309.53444 962.42921 -2974.5261 -2974.9944 0.89961859 0.80931361 -0.91892105 -0.49661907 + 5000 316.06666 -1869.3275 -2974.8492 -2974.7804 0.65817496 0.43319428 -1.0974595 0.048447651 + 5100 304.82485 4042.6797 -2975.2715 -2974.6661 0.47073268 0.22158926 -0.82059377 -0.31531887 + 5200 307.75342 -5058.4814 -2975.7195 -2974.6547 0.44733518 0.20010876 -0.68956594 -0.65171579 + 5300 298.83511 3096.4566 -2976.3329 -2974.7467 0.60599527 0.36723026 -1.0652601 0.032591262 + 5400 296.85413 -1929.1654 -2976.8797 -2974.9367 0.82832935 0.68612952 -0.91576774 -0.50322222 + 5500 295.88343 1449.3005 -2977.4488 -2975.215 1.044317 1.090598 -0.67574925 -0.92510515 + 5600 305.59328 -1504.0321 -2977.9573 -2975.5653 1.2243609 1.4990595 -0.46160433 -1.1708115 + 5700 293.40683 2579.0134 -2978.4364 -2975.97 1.3577316 1.843435 -0.27746111 -1.2993802 + 5800 297.93644 -2742.705 -2978.8276 -2976.411 1.4332742 2.054275 -0.11245859 -1.3584974 + 5900 290.39408 1189.4042 -2979.2224 -2976.8733 1.4576633 2.1247823 0.030209056 -1.3466833 + 6000 293.73148 -232.54292 -2979.503 -2977.3408 1.4300816 2.0451335 0.15663025 -1.2965878 + 6100 292.04933 -168.30971 -2979.6898 -2977.7936 1.3523929 1.8289665 0.28027258 -1.2214523 + 6200 299.23747 839.17828 -2979.7883 -2978.2154 1.2284868 1.5091798 0.40149929 -1.1382373 + 6300 294.92201 -1597.9426 -2979.7975 -2978.589 1.072002 1.1491883 0.53769821 -1.0262094 + 6400 291.7185 3411.2916 -2979.6978 -2978.9013 0.89165749 0.79505308 0.70748196 -0.83601078 + 6500 285.34227 -4280.7968 -2979.4874 -2979.1407 0.69727552 0.48619315 0.91500724 -0.4890805 + 6600 295.53838 2138.7496 -2979.2799 -2979.3084 0.50938648 0.25947459 1.0827149 -0.0043801382 + 6700 288.54718 -1818.7662 -2978.9379 -2979.3979 0.3658125 0.13381879 0.85573626 -0.20104653 + 6800 290.41342 2175.3559 -2978.543 -2979.4085 0.34439248 0.11860618 0.70989241 -0.55138716 + 6900 296.34456 -4782.08 -2978.0362 -2979.3362 0.47081063 0.22166265 1.1051059 0.16381282 + 7000 303.74314 5905.219 -2977.577 -2979.182 0.65635739 0.43080502 0.97456755 -0.34269231 + 7100 303.90284 -3291.7627 -2977.1308 -2978.9595 0.83412944 0.69577192 0.71973637 -0.85687335 + 7200 296.13966 2209.574 -2976.7001 -2978.6767 0.98885368 0.97783159 0.50554418 -1.124705 + 7300 295.79694 -1609.1898 -2976.2816 -2978.3446 1.1093729 1.2307082 0.32952142 -1.2657581 + 7400 306.53289 988.50902 -2975.8992 -2977.977 1.1910167 1.4185209 0.17936365 -1.331845 + 7500 303.89992 -631.22838 -2975.5597 -2977.5901 1.2352698 1.5258915 0.033110856 -1.3362459 + 7600 303.83684 -348.48744 -2975.3074 -2977.1915 1.2312686 1.5160224 -0.094817417 -1.3063491 + 7700 309.67313 1350.9414 -2975.1279 -2976.7984 1.1829266 1.3993154 -0.21343083 -1.2573517 + 7800 309.74314 -1182.8905 -2975.0174 -2976.4294 1.0913021 1.1909402 -0.3401118 -1.198459 + 7900 309.42429 999.08033 -2975.0089 -2976.0995 0.96393318 0.92916717 -0.48456322 -1.1149956 + 8000 315.51872 -1337.8894 -2975.0791 -2975.822 0.81535467 0.66480324 -0.67906685 -0.90499956 + 8100 314.80533 2392.3424 -2975.25 -2975.6019 0.64582022 0.41708376 -0.90521871 -0.5328796 + 8200 303.80236 -3224.5976 -2975.4744 -2975.4481 0.47449379 0.22514436 -1.0884377 -0.00018150871 + 8300 295.0505 3296.6912 -2975.8196 -2975.3667 0.34164698 0.11672266 -0.83269043 -0.31809119 + 8400 302.4154 -3314.5096 -2976.1586 -2975.3606 0.32904826 0.10827276 -0.73500255 -0.57861735 + 8500 300.95491 2971.1291 -2976.5859 -2975.4288 0.44584452 0.19877734 -1.0760301 0.014924509 + 8600 301.68919 -2297.6673 -2976.9953 -2975.5682 0.60852433 0.37030186 -0.91802963 -0.5143582 + 8700 291.21002 1477.5703 -2977.4323 -2975.7733 0.76843347 0.59048999 -0.68059043 -0.92051715 + 8800 305.87126 -1085.459 -2977.8247 -2976.0327 0.90672273 0.82214612 -0.47413162 -1.1492716 + 8900 296.17567 777.95805 -2978.2081 -2976.3349 1.0129061 1.0259789 -0.29734681 -1.271416 + 9000 295.71917 -425.00708 -2978.5264 -2976.6672 1.0786137 1.1634075 -0.14055755 -1.3302079 + 9100 296.85578 -533.46289 -2978.8197 -2977.0152 1.1000855 1.2101882 0.0045950751 -1.3434868 + 9200 293.949 605.27065 -2979.0349 -2977.3702 1.0854405 1.1781811 0.123965 -1.3093197 + 9300 289.11704 -896.44753 -2979.1981 -2977.7166 1.0353526 1.071955 0.23898813 -1.2558296 + 9400 285.34521 1181.7542 -2979.2879 -2978.0404 0.95298596 0.90818224 0.36461645 -1.1736585 + 9500 296.17714 -2503.9848 -2979.2668 -2978.3301 0.8407037 0.70678272 0.50841734 -1.0540275 + 9600 296.43744 4912.6395 -2979.1829 -2978.5736 0.70352404 0.49494608 0.68312042 -0.86335848 + 9700 288.63317 -3935.8902 -2979.0381 -2978.7635 0.55322477 0.30605764 0.88509388 -0.54108379 + 9800 296.27133 1365.4106 -2978.8723 -2978.8969 0.40665162 0.16536554 1.0460992 -0.092552905 + 9900 299.37628 -1267.2668 -2978.5934 -2978.9673 0.29467695 0.086834506 0.80391757 -0.38307943 + 10000 296.60645 1950.1018 -2978.2725 -2978.9739 0.28169006 0.079349287 0.70171659 -0.62026504 +Loop time of 47.4814 on 1 procs for 10000 steps with 864 atoms + +Performance: 36.393 ns/day, 0.659 hours/ns, 210.609 timesteps/s, 181.966 katom-step/s +99.9% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 46.299 | 46.299 | 46.299 | 0.0 | 97.51 +Neigh | 0.010908 | 0.010908 | 0.010908 | 0.0 | 0.02 +Comm | 0.29643 | 0.29643 | 0.29643 | 0.0 | 0.62 +Output | 0.0090682 | 0.0090682 | 0.0090682 | 0.0 | 0.02 +Modify | 0.7406 | 0.7406 | 0.7406 | 0.0 | 1.56 +Other | | 0.1254 | | | 0.26 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 3767 ave 3767 max 3767 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 96746 ave 96746 max 96746 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 96746 +Ave neighs/atom = 111.97454 +Neighbor list builds = 1 +Dangerous builds = 0 + +Total wall time: 0:00:47 diff --git a/examples/PACKAGES/moments/log.02May2025.simple.g++.4 b/examples/PACKAGES/moments/log.02May2025.simple.g++.4 new file mode 100644 index 0000000000..dde6be4aa3 --- /dev/null +++ b/examples/PACKAGES/moments/log.02May2025.simple.g++.4 @@ -0,0 +1,177 @@ +LAMMPS (2 Apr 2025 - Development - patch_4Feb2025-645-gba166d42e1-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# create pure copper system +units metal +lattice fcc 3.75 +Lattice spacing in x,y,z = 3.75 3.75 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box +Created orthogonal box = (0 0 0) to (22.5 22.5 22.5) + 1 by 2 by 2 MPI processor grid + +timestep 0.002 +create_atoms 1 box +Created 864 atoms + using lattice units in orthogonal box = (0 0 0) to (22.5 22.5 22.5) + create_atoms CPU = 0.010 seconds + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 0.2000000000000000111 + +variable toteng equal "etotal" +fix 2 all ave/moments 5 200 100 v_toteng mean stddev variance skew kurtosis + +thermo_style custom step temp press etotal f_2[*] + +thermo 100 +run 10000 +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 8.6825 + ghost atom cutoff = 8.6825 + binsize = 4.34125, bins = 6 6 6 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair eam/alloy, perpetual + attributes: half, newton on + pair build: half/bin/atomonly/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 3.42 | 3.42 | 3.42 Mbytes + Step Temp Press TotEng f_2[1] f_2[2] f_2[3] f_2[4] f_2[5] + 0 1000 -107410.22 -2884.9159 0 0 0 0 0 + 100 492.38014 -134.33622 -2928.6874 -2927.2291 1.7092959 2.9216925 2.5081594 6.099781 + 200 484.82396 -214.26318 -2931.4603 -2928.71 2.0003214 4.0012857 1.3645049 3.3103886 + 300 476.69743 15.78678 -2934.0022 -2930.0515 2.5470901 6.4876682 0.6954232 0.86102766 + 400 482.51415 141.67184 -2936.9347 -2931.4152 3.2681043 10.680505 0.30641098 -0.22337036 + 500 455.45411 2.4424602 -2939.9649 -2932.8397 4.1076295 16.87262 0.10483325 -0.6997127 + 600 455.20054 -6.8170934 -2943.0454 -2934.2947 4.9842257 24.842506 0.018003661 -0.92490336 + 700 429.81168 -75.812923 -2946.0438 -2935.7704 5.8766819 34.53539 -0.019539731 -1.0444564 + 800 428.22097 604.18705 -2948.9285 -2937.2449 6.7522047 45.592268 -0.026384526 -1.1194924 + 900 399.10914 -3622.6904 -2951.7252 -2938.7094 7.6043904 57.826753 -0.019997758 -1.1658244 + 1000 394.62543 7905.9041 -2954.2925 -2940.15 8.4168551 70.84345 -0.0026187371 -1.2004009 + 1100 404.27007 -2565.5508 -2956.9736 -2943.0009 8.3722389 70.094384 0.015852037 -1.2665587 + 1200 368.47178 741.43707 -2959.4264 -2945.8091 8.3127243 69.101386 0.069744698 -1.2412651 + 1300 360.91266 -267.08372 -2961.69 -2948.5981 8.1334656 66.153263 0.1116445 -1.2129213 + 1400 356.74405 158.09093 -2963.8501 -2951.3302 7.8574973 61.740264 0.13825232 -1.1999727 + 1500 335.45696 -71.007783 -2965.8817 -2953.9689 7.5384846 56.82875 0.15915227 -1.1877331 + 1600 331.01199 -454.90004 -2967.7708 -2956.5 7.1862592 51.642321 0.17403957 -1.1840985 + 1700 329.223 2428.4284 -2969.5452 -2958.9073 6.8228029 46.55064 0.19027454 -1.1778276 + 1800 327.61481 -4757.648 -2971.1105 -2961.1863 6.4445074 41.531675 0.20819854 -1.1712539 + 1900 318.18741 2226.7765 -2972.6906 -2963.3396 6.0703365 36.848986 0.22378928 -1.1556732 + 2000 308.79313 -1089.8603 -2974.0899 -2965.3712 5.6913723 32.391718 0.23279863 -1.1445916 + 2100 303.32047 757.53534 -2975.3597 -2967.2741 5.3153102 28.252523 0.23857925 -1.1465858 + 2200 307.41102 -837.97246 -2976.4966 -2969.0433 4.9515105 24.517456 0.25216298 -1.1426077 + 2300 303.01088 1618.29 -2977.5454 -2970.6862 4.593227 21.097734 0.26914071 -1.1356519 + 2400 297.59385 -3233.8282 -2978.4064 -2972.2049 4.235209 17.936995 0.28804295 -1.1332908 + 2500 288.72232 5209.2099 -2979.1999 -2973.5963 3.8804647 15.058006 0.31533205 -1.1258312 + 2600 298.92201 -2193.618 -2979.8873 -2974.8649 3.5301507 12.461964 0.34927897 -1.1048024 + 2700 282.61818 765.88178 -2980.4563 -2976.0148 3.1852407 10.145758 0.3879755 -1.0655899 + 2800 273.63104 -389.49749 -2980.8636 -2977.0468 2.8322558 8.021673 0.4259426 -1.0370247 + 2900 274.12166 -9.2552992 -2981.1421 -2977.9525 2.4816703 6.1586877 0.47721359 -1.0061337 + 3000 279.43592 212.25445 -2981.2716 -2978.7309 2.1328425 4.5490171 0.5532015 -0.94983292 + 3100 291.10071 -1139.205 -2981.2475 -2979.3812 1.7828537 3.1785674 0.66452451 -0.83906914 + 3200 281.53171 3124.6411 -2981.0818 -2979.9003 1.4287164 2.0412304 0.81952022 -0.6386061 + 3300 277.0223 -2795.9494 -2980.7825 -2980.287 1.0830229 1.1729385 1.0186688 -0.26502454 + 3400 284.8443 1587.8876 -2980.3701 -2980.5435 0.76893619 0.59126286 1.1646672 0.27529682 + 3500 281.19 -1143.0785 -2979.8374 -2980.6693 0.54860209 0.30096426 0.79069857 -0.36626891 + 3600 296.58287 1156.4706 -2979.2182 -2980.6646 0.55745952 0.31076112 0.81914175 -0.31895116 + 3700 297.24517 -1888.4993 -2978.5352 -2980.5318 0.77195451 0.59591377 1.0713124 -0.027796216 + 3800 290.81586 3843.3483 -2977.8509 -2980.2819 1.0444771 1.0909324 0.88270245 -0.57339499 + 3900 300.39456 -5584.8386 -2977.0837 -2979.9273 1.3073719 1.7092212 0.65444496 -0.94023014 + 4000 306.15811 3310.0105 -2976.5086 -2979.4859 1.5269967 2.3317191 0.45120199 -1.1665402 + 4100 295.907 -1475.0458 -2975.9096 -2978.9779 1.6878413 2.8488082 0.27738537 -1.2909517 + 4200 322.70162 933.76586 -2975.3867 -2978.425 1.7872637 3.1943116 0.12322364 -1.3421568 + 4300 306.69631 -512.7048 -2974.9324 -2977.8465 1.8221493 3.3202281 -0.016769435 -1.3380921 + 4400 309.23776 226.77219 -2974.5791 -2977.2621 1.788532 3.1988469 -0.14279249 -1.3044784 + 4500 313.15783 508.29785 -2974.3263 -2976.6947 1.6959722 2.8763217 -0.26351575 -1.2425552 + 4600 316.26151 -2043.7571 -2974.1697 -2976.1635 1.5525328 2.4103582 -0.38443906 -1.156175 + 4700 312.27329 1831.682 -2974.1732 -2975.6917 1.3614048 1.8534231 -0.52504872 -1.0383081 + 4800 307.61066 -1476.0019 -2974.2885 -2975.296 1.1354139 1.2891647 -0.69734331 -0.84719677 + 4900 305.73489 1303.4848 -2974.5506 -2974.9905 0.8913743 0.79454814 -0.90609876 -0.50216921 + 5000 309.3774 -1574.6812 -2974.8687 -2974.7812 0.65272109 0.42604482 -1.0613188 0.00291608 + 5100 304.8602 2679.7476 -2975.3082 -2974.6718 0.4727141 0.22345862 -0.75321909 -0.42028824 + 5200 297.54226 -5008.0905 -2975.7443 -2974.6646 0.45797515 0.20974124 -0.66557441 -0.64583954 + 5300 306.18872 4840.4175 -2976.324 -2974.7575 0.61348896 0.3763687 -1.0084709 -0.10258503 + 5400 299.57661 -2513.1706 -2976.8842 -2974.9472 0.83376011 0.69515592 -0.88189118 -0.55222188 + 5500 302.30844 1301.3525 -2977.4539 -2975.2244 1.0486412 1.0996484 -0.65075151 -0.94687541 + 5600 302.11038 -760.79712 -2977.9764 -2975.5765 1.2259535 1.502962 -0.44510538 -1.1709493 + 5700 294.49825 718.67318 -2978.4584 -2975.9844 1.357155 1.8418697 -0.27309672 -1.2848748 + 5800 305.97636 -478.64224 -2978.8638 -2976.429 1.4331646 2.0539608 -0.1197893 -1.3417863 + 5900 291.93868 -419.74179 -2979.2292 -2976.8905 1.4535887 2.1129201 0.024018983 -1.349863 + 6000 289.50667 859.85085 -2979.5018 -2977.3557 1.4249736 2.0305497 0.15271261 -1.3095465 + 6100 305.70118 -933.35917 -2979.6877 -2977.8064 1.3480601 1.8172659 0.27785119 -1.2402584 + 6200 284.37805 1526.0707 -2979.806 -2978.2265 1.2296781 1.5121082 0.40681415 -1.1355005 + 6300 291.08863 -2156.6708 -2979.8064 -2978.6017 1.0733214 1.1520189 0.54137333 -1.0156432 + 6400 295.99073 2819.8245 -2979.7378 -2978.9165 0.8941904 0.79957647 0.7073501 -0.82385123 + 6500 298.06769 -3396.3504 -2979.5428 -2979.1626 0.70228297 0.49320137 0.91043588 -0.48653641 + 6600 301.78514 5496.6525 -2979.2768 -2979.3329 0.51276653 0.26292952 1.0681056 -0.036293782 + 6700 290.80665 -5229.4989 -2978.9177 -2979.4217 0.36990055 0.13682642 0.81466085 -0.37332419 + 6800 296.75761 2401.7807 -2978.5996 -2979.4338 0.34589164 0.11964103 0.65253856 -0.7737558 + 6900 295.77553 -1521.6269 -2978.1619 -2979.3685 0.46007271 0.21166689 1.0427138 -0.013014477 + 7000 303.59015 1530.7255 -2977.7097 -2979.225 0.63320287 0.40094588 0.93012255 -0.45527217 + 7100 297.51038 -3016.4426 -2977.2025 -2979.0103 0.81101521 0.65774567 0.7114444 -0.84465178 + 7200 293.53789 2705.9808 -2976.7651 -2978.7294 0.97512025 0.95085951 0.52979295 -1.0479526 + 7300 301.78809 -1042.1076 -2976.3388 -2978.3998 1.1024575 1.2154126 0.35564664 -1.2137023 + 7400 307.50053 214.56923 -2975.9581 -2978.0341 1.188001 1.4113463 0.20025025 -1.3077784 + 7500 301.98985 281.86495 -2975.6146 -2977.6451 1.2301918 1.5133718 0.063886193 -1.3465506 + 7600 318.37347 -1145.7795 -2975.3473 -2977.2486 1.2295055 1.5116837 -0.066939137 -1.3475567 + 7700 314.94512 4536.9887 -2975.1351 -2976.8564 1.1948121 1.427576 -0.19450637 -1.2864658 + 7800 312.91485 -2980.6408 -2975.0156 -2976.4828 1.1134406 1.2397499 -0.32749726 -1.207718 + 7900 310.06854 2244.3877 -2975.0094 -2976.1462 0.99080702 0.98169854 -0.48336959 -1.0840695 + 8000 308.55007 -2427.1464 -2975.0491 -2975.8566 0.83800849 0.70225823 -0.65822117 -0.89212512 + 8100 323.02796 3187.4728 -2975.2081 -2975.6251 0.66510054 0.44235872 -0.84857729 -0.62984027 + 8200 327.05029 -6447.7875 -2975.3162 -2975.4608 0.49730291 0.24731018 -1.0534735 -0.14095413 + 8300 311.194 4273.1174 -2975.7217 -2975.3642 0.35491458 0.12596436 -0.95967595 -0.04445204 + 8400 290.61931 -2301.019 -2976.0963 -2975.3446 0.31530296 0.09941596 -0.69056625 -0.72257435 + 8500 314.00559 1966.1297 -2976.5206 -2975.3995 0.41659574 0.17355201 -1.1134124 0.18107632 + 8600 288.26541 -1608.4524 -2976.9304 -2975.526 0.57968749 0.33603759 -1.0014591 -0.34698354 + 8700 298.92083 1353.9988 -2977.355 -2975.7203 0.74176087 0.55020919 -0.74109062 -0.86227705 + 8800 299.97274 -638.68301 -2977.766 -2975.9682 0.87950613 0.77353104 -0.50839929 -1.1555064 + 8900 300.66443 -279.62514 -2978.1476 -2976.262 0.99526406 0.99055054 -0.33059914 -1.261881 + 9000 290.44715 489.06352 -2978.4892 -2976.5918 1.0763797 1.1585932 -0.17871557 -1.3082755 + 9100 289.06733 -1063.4482 -2978.784 -2976.943 1.1174524 1.2486999 -0.037767225 -1.3120851 + 9200 297.63931 2664.6535 -2979.0202 -2977.3033 1.1127042 1.2381106 0.090936095 -1.2913777 + 9300 297.9983 -4684.428 -2979.1316 -2977.6563 1.0596342 1.1228247 0.20756305 -1.2867214 + 9400 285.14009 2779.1548 -2979.2804 -2977.9868 0.98034602 0.96107833 0.33668495 -1.2294268 + 9500 284.11569 -2437.5003 -2979.2918 -2978.2852 0.87286876 0.76189987 0.48407552 -1.1274969 + 9600 291.97193 2772.1396 -2979.2473 -2978.5402 0.74294711 0.55197041 0.67450455 -0.91152584 + 9700 292.59563 -3615.4496 -2979.0801 -2978.7442 0.59448857 0.35341666 0.91630006 -0.47180257 + 9800 296.1785 4869.2744 -2978.8849 -2978.891 0.43463281 0.18890568 1.1020846 0.093881572 + 9900 298.44745 -3587.7391 -2978.5978 -2978.9712 0.30680426 0.094128854 0.8532075 -0.19634913 + 10000 297.99863 1312.5643 -2978.3205 -2978.9854 0.27829395 0.077447522 0.60818263 -0.79004935 +Loop time of 15.3108 on 4 procs for 10000 steps with 864 atoms + +Performance: 112.862 ns/day, 0.213 hours/ns, 653.136 timesteps/s, 564.309 katom-step/s +92.4% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 11.428 | 12.158 | 12.621 | 13.0 | 79.41 +Neigh | 0.0019158 | 0.0020708 | 0.002163 | 0.2 | 0.01 +Comm | 1.936 | 2.3948 | 3.0967 | 28.3 | 15.64 +Output | 0.0026067 | 0.0037308 | 0.0066123 | 2.7 | 0.02 +Modify | 0.44688 | 0.45929 | 0.47131 | 1.6 | 3.00 +Other | | 0.2928 | | | 1.91 + +Nlocal: 216 ave 224 max 204 min +Histogram: 1 0 0 0 0 0 0 2 0 1 +Nghost: 2147 ave 2159 max 2139 min +Histogram: 1 0 0 2 0 0 0 0 0 1 +Neighs: 24185.8 ave 26045 max 21309 min +Histogram: 1 0 0 0 0 1 0 0 0 2 + +Total # of neighbors = 96743 +Ave neighs/atom = 111.97106 +Neighbor list builds = 1 +Dangerous builds = 0 + +Total wall time: 0:00:15 diff --git a/examples/PACKAGES/moments/log.02May2025.valtest.g++.1 b/examples/PACKAGES/moments/log.02May2025.valtest.g++.1 new file mode 100644 index 0000000000..86cbeee12b --- /dev/null +++ b/examples/PACKAGES/moments/log.02May2025.valtest.g++.1 @@ -0,0 +1,178 @@ +LAMMPS (2 Apr 2025 - Development - patch_4Feb2025-645-gba166d42e1-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# create pure copper system +units metal +lattice fcc 3.75 +Lattice spacing in x,y,z = 3.75 3.75 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box +Created orthogonal box = (0 0 0) to (22.5 22.5 22.5) + 1 by 1 by 1 MPI processor grid + +timestep 0.002 +create_atoms 1 box +Created 864 atoms + using lattice units in orthogonal box = (0 0 0) to (22.5 22.5 22.5) + create_atoms CPU = 0.001 seconds + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 0.2000000000000000111 + +variable toteng equal "etotal" +fix 2 all ave/moments 1 10 10 v_toteng mean variance skew kurtosis + +thermo_style custom step etotal f_2[*] +thermo_modify format float %14.8f + +thermo 1 +run 100 +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 8.6825 + ghost atom cutoff = 8.6825 + binsize = 4.34125, bins = 6 6 6 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair eam/alloy, perpetual + attributes: half, newton on + pair build: half/bin/atomonly/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 3.484 | 3.484 | 3.484 Mbytes + Step TotEng f_2[1] f_2[2] f_2[3] f_2[4] + 0 -2884.91592826 0.00000000 0.00000000 0.00000000 0.00000000 + 1 -2888.74461907 0.00000000 0.00000000 0.00000000 0.00000000 + 2 -2898.78491936 0.00000000 0.00000000 0.00000000 0.00000000 + 3 -2910.70619667 0.00000000 0.00000000 0.00000000 0.00000000 + 4 -2919.41734302 0.00000000 0.00000000 0.00000000 0.00000000 + 5 -2923.24980175 0.00000000 0.00000000 0.00000000 0.00000000 + 6 -2923.79800148 0.00000000 0.00000000 0.00000000 0.00000000 + 7 -2922.97580252 0.00000000 0.00000000 0.00000000 0.00000000 + 8 -2921.95601941 0.00000000 0.00000000 0.00000000 0.00000000 + 9 -2921.45319499 0.00000000 0.00000000 0.00000000 0.00000000 + 10 -2921.81460149 -2915.29004998 148.32538381 1.60272422 1.50844200 + 11 -2923.00059466 -2915.29004998 148.32538381 1.60272422 1.50844200 + 12 -2924.63075671 -2915.29004998 148.32538381 1.60272422 1.50844200 + 13 -2926.18037946 -2915.29004998 148.32538381 1.60272422 1.50844200 + 14 -2927.22356281 -2915.29004998 148.32538381 1.60272422 1.50844200 + 15 -2927.62053073 -2915.29004998 148.32538381 1.60272422 1.50844200 + 16 -2927.49949128 -2915.29004998 148.32538381 1.60272422 1.50844200 + 17 -2927.12292174 -2915.29004998 148.32538381 1.60272422 1.50844200 + 18 -2926.73637250 -2915.29004998 148.32538381 1.60272422 1.50844200 + 19 -2926.49482990 -2915.29004998 148.32538381 1.60272422 1.50844200 + 20 -2926.44714720 -2926.29565870 2.07215006 1.62317861 2.37019300 + 21 -2926.56102718 -2926.29565870 2.07215006 1.62317861 2.37019300 + 22 -2926.76734347 -2926.29565870 2.07215006 1.62317861 2.37019300 + 23 -2926.98403044 -2926.29565870 2.07215006 1.62317861 2.37019300 + 24 -2927.15193693 -2926.29565870 2.07215006 1.62317861 2.37019300 + 25 -2927.24498540 -2926.29565870 2.07215006 1.62317861 2.37019300 + 26 -2927.26914121 -2926.29565870 2.07215006 1.62317861 2.37019300 + 27 -2927.25021402 -2926.29565870 2.07215006 1.62317861 2.37019300 + 28 -2927.21637817 -2926.29565870 2.07215006 1.62317861 2.37019300 + 29 -2927.19085616 -2926.29565870 2.07215006 1.62317861 2.37019300 + 30 -2927.18360687 -2927.08195198 0.05722486 1.54894969 1.44984748 + 31 -2927.19243579 -2927.08195198 0.05722486 1.54894969 1.44984748 + 32 -2927.20805612 -2927.08195198 0.05722486 1.54894969 1.44984748 + 33 -2927.22285606 -2927.08195198 0.05722486 1.54894969 1.44984748 + 34 -2927.23274852 -2927.08195198 0.05722486 1.54894969 1.44984748 + 35 -2927.23953263 -2927.08195198 0.05722486 1.54894969 1.44984748 + 36 -2927.24805761 -2927.08195198 0.05722486 1.54894969 1.44984748 + 37 -2927.26215638 -2927.08195198 0.05722486 1.54894969 1.44984748 + 38 -2927.28298252 -2927.08195198 0.05722486 1.54894969 1.44984748 + 39 -2927.31025065 -2927.08195198 0.05722486 1.54894969 1.44984748 + 40 -2927.33874897 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 41 -2927.36224413 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 42 -2927.37729800 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 43 -2927.38671916 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 44 -2927.39115082 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 45 -2927.39614318 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 46 -2927.40444730 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 47 -2927.41888601 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 48 -2927.43954388 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 49 -2927.46210058 -2927.25378252 0.00209108 -0.65432756 -0.21113798 + 50 -2927.48270024 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 51 -2927.49822500 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 52 -2927.50765361 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 53 -2927.51223225 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 54 -2927.51510653 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 55 -2927.52035921 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 56 -2927.53170012 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 57 -2927.54910408 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 58 -2927.57357292 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 59 -2927.60356966 -2927.41212333 0.00148630 -0.72914987 -0.39161968 + 60 -2927.63344447 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 61 -2927.66186165 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 62 -2927.68810360 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 63 -2927.71163480 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 64 -2927.73036225 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 65 -2927.74726656 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 66 -2927.76525638 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 67 -2927.78432762 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 68 -2927.80305095 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 69 -2927.82406714 -2927.54449679 0.00204640 -1.06571776 0.04430271 + 70 -2927.84622122 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 71 -2927.86886493 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 72 -2927.89150302 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 73 -2927.91480122 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 74 -2927.93739399 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 75 -2927.96075707 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 76 -2927.98525702 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 77 -2928.00918972 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 78 -2928.03266453 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 79 -2928.05673430 -2927.75621522 0.00356092 0.06232090 -0.94076248 + 80 -2928.08120268 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 81 -2928.10618717 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 82 -2928.13191751 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 83 -2928.15675025 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 84 -2928.18178044 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 85 -2928.20538210 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 86 -2928.22991006 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 87 -2928.25238345 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 88 -2928.27490378 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 89 -2928.29697980 -2927.97383685 0.00511363 -0.03242365 -1.20956903 + 90 -2928.31902032 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 91 -2928.34079951 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 92 -2928.36448072 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 93 -2928.38918869 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 94 -2928.41578734 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 95 -2928.44466633 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 96 -2928.47414034 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 97 -2928.50507273 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 98 -2928.53751007 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 99 -2928.56947939 -2928.21552149 0.00511983 0.08421866 -1.19120544 + 100 -2928.60000318 -2928.46411283 0.00779929 -0.14908790 -1.24292534 +Loop time of 0.579661 on 1 procs for 100 steps with 864 atoms + +Performance: 29.811 ns/day, 0.805 hours/ns, 172.515 timesteps/s, 149.053 katom-step/s +96.3% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.54316 | 0.54316 | 0.54316 | 0.0 | 93.70 +Neigh | 0.0041212 | 0.0041212 | 0.0041212 | 0.0 | 0.71 +Comm | 0.0034702 | 0.0034702 | 0.0034702 | 0.0 | 0.60 +Output | 0.014085 | 0.014085 | 0.014085 | 0.0 | 2.43 +Modify | 0.01321 | 0.01321 | 0.01321 | 0.0 | 2.28 +Other | | 0.001612 | | | 0.28 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 3767 ave 3767 max 3767 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 96746 ave 96746 max 96746 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 96746 +Ave neighs/atom = 111.97454 +Neighbor list builds = 1 +Dangerous builds = 0 + +Total wall time: 0:00:00 diff --git a/examples/PACKAGES/moments/log.02May2025.valtest.g++.4 b/examples/PACKAGES/moments/log.02May2025.valtest.g++.4 new file mode 100644 index 0000000000..f7321d2326 --- /dev/null +++ b/examples/PACKAGES/moments/log.02May2025.valtest.g++.4 @@ -0,0 +1,178 @@ +LAMMPS (2 Apr 2025 - Development - patch_4Feb2025-645-gba166d42e1-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# create pure copper system +units metal +lattice fcc 3.75 +Lattice spacing in x,y,z = 3.75 3.75 3.75 +region box block 0 6 0 6 0 6 +create_box 2 box +Created orthogonal box = (0 0 0) to (22.5 22.5 22.5) + 1 by 2 by 2 MPI processor grid + +timestep 0.002 +create_atoms 1 box +Created 864 atoms + using lattice units in orthogonal box = (0 0 0) to (22.5 22.5 22.5) + create_atoms CPU = 0.001 seconds + +pair_style eam/alloy +pair_coeff * * AlCu.eam.alloy Cu Al + +# Initialize to a high temperature, then cool in npt ensemble +velocity all create 1000.0 6567345 +fix 1 all npt temp 300.0 300.0 $(500*dt) iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 $(100*dt) +fix 1 all npt temp 300.0 300.0 1 iso 0.0 0.0 0.2000000000000000111 + +variable toteng equal "etotal" +fix 2 all ave/moments 1 10 10 v_toteng mean variance skew kurtosis + +thermo_style custom step etotal f_2[*] +thermo_modify format float %14.8f + +thermo 1 +run 100 +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 8.6825 + ghost atom cutoff = 8.6825 + binsize = 4.34125, bins = 6 6 6 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair eam/alloy, perpetual + attributes: half, newton on + pair build: half/bin/atomonly/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 3.42 | 3.42 | 3.42 Mbytes + Step TotEng f_2[1] f_2[2] f_2[3] f_2[4] + 0 -2884.91592826 0.00000000 0.00000000 0.00000000 0.00000000 + 1 -2888.74473521 0.00000000 0.00000000 0.00000000 0.00000000 + 2 -2898.78463435 0.00000000 0.00000000 0.00000000 0.00000000 + 3 -2910.70366466 0.00000000 0.00000000 0.00000000 0.00000000 + 4 -2919.40999553 0.00000000 0.00000000 0.00000000 0.00000000 + 5 -2923.23570887 0.00000000 0.00000000 0.00000000 0.00000000 + 6 -2923.77707961 0.00000000 0.00000000 0.00000000 0.00000000 + 7 -2922.94386730 0.00000000 0.00000000 0.00000000 0.00000000 + 8 -2921.92251474 0.00000000 0.00000000 0.00000000 0.00000000 + 9 -2921.42476103 0.00000000 0.00000000 0.00000000 0.00000000 + 10 -2921.79501042 -2915.27419717 148.08574615 1.60354430 1.51194865 + 11 -2922.99498349 -2915.27419717 148.08574615 1.60354430 1.51194865 + 12 -2924.64023395 -2915.27419717 148.08574615 1.60354430 1.51194865 + 13 -2926.19980790 -2915.27419717 148.08574615 1.60354430 1.51194865 + 14 -2927.25022454 -2915.27419717 148.08574615 1.60354430 1.51194865 + 15 -2927.64953875 -2915.27419717 148.08574615 1.60354430 1.51194865 + 16 -2927.52804735 -2915.27419717 148.08574615 1.60354430 1.51194865 + 17 -2927.14916045 -2915.27419717 148.08574615 1.60354430 1.51194865 + 18 -2926.76078244 -2915.27419717 148.08574615 1.60354430 1.51194865 + 19 -2926.51878380 -2915.27419717 148.08574615 1.60354430 1.51194865 + 20 -2926.47129883 -2926.31628615 2.10313655 1.62594474 2.38000930 + 21 -2926.59030835 -2926.31628615 2.10313655 1.62594474 2.38000930 + 22 -2926.80121221 -2926.31628615 2.10313655 1.62594474 2.38000930 + 23 -2927.02526150 -2926.31628615 2.10313655 1.62594474 2.38000930 + 24 -2927.20079704 -2926.31628615 2.10313655 1.62594474 2.38000930 + 25 -2927.30192483 -2926.31628615 2.10313655 1.62594474 2.38000930 + 26 -2927.33194351 -2926.31628615 2.10313655 1.62594474 2.38000930 + 27 -2927.31647527 -2926.31628615 2.10313655 1.62594474 2.38000930 + 28 -2927.28391864 -2926.31628615 2.10313655 1.62594474 2.38000930 + 29 -2927.25821953 -2926.31628615 2.10313655 1.62594474 2.38000930 + 30 -2927.25085808 -2927.13609190 0.06387000 1.52055179 1.31247839 + 31 -2927.25723201 -2927.13609190 0.06387000 1.52055179 1.31247839 + 32 -2927.27197789 -2927.13609190 0.06387000 1.52055179 1.31247839 + 33 -2927.28667044 -2927.13609190 0.06387000 1.52055179 1.31247839 + 34 -2927.29879455 -2927.13609190 0.06387000 1.52055179 1.31247839 + 35 -2927.30701891 -2927.13609190 0.06387000 1.52055179 1.31247839 + 36 -2927.31785921 -2927.13609190 0.06387000 1.52055179 1.31247839 + 37 -2927.33272014 -2927.13609190 0.06387000 1.52055179 1.31247839 + 38 -2927.35282056 -2927.13609190 0.06387000 1.52055179 1.31247839 + 39 -2927.37849130 -2927.13609190 0.06387000 1.52055179 1.31247839 + 40 -2927.40448350 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 41 -2927.42423249 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 42 -2927.43769919 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 43 -2927.44493813 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 44 -2927.44923137 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 45 -2927.45439729 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 46 -2927.46365674 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 47 -2927.48173952 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 48 -2927.50371663 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 49 -2927.52750629 -2927.32080685 0.00219675 -0.52051260 -0.50322958 + 50 -2927.54872274 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 51 -2927.56277664 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 52 -2927.57050508 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 53 -2927.57241043 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 54 -2927.57517748 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 55 -2927.58161786 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 56 -2927.59393740 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 57 -2927.61367876 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 58 -2927.64096296 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 59 -2927.67356621 -2927.47358404 0.00168128 -0.79883601 -0.48497973 + 60 -2927.70625176 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 61 -2927.73673853 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 62 -2927.76292153 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 63 -2927.78541405 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 64 -2927.80292853 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 65 -2927.81988675 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 66 -2927.83680256 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 67 -2927.85379296 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 68 -2927.87418119 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 69 -2927.89451588 -2927.60908846 0.00241645 -1.10903745 0.07175615 + 70 -2927.91602570 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 71 -2927.93874793 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 72 -2927.96195498 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 73 -2927.98521535 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 74 -2928.01060565 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 75 -2928.03584561 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 76 -2928.06090892 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 77 -2928.08509438 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 78 -2928.11095399 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 79 -2928.13711339 -2927.82832077 0.00334657 0.04700770 -0.91589129 + 80 -2928.16413424 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 81 -2928.19005959 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 82 -2928.21654649 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 83 -2928.24249986 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 84 -2928.26861892 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 85 -2928.29480718 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 86 -2928.32144325 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 87 -2928.34727619 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 88 -2928.37131285 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 89 -2928.39531126 -2928.04905744 0.00575008 -0.05409710 -1.19501222 + 90 -2928.41739503 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 91 -2928.43978811 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 92 -2928.46316822 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 93 -2928.48654219 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 94 -2928.51132482 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 95 -2928.53938009 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 96 -2928.56852408 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 97 -2928.59814410 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 98 -2928.62787940 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 99 -2928.65853178 -2928.30652706 0.00595440 0.06693205 -1.24851322 + 100 -2928.68735978 -2928.55806426 0.00711607 -0.13829819 -1.25519738 +Loop time of 0.327437 on 4 procs for 100 steps with 864 atoms + +Performance: 52.774 ns/day, 0.455 hours/ns, 305.402 timesteps/s, 263.868 katom-step/s +91.9% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.27213 | 0.27259 | 0.27312 | 0.1 | 83.25 +Neigh | 0.00096945 | 0.0015991 | 0.0022533 | 1.5 | 0.49 +Comm | 0.026726 | 0.027088 | 0.027516 | 0.2 | 8.27 +Output | 0.0029839 | 0.0048706 | 0.0097487 | 4.0 | 1.49 +Modify | 0.012374 | 0.016834 | 0.018623 | 2.0 | 5.14 +Other | | 0.004455 | | | 1.36 + +Nlocal: 216 ave 224 max 204 min +Histogram: 1 0 0 0 0 0 0 2 0 1 +Nghost: 2147 ave 2159 max 2139 min +Histogram: 1 0 0 2 0 0 0 0 0 1 +Neighs: 24185.8 ave 26045 max 21309 min +Histogram: 1 0 0 0 0 1 0 0 0 2 + +Total # of neighbors = 96743 +Ave neighs/atom = 111.97106 +Neighbor list builds = 1 +Dangerous builds = 0 + +Total wall time: 0:00:00 diff --git a/examples/PACKAGES/neighbor-swap/MoCoNiVFeAlCr_2nn.meam b/examples/PACKAGES/neighbor-swap/MoCoNiVFeAlCr_2nn.meam new file mode 120000 index 0000000000..160501aee4 --- /dev/null +++ b/examples/PACKAGES/neighbor-swap/MoCoNiVFeAlCr_2nn.meam @@ -0,0 +1 @@ +../../../potentials/MoCoNiVFeAlCr_2nn.meam \ No newline at end of file diff --git a/examples/PACKAGES/neighbor-swap/in.KMC_pulse_center b/examples/PACKAGES/neighbor-swap/in.KMC_pulse_center new file mode 100644 index 0000000000..29993fab29 --- /dev/null +++ b/examples/PACKAGES/neighbor-swap/in.KMC_pulse_center @@ -0,0 +1,46 @@ +# May 2025 +# Test script for MD-KMC accelerated diffusion testing in LAMMPS +# Created by Jacob Tavenner, Baylor University + +# Initiation ------------------------------------- +units metal +dimension 3 +boundary p p p +atom_style atomic + +# Atom Definition -------------------------------- +lattice fcc 3.762 +region whole block 0 1 0 1 0 1 +create_box 2 whole +create_atoms 1 region whole + +replicate 6 16 6 + +region puck block INF INF 7 9 INF INF +set region puck type 2 + +# Force Fields ----------------------------------- +pair_style meam +pair_coeff * * library_2nn.meam Mo Co Ni V Fe Al Cr MoCoNiVFeAlCr_2nn.meam Ni Cr + +# Settings --------------------------------------- +timestep 0.002 +thermo 100 + +# Computations ----------------------------------- +compute voroN all voronoi/atom neighbors yes + +run 0 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe + +# Execution -------------------------------------- + +velocity all create 2400 908124 loop geom +fix temp all npt temp 1000 1000 1000 aniso 0 0 1 +fix mc all neighbor/swap 50 12 1340723 1000 3 voroN diff 2 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe f_mc[*] +#dump dump2 all custom 5000 dump.edge-3_Ni-Cr.* id type x y z c_eng c_csym + +run 1000 + +#write_data pulse_center.data diff --git a/examples/PACKAGES/neighbor-swap/in.KMC_pulse_edge b/examples/PACKAGES/neighbor-swap/in.KMC_pulse_edge new file mode 100644 index 0000000000..5bf51d2ed1 --- /dev/null +++ b/examples/PACKAGES/neighbor-swap/in.KMC_pulse_edge @@ -0,0 +1,47 @@ +# May 2025 +# Test script for MD-KMC accelerated diffusion testing in LAMMPS +# Created by Jacob Tavenner, Baylor University + +# Initiation ------------------------------------- +units metal +dimension 3 +boundary p p p +atom_style atomic + + +# Atom Definition -------------------------------- +lattice fcc 3.762 +region whole block 0 1 0 1 0 1 +create_box 2 whole +create_atoms 1 region whole + +replicate 6 16 6 + +region puck block INF INF INF 2 INF INF +set region puck type 2 + +# Force Fields ----------------------------------- +pair_style meam +pair_coeff * * library_2nn.meam Mo Co Ni V Fe Al Cr MoCoNiVFeAlCr_2nn.meam Ni Cr + +# Settings --------------------------------------- +timestep 0.002 +thermo 100 + +# Computations ----------------------------------- +compute voroN all voronoi/atom neighbors yes + +run 0 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe + +# Execution -------------------------------------- + +velocity all create 2400 908124 loop geom +fix temp all npt temp 1000 1000 1000 aniso 0 0 1 +fix mc all neighbor/swap 50 12 1340723 1000 3 voroN diff 2 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe f_mc[*] +#dump dump2 all custom 5000 dump.edge-3_Ni-Cr.* id type x y z c_eng c_csym + +run 1000 + +#write_data pulse_end.data diff --git a/examples/PACKAGES/neighbor-swap/library_2nn.meam b/examples/PACKAGES/neighbor-swap/library_2nn.meam new file mode 120000 index 0000000000..278b81be6a --- /dev/null +++ b/examples/PACKAGES/neighbor-swap/library_2nn.meam @@ -0,0 +1 @@ +../../../potentials/library_2nn.meam \ No newline at end of file diff --git a/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_center.g++.1 b/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_center.g++.1 new file mode 100644 index 0000000000..1f1bd00a71 --- /dev/null +++ b/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_center.g++.1 @@ -0,0 +1,154 @@ +LAMMPS (2 Apr 2025 - Development - patch_2Apr2025-384-g88bc7dc720-modified) + using 1 OpenMP thread(s) per MPI task +# May 2025 +# Test script for MD-KMC accelerated diffusion testing in LAMMPS +# Created by Jacob Tavenner, Baylor University + +# Initiation ------------------------------------- +units metal +dimension 3 +boundary p p p +atom_style atomic + +# Atom Definition -------------------------------- +lattice fcc 3.762 +Lattice spacing in x,y,z = 3.762 3.762 3.762 +region whole block 0 1 0 1 0 1 +create_box 2 whole +Created orthogonal box = (0 0 0) to (3.762 3.762 3.762) + 1 by 1 by 1 MPI processor grid +create_atoms 1 region whole +Created 4 atoms + using lattice units in orthogonal box = (0 0 0) to (3.762 3.762 3.762) + create_atoms CPU = 0.000 seconds + +replicate 6 16 6 +Replication is creating a 6x16x6 = 576 times larger system... + orthogonal box = (0 0 0) to (22.572 60.192 22.572) + 1 by 1 by 1 MPI processor grid + 2304 atoms + replicate CPU = 0.000 seconds + +region puck block INF INF 7 9 INF INF +set region puck type 2 +Setting atom values ... + 360 settings made for type + +# Force Fields ----------------------------------- +pair_style meam +pair_coeff * * library_2nn.meam Mo Co Ni V Fe Al Cr MoCoNiVFeAlCr_2nn.meam Ni Cr +Reading MEAM library file library_2nn.meam with DATE: 2024-08-08 +Reading MEAM potential file MoCoNiVFeAlCr_2nn.meam with DATE: 2024-08-08 + +# Settings --------------------------------------- +timestep 0.002 +thermo 100 + +# Computations ----------------------------------- +compute voroN all voronoi/atom neighbors yes + +run 0 +WARNING: No fixes with time integration, atoms won't move +For more information see https://docs.lammps.org/err0028 (src/verlet.cpp:60) +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.8 + ghost atom cutoff = 6.8 + binsize = 3.4, bins = 7 18 7 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair meam, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard + (2) pair meam, perpetual, half/full from (1) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 13.32 | 13.32 | 13.32 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 0 -9674.3728 0 -9674.3728 -212400.94 +Loop time of 1.202e-06 on 1 procs for 0 steps with 2304 atoms + +0.0% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0 | 0 | 0 | 0.0 | 0.00 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 1.202e-06 | | |100.00 + +Nlocal: 2304 ave 2304 max 2304 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 4735 ave 4735 max 4735 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 99072 ave 99072 max 99072 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 198144 ave 198144 max 198144 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 198144 +Ave neighs/atom = 86 +Neighbor list builds = 0 +Dangerous builds = 0 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe + +# Execution -------------------------------------- + +velocity all create 2400 908124 +fix temp all npt temp 1000 1000 1000 aniso 0 0 1 +fix mc all neighbor/swap 50 12 1340723 1000 3 voroN diff 2 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe f_mc[*] +#dump dump2 all custom 5000 dump.edge-3_Ni-Cr.* id type x y z c_eng c_csym + +run 1000 +Per MPI rank memory allocation (min/avg/max) = 13.32 | 13.32 | 13.32 Mbytes + Step Temp Press Pxx Pyy Pzz Lx Ly Lz Volume PotEng f_mc[1] f_mc[2] + 0 2400 -187517.52 -187403.07 -187750.14 -187399.35 22.572 60.192 22.572 30667.534 -9674.3728 0 0 + 100 1664.9956 14000 14280.682 15095.077 12624.241 21.635315 57.726568 21.64791 27036.778 -9592.8978 24 22 + 200 1560.0093 -5452.2434 -5749.5816 -2957.4228 -7649.7258 21.734212 58.085959 21.724853 27426.596 -9562.8822 48 45 + 300 1586.4553 2030.9253 2776.4677 775.50538 2540.803 21.678654 58.101753 21.654423 27275.215 -9571.1308 72 66 + 400 1603.6896 -223.16773 156.17673 -478.47929 -347.20061 21.701021 58.098904 21.657752 27306.213 -9576.4456 96 90 + 500 1618.236 -925.51874 -1640.9078 451.6228 -1587.2713 21.718334 58.042685 21.666081 27312.054 -9581.2045 120 110 + 600 1581.9995 290.10126 1359.1314 1407.5434 -1896.371 21.679813 58.086147 21.692118 27316.815 -9570.4803 144 132 + 700 1568.3261 1387.3472 938.81523 2159.3686 1063.8577 21.685928 58.075626 21.67273 27295.153 -9566.2914 168 155 + 800 1607.1531 46.792964 -453.90265 -1533.3908 2127.6723 21.685188 58.202356 21.628338 27297.753 -9577.7848 192 177 + 900 1573.4747 -84.225488 548.90935 -1356.7479 555.16208 21.69634 58.150052 21.651847 27316.908 -9567.7039 216 196 + 1000 1609.2136 1215.0833 764.08936 3301.0811 -419.92053 21.683731 58.000401 21.68726 27275.31 -9578.2843 240 219 +Loop time of 31.6263 on 1 procs for 1000 steps with 2304 atoms + +Performance: 5.464 ns/day, 4.393 hours/ns, 31.619 timesteps/s, 72.851 katom-step/s +99.2% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 28.487 | 28.487 | 28.487 | 0.0 | 90.07 +Neigh | 0.22789 | 0.22789 | 0.22789 | 0.0 | 0.72 +Comm | 0.010808 | 0.010808 | 0.010808 | 0.0 | 0.03 +Output | 0.00033526 | 0.00033526 | 0.00033526 | 0.0 | 0.00 +Modify | 2.8963 | 2.8963 | 2.8963 | 0.0 | 9.16 +Other | | 0.003905 | | | 0.01 + +Nlocal: 2304 ave 2304 max 2304 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 4750 ave 4750 max 4750 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 130023 ave 130023 max 130023 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 260046 ave 260046 max 260046 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 260046 +Ave neighs/atom = 112.86719 +Neighbor list builds = 65 +Dangerous builds = 0 + +#write_data pulse_center.data +Total wall time: 0:00:31 diff --git a/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_center.g++.4 b/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_center.g++.4 new file mode 100644 index 0000000000..54c372d0f7 --- /dev/null +++ b/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_center.g++.4 @@ -0,0 +1,154 @@ +LAMMPS (2 Apr 2025 - Development - patch_2Apr2025-384-g88bc7dc720-modified) + using 1 OpenMP thread(s) per MPI task +# May 2025 +# Test script for MD-KMC accelerated diffusion testing in LAMMPS +# Created by Jacob Tavenner, Baylor University + +# Initiation ------------------------------------- +units metal +dimension 3 +boundary p p p +atom_style atomic + +# Atom Definition -------------------------------- +lattice fcc 3.762 +Lattice spacing in x,y,z = 3.762 3.762 3.762 +region whole block 0 1 0 1 0 1 +create_box 2 whole +Created orthogonal box = (0 0 0) to (3.762 3.762 3.762) + 1 by 2 by 2 MPI processor grid +create_atoms 1 region whole +Created 4 atoms + using lattice units in orthogonal box = (0 0 0) to (3.762 3.762 3.762) + create_atoms CPU = 0.000 seconds + +replicate 6 16 6 +Replication is creating a 6x16x6 = 576 times larger system... + orthogonal box = (0 0 0) to (22.572 60.192 22.572) + 1 by 4 by 1 MPI processor grid + 2304 atoms + replicate CPU = 0.000 seconds + +region puck block INF INF 7 9 INF INF +set region puck type 2 +Setting atom values ... + 360 settings made for type + +# Force Fields ----------------------------------- +pair_style meam +pair_coeff * * library_2nn.meam Mo Co Ni V Fe Al Cr MoCoNiVFeAlCr_2nn.meam Ni Cr +Reading MEAM library file library_2nn.meam with DATE: 2024-08-08 +Reading MEAM potential file MoCoNiVFeAlCr_2nn.meam with DATE: 2024-08-08 + +# Settings --------------------------------------- +timestep 0.002 +thermo 100 + +# Computations ----------------------------------- +compute voroN all voronoi/atom neighbors yes + +run 0 +WARNING: No fixes with time integration, atoms won't move +For more information see https://docs.lammps.org/err0028 (src/verlet.cpp:60) +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.8 + ghost atom cutoff = 6.8 + binsize = 3.4, bins = 7 18 7 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair meam, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard + (2) pair meam, perpetual, half/full from (1) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 9.636 | 9.636 | 9.636 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 0 -9674.3728 0 -9674.3728 -212400.94 +Loop time of 1.422e-06 on 4 procs for 0 steps with 2304 atoms + +35.2% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0 | 0 | 0 | 0.0 | 0.00 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 1.422e-06 | | |100.00 + +Nlocal: 576 ave 576 max 576 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Nghost: 2131 ave 2131 max 2131 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Neighs: 24768 ave 24768 max 24768 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +FullNghs: 49536 ave 49536 max 49536 min +Histogram: 4 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 198144 +Ave neighs/atom = 86 +Neighbor list builds = 0 +Dangerous builds = 0 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe + +# Execution -------------------------------------- + +velocity all create 2400 908124 +fix temp all npt temp 1000 1000 1000 aniso 0 0 1 +fix mc all neighbor/swap 50 12 1340723 1000 3 voroN diff 2 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe f_mc[*] +#dump dump2 all custom 5000 dump.edge-3_Ni-Cr.* id type x y z c_eng c_csym + +run 1000 +Per MPI rank memory allocation (min/avg/max) = 9.636 | 9.636 | 9.636 Mbytes + Step Temp Press Pxx Pyy Pzz Lx Ly Lz Volume PotEng f_mc[1] f_mc[2] + 0 2400 -187517.52 -187403.09 -187750.05 -187399.42 22.572 60.192 22.572 30667.534 -9674.3728 0 0 + 100 1668.8754 13300.763 12419.304 15568.772 11914.212 21.636248 57.724775 21.647685 27036.823 -9594.7526 24 23 + 200 1584.9699 -5686.0414 -4741.8496 -5914.7681 -6401.5064 21.729384 58.060532 21.730736 27415.923 -9571.0639 48 46 + 300 1582.0473 2806.2983 3413.4122 2716.0124 2289.4702 21.6679 58.033587 21.694744 27280.402 -9570.5549 72 69 + 400 1582.5825 845.29268 -849.61221 2123.5339 1261.9563 21.676298 58.14253 21.656418 27293.905 -9570.7948 96 93 + 500 1591.7285 -501.17955 1151.9743 -1719.3712 -936.14174 21.696367 58.157211 21.648308 27315.839 -9573.5089 120 116 + 600 1610.708 -821.74669 -1002.4957 291.88502 -1754.6294 21.730338 58.008213 21.661226 27304.8 -9579.5573 144 138 + 700 1598.5176 -590.00633 -1844.42 408.97706 -334.57602 21.712908 57.96131 21.698129 27307.281 -9575.8973 168 162 + 800 1584.3478 330.16711 666.88818 74.698331 248.91482 21.650908 58.045055 21.719838 27295.933 -9571.9268 192 186 + 900 1557.9946 1471.1207 2124.6512 1526.9937 761.71731 21.645578 58.156083 21.681637 27293.323 -9564.4385 216 207 + 1000 1582.5312 379.57005 -602.96446 2696.737 -955.06238 21.655418 58.231248 21.649581 27300.598 -9571.9879 240 227 +Loop time of 9.1632 on 4 procs for 1000 steps with 2304 atoms + +Performance: 18.858 ns/day, 1.273 hours/ns, 109.132 timesteps/s, 251.440 katom-step/s +98.5% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 7.867 | 7.9923 | 8.1311 | 4.3 | 87.22 +Neigh | 0.054997 | 0.057518 | 0.060145 | 1.0 | 0.63 +Comm | 0.017529 | 0.14801 | 0.27408 | 29.5 | 1.62 +Output | 0.00015963 | 0.00017216 | 0.00020869 | 0.0 | 0.00 +Modify | 0.95227 | 0.96325 | 0.9917 | 1.7 | 10.51 +Other | | 0.001983 | | | 0.02 + +Nlocal: 576 ave 609 max 540 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Nghost: 2161.5 ave 2173 max 2151 min +Histogram: 1 0 1 0 0 0 1 0 0 1 +Neighs: 32450.2 ave 35422 max 29271 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +FullNghs: 64900.5 ave 70800 max 58684 min +Histogram: 2 0 0 0 0 0 0 0 0 2 + +Total # of neighbors = 259602 +Ave neighs/atom = 112.67448 +Neighbor list builds = 62 +Dangerous builds = 0 + +#write_data pulse_center.data +Total wall time: 0:00:09 diff --git a/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_edge.g++.1 b/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_edge.g++.1 new file mode 100644 index 0000000000..c7ee0d41b5 --- /dev/null +++ b/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_edge.g++.1 @@ -0,0 +1,155 @@ +LAMMPS (2 Apr 2025 - Development - patch_2Apr2025-384-g88bc7dc720-modified) + using 1 OpenMP thread(s) per MPI task +# May 2025 +# Test script for MD-KMC accelerated diffusion testing in LAMMPS +# Created by Jacob Tavenner, Baylor University + +# Initiation ------------------------------------- +units metal +dimension 3 +boundary p p p +atom_style atomic + + +# Atom Definition -------------------------------- +lattice fcc 3.762 +Lattice spacing in x,y,z = 3.762 3.762 3.762 +region whole block 0 1 0 1 0 1 +create_box 2 whole +Created orthogonal box = (0 0 0) to (3.762 3.762 3.762) + 1 by 1 by 1 MPI processor grid +create_atoms 1 region whole +Created 4 atoms + using lattice units in orthogonal box = (0 0 0) to (3.762 3.762 3.762) + create_atoms CPU = 0.000 seconds + +replicate 6 16 6 +Replication is creating a 6x16x6 = 576 times larger system... + orthogonal box = (0 0 0) to (22.572 60.192 22.572) + 1 by 1 by 1 MPI processor grid + 2304 atoms + replicate CPU = 0.000 seconds + +region puck block INF INF INF 2 INF INF +set region puck type 2 +Setting atom values ... + 360 settings made for type + +# Force Fields ----------------------------------- +pair_style meam +pair_coeff * * library_2nn.meam Mo Co Ni V Fe Al Cr MoCoNiVFeAlCr_2nn.meam Ni Cr +Reading MEAM library file library_2nn.meam with DATE: 2024-08-08 +Reading MEAM potential file MoCoNiVFeAlCr_2nn.meam with DATE: 2024-08-08 + +# Settings --------------------------------------- +timestep 0.002 +thermo 100 + +# Computations ----------------------------------- +compute voroN all voronoi/atom neighbors yes + +run 0 +WARNING: No fixes with time integration, atoms won't move +For more information see https://docs.lammps.org/err0028 (src/verlet.cpp:60) +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.8 + ghost atom cutoff = 6.8 + binsize = 3.4, bins = 7 18 7 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair meam, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard + (2) pair meam, perpetual, half/full from (1) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 13.32 | 13.32 | 13.32 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 0 -9674.3728 0 -9674.3728 -212400.94 +Loop time of 1.232e-06 on 1 procs for 0 steps with 2304 atoms + +81.2% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0 | 0 | 0 | 0.0 | 0.00 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 1.232e-06 | | |100.00 + +Nlocal: 2304 ave 2304 max 2304 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 4735 ave 4735 max 4735 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 99072 ave 99072 max 99072 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 198144 ave 198144 max 198144 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 198144 +Ave neighs/atom = 86 +Neighbor list builds = 0 +Dangerous builds = 0 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe + +# Execution -------------------------------------- + +velocity all create 2400 908124 loop geom +fix temp all npt temp 1000 1000 1000 aniso 0 0 1 +fix mc all neighbor/swap 50 12 1340723 1000 3 voroN diff 2 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe f_mc[*] +#dump dump2 all custom 5000 dump.edge-3_Ni-Cr.* id type x y z c_eng c_csym + +run 1000 +Per MPI rank memory allocation (min/avg/max) = 13.32 | 13.32 | 13.32 Mbytes + Step Temp Press Pxx Pyy Pzz Lx Ly Lz Volume PotEng f_mc[1] f_mc[2] + 0 2400 -187517.52 -187464.47 -188202.62 -186885.48 22.572 60.192 22.572 30667.534 -9674.3728 0 0 + 100 1665.6154 14281.316 14426.547 14555.867 13861.534 21.637238 57.719793 21.637281 27022.733 -9594.4303 24 24 + 200 1603.3309 -7325.7341 -8878.1524 -5333.0485 -7766.0015 21.710246 58.122827 21.725933 27415.106 -9577.4545 48 48 + 300 1603.2974 207.19165 1983.4565 -1841.9518 480.07024 21.678227 58.079126 21.674033 27288.745 -9577.6391 72 69 + 400 1600.1515 810.95054 1087.969 802.04946 542.83316 21.683731 58.045848 21.678505 27285.662 -9576.6508 96 92 + 500 1629.8313 -2808.1005 -3197.9357 310.89931 -5537.265 21.683924 58.090375 21.697076 27330.229 -9585.5435 120 113 + 600 1598.8232 -67.845623 -1573.0718 -1526.7607 2896.2957 21.70213 58.12191 21.653853 27313.504 -9576.4147 144 137 + 700 1607.2185 154.66718 -1777.2469 2566.4705 -325.22208 21.712408 57.971553 21.678708 27287.033 -9579.1772 168 158 + 800 1582.559 -891.23631 -632.46037 -636.88203 -1404.3665 21.671936 58.127004 21.678224 27308.594 -9571.6663 192 180 + 900 1586.7172 -617.17083 -2495.5378 -2302.8766 2946.9018 21.658489 58.181921 21.668968 27305.771 -9572.9641 216 204 + 1000 1607.563 -389.8113 810.4908 298.84287 -2278.7676 21.624573 58.076745 21.724272 27283.183 -9579.5034 240 227 +Loop time of 31.7733 on 1 procs for 1000 steps with 2304 atoms + +Performance: 5.439 ns/day, 4.413 hours/ns, 31.473 timesteps/s, 72.514 katom-step/s +99.2% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 28.604 | 28.604 | 28.604 | 0.0 | 90.02 +Neigh | 0.21293 | 0.21293 | 0.21293 | 0.0 | 0.67 +Comm | 0.010645 | 0.010645 | 0.010645 | 0.0 | 0.03 +Output | 0.00033194 | 0.00033194 | 0.00033194 | 0.0 | 0.00 +Modify | 2.9411 | 2.9411 | 2.9411 | 0.0 | 9.26 +Other | | 0.00448 | | | 0.01 + +Nlocal: 2304 ave 2304 max 2304 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 4748 ave 4748 max 4748 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 130301 ave 130301 max 130301 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 260602 ave 260602 max 260602 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 260602 +Ave neighs/atom = 113.10851 +Neighbor list builds = 62 +Dangerous builds = 0 + +#write_data pulse_end.data +Total wall time: 0:00:31 diff --git a/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_edge.g++.4 b/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_edge.g++.4 new file mode 100644 index 0000000000..da7976d867 --- /dev/null +++ b/examples/PACKAGES/neighbor-swap/log.22May22.KMC_pulse_edge.g++.4 @@ -0,0 +1,155 @@ +LAMMPS (2 Apr 2025 - Development - patch_2Apr2025-384-g88bc7dc720-modified) + using 1 OpenMP thread(s) per MPI task +# May 2025 +# Test script for MD-KMC accelerated diffusion testing in LAMMPS +# Created by Jacob Tavenner, Baylor University + +# Initiation ------------------------------------- +units metal +dimension 3 +boundary p p p +atom_style atomic + + +# Atom Definition -------------------------------- +lattice fcc 3.762 +Lattice spacing in x,y,z = 3.762 3.762 3.762 +region whole block 0 1 0 1 0 1 +create_box 2 whole +Created orthogonal box = (0 0 0) to (3.762 3.762 3.762) + 1 by 2 by 2 MPI processor grid +create_atoms 1 region whole +Created 4 atoms + using lattice units in orthogonal box = (0 0 0) to (3.762 3.762 3.762) + create_atoms CPU = 0.000 seconds + +replicate 6 16 6 +Replication is creating a 6x16x6 = 576 times larger system... + orthogonal box = (0 0 0) to (22.572 60.192 22.572) + 1 by 4 by 1 MPI processor grid + 2304 atoms + replicate CPU = 0.000 seconds + +region puck block INF INF INF 2 INF INF +set region puck type 2 +Setting atom values ... + 360 settings made for type + +# Force Fields ----------------------------------- +pair_style meam +pair_coeff * * library_2nn.meam Mo Co Ni V Fe Al Cr MoCoNiVFeAlCr_2nn.meam Ni Cr +Reading MEAM library file library_2nn.meam with DATE: 2024-08-08 +Reading MEAM potential file MoCoNiVFeAlCr_2nn.meam with DATE: 2024-08-08 + +# Settings --------------------------------------- +timestep 0.002 +thermo 100 + +# Computations ----------------------------------- +compute voroN all voronoi/atom neighbors yes + +run 0 +WARNING: No fixes with time integration, atoms won't move +For more information see https://docs.lammps.org/err0028 (src/verlet.cpp:60) +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.8 + ghost atom cutoff = 6.8 + binsize = 3.4, bins = 7 18 7 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair meam, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard + (2) pair meam, perpetual, half/full from (1) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 9.636 | 9.636 | 9.636 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 0 -9674.3728 0 -9674.3728 -212400.94 +Loop time of 1.53e-06 on 4 procs for 0 steps with 2304 atoms + +65.4% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0 | 0 | 0 | 0.0 | 0.00 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 1.53e-06 | | |100.00 + +Nlocal: 576 ave 576 max 576 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Nghost: 2131 ave 2131 max 2131 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Neighs: 24768 ave 24768 max 24768 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +FullNghs: 49536 ave 49536 max 49536 min +Histogram: 4 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 198144 +Ave neighs/atom = 86 +Neighbor list builds = 0 +Dangerous builds = 0 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe + +# Execution -------------------------------------- + +velocity all create 2400 908124 loop geom +fix temp all npt temp 1000 1000 1000 aniso 0 0 1 +fix mc all neighbor/swap 50 12 1340723 1000 3 voroN diff 2 +thermo_style custom step temp press pxx pyy pzz lx ly lz vol pe f_mc[*] +#dump dump2 all custom 5000 dump.edge-3_Ni-Cr.* id type x y z c_eng c_csym + +run 1000 +Per MPI rank memory allocation (min/avg/max) = 9.636 | 9.636 | 9.636 Mbytes + Step Temp Press Pxx Pyy Pzz Lx Ly Lz Volume PotEng f_mc[1] f_mc[2] + 0 2400 -187517.52 -187464.47 -188202.62 -186885.48 22.572 60.192 22.572 30667.534 -9674.3728 0 0 + 100 1665.569 14271.813 14638.855 14316.569 13860.016 21.63675 57.721065 21.637799 27023.366 -9594.291 24 24 + 200 1598.6479 -6990.8349 -8574.1986 -5033.6147 -7364.6916 21.708963 58.123129 21.724821 27412.223 -9575.7322 48 47 + 300 1604.388 456.43285 1926.408 -1214.1721 657.0626 21.673369 58.090421 21.671716 27285.018 -9577.698 72 70 + 400 1601.1591 1303.6721 703.88473 1137.6607 2069.471 21.684004 58.049595 21.671161 27278.522 -9576.4811 96 94 + 500 1623.6044 -2243.2478 -2084.532 320.87709 -4966.0885 21.686171 58.097101 21.695911 27334.758 -9583.1878 120 118 + 600 1587.2041 421.60034 190.88741 -328.76599 1402.6796 21.712439 58.086039 21.655927 27312.229 -9572.559 144 141 + 700 1591.2923 32.327829 -2893.2353 1839.7574 1150.4614 21.719102 57.999862 21.666164 27292.974 -9573.9009 168 165 + 800 1580.8587 -105.51079 654.26389 -160.04168 -810.75457 21.670225 58.109245 21.684683 27306.229 -9570.6482 192 186 + 900 1570.7648 1290.088 1252.3689 255.62548 2362.2695 21.68101 58.100507 21.658755 27283.051 -9567.9864 216 209 + 1000 1598.1483 -125.35291 -3626.5479 3404.789 -154.29983 21.720146 57.952942 21.686111 27297.313 -9576.2975 240 231 +Loop time of 9.17241 on 4 procs for 1000 steps with 2304 atoms + +Performance: 18.839 ns/day, 1.274 hours/ns, 109.023 timesteps/s, 251.188 katom-step/s +98.1% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 7.7477 | 8.0143 | 8.1344 | 5.5 | 87.37 +Neigh | 0.050543 | 0.056882 | 0.05986 | 1.6 | 0.62 +Comm | 0.069784 | 0.16898 | 0.40996 | 34.2 | 1.84 +Output | 0.00015612 | 0.0001707 | 0.00021249 | 0.0 | 0.00 +Modify | 0.90628 | 0.93003 | 0.96157 | 2.2 | 10.14 +Other | | 0.002053 | | | 0.02 + +Nlocal: 576 ave 614 max 505 min +Histogram: 1 0 0 0 0 0 1 0 0 2 +Nghost: 2165.75 ave 2204 max 2132 min +Histogram: 1 0 0 0 2 0 0 0 0 1 +Neighs: 32430.8 ave 35552 max 26564 min +Histogram: 1 0 0 0 0 0 1 0 0 2 +FullNghs: 64861.5 ave 71111 max 53164 min +Histogram: 1 0 0 0 0 0 1 0 0 2 + +Total # of neighbors = 259446 +Ave neighs/atom = 112.60677 +Neighbor list builds = 62 +Dangerous builds = 0 + +#write_data pulse_end.data +Total wall time: 0:00:09 diff --git a/examples/gjf/README b/examples/gjf/README new file mode 100644 index 0000000000..f7c955080f --- /dev/null +++ b/examples/gjf/README @@ -0,0 +1,47 @@ +LAMMPS GJ THERMOSTAT EXAMPLE + +Required LAMMPS packages: EXTRA-FIX, MOLECULE, EXTRA-PAIR + +This directory contains the ingredients to run an NVT simulation using the +GJ thermostats. + +Example: + +NP=4 #number of processors +mpirun -np $NP lmp_mpi -in.gjf.vhalf + +Compared to other thermostats, the GJ thermostat allows for larger timesteps +with the correct Boltzmann statistics. A comparison using averaged properties +from this example's input file is shown below. 'X' denotes a failed simulation. +The theoretical value for KE is 1.1168 eV. + +POTENTIAL ENERGY (eV) +| Δt || 0.01 | 0.05 | 0.10 | 0.11 | 0.12 | 0.13 | 0.14 | +|===================||========|========|========|========|========|========|========| +| gjf half || -55.11 | -55.11 | -55.11 | -55.11 | -55.11 | -55.10 | -55.07 | +| gjf full || -55.11 | -55.11 | -55.11 | -55.11 | -55.11 | -55.10 | -55.07 | +| langevin || -55.11 | -55.07 | -54.87 | -54.79 | -54.65 | X | X | +| nvt (Nose-Hoover) || -55.14 | -55.07 | -54.90 | -54.84 | -54.76 | X | X | +|-------------------||--------|--------|--------|--------|--------|--------|--------| + +KINETIC ENERGY (eV) +| Δt || 0.01 | 0.05 | 0.10 | 0.11 | 0.12 | 0.13 | 0.14 | +|===================||========|========|========|========|========|========|========| +| gjf half || 1.117 | 1.116 | 1.119 | 1.119 | 1.123 | 1.136 | 1.170 | +| gjf full || 1.116 | 1.071 | 0.938 | 0.898 | 0.858 | 0.817 | 0.780 | +| langevin || 1.110 | 1.113 | 1.121 | 1.129 | 1.157 | X | X | +| nvt (Nose-Hoover) || 1.083 | 1.109 | 1.112 | 1.113 | 1.114 | X | X | +|-------------------||--------|--------|--------|--------|--------|--------|--------| + + +Script Commands: +-- +fix lang all gjf 10 10 1 26488 +-- +fix lang all gjf 10 10 1 26488 vel vfull +-- +fix nve all nve +fix lang all langevin 10 10 1 26488 +-- +fix noho all nvt temp 10 10 1 +-- \ No newline at end of file diff --git a/examples/gjf/README.md b/examples/gjf/README.md deleted file mode 100644 index e6886cb2dd..0000000000 --- a/examples/gjf/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# LAMMPS GJF-2GJ THERMOSTAT EXAMPLE - -## GJF-2GJ THERMOSTAT - -This directory contains the ingredients to run an NVT simulation using the GJF-2GJ thermostat. - -Example: -``` -NP=4 #number of processors -mpirun -np $NP lmp_mpi -in.gjf.vhalf -``` - -## Required LAMMPS packages: MOLECULE package diff --git a/examples/gjf/in.gjf.vfull b/examples/gjf/in.gjf.vfull index 40512ac37a..fad6df4a9b 100644 --- a/examples/gjf/in.gjf.vfull +++ b/examples/gjf/in.gjf.vfull @@ -1,23 +1,25 @@ -# GJF-2GJ thermostat +# GJ thermostat units metal atom_style full boundary p p p read_data argon.lmp - include ff-argon.lmp velocity all create 10 2357 mom yes dist gaussian - neighbor 1 bin timestep 0.1 -fix lang all langevin 10 10 1 26488 gjf vfull -fix nve all nve +compute myKE all ke +compute myPE all pe + +fix lang all gjf 10 10 1 26488 vel vfull method 1 -thermo 200 run 5000 +fix energies all ave/time 1 20000 20000 c_myKE c_myPE #file ave.out +thermo 2000 +run 35000 \ No newline at end of file diff --git a/examples/gjf/in.gjf.vhalf b/examples/gjf/in.gjf.vhalf index 63fb8bd467..2f5c482928 100644 --- a/examples/gjf/in.gjf.vhalf +++ b/examples/gjf/in.gjf.vhalf @@ -1,23 +1,25 @@ -# GJF-2GJ thermostat +# GJ thermostat units metal atom_style full boundary p p p read_data argon.lmp - include ff-argon.lmp velocity all create 10 2357 mom yes dist gaussian - neighbor 1 bin timestep 0.1 -fix lang all langevin 10 10 1 26488 gjf vhalf -fix nve all nve +compute myKE all ke +compute myPE all pe + +fix lang all gjf 10 10 1 26488 -thermo 200 run 5000 +fix energies all ave/time 1 20000 20000 c_myKE c_myPE #file ave.out +thermo 2000 +run 35000 \ No newline at end of file diff --git a/examples/gjf/log.15Oct19.gjf.vfull.g++.1 b/examples/gjf/log.15Oct19.gjf.vfull.g++.1 deleted file mode 100644 index e3e9cce124..0000000000 --- a/examples/gjf/log.15Oct19.gjf.vfull.g++.1 +++ /dev/null @@ -1,125 +0,0 @@ -LAMMPS (19 Sep 2019) - using 1 OpenMP thread(s) per MPI task -# GJF-2GJ thermostat - -units metal -atom_style full - -boundary p p p -read_data argon.lmp - orthogonal box = (0 0 0) to (32.146 32.146 32.146) - 1 by 1 by 1 MPI processor grid - reading atoms ... - 864 atoms - 0 = max # of 1-2 neighbors - 0 = max # of 1-3 neighbors - 0 = max # of 1-4 neighbors - 1 = max # of special neighbors - special bonds CPU = 0.000150019 secs - read_data CPU = 0.001946 secs - -include ff-argon.lmp -############################# -#Atoms types - mass - charge# -############################# -#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# - -variable Ar equal 1 - -############# -#Atom Masses# -############# - -mass ${Ar} 39.903 -mass 1 39.903 - -########################### -#Pair Potentials - Tersoff# -########################### - -pair_style lj/cubic -pair_coeff * * 0.0102701 3.42 - - -velocity all create 10 2357 mom yes dist gaussian - -neighbor 1 bin - -timestep 0.1 - -fix lang all langevin 10 10 1 26488 gjf vfull -fix nve all nve - -thermo 200 -run 5000 -Neighbor list info ... - update every 1 steps, delay 10 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 6.94072 - ghost atom cutoff = 6.94072 - binsize = 3.47036, bins = 10 10 10 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cubic, perpetual - attributes: half, newton on - pair build: half/bin/newton - stencil: half/bin/3d/newton - bin: standard -Per MPI rank memory allocation (min/avg/max) = 6.875 | 6.875 | 6.875 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 11.080223 -56.207655 0 -54.97164 37.215524 - 200 8.2588471 -55.073602 0 -54.152316 339.80416 - 400 8.1427292 -55.072244 0 -54.16391 338.91883 - 600 8.7595618 -55.066739 0 -54.089596 344.25426 - 800 8.550633 -55.148315 0 -54.194479 318.9385 - 1000 8.5394337 -55.125709 0 -54.173122 326.59471 - 1200 8.565973 -55.114892 0 -54.159345 328.5193 - 1400 8.2092914 -55.109233 0 -54.193475 329.56161 - 1600 8.209495 -55.138161 0 -54.22238 321.39971 - 1800 8.4039924 -55.13355 0 -54.196072 322.64214 - 2000 8.4548937 -55.062994 0 -54.119838 343.29888 - 2200 8.3775139 -55.13364 0 -54.199116 323.63744 - 2400 8.537332 -55.163702 0 -54.21135 315.62864 - 2600 8.672488 -55.112054 0 -54.144625 330.1106 - 2800 8.3000218 -55.147275 0 -54.221396 318.73112 - 3000 8.3552421 -55.135164 0 -54.203124 323.53075 - 3200 8.4126798 -55.135753 0 -54.197306 321.48817 - 3400 8.4986413 -55.135408 0 -54.187372 323.42951 - 3600 8.38431 -55.103932 0 -54.16865 330.68929 - 3800 8.8262454 -55.103648 0 -54.119067 332.97779 - 4000 7.9658136 -55.120402 0 -54.231803 324.9595 - 4200 8.2265544 -55.129011 0 -54.211327 323.87069 - 4400 8.1253738 -55.153089 0 -54.246691 316.304 - 4600 8.2010823 -55.124053 0 -54.20921 325.98402 - 4800 8.5512149 -55.075877 0 -54.121976 338.30137 - 5000 8.4737659 -55.158604 0 -54.213343 316.22418 -Loop time of 2.73236 on 1 procs for 5000 steps with 864 atoms - -Performance: 15810.507 ns/day, 0.002 hours/ns, 1829.920 timesteps/s -99.7% CPU use with 1 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 1.4262 | 1.4262 | 1.4262 | 0.0 | 52.20 -Bond | 0.00042836 | 0.00042836 | 0.00042836 | 0.0 | 0.02 -Neigh | 0.12819 | 0.12819 | 0.12819 | 0.0 | 4.69 -Comm | 0.058611 | 0.058611 | 0.058611 | 0.0 | 2.15 -Output | 0.00047283 | 0.00047283 | 0.00047283 | 0.0 | 0.02 -Modify | 1.0924 | 1.0924 | 1.0924 | 0.0 | 39.98 -Other | | 0.02605 | | | 0.95 - -Nlocal: 864 ave 864 max 864 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Nghost: 1593 ave 1593 max 1593 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 18143 ave 18143 max 18143 min -Histogram: 1 0 0 0 0 0 0 0 0 0 - -Total # of neighbors = 18143 -Ave neighs/atom = 20.9988 -Ave special neighs/atom = 0 -Neighbor list builds = 158 -Dangerous builds = 5 - - -Total wall time: 0:00:02 diff --git a/examples/gjf/log.15Oct19.gjf.vfull.g++.4 b/examples/gjf/log.15Oct19.gjf.vfull.g++.4 deleted file mode 100644 index 95caed5dc9..0000000000 --- a/examples/gjf/log.15Oct19.gjf.vfull.g++.4 +++ /dev/null @@ -1,125 +0,0 @@ -LAMMPS (19 Sep 2019) - using 1 OpenMP thread(s) per MPI task -# GJF-2GJ thermostat - -units metal -atom_style full - -boundary p p p -read_data argon.lmp - orthogonal box = (0 0 0) to (32.146 32.146 32.146) - 1 by 2 by 2 MPI processor grid - reading atoms ... - 864 atoms - 0 = max # of 1-2 neighbors - 0 = max # of 1-3 neighbors - 0 = max # of 1-4 neighbors - 1 = max # of special neighbors - special bonds CPU = 0.000556268 secs - read_data CPU = 0.003817 secs - -include ff-argon.lmp -############################# -#Atoms types - mass - charge# -############################# -#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# - -variable Ar equal 1 - -############# -#Atom Masses# -############# - -mass ${Ar} 39.903 -mass 1 39.903 - -########################### -#Pair Potentials - Tersoff# -########################### - -pair_style lj/cubic -pair_coeff * * 0.0102701 3.42 - - -velocity all create 10 2357 mom yes dist gaussian - -neighbor 1 bin - -timestep 0.1 - -fix lang all langevin 10 10 1 26488 gjf vfull -fix nve all nve - -thermo 200 -run 5000 -Neighbor list info ... - update every 1 steps, delay 10 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 6.94072 - ghost atom cutoff = 6.94072 - binsize = 3.47036, bins = 10 10 10 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cubic, perpetual - attributes: half, newton on - pair build: half/bin/newton - stencil: half/bin/3d/newton - bin: standard -Per MPI rank memory allocation (min/avg/max) = 6.808 | 6.808 | 6.808 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 11.080228 -56.207655 0 -54.971639 37.215541 - 200 8.4818184 -55.127334 0 -54.181174 324.96159 - 400 8.5960916 -55.09236 0 -54.133453 334.83136 - 600 8.1607556 -55.073136 0 -54.162791 339.035 - 800 8.8350489 -55.133382 0 -54.147819 324.48149 - 1000 8.5692704 -55.118463 0 -54.162548 327.26328 - 1200 8.4174147 -55.126297 0 -54.187322 324.4248 - 1400 8.6362603 -55.123075 0 -54.159688 326.7798 - 1600 8.222512 -55.153799 0 -54.236565 317.8147 - 1800 8.324523 -55.116698 0 -54.188085 327.35373 - 2000 7.9615959 -55.155825 0 -54.267697 315.37215 - 2200 8.495968 -55.083943 0 -54.136205 336.67775 - 2400 7.7926986 -55.044816 0 -54.175529 344.87758 - 2600 8.1551351 -55.069404 0 -54.159687 339.60901 - 2800 8.2593599 -55.084151 0 -54.162807 336.54935 - 3000 8.2860869 -55.110296 0 -54.185971 328.99074 - 3200 8.4074534 -55.123576 0 -54.185712 326.06823 - 3400 8.6694364 -55.128925 0 -54.161836 324.67512 - 3600 8.5718984 -55.129861 0 -54.173653 325.20586 - 3800 8.508102 -55.099093 0 -54.150001 333.91437 - 4000 8.2966658 -55.117782 0 -54.192276 327.13516 - 4200 8.7641728 -55.135792 0 -54.158136 324.00844 - 4400 8.8827909 -55.096369 0 -54.10548 335.08467 - 4600 8.7666577 -55.127213 0 -54.149279 326.15539 - 4800 8.6670762 -55.163395 0 -54.19657 316.48383 - 5000 8.1893094 -55.073756 0 -54.160226 337.95271 -Loop time of 0.870594 on 4 procs for 5000 steps with 864 atoms - -Performance: 49621.267 ns/day, 0.000 hours/ns, 5743.202 timesteps/s -96.5% CPU use with 4 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 0.33582 | 0.35125 | 0.3724 | 2.3 | 40.35 -Bond | 0.00030267 | 0.00031316 | 0.00033538 | 0.0 | 0.04 -Neigh | 0.034246 | 0.03479 | 0.035904 | 0.4 | 4.00 -Comm | 0.15068 | 0.17419 | 0.19191 | 3.6 | 20.01 -Output | 0.00044776 | 0.00054703 | 0.00083177 | 0.0 | 0.06 -Modify | 0.27679 | 0.28079 | 0.28849 | 0.9 | 32.25 -Other | | 0.02871 | | | 3.30 - -Nlocal: 216 ave 216 max 216 min -Histogram: 4 0 0 0 0 0 0 0 0 0 -Nghost: 888.75 ave 899 max 876 min -Histogram: 1 0 1 0 0 0 0 0 0 2 -Neighs: 4536 ave 4737 max 4335 min -Histogram: 2 0 0 0 0 0 0 0 0 2 - -Total # of neighbors = 18144 -Ave neighs/atom = 21 -Ave special neighs/atom = 0 -Neighbor list builds = 178 -Dangerous builds = 11 - - -Total wall time: 0:00:00 diff --git a/examples/gjf/log.15Oct19.gjf.vhalf.g++.1 b/examples/gjf/log.15Oct19.gjf.vhalf.g++.1 deleted file mode 100644 index a87b20a887..0000000000 --- a/examples/gjf/log.15Oct19.gjf.vhalf.g++.1 +++ /dev/null @@ -1,125 +0,0 @@ -LAMMPS (19 Sep 2019) - using 1 OpenMP thread(s) per MPI task -# GJF-2GJ thermostat - -units metal -atom_style full - -boundary p p p -read_data argon.lmp - orthogonal box = (0 0 0) to (32.146 32.146 32.146) - 1 by 1 by 1 MPI processor grid - reading atoms ... - 864 atoms - 0 = max # of 1-2 neighbors - 0 = max # of 1-3 neighbors - 0 = max # of 1-4 neighbors - 1 = max # of special neighbors - special bonds CPU = 0.000147804 secs - read_data CPU = 0.00194898 secs - -include ff-argon.lmp -############################# -#Atoms types - mass - charge# -############################# -#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# - -variable Ar equal 1 - -############# -#Atom Masses# -############# - -mass ${Ar} 39.903 -mass 1 39.903 - -########################### -#Pair Potentials - Tersoff# -########################### - -pair_style lj/cubic -pair_coeff * * 0.0102701 3.42 - - -velocity all create 10 2357 mom yes dist gaussian - -neighbor 1 bin - -timestep 0.1 - -fix lang all langevin 10 10 1 26488 gjf vhalf -fix nve all nve - -thermo 200 -run 5000 -Neighbor list info ... - update every 1 steps, delay 10 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 6.94072 - ghost atom cutoff = 6.94072 - binsize = 3.47036, bins = 10 10 10 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cubic, perpetual - attributes: half, newton on - pair build: half/bin/newton - stencil: half/bin/3d/newton - bin: standard -Per MPI rank memory allocation (min/avg/max) = 6.5 | 6.5 | 6.5 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 11.080223 -56.207655 0 -54.97164 37.215524 - 200 9.8808568 -55.073602 0 -53.971378 345.62207 - 400 9.8712816 -55.072244 0 -53.971088 345.11889 - 600 10.528988 -55.066739 0 -53.892214 350.60093 - 800 10.167171 -55.148315 0 -54.014152 324.73679 - 1000 10.029026 -55.125709 0 -54.006956 331.93766 - 1200 10.194424 -55.114892 0 -53.977688 334.36032 - 1400 9.3473846 -55.109233 0 -54.066518 333.64378 - 1600 9.7774071 -55.138161 0 -54.047477 327.02358 - 1800 9.9814275 -55.13355 0 -54.020107 328.30017 - 2000 10.2515 -55.062994 0 -53.919424 349.74304 - 2200 9.8126922 -55.13364 0 -54.039019 328.78521 - 2400 10.044314 -55.163702 0 -54.043244 321.03397 - 2600 10.543316 -55.112054 0 -53.935932 336.82099 - 2800 9.7874375 -55.147275 0 -54.055472 324.06626 - 3000 9.7703821 -55.135164 0 -54.045263 328.60665 - 3200 10.141958 -55.135753 0 -54.004402 327.69084 - 3400 10.160576 -55.135408 0 -54.00198 329.39063 - 3600 10.044652 -55.103932 0 -53.983436 336.64469 - 3800 10.662403 -55.103648 0 -53.914241 339.56382 - 4000 9.2921047 -55.120402 0 -54.083853 329.71671 - 4200 9.8744553 -55.129011 0 -54.027501 329.78147 - 4400 9.4085964 -55.153089 0 -54.103546 320.90673 - 4600 9.5463801 -55.124053 0 -54.05914 330.80941 - 4800 10.223884 -55.075877 0 -53.935387 344.30099 - 5000 9.6243338 -55.158604 0 -54.084996 320.3511 -Loop time of 2.29551 on 1 procs for 5000 steps with 864 atoms - -Performance: 18819.358 ns/day, 0.001 hours/ns, 2178.166 timesteps/s -99.7% CPU use with 1 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 1.4393 | 1.4393 | 1.4393 | 0.0 | 62.70 -Bond | 0.0004441 | 0.0004441 | 0.0004441 | 0.0 | 0.02 -Neigh | 0.12136 | 0.12136 | 0.12136 | 0.0 | 5.29 -Comm | 0.059342 | 0.059342 | 0.059342 | 0.0 | 2.59 -Output | 0.00046968 | 0.00046968 | 0.00046968 | 0.0 | 0.02 -Modify | 0.64937 | 0.64937 | 0.64937 | 0.0 | 28.29 -Other | | 0.02522 | | | 1.10 - -Nlocal: 864 ave 864 max 864 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Nghost: 1593 ave 1593 max 1593 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 18143 ave 18143 max 18143 min -Histogram: 1 0 0 0 0 0 0 0 0 0 - -Total # of neighbors = 18143 -Ave neighs/atom = 20.9988 -Ave special neighs/atom = 0 -Neighbor list builds = 158 -Dangerous builds = 5 - - -Total wall time: 0:00:02 diff --git a/examples/gjf/log.15Oct19.gjf.vhalf.g++.4 b/examples/gjf/log.15Oct19.gjf.vhalf.g++.4 deleted file mode 100644 index a70a67a89c..0000000000 --- a/examples/gjf/log.15Oct19.gjf.vhalf.g++.4 +++ /dev/null @@ -1,125 +0,0 @@ -LAMMPS (19 Sep 2019) - using 1 OpenMP thread(s) per MPI task -# GJF-2GJ thermostat - -units metal -atom_style full - -boundary p p p -read_data argon.lmp - orthogonal box = (0 0 0) to (32.146 32.146 32.146) - 1 by 2 by 2 MPI processor grid - reading atoms ... - 864 atoms - 0 = max # of 1-2 neighbors - 0 = max # of 1-3 neighbors - 0 = max # of 1-4 neighbors - 1 = max # of special neighbors - special bonds CPU = 0.000315903 secs - read_data CPU = 0.0653752 secs - -include ff-argon.lmp -############################# -#Atoms types - mass - charge# -############################# -#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# - -variable Ar equal 1 - -############# -#Atom Masses# -############# - -mass ${Ar} 39.903 -mass 1 39.903 - -########################### -#Pair Potentials - Tersoff# -########################### - -pair_style lj/cubic -pair_coeff * * 0.0102701 3.42 - - -velocity all create 10 2357 mom yes dist gaussian - -neighbor 1 bin - -timestep 0.1 - -fix lang all langevin 10 10 1 26488 gjf vhalf -fix nve all nve - -thermo 200 -run 5000 -Neighbor list info ... - update every 1 steps, delay 10 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 6.94072 - ghost atom cutoff = 6.94072 - binsize = 3.47036, bins = 10 10 10 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cubic, perpetual - attributes: half, newton on - pair build: half/bin/newton - stencil: half/bin/3d/newton - bin: standard -Per MPI rank memory allocation (min/avg/max) = 6.433 | 6.433 | 6.433 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 11.080228 -56.207655 0 -54.971639 37.215541 - 200 9.8046716 -55.127334 0 -54.033608 329.70647 - 400 10.174622 -55.09236 0 -53.957366 340.49331 - 600 9.9812299 -55.073136 0 -53.959714 345.56477 - 800 10.512874 -55.133382 0 -53.960655 330.4996 - 1000 9.9587885 -55.118463 0 -54.007545 332.24728 - 1200 10.236607 -55.126297 0 -53.984388 330.94998 - 1400 10.134679 -55.123075 0 -53.992537 332.15441 - 1600 9.8934078 -55.153799 0 -54.050174 323.80795 - 1800 10.064966 -55.116698 0 -53.993936 333.59644 - 2000 9.6736107 -55.155825 0 -54.076719 321.5129 - 2200 10.264537 -55.083943 0 -53.938918 343.02135 - 2400 9.5640032 -55.044816 0 -53.977937 351.23099 - 2600 9.6581077 -55.069404 0 -53.992028 344.99996 - 2800 9.9622575 -55.084151 0 -53.972846 342.6574 - 3000 9.8724909 -55.110296 0 -54.009005 334.68094 - 3200 10.032027 -55.123576 0 -54.004488 331.89534 - 3400 10.221132 -55.128925 0 -53.988742 330.24082 - 3600 10.085802 -55.129861 0 -54.004774 330.63601 - 3800 10.098545 -55.099093 0 -53.972585 339.61905 - 4000 10.000257 -55.117782 0 -54.002238 333.24569 - 4200 10.20477 -55.135792 0 -53.997435 329.17565 - 4400 10.545132 -55.096369 0 -53.920044 341.04725 - 4600 10.376108 -55.127213 0 -53.969743 331.92825 - 4800 10.247392 -55.163395 0 -54.020283 322.15219 - 5000 9.7753102 -55.073756 0 -53.983305 343.64146 -Loop time of 1.19785 on 4 procs for 5000 steps with 864 atoms - -Performance: 36064.674 ns/day, 0.001 hours/ns, 4174.152 timesteps/s -88.6% CPU use with 4 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 0.36387 | 0.38652 | 0.44086 | 5.1 | 32.27 -Bond | 0.00028847 | 0.00030833 | 0.000338 | 0.0 | 0.03 -Neigh | 0.033934 | 0.034959 | 0.036917 | 0.6 | 2.92 -Comm | 0.39292 | 0.47821 | 0.52198 | 7.3 | 39.92 -Output | 0.00050343 | 0.0012343 | 0.0023338 | 1.9 | 0.10 -Modify | 0.1605 | 0.17963 | 0.19457 | 2.9 | 15.00 -Other | | 0.117 | | | 9.77 - -Nlocal: 216 ave 216 max 216 min -Histogram: 4 0 0 0 0 0 0 0 0 0 -Nghost: 888.75 ave 899 max 876 min -Histogram: 1 0 1 0 0 0 0 0 0 2 -Neighs: 4536 ave 4737 max 4335 min -Histogram: 2 0 0 0 0 0 0 0 0 2 - -Total # of neighbors = 18144 -Ave neighs/atom = 21 -Ave special neighs/atom = 0 -Neighbor list builds = 178 -Dangerous builds = 11 - - -Total wall time: 0:00:01 diff --git a/examples/gjf/log.2Apr25.gjf.vfull.g++.1 b/examples/gjf/log.2Apr25.gjf.vfull.g++.1 new file mode 100644 index 0000000000..ca739b3a22 --- /dev/null +++ b/examples/gjf/log.2Apr25.gjf.vfull.g++.1 @@ -0,0 +1,193 @@ +LAMMPS (2 Apr 2025 - Development - d4867ab55e-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# GJ thermostat + +units metal +atom_style full + +boundary p p p +read_data argon.lmp +Reading data file ... + orthogonal box = (0 0 0) to (32.146 32.146 32.146) + 1 by 1 by 1 MPI processor grid + reading atoms ... + 864 atoms +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 0 0 + special bond factors coul: 0 0 0 + 0 = max # of 1-2 neighbors + 0 = max # of 1-3 neighbors + 0 = max # of 1-4 neighbors + 1 = max # of special neighbors + special bonds CPU = 0.000 seconds + read_data CPU = 0.007 seconds +include ff-argon.lmp +############################# +#Atoms types - mass - charge# +############################# +#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# + +variable Ar equal 1 + +############# +#Atom Masses# +############# + +mass ${Ar} 39.903 +mass 1 39.903 + +########################### +#Pair Potentials - Tersoff# +########################### + +pair_style lj/cubic +pair_coeff * * 0.0102701 3.42 + + +velocity all create 10 2357 mom yes dist gaussian +neighbor 1 bin + +timestep 0.1 + +compute myKE all ke +compute myPE all pe + +fix lang all gjf 10 10 1 26488 vel vfull method 1 + +run 5000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- GJ methods: doi:10.1080/00268976.2019.1662506 + +@Article{gronbech-jensen_complete_2020, +title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations}, +volume = {118}, +number = {8}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506}, +doi = {10.1080/00268976.2019.1662506}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels}, +year = {2020} +} + +- GJ-I vfull method: doi:10.1080/00268976.2012.760055 + +@Article{gronbech-jensen_simple_2013, +title = {A simple and effective Verlet-type algorithm for simulating Langevin dynamics}, +volume = {111}, +url = {http://www.tandfonline.com/doi/abs/10.1080/00268976.2012.760055}, +doi = {10.1080/00268976.2012.760055}, +pages = {983-991}, +number = {8}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels and Farago, Oded}, +year = {2013} +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.9407173 + ghost atom cutoff = 6.9407173 + binsize = 3.4703587, bins = 10 10 10 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cubic, perpetual + attributes: half, newton on + pair build: half/bin/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 10 -56.207652 0 -55.092137 33.341103 + 5000 8.4535562 -55.150518 0 -54.207511 318.20862 +Loop time of 2.26831 on 1 procs for 5000 steps with 864 atoms + +Performance: 19044.977 ns/day, 0.001 hours/ns, 2204.280 timesteps/s, 1.904 Matom-step/s +99.9% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.2802 | 1.2802 | 1.2802 | 0.0 | 56.44 +Bond | 0.00051213 | 0.00051213 | 0.00051213 | 0.0 | 0.02 +Neigh | 0.27007 | 0.27007 | 0.27007 | 0.0 | 11.91 +Comm | 0.057527 | 0.057527 | 0.057527 | 0.0 | 2.54 +Output | 6.3876e-05 | 6.3876e-05 | 6.3876e-05 | 0.0 | 0.00 +Modify | 0.63364 | 0.63364 | 0.63364 | 0.0 | 27.93 +Other | | 0.02635 | | | 1.16 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1593 ave 1593 max 1593 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18143 ave 18143 max 18143 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 18143 +Ave neighs/atom = 20.998843 +Ave special neighs/atom = 0 +Neighbor list builds = 258 +Dangerous builds = 0 + +fix energies all ave/time 1 20000 20000 c_myKE c_myPE #file ave.out + +thermo 2000 +run 35000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes + Step Temp E_pair E_mol TotEng Press + 5000 8.4535562 -55.150518 0 -54.207511 318.20862 + 6000 8.4899401 -55.108242 0 -54.161176 331.10703 + 8000 8.3618893 -55.092171 0 -54.15939 334.11831 + 10000 8.8684311 -55.100316 0 -54.111029 334.09931 + 12000 8.4339192 -55.07343 0 -54.132614 340.00487 + 14000 8.072393 -55.115121 0 -54.214633 327.98965 + 16000 8.3420289 -55.077813 0 -54.147247 337.74926 + 18000 8.3803911 -55.12201 0 -54.187164 326.10485 + 20000 8.4676985 -55.176339 0 -54.231754 311.57092 + 22000 8.8560138 -55.110505 0 -54.122603 330.66179 + 24000 8.3187826 -55.120592 0 -54.192619 327.01148 + 26000 8.0327666 -55.116664 0 -54.220596 326.25179 + 28000 8.3672169 -55.130413 0 -54.197037 324.2368 + 30000 8.1669275 -55.057678 0 -54.146645 344.9168 + 32000 8.3819314 -55.08989 0 -54.154873 335.45317 + 34000 8.109088 -55.17222 0 -54.267639 310.83717 + 36000 8.3048574 -55.079475 0 -54.153056 338.04291 + 38000 8.8708544 -55.108991 0 -54.119434 330.70097 + 40000 8.4012779 -55.080817 0 -54.143642 338.54326 +Loop time of 18.9699 on 1 procs for 35000 steps with 864 atoms + +Performance: 15941.040 ns/day, 0.002 hours/ns, 1845.028 timesteps/s, 1.594 Matom-step/s +99.9% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 11.593 | 11.593 | 11.593 | 0.0 | 61.11 +Bond | 0.0041801 | 0.0041801 | 0.0041801 | 0.0 | 0.02 +Neigh | 2.2671 | 2.2671 | 2.2671 | 0.0 | 11.95 +Comm | 0.42339 | 0.42339 | 0.42339 | 0.0 | 2.23 +Output | 0.00062204 | 0.00062204 | 0.00062204 | 0.0 | 0.00 +Modify | 4.4976 | 4.4976 | 4.4976 | 0.0 | 23.71 +Other | | 0.1839 | | | 0.97 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1592 ave 1592 max 1592 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18144 ave 18144 max 18144 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 18144 +Ave neighs/atom = 21 +Ave special neighs/atom = 0 +Neighbor list builds = 2122 +Dangerous builds = 0 +Total wall time: 0:00:21 diff --git a/examples/gjf/log.2Apr25.gjf.vfull.g++.4 b/examples/gjf/log.2Apr25.gjf.vfull.g++.4 new file mode 100644 index 0000000000..93466e8dfe --- /dev/null +++ b/examples/gjf/log.2Apr25.gjf.vfull.g++.4 @@ -0,0 +1,193 @@ +LAMMPS (2 Apr 2025 - Development - d4867ab55e-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# GJ thermostat + +units metal +atom_style full + +boundary p p p +read_data argon.lmp +Reading data file ... + orthogonal box = (0 0 0) to (32.146 32.146 32.146) + 1 by 2 by 2 MPI processor grid + reading atoms ... + 864 atoms +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 0 0 + special bond factors coul: 0 0 0 + 0 = max # of 1-2 neighbors + 0 = max # of 1-3 neighbors + 0 = max # of 1-4 neighbors + 1 = max # of special neighbors + special bonds CPU = 0.002 seconds + read_data CPU = 0.015 seconds +include ff-argon.lmp +############################# +#Atoms types - mass - charge# +############################# +#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# + +variable Ar equal 1 + +############# +#Atom Masses# +############# + +mass ${Ar} 39.903 +mass 1 39.903 + +########################### +#Pair Potentials - Tersoff# +########################### + +pair_style lj/cubic +pair_coeff * * 0.0102701 3.42 + + +velocity all create 10 2357 mom yes dist gaussian +neighbor 1 bin + +timestep 0.1 + +compute myKE all ke +compute myPE all pe + +fix lang all gjf 10 10 1 26488 vel vfull method 1 + +run 5000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- GJ methods: doi:10.1080/00268976.2019.1662506 + +@Article{gronbech-jensen_complete_2020, +title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations}, +volume = {118}, +number = {8}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506}, +doi = {10.1080/00268976.2019.1662506}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels}, +year = {2020} +} + +- GJ-I vfull method: doi:10.1080/00268976.2012.760055 + +@Article{gronbech-jensen_simple_2013, +title = {A simple and effective Verlet-type algorithm for simulating Langevin dynamics}, +volume = {111}, +url = {http://www.tandfonline.com/doi/abs/10.1080/00268976.2012.760055}, +doi = {10.1080/00268976.2012.760055}, +pages = {983-991}, +number = {8}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels and Farago, Oded}, +year = {2013} +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.9407173 + ghost atom cutoff = 6.9407173 + binsize = 3.4703587, bins = 10 10 10 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cubic, perpetual + attributes: half, newton on + pair build: half/bin/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 6.427 | 6.427 | 6.427 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 10 -56.207652 0 -55.092137 33.341103 + 5000 7.946377 -55.076514 0 -54.190084 337.31999 +Loop time of 2.0998 on 4 procs for 5000 steps with 864 atoms + +Performance: 20573.405 ns/day, 0.001 hours/ns, 2381.181 timesteps/s, 2.057 Matom-step/s +65.2% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.53641 | 0.54389 | 0.54721 | 0.6 | 25.90 +Bond | 0.00056487 | 0.0006195 | 0.00068462 | 0.0 | 0.03 +Neigh | 0.10567 | 0.1086 | 0.11128 | 0.7 | 5.17 +Comm | 0.96913 | 0.97758 | 0.98191 | 0.5 | 46.56 +Output | 0.00025213 | 0.00025642 | 0.00026405 | 0.0 | 0.01 +Modify | 0.25061 | 0.25105 | 0.25172 | 0.1 | 11.96 +Other | | 0.2178 | | | 10.37 + +Nlocal: 216 ave 216 max 216 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Nghost: 884.75 ave 885 max 884 min +Histogram: 1 0 0 0 0 0 0 0 0 3 +Neighs: 4536 ave 4737 max 4335 min +Histogram: 2 0 0 0 0 0 0 0 0 2 + +Total # of neighbors = 18144 +Ave neighs/atom = 21 +Ave special neighs/atom = 0 +Neighbor list builds = 273 +Dangerous builds = 0 + +fix energies all ave/time 1 20000 20000 c_myKE c_myPE #file ave.out + +thermo 2000 +run 35000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 6.428 | 6.428 | 6.428 Mbytes + Step Temp E_pair E_mol TotEng Press + 5000 7.946377 -55.076514 0 -54.190084 337.31999 + 6000 8.2565866 -55.129244 0 -54.208209 324.57967 + 8000 7.9942397 -55.101417 0 -54.209648 331.24127 + 10000 8.5413968 -55.083292 0 -54.130486 337.82599 + 12000 8.3682078 -55.090905 0 -54.157419 335.08066 + 14000 8.5082065 -55.085051 0 -54.135948 336.2765 + 16000 8.1944037 -55.090733 0 -54.176635 334.03786 + 18000 8.2607106 -55.030131 0 -54.108637 352.49892 + 20000 8.1154691 -55.104072 0 -54.198779 330.14203 + 22000 8.5592601 -55.152019 0 -54.197221 318.03507 + 24000 8.3182914 -55.115242 0 -54.187324 328.46084 + 26000 8.3691375 -55.125275 0 -54.191685 325.43673 + 28000 8.531632 -55.107097 0 -54.155381 331.42771 + 30000 8.1102222 -55.099011 0 -54.194304 332.04678 + 32000 8.5558571 -55.077016 0 -54.122598 339.87746 + 34000 8.4213946 -55.097068 0 -54.157649 333.34935 + 36000 8.0936615 -55.152202 0 -54.249342 316.20169 + 38000 7.999652 -55.048407 0 -54.156034 345.07945 + 40000 8.6699753 -55.087634 0 -54.120485 337.23709 +Loop time of 17.6726 on 4 procs for 35000 steps with 864 atoms + +Performance: 17111.263 ns/day, 0.001 hours/ns, 1980.470 timesteps/s, 1.711 Matom-step/s +65.4% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 5.0739 | 5.1178 | 5.1689 | 1.5 | 28.96 +Bond | 0.0043764 | 0.004688 | 0.0051706 | 0.4 | 0.03 +Neigh | 0.83797 | 0.85506 | 0.87554 | 1.8 | 4.84 +Comm | 6.816 | 6.8932 | 6.9215 | 1.7 | 39.00 +Output | 0.0043624 | 0.0045336 | 0.004998 | 0.4 | 0.03 +Modify | 3.3008 | 3.3033 | 3.3066 | 0.1 | 18.69 +Other | | 1.494 | | | 8.45 + +Nlocal: 216 ave 222 max 210 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Nghost: 905.5 ave 911 max 899 min +Histogram: 1 1 0 0 0 0 0 0 0 2 +Neighs: 4535.75 ave 4837 max 4218 min +Histogram: 1 0 0 1 0 0 1 0 0 1 + +Total # of neighbors = 18143 +Ave neighs/atom = 20.998843 +Ave special neighs/atom = 0 +Neighbor list builds = 2140 +Dangerous builds = 0 +Total wall time: 0:00:19 diff --git a/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 b/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 new file mode 100644 index 0000000000..569b13bad6 --- /dev/null +++ b/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 @@ -0,0 +1,192 @@ +LAMMPS (2 Apr 2025 - Development - d4867ab55e-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# GJ thermostat + +units metal +atom_style full + +boundary p p p +read_data argon.lmp +Reading data file ... + orthogonal box = (0 0 0) to (32.146 32.146 32.146) + 1 by 1 by 1 MPI processor grid + reading atoms ... + 864 atoms +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 0 0 + special bond factors coul: 0 0 0 + 0 = max # of 1-2 neighbors + 0 = max # of 1-3 neighbors + 0 = max # of 1-4 neighbors + 1 = max # of special neighbors + special bonds CPU = 0.000 seconds + read_data CPU = 0.010 seconds +include ff-argon.lmp +############################# +#Atoms types - mass - charge# +############################# +#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# + +variable Ar equal 1 + +############# +#Atom Masses# +############# + +mass ${Ar} 39.903 +mass 1 39.903 + +########################### +#Pair Potentials - Tersoff# +########################### + +pair_style lj/cubic +pair_coeff * * 0.0102701 3.42 + + +velocity all create 10 2357 mom yes dist gaussian +neighbor 1 bin + +timestep 0.1 + +compute myKE all ke +compute myPE all pe + +fix lang all gjf 10 10 1 26488 + +run 5000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- GJ methods: doi:10.1080/00268976.2019.1662506 + +@Article{gronbech-jensen_complete_2020, +title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations}, +volume = {118}, +number = {8}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506}, +doi = {10.1080/00268976.2019.1662506}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels}, +year = {2020} +} + +- GJ-I vhalf method: doi:10.1080/00268976.2019.1570369 + +@Article{jensen_accurate_2019, +title = {Accurate configurational and kinetic statistics in discrete-time Langevin systems}, +volume = {117}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1570369}, +doi = {10.1080/00268976.2019.1570369}, +number = {18}, +journal = {Molecular Physics}, +author = {Jensen, Lucas Frese Grønbech and Grønbech-Jensen, Niels}, +year = {2019} +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.9407173 + ghost atom cutoff = 6.9407173 + binsize = 3.4703587, bins = 10 10 10 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cubic, perpetual + attributes: half, newton on + pair build: half/bin/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 10 -56.207652 0 -55.092137 33.341103 + 5000 9.7731898 -55.150518 0 -54.060304 322.94195 +Loop time of 2.28421 on 1 procs for 5000 steps with 864 atoms + +Performance: 18912.438 ns/day, 0.001 hours/ns, 2188.940 timesteps/s, 1.891 Matom-step/s +99.9% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.2715 | 1.2715 | 1.2715 | 0.0 | 55.66 +Bond | 0.00057126 | 0.00057126 | 0.00057126 | 0.0 | 0.03 +Neigh | 0.27008 | 0.27008 | 0.27008 | 0.0 | 11.82 +Comm | 0.057938 | 0.057938 | 0.057938 | 0.0 | 2.54 +Output | 6.1954e-05 | 6.1954e-05 | 6.1954e-05 | 0.0 | 0.00 +Modify | 0.658 | 0.658 | 0.658 | 0.0 | 28.81 +Other | | 0.0261 | | | 1.14 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1593 ave 1593 max 1593 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18143 ave 18143 max 18143 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 18143 +Ave neighs/atom = 20.998843 +Ave special neighs/atom = 0 +Neighbor list builds = 258 +Dangerous builds = 0 + +fix energies all ave/time 1 20000 20000 c_myKE c_myPE #file ave.out + +thermo 2000 +run 35000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes + Step Temp E_pair E_mol TotEng Press + 5000 9.7731898 -55.150518 0 -54.060304 322.94195 + 6000 10.024842 -55.108242 0 -53.989956 336.6125 + 8000 10.118994 -55.092171 0 -53.963382 340.42078 + 10000 10.541359 -55.100316 0 -53.924412 340.09986 + 12000 10.023234 -55.07343 0 -53.955323 345.70551 + 14000 9.5912018 -55.115121 0 -54.045208 333.43739 + 16000 9.9450498 -55.077813 0 -53.968428 343.49906 + 18000 10.113744 -55.12201 0 -53.993806 332.32214 + 20000 9.9345204 -55.176339 0 -54.068128 316.83219 + 22000 10.585719 -55.110505 0 -53.929652 336.86599 + 24000 10.024757 -55.120592 0 -54.002315 333.13056 + 26000 9.7787474 -55.116664 0 -54.02583 332.51437 + 28000 9.6092087 -55.130413 0 -54.058491 328.69165 + 30000 9.8245787 -55.057678 0 -53.961731 350.86255 + 32000 10.066994 -55.08989 0 -53.966902 341.49724 + 34000 9.5677059 -55.17222 0 -54.104928 316.06902 + 36000 9.7252627 -55.079475 0 -53.994608 343.13769 + 38000 10.438984 -55.108991 0 -53.944506 336.32562 + 40000 10.238268 -55.080817 0 -53.938723 345.13228 +Loop time of 19.138 on 1 procs for 35000 steps with 864 atoms + +Performance: 15801.041 ns/day, 0.002 hours/ns, 1828.824 timesteps/s, 1.580 Matom-step/s +99.9% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 11.568 | 11.568 | 11.568 | 0.0 | 60.44 +Bond | 0.0042372 | 0.0042372 | 0.0042372 | 0.0 | 0.02 +Neigh | 2.2577 | 2.2577 | 2.2577 | 0.0 | 11.80 +Comm | 0.42841 | 0.42841 | 0.42841 | 0.0 | 2.24 +Output | 0.00060128 | 0.00060128 | 0.00060128 | 0.0 | 0.00 +Modify | 4.694 | 4.694 | 4.694 | 0.0 | 24.53 +Other | | 0.1852 | | | 0.97 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1592 ave 1592 max 1592 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18144 ave 18144 max 18144 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 18144 +Ave neighs/atom = 21 +Ave special neighs/atom = 0 +Neighbor list builds = 2122 +Dangerous builds = 0 +Total wall time: 0:00:21 diff --git a/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 b/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 new file mode 100644 index 0000000000..2b5e19e634 --- /dev/null +++ b/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 @@ -0,0 +1,192 @@ +LAMMPS (2 Apr 2025 - Development - d4867ab55e-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# GJ thermostat + +units metal +atom_style full + +boundary p p p +read_data argon.lmp +Reading data file ... + orthogonal box = (0 0 0) to (32.146 32.146 32.146) + 1 by 2 by 2 MPI processor grid + reading atoms ... + 864 atoms +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 0 0 + special bond factors coul: 0 0 0 + 0 = max # of 1-2 neighbors + 0 = max # of 1-3 neighbors + 0 = max # of 1-4 neighbors + 1 = max # of special neighbors + special bonds CPU = 0.002 seconds + read_data CPU = 0.015 seconds +include ff-argon.lmp +############################# +#Atoms types - mass - charge# +############################# +#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# + +variable Ar equal 1 + +############# +#Atom Masses# +############# + +mass ${Ar} 39.903 +mass 1 39.903 + +########################### +#Pair Potentials - Tersoff# +########################### + +pair_style lj/cubic +pair_coeff * * 0.0102701 3.42 + + +velocity all create 10 2357 mom yes dist gaussian +neighbor 1 bin + +timestep 0.1 + +compute myKE all ke +compute myPE all pe + +fix lang all gjf 10 10 1 26488 + +run 5000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- GJ methods: doi:10.1080/00268976.2019.1662506 + +@Article{gronbech-jensen_complete_2020, +title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations}, +volume = {118}, +number = {8}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506}, +doi = {10.1080/00268976.2019.1662506}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels}, +year = {2020} +} + +- GJ-I vhalf method: doi:10.1080/00268976.2019.1570369 + +@Article{jensen_accurate_2019, +title = {Accurate configurational and kinetic statistics in discrete-time Langevin systems}, +volume = {117}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1570369}, +doi = {10.1080/00268976.2019.1570369}, +number = {18}, +journal = {Molecular Physics}, +author = {Jensen, Lucas Frese Grønbech and Grønbech-Jensen, Niels}, +year = {2019} +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.9407173 + ghost atom cutoff = 6.9407173 + binsize = 3.4703587, bins = 10 10 10 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cubic, perpetual + attributes: half, newton on + pair build: half/bin/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 6.427 | 6.427 | 6.427 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 10 -56.207652 0 -55.092137 33.341103 + 5000 9.3726166 -55.076514 0 -54.030985 342.43571 +Loop time of 2.11818 on 4 procs for 5000 steps with 864 atoms + +Performance: 20394.822 ns/day, 0.001 hours/ns, 2360.512 timesteps/s, 2.039 Matom-step/s +63.1% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.53987 | 0.54922 | 0.56044 | 1.2 | 25.93 +Bond | 0.00058281 | 0.00063674 | 0.00075153 | 0.0 | 0.03 +Neigh | 0.10821 | 0.10912 | 0.11017 | 0.2 | 5.15 +Comm | 0.96075 | 0.97484 | 0.98645 | 1.1 | 46.02 +Output | 0.00026318 | 0.00026575 | 0.00027192 | 0.0 | 0.01 +Modify | 0.26142 | 0.2634 | 0.26465 | 0.2 | 12.44 +Other | | 0.2207 | | | 10.42 + +Nlocal: 216 ave 216 max 216 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Nghost: 884.75 ave 885 max 884 min +Histogram: 1 0 0 0 0 0 0 0 0 3 +Neighs: 4536 ave 4737 max 4335 min +Histogram: 2 0 0 0 0 0 0 0 0 2 + +Total # of neighbors = 18144 +Ave neighs/atom = 21 +Ave special neighs/atom = 0 +Neighbor list builds = 273 +Dangerous builds = 0 + +fix energies all ave/time 1 20000 20000 c_myKE c_myPE #file ave.out + +thermo 2000 +run 35000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 6.428 | 6.428 | 6.428 Mbytes + Step Temp E_pair E_mol TotEng Press + 5000 9.3726166 -55.076514 0 -54.030985 342.43571 + 6000 9.6911866 -55.129244 0 -54.048177 329.72537 + 8000 9.7296551 -55.101417 0 -54.016059 337.46595 + 10000 10.098808 -55.083292 0 -53.956755 343.4122 + 12000 10.114344 -55.090905 0 -53.962635 341.3438 + 14000 10.230012 -55.085051 0 -53.943878 342.45237 + 16000 9.5989709 -55.090733 0 -54.019954 339.07584 + 18000 10.016071 -55.030131 0 -53.912824 358.79514 + 20000 9.7197057 -55.104072 0 -54.019824 335.89619 + 22000 9.959647 -55.152019 0 -54.041005 323.05805 + 24000 10.075138 -55.115242 0 -53.991345 334.76239 + 26000 10.227192 -55.125275 0 -53.984416 332.10131 + 28000 10.177109 -55.107097 0 -53.971825 337.32979 + 30000 9.521036 -55.099011 0 -54.036925 337.10716 + 32000 10.265633 -55.077016 0 -53.93187 346.01018 + 34000 10.173978 -55.097068 0 -53.962146 339.63562 + 36000 9.6032778 -55.152202 0 -54.080942 321.61646 + 38000 9.8802995 -55.048407 0 -53.946245 351.82506 + 40000 10.372288 -55.087634 0 -53.93059 343.34304 +Loop time of 17.867 on 4 procs for 35000 steps with 864 atoms + +Performance: 16925.013 ns/day, 0.001 hours/ns, 1958.914 timesteps/s, 1.693 Matom-step/s +65.3% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 5.0932 | 5.1683 | 5.2256 | 2.5 | 28.93 +Bond | 0.0044473 | 0.0048347 | 0.0058137 | 0.8 | 0.03 +Neigh | 0.85262 | 0.8601 | 0.87438 | 0.9 | 4.81 +Comm | 6.8164 | 6.8981 | 6.9859 | 2.6 | 38.61 +Output | 0.0046884 | 0.0047093 | 0.0047322 | 0.0 | 0.03 +Modify | 3.4107 | 3.4186 | 3.4248 | 0.3 | 19.13 +Other | | 1.512 | | | 8.47 + +Nlocal: 216 ave 222 max 210 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Nghost: 905.5 ave 911 max 899 min +Histogram: 1 1 0 0 0 0 0 0 0 2 +Neighs: 4535.75 ave 4837 max 4218 min +Histogram: 1 0 0 1 0 0 1 0 0 1 + +Total # of neighbors = 18143 +Ave neighs/atom = 20.998843 +Ave special neighs/atom = 0 +Neighbor list builds = 2140 +Dangerous builds = 0 +Total wall time: 0:00:21 diff --git a/examples/granular/in.tableting.200 b/examples/granular/in.tableting.200 index 41723c72af..58fc8dde3e 100644 --- a/examples/granular/in.tableting.200 +++ b/examples/granular/in.tableting.200 @@ -28,19 +28,20 @@ variable dieHeight equal 1e-2 pair_style granular -# mdr = E, nu, Y, gamma, psi_b, CoR +# mdr = E, nu, Y, gamma, psi_b, damp variable YoungsModulus equal 5e6 variable YieldStress equal 1.9e5 variable PoissonsRatio equal 0.4 variable SurfaceEnergy equal 2 variable SurfaceEnergyWall equal 0.0 -variable CoR equal 0.5 variable psi_b equal 0.5 +variable damp equal 0.2 +variable damp_type equal 1 # linear_history = k_t, x_gammat, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} variable kt_wall equal 2/7*${YoungsModulus}*${atomRadius} -variable xgammat equal 0.0 +variable xgammat equal 1.0 variable mu_s equal 0.7 variable mu_s_wall equal 0.1 @@ -49,14 +50,17 @@ variable mu_roll equal 0.6 variable k_roll equal 2.25*${mu_roll}*${mu_roll}*${YoungsModulus}*${atomRadius} variable gamma_roll equal 0.0 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} damping none +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} & + damping mdr ${damp_type} & + tangential linear_history ${kt} ${xgammat} ${mu_s} & + rolling sds ${k_roll} ${gamma_roll} ${mu_roll} ######################################### ADD DIE AND PUNCH WALLS ############################################ variable disp_upper equal 0.0 variable disp_lower equal 0.0 -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${CoR} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} damping none" +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" variable dieHeight2 equal 2*${dieHeight} @@ -73,7 +77,7 @@ variable avgUpperPunchForce equal c_avgUpperPunchForce compute avgLowerPunchForce all reduce sum f_lowerPunch[4] variable avgLowerPunchForce equal c_avgLowerPunchForce -fix printFD all print 1 "${disp_upper} ${avgUpperPunchForce} ${avgLowerPunchForce}" file punch_force_disp_tableting200.csv screen no +#fix printFD all print 1 "${disp_upper} ${avgUpperPunchForce} ${avgLowerPunchForce}" file punch_force_disp_tableting200.csv screen no ##################################### INTEGRATION AND GRAVITY ################################################# @@ -109,13 +113,13 @@ variable syy_ave equal c_sigmayy_ave variable szz_ave equal c_sigmazz_ave variable Vparticles equal c_Velas_sum -fix log all print 1 "${sxx_ave} ${syy_ave} ${szz_ave} ${Vparticles}" file average_normal_stresses_tableting200.csv screen no -dump dumpParticles all custom ${output_rate} tableting200.dump id type mass diameter x y z vx vy vz fx fy fz c_ke c_sigmaxx c_sigmayy c_sigmazz +#fix log all print 1 "${sxx_ave} ${syy_ave} ${szz_ave} ${Vparticles}" file average_normal_stresses_tableting200.csv screen no +#dump dumpParticles all custom ${output_rate} tableting200.dump id type mass diameter x y z vx vy vz fx fy fz c_ke c_sigmaxx c_sigmayy c_sigmazz #dump dumpParticlesVTK all vtk ${output_rate} post/particles_*.vtk id x y z fx fy fz vx vy vz c_ke radius c_sigmaxx c_sigmayy c_sigmazz ############################################## RUN SIMULATION ################################################# -variable upper_punch_stroke equal 0.6733*${dieHeight} +variable upper_punch_stroke equal 0.7*${dieHeight} variable vel_upper equal 0.25 variable settling_steps equal round(0.02/dt) @@ -146,4 +150,4 @@ run ${ejection_steps} variable disp_lower equal ${dieHeight} variable disp_upper equal ${dieHeight}*0.9 variable max_disp equal ${dieRadius}*0.75 -run ${free_float_steps} \ No newline at end of file +run ${free_float_steps} diff --git a/examples/granular/in.triaxial.compaction.12 b/examples/granular/in.triaxial.compaction.12 index eee9a2bfd8..0a35ab3c0a 100644 --- a/examples/granular/in.triaxial.compaction.12 +++ b/examples/granular/in.triaxial.compaction.12 @@ -1,7 +1,7 @@ ############################### SIMULATION SETTINGS ################################################### atom_style sphere 1 -atom_modify map array +atom_modify map array comm_modify vel yes units si newton off @@ -24,20 +24,23 @@ variable atomRadius equal 0.5 pair_style granular -# mdr = E, nu, Y, gamma, psi_b, CoR +# mdr = E, nu, Y, gamma, psi_b, damp variable YoungsModulus equal 1e9 variable PoissonsRatio equal 0.3 variable YieldStress equal 50e6 variable SurfaceEnergy equal 0.0 variable psi_b equal 0.5 -variable CoR equal 0.5 +variable damp equal 0.2 +variable damp_type equal 1 # linear_history = k_t, x_gamma,t, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} variable xgammat equal 0.0 variable mu_s equal 0.5 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} damping none +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} & + damping mdr ${damp_type} & + tangential linear_history ${kt} ${xgammat} ${mu_s} ######################################### ADD IN PLANES ################################################ @@ -54,7 +57,7 @@ region plane_xz_neg plane 0 -${halfBoxWidth} 0 0 1 0 side in move NULL v_plane_d region plane_xy_pos plane 0 0 ${halfBoxWidth} 0 0 -1 side in move NULL NULL v_plane_disp_neg units box region plane_xy_neg plane 0 0 -${halfBoxWidth} 0 0 1 side in move NULL NULL v_plane_disp units box -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} damping none" +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} " fix plane_yz_pos all wall/gran/region ${wall_contact_string} region plane_yz_pos contacts fix plane_yz_neg all wall/gran/region ${wall_contact_string} region plane_yz_neg contacts @@ -72,12 +75,12 @@ variable plane_xz_neg_force equal c_plane_xz_neg_force compute plane_yz_neg_force all reduce sum f_plane_yz_neg[2] variable plane_yz_neg_force equal c_plane_yz_neg_force -fix print1 all print 1 "${plane_disp} ${plane_xy_neg_force} ${plane_xz_neg_force} ${plane_yz_neg_force}" file force_disp_triaxial12.csv screen no +#fix print1 all print 1 "${plane_disp} ${plane_xy_neg_force} ${plane_xz_neg_force} ${plane_yz_neg_force}" file force_disp_triaxial12.csv screen no -######################################## SCREEN OUTPUT #################################################### +######################################## SCREEN OUTPUT #################################################### compute 1 all erotate/sphere -thermo_style custom dt step atoms ke c_1 vol +thermo_style custom dt step atoms ke c_1 vol thermo 100 thermo_modify lost ignore norm no @@ -89,8 +92,8 @@ variable compression_steps equal round(${disp_max}/${ddisp}) variable output_rate equal round(${compression_steps}/100) ##################################### SET UP DUMP OUTPUTS #################################################### - -dump dumpParticles all custom ${output_rate} triaxial_compaction_12.dump id type mass x y z vx vy vz fx fy fz radius + +#dump dumpParticles all custom ${output_rate} triaxial_compaction_12.dump id type mass x y z vx vy vz fx fy fz radius #dump dmp all vtk ${output_rate} post/triaxial12particles_*.vtk id type mass x y z vx vy vz fx fy fz radius #################################### COMPRESS THE PARTICLES ################################################## @@ -101,7 +104,7 @@ run 0 compute Ac_1_12 particles_1_12 pair/local p13 cutoff radius compute Ac_1_12_sum particles_1_12 reduce sum c_Ac_1_12 inputs local variable Ac_1_12 equal c_Ac_1_12_sum -fix logArea all print 100 "${plane_disp} ${Ac_1_12}" file pair_1_12_contact_area_triaxial12.csv screen no +#fix logArea all print 100 "${plane_disp} ${Ac_1_12}" file pair_1_12_contact_area_triaxial12.csv screen no variable plane_disp equal ${ddisp}*elapsed variable plane_disp_neg equal -${ddisp}*elapsed diff --git a/examples/granular/log.4Feb25.tableting.200.g++.1 b/examples/granular/log.4Feb25.tableting.200.g++.1 new file mode 100644 index 0000000000..c164f3dbee --- /dev/null +++ b/examples/granular/log.4Feb25.tableting.200.g++.1 @@ -0,0 +1,795 @@ +LAMMPS (4 Feb 2025 - Development - patch_5May2020-22356-g0c29a0a0c9-modified) +##################################### SIMULATION SETTINGS ################################################### + +atom_style sphere 1 +atom_modify map array +comm_modify vel yes +units si +newton off +neighbor 1.0e-3 bin +neigh_modify every 10 delay 60 check no +timestep 4e-6 +#processors 2 2 1 + +############################## SIMULATION BOUNDING BOX AND INSERT PARTICLES ################################# + +boundary f f f +read_data spheres200.data +Reading data file ... + orthogonal box = (-0.005 -0.005 -0.001) to (0.005 0.005 0.02) + 1 by 1 by 1 MPI processor grid + reading atoms ... + 200 atoms + read_data CPU = 0.024 seconds + +#################################### ADD DIE AND ATOM PARAMETERIZATION ###################################### + +variable atomRadius equal 0.44e-3*1.25 +variable atomDiameter equal 2*${atomRadius} +variable atomDiameter equal 2*0.00055 +variable atomDensity equal 1560 +variable atomMassAvg equal ${atomDensity}*4.0/3.0*PI*${atomRadius}^3.0 +variable atomMassAvg equal 1560*4.0/3.0*PI*${atomRadius}^3.0 +variable atomMassAvg equal 1560*4.0/3.0*PI*0.00055^3.0 +variable dieRadius equal 4e-3 +variable dieHeight equal 1e-2 + +############################## PARTICLE MATERIAL PROPERTIES AND FORCE MODEL ################################## + +pair_style granular + +# mdr = E, nu, Y, gamma, psi_b, damp +variable YoungsModulus equal 5e6 +variable YieldStress equal 1.9e5 +variable PoissonsRatio equal 0.4 +variable SurfaceEnergy equal 2 +variable SurfaceEnergyWall equal 0.0 +variable psi_b equal 0.5 +variable damp equal 0.2 +variable damp_type equal 1 + +# linear_history = k_t, x_gammat, mu_s +variable kt equal 2/7*${YoungsModulus}*${atomRadius} +variable kt equal 2/7*5000000*${atomRadius} +variable kt equal 2/7*5000000*0.00055 +variable kt_wall equal 2/7*${YoungsModulus}*${atomRadius} +variable kt_wall equal 2/7*5000000*${atomRadius} +variable kt_wall equal 2/7*5000000*0.00055 +variable xgammat equal 1.0 +variable mu_s equal 0.7 +variable mu_s_wall equal 0.1 + +# sds = mu_roll, k_roll, gamma_roll +variable mu_roll equal 0.6 +variable k_roll equal 2.25*${mu_roll}*${mu_roll}*${YoungsModulus}*${atomRadius} +variable k_roll equal 2.25*0.6*${mu_roll}*${YoungsModulus}*${atomRadius} +variable k_roll equal 2.25*0.6*0.6*${YoungsModulus}*${atomRadius} +variable k_roll equal 2.25*0.6*0.6*5000000*${atomRadius} +variable k_roll equal 2.25*0.6*0.6*5000000*0.00055 +variable gamma_roll equal 0.0 + +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.7 rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 0 ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 0 0.6 + +######################################### ADD DIE AND PUNCH WALLS ############################################ + +variable disp_upper equal 0.0 +variable disp_lower equal 0.0 + +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" +granular mdr 5000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 + +variable dieHeight2 equal 2*${dieHeight} +variable dieHeight2 equal 2*0.01 + +region lowerPunch plane 0 0 0 0 0 1 side in units box move NULL NULL v_disp_lower units box +region upperPunch plane 0 0 ${dieHeight} 0 0 -1 side in move NULL NULL v_disp_upper units box +region upperPunch plane 0 0 0.01 0 0 -1 side in move NULL NULL v_disp_upper units box +region die cylinder z 0 0 ${dieRadius} 0 ${dieHeight2} side in units box +region die cylinder z 0 0 0.004 0 ${dieHeight2} side in units box +region die cylinder z 0 0 0.004 0 0.02 side in units box + +fix lowerPunch all wall/gran/region ${wall_contact_string} region lowerPunch contacts +fix lowerPunch all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region lowerPunch contacts +fix upperPunch all wall/gran/region ${wall_contact_string} region upperPunch contacts +fix upperPunch all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region upperPunch contacts +fix die all wall/gran/region ${wall_contact_string} region die contacts +fix die all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region die contacts + +compute avgUpperPunchForce all reduce sum f_upperPunch[4] +variable avgUpperPunchForce equal c_avgUpperPunchForce +compute avgLowerPunchForce all reduce sum f_lowerPunch[4] +variable avgLowerPunchForce equal c_avgLowerPunchForce + +#fix printFD all print 1 "${disp_upper} ${avgUpperPunchForce} ${avgLowerPunchForce}" file punch_force_disp_tableting200.csv screen no + +##################################### INTEGRATION AND GRAVITY ################################################# + +fix 1 all nve/sphere +fix grav all gravity 9.81 vector 0 0 -1 + +########################################### SCREEN OUTPUT #################################################### + +compute 1 all erotate/sphere +thermo_style custom dt step atoms ke vol v_disp_upper +thermo 100 +thermo_modify lost ignore norm no + +##################################### SET UP DUMP OUTPUTS #################################################### + +compute ke all ke/atom +variable output_rate equal round(1e-3/dt) + +run 0 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- MDR contact model command: (i) https://doi.org/10.1016/j.jmps.2023.105492 || (ii) https://doi.org/10.1016/j.jmps.2023.105493 || (iii) https://doi.org/10.31224/4289 + +@Article{zunker2024mechanicallyI, + author = {Zunker, William and Kamrin, Ken}, + title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles, + Part I: Utilizing the method of dimensionality reduction}, + journal = {Journal of the Mechanics and Physics of Solids}, + year = {2024}, + volume = {183}, + pages = {105492}, +} + +@Article{zunker2024mechanicallyII, + author = {Zunker, William and Kamrin, Ken}, + title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles, + Part II: Contact under high compaction—modeling a bulk elastic response}, + journal = {Journal of the Mechanics and Physics of Solids}, + year = {2024}, + volume = {183}, + pages = {105493}, +} + +@Article{zunker2025experimentally, + author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken}, + title = {Experimentally validated DEM for large deformation powder compaction: + mechanically-derived contact model and screening of non-physical contacts}, + journal = {Powder Technology}, + year = {2025}, + pages = {120972}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 10 steps, delay = 60 steps, check = no + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 0.002318 + ghost atom cutoff = 0.002318 + binsize = 0.001159, bins = 9 9 19 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair granular, perpetual + attributes: half, newton off, size, history + pair build: half/size/bin/atomonly/newtoff + stencil: full/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 0 200 0 2.1e-06 0 +Loop time of 7.43e-07 on 1 procs for 0 steps with 200 atoms + +134.6% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0 | 0 | 0 | 0.0 | 0.00 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 7.43e-07 | | |100.00 + +Nlocal: 200 ave 200 max 200 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 1341 ave 1341 max 1341 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 1341 +Ave neighs/atom = 6.705 +Neighbor list builds = 0 +Dangerous builds not checked + +compute sigmaxx all property/atom d_sigmaxx +compute sigmayy all property/atom d_sigmayy +compute sigmazz all property/atom d_sigmazz +compute Velas all property/atom d_Velas + +compute sigmaxx_ave all reduce ave c_sigmaxx +compute sigmayy_ave all reduce ave c_sigmayy +compute sigmazz_ave all reduce ave c_sigmazz +compute Velas_sum all reduce sum c_Velas + +variable sxx_ave equal c_sigmaxx_ave +variable syy_ave equal c_sigmayy_ave +variable szz_ave equal c_sigmazz_ave +variable Vparticles equal c_Velas_sum + +#fix log all print 1 "${sxx_ave} ${syy_ave} ${szz_ave} ${Vparticles}" file average_normal_stresses_tableting200.csv screen no +#dump dumpParticles all custom ${output_rate} tableting200.dump id type mass diameter x y z vx vy vz fx fy fz c_ke c_sigmaxx c_sigmayy c_sigmazz +#dump dumpParticlesVTK all vtk ${output_rate} post/particles_*.vtk id x y z fx fy fz vx vy vz c_ke radius c_sigmaxx c_sigmayy c_sigmazz + +############################################## RUN SIMULATION ################################################# + +variable upper_punch_stroke equal 0.7*${dieHeight} +variable upper_punch_stroke equal 0.7*0.01 +variable vel_upper equal 0.25 + +variable settling_steps equal round(0.02/dt) +variable compression_steps equal 2*round(${upper_punch_stroke}/${vel_upper}/dt) +variable compression_steps equal 2*round(0.007/${vel_upper}/dt) +variable compression_steps equal 2*round(0.007/0.25/dt) +variable ejection_steps equal ${compression_steps} +variable ejection_steps equal 14000 +variable free_float_steps equal round(0.02/dt) + +##### SETTLING ##### + +run ${settling_steps} +run 5000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 0 200 0 2.1e-06 0 + 4e-06 100 200 1.5945503e-09 2.1e-06 0 + 4e-06 200 200 6.3750614e-09 2.1e-06 0 + 4e-06 300 200 1.4225143e-08 2.1e-06 0 + 4e-06 400 200 2.5255561e-08 2.1e-06 0 + 4e-06 500 200 3.947508e-08 2.1e-06 0 + 4e-06 600 200 5.6839079e-08 2.1e-06 0 + 4e-06 700 200 7.7346494e-08 2.1e-06 0 + 4e-06 800 200 1.0075645e-07 2.1e-06 0 + 4e-06 900 200 1.2660105e-07 2.1e-06 0 + 4e-06 1000 200 1.5571123e-07 2.1e-06 0 + 4e-06 1100 200 1.8785107e-07 2.1e-06 0 + 4e-06 1200 200 2.2200974e-07 2.1e-06 0 + 4e-06 1300 200 2.6009223e-07 2.1e-06 0 + 4e-06 1400 200 3.0148646e-07 2.1e-06 0 + 4e-06 1500 200 3.4269724e-07 2.1e-06 0 + 4e-06 1600 200 3.8502938e-07 2.1e-06 0 + 4e-06 1700 200 4.2763891e-07 2.1e-06 0 + 4e-06 1800 200 4.6779321e-07 2.1e-06 0 + 4e-06 1900 200 5.1285578e-07 2.1e-06 0 + 4e-06 2000 200 5.6630973e-07 2.1e-06 0 + 4e-06 2100 200 6.1904302e-07 2.1e-06 0 + 4e-06 2200 200 6.7462868e-07 2.1e-06 0 + 4e-06 2300 200 7.3066636e-07 2.1e-06 0 + 4e-06 2400 200 7.7407334e-07 2.1e-06 0 + 4e-06 2500 200 8.3353557e-07 2.1e-06 0 + 4e-06 2600 200 9.0017986e-07 2.1e-06 0 + 4e-06 2700 200 9.5154909e-07 2.1e-06 0 + 4e-06 2800 200 1.0110977e-06 2.1e-06 0 + 4e-06 2900 200 1.0661364e-06 2.1e-06 0 + 4e-06 3000 200 1.1226841e-06 2.1e-06 0 + 4e-06 3100 200 1.1703917e-06 2.1e-06 0 + 4e-06 3200 200 1.2254551e-06 2.1e-06 0 + 4e-06 3300 200 1.2239859e-06 2.1e-06 0 + 4e-06 3400 200 1.273437e-06 2.1e-06 0 + 4e-06 3500 200 1.3357598e-06 2.1e-06 0 + 4e-06 3600 200 1.3949477e-06 2.1e-06 0 + 4e-06 3700 200 1.459988e-06 2.1e-06 0 + 4e-06 3800 200 1.5053806e-06 2.1e-06 0 + 4e-06 3900 200 1.4952453e-06 2.1e-06 0 + 4e-06 4000 200 1.5037857e-06 2.1e-06 0 + 4e-06 4100 200 1.5225204e-06 2.1e-06 0 + 4e-06 4200 200 1.5375323e-06 2.1e-06 0 + 4e-06 4300 200 1.5552328e-06 2.1e-06 0 + 4e-06 4400 200 1.581097e-06 2.1e-06 0 + 4e-06 4500 200 1.6066427e-06 2.1e-06 0 + 4e-06 4600 200 1.6061944e-06 2.1e-06 0 + 4e-06 4700 200 1.6110891e-06 2.1e-06 0 + 4e-06 4800 200 1.6072997e-06 2.1e-06 0 + 4e-06 4900 200 1.5907992e-06 2.1e-06 0 + 4e-06 5000 200 1.5501104e-06 2.1e-06 0 +Loop time of 0.592588 on 1 procs for 5000 steps with 200 atoms + +99.4% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.20465 | 0.20465 | 0.20465 | 0.0 | 34.53 +Neigh | 0.013252 | 0.013252 | 0.013252 | 0.0 | 2.24 +Comm | 0.00037594 | 0.00037594 | 0.00037594 | 0.0 | 0.06 +Output | 0.00037454 | 0.00037454 | 0.00037454 | 0.0 | 0.06 +Modify | 0.37295 | 0.37295 | 0.37295 | 0.0 | 62.93 +Other | | 0.0009914 | | | 0.17 + +Nlocal: 200 ave 200 max 200 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 1632 ave 1632 max 1632 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 1632 +Ave neighs/atom = 8.16 +Neighbor list builds = 83 +Dangerous builds not checked + +##### Compression & Release ##### + +variable punch_frequency equal PI/2/(dt*${compression_steps}/2) +variable punch_frequency equal PI/2/(dt*14000/2) +variable disp_upper equal -${upper_punch_stroke}*sin(${punch_frequency}*elapsed*dt) +variable disp_upper equal -0.007*sin(${punch_frequency}*elapsed*dt) +variable disp_upper equal -0.007*sin(56.0998688141035*elapsed*dt) +variable short_release equal round(${compression_steps}*1.0) +variable short_release equal round(14000*1.0) +run ${short_release} +run 14000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 5000 200 1.5501104e-06 2.1e-06 0 + 4e-06 5100 200 1.5146077e-06 2.1e-06 -0.00015706645 + 4e-06 5200 200 1.4902158e-06 2.1e-06 -0.00031405381 + 4e-06 5300 200 1.3871134e-06 2.1e-06 -0.00047088304 + 4e-06 5400 200 1.3531184e-06 2.1e-06 -0.00062747516 + 4e-06 5500 200 1.3154278e-06 2.1e-06 -0.00078375133 + 4e-06 5600 200 1.2461265e-06 2.1e-06 -0.00093963286 + 4e-06 5700 200 1.1840322e-06 2.1e-06 -0.0010950413 + 4e-06 5800 200 1.083844e-06 2.1e-06 -0.0012498983 + 4e-06 5900 200 9.8572649e-07 2.1e-06 -0.0014041259 + 4e-06 6000 200 8.6605656e-07 2.1e-06 -0.0015576465 + 4e-06 6100 200 7.6694391e-07 2.1e-06 -0.0017103828 + 4e-06 6200 200 7.1292979e-07 2.1e-06 -0.0018622579 + 4e-06 6300 200 6.475067e-07 2.1e-06 -0.0020131953 + 4e-06 6400 200 5.378202e-07 2.1e-06 -0.002163119 + 4e-06 6500 200 4.5668598e-07 2.1e-06 -0.0023119534 + 4e-06 6600 200 3.1208987e-07 2.1e-06 -0.0024596238 + 4e-06 6700 200 2.2996407e-07 2.1e-06 -0.0026060556 + 4e-06 6800 200 1.658813e-07 2.1e-06 -0.0027511752 + 4e-06 6900 200 1.4495016e-07 2.1e-06 -0.0028949095 + 4e-06 7000 200 1.6172966e-07 2.1e-06 -0.0030371862 + 4e-06 7100 200 4.6620591e-07 2.1e-06 -0.0031779335 + 4e-06 7200 200 6.8121833e-07 2.1e-06 -0.0033170806 + 4e-06 7300 200 1.5506154e-06 2.1e-06 -0.0034545575 + 4e-06 7400 200 2.5919669e-06 2.1e-06 -0.0035902949 + 4e-06 7500 200 2.9403576e-06 2.1e-06 -0.0037242245 + 4e-06 7600 200 2.7726732e-06 2.1e-06 -0.0038562789 + 4e-06 7700 200 2.6586936e-06 2.1e-06 -0.0039863915 + 4e-06 7800 200 2.7059447e-06 2.1e-06 -0.0041144968 + 4e-06 7900 200 2.8454301e-06 2.1e-06 -0.0042405303 + 4e-06 8000 200 2.7747574e-06 2.1e-06 -0.0043644286 + 4e-06 8100 200 2.6329747e-06 2.1e-06 -0.0044861293 + 4e-06 8200 200 2.3654294e-06 2.1e-06 -0.0046055711 + 4e-06 8300 200 2.616465e-06 2.1e-06 -0.0047226938 + 4e-06 8400 200 2.6920973e-06 2.1e-06 -0.0048374385 + 4e-06 8500 200 2.6041158e-06 2.1e-06 -0.0049497475 + 4e-06 8600 200 1.8236056e-06 2.1e-06 -0.005059564 + 4e-06 8700 200 2.1290462e-06 2.1e-06 -0.005166833 + 4e-06 8800 200 1.8723934e-06 2.1e-06 -0.0052715003 + 4e-06 8900 200 1.7196474e-06 2.1e-06 -0.0053735132 + 4e-06 9000 200 1.558001e-06 2.1e-06 -0.0054728204 + 4e-06 9100 200 1.1714433e-06 2.1e-06 -0.0055693718 + 4e-06 9200 200 1.7973167e-06 2.1e-06 -0.005663119 + 4e-06 9300 200 1.4951874e-06 2.1e-06 -0.0057540145 + 4e-06 9400 200 1.197557e-06 2.1e-06 -0.0058420128 + 4e-06 9500 200 1.1638085e-06 2.1e-06 -0.0059270694 + 4e-06 9600 200 1.2591061e-06 2.1e-06 -0.0060091416 + 4e-06 9700 200 1.2747299e-06 2.1e-06 -0.0060881879 + 4e-06 9800 200 1.2424243e-06 2.1e-06 -0.0061641687 + 4e-06 9900 200 1.1624586e-06 2.1e-06 -0.0062370457 + 4e-06 10000 200 1.0724272e-06 2.1e-06 -0.0063067821 + 4e-06 10100 200 1.0806622e-06 2.1e-06 -0.0063733428 + 4e-06 10200 200 9.2046484e-07 2.1e-06 -0.0064366944 + 4e-06 10300 200 8.1801156e-07 2.1e-06 -0.0064968049 + 4e-06 10400 200 7.74927e-07 2.1e-06 -0.0065536441 + 4e-06 10500 200 6.85447e-07 2.1e-06 -0.0066071833 + 4e-06 10600 200 5.4693931e-07 2.1e-06 -0.0066573956 + 4e-06 10700 200 4.5275522e-07 2.1e-06 -0.0067042557 + 4e-06 10800 200 4.2807826e-07 2.1e-06 -0.00674774 + 4e-06 10900 200 3.5676739e-07 2.1e-06 -0.0067878266 + 4e-06 11000 200 2.9448839e-07 2.1e-06 -0.0068244954 + 4e-06 11100 200 2.7397196e-07 2.1e-06 -0.0068577278 + 4e-06 11200 200 1.8313029e-07 2.1e-06 -0.0068875071 + 4e-06 11300 200 1.4616679e-07 2.1e-06 -0.0069138184 + 4e-06 11400 200 1.0916404e-07 2.1e-06 -0.0069366483 + 4e-06 11500 200 7.4608897e-08 2.1e-06 -0.0069559855 + 4e-06 11600 200 4.9799693e-08 2.1e-06 -0.0069718201 + 4e-06 11700 200 2.996701e-08 2.1e-06 -0.0069841441 + 4e-06 11800 200 1.1810054e-08 2.1e-06 -0.0069929515 + 4e-06 11900 200 3.9455661e-09 2.1e-06 -0.0069982376 + 4e-06 12000 200 7.0818836e-11 2.1e-06 -0.007 + 4e-06 12100 200 3.989114e-09 2.1e-06 -0.0069982376 + 4e-06 12200 200 1.0481589e-08 2.1e-06 -0.0069929515 + 4e-06 12300 200 2.3561653e-08 2.1e-06 -0.0069841441 + 4e-06 12400 200 4.1819363e-08 2.1e-06 -0.0069718201 + 4e-06 12500 200 6.5328826e-08 2.1e-06 -0.0069559855 + 4e-06 12600 200 9.3738095e-08 2.1e-06 -0.0069366483 + 4e-06 12700 200 1.3058219e-07 2.1e-06 -0.0069138184 + 4e-06 12800 200 1.7668602e-07 2.1e-06 -0.0068875071 + 4e-06 12900 200 2.1482809e-07 2.1e-06 -0.0068577278 + 4e-06 13000 200 2.7185589e-07 2.1e-06 -0.0068244954 + 4e-06 13100 200 3.3577426e-07 2.1e-06 -0.0067878266 + 4e-06 13200 200 3.9749034e-07 2.1e-06 -0.00674774 + 4e-06 13300 200 5.0743398e-07 2.1e-06 -0.0067042557 + 4e-06 13400 200 5.6629069e-07 2.1e-06 -0.0066573956 + 4e-06 13500 200 5.9092105e-07 2.1e-06 -0.0066071833 + 4e-06 13600 200 7.313638e-07 2.1e-06 -0.0065536441 + 4e-06 13700 200 1.0954352e-06 2.1e-06 -0.0064968049 + 4e-06 13800 200 7.1637332e-07 2.1e-06 -0.0064366944 + 4e-06 13900 200 8.5398051e-07 2.1e-06 -0.0063733428 + 4e-06 14000 200 1.0429888e-06 2.1e-06 -0.0063067821 + 4e-06 14100 200 1.6673022e-07 2.1e-06 -0.0062370457 + 4e-06 14200 200 2.0206568e-08 2.1e-06 -0.0061641687 + 4e-06 14300 200 5.6062261e-09 2.1e-06 -0.0060881879 + 4e-06 14400 200 4.5198973e-09 2.1e-06 -0.0060091416 + 4e-06 14500 200 2.5522353e-09 2.1e-06 -0.0059270694 + 4e-06 14600 200 9.091094e-10 2.1e-06 -0.0058420128 + 4e-06 14700 200 1.3992806e-10 2.1e-06 -0.0057540145 + 4e-06 14800 200 1.0208666e-11 2.1e-06 -0.005663119 + 4e-06 14900 200 8.4078334e-11 2.1e-06 -0.0055693718 + 4e-06 15000 200 1.2567311e-10 2.1e-06 -0.0054728204 + 4e-06 15100 200 5.2285722e-10 2.1e-06 -0.0053735132 + 4e-06 15200 200 1.5839179e-10 2.1e-06 -0.0052715003 + 4e-06 15300 200 3.2283374e-11 2.1e-06 -0.005166833 + 4e-06 15400 200 2.9516435e-12 2.1e-06 -0.005059564 + 4e-06 15500 200 1.0302118e-11 2.1e-06 -0.0049497475 + 4e-06 15600 200 1.7289975e-11 2.1e-06 -0.0048374385 + 4e-06 15700 200 1.4850209e-11 2.1e-06 -0.0047226938 + 4e-06 15800 200 8.0260964e-12 2.1e-06 -0.0046055711 + 4e-06 15900 200 2.616591e-12 2.1e-06 -0.0044861293 + 4e-06 16000 200 3.0793261e-13 2.1e-06 -0.0043644286 + 4e-06 16100 200 4.9187696e-13 2.1e-06 -0.0042405303 + 4e-06 16200 200 3.9849142e-13 2.1e-06 -0.0041144968 + 4e-06 16300 200 5.2823345e-13 2.1e-06 -0.0039863915 + 4e-06 16400 200 3.9902725e-13 2.1e-06 -0.0038562789 + 4e-06 16500 200 1.9259043e-13 2.1e-06 -0.0037242245 + 4e-06 16600 200 5.3557316e-14 2.1e-06 -0.0035902949 + 4e-06 16700 200 3.7734621e-15 2.1e-06 -0.0034545575 + 4e-06 16800 200 3.0867115e-15 2.1e-06 -0.0033170806 + 4e-06 16900 200 1.1841579e-14 2.1e-06 -0.0031779335 + 4e-06 17000 200 1.3850503e-14 2.1e-06 -0.0030371862 + 4e-06 17100 200 9.8491914e-15 2.1e-06 -0.0028949095 + 4e-06 17200 200 4.7140149e-15 2.1e-06 -0.0027511752 + 4e-06 17300 200 1.3440466e-15 2.1e-06 -0.0026060556 + 4e-06 17400 200 1.0627828e-16 2.1e-06 -0.0024596238 + 4e-06 17500 200 6.2015781e-17 2.1e-06 -0.0023119534 + 4e-06 17600 200 2.8723007e-16 2.1e-06 -0.002163119 + 4e-06 17700 200 3.6601367e-16 2.1e-06 -0.0020131953 + 4e-06 17800 200 2.7862312e-16 2.1e-06 -0.0018622579 + 4e-06 17900 200 1.4268051e-16 2.1e-06 -0.0017103828 + 4e-06 18000 200 4.5443603e-17 2.1e-06 -0.0015576465 + 4e-06 18100 200 5.2330376e-18 2.1e-06 -0.0014041259 + 4e-06 18200 200 7.3566254e-19 2.1e-06 -0.0012498983 + 4e-06 18300 200 6.5880468e-18 2.1e-06 -0.0010950413 + 4e-06 18400 200 9.5744931e-18 2.1e-06 -0.00093963286 + 4e-06 18500 200 7.8604487e-18 2.1e-06 -0.00078375133 + 4e-06 18600 200 4.3166295e-18 2.1e-06 -0.00062747516 + 4e-06 18700 200 1.5188792e-18 2.1e-06 -0.00047088304 + 4e-06 18800 200 2.3221067e-19 2.1e-06 -0.00031405381 + 4e-06 18900 200 4.7558964e-21 2.1e-06 -0.00015706645 + 4e-06 19000 200 1.4567292e-19 2.1e-06 2.0903119e-17 +Loop time of 6.96616 on 1 procs for 14000 steps with 200 atoms + +99.5% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 3.8534 | 3.8534 | 3.8534 | 0.0 | 55.32 +Neigh | 0.038778 | 0.038778 | 0.038778 | 0.0 | 0.56 +Comm | 0.0015081 | 0.0015081 | 0.0015081 | 0.0 | 0.02 +Output | 0.0018007 | 0.0018007 | 0.0018007 | 0.0 | 0.03 +Modify | 3.0668 | 3.0668 | 3.0668 | 0.0 | 44.02 +Other | | 0.003851 | | | 0.06 + +Nlocal: 200 ave 200 max 200 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 3031 ave 3031 max 3031 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 3031 +Ave neighs/atom = 15.155 +Neighbor list builds = 233 +Dangerous builds not checked + +##### EJECTION ##### + +variable punch_frequency equal PI/2/(dt*${ejection_steps}) +variable punch_frequency equal PI/2/(dt*14000) +variable disp_lower equal ${dieHeight}*sin(${punch_frequency}*elapsed*dt) +variable disp_lower equal 0.01*sin(${punch_frequency}*elapsed*dt) +variable disp_lower equal 0.01*sin(28.0499344070517*elapsed*dt) +variable disp_upper equal 0.9*v_disp_lower +run ${ejection_steps} +run 14000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 72.31 | 72.31 | 72.31 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 19000 200 1.4567292e-19 2.1e-06 0 + 4e-06 19100 200 1.9132195e-05 2.1e-06 0.00010097765 + 4e-06 19200 200 3.1561748e-06 2.1e-06 0.00020194258 + 4e-06 19300 200 1.4462178e-05 2.1e-06 0.00030288209 + 4e-06 19400 200 4.6622112e-06 2.1e-06 0.00040378347 + 4e-06 19500 200 1.1929852e-05 2.1e-06 0.00050463403 + 4e-06 19600 200 5.6933661e-06 2.1e-06 0.00060542105 + 4e-06 19700 200 1.0429976e-05 2.1e-06 0.00070613186 + 4e-06 19800 200 6.6580254e-06 2.1e-06 0.00080675378 + 4e-06 19900 200 9.1721686e-06 2.1e-06 0.00090727414 + 4e-06 20000 200 7.4553343e-06 2.1e-06 0.0010076803 + 4e-06 20100 200 8.3534813e-06 2.1e-06 0.0011079596 + 4e-06 20200 200 7.8671075e-06 2.1e-06 0.0012080994 + 4e-06 20300 200 7.9115898e-06 2.1e-06 0.0013080871 + 4e-06 20400 200 8.2222312e-06 2.1e-06 0.0014079102 + 4e-06 20500 200 7.5281175e-06 2.1e-06 0.001507556 + 4e-06 20600 200 8.4242027e-06 2.1e-06 0.0016070121 + 4e-06 20700 200 7.3282364e-06 2.1e-06 0.0017062658 + 4e-06 20800 200 8.3501222e-06 2.1e-06 0.0018053047 + 4e-06 20900 200 7.3417566e-06 2.1e-06 0.0019041164 + 4e-06 21000 200 8.0702927e-06 2.1e-06 0.0020026884 + 4e-06 21100 200 7.5896194e-06 2.1e-06 0.0021010083 + 4e-06 21200 200 7.6596342e-06 2.1e-06 0.0021990637 + 4e-06 21300 200 7.7009755e-06 2.1e-06 0.0022968422 + 4e-06 21400 200 7.4010568e-06 2.1e-06 0.0023943316 + 4e-06 21500 200 7.7254953e-06 2.1e-06 0.0024915196 + 4e-06 21600 200 7.2931076e-06 2.1e-06 0.0025883939 + 4e-06 21700 200 7.5667043e-06 2.1e-06 0.0026849424 + 4e-06 21800 200 7.2767179e-06 2.1e-06 0.0027811529 + 4e-06 21900 200 7.3632148e-06 2.1e-06 0.0028770133 + 4e-06 22000 200 7.2563523e-06 2.1e-06 0.0029725116 + 4e-06 22100 200 7.2003226e-06 2.1e-06 0.0030676356 + 4e-06 22200 200 7.1862422e-06 2.1e-06 0.0031623734 + 4e-06 22300 200 7.0035785e-06 2.1e-06 0.0032567132 + 4e-06 22400 200 7.1023437e-06 2.1e-06 0.0033506429 + 4e-06 22500 200 6.8767896e-06 2.1e-06 0.0034441509 + 4e-06 22600 200 6.9556381e-06 2.1e-06 0.0035372253 + 4e-06 22700 200 6.7754491e-06 2.1e-06 0.0036298544 + 4e-06 22800 200 6.7752923e-06 2.1e-06 0.0037220265 + 4e-06 22900 200 6.6947789e-06 2.1e-06 0.0038137301 + 4e-06 23000 200 6.5811876e-06 2.1e-06 0.0039049537 + 4e-06 23100 200 6.5600064e-06 2.1e-06 0.0039956856 + 4e-06 23200 200 6.407054e-06 2.1e-06 0.0040859145 + 4e-06 23300 200 6.4635326e-06 2.1e-06 0.0041756291 + 4e-06 23400 200 6.2604509e-06 2.1e-06 0.004264818 + 4e-06 23500 200 6.2914059e-06 2.1e-06 0.00435347 + 4e-06 23600 200 6.1416598e-06 2.1e-06 0.004441574 + 4e-06 23700 200 6.0839487e-06 2.1e-06 0.0045291188 + 4e-06 23800 200 6.0216029e-06 2.1e-06 0.0046160935 + 4e-06 23900 200 5.896464e-06 2.1e-06 0.0047024871 + 4e-06 24000 200 5.8682556e-06 2.1e-06 0.0047882887 + 4e-06 24100 200 5.8744357e-06 2.1e-06 0.0048734875 + 4e-06 24200 200 5.6172509e-06 2.1e-06 0.0049580728 + 4e-06 24300 200 5.6527872e-06 2.1e-06 0.005042034 + 4e-06 24400 200 5.4706998e-06 2.1e-06 0.0051253604 + 4e-06 24500 200 5.4368713e-06 2.1e-06 0.0052080417 + 4e-06 24600 200 5.3496195e-06 2.1e-06 0.0052900673 + 4e-06 24700 200 5.2020248e-06 2.1e-06 0.0053714269 + 4e-06 24800 200 5.2035809e-06 2.1e-06 0.0054521104 + 4e-06 24900 200 5.0302031e-06 2.1e-06 0.0055321075 + 4e-06 25000 200 5.0094633e-06 2.1e-06 0.0056114082 + 4e-06 25100 200 4.8588064e-06 2.1e-06 0.0056900025 + 4e-06 25200 200 4.8221437e-06 2.1e-06 0.0057678805 + 4e-06 25300 200 4.7117322e-06 2.1e-06 0.0058450324 + 4e-06 25400 200 4.6148719e-06 2.1e-06 0.0059214485 + 4e-06 25500 200 4.5348297e-06 2.1e-06 0.0059971192 + 4e-06 25600 200 4.4325937e-06 2.1e-06 0.0060720349 + 4e-06 25700 200 4.3587865e-06 2.1e-06 0.0061461862 + 4e-06 25800 200 4.2449842e-06 2.1e-06 0.0062195638 + 4e-06 25900 200 4.1730814e-06 2.1e-06 0.0062921585 + 4e-06 26000 200 4.0712085e-06 2.1e-06 0.006363961 + 4e-06 26100 200 3.9603603e-06 2.1e-06 0.0064349624 + 4e-06 26200 200 3.9152641e-06 2.1e-06 0.0065051538 + 4e-06 26300 200 3.7864366e-06 2.1e-06 0.0065745262 + 4e-06 26400 200 3.7211553e-06 2.1e-06 0.006643071 + 4e-06 26500 200 3.6038142e-06 2.1e-06 0.0067107795 + 4e-06 26600 200 3.5518456e-06 2.1e-06 0.0067776432 + 4e-06 26700 200 3.4213616e-06 2.1e-06 0.0068436537 + 4e-06 26800 200 3.348649e-06 2.1e-06 0.0069088027 + 4e-06 26900 200 3.2592054e-06 2.1e-06 0.0069730819 + 4e-06 27000 200 3.1640896e-06 2.1e-06 0.0070364833 + 4e-06 27100 200 3.1491467e-06 2.1e-06 0.007098999 + 4e-06 27200 200 2.9475347e-06 2.1e-06 0.0071606209 + 4e-06 27300 200 2.9234007e-06 2.1e-06 0.0072213415 + 4e-06 27400 200 2.8106832e-06 2.1e-06 0.0072811529 + 4e-06 27500 200 2.7190831e-06 2.1e-06 0.0073400478 + 4e-06 27600 200 2.6595021e-06 2.1e-06 0.0073980187 + 4e-06 27700 200 2.5384163e-06 2.1e-06 0.0074550582 + 4e-06 27800 200 2.4906759e-06 2.1e-06 0.0075111593 + 4e-06 27900 200 2.3760852e-06 2.1e-06 0.0075663148 + 4e-06 28000 200 2.3135864e-06 2.1e-06 0.0076205178 + 4e-06 28100 200 2.206388e-06 2.1e-06 0.0076737615 + 4e-06 28200 200 2.1580755e-06 2.1e-06 0.0077260391 + 4e-06 28300 200 2.0541807e-06 2.1e-06 0.0077773442 + 4e-06 28400 200 1.9879886e-06 2.1e-06 0.0078276702 + 4e-06 28500 200 1.9080731e-06 2.1e-06 0.0078770108 + 4e-06 28600 200 1.8244513e-06 2.1e-06 0.0079253598 + 4e-06 28700 200 1.7612085e-06 2.1e-06 0.0079727111 + 4e-06 28800 200 1.6725418e-06 2.1e-06 0.0080190587 + 4e-06 28900 200 1.6108221e-06 2.1e-06 0.0080643969 + 4e-06 29000 200 1.5315923e-06 2.1e-06 0.0081087198 + 4e-06 29100 200 1.4668177e-06 2.1e-06 0.008152022 + 4e-06 29200 200 1.389947e-06 2.1e-06 0.0081942979 + 4e-06 29300 200 1.3244327e-06 2.1e-06 0.0082355423 + 4e-06 29400 200 1.2613389e-06 2.1e-06 0.00827575 + 4e-06 29500 200 1.189317e-06 2.1e-06 0.0083149158 + 4e-06 29600 200 1.1328651e-06 2.1e-06 0.0083530349 + 4e-06 29700 200 1.0634003e-06 2.1e-06 0.0083901025 + 4e-06 29800 200 1.0089659e-06 2.1e-06 0.0084261138 + 4e-06 29900 200 9.452383e-07 2.1e-06 0.0084610645 + 4e-06 30000 200 8.8857387e-07 2.1e-06 0.00849495 + 4e-06 30100 200 8.3934751e-07 2.1e-06 0.0085277661 + 4e-06 30200 200 7.7404495e-07 2.1e-06 0.0085595086 + 4e-06 30300 200 7.2760888e-07 2.1e-06 0.0085901737 + 4e-06 30400 200 6.7239685e-07 2.1e-06 0.0086197574 + 4e-06 30500 200 6.245416e-07 2.1e-06 0.0086482559 + 4e-06 30600 200 5.7834155e-07 2.1e-06 0.0086756657 + 4e-06 30700 200 5.2814574e-07 2.1e-06 0.0087019834 + 4e-06 30800 200 4.8878902e-07 2.1e-06 0.0087272057 + 4e-06 30900 200 4.4241206e-07 2.1e-06 0.0087513293 + 4e-06 31000 200 4.0442514e-07 2.1e-06 0.0087743512 + 4e-06 31100 200 3.642199e-07 2.1e-06 0.0087962686 + 4e-06 31200 200 3.2738558e-07 2.1e-06 0.0088170786 + 4e-06 31300 200 2.9389397e-07 2.1e-06 0.0088367787 + 4e-06 31400 200 2.5861566e-07 2.1e-06 0.0088553663 + 4e-06 31500 200 2.2934636e-07 2.1e-06 0.0088728392 + 4e-06 31600 200 1.9888494e-07 2.1e-06 0.0088891951 + 4e-06 31700 200 1.7250531e-07 2.1e-06 0.0089044319 + 4e-06 31800 200 1.4678036e-07 2.1e-06 0.0089185479 + 4e-06 31900 200 1.2324632e-07 2.1e-06 0.0089315411 + 4e-06 32000 200 1.0248084e-07 2.1e-06 0.0089434099 + 4e-06 32100 200 8.2609273e-08 2.1e-06 0.0089541529 + 4e-06 32200 200 6.551679e-08 2.1e-06 0.0089637686 + 4e-06 32300 200 5.0080052e-08 2.1e-06 0.008972256 + 4e-06 32400 200 3.6856646e-08 2.1e-06 0.0089796139 + 4e-06 32500 200 2.5648284e-08 2.1e-06 0.0089858413 + 4e-06 32600 200 1.637837e-08 2.1e-06 0.0089909376 + 4e-06 32700 200 9.2578154e-09 2.1e-06 0.008994902 + 4e-06 32800 200 4.0824723e-09 2.1e-06 0.0089977341 + 4e-06 32900 200 1.0371165e-09 2.1e-06 0.0089994335 + 4e-06 33000 200 6.1012168e-14 2.1e-06 0.009 +Loop time of 7.70808 on 1 procs for 14000 steps with 200 atoms + +99.6% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 4.4414 | 4.4414 | 4.4414 | 0.0 | 57.62 +Neigh | 0.040941 | 0.040941 | 0.040941 | 0.0 | 0.53 +Comm | 0.001526 | 0.001526 | 0.001526 | 0.0 | 0.02 +Output | 0.0019617 | 0.0019617 | 0.0019617 | 0.0 | 0.03 +Modify | 3.2183 | 3.2183 | 3.2183 | 0.0 | 41.75 +Other | | 0.003942 | | | 0.05 + +Nlocal: 200 ave 200 max 200 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 3026 ave 3026 max 3026 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 3026 +Ave neighs/atom = 15.13 +Neighbor list builds = 233 +Dangerous builds not checked + +##### FREE FLOAT ##### + +variable disp_lower equal ${dieHeight} +variable disp_lower equal 0.01 +variable disp_upper equal ${dieHeight}*0.9 +variable disp_upper equal 0.01*0.9 +variable max_disp equal ${dieRadius}*0.75 +variable max_disp equal 0.004*0.75 +run ${free_float_steps} +run 5000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 72.31 | 72.31 | 72.31 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 33000 200 6.1012168e-14 2.1e-06 0.009 + 4e-06 33100 200 6.7902539e-11 2.1e-06 0.009 + 4e-06 33200 200 2.0896758e-11 2.1e-06 0.009 + 4e-06 33300 200 2.5200405e-11 2.1e-06 0.009 + 4e-06 33400 200 2.1747895e-12 2.1e-06 0.009 + 4e-06 33500 200 1.1228817e-11 2.1e-06 0.009 + 4e-06 33600 200 3.3597579e-12 2.1e-06 0.009 + 4e-06 33700 200 1.4808583e-12 2.1e-06 0.009 + 4e-06 33800 200 3.5132295e-12 2.1e-06 0.009 + 4e-06 33900 200 8.2438639e-14 2.1e-06 0.009 + 4e-06 34000 200 1.3267378e-12 2.1e-06 0.009 + 4e-06 34100 200 6.2365031e-13 2.1e-06 0.009 + 4e-06 34200 200 1.1820072e-13 2.1e-06 0.009 + 4e-06 34300 200 5.2797742e-13 2.1e-06 0.009 + 4e-06 34400 200 3.2199555e-14 2.1e-06 0.009 + 4e-06 34500 200 1.553388e-13 2.1e-06 0.009 + 4e-06 34600 200 1.1458173e-13 2.1e-06 0.009 + 4e-06 34700 200 5.8686124e-15 2.1e-06 0.009 + 4e-06 34800 200 7.3486748e-14 2.1e-06 0.009 + 4e-06 34900 200 1.0877367e-14 2.1e-06 0.009 + 4e-06 35000 200 1.5284442e-14 2.1e-06 0.009 + 4e-06 35100 200 2.0294057e-14 2.1e-06 0.009 + 4e-06 35200 200 1.5385334e-17 2.1e-06 0.009 + 4e-06 35300 200 9.5858898e-15 2.1e-06 0.009 + 4e-06 35400 200 3.1985384e-15 2.1e-06 0.009 + 4e-06 35500 200 1.1327574e-15 2.1e-06 0.009 + 4e-06 35600 200 3.3810722e-15 2.1e-06 0.009 + 4e-06 35700 200 1.2867327e-16 2.1e-06 0.009 + 4e-06 35800 200 1.0755232e-15 2.1e-06 0.009 + 4e-06 35900 200 7.3381985e-16 2.1e-06 0.009 + 4e-06 36000 200 3.7750251e-17 2.1e-06 0.009 + 4e-06 36100 200 4.8518794e-16 2.1e-06 0.009 + 4e-06 36200 200 8.361623e-17 2.1e-06 0.009 + 4e-06 36300 200 8.9347649e-17 2.1e-06 0.009 + 4e-06 36400 200 1.4528409e-16 2.1e-06 0.009 + 4e-06 36500 200 8.2328133e-19 2.1e-06 0.009 + 4e-06 36600 200 5.9628413e-17 2.1e-06 0.009 + 4e-06 36700 200 2.857306e-17 2.1e-06 0.009 + 4e-06 36800 200 4.1078269e-18 2.1e-06 0.009 + 4e-06 36900 200 2.4094514e-17 2.1e-06 0.009 + 4e-06 37000 200 2.6153896e-18 2.1e-06 0.009 + 4e-06 37100 200 5.6577297e-18 2.1e-06 0.009 + 4e-06 37200 200 6.5849416e-18 2.1e-06 0.009 + 4e-06 37300 200 4.5596918e-21 2.1e-06 0.009 + 4e-06 37400 200 3.2329813e-18 2.1e-06 0.009 + 4e-06 37500 200 1.123288e-18 2.1e-06 0.009 + 4e-06 37600 200 3.4227094e-19 2.1e-06 0.009 + 4e-06 37700 200 1.1782135e-18 2.1e-06 0.009 + 4e-06 37800 200 6.9535961e-20 2.1e-06 0.009 + 4e-06 37900 200 3.4055174e-19 2.1e-06 0.009 + 4e-06 38000 200 2.8968649e-19 2.1e-06 0.009 +Loop time of 2.65906 on 1 procs for 5000 steps with 200 atoms + +99.6% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.5595 | 1.5595 | 1.5595 | 0.0 | 58.65 +Neigh | 0.012904 | 0.012904 | 0.012904 | 0.0 | 0.49 +Comm | 0.00041333 | 0.00041333 | 0.00041333 | 0.0 | 0.02 +Output | 0.00053486 | 0.00053486 | 0.00053486 | 0.0 | 0.02 +Modify | 1.0844 | 1.0844 | 1.0844 | 0.0 | 40.78 +Other | | 0.001336 | | | 0.05 + +Nlocal: 200 ave 200 max 200 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 3026 ave 3026 max 3026 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 3026 +Ave neighs/atom = 15.13 +Neighbor list builds = 83 +Dangerous builds not checked +Total wall time: 0:00:18 diff --git a/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 b/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 new file mode 100644 index 0000000000..1992fb2555 --- /dev/null +++ b/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 @@ -0,0 +1,784 @@ +LAMMPS (4 Feb 2025 - Development - patch_5May2020-22356-g0c29a0a0c9-modified) +############################### SIMULATION SETTINGS ################################################### + +atom_style sphere 1 +atom_modify map array +comm_modify vel yes +units si +newton off +neighbor 2 bin +neigh_modify delay 0 +timestep 1e-6 + +##################### SIMULATION BOUNDING BOX, INSERT PARTICLES, AND INTEGRATION ####################### + +boundary f f f +read_data spheres12.data +Reading data file ... + orthogonal box = (-10 -10 -10) to (10 10 10) + 1 by 1 by 1 MPI processor grid + reading atoms ... + 12 atoms + read_data CPU = 0.029 seconds +fix integr all nve/sphere + +# create pair group for contact area outputs +group particles_1_12 id 1 12 +2 atoms in group particles_1_12 + +########################### PARTICLE MATERIAL PROPERTIES AND FORCE MODEL ############################### + +variable atomRadius equal 0.5 + +pair_style granular + +# mdr = E, nu, Y, gamma, psi_b, damp +variable YoungsModulus equal 1e9 +variable PoissonsRatio equal 0.3 +variable YieldStress equal 50e6 +variable SurfaceEnergy equal 0.0 +variable psi_b equal 0.5 +variable damp equal 0.2 +variable damp_type equal 1 + +# linear_history = k_t, x_gamma,t, mu_s +variable kt equal 2/7*${YoungsModulus}*${atomRadius} +variable kt equal 2/7*1000000000*${atomRadius} +variable kt equal 2/7*1000000000*0.5 +variable xgammat equal 0.0 +variable mu_s equal 0.5 + +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 + +######################################### ADD IN PLANES ################################################ + +variable boxWidth equal 3 +variable halfBoxWidth equal ${boxWidth}/2 +variable halfBoxWidth equal 3/2 + +variable plane_disp equal 0.0 +variable plane_disp_neg equal 0.0 + +region plane_yz_pos plane ${halfBoxWidth} 0 0 -1 0 0 side in move v_plane_disp_neg NULL NULL units box +region plane_yz_pos plane 1.5 0 0 -1 0 0 side in move v_plane_disp_neg NULL NULL units box +region plane_yz_neg plane -${halfBoxWidth} 0 0 1 0 0 side in move v_plane_disp NULL NULL units box +region plane_yz_neg plane -1.5 0 0 1 0 0 side in move v_plane_disp NULL NULL units box +region plane_xz_pos plane 0 ${halfBoxWidth} 0 0 -1 0 side in move NULL v_plane_disp_neg NULL units box +region plane_xz_pos plane 0 1.5 0 0 -1 0 side in move NULL v_plane_disp_neg NULL units box +region plane_xz_neg plane 0 -${halfBoxWidth} 0 0 1 0 side in move NULL v_plane_disp NULL units box +region plane_xz_neg plane 0 -1.5 0 0 1 0 side in move NULL v_plane_disp NULL units box +region plane_xy_pos plane 0 0 ${halfBoxWidth} 0 0 -1 side in move NULL NULL v_plane_disp_neg units box +region plane_xy_pos plane 0 0 1.5 0 0 -1 side in move NULL NULL v_plane_disp_neg units box +region plane_xy_neg plane 0 0 -${halfBoxWidth} 0 0 1 side in move NULL NULL v_plane_disp units box +region plane_xy_neg plane 0 0 -1.5 0 0 1 side in move NULL NULL v_plane_disp units box + +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} " +granular mdr 1000000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 + +fix plane_yz_pos all wall/gran/region ${wall_contact_string} region plane_yz_pos contacts +fix plane_yz_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_yz_pos contacts +fix plane_yz_neg all wall/gran/region ${wall_contact_string} region plane_yz_neg contacts +fix plane_yz_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_yz_neg contacts +fix plane_xz_pos all wall/gran/region ${wall_contact_string} region plane_xz_pos contacts +fix plane_xz_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_xz_pos contacts +fix plane_xz_neg all wall/gran/region ${wall_contact_string} region plane_xz_neg contacts +fix plane_xz_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_xz_neg contacts +fix plane_xy_pos all wall/gran/region ${wall_contact_string} region plane_xy_pos contacts +fix plane_xy_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_xy_pos contacts +fix plane_xy_neg all wall/gran/region ${wall_contact_string} region plane_xy_neg contacts +fix plane_xy_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_xy_neg contacts + +compute plane_xy_neg_force all reduce sum f_plane_xy_neg[4] +variable plane_xy_neg_force equal c_plane_xy_neg_force + +compute plane_xz_neg_force all reduce sum f_plane_xz_neg[3] +variable plane_xz_neg_force equal c_plane_xz_neg_force + +compute plane_yz_neg_force all reduce sum f_plane_yz_neg[2] +variable plane_yz_neg_force equal c_plane_yz_neg_force + +#fix print1 all print 1 "${plane_disp} ${plane_xy_neg_force} ${plane_xz_neg_force} ${plane_yz_neg_force}" file force_disp_triaxial12.csv screen no + +######################################## SCREEN OUTPUT #################################################### + +compute 1 all erotate/sphere +thermo_style custom dt step atoms ke c_1 vol +thermo 100 +thermo_modify lost ignore norm no + +##################################### DEFINE WALL MOVEMENT ################################################# + +variable disp_max equal 0.499 +variable ddisp equal 0.00001 +variable compression_steps equal round(${disp_max}/${ddisp}) +variable compression_steps equal round(0.499/${ddisp}) +variable compression_steps equal round(0.499/1e-05) +variable output_rate equal round(${compression_steps}/100) +variable output_rate equal round(49900/100) + +##################################### SET UP DUMP OUTPUTS #################################################### + +#dump dumpParticles all custom ${output_rate} triaxial_compaction_12.dump id type mass x y z vx vy vz fx fy fz radius +#dump dmp all vtk ${output_rate} post/triaxial12particles_*.vtk id type mass x y z vx vy vz fx fy fz radius + +#################################### COMPRESS THE PARTICLES ################################################## + +run 0 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- MDR contact model command: (i) https://doi.org/10.1016/j.jmps.2023.105492 || (ii) https://doi.org/10.1016/j.jmps.2023.105493 || (iii) https://doi.org/10.31224/4289 + +@Article{zunker2024mechanicallyI, + author = {Zunker, William and Kamrin, Ken}, + title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles, + Part I: Utilizing the method of dimensionality reduction}, + journal = {Journal of the Mechanics and Physics of Solids}, + year = {2024}, + volume = {183}, + pages = {105492}, +} + +@Article{zunker2024mechanicallyII, + author = {Zunker, William and Kamrin, Ken}, + title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles, + Part II: Contact under high compaction—modeling a bulk elastic response}, + journal = {Journal of the Mechanics and Physics of Solids}, + year = {2024}, + volume = {183}, + pages = {105493}, +} + +@Article{zunker2025experimentally, + author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken}, + title = {Experimentally validated DEM for large deformation powder compaction: + mechanically-derived contact model and screening of non-physical contacts}, + journal = {Powder Technology}, + year = {2025}, + pages = {120972}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.2 + ghost atom cutoff = 3.2 + binsize = 1.6, bins = 13 13 13 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair granular, perpetual + attributes: half, newton off, size, history + pair build: half/size/bin/atomonly/newtoff + stencil: full/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 74.54 | 74.54 | 74.54 Mbytes + Dt Step Atoms KinEng c_1 Volume + 1e-06 0 12 0 0 8000 +Loop time of 8.28e-07 on 1 procs for 0 steps with 12 atoms + +0.0% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0 | 0 | 0 | 0.0 | 0.00 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 8.28e-07 | | |100.00 + +Nlocal: 12 ave 12 max 12 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 66 ave 66 max 66 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 66 +Ave neighs/atom = 5.5 +Neighbor list builds = 0 +Dangerous builds = 0 + +# print out contact area evolution for particles 1 and 12 +compute Ac_1_12 particles_1_12 pair/local p13 cutoff radius +compute Ac_1_12_sum particles_1_12 reduce sum c_Ac_1_12 inputs local +variable Ac_1_12 equal c_Ac_1_12_sum +#fix logArea all print 100 "${plane_disp} ${Ac_1_12}" file pair_1_12_contact_area_triaxial12.csv screen no + +variable plane_disp equal ${ddisp}*elapsed +variable plane_disp equal 1e-05*elapsed +variable plane_disp_neg equal -${ddisp}*elapsed +variable plane_disp_neg equal -1e-05*elapsed + +run ${compression_steps} +run 49900 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.2 + ghost atom cutoff = 3.2 + binsize = 1.6, bins = 13 13 13 + 2 neighbor lists, perpetual/occasional/extra = 1 1 0 + (1) pair granular, perpetual + attributes: half, newton off, size, history + pair build: half/size/bin/atomonly/newtoff + stencil: full/bin/3d + bin: standard + (2) compute pair/local, occasional + attributes: half, newton off, size + pair build: half/size/bin/atomonly/newtoff + stencil: full/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 75.17 | 75.17 | 75.17 Mbytes + Dt Step Atoms KinEng c_1 Volume + 1e-06 0 12 0 0 8000 + 1e-06 100 12 0.063728867 0 8000 + 1e-06 200 12 0.79328888 0 8000 + 1e-06 300 12 3.1671095 0 8000 + 1e-06 400 12 8.7248683 0 8000 + 1e-06 500 12 20.158012 0 8000 + 1e-06 600 12 41.157061 0 8000 + 1e-06 700 12 76.628872 0 8000 + 1e-06 800 12 132.88829 0 8000 + 1e-06 900 12 217.80403 0 8000 + 1e-06 1000 12 340.91325 0 8000 + 1e-06 1100 12 513.50254 0 8000 + 1e-06 1200 12 748.65202 0 8000 + 1e-06 1300 12 1061.2394 0 8000 + 1e-06 1400 12 1467.9017 0 8000 + 1e-06 1500 12 1986.9524 0 8000 + 1e-06 1600 12 2638.2542 0 8000 + 1e-06 1700 12 3443.0464 0 8000 + 1e-06 1800 12 4423.728 0 8000 + 1e-06 1900 12 5603.6004 0 8000 + 1e-06 2000 12 7006.5697 0 8000 + 1e-06 2100 12 8656.8153 0 8000 + 1e-06 2200 12 10575.061 0.00041930161 8000 + 1e-06 2300 12 12776.34 0.031472922 8000 + 1e-06 2400 12 15285.834 0.16547279 8000 + 1e-06 2500 12 18123.472 0.48824818 8000 + 1e-06 2600 12 21306.73 1.1172148 8000 + 1e-06 2700 12 24850.635 2.2101203 8000 + 1e-06 2800 12 28767.448 3.9742876 8000 + 1e-06 2900 12 33066.341 6.6765245 8000 + 1e-06 3000 12 37753.104 10.653677 8000 + 1e-06 3100 12 42829.905 16.323673 8000 + 1e-06 3200 12 48295.143 24.196804 8000 + 1e-06 3300 12 54143.784 34.886968 8000 + 1e-06 3400 12 60367.427 49.122473 8000 + 1e-06 3500 12 66954.459 67.756017 8000 + 1e-06 3600 12 73890.367 91.773371 8000 + 1e-06 3700 12 81158.051 122.30029 8000 + 1e-06 3800 12 88738.15 160.60714 8000 + 1e-06 3900 12 96609.374 208.11075 8000 + 1e-06 4000 12 104748.82 266.37305 8000 + 1e-06 4100 12 113132.27 337.09603 8000 + 1e-06 4200 12 121734.46 422.11267 8000 + 1e-06 4300 12 130529.26 523.37361 8000 + 1e-06 4400 12 139489.96 642.8869 8000 + 1e-06 4500 12 148590.48 781.76659 8000 + 1e-06 4600 12 157805.54 939.73777 8000 + 1e-06 4700 12 167102.78 1115.3765 8000 + 1e-06 4800 12 176408.3 1304.8823 8000 + 1e-06 4900 12 185727.22 1506.1791 8000 + 1e-06 5000 12 195037.08 1715.5141 8000 + 1e-06 5100 12 204311.37 1928.3496 8000 + 1e-06 5200 12 213522.05 2139.6607 8000 + 1e-06 5300 12 222640.01 2344.2078 8000 + 1e-06 5400 12 231635.3 2536.8271 8000 + 1e-06 5500 12 240477.26 2712.7272 8000 + 1e-06 5600 12 249036.18 2865.4067 8000 + 1e-06 5700 12 257225.21 2990.2307 8000 + 1e-06 5800 12 265107.22 3088.4777 8000 + 1e-06 5900 12 272662.78 3160.202 8000 + 1e-06 6000 12 279867.43 3206.6334 8000 + 1e-06 6100 12 286696.38 3230.2607 8000 + 1e-06 6200 12 293126.06 3234.7442 8000 + 1e-06 6300 12 299135.09 3224.7366 8000 + 1e-06 6400 12 304704.84 3205.6378 8000 + 1e-06 6500 12 309820.07 3183.3082 8000 + 1e-06 6600 12 314469.34 3163.76 8000 + 1e-06 6700 12 318645.43 3152.8517 8000 + 1e-06 6800 12 322345.74 3156.004 8000 + 1e-06 6900 12 325572.61 3177.9574 8000 + 1e-06 7000 12 328333.69 3222.5849 8000 + 1e-06 7100 12 330642.36 3292.7692 8000 + 1e-06 7200 12 332518.34 3390.3494 8000 + 1e-06 7300 12 333988.86 3516.133 8000 + 1e-06 7400 12 335091.17 3669.9688 8000 + 1e-06 7500 12 335881.45 3850.8676 8000 + 1e-06 7600 12 336541.99 4057.1561 8000 + 1e-06 7700 12 337100.25 4286.6487 8000 + 1e-06 7800 12 337436.07 4536.819 8000 + 1e-06 7900 12 337576.23 4804.9572 8000 + 1e-06 8000 12 337553.74 5088.3001 8000 + 1e-06 8100 12 337412.69 5384.125 8000 + 1e-06 8200 12 337266.12 5689.8034 8000 + 1e-06 8300 12 337141.16 6002.815 8000 + 1e-06 8400 12 336990.23 6320.7444 8000 + 1e-06 8500 12 336832.35 6645.3584 8000 + 1e-06 8600 12 336684.67 6980.6347 8000 + 1e-06 8700 12 336479.86 7317.4769 8000 + 1e-06 8800 12 336286.29 7653.1265 8000 + 1e-06 8900 12 336134.3 7982.859 8000 + 1e-06 9000 12 336043.31 8307.1796 8000 + 1e-06 9100 12 336035 8626.669 8000 + 1e-06 9200 12 336134.55 8942.2162 8000 + 1e-06 9300 12 336370.73 9254.9724 8000 + 1e-06 9400 12 336775.97 9566.1537 8000 + 1e-06 9500 12 337386.26 9876.5005 8000 + 1e-06 9600 12 338238.87 10185.038 8000 + 1e-06 9700 12 339373.93 10490.42 8000 + 1e-06 9800 12 340832.84 10792.816 8000 + 1e-06 9900 12 342649.99 11091.69 8000 + 1e-06 10000 12 344857.32 11386.232 8000 + 1e-06 10100 12 347498.52 11676.525 8000 + 1e-06 10200 12 350625.53 11966.038 8000 + 1e-06 10300 12 354228.27 12250.382 8000 + 1e-06 10400 12 358314.64 12529.915 8000 + 1e-06 10500 12 362887.71 12806.586 8000 + 1e-06 10600 12 367944.26 13083.935 8000 + 1e-06 10700 12 373508.47 13375.901 8000 + 1e-06 10800 12 379544.75 13682.748 8000 + 1e-06 10900 12 385955.58 13992.431 8000 + 1e-06 11000 12 392687 14307.793 8000 + 1e-06 11100 12 399676.01 14631.631 8000 + 1e-06 11200 12 406851.99 14966.316 8000 + 1e-06 11300 12 414139.37 15312.299 8000 + 1e-06 11400 12 421458.35 15668.76 8000 + 1e-06 11500 12 428725.85 16034.567 8000 + 1e-06 11600 12 435860.63 16408.01 8000 + 1e-06 11700 12 442914.03 16784.22 8000 + 1e-06 11800 12 449956.98 17165.7 8000 + 1e-06 11900 12 456943.52 17548.894 8000 + 1e-06 12000 12 463832.6 17927.761 8000 + 1e-06 12100 12 470563.99 18302.718 8000 + 1e-06 12200 12 477048.89 18678.218 8000 + 1e-06 12300 12 483212.97 19059.367 8000 + 1e-06 12400 12 489085.23 19458.596 8000 + 1e-06 12500 12 494661.19 19885.306 8000 + 1e-06 12600 12 499940 20344.66 8000 + 1e-06 12700 12 504927.83 20838.53 8000 + 1e-06 12800 12 509641.24 21366.554 8000 + 1e-06 12900 12 514117.28 21934.019 8000 + 1e-06 13000 12 518378.2 22538.416 8000 + 1e-06 13100 12 522458.77 23167.62 8000 + 1e-06 13200 12 525853.3 23780.032 8000 + 1e-06 13300 12 528815.22 24345.078 8000 + 1e-06 13400 12 531513.34 24883.702 8000 + 1e-06 13500 12 534014.75 25400.482 8000 + 1e-06 13600 12 536357.43 25891.923 8000 + 1e-06 13700 12 538572.95 26355.972 8000 + 1e-06 13800 12 540657.99 26795.836 8000 + 1e-06 13900 12 542612.1 27223.435 8000 + 1e-06 14000 12 544466.84 27647.413 8000 + 1e-06 14100 12 546241.59 28080.229 8000 + 1e-06 14200 12 547953.9 28538.741 8000 + 1e-06 14300 12 549620.46 29043.928 8000 + 1e-06 14400 12 551260.1 29617.65 8000 + 1e-06 14500 12 552886.91 30280.697 8000 + 1e-06 14600 12 554517.93 31050.292 8000 + 1e-06 14700 12 556175.17 31938.659 8000 + 1e-06 14800 12 557897.11 32951.814 8000 + 1e-06 14900 12 559696.65 34092.387 8000 + 1e-06 15000 12 561564.33 35360.561 8000 + 1e-06 15100 12 563512.54 36749.828 8000 + 1e-06 15200 12 565557.63 38246.838 8000 + 1e-06 15300 12 567718.92 39832.256 8000 + 1e-06 15400 12 569910.41 41477.599 8000 + 1e-06 15500 12 572038.38 43132.458 8000 + 1e-06 15600 12 573913.47 44763.446 8000 + 1e-06 15700 12 575651.62 46334.905 8000 + 1e-06 15800 12 577306.75 47812.828 8000 + 1e-06 15900 12 578897.86 49166.374 8000 + 1e-06 16000 12 580431.98 50370.863 8000 + 1e-06 16100 12 581917.67 51410.025 8000 + 1e-06 16200 12 583392.37 52290.363 8000 + 1e-06 16300 12 584896.54 53001.616 8000 + 1e-06 16400 12 586445.21 53535.481 8000 + 1e-06 16500 12 588052.51 53896.917 8000 + 1e-06 16600 12 589732.17 54102.867 8000 + 1e-06 16700 12 591496.83 54180.423 8000 + 1e-06 16800 12 593357.37 54163.728 8000 + 1e-06 16900 12 595249.77 54088.894 8000 + 1e-06 17000 12 597130.72 53987.792 8000 + 1e-06 17100 12 598744.15 53852.584 8000 + 1e-06 17200 12 600057.69 53662.064 8000 + 1e-06 17300 12 601263.08 53505.031 8000 + 1e-06 17400 12 602411.57 53452.104 8000 + 1e-06 17500 12 603541.22 53553.609 8000 + 1e-06 17600 12 604067.01 53875.668 8000 + 1e-06 17700 12 602571.09 54490.575 8000 + 1e-06 17800 12 600292.75 55434.526 8000 + 1e-06 17900 12 597386.86 56736.273 8000 + 1e-06 18000 12 593981.08 58424.745 8000 + 1e-06 18100 12 590178.8 60527.06 8000 + 1e-06 18200 12 586056.65 63073.313 8000 + 1e-06 18300 12 581695.18 66084.237 8000 + 1e-06 18400 12 577195.63 69560.379 8000 + 1e-06 18500 12 572657.32 73490.56 8000 + 1e-06 18600 12 568173.86 77853.568 8000 + 1e-06 18700 12 563830.46 82617.321 8000 + 1e-06 18800 12 559701.49 87738.316 8000 + 1e-06 18900 12 555848.76 93162.955 8000 + 1e-06 19000 12 552088.23 98803.436 8000 + 1e-06 19100 12 548185.32 104427.42 8000 + 1e-06 19200 12 544535.46 110064.18 8000 + 1e-06 19300 12 541228.34 115757.05 8000 + 1e-06 19400 12 538293.89 121467.69 8000 + 1e-06 19500 12 535108.7 127127.41 8000 + 1e-06 19600 12 531413.61 132495.98 8000 + 1e-06 19700 12 527729.51 137678.56 8000 + 1e-06 19800 12 524151.76 142754.02 8000 + 1e-06 19900 12 520715.23 147730.68 8000 + 1e-06 20000 12 517436.17 152621.73 8000 + 1e-06 20100 12 514316.17 157423.95 8000 + 1e-06 20200 12 511400.64 162074.69 8000 + 1e-06 20300 12 508692.38 166497.97 8000 + 1e-06 20400 12 506153.1 170617.84 8000 + 1e-06 20500 12 503717.78 174351.25 8000 + 1e-06 20600 12 501293.63 177615.72 8000 + 1e-06 20700 12 498966.36 180365.82 8000 + 1e-06 20800 12 496760.02 182555.39 8000 + 1e-06 20900 12 494705.8 184132.07 8000 + 1e-06 21000 12 492841.84 185052.2 8000 + 1e-06 21100 12 491215.97 185288.72 8000 + 1e-06 21200 12 489677.84 184786.05 8000 + 1e-06 21300 12 488104.26 183535.77 8000 + 1e-06 21400 12 486394.75 181560.76 8000 + 1e-06 21500 12 484603.38 178874.58 8000 + 1e-06 21600 12 482731.75 175610.89 8000 + 1e-06 21700 12 480707.38 172071.04 8000 + 1e-06 21800 12 478504.9 168244.44 8000 + 1e-06 21900 12 476099.5 164130.08 8000 + 1e-06 22000 12 473401.48 159927.13 8000 + 1e-06 22100 12 470370.26 155762.08 8000 + 1e-06 22200 12 467067.88 151634.35 8000 + 1e-06 22300 12 463485.76 147589.77 8000 + 1e-06 22400 12 459593.94 143696.49 8000 + 1e-06 22500 12 455376.67 140035.23 8000 + 1e-06 22600 12 450819.48 136692.31 8000 + 1e-06 22700 12 445945.91 133704.47 8000 + 1e-06 22800 12 440758.89 131179.35 8000 + 1e-06 22900 12 435302.31 129342.22 8000 + 1e-06 23000 12 429598.98 128282.87 8000 + 1e-06 23100 12 423606.11 127995.47 8000 + 1e-06 23200 12 417364.51 128494.32 8000 + 1e-06 23300 12 410931.48 129772.21 8000 + 1e-06 23400 12 404376.34 131791.95 8000 + 1e-06 23500 12 397794.05 134484.8 8000 + 1e-06 23600 12 390990.06 137778.07 8000 + 1e-06 23700 12 384162.26 141638.59 8000 + 1e-06 23800 12 377636.5 145932.03 8000 + 1e-06 23900 12 371606.04 150514.72 8000 + 1e-06 24000 12 366266.24 155257.47 8000 + 1e-06 24100 12 361786.35 160026.32 8000 + 1e-06 24200 12 358332.56 164701.26 8000 + 1e-06 24300 12 356060.82 169171.06 8000 + 1e-06 24400 12 355078.48 173360.16 8000 + 1e-06 24500 12 355450.93 177217.02 8000 + 1e-06 24600 12 357219.84 180708.91 8000 + 1e-06 24700 12 360415.01 183807.52 8000 + 1e-06 24800 12 365023.77 186489.43 8000 + 1e-06 24900 12 371003.31 188744.64 8000 + 1e-06 25000 12 377719.96 190508.83 8000 + 1e-06 25100 12 385044.02 191723.21 8000 + 1e-06 25200 12 392909.32 192416.99 8000 + 1e-06 25300 12 401135.52 192645.59 8000 + 1e-06 25400 12 409539.24 192477.65 8000 + 1e-06 25500 12 417291.42 191761.92 8000 + 1e-06 25600 12 424737.36 190597.14 8000 + 1e-06 25700 12 431913.53 189106.01 8000 + 1e-06 25800 12 438736.08 187391.23 8000 + 1e-06 25900 12 445137.75 185551.39 8000 + 1e-06 26000 12 451066.87 183681.98 8000 + 1e-06 26100 12 456506.74 181876.3 8000 + 1e-06 26200 12 461444.38 180210.36 8000 + 1e-06 26300 12 465927.86 178746.53 8000 + 1e-06 26400 12 470133.57 177568.71 8000 + 1e-06 26500 12 474134.12 176672.99 8000 + 1e-06 26600 12 477972.05 176033.42 8000 + 1e-06 26700 12 481533.44 175580.73 8000 + 1e-06 26800 12 484262.56 175093.24 8000 + 1e-06 26900 12 486070.74 174178.51 8000 + 1e-06 27000 12 487322.68 173184.75 8000 + 1e-06 27100 12 488010.07 172084.41 8000 + 1e-06 27200 12 488079.27 170808.69 8000 + 1e-06 27300 12 487463.01 169291.88 8000 + 1e-06 27400 12 486083.88 167484.29 8000 + 1e-06 27500 12 483861.52 165357.96 8000 + 1e-06 27600 12 480726.55 162915.35 8000 + 1e-06 27700 12 476628.16 160197.08 8000 + 1e-06 27800 12 471546.66 157277.97 8000 + 1e-06 27900 12 465514.41 154256.68 8000 + 1e-06 28000 12 458577.33 151265.67 8000 + 1e-06 28100 12 450810.58 148472.95 8000 + 1e-06 28200 12 442311.34 146058.64 8000 + 1e-06 28300 12 433200.29 144179.21 8000 + 1e-06 28400 12 423625.66 142953.04 8000 + 1e-06 28500 12 413765.24 142450.35 8000 + 1e-06 28600 12 403817.87 142689.67 8000 + 1e-06 28700 12 393989.03 143646.16 8000 + 1e-06 28800 12 384484.33 145259.76 8000 + 1e-06 28900 12 375502.5 147428.86 8000 + 1e-06 29000 12 367250.91 150041.97 8000 + 1e-06 29100 12 359903.16 153002.45 8000 + 1e-06 29200 12 353678.89 156213.09 8000 + 1e-06 29300 12 348513.14 159524.58 8000 + 1e-06 29400 12 344408.06 162793.23 8000 + 1e-06 29500 12 341354.25 165860.66 8000 + 1e-06 29600 12 339292.66 168560.48 8000 + 1e-06 29700 12 338131.77 170723.76 8000 + 1e-06 29800 12 337633.87 172131.92 8000 + 1e-06 29900 12 337374.11 172433.2 8000 + 1e-06 30000 12 337379.48 171680.35 8000 + 1e-06 30100 12 337530.24 169927.53 8000 + 1e-06 30200 12 337706.33 167168.98 8000 + 1e-06 30300 12 337790.98 163426.76 8000 + 1e-06 30400 12 337697.64 158781.65 8000 + 1e-06 30500 12 337366.76 153367.47 8000 + 1e-06 30600 12 336755.07 147361.71 8000 + 1e-06 30700 12 335854.47 140976.25 8000 + 1e-06 30800 12 334662.2 134438.92 8000 + 1e-06 30900 12 333206.26 127982.95 8000 + 1e-06 31000 12 331464.93 121911.39 8000 + 1e-06 31100 12 329488.62 116351.57 8000 + 1e-06 31200 12 327373.17 111369.57 8000 + 1e-06 31300 12 325228.82 107014.37 8000 + 1e-06 31400 12 323169.4 103330.69 8000 + 1e-06 31500 12 321071.03 100385.5 8000 + 1e-06 31600 12 319031.38 98193.648 8000 + 1e-06 31700 12 317126.27 96712.557 8000 + 1e-06 31800 12 315438.37 95876.196 8000 + 1e-06 31900 12 313815.51 95565.683 8000 + 1e-06 32000 12 312239.38 95585.612 8000 + 1e-06 32100 12 310926.28 95828.27 8000 + 1e-06 32200 12 309948.5 96173.311 8000 + 1e-06 32300 12 309370.35 96442.454 8000 + 1e-06 32400 12 309201.18 96472.304 8000 + 1e-06 32500 12 309383.35 96140.953 8000 + 1e-06 32600 12 309865.73 95349.932 8000 + 1e-06 32700 12 310615.88 94029.061 8000 + 1e-06 32800 12 311624.15 92145.895 8000 + 1e-06 32900 12 312897.69 89717.564 8000 + 1e-06 33000 12 314451.54 86812.433 8000 + 1e-06 33100 12 316227.53 83544.302 8000 + 1e-06 33200 12 318247.7 80051.39 8000 + 1e-06 33300 12 320540.3 76478.862 8000 + 1e-06 33400 12 323095.15 72955.915 8000 + 1e-06 33500 12 325858.6 69576.683 8000 + 1e-06 33600 12 328744.8 66391.967 8000 + 1e-06 33700 12 331653.91 63413.798 8000 + 1e-06 33800 12 334464.83 60630.152 8000 + 1e-06 33900 12 337044.79 58019.718 8000 + 1e-06 34000 12 339236.01 55565.231 8000 + 1e-06 34100 12 340903.65 53265.034 8000 + 1e-06 34200 12 341925.23 51135.512 8000 + 1e-06 34300 12 342206.93 49222.627 8000 + 1e-06 34400 12 341649.35 47586.207 8000 + 1e-06 34500 12 340176.56 46291.105 8000 + 1e-06 34600 12 337667.96 45393.826 8000 + 1e-06 34700 12 333648.9 44922.723 8000 + 1e-06 34800 12 328322.97 44898.764 8000 + 1e-06 34900 12 321776.97 45316.954 8000 + 1e-06 35000 12 314135.31 46151.059 8000 + 1e-06 35100 12 305598.53 47348.476 8000 + 1e-06 35200 12 296352.23 48877.862 8000 + 1e-06 35300 12 286690.37 50727.291 8000 + 1e-06 35400 12 276916.56 52890.03 8000 + 1e-06 35500 12 267324.34 55346.515 8000 + 1e-06 35600 12 258272.27 58117.818 8000 + 1e-06 35700 12 250043.55 61209.498 8000 + 1e-06 35800 12 242858.64 64607.799 8000 + 1e-06 35900 12 236841.89 68268.869 8000 + 1e-06 36000 12 232039.2 72109.967 8000 + 1e-06 36100 12 228474.09 76010.069 8000 + 1e-06 36200 12 226115.66 79808.944 8000 + 1e-06 36300 12 224858.91 83318.088 8000 + 1e-06 36400 12 224574.55 86340.123 8000 + 1e-06 36500 12 225062.39 88691.698 8000 + 1e-06 36600 12 226104.86 90211.829 8000 + 1e-06 36700 12 227493.83 90797.861 8000 + 1e-06 36800 12 229033.4 90446.128 8000 + 1e-06 36900 12 230503.16 89238.368 8000 + 1e-06 37000 12 231859.26 87294.45 8000 + 1e-06 37100 12 233083.51 84767.219 8000 + 1e-06 37200 12 234235.94 81827.155 8000 + 1e-06 37300 12 235402.6 78655.588 8000 + 1e-06 37400 12 236702.37 75432.209 8000 + 1e-06 37500 12 238271.62 72343.239 8000 + 1e-06 37600 12 240191.8 69493.919 8000 + 1e-06 37700 12 242533.8 66949.307 8000 + 1e-06 37800 12 245357.31 64751.161 8000 + 1e-06 37900 12 248707.62 62935.998 8000 + 1e-06 38000 12 252613.72 61551.838 8000 + 1e-06 38100 12 257052.41 60672.572 8000 + 1e-06 38200 12 261959.48 60392.157 8000 + 1e-06 38300 12 267252.31 60809.22 8000 + 1e-06 38400 12 272813.05 62005.004 8000 + 1e-06 38500 12 278498.77 64020.387 8000 + 1e-06 38600 12 284150.51 66835.207 8000 + 1e-06 38700 12 289604.09 70354.609 8000 + 1e-06 38800 12 294696.3 74392.688 8000 + 1e-06 38900 12 299233.72 78587.64 8000 + 1e-06 39000 12 303148.91 82674.175 8000 + 1e-06 39100 12 306708.36 86536.948 8000 + 1e-06 39200 12 309600.62 89862.067 8000 + 1e-06 39300 12 311700.43 92456.711 8000 + 1e-06 39400 12 312846.09 94218.029 8000 + 1e-06 39500 12 312996.55 95123.249 8000 + 1e-06 39600 12 311853.31 95204.167 8000 + 1e-06 39700 12 309573.91 94589.061 8000 + 1e-06 39800 12 306120.98 93445.743 8000 + 1e-06 39900 12 301697.58 91905.478 8000 + 1e-06 40000 12 296465.51 90172.857 8000 + 1e-06 40100 12 290548.45 88402.41 8000 + 1e-06 40200 12 284112.93 86721.642 8000 + 1e-06 40300 12 277419.21 85394.11 8000 + 1e-06 40400 12 270601.67 84327.103 8000 + 1e-06 40500 12 263782.18 83363.209 8000 + 1e-06 40600 12 257075.79 82350.637 8000 + 1e-06 40700 12 250587.81 81169.87 8000 + 1e-06 40800 12 244408.86 79765.108 8000 + 1e-06 40900 12 238613.12 78159.356 8000 + 1e-06 41000 12 233263.11 76444.561 8000 + 1e-06 41100 12 228410.45 74765.108 8000 + 1e-06 41200 12 224097.82 73288.059 8000 + 1e-06 41300 12 220360.61 72170.137 8000 + 1e-06 41400 12 217228.06 71527.798 8000 + 1e-06 41500 12 214724.04 71415.43 8000 + 1e-06 41600 12 212866.32 71815.969 8000 + 1e-06 41700 12 211661 72645.932 8000 + 1e-06 41800 12 211103.8 73762.785 8000 + 1e-06 41900 12 211177.1 74986.705 8000 + 1e-06 42000 12 211607.62 76028.195 8000 + 1e-06 42100 12 212363.62 76700.039 8000 + 1e-06 42200 12 213529.03 76938.547 8000 + 1e-06 42300 12 215008.35 76693.739 8000 + 1e-06 42400 12 216674.6 75984.606 8000 + 1e-06 42500 12 218453.89 74873.786 8000 + 1e-06 42600 12 220270.22 73459.542 8000 + 1e-06 42700 12 222044.1 71860.203 8000 + 1e-06 42800 12 223693.34 70197.611 8000 + 1e-06 42900 12 225131.14 68583.075 8000 + 1e-06 43000 12 226264.5 67108.382 8000 + 1e-06 43100 12 227001.96 65842.14 8000 + 1e-06 43200 12 227259.44 64830.806 8000 + 1e-06 43300 12 226966.5 64102.73 8000 + 1e-06 43400 12 226072.23 63673.107 8000 + 1e-06 43500 12 224550.01 63547.892 8000 + 1e-06 43600 12 222400.27 63725.546 8000 + 1e-06 43700 12 219649.08 64198.122 8000 + 1e-06 43800 12 216345.77 64940.248 8000 + 1e-06 43900 12 212561.67 65898.806 8000 + 1e-06 44000 12 208386.13 66994.934 8000 + 1e-06 44100 12 203921.52 68131.378 8000 + 1e-06 44200 12 199278.14 69204.386 8000 + 1e-06 44300 12 194569.44 70118.481 8000 + 1e-06 44400 12 189909.06 70810.594 8000 + 1e-06 44500 12 185407.95 71268.155 8000 + 1e-06 44600 12 181166.51 71493.826 8000 + 1e-06 44700 12 177276.76 71524.448 8000 + 1e-06 44800 12 173823.45 71423.226 8000 + 1e-06 44900 12 170886.41 71262.132 8000 + 1e-06 45000 12 168528.37 71107.616 8000 + 1e-06 45100 12 166817.96 70991.562 8000 + 1e-06 45200 12 165820.31 70920.666 8000 + 1e-06 45300 12 165574.99 70863.13 8000 + 1e-06 45400 12 166019.37 70710.029 8000 + 1e-06 45500 12 167147.87 70350.412 8000 + 1e-06 45600 12 169082.77 69657.821 8000 + 1e-06 45700 12 171945.43 68520.345 8000 + 1e-06 45800 12 175909.9 66883.643 8000 + 1e-06 45900 12 181195.22 64747.392 8000 + 1e-06 46000 12 188023.1 62178.63 8000 + 1e-06 46100 12 196442.27 59308.946 8000 + 1e-06 46200 12 206276.92 56311.64 8000 + 1e-06 46300 12 217187.2 53375.161 8000 + 1e-06 46400 12 228713.53 50677.575 8000 + 1e-06 46500 12 240278.4 48364.725 8000 + 1e-06 46600 12 251273.01 46535.827 8000 + 1e-06 46700 12 261407.3 45239.704 8000 + 1e-06 46800 12 270264.36 44479.416 8000 + 1e-06 46900 12 277578.87 44223.038 8000 + 1e-06 47000 12 283258 44417.235 8000 + 1e-06 47100 12 287156.44 45000.19 8000 + 1e-06 47200 12 289242.87 45911.176 8000 + 1e-06 47300 12 289597.36 47095.056 8000 + 1e-06 47400 12 288380.97 48501.691 8000 + 1e-06 47500 12 285805.13 50081.427 8000 + 1e-06 47600 12 282130.22 51780.572 8000 + 1e-06 47700 12 277128.82 53385.936 8000 + 1e-06 47800 12 271407.61 54873.773 8000 + 1e-06 47900 12 265556.17 56217.287 8000 + 1e-06 48000 12 260082.32 57338.782 8000 + 1e-06 48100 12 255399.15 58166.789 8000 + 1e-06 48200 12 251785.89 58653.934 8000 + 1e-06 48300 12 249277.86 58789.891 8000 + 1e-06 48400 12 247494.11 58609.44 8000 + 1e-06 48500 12 245660.12 58192.865 8000 + 1e-06 48600 12 242968.44 57656.856 8000 + 1e-06 48700 12 238968.69 57140.878 8000 + 1e-06 48800 12 233565.17 56788.953 8000 + 1e-06 48900 12 227411.99 56720.334 8000 + 1e-06 49000 12 221053.64 57003.014 8000 + 1e-06 49100 12 215153.96 57629.419 8000 + 1e-06 49200 12 210402.16 58574.859 8000 + 1e-06 49300 12 207216.41 59750.238 8000 + 1e-06 49400 12 205860.43 61020.818 8000 + 1e-06 49500 12 206382.26 62237.849 8000 + 1e-06 49600 12 208600.44 63264.958 8000 + 1e-06 49700 12 212280.2 63999.734 8000 + 1e-06 49800 12 217167.6 64388.533 8000 + 1e-06 49900 12 223002.61 64430.977 8000 +Loop time of 0.997677 on 1 procs for 49900 steps with 12 atoms + +99.2% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.24529 | 0.24529 | 0.24529 | 0.0 | 24.59 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0.0019929 | 0.0019929 | 0.0019929 | 0.0 | 0.20 +Output | 0.0024977 | 0.0024977 | 0.0024977 | 0.0 | 0.25 +Modify | 0.74056 | 0.74056 | 0.74056 | 0.0 | 74.23 +Other | | 0.007341 | | | 0.74 + +Nlocal: 12 ave 12 max 12 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 66 ave 66 max 66 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 66 +Ave neighs/atom = 5.5 +Neighbor list builds = 0 +Dangerous builds = 0 +Total wall time: 0:00:01 diff --git a/examples/plugins/LAMMPSInterfaceCXX.cmake b/examples/plugins/LAMMPSInterfaceCXX.cmake index 4cd4510a61..6ff154dec4 100644 --- a/examples/plugins/LAMMPSInterfaceCXX.cmake +++ b/examples/plugins/LAMMPSInterfaceCXX.cmake @@ -33,90 +33,49 @@ endif() ################################################################################ # MPI configuration +# do not include the (obsolete) MPI C++ bindings which makes +# for leaner object files and avoids namespace conflicts +set(MPI_CXX_SKIP_MPICXX TRUE) if(NOT CMAKE_CROSSCOMPILING) - set(MPI_CXX_SKIP_MPICXX TRUE) - find_package(MPI QUIET) + find_package(MPI QUIET COMPONENTS CXX) option(BUILD_MPI "Build MPI version" ${MPI_FOUND}) else() option(BUILD_MPI "Build MPI version" OFF) endif() if(BUILD_MPI) - # do not include the (obsolete) MPI C++ bindings which makes - # for leaner object files and avoids namespace conflicts - set(MPI_CXX_SKIP_MPICXX TRUE) # We use a non-standard procedure to cross-compile with MPI on Windows if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND CMAKE_CROSSCOMPILING) - # Download and configure MinGW compatible MPICH development files for Windows - option(USE_MSMPI "Use Microsoft's MS-MPI SDK instead of MPICH2-1.4.1" OFF) - if(USE_MSMPI) - message(STATUS "Downloading and configuring MS-MPI 10.1 for Windows cross-compilation") - set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/msmpi-win64-devel.tar.gz" CACHE STRING "URL for MS-MPI (win64) tarball") - set(MPICH2_WIN64_DEVEL_MD5 "86314daf1bffb809f1fcbefb8a547490" CACHE STRING "MD5 checksum of MS-MPI (win64) tarball") - mark_as_advanced(MPICH2_WIN64_DEVEL_URL) - mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) + message(STATUS "Downloading and configuring MS-MPI 10.1 for Windows cross-compilation") + set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/msmpi-win64-devel.tar.gz" CACHE STRING "URL for MS-MPI (win64) tarball") + set(MPICH2_WIN64_DEVEL_MD5 "86314daf1bffb809f1fcbefb8a547490" CACHE STRING "MD5 checksum of MS-MPI (win64) tarball") + mark_as_advanced(MPICH2_WIN64_DEVEL_URL) + mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) - include(ExternalProject) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN64_DEVEL_URL} - URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmsmpi.a) - else() - message(FATAL_ERROR "Only x86 64-bit builds are supported with MS-MPI") - endif() - - ExternalProject_get_property(mpi4win_build SOURCE_DIR) - file(MAKE_DIRECTORY "${SOURCE_DIR}/include") - add_library(MPI::MPI_CXX UNKNOWN IMPORTED) - set_target_properties(MPI::MPI_CXX PROPERTIES - IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmsmpi.a" - INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" - INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - add_dependencies(MPI::MPI_CXX mpi4win_build) - - # set variables for status reporting at the end of CMake run - set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") - set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmsmpi.a") + include(ExternalProject) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + ExternalProject_Add(mpi4win_build + URL ${MPICH2_WIN64_DEVEL_URL} + URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} + CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" + BUILD_BYPRODUCTS /lib/libmsmpi.a) else() - # Download and configure custom MPICH files for Windows - message(STATUS "Downloading and configuring MPICH-1.4.1 for Windows") - set(MPICH2_WIN64_DEVEL_URL "${LAMMPS_THIRDPARTY_URL}/mpich2-win64-devel.tar.gz" CACHE STRING "URL for MPICH2 (win64) tarball") - set(MPICH2_WIN64_DEVEL_MD5 "4939fdb59d13182fd5dd65211e469f14" CACHE STRING "MD5 checksum of MPICH2 (win64) tarball") - mark_as_advanced(MPICH2_WIN64_DEVEL_URL) - mark_as_advanced(MPICH2_WIN64_DEVEL_MD5) - - include(ExternalProject) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN64_DEVEL_URL} - URL_MD5 ${MPICH2_WIN64_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmpi.a) - else() - ExternalProject_Add(mpi4win_build - URL ${MPICH2_WIN32_DEVEL_URL} - URL_MD5 ${MPICH2_WIN32_DEVEL_MD5} - CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS /lib/libmpi.a) - endif() - - ExternalProject_get_property(mpi4win_build SOURCE_DIR) - file(MAKE_DIRECTORY "${SOURCE_DIR}/include") - add_library(MPI::MPI_CXX UNKNOWN IMPORTED) - set_target_properties(MPI::MPI_CXX PROPERTIES - IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmpi.a" - INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" - INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - add_dependencies(MPI::MPI_CXX mpi4win_build) - - # set variables for status reporting at the end of CMake run - set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") - set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX") - set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmpi.a") + message(FATAL_ERROR "Only x86 64-bit builds are supported with MS-MPI") endif() + + ExternalProject_get_property(mpi4win_build SOURCE_DIR) + file(MAKE_DIRECTORY "${SOURCE_DIR}/include") + add_library(MPI::MPI_CXX UNKNOWN IMPORTED) + set_target_properties(MPI::MPI_CXX PROPERTIES + IMPORTED_LOCATION "${SOURCE_DIR}/lib/libmsmpi.a" + INTERFACE_INCLUDE_DIRECTORIES "${SOURCE_DIR}/include" + INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX=1") + add_dependencies(MPI::MPI_CXX mpi4win_build) + + # set variables for status reporting at the end of CMake run + set(MPI_CXX_INCLUDE_PATH "${SOURCE_DIR}/include") + set(MPI_CXX_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX=1") + set(MPI_CXX_LIBRARIES "${SOURCE_DIR}/lib/libmsmpi.a") else() find_package(MPI REQUIRED) option(LAMMPS_LONGLONG_TO_LONG "Workaround if your system or MPI version does not recognize 'long long' data types" OFF) diff --git a/fortran/lammps.f90 b/fortran/lammps.f90 index fdd10167bf..4baff4d03a 100644 --- a/fortran/lammps.f90 +++ b/fortran/lammps.f90 @@ -74,7 +74,9 @@ MODULE LIBLAMMPS LMP_VAR_EQUAL = 0, & ! equal-style variables (and compatible) LMP_VAR_ATOM = 1, & ! atom-style variables LMP_VAR_VECTOR = 2, & ! vector variables - LMP_VAR_STRING = 3 ! string variables (everything else) + LMP_VAR_STRING = 3, & ! string variables (everything else) + LMP_NEIGH_HALF = 0, & ! request (default) half neighbor list + LMP_NEIGH_FULL = 1 ! request full neighbor list ! Constants we set once (in the constructor) and never need to check again INTEGER(c_int), SAVE :: SIZE_TAGINT, SIZE_BIGINT, SIZE_IMAGEINT @@ -195,10 +197,11 @@ MODULE LIBLAMMPS PROCEDURE, PRIVATE :: lmp_create_atoms_bigbig GENERIC :: create_atoms => lmp_create_atoms_int, & lmp_create_atoms_bigbig - PROCEDURE :: find_pair_neighlist => lmp_find_pair_neighlist - PROCEDURE :: find_fix_neighlist => lmp_find_fix_neighlist - PROCEDURE :: find_compute_neighlist => lmp_find_compute_neighlist - PROCEDURE :: neighlist_num_elements => lmp_neighlist_num_elements + PROCEDURE :: find_pair_neighlist => lmp_find_pair_neighlist + PROCEDURE :: find_fix_neighlist => lmp_find_fix_neighlist + PROCEDURE :: find_compute_neighlist => lmp_find_compute_neighlist + PROCEDURE :: request_single_neighlist => lmp_request_single_neighlist + PROCEDURE :: neighlist_num_elements => lmp_neighlist_num_elements PROCEDURE :: neighlist_element_neighbors => lmp_neighlist_element_neighbors PROCEDURE :: version => lmp_version PROCEDURE, NOPASS :: get_os_info => lmp_get_os_info @@ -778,6 +781,15 @@ MODULE LIBLAMMPS INTEGER(c_int) :: lammps_find_compute_neighlist END FUNCTION lammps_find_compute_neighlist + FUNCTION lammps_request_single_neighlist(handle, id, flags, cutoff) BIND(C) + IMPORT :: c_int, c_double, c_ptr + IMPLICIT NONE + TYPE(c_ptr), VALUE :: handle, id + INTEGER(c_int), VALUE :: flags + REAL(c_double), VALUE :: cutoff + INTEGER(c_int) :: lammps_request_single_neighlist + END FUNCTION lammps_request_single_neighlist + FUNCTION lammps_neighlist_num_elements(handle, idx) BIND(C) IMPORT :: c_ptr, c_int TYPE(c_ptr), VALUE :: handle @@ -2942,6 +2954,36 @@ CONTAINS CALL lammps_free(Cid) END FUNCTION lmp_find_compute_neighlist + ! equivalent function to lammps_request_single_neighlist + INTEGER(c_int) FUNCTION lmp_request_single_neighlist(self, id, flags, cutoff) RESULT(idx) + CLASS(lammps), INTENT(IN) :: self + CHARACTER(LEN=*), INTENT(IN) :: id + INTEGER(c_int), INTENT(IN), OPTIONAL :: flags + REAL(c_double), INTENT(IN), OPTIONAL :: cutoff + TYPE(c_ptr) :: Cid + INTEGER(c_int) :: Cflags + REAL(c_double) :: Ccutoff + + IF (PRESENT(flags)) THEN + Cflags = flags + ELSE + Cflags = LMP_NEIGH_HALF + END IF + IF (PRESENT(cutoff)) THEN + Ccutoff = cutoff + ELSE + Ccutoff = 1.0_c_double + END IF + + Cid = f2c_string(id) + idx = lammps_request_single_neighlist(self%handle, Cid, Cflags, Ccutoff) + IF (idx < 0) THEN + CALL lmp_error(self, LMP_ERROR_WARNING + LMP_ERROR_WORLD, & + 'neighbor list build failed [Fortran/request_single_neighlist]') + END IF + CALL lammps_free(Cid) + END FUNCTION lmp_request_single_neighlist + INTEGER(c_int) FUNCTION lmp_neighlist_num_elements(self, idx) RESULT(inum) CLASS(lammps), INTENT(IN) :: self INTEGER(c_int), INTENT(IN) :: idx diff --git a/lib/atc/LammpsInterface.cpp b/lib/atc/LammpsInterface.cpp index 07b3ca6426..3912961b9d 100644 --- a/lib/atc/LammpsInterface.cpp +++ b/lib/atc/LammpsInterface.cpp @@ -561,7 +561,7 @@ bool LammpsInterface::region_bounds(const char * regionName, } void LammpsInterface::minimum_image(double & dx, double & dy, double & dz) const { - lammps_->domain->minimum_image(dx,dy,dz); + lammps_->domain->minimum_image(FLERR,dx,dy,dz); } void LammpsInterface::closest_image(const double * const xi, const double * const xj, double * const xjImage) const { diff --git a/lib/colvars/Makefile.common b/lib/colvars/Makefile.common index f0282b8caf..9203f9d158 100644 --- a/lib/colvars/Makefile.common +++ b/lib/colvars/Makefile.common @@ -32,6 +32,7 @@ COLVARS_SRCS = \ colvarbias_histogram_reweight_amd.cpp \ colvarbias_meta.cpp \ colvarbias_restraint.cpp \ + colvarbias_opes.cpp \ colvarcomp_alchlambda.cpp \ colvarcomp_angles.cpp \ colvarcomp_apath.cpp \ @@ -40,6 +41,7 @@ COLVARS_SRCS = \ colvarcomp_distances.cpp \ colvarcomp_gpath.cpp \ colvarcomp_neuralnetwork.cpp \ + colvarcomp_torchann.cpp \ colvarcomp_combination.cpp \ colvarcomp_protein.cpp \ colvarcomp_rotations.cpp \ diff --git a/lib/colvars/Makefile.deps b/lib/colvars/Makefile.deps index 61f0b1a335..82d36e53c4 100644 --- a/lib/colvars/Makefile.deps +++ b/lib/colvars/Makefile.deps @@ -52,6 +52,12 @@ $(COLVARS_OBJ_DIR)colvarbias_restraint.o: colvarbias_restraint.cpp \ colvarproxy_tcl.h colvarproxy_volmaps.h colvarvalue.h \ colvarbias_restraint.h colvarbias.h colvar.h colvarparse.h \ colvarparams.h colvardeps.h +$(COLVARS_OBJ_DIR)colvarbias_opes.o: colvarbias_opes.cpp \ + colvarmodule.h colvars_version.h colvarproxy.h colvartypes.h \ + ../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \ + colvarproxy_tcl.h colvarproxy_volmaps.h colvarvalue.h \ + colvarbias_opes.h colvarbias.h colvar.h colvarparse.h \ + colvarparams.h colvardeps.h $(COLVARS_OBJ_DIR)colvarcomp_alchlambda.o: colvarcomp_alchlambda.cpp \ colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \ ../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \ @@ -101,6 +107,11 @@ $(COLVARS_OBJ_DIR)colvarcomp_neuralnetwork.o: \ colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \ colvarproxy_volmaps.h colvar_geometricpath.h \ colvar_neuralnetworkcompute.h +$(COLVARS_OBJ_DIR)colvarcomp_torchann.o: \ + colvarcomp_torchann.cpp colvarmodule.h colvars_version.h \ + colvarvalue.h colvartypes.h colvarparse.h colvarparams.h colvar.h \ + colvardeps.h colvarcomp.h colvarcomp_torchann.h colvaratoms.h colvarproxy.h colvarproxy_io.h \ + colvarproxy_system.h colvarproxy_tcl.h $(COLVARS_OBJ_DIR)colvarcomp_combination.o: colvarcomp_combination.cpp \ colvarcomp.h colvarmodule.h colvars_version.h colvaratoms.h \ colvarproxy.h colvartypes.h ../../src/math_eigen_impl.h colvarproxy_io.h \ @@ -127,7 +138,7 @@ $(COLVARS_OBJ_DIR)colvarcomp_volmaps.o: colvarcomp_volmaps.cpp \ colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvar.o: colvar.cpp colvarmodule.h colvars_version.h \ colvarvalue.h colvartypes.h ../../src/math_eigen_impl.h colvarparse.h \ - colvarparams.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \ + colvarparams.h colvarcomp.h colvarcomp_torchann.h colvaratoms.h colvarproxy.h colvarproxy_io.h \ colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \ colvardeps.h colvar.h colvar_geometricpath.h colvarbias.h \ colvars_memstream.h @@ -152,7 +163,8 @@ $(COLVARS_OBJ_DIR)colvarmodule.o: colvarmodule.cpp colvarmodule.h \ colvarbias_histogram_reweight_amd.h colvarbias_meta.h colvarscript.h \ colvarscript_commands.h colvarscript_commands_colvar.h \ colvarscript_commands_bias.h colvaratoms.h colvarcomp.h \ - colvar_geometricpath.h colvars_memstream.h colvarmodule_refs.h + colvar_geometricpath.h colvars_memstream.h colvarmodule_refs.h \ + colvarbias_opes.h $(COLVARS_OBJ_DIR)colvarparams.o: colvarparams.cpp colvarmodule.h \ colvars_version.h colvarvalue.h colvartypes.h \ ../../src/math_eigen_impl.h colvarparams.h diff --git a/lib/colvars/colvar.cpp b/lib/colvars/colvar.cpp index 58eb87fd0e..136aa2afd5 100644 --- a/lib/colvars/colvar.cpp +++ b/lib/colvars/colvar.cpp @@ -21,6 +21,7 @@ #include "colvarbias.h" #include "colvars_memstream.h" +#include "colvarcomp_torchann.h" std::map> colvar::global_cvc_map = std::map>(); @@ -95,6 +96,12 @@ int colvar::init(std::string const &conf) if (error_code != COLVARS_OK) { return cvm::get_error(); } +#else + if (key_lookup(conf, "customFunction")) { + return cvm::error( + "Error: customFunction keyword is used, but the Lepton library is not available.\n", + COLVARS_NOT_IMPLEMENTED); + } #endif // Setup colvar as scripted function of components @@ -175,12 +182,6 @@ int colvar::init(std::string const &conf) set_enabled(f_cv_scalar, (value().type() == colvarvalue::type_scalar)); - // If using scripted biases, any colvar may receive bias forces - // and will need its gradient - if (cvm::scripted_forces()) { - enable(f_cv_gradient); - } - // check for linear combinations { bool lin = !(is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function)); @@ -311,9 +312,27 @@ int colvar::init(std::string const &conf) // Detect if we have a single component that is an alchemical lambda if (is_enabled(f_cv_single_cvc) && cvcs[0]->function_type() == "alchLambda") { enable(f_cv_external); + + static_cast(cvcs[0].get())->init_alchemy(time_step_factor); + } + + // If using scripted biases, any colvar may receive bias forces + if (cvm::scripted_forces()) { + enable(f_cv_apply_force); } error_code |= init_extended_Lagrangian(conf); + + // when total atomic forces are obtained from the previous time step, + // we cannot (currently) have colvar values and projected total forces for the same timestep + // (that would require anticipating the total force request by one timestep) + // i.e. the combination of f_cv_total_force_calc and f_cv_multiple_ts requires f_cv_total_force_current_step + // Because f_cv_total_force_current_step is static, we can hard-code this, once other features are set + // that is f_cv_external and f_cv_extended_Lagrangian + if (!is_enabled(f_cv_total_force_current_step)) { + exclude_feature_self(f_cv_multiple_ts, f_cv_total_force_calc); + } + error_code |= init_output_flags(conf); // Now that the children are defined we can solve dependencies @@ -495,8 +514,6 @@ int colvar::init_grid_parameters(std::string const &conf) { int error_code = COLVARS_OK; - colvarmodule *cv = cvm::main(); - cvm::real default_width = width; if (!key_already_set("width")) { @@ -522,34 +539,68 @@ int colvar::init_grid_parameters(std::string const &conf) if (is_enabled(f_cv_scalar)) { - if (is_enabled(f_cv_single_cvc)) { - // Get the default boundaries from the component + // Record the CVC's intrinsic boundaries, and set them as default values for the user's choice + colvarvalue cvc_lower_boundary, cvc_upper_boundary; + + if (is_enabled(f_cv_single_cvc)) { // Get the intrinsic boundaries of the CVC + if (cvcs[0]->is_enabled(f_cvc_lower_boundary)) { enable(f_cv_lower_boundary); enable(f_cv_hard_lower_boundary); - lower_boundary = + lower_boundary = cvc_lower_boundary = *(reinterpret_cast(cvcs[0]->get_param_ptr("lowerBoundary"))); } + if (cvcs[0]->is_enabled(f_cvc_upper_boundary)) { enable(f_cv_upper_boundary); enable(f_cv_hard_upper_boundary); - upper_boundary = - *(reinterpret_cast(cvcs[0]->get_param_ptr("upperBoundary"))); + upper_boundary = cvc_upper_boundary = + *(reinterpret_cast(cvcs[0]->get_param_ptr("upperBoundary"))); } } if (get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary)) { enable(f_cv_lower_boundary); - // Because this is the user's choice, we cannot assume it is a true - // physical boundary - disable(f_cv_hard_lower_boundary); + if (is_enabled(f_cv_single_cvc) && is_enabled(f_cv_hard_lower_boundary)) { + if (cvm::sqrt(dist2(lower_boundary, cvc_lower_boundary))/width > colvar_boundaries_tol) { + // The user choice is different from the CVC's default + disable(f_cv_hard_lower_boundary); + } + } } if (get_keyval(conf, "upperBoundary", upper_boundary, upper_boundary)) { enable(f_cv_upper_boundary); - disable(f_cv_hard_upper_boundary); + if (is_enabled(f_cv_single_cvc) && is_enabled(f_cv_hard_upper_boundary)) { + if (cvm::sqrt(dist2(upper_boundary, cvc_upper_boundary))/width > colvar_boundaries_tol) { + disable(f_cv_hard_upper_boundary); + } + } } + get_keyval_feature(this, conf, "hardLowerBoundary", f_cv_hard_lower_boundary, + is_enabled(f_cv_hard_lower_boundary)); + + get_keyval_feature(this, conf, "hardUpperBoundary", f_cv_hard_upper_boundary, + is_enabled(f_cv_hard_upper_boundary)); + + get_keyval(conf, "expandBoundaries", expand_boundaries, expand_boundaries); + + error_code |= parse_legacy_wall_params(conf); + error_code |= check_grid_parameters(); + } + + return error_code; +} + + +int colvar::parse_legacy_wall_params(std::string const &conf) +{ + int error_code = COLVARS_OK; + colvarmodule *cv = cvm::main(); + + if (is_enabled(f_cv_scalar)) { + // Parse legacy wall options and set up a harmonicWalls bias if needed cvm::real lower_wall_k = 0.0, upper_wall_k = 0.0; cvm::real lower_wall = 0.0, upper_wall = 0.0; @@ -603,13 +654,14 @@ harmonicWalls {\n\ } } - get_keyval_feature(this, conf, "hardLowerBoundary", f_cv_hard_lower_boundary, - is_enabled(f_cv_hard_lower_boundary)); + return error_code; +} - get_keyval_feature(this, conf, "hardUpperBoundary", f_cv_hard_upper_boundary, - is_enabled(f_cv_hard_upper_boundary)); - // consistency checks for boundaries and walls +int colvar::check_grid_parameters() +{ + int error_code = COLVARS_OK; + if (is_enabled(f_cv_lower_boundary) && is_enabled(f_cv_upper_boundary)) { if (lower_boundary >= upper_boundary) { error_code |= cvm::error("Error: the upper boundary, "+ @@ -620,7 +672,6 @@ harmonicWalls {\n\ } } - get_keyval(conf, "expandBoundaries", expand_boundaries, expand_boundaries); if (expand_boundaries && periodic_boundaries()) { error_code |= cvm::error("Error: trying to expand boundaries that already " "cover a whole period of a periodic colvar.\n", @@ -654,14 +705,15 @@ int colvar::init_extended_Lagrangian(std::string const &conf) x_ext.type(colvarvalue::type_notset); v_ext.type(value()); fr.type(value()); - const bool temp_provided = get_keyval(conf, "extendedTemp", temp, - proxy->target_temperature()); + const bool temp_provided = get_keyval(conf, "extendedTemp", temp, proxy->target_temperature()); if (is_enabled(f_cv_external)) { - // In the case of an "external" coordinate, there is no coupling potential: + // In the case of a driven external parameter in the back-end, there is no coupling potential: // only the fictitious mass is meaningful get_keyval(conf, "extendedMass", ext_mass); // Ensure that the computed restraint energy term is zero ext_force_k = 0.0; + // Then we need forces from the back-end + enable(f_cv_total_force_calc); } else { // Standard case of coupling to a geometric colvar if (temp <= 0.0) { // Then a finite temperature is required @@ -779,6 +831,7 @@ int colvar::init_components_type(const std::string& conf, const char* def_config &def_conf, &pos) ) { + cvm::increase_depth(); cvm::log("Initializing " "a new \""+std::string(def_config_key)+"\" component"+ (cvm::debug() ? ", with configuration:\n"+def_conf @@ -791,7 +844,6 @@ int colvar::init_components_type(const std::string& conf, const char* def_config } cvcs.push_back(std::shared_ptr(cvcp)); - cvm::increase_depth(); int error_code_this = cvcp->init(def_conf); if (error_code_this == COLVARS_OK) { // Checking for invalid keywords only if the parsing was successful, otherwise any @@ -851,12 +903,8 @@ void colvar::define_component_types() add_component_type("dipole angle", "dipoleAngle"); add_component_type("dihedral", "dihedral"); add_component_type("hydrogen bond", "hBond"); - - if (proxy->check_atom_name_selections_available() == COLVARS_OK) { - add_component_type("alpha helix", "alpha"); - add_component_type("dihedral principal component", "dihedralPC"); - } - + add_component_type("alpha helix", "alpha"); + add_component_type("dihedral principal component", "dihedralPC"); add_component_type("orientation", "orientation"); add_component_type("orientation angle", "orientationAngle"); add_component_type("orientation projection", "orientationProj"); @@ -888,6 +936,8 @@ void colvar::define_component_types() add_component_type("neural network CV for other CVs", "neuralNetwork"); + add_component_type("CV defined by PyTorch artifical neural network models", "torchANN"); + if (proxy->check_volmaps_available() == COLVARS_OK) { add_component_type("total value of atomic map", "mapTotal"); } @@ -1098,6 +1148,9 @@ int colvar::init_dependencies() { init_feature(f_cv_gradient, "gradient", f_type_dynamic); require_feature_children(f_cv_gradient, f_cvc_gradient); + init_feature(f_cv_apply_force, "apply_force", f_type_dynamic); + require_feature_alt(f_cv_apply_force, f_cv_gradient, f_cv_external); + init_feature(f_cv_collect_gradient, "collect_gradient", f_type_dynamic); require_feature_self(f_cv_collect_gradient, f_cv_gradient); require_feature_self(f_cv_collect_gradient, f_cv_scalar); @@ -1116,6 +1169,10 @@ int colvar::init_dependencies() { init_feature(f_cv_total_force, "total_force", f_type_dynamic); require_feature_alt(f_cv_total_force, f_cv_extended_Lagrangian, f_cv_total_force_calc); + // If this is active, the total force reported to biases (ABF / TI) is from the current step + // therefore it does not include Colvars biases -> it is a "system force" + init_feature(f_cv_total_force_current_step, "total_force_current_step", f_type_dynamic); + // Deps for explicit total force calculation init_feature(f_cv_total_force_calc, "total_force_calculation", f_type_dynamic); require_feature_self(f_cv_total_force_calc, f_cv_scalar); @@ -1134,13 +1191,15 @@ int colvar::init_dependencies() { init_feature(f_cv_extended_Lagrangian, "extended_Lagrangian", f_type_user); require_feature_self(f_cv_extended_Lagrangian, f_cv_scalar); - require_feature_self(f_cv_extended_Lagrangian, f_cv_gradient); + require_feature_self(f_cv_extended_Lagrangian, f_cv_apply_force); init_feature(f_cv_Langevin, "Langevin_dynamics", f_type_user); require_feature_self(f_cv_Langevin, f_cv_extended_Lagrangian); - init_feature(f_cv_external, "external", f_type_user); + init_feature(f_cv_external, "external_parameter", f_type_static); require_feature_self(f_cv_external, f_cv_single_cvc); + // External parameters always report the total force for current step + require_feature_self(f_cv_external, f_cv_total_force_current_step); init_feature(f_cv_single_cvc, "single_component", f_type_static); @@ -1201,10 +1260,7 @@ int colvar::init_dependencies() { init_feature(f_cv_linear, "linear", f_type_static); init_feature(f_cv_homogeneous, "homogeneous", f_type_static); - // because total forces are obtained from the previous time step, - // we cannot (currently) have colvar values and total forces for the same timestep init_feature(f_cv_multiple_ts, "multiple_timestep", f_type_static); - exclude_feature_self(f_cv_multiple_ts, f_cv_total_force_calc); // check that everything is initialized for (i = 0; i < colvardeps::f_cv_ntot; i++) { @@ -1225,6 +1281,10 @@ int colvar::init_dependencies() { feature_states[f_cv_fdiff_velocity].available = cvm::main()->proxy->simulation_running(); + // Some back-ends report current total forces for all colvars + if (cvm::main()->proxy->total_forces_same_step()) + enable(f_cv_total_force_current_step); + return COLVARS_OK; } @@ -1351,7 +1411,6 @@ int colvar::calc_cvcs(int first_cvc, size_t num_cvcs) cvm::log("Calculating colvar \""+this->name+"\", components "+ cvm::to_str(first_cvc)+" through "+cvm::to_str(first_cvc+num_cvcs)+".\n"); - colvarproxy *proxy = cvm::main()->proxy; int error_code = COLVARS_OK; error_code |= check_cvc_range(first_cvc, num_cvcs); @@ -1359,7 +1418,7 @@ int colvar::calc_cvcs(int first_cvc, size_t num_cvcs) return error_code; } - if ((cvm::step_relative() > 0) && (!proxy->total_forces_same_step())){ + if ((cvm::step_relative() > 0) && (!is_enabled(f_cv_total_force_current_step))){ // Use Jacobian derivative from previous timestep error_code |= calc_cvc_total_force(first_cvc, num_cvcs); } @@ -1367,7 +1426,7 @@ int colvar::calc_cvcs(int first_cvc, size_t num_cvcs) error_code |= calc_cvc_values(first_cvc, num_cvcs); error_code |= calc_cvc_gradients(first_cvc, num_cvcs); error_code |= calc_cvc_Jacobians(first_cvc, num_cvcs); - if (proxy->total_forces_same_step()){ + if (is_enabled(f_cv_total_force_current_step)){ // Use Jacobian derivative from this timestep error_code |= calc_cvc_total_force(first_cvc, num_cvcs); } @@ -1384,10 +1443,9 @@ int colvar::collect_cvc_data() if (cvm::debug()) cvm::log("Calculating colvar \""+this->name+"\"'s properties.\n"); - colvarproxy *proxy = cvm::main()->proxy; int error_code = COLVARS_OK; - if ((cvm::step_relative() > 0) && (!proxy->total_forces_same_step())){ + if ((cvm::step_relative() > 0) && (!is_enabled(f_cv_total_force_current_step))){ // Total force depends on Jacobian derivative from previous timestep // collect_cvc_total_forces() uses the previous value of jd error_code |= collect_cvc_total_forces(); @@ -1395,7 +1453,7 @@ int colvar::collect_cvc_data() error_code |= collect_cvc_values(); error_code |= collect_cvc_gradients(); error_code |= collect_cvc_Jacobians(); - if (proxy->total_forces_same_step()){ + if (is_enabled(f_cv_total_force_current_step)){ // Use Jacobian derivative from this timestep error_code |= collect_cvc_total_forces(); } @@ -1609,22 +1667,20 @@ int colvar::collect_cvc_total_forces() if (is_enabled(f_cv_total_force_calc)) { ft.reset(); - if (cvm::step_relative() > 0) { - // get from the cvcs the total forces from the PREVIOUS step - for (size_t i = 0; i < cvcs.size(); i++) { - if (!cvcs[i]->is_enabled()) continue; - if (cvm::debug()) - cvm::log("Colvar component no. "+cvm::to_str(i+1)+ - " within colvar \""+this->name+"\" has total force "+ - cvm::to_str((cvcs[i])->total_force(), - cvm::cv_width, cvm::cv_prec)+".\n"); - // linear combination is assumed - ft += (cvcs[i])->total_force() * (cvcs[i])->sup_coeff / active_cvc_square_norm; - } + for (size_t i = 0; i < cvcs.size(); i++) { + if (!cvcs[i]->is_enabled()) continue; + if (cvm::debug()) + cvm::log("Colvar component no. "+cvm::to_str(i+1)+ + " within colvar \""+this->name+"\" has total force "+ + cvm::to_str((cvcs[i])->total_force(), + cvm::cv_width, cvm::cv_prec)+".\n"); + // linear combination is assumed + ft += (cvcs[i])->total_force() * (cvcs[i])->sup_coeff / active_cvc_square_norm; } if (!(is_enabled(f_cv_hide_Jacobian) && is_enabled(f_cv_subtract_applied_force))) { - // add the Jacobian force to the total force, and don't apply any silent + // This is by far the most common case + // Add the Jacobian force to the total force, and don't apply any silent // correction internally: biases such as colvarbias_abf will handle it // If f_cv_hide_Jacobian is enabled, a force of -fj is present in ft due to the // Jacobian-compensating force @@ -1632,6 +1688,10 @@ int colvar::collect_cvc_total_forces() } } + if (is_enabled(f_cv_total_force_current_step)) { + // Report total force value without waiting for calc_colvar_properties() + ft_reported = ft; + } return COLVARS_OK; } @@ -1733,12 +1793,15 @@ int colvar::calc_colvar_properties() // But we report values at the beginning of the timestep (value at t=0 on the first timestep) x_reported = x_ext; v_reported = v_ext; - // the "total force" with the extended Lagrangian is - // calculated in update_forces_energy() below + // the "total force" for the extended Lagrangian is calculated in update_forces_energy() below + // A future improvement could compute a "system force" here, borrowing a part of update_extended_Lagrangian() + // this would change the behavior of eABF with respect to other biases + // by enabling f_cv_total_force_current_step, and reducing the total force to a system force + // giving the behavior of f_cv_subtract_applied_force - this is correct for WTM-eABF etc. } else { - if (is_enabled(f_cv_subtract_applied_force)) { + if (is_enabled(f_cv_subtract_applied_force) && !cvm::proxy->total_forces_same_step()) { // correct the total force only if it has been measured // TODO add a specific test instead of relying on sq norm if (ft.norm2() > 0.0) { @@ -1825,7 +1888,8 @@ void colvar::update_extended_Lagrangian() // Integrate with slow timestep (if time_step_factor != 1) cvm::real dt = cvm::dt() * cvm::real(time_step_factor); - colvarvalue f_ext(fr.type()); // force acting on the extended variable + // Force acting on the extended variable + colvarvalue f_ext(fr.type()); f_ext.reset(); if (is_enabled(f_cv_external)) { @@ -1834,13 +1898,13 @@ void colvar::update_extended_Lagrangian() f += fb_actual; } - // fr: bias force on extended variable (without harmonic spring), for output in trajectory - fr = f; - // External force has been scaled for an inner-timestep impulse (for the back-end integrator) // here we scale it back because this integrator uses only the outer (long) timestep f_ext = f / cvm::real(time_step_factor); + // fr: bias force on extended variable (without harmonic spring), for output in trajectory + fr = f_ext; + colvarvalue f_system(fr.type()); // force exterted by the system on the extended DOF if (is_enabled(f_cv_external)) { @@ -1863,14 +1927,18 @@ void colvar::update_extended_Lagrangian() } f_ext += f_system; - if (is_enabled(f_cv_subtract_applied_force)) { - // Report a "system" force without the biases on this colvar - // that is, just the spring force (or alchemical force) - ft_reported = f_system; - } else { - // The total force acting on the extended variable is f_ext - // This will be used in the next timestep - ft_reported = f_ext; + if ( ! is_enabled(f_cv_total_force_current_step)) { + if (is_enabled(f_cv_subtract_applied_force)) { + // Report a "system" force without the biases on this colvar + // that is, just the spring force (or alchemical force) + ft_reported = f_system; + } else { + // The total force acting on the extended variable is f_ext + // This will be used in the next timestep + ft_reported = f_ext; + } + // Since biases have already been updated, this ft_reported will only be + // communicated to biases at the next timestep } // backup in case we need to revert this integration timestep @@ -2184,12 +2252,10 @@ int colvar::set_cvc_param(std::string const ¶m_name, void const *new_value) bool colvar::periodic_boundaries(colvarvalue const &lb, colvarvalue const &ub) const { if (period > 0.0) { - if ( ((cvm::sqrt(this->dist2(lb, ub))) / this->width) - < 1.0E-10 ) { + if (((cvm::sqrt(this->dist2(lb, ub))) / this->width) < colvar_boundaries_tol) { return true; } } - return false; } @@ -2347,6 +2413,11 @@ int colvar::set_state_params(std::string const &conf) cvm::to_str(x)+"\n"); x_restart = x; after_restart = true; + // Externally driven cv (e.g. alchemical lambda) is imposed by restart value + if (is_enabled(f_cv_external) && is_enabled(f_cv_extended_Lagrangian)) { + // Request immediate sync of driven parameter to back-end code + cvcs[0]->set_value(x, true); + } } if (is_enabled(f_cv_extended_Lagrangian)) { @@ -2489,8 +2560,14 @@ std::string const colvar::get_state_params() const os << " name " << name << "\n" << " x " << std::setprecision(cvm::cv_prec) - << std::setw(cvm::cv_width) - << x << "\n"; + << std::setw(cvm::cv_width); + if (is_enabled(f_cv_external) && is_enabled(f_cv_extended_Lagrangian)) { + // For an external colvar, x is one timestep in the future after integration + // write x at beginning of timestep + os << x_reported << "\n"; + } else { + os << x << "\n"; + } if (is_enabled(f_cv_output_velocity)) { os << " v " diff --git a/lib/colvars/colvar.h b/lib/colvars/colvar.h index 443e1e4bdd..1db313f416 100644 --- a/lib/colvars/colvar.h +++ b/lib/colvars/colvar.h @@ -263,6 +263,12 @@ public: /// Init defaults for grid options int init_grid_parameters(std::string const &conf); + /// Consistency check for the grid paramaters + int check_grid_parameters(); + + /// Read legacy wall keyword (these are biases now) + int parse_legacy_wall_params(std::string const &conf); + /// Init extended Lagrangian parameters int init_extended_Lagrangian(std::string const &conf); @@ -633,6 +639,7 @@ public: class euler_psi; class euler_theta; class neuralNetwork; + class torchANN; class customColvar; // non-scalar components @@ -753,7 +760,7 @@ inline colvarvalue const & colvar::total_force() const inline void colvar::add_bias_force(colvarvalue const &force) { - check_enabled(f_cv_gradient, + check_enabled(f_cv_apply_force, std::string("applying a force to the variable \""+name+"\"")); if (cvm::debug()) { cvm::log("Adding biasing force "+cvm::to_str(force)+" to colvar \""+name+"\".\n"); @@ -778,4 +785,10 @@ inline void colvar::reset_bias_force() { fb_actual.reset(); } + +namespace { + // Tolerance parameter to decide when two boundaries coincide + constexpr cvm::real colvar_boundaries_tol = 1.0e-10; +} + #endif diff --git a/lib/colvars/colvar_rotation_derivative.h b/lib/colvars/colvar_rotation_derivative.h index 50f4f1aa97..ceaf728c36 100644 --- a/lib/colvars/colvar_rotation_derivative.h +++ b/lib/colvars/colvar_rotation_derivative.h @@ -5,11 +5,21 @@ #include #include +#ifndef _noalias +#if defined(__INTEL_COMPILER) || (defined(__PGI) && !defined(__NVCOMPILER)) +#define _noalias restrict +#elif defined(__GNUC__) || defined(__INTEL_LLVM_COMPILER) || defined(__NVCOMPILER) +#define _noalias __restrict +#else +#define _noalias +#endif +#endif + /// \brief Helper function for loading the ia-th atom in the vector pos to x, y and z (C++11 SFINAE is used) template ::value, bool>::type = true> inline void read_atom_coord( size_t ia, const std::vector& pos, - cvm::real* x, cvm::real* y, cvm::real* z) { + cvm::real* _noalias x, cvm::real* _noalias y, cvm::real* _noalias z) { *x = pos[ia].x; *y = pos[ia].y; *z = pos[ia].z; @@ -18,7 +28,7 @@ inline void read_atom_coord( template ::value, bool>::type = true> inline void read_atom_coord( size_t ia, const std::vector& pos, - cvm::real* x, cvm::real* y, cvm::real* z) { + cvm::real* _noalias x, cvm::real* _noalias y, cvm::real* _noalias z) { *x = pos[ia].pos.x; *y = pos[ia].pos.y; *z = pos[ia].pos.z; @@ -26,9 +36,9 @@ inline void read_atom_coord( /// \brief Helper enum class for specifying options in rotation_derivative::prepare_derivative enum class rotation_derivative_dldq { - /// Require the derivative of the leading eigenvalue with respect to the atom coordinats + /// Require the derivative of the leading eigenvalue with respect to the atom coordinates use_dl = 1 << 0, - /// Require the derivative of the leading eigenvector with respect to the atom coordinats + /// Require the derivative of the leading eigenvector with respect to the atom coordinates use_dq = 1 << 1 }; @@ -327,12 +337,13 @@ struct rotation_derivative { * @param[out] dq0_out The output of derivative of Q * @param[out] ds_out The output of derivative of overlap matrix S */ + template void calc_derivative_impl( const cvm::rvector (&ds)[4][4], - cvm::rvector* const dl0_out, - cvm::vector1d* const dq0_out, - cvm::matrix2d* const ds_out) const { - if (ds_out != nullptr) { + cvm::rvector* _noalias const dl0_out, + cvm::vector1d* _noalias const dq0_out, + cvm::matrix2d* _noalias const ds_out) const { + if (use_ds) { // this code path is for debug_gradients, so not necessary to unroll the loop *ds_out = cvm::matrix2d(4, 4); for (int i = 0; i < 4; ++i) { @@ -341,7 +352,7 @@ struct rotation_derivative { } } } - if (dl0_out != nullptr) { + if (use_dl) { /* manually loop unrolling of the following loop: dl0_1.reset(); for (size_t i = 0; i < 4; i++) { @@ -367,7 +378,7 @@ struct rotation_derivative { tmp_Q0Q0[3][2] * ds[3][2] + tmp_Q0Q0[3][3] * ds[3][3]; } - if (dq0_out != nullptr) { + if (use_dq) { // we can skip this check if a fixed-size array is used if (dq0_out->size() != 4) dq0_out->resize(4); /* manually loop unrolling of the following loop: @@ -462,32 +473,21 @@ struct rotation_derivative { * @param[out] ds_1_out The output of derivative of overlap matrix S with * respect to ia-th atom of group 1 */ + template void calc_derivative_wrt_group1( - size_t ia, cvm::rvector* const dl0_1_out = nullptr, - cvm::vector1d* const dq0_1_out = nullptr, - cvm::matrix2d* const ds_1_out = nullptr) const { - if (dl0_1_out == nullptr && dq0_1_out == nullptr) return; + size_t ia, cvm::rvector* _noalias const dl0_1_out = nullptr, + cvm::vector1d* _noalias const dq0_1_out = nullptr, + cvm::matrix2d* _noalias const ds_1_out = nullptr) const { + // if (dl0_1_out == nullptr && dq0_1_out == nullptr) return; cvm::real a2x, a2y, a2z; // we can get rid of the helper function read_atom_coord if C++17 (constexpr) is available read_atom_coord(ia, m_pos2, &a2x, &a2y, &a2z); - cvm::rvector ds_1[4][4]; - ds_1[0][0].set( a2x, a2y, a2z); - ds_1[1][0].set( 0.0, a2z, -a2y); - ds_1[0][1] = ds_1[1][0]; - ds_1[2][0].set(-a2z, 0.0, a2x); - ds_1[0][2] = ds_1[2][0]; - ds_1[3][0].set( a2y, -a2x, 0.0); - ds_1[0][3] = ds_1[3][0]; - ds_1[1][1].set( a2x, -a2y, -a2z); - ds_1[2][1].set( a2y, a2x, 0.0); - ds_1[1][2] = ds_1[2][1]; - ds_1[3][1].set( a2z, 0.0, a2x); - ds_1[1][3] = ds_1[3][1]; - ds_1[2][2].set(-a2x, a2y, -a2z); - ds_1[3][2].set( 0.0, a2z, a2y); - ds_1[2][3] = ds_1[3][2]; - ds_1[3][3].set(-a2x, -a2y, a2z); - calc_derivative_impl(ds_1, dl0_1_out, dq0_1_out, ds_1_out); + const cvm::rvector ds_1[4][4] = { + {{ a2x, a2y, a2z}, { 0.0, a2z, -a2y}, {-a2z, 0.0, a2x}, { a2y, -a2x, 0.0}}, + {{ 0.0, a2z, -a2y}, { a2x, -a2y, -a2z}, { a2y, a2x, 0.0}, { a2z, 0.0, a2x}}, + {{-a2z, 0.0, a2x}, { a2y, a2x, 0.0}, {-a2x, a2y, -a2z}, { 0.0, a2z, a2y}}, + {{ a2y, -a2x, 0.0}, { a2z, 0.0, a2x}, { 0.0, a2z, a2y}, {-a2x, -a2y, a2z}}}; + calc_derivative_impl(ds_1, dl0_1_out, dq0_1_out, ds_1_out); } /*! @brief Calculate the derivatives of S, the leading eigenvalue L and * the leading eigenvector Q with respect to `m_pos2` @@ -499,32 +499,21 @@ struct rotation_derivative { * @param[out] ds_2_out The output of derivative of overlap matrix S with * respect to ia-th atom of group 2 */ + template void calc_derivative_wrt_group2( - size_t ia, cvm::rvector* const dl0_2_out = nullptr, - cvm::vector1d* const dq0_2_out = nullptr, - cvm::matrix2d* const ds_2_out = nullptr) const { - if (dl0_2_out == nullptr && dq0_2_out == nullptr) return; + size_t ia, cvm::rvector* _noalias const dl0_2_out = nullptr, + cvm::vector1d* _noalias const dq0_2_out = nullptr, + cvm::matrix2d* _noalias const ds_2_out = nullptr) const { + // if (dl0_2_out == nullptr && dq0_2_out == nullptr) return; cvm::real a1x, a1y, a1z; // we can get rid of the helper function read_atom_coord if C++17 (constexpr) is available read_atom_coord(ia, m_pos1, &a1x, &a1y, &a1z); - cvm::rvector ds_2[4][4]; - ds_2[0][0].set( a1x, a1y, a1z); - ds_2[1][0].set( 0.0, -a1z, a1y); - ds_2[0][1] = ds_2[1][0]; - ds_2[2][0].set( a1z, 0.0, -a1x); - ds_2[0][2] = ds_2[2][0]; - ds_2[3][0].set(-a1y, a1x, 0.0); - ds_2[0][3] = ds_2[3][0]; - ds_2[1][1].set( a1x, -a1y, -a1z); - ds_2[2][1].set( a1y, a1x, 0.0); - ds_2[1][2] = ds_2[2][1]; - ds_2[3][1].set( a1z, 0.0, a1x); - ds_2[1][3] = ds_2[3][1]; - ds_2[2][2].set(-a1x, a1y, -a1z); - ds_2[3][2].set( 0.0, a1z, a1y); - ds_2[2][3] = ds_2[3][2]; - ds_2[3][3].set(-a1x, -a1y, a1z); - calc_derivative_impl(ds_2, dl0_2_out, dq0_2_out, ds_2_out); + const cvm::rvector ds_2[4][4] = { + {{ a1x, a1y, a1z}, { 0.0, -a1z, a1y}, { a1z, 0.0, -a1x}, {-a1y, a1x, 0.0}}, + {{ 0.0, -a1z, a1y}, { a1x, -a1y, -a1z}, { a1y, a1x, 0.0}, { a1z, 0.0, a1x}}, + {{ a1z, 0.0, -a1x}, { a1y, a1x, 0.0}, {-a1x, a1y, -a1z}, { 0.0, a1z, a1y}}, + {{-a1y, a1x, 0.0}, { a1z, 0.0, a1x}, { 0.0, a1z, a1y}, {-a1x, -a1y, a1z}}}; + calc_derivative_impl(ds_2, dl0_2_out, dq0_2_out, ds_2_out); } }; @@ -585,10 +574,7 @@ void debug_gradients( cvm::real S_new_eigval[4]; cvm::real S_new_eigvec[4][4]; for (size_t ia = 0; ia < pos2.size(); ++ia) { - // cvm::real const &a1x = pos1[ia].x; - // cvm::real const &a1y = pos1[ia].y; - // cvm::real const &a1z = pos1[ia].z; - deriv.calc_derivative_wrt_group2(ia, &dl0_2, &dq0_2, &ds_2); + deriv.template calc_derivative_wrt_group2(ia, &dl0_2, &dq0_2, &ds_2); // make an infitesimal move along each cartesian coordinate of // this atom, and solve again the eigenvector problem for (size_t comp = 0; comp < 3; comp++) { diff --git a/lib/colvars/colvaratoms.cpp b/lib/colvars/colvaratoms.cpp index e15b9301a1..054db505f3 100644 --- a/lib/colvars/colvaratoms.cpp +++ b/lib/colvars/colvaratoms.cpp @@ -673,7 +673,7 @@ int cvm::atom_group::add_atom_numbers(std::string const &numbers_conf) } -int cvm::atom_group::add_index_group(std::string const &index_group_name) +int cvm::atom_group::add_index_group(std::string const &index_group_name, bool silent) { std::vector const &index_group_names = cvm::main()->index_group_names; @@ -687,7 +687,10 @@ int cvm::atom_group::add_index_group(std::string const &index_group_name) } if (i_group >= index_group_names.size()) { - return cvm::error("Error: could not find index group "+ + if (silent) + return COLVARS_INPUT_ERROR; + else + return cvm::error("Error: could not find index group "+ index_group_name+" among those already provided.\n", COLVARS_INPUT_ERROR); } @@ -1055,6 +1058,14 @@ void cvm::atom_group::calc_apply_roto_translation() } } + if (is_enabled(f_ag_fit_gradients) && !b_dummy) { + // Save the unrotated frame for fit gradients + pos_unrotated.resize(size()); + for (size_t i = 0; i < size(); ++i) { + pos_unrotated[i] = atoms[i].pos; + } + } + if (is_enabled(f_ag_rotate)) { // rotate the group (around the center of geometry if f_ag_center is // enabled, around the origin otherwise) @@ -1217,23 +1228,30 @@ void cvm::atom_group::calc_fit_gradients() if (cvm::debug()) cvm::log("Calculating fit gradients.\n"); + cvm::atom_group *group_for_fit = fitting_group ? fitting_group : this; + + auto accessor_main = [this](size_t i){return atoms[i].grad;}; + auto accessor_fitting = [&group_for_fit](size_t j, const cvm::rvector& grad){group_for_fit->fit_gradients[j] = grad;}; if (is_enabled(f_ag_center) && is_enabled(f_ag_rotate)) - calc_fit_gradients_impl(); + calc_fit_forces_impl(accessor_main, accessor_fitting); if (is_enabled(f_ag_center) && !is_enabled(f_ag_rotate)) - calc_fit_gradients_impl(); + calc_fit_forces_impl(accessor_main, accessor_fitting); if (!is_enabled(f_ag_center) && is_enabled(f_ag_rotate)) - calc_fit_gradients_impl(); + calc_fit_forces_impl(accessor_main, accessor_fitting); if (!is_enabled(f_ag_center) && !is_enabled(f_ag_rotate)) - calc_fit_gradients_impl(); + calc_fit_forces_impl(accessor_main, accessor_fitting); if (cvm::debug()) cvm::log("Done calculating fit gradients.\n"); } -template -void cvm::atom_group::calc_fit_gradients_impl() { - cvm::atom_group *group_for_fit = fitting_group ? fitting_group : this; +template +void cvm::atom_group::calc_fit_forces_impl( + main_force_accessor_T accessor_main, + fitting_force_accessor_T accessor_fitting) const { + const cvm::atom_group *group_for_fit = fitting_group ? fitting_group : this; // the center of geometry contribution to the gradients cvm::rvector atom_grad; // the rotation matrix contribution to the gradients @@ -1243,17 +1261,13 @@ void cvm::atom_group::calc_fit_gradients_impl() { cvm::vector1d dq0_1(4); // loop 1: iterate over the current atom group for (size_t i = 0; i < size(); i++) { - cvm::atom_pos pos_orig; if (B_ag_center) { - atom_grad += atoms[i].grad; - if (B_ag_rotate) pos_orig = rot_inv * (atoms[i].pos - ref_pos_cog); - } else { - if (B_ag_rotate) pos_orig = atoms[i].pos; + atom_grad += accessor_main(i); } if (B_ag_rotate) { // calculate \partial(R(q) \vec{x}_i)/\partial q) \cdot \partial\xi/\partial\vec{x}_i cvm::quaternion const dxdq = - rot.q.position_derivative_inner(pos_orig, atoms[i].grad); + rot.q.position_derivative_inner(pos_unrotated[i], accessor_main(i)); sum_dxdq[0] += dxdq[0]; sum_dxdq[1] += dxdq[1]; sum_dxdq[2] += dxdq[2]; @@ -1261,26 +1275,45 @@ void cvm::atom_group::calc_fit_gradients_impl() { } } if (B_ag_center) { - if (B_ag_rotate) atom_grad = rot.inverse().matrix() * atom_grad; + if (B_ag_rotate) atom_grad = rot_inv * atom_grad; atom_grad *= (-1.0)/(cvm::real(group_for_fit->size())); } // loop 2: iterate over the fitting group if (B_ag_rotate) rot_deriv->prepare_derivative(rotation_derivative_dldq::use_dq); for (size_t j = 0; j < group_for_fit->size(); j++) { + cvm::rvector fitting_force_grad{0, 0, 0}; if (B_ag_center) { - group_for_fit->fit_gradients[j] = atom_grad; + fitting_force_grad += atom_grad; } if (B_ag_rotate) { - rot_deriv->calc_derivative_wrt_group1(j, nullptr, &dq0_1); + rot_deriv->calc_derivative_wrt_group1(j, nullptr, &dq0_1); // multiply by {\partial q}/\partial\vec{x}_j and add it to the fit gradients - group_for_fit->fit_gradients[j] += sum_dxdq[0] * dq0_1[0] + - sum_dxdq[1] * dq0_1[1] + - sum_dxdq[2] * dq0_1[2] + - sum_dxdq[3] * dq0_1[3]; + fitting_force_grad += sum_dxdq[0] * dq0_1[0] + + sum_dxdq[1] * dq0_1[1] + + sum_dxdq[2] * dq0_1[2] + + sum_dxdq[3] * dq0_1[3]; } + if (cvm::debug()) { + cvm::log(cvm::to_str(fitting_force_grad)); + } + accessor_fitting(j, fitting_force_grad); } } +template +void cvm::atom_group::calc_fit_forces( + main_force_accessor_T accessor_main, + fitting_force_accessor_T accessor_fitting) const { + if (is_enabled(f_ag_center) && is_enabled(f_ag_rotate)) + calc_fit_forces_impl(accessor_main, accessor_fitting); + if (is_enabled(f_ag_center) && !is_enabled(f_ag_rotate)) + calc_fit_forces_impl(accessor_main, accessor_fitting); + if (!is_enabled(f_ag_center) && is_enabled(f_ag_rotate)) + calc_fit_forces_impl(accessor_main, accessor_fitting); + if (!is_enabled(f_ag_center) && !is_enabled(f_ag_rotate)) + calc_fit_forces_impl(accessor_main, accessor_fitting); +} + std::vector cvm::atom_group::positions() const { @@ -1452,17 +1485,72 @@ void cvm::atom_group::apply_force(cvm::rvector const &force) return; } - if (is_enabled(f_ag_rotate)) { + auto ag_force = get_group_force_object(); + for (size_t i = 0; i < size(); ++i) { + ag_force.add_atom_force(i, atoms[i].mass / total_mass * force); + } +} - const auto rot_inv = rot.inverse().matrix(); - for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) { - ai->apply_force(rot_inv * ((ai->mass/total_mass) * force)); +cvm::atom_group::group_force_object cvm::atom_group::get_group_force_object() { + return cvm::atom_group::group_force_object(this); +} + +cvm::atom_group::group_force_object::group_force_object(cvm::atom_group* ag): +m_ag(ag), m_group_for_fit(m_ag->fitting_group ? m_ag->fitting_group : m_ag), +m_has_fitting_force(m_ag->is_enabled(f_ag_center) || m_ag->is_enabled(f_ag_rotate)) { + if (m_has_fitting_force) { + if (m_ag->group_forces.size() != m_ag->size()) { + m_ag->group_forces.assign(m_ag->size(), 0); + } else { + std::fill(m_ag->group_forces.begin(), + m_ag->group_forces.end(), 0); } + } +} +cvm::atom_group::group_force_object::~group_force_object() { + if (m_has_fitting_force) { + apply_force_with_fitting_group(); + } +} + +void cvm::atom_group::group_force_object::add_atom_force(size_t i, const cvm::rvector& force) { + if (m_has_fitting_force) { + m_ag->group_forces[i] += force; } else { + // Apply the force directly if we don't use fitting + (*m_ag)[i].apply_force(force); + } +} - for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) { - ai->apply_force((ai->mass/total_mass) * force); +void cvm::atom_group::group_force_object::apply_force_with_fitting_group() { + const cvm::rmatrix rot_inv = m_ag->rot.inverse().matrix(); + if (cvm::debug()) { + cvm::log("Applying force on main group " + m_ag->name + ":\n"); + } + for (size_t ia = 0; ia < m_ag->size(); ++ia) { + const cvm::rvector f_ia = rot_inv * m_ag->group_forces[ia]; + (*m_ag)[ia].apply_force(f_ia); + if (cvm::debug()) { + cvm::log(cvm::to_str(f_ia)); + } + } + // Gradients are only available with scalar components, so for a scalar component, + // if f_ag_fit_gradients is disabled, then the forces on the fitting group is not + // computed. For a vector component, we can only know the forces on the fitting + // group, but checking this flag can mimic results that the users expect (if + // "enableFitGradients no" then there is no force on the fitting group). + if (!m_ag->b_dummy && m_ag->is_enabled(f_ag_fit_gradients)) { + auto accessor_main = [this](size_t i){return m_ag->group_forces[i];}; + auto accessor_fitting = [this](size_t j, const cvm::rvector& fitting_force){ + (*(m_group_for_fit))[j].apply_force(fitting_force); + }; + if (cvm::debug()) { + cvm::log("Applying force on the fitting group of main group" + m_ag->name + ":\n"); + } + m_ag->calc_fit_forces(accessor_main, accessor_fitting); + if (cvm::debug()) { + cvm::log("Done applying force on the fitting group of main group" + m_ag->name + ":\n"); } } } diff --git a/lib/colvars/colvaratoms.h b/lib/colvars/colvaratoms.h index d16ca7bd56..528e849df0 100644 --- a/lib/colvars/colvaratoms.h +++ b/lib/colvars/colvaratoms.h @@ -194,7 +194,7 @@ public: int add_atom_numbers(std::string const &numbers_conf); int add_atoms_of_group(atom_group const * ag); - int add_index_group(std::string const &index_group_name); + int add_index_group(std::string const &index_group_name, bool silent = false); int add_atom_numbers_range(std::string const &range_conf); int add_atom_name_residue_range(std::string const &psf_segid, std::string const &range_conf); @@ -257,8 +257,63 @@ protected: /// \brief Index in the colvarproxy arrays (if the group is scalable) int index; + /// \brief The temporary forces acting on the main group atoms. + /// Currently this is only used for calculating the fitting group forces for + /// non-scalar components. + std::vector group_forces; + public: + /*! @class group_force_object + * @brief A helper class for applying forces on an atom group in a way that + * is aware of the fitting group. NOTE: you are encouraged to use + * get_group_force_object() to get an instance of group_force_object + * instead of constructing directly. + */ + class group_force_object { + public: + /*! @brief Constructor of group_force_object + * @param ag The pointer to the atom group that forces will be applied on. + */ + group_force_object(cvm::atom_group* ag); + /*! @brief Destructor of group_force_object + */ + ~group_force_object(); + /*! @brief Apply force to atom i + * @param i The i-th of atom in the atom group. + * @param force The force being added to atom i. + * + * The function can be used as follows, + * @code + * // In your colvar::cvc::apply_force() loop of a component: + * auto ag_force = atoms->get_group_force_object(); + * for (ia = 0; ia < atoms->size(); ia++) { + * const cvm::rvector f = compute_force_on_atom_ia(); + * ag_force.add_atom_force(ia, f); + * } + * @endcode + * There are actually two scenarios under the hood: + * (i) If the atom group does not have a fitting group, then the force is + * added to atom i directly; + * (ii) If the atom group has a fitting group, the force on atom i will just + * be temporary stashed into ag->group_forces. At the end of the loop + * of apply_force(), the destructor ~group_force_object() will be called, + * which then call apply_force_with_fitting_group(). The forces on the + * main group will be rotated back by multiplying ag->group_forces with + * the inverse rotation. The forces on the fitting group (if + * enableFitGradients is on) will be calculated by calling + * calc_fit_forces. + */ + void add_atom_force(size_t i, const cvm::rvector& force); + private: + cvm::atom_group* m_ag; + cvm::atom_group* m_group_for_fit; + bool m_has_fitting_force; + void apply_force_with_fitting_group(); + }; + + group_force_object get_group_force_object(); + inline cvm::atom & operator [] (size_t const i) { return atoms[i]; @@ -423,6 +478,9 @@ private: /// \brief Center of geometry before any fitting cvm::atom_pos cog_orig; + /// \brief Unrotated atom positions for fit gradients + std::vector pos_unrotated; + public: /// \brief Return the center of geometry of the atomic positions @@ -497,15 +555,60 @@ public: /// \brief Calculate the derivatives of the fitting transformation void calc_fit_gradients(); -/*! @brief Actual implementation of `calc_fit_gradients`. The template is +/*! @brief Actual implementation of `calc_fit_gradients` and + * `calc_fit_forces`. The template is * used to avoid branching inside the loops in case that the CPU * branch prediction is broken (or further migration to GPU code). * @tparam B_ag_center Centered the reference to origin? This should follow * the value of `is_enabled(f_ag_center)`. * @tparam B_ag_rotate Calculate the optimal rotation? This should follow * the value of `is_enabled(f_ag_rotate)`. + * @tparam main_force_accessor_T The type of accessor of the main + * group forces or gradients acting on the rotated frame. + * @tparam fitting_force_accessor_T The type of accessor of the fitting group + * forces or gradients. + * @param accessor_main The accessor of the main group forces or gradients. + * accessor_main(i) should return the i-th force or gradient of the + * rotated main group. + * @param accessor_fitting The accessor of the fitting group forces or gradients. + * accessor_fitting(j, v) should store/apply the j-th atom gradient or + * force in the fitting group. + * + * This function is used to (i) project the gradients of CV with respect to + * rotated main group atoms to fitting group atoms, or (ii) project the forces + * on rotated main group atoms to fitting group atoms, by the following two steps + * (using the goal (ii) for example): + * (1) Loop over the positions of main group atoms and call cvm::quaternion::position_derivative_inner + * to project the forces on rotated main group atoms to the forces on quaternion. + * (2) Loop over the positions of fitting group atoms, compute the gradients of + * \f$\mathbf{q}\f$ with respect to the position of each atom, and then multiply + * that with the force on \f$\mathbf{q}\f$ (chain rule). */ - template void calc_fit_gradients_impl(); + template + void calc_fit_forces_impl( + main_force_accessor_T accessor_main, + fitting_force_accessor_T accessor_fitting) const; + +/*! @brief Calculate or apply the fitting group forces from the main group forces. + * @tparam main_force_accessor_T The type of accessor of the main + * group forces or gradients. + * @tparam fitting_force_accessor_T The type of accessor of the fitting group + * forces or gradients. + * @param accessor_main The accessor of the main group forces or gradients. + * accessor_main(i) should return the i-th force or gradient of the + * main group. + * @param accessor_fitting The accessor of the fitting group forces or gradients. + * accessor_fitting(j, v) should store/apply the j-th atom gradient or + * force in the fitting group. + * + * This function just dispatches the parameters to calc_fit_forces_impl that really + * performs the calculations. + */ + template + void calc_fit_forces( + main_force_accessor_T accessor_main, + fitting_force_accessor_T accessor_fitting) const; /// \brief Derivatives of the fitting transformation std::vector fit_gradients; diff --git a/lib/colvars/colvarbias.cpp b/lib/colvars/colvarbias.cpp index fdffdc1794..43b54d672f 100644 --- a/lib/colvars/colvarbias.cpp +++ b/lib/colvars/colvarbias.cpp @@ -93,6 +93,8 @@ int colvarbias::init(std::string const &conf) cvm::log("Reinitializing bias \""+name+"\".\n"); } + feature_states[f_cvb_step_zero_data].available = true; + colvar_values.resize(num_variables()); for (i = 0; i < num_variables(); i++) { colvar_values[i].type(colvars[i]->value().type()); @@ -157,7 +159,7 @@ int colvarbias::init_dependencies() { init_feature(f_cvb_step_zero_data, "step_zero_data", f_type_user); init_feature(f_cvb_apply_force, "apply_force", f_type_user); - require_feature_children(f_cvb_apply_force, f_cv_gradient); + require_feature_children(f_cvb_apply_force, f_cv_apply_force); init_feature(f_cvb_bypass_ext_lagrangian, "bypass_extended_Lagrangian_coordinates", f_type_user); @@ -199,6 +201,8 @@ int colvarbias::init_dependencies() { init_feature(f_cvb_extended, "Bias on extended-Lagrangian variables", f_type_static); + init_feature(f_cvb_smp, "smp_computation", f_type_user); + // check that everything is initialized for (i = 0; i < colvardeps::f_cvb_ntot; i++) { if (is_not_set(i)) { @@ -221,8 +225,9 @@ int colvarbias::init_dependencies() { // The feature f_cvb_bypass_ext_lagrangian is only implemented by some derived classes // (initially, harmonicWalls) feature_states[f_cvb_bypass_ext_lagrangian].available = false; - // disabled by default; can be changed by derived classes that implement it - feature_states[f_cvb_bypass_ext_lagrangian].enabled = false; + + // Most biases cannot currently be processed in parallel over threads + feature_states[f_cvb_smp].available = false; return COLVARS_OK; } @@ -704,7 +709,7 @@ int colvarbias::read_state_string(char const *buffer) std::ostream &colvarbias::write_state_data_key(std::ostream &os, std::string const &key, - bool header) + bool header) const { os << (header ? "\n" : "") << key << (header ? "\n" : " "); return os; @@ -712,7 +717,7 @@ std::ostream &colvarbias::write_state_data_key(std::ostream &os, std::string con cvm::memory_stream &colvarbias::write_state_data_key(cvm::memory_stream &os, std::string const &key, - bool /* header */) + bool /* header */) const { os << std::string(key); return os; @@ -792,6 +797,8 @@ int colvarbias_ti::init(std::string const &conf) { int error_code = COLVARS_OK; + key_lookup(conf, "grid", &grid_conf); + get_keyval_feature(this, conf, "writeTISamples", f_cvb_write_ti_samples, is_enabled(f_cvb_write_ti_samples)); @@ -800,18 +807,16 @@ int colvarbias_ti::init(std::string const &conf) f_cvb_write_ti_pmf, is_enabled(f_cvb_write_ti_pmf)); + if (is_enabled(f_cvb_write_ti_pmf)) { + enable(f_cvb_write_ti_samples); + } + if ((num_variables() > 1) && is_enabled(f_cvb_write_ti_pmf)) { return cvm::error("Error: only 1-dimensional PMFs can be written " "on the fly.\n" "Consider using writeTISamples instead and " "post-processing the sampled free-energy gradients.\n", COLVARS_NOT_IMPLEMENTED); - } else { - error_code |= init_grids(); - } - - if (is_enabled(f_cvb_write_ti_pmf)) { - enable(f_cvb_write_ti_samples); } if (is_enabled(f_cvb_calc_ti_samples)) { @@ -831,6 +836,8 @@ int colvarbias_ti::init(std::string const &conf) } } + error_code |= colvarbias_ti::init_grids(); + if (is_enabled(f_cvb_write_ti_pmf) || is_enabled(f_cvb_write_ti_samples)) { cvm::main()->cite_feature("Internal-forces free energy estimator"); } @@ -844,16 +851,15 @@ int colvarbias_ti::init_grids() if (is_enabled(f_cvb_calc_ti_samples)) { if (!ti_avg_forces) { ti_bin.resize(num_variables()); + ti_bin.assign(ti_bin.size(), -1); ti_system_forces.resize(num_variables()); for (size_t icv = 0; icv < num_variables(); icv++) { ti_system_forces[icv].type(variables(icv)->value()); ti_system_forces[icv].is_derivative(); ti_system_forces[icv].reset(); } - ti_avg_forces.reset(new colvar_grid_gradient(colvars)); - ti_count.reset(new colvar_grid_count(colvars)); - ti_avg_forces->samples = ti_count; - ti_count->has_parent_data = true; + ti_count.reset(new colvar_grid_count(colvars, grid_conf)); + ti_avg_forces.reset(new colvar_grid_gradient(colvars, ti_count)); } } @@ -884,8 +890,12 @@ int colvarbias_ti::update_system_forces(std::vector const size_t i; - if (proxy->total_forces_same_step()) { - for (i = 0; i < num_variables(); i++) { + if (cvm::debug()) { + cvm::log("TI bin for bias \"" + name + "\" = " + cvm::to_str(ti_bin) + ".\n"); + } + + for (i = 0; i < num_variables(); i++) { + if (variables(i)->is_enabled(f_cv_total_force_current_step)) { ti_bin[i] = ti_avg_forces->current_bin_scalar(i); } } @@ -894,8 +904,10 @@ int colvarbias_ti::update_system_forces(std::vector const if ((cvm::step_relative() > 0) || proxy->total_forces_same_step()) { if (ti_avg_forces->index_ok(ti_bin)) { for (i = 0; i < num_variables(); i++) { - if (variables(i)->is_enabled(f_cv_subtract_applied_force)) { + if (variables(i)->is_enabled(f_cv_subtract_applied_force) || + (cvm::proxy->total_forces_same_step() && !variables(i)->is_enabled(f_cv_external))) { // this colvar is already subtracting all applied forces + // or the "total force" is really a system force at current step ti_system_forces[i] = variables(i)->total_force(); } else { ti_system_forces[i] = variables(i)->total_force() - @@ -904,14 +916,17 @@ int colvarbias_ti::update_system_forces(std::vector const } } if (cvm::step_relative() > 0 || is_enabled(f_cvb_step_zero_data)) { + if (cvm::debug()) { + cvm::log("Accumulating TI forces for bias \"" + name + "\".\n"); + } ti_avg_forces->acc_value(ti_bin, ti_system_forces); } } } - if (!proxy->total_forces_same_step()) { - // Set the index for use in the next iteration, when total forces come in - for (i = 0; i < num_variables(); i++) { + for (i = 0; i < num_variables(); i++) { + if (!variables(i)->is_enabled(f_cv_total_force_current_step)) { + // Set the index for use in the next iteration, when total forces come in ti_bin[i] = ti_avg_forces->current_bin_scalar(i); } } diff --git a/lib/colvars/colvarbias.h b/lib/colvars/colvarbias.h index 03f93f4315..35438752a1 100644 --- a/lib/colvars/colvarbias.h +++ b/lib/colvars/colvarbias.h @@ -174,14 +174,14 @@ public: /// \param[in,out] os Output stream /// \param[in] key Keyword labeling the header block /// \param[in] header Whether this is the header of a multi-line segment vs a single line - std::ostream &write_state_data_key(std::ostream &os, std::string const &key, bool header = true); + std::ostream &write_state_data_key(std::ostream &os, std::string const &key, bool header = true) const; /// Write a keyword header for a data sequence to an unformatted stream /// \param[in,out] os Output stream /// \param[in] key Keyword labeling the header block /// \param[in] header Ignored cvm::memory_stream &write_state_data_key(cvm::memory_stream &os, std::string const &key, - bool header = true); + bool header = true) const; private: @@ -358,6 +358,9 @@ protected: /// \brief Forces exerted from the system to the associated variables std::vector ti_system_forces; + /// Grid configuration parameters (also used by grids in derived classes) + std::string grid_conf; + /// Averaged system forces std::shared_ptr ti_avg_forces; diff --git a/lib/colvars/colvarbias_abf.cpp b/lib/colvars/colvarbias_abf.cpp index 6327650863..b01e9de853 100644 --- a/lib/colvars/colvarbias_abf.cpp +++ b/lib/colvars/colvarbias_abf.cpp @@ -87,24 +87,25 @@ int colvarbias_abf::init(std::string const &conf) get_keyval(conf, "shared", shared_on, false); if (shared_on) { cvm::main()->cite_feature("Multiple-walker ABF implementation"); - if ((proxy->replica_enabled() != COLVARS_OK) || - (proxy->num_replicas() <= 1)) { - return cvm::error("Error: shared ABF requires more than one replica.", - COLVARS_INPUT_ERROR); - } - cvm::log("shared ABF will be applied among "+ - cvm::to_str(proxy->num_replicas()) + " replicas.\n"); + cvm::main()->cite_feature("Updated multiple-walker ABF implementation"); + + + // Cannot check this here because the replica communicator is obtained later + // in Gromacs + + // if ((proxy->check_replicas_enabled() != COLVARS_OK) || + // (proxy->num_replicas() <= 1)) { + // return cvm::error("Error: shared ABF requires more than one replica.", + // COLVARS_INPUT_ERROR); + // } + // cvm::log("shared ABF will be applied among "+ + // cvm::to_str(proxy->num_replicas()) + " replicas.\n"); // If shared_freq is not set, we default to output_freq get_keyval(conf, "sharedFreq", shared_freq, output_freq); if ( shared_freq && output_freq % shared_freq ) { return cvm::error("Error: outputFreq must be a multiple of sharedFreq.\n"); } - - // Allocate these at init time if possible - local_samples.reset(new colvar_grid_count(colvars)); - local_gradients.reset(new colvar_grid_gradient(colvars, local_samples)); - local_pmf.reset(new integrate_potential(colvars, local_gradients)); } // ************* checking the associated colvars ******************* @@ -124,10 +125,17 @@ int colvarbias_abf::init(std::string const &conf) colvars[i]->enable(f_cv_hide_Jacobian); } - // If any colvar is extended-system, we need to collect the extended - // system gradient - if (colvars[i]->is_enabled(f_cv_extended_Lagrangian)) + // If any colvar is extended-system (restrained, not driven external param), we are running eABF + if (colvars[i]->is_enabled(f_cv_extended_Lagrangian) + && !colvars[i]->is_enabled(f_cv_external)) { enable(f_cvb_extended); + } + + if (!colvars[i]->is_enabled(f_cv_total_force_current_step)) { + // If any colvar does not have current-step total force, then + // we can't do step 0 data + provide(f_cvb_step_zero_data, false); + } // Cannot mix and match coarse time steps with ABF because it gives // wrong total force averages - total force needs to be averaged over @@ -181,12 +189,23 @@ int colvarbias_abf::init(std::string const &conf) cvm::log("Allocating count and free energy gradient grids.\n"); } - samples.reset(new colvar_grid_count(colvars)); - gradients.reset(new colvar_grid_gradient(colvars, samples)); + { + /// Optional custom configuration string for grid parameters + std::string grid_conf; + key_lookup(conf, "grid", &grid_conf); + + samples.reset(new colvar_grid_count(colvars, grid_conf)); + } + gradients.reset(new colvar_grid_gradient(colvars, samples)); // Also use samples as template for sizes gradients->full_samples = full_samples; gradients->min_samples = min_samples; + if (shared_on) { + local_samples.reset(new colvar_grid_count(colvars, samples)); + local_gradients.reset(new colvar_grid_gradient(colvars, local_samples)); + } + // Data for eABF z-based estimator if (is_enabled(f_cvb_extended)) { get_keyval(conf, "CZARestimator", b_CZAR_estimator, true); @@ -198,11 +217,11 @@ int colvarbias_abf::init(std::string const &conf) colvarparse::parse_silent); z_bin.assign(num_variables(), 0); - z_samples.reset(new colvar_grid_count(colvars)); + z_samples.reset(new colvar_grid_count(colvars, samples)); z_samples->request_actual_value(); z_gradients.reset(new colvar_grid_gradient(colvars, z_samples)); z_gradients->request_actual_value(); - czar_gradients.reset(new colvar_grid_gradient(colvars)); + czar_gradients.reset(new colvar_grid_gradient(colvars, nullptr, samples)); } get_keyval(conf, "integrate", b_integrate, num_variables() <= 3); // Integrate for output if d<=3 @@ -216,6 +235,9 @@ int colvarbias_abf::init(std::string const &conf) if (b_CZAR_estimator) { czar_pmf.reset(new integrate_potential(colvars, czar_gradients)); } + if (shared_on) { + local_pmf.reset(new integrate_potential(colvars, local_gradients)); + } // Parameters for integrating initial (and final) gradient data get_keyval(conf, "integrateMaxIterations", integrate_iterations, 10000, colvarparse::parse_silent); get_keyval(conf, "integrateTol", integrate_tol, 1e-6, colvarparse::parse_silent); @@ -228,9 +250,9 @@ int colvarbias_abf::init(std::string const &conf) if (b_CZAR_estimator && shared_on && cvm::main()->proxy->replica_index() == 0) { // The pointers below are used for outputting CZAR data // Allocate grids for collected global data, on replica 0 only - global_z_samples.reset(new colvar_grid_count(colvars)); + global_z_samples.reset(new colvar_grid_count(colvars, samples)); global_z_gradients.reset(new colvar_grid_gradient(colvars, global_z_samples)); - global_czar_gradients.reset(new colvar_grid_gradient(colvars)); + global_czar_gradients.reset(new colvar_grid_gradient(colvars, nullptr, samples)); global_czar_pmf.reset(new integrate_potential(colvars, global_czar_gradients)); } else { // otherwise they are just aliases for the local CZAR grids @@ -244,10 +266,10 @@ int colvarbias_abf::init(std::string const &conf) // This used to be only if "shared" was defined, // but now we allow calling share externally (e.g. from Tcl). if (b_CZAR_estimator) { - z_samples_in.reset(new colvar_grid_count(colvars)); + z_samples_in.reset(new colvar_grid_count(colvars, samples)); z_gradients_in.reset(new colvar_grid_gradient(colvars, z_samples_in)); } - last_samples.reset(new colvar_grid_count(colvars)); + last_samples.reset(new colvar_grid_count(colvars, samples)); last_gradients.reset(new colvar_grid_gradient(colvars, last_samples)); // Any data collected after now is new for shared ABF purposes shared_last_step = cvm::step_absolute(); @@ -315,27 +337,36 @@ int colvarbias_abf::update() size_t i; for (i = 0; i < num_variables(); i++) { bin[i] = samples->current_bin_scalar(i); + if (colvars[i]->is_enabled(f_cv_total_force_current_step)) { + force_bin[i] = bin[i]; + } } - // *********************************************************** // ****** ABF Part I: update the FE gradient estimate ****** // *********************************************************** - if (cvm::proxy->total_forces_same_step()) { - // e.g. in LAMMPS, total forces are current - force_bin = bin; + // Share data first, so that 2d/3d PMF is refreshed using new data for mw-pABF. + // shared_on can be true with shared_freq 0 if we are sharing via script + if (shared_on && shared_freq && + shared_last_step >= 0 && // we have already collected some data + cvm::step_absolute() > shared_last_step && // time has passed since the last sharing timestep + // (avoid re-sharing at last and first ts of successive run statements) + cvm::step_absolute() % shared_freq == 0) { + // Share gradients and samples for shared ABF. + replica_share(); } if (can_accumulate_data() && is_enabled(f_cvb_history_dependent)) { if (cvm::step_relative() > 0 || cvm::proxy->total_forces_same_step()) { + // Note: this will skip step 0 data when available in some cases (extended system), + // but not doing so would make the code more complex if (samples->index_ok(force_bin)) { // Only if requested and within bounds of the grid... - // get total forces (lagging by 1 timestep) from colvars - // and subtract previous ABF force if necessary + // get total force and subtract previous ABF force if necessary update_system_force(); gradients->acc_force(force_bin, system_force); @@ -368,21 +399,11 @@ int colvarbias_abf::update() } } - if (!(cvm::proxy->total_forces_same_step())) { - // e.g. in NAMD, total forces will be available for next timestep - // hence we store the current colvar bin - force_bin = bin; - } + // In some cases, total forces are stored for next timestep + // hence we store the current colvar bin - this is overwritten on a per-colvar basis + // at the top of update() + force_bin = bin; - // Share data after force sample is collected for this time step - // shared_on can be true with shared_freq 0 if we are sharing via script - if (shared_on && shared_freq && - cvm::step_absolute() > shared_last_step && // time has passed since the last sharing timestep - // (avoid re-sharing at last and first ts of successive run statements) - cvm::step_absolute() % shared_freq == 0) { - // Share gradients and samples for shared ABF. - replica_share(); - } // ****************************************************************** // ****** ABF Part II: calculate and apply the biasing force ****** @@ -452,10 +473,13 @@ int colvarbias_abf::update_system_force() // System force from atomic forces (or extended Lagrangian if applicable) for (i = 0; i < num_variables(); i++) { - if (colvars[i]->is_enabled(f_cv_subtract_applied_force)) { + if (colvars[i]->is_enabled(f_cv_subtract_applied_force) + || colvars[i]->is_enabled(f_cv_total_force_current_step)) { // this colvar is already subtracting the ABF force + // or the "total force" is from current step and cannot possibly contain Colvars biases system_force[i] = colvars[i]->total_force().real_value; } else { + // Subtract previous step's bias force from previous step's total force system_force[i] = colvars[i]->total_force().real_value - colvar_forces[i].real_value; } @@ -525,7 +549,7 @@ int colvarbias_abf::replica_share() { colvarproxy *proxy = cvm::main()->proxy; - if (proxy->replica_enabled() != COLVARS_OK) { + if (proxy->check_replicas_enabled() != COLVARS_OK) { cvm::error("Error: shared ABF: No replicas.\n"); return COLVARS_ERROR; } @@ -542,7 +566,7 @@ int colvarbias_abf::replica_share() { if (!local_samples) { // We arrive here if sharing has just been enabled by a script // in which case local arrays have not been initialized yet - local_samples.reset(new colvar_grid_count(colvars)); + local_samples.reset(new colvar_grid_count(colvars, samples)); local_gradients.reset(new colvar_grid_gradient(colvars, local_samples)); local_pmf.reset(new integrate_potential(colvars, local_gradients)); } @@ -662,9 +686,9 @@ int colvarbias_abf::replica_share_CZAR() { // We arrive here if sharing has just been enabled by a script // Allocate grids for collective data, on replica 0 only // overriding CZAR grids that are equal to local ones by default - global_z_samples.reset(new colvar_grid_count(colvars)); + global_z_samples.reset(new colvar_grid_count(colvars, samples)); global_z_gradients.reset(new colvar_grid_gradient(colvars, global_z_samples)); - global_czar_gradients.reset(new colvar_grid_gradient(colvars)); + global_czar_gradients.reset(new colvar_grid_gradient(colvars, nullptr, samples)); global_czar_pmf.reset(new integrate_potential(colvars, global_czar_gradients)); } diff --git a/lib/colvars/colvarbias_histogram.cpp b/lib/colvars/colvarbias_histogram.cpp index 98de275304..aab2c8f593 100644 --- a/lib/colvars/colvarbias_histogram.cpp +++ b/lib/colvars/colvarbias_histogram.cpp @@ -98,10 +98,10 @@ int colvarbias_histogram::init(std::string const &conf) } { - std::string grid_conf; - if (key_lookup(conf, "histogramGrid", &grid_conf)) { + if (key_lookup(conf, "histogramGrid", &grid_conf) || + key_lookup(conf, "grid", &grid_conf)) { grid->parse_params(grid_conf); - grid->check_keywords(grid_conf, "histogramGrid"); + grid->check_keywords(grid_conf, "grid"); } } diff --git a/lib/colvars/colvarbias_histogram.h b/lib/colvars/colvarbias_histogram.h index 2c6ee84d1f..ed3ee346a6 100644 --- a/lib/colvars/colvarbias_histogram.h +++ b/lib/colvars/colvarbias_histogram.h @@ -38,6 +38,7 @@ protected: /// n-dim histogram colvar_grid_scalar *grid; + std::string grid_conf; std::vector bin; std::string out_name, out_name_dx; diff --git a/lib/colvars/colvarbias_histogram_reweight_amd.cpp b/lib/colvars/colvarbias_histogram_reweight_amd.cpp index de2f6d9b8a..3c31e175f2 100644 --- a/lib/colvars/colvarbias_histogram_reweight_amd.cpp +++ b/lib/colvars/colvarbias_histogram_reweight_amd.cpp @@ -11,43 +11,9 @@ #include "colvarproxy.h" #include "colvars_memstream.h" -colvarbias_reweightaMD::colvarbias_reweightaMD(char const *key) - : colvarbias_histogram(key), grid_count(NULL), grid_dV(NULL), - grid_dV_square(NULL), pmf_grid_exp_avg(NULL), pmf_grid_cumulant(NULL), - grad_grid_exp_avg(NULL), grad_grid_cumulant(NULL) -{ -} +colvarbias_reweightaMD::colvarbias_reweightaMD(char const *key) : colvarbias_histogram(key) {} -colvarbias_reweightaMD::~colvarbias_reweightaMD() { - if (grid_dV) { - delete grid_dV; - grid_dV = NULL; - } - if (grid_dV_square) { - delete grid_dV_square; - grid_dV_square = NULL; - } - if (grid_count) { - delete grid_count; - grid_count = NULL; - } - if (pmf_grid_exp_avg) { - delete pmf_grid_exp_avg; - pmf_grid_exp_avg = NULL; - } - if (pmf_grid_cumulant) { - delete pmf_grid_cumulant; - pmf_grid_cumulant = NULL; - } - if (grad_grid_exp_avg) { - delete grad_grid_exp_avg; - grad_grid_exp_avg = NULL; - } - if (grad_grid_cumulant) { - delete grad_grid_cumulant; - grad_grid_cumulant = NULL; - } -} +colvarbias_reweightaMD::~colvarbias_reweightaMD() {} int colvarbias_reweightaMD::init(std::string const &conf) { if (cvm::proxy->accelMD_enabled() == false) { @@ -60,21 +26,21 @@ int colvarbias_reweightaMD::init(std::string const &conf) { get_keyval(conf, "WritePMFGradients", b_write_gradients, true); get_keyval(conf, "historyFreq", history_freq, 0); b_history_files = (history_freq > 0); - grid_count = new colvar_grid_scalar(colvars); + grid_count.reset(new colvar_grid_scalar(colvars, nullptr, false, grid_conf)); grid_count->request_actual_value(); grid->request_actual_value(); - pmf_grid_exp_avg = new colvar_grid_scalar(colvars); + pmf_grid_exp_avg.reset(new colvar_grid_scalar(colvars, grid_count)); if (b_write_gradients) { - grad_grid_exp_avg = new colvar_grid_gradient(colvars); + grad_grid_exp_avg.reset(new colvar_grid_gradient(colvars, nullptr, grid_count)); } if (b_use_cumulant_expansion) { - grid_dV = new colvar_grid_scalar(colvars); - grid_dV_square = new colvar_grid_scalar(colvars); - pmf_grid_cumulant = new colvar_grid_scalar(colvars); + grid_dV.reset(new colvar_grid_scalar(colvars, grid_count)); + grid_dV_square.reset(new colvar_grid_scalar(colvars, grid_count)); + pmf_grid_cumulant.reset(new colvar_grid_scalar(colvars, grid_count)); grid_dV->request_actual_value(); grid_dV_square->request_actual_value(); if (b_write_gradients) { - grad_grid_cumulant = new colvar_grid_gradient(colvars); + grad_grid_cumulant.reset(new colvar_grid_gradient(colvars, nullptr, grid_count)); } } previous_bin.assign(num_variables(), -1); @@ -193,7 +159,7 @@ int colvarbias_reweightaMD::write_exponential_reweighted_pmf( pmf_grid_exp_avg->set_value(i, tmp / count); } } - hist_to_pmf(pmf_grid_exp_avg, grid_count); + hist_to_pmf(pmf_grid_exp_avg.get(), grid_count.get()); pmf_grid_exp_avg->write_multicol(pmf_grid_os); if (!keep_open) { cvm::proxy->close_output_stream(output_pmf); @@ -231,9 +197,9 @@ int colvarbias_reweightaMD::write_cumulant_expansion_pmf( if (!pmf_grid_cumulant_os) { return COLVARS_FILE_ERROR; } - compute_cumulant_expansion_factor(grid_dV, grid_dV_square, - grid_count, pmf_grid_cumulant); - hist_to_pmf(pmf_grid_cumulant, grid_count); + compute_cumulant_expansion_factor(grid_dV.get(), grid_dV_square.get(), + grid_count.get(), pmf_grid_cumulant.get()); + hist_to_pmf(pmf_grid_cumulant.get(), grid_count.get()); pmf_grid_cumulant->write_multicol(pmf_grid_cumulant_os); if (!keep_open) { cvm::proxy->close_output_stream(output_pmf); diff --git a/lib/colvars/colvarbias_histogram_reweight_amd.h b/lib/colvars/colvarbias_histogram_reweight_amd.h index 43759b3bde..3e3bdede26 100644 --- a/lib/colvars/colvarbias_histogram_reweight_amd.h +++ b/lib/colvars/colvarbias_histogram_reweight_amd.h @@ -68,9 +68,9 @@ protected: /// Use cumulant expansion to second order? bool b_use_cumulant_expansion; - colvar_grid_scalar* grid_count; - colvar_grid_scalar* grid_dV; - colvar_grid_scalar* grid_dV_square; + std::shared_ptr grid_count; + std::unique_ptr grid_dV; + std::unique_ptr grid_dV_square; /// Number of timesteps between recording data in history files (if non-zero) size_t history_freq; @@ -90,10 +90,10 @@ protected: private: /// temporary grids for evaluating PMFs - colvar_grid_scalar *pmf_grid_exp_avg; - colvar_grid_scalar *pmf_grid_cumulant; - colvar_grid_gradient *grad_grid_exp_avg; - colvar_grid_gradient *grad_grid_cumulant; + std::unique_ptr pmf_grid_exp_avg; + std::unique_ptr pmf_grid_cumulant; + std::unique_ptr grad_grid_exp_avg; + std::unique_ptr grad_grid_cumulant; }; #endif // COLVARBIAS_HISTOGRAM_REWEIGHT_AMD diff --git a/lib/colvars/colvarbias_meta.cpp b/lib/colvars/colvarbias_meta.cpp index 905cd17883..1131c88ec5 100644 --- a/lib/colvars/colvarbias_meta.cpp +++ b/lib/colvars/colvarbias_meta.cpp @@ -11,27 +11,10 @@ #include #include -// Define function to get the absolute path of a replica file -#if defined(_WIN32) && !defined(__CYGWIN__) -#include -#define GETCWD(BUF, SIZE) ::_getcwd(BUF, SIZE) -#define PATHSEP "\\" -#else -#include -#define GETCWD(BUF, SIZE) ::getcwd(BUF, SIZE) -#define PATHSEP "/" -#endif - -#ifdef __cpp_lib_filesystem -// When std::filesystem is available, use it -#include -#undef GETCWD -#define GETCWD(BUF, SIZE) (std::filesystem::current_path().string().c_str()) -#endif - #include "colvarmodule.h" #include "colvarproxy.h" #include "colvar.h" +#include "colvargrid.h" #include "colvarbias_meta.h" #include "colvars_memstream.h" @@ -49,8 +32,6 @@ colvarbias_meta::colvarbias_meta(char const *key) use_grids = true; grids_freq = 0; rebin_grids = false; - hills_energy = NULL; - hills_energy_gradients = NULL; dump_fes = true; keep_hills = false; @@ -161,9 +142,9 @@ int colvarbias_meta::init(std::string const &conf) get_keyval(conf, "keepHills", keep_hills, keep_hills); get_keyval(conf, "keepFreeEnergyFiles", dump_fes_save, dump_fes_save); - if (hills_energy == NULL) { - hills_energy = new colvar_grid_scalar(colvars); - hills_energy_gradients = new colvar_grid_gradient(colvars); + if (!hills_energy) { + hills_energy.reset(new colvar_grid_scalar(colvars, nullptr, false, grid_conf)); + hills_energy_gradients.reset(new colvar_grid_gradient(colvars, nullptr, hills_energy)); } } else { @@ -209,7 +190,7 @@ int colvarbias_meta::init_replicas_params(std::string const &conf) get_keyval(conf, "replicaID", replica_id, replica_id); if (!replica_id.size()) { - if (proxy->replica_enabled() == COLVARS_OK) { + if (proxy->check_replicas_enabled() == COLVARS_OK) { // Obtain replicaID from the communicator replica_id = cvm::to_str(proxy->replica_index()); cvm::log("Setting replicaID from communication layer: replicaID = "+ @@ -272,7 +253,6 @@ int colvarbias_meta::init_ebmeta_params(std::string const &conf) { int error_code = COLVARS_OK; // for ebmeta - target_dist = NULL; get_keyval(conf, "ebMeta", ebmeta, false); if(ebmeta){ cvm::main()->cite_feature("Ensemble-biased metadynamics (ebMetaD)"); @@ -283,7 +263,7 @@ int colvarbias_meta::init_ebmeta_params(std::string const &conf) "targetDistFile accordingly.\n", COLVARS_INPUT_ERROR); } - target_dist = new colvar_grid_scalar(); + target_dist.reset(new colvar_grid_scalar()); error_code |= target_dist->init_from_colvars(colvars); std::string target_dist_file; get_keyval(conf, "targetDistFile", target_dist_file); @@ -336,33 +316,15 @@ colvarbias_meta::~colvarbias_meta() { colvarbias_meta::clear_state_data(); colvarproxy *proxy = cvm::main()->proxy; - proxy->close_output_stream(replica_hills_file); - proxy->close_output_stream(hills_traj_file_name()); - - if (target_dist) { - delete target_dist; - target_dist = NULL; - } } int colvarbias_meta::clear_state_data() { - if (hills_energy) { - delete hills_energy; - hills_energy = NULL; - } - - if (hills_energy_gradients) { - delete hills_energy_gradients; - hills_energy_gradients = NULL; - } - hills.clear(); hills_off_grid.clear(); - return COLVARS_OK; } @@ -451,8 +413,11 @@ int colvarbias_meta::update() error_code |= update_grid_params(); // add new biasing energy/forces error_code |= update_bias(); - // update grid content to reflect new bias - error_code |= update_grid_data(); + + if (use_grids) { + // update grid content to reflect new bias + error_code |= update_grid_data(); + } if (comm != single_replica && (cvm::step_absolute() % replica_update_freq) == 0) { @@ -539,9 +504,9 @@ int colvarbias_meta::update_grid_params() // map everything into new grids colvar_grid_scalar *new_hills_energy = - new colvar_grid_scalar(*hills_energy); + new colvar_grid_scalar(*hills_energy); colvar_grid_gradient *new_hills_energy_gradients = - new colvar_grid_gradient(*hills_energy_gradients); + new colvar_grid_gradient(*hills_energy_gradients); // supply new boundaries to the new grids @@ -556,10 +521,8 @@ int colvarbias_meta::update_grid_params() new_hills_energy->map_grid(*hills_energy); new_hills_energy_gradients->map_grid(*hills_energy_gradients); - delete hills_energy; - delete hills_energy_gradients; - hills_energy = new_hills_energy; - hills_energy_gradients = new_hills_energy_gradients; + hills_energy.reset(new_hills_energy); + hills_energy_gradients.reset(new_hills_energy_gradients); curr_bin = hills_energy->get_colvars_index(); if (cvm::debug()) @@ -641,8 +604,7 @@ int colvarbias_meta::update_grid_data() { if ((cvm::step_absolute() % grids_freq) == 0) { // map the most recent gaussians to the grids - project_hills(new_hills_begin, hills.end(), - hills_energy, hills_energy_gradients); + project_hills(new_hills_begin, hills.end(), hills_energy.get(), hills_energy_gradients.get()); new_hills_begin = hills.end(); // TODO: we may want to condense all into one replicas array, @@ -651,8 +613,8 @@ int colvarbias_meta::update_grid_data() for (size_t ir = 0; ir < replicas.size(); ir++) { replicas[ir]->project_hills(replicas[ir]->new_hills_begin, replicas[ir]->hills.end(), - replicas[ir]->hills_energy, - replicas[ir]->hills_energy_gradients); + replicas[ir]->hills_energy.get(), + replicas[ir]->hills_energy_gradients.get()); replicas[ir]->new_hills_begin = replicas[ir]->hills.end(); } } @@ -670,11 +632,20 @@ int colvarbias_meta::calc_energy(std::vector const *values) replicas[ir]->bias_energy = 0.0; } - std::vector const curr_bin = values ? - hills_energy->get_colvars_index(*values) : - hills_energy->get_colvars_index(); + bool index_ok = false; + std::vector curr_bin; - if (hills_energy->index_ok(curr_bin)) { + if (use_grids) { + + curr_bin = values ? + hills_energy->get_colvars_index(*values) : + hills_energy->get_colvars_index(); + + index_ok = hills_energy->index_ok(curr_bin); + + } + + if ( index_ok ) { // index is within the grid: get the energy from there for (ir = 0; ir < replicas.size(); ir++) { @@ -723,11 +694,20 @@ int colvarbias_meta::calc_forces(std::vector const *values) } } - std::vector const curr_bin = values ? - hills_energy->get_colvars_index(*values) : - hills_energy->get_colvars_index(); + bool index_ok = false; + std::vector curr_bin; - if (hills_energy->index_ok(curr_bin)) { + if (use_grids) { + + curr_bin = values ? + hills_energy->get_colvars_index(*values) : + hills_energy->get_colvars_index(); + + index_ok = hills_energy->index_ok(curr_bin); + + } + + if ( index_ok ) { for (ir = 0; ir < replicas.size(); ir++) { cvm::real const *f = &(replicas[ir]->hills_energy_gradients->value(curr_bin)); for (ic = 0; ic < num_variables(); ic++) { @@ -959,8 +939,7 @@ void colvarbias_meta::project_hills(colvarbias_meta::hill_iter h_first, void colvarbias_meta::recount_hills_off_grid(colvarbias_meta::hill_iter h_first, - colvarbias_meta::hill_iter h_last, - colvar_grid_scalar * /* he */) + colvarbias_meta::hill_iter h_last) { hills_off_grid.clear(); @@ -1078,9 +1057,13 @@ int colvarbias_meta::update_replicas_registry() (replicas.back())->comm = multiple_replicas; if (use_grids) { - (replicas.back())->hills_energy = new colvar_grid_scalar(colvars); - (replicas.back())->hills_energy_gradients = new colvar_grid_gradient(colvars); + (replicas.back()) + ->hills_energy.reset(new colvar_grid_scalar(colvars, hills_energy)); + (replicas.back()) + ->hills_energy_gradients.reset( + new colvar_grid_gradient(colvars, nullptr, hills_energy)); } + if (is_enabled(f_cvb_calc_ti_samples)) { (replicas.back())->enable(f_cvb_calc_ti_samples); (replicas.back())->colvarbias_ti::init_grids(); @@ -1336,34 +1319,40 @@ template IST &colvarbias_meta::read_state_data_template_(IST &is) { if (use_grids) { - colvar_grid_scalar *hills_energy_backup = NULL; - colvar_grid_gradient *hills_energy_gradients_backup = NULL; + std::shared_ptr hills_energy_backup; + std::shared_ptr hills_energy_gradients_backup; - if (has_data) { + bool const need_backup = has_data; + + if (need_backup) { if (cvm::debug()) - cvm::log("Backupping grids for metadynamics bias \""+ - this->name+"\""+ - ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n"); - hills_energy_backup = hills_energy; - hills_energy_gradients_backup = hills_energy_gradients; - hills_energy = new colvar_grid_scalar(colvars); - hills_energy_gradients = new colvar_grid_gradient(colvars); + cvm::log("Backing up grids for metadynamics bias \"" + this->name + "\"" + + ((comm != single_replica) ? ", replica \"" + replica_id + "\"" : "") + ".\n"); + + hills_energy_backup = std::move(hills_energy); + hills_energy_gradients_backup = std::move(hills_energy_gradients); + hills_energy.reset(new colvar_grid_scalar(colvars, hills_energy)); + hills_energy_gradients.reset(new colvar_grid_gradient(colvars, nullptr, hills_energy)); } - read_grid_data_template_(is, "hills_energy", hills_energy, - hills_energy_backup); + read_grid_data_template_(is, "hills_energy", hills_energy.get(), + hills_energy_backup.get()); - read_grid_data_template_( - is, "hills_energy_gradients", hills_energy_gradients, hills_energy_gradients_backup); + read_grid_data_template_(is, "hills_energy_gradients", + hills_energy_gradients.get(), + hills_energy_gradients_backup.get()); if (is) { cvm::log(" successfully read the biasing potential and its gradients from grids.\n"); - if (hills_energy_backup != nullptr) { - // Now that we have successfully updated the grids, delete the backup copies - delete hills_energy_backup; - delete hills_energy_gradients_backup; - } } else { + if (need_backup) { + if (cvm::debug()) + cvm::log("Restoring grids from backup for metadynamics bias \"" + this->name + "\"" + + ((comm != single_replica) ? ", replica \"" + replica_id + "\"" : "") + ".\n"); + // Restoring content from original grid + hills_energy->copy_grid(*hills_energy_backup); + hills_energy_gradients->copy_grid(*hills_energy_gradients_backup); + } return is; } } @@ -1451,10 +1440,12 @@ void colvarbias_meta::rebin_grids_after_restart() // read from the configuration file), and project onto them the // grids just read from the restart file - colvar_grid_scalar *new_hills_energy = - new colvar_grid_scalar(colvars); - colvar_grid_gradient *new_hills_energy_gradients = - new colvar_grid_gradient(colvars); + // Create new grids based on the configuration parameters, because reading from the state + // file automatically sets the old parameters + std::shared_ptr new_hills_energy( + new colvar_grid_scalar(colvars, nullptr, false, grid_conf)); + std::shared_ptr new_hills_energy_gradients( + new colvar_grid_gradient(colvars, nullptr, new_hills_energy)); if (cvm::debug()) { std::ostringstream tmp_os; @@ -1468,9 +1459,9 @@ void colvarbias_meta::rebin_grids_after_restart() if (restart_keep_hills && !hills.empty()) { // if there are hills, recompute the new grids from them cvm::log("Rebinning the energy and forces grids from "+ - cvm::to_str(hills.size())+" hills (this may take a while)...\n"); - project_hills(hills.begin(), hills.end(), - new_hills_energy, new_hills_energy_gradients, true); + cvm::to_str(hills.size())+" hills (this may take a bit)...\n"); + project_hills(hills.begin(), hills.end(), new_hills_energy.get(), + new_hills_energy_gradients.get(), true); cvm::log("rebinning done.\n"); } else { @@ -1481,15 +1472,13 @@ void colvarbias_meta::rebin_grids_after_restart() new_hills_energy_gradients->map_grid(*hills_energy_gradients); } - delete hills_energy; - delete hills_energy_gradients; - hills_energy = new_hills_energy; - hills_energy_gradients = new_hills_energy_gradients; + hills_energy = std::move(new_hills_energy); + hills_energy_gradients = std::move(new_hills_energy_gradients); // assuming that some boundaries have expanded, eliminate those // off-grid hills that aren't necessary any more if (!hills.empty()) - recount_hills_off_grid(hills.begin(), hills.end(), hills_energy); + recount_hills_off_grid(hills.begin(), hills.end()); } } @@ -1718,29 +1707,17 @@ int colvarbias_meta::setup_output() if (comm == multiple_replicas) { - // TODO: one may want to specify the path manually for intricated filesystems? - char *pwd = new char[3001]; - if (GETCWD(pwd, 3000) == nullptr) { - if (pwd != nullptr) { // - delete[] pwd; - } - return cvm::error("Error: cannot get the path of the current working directory.\n", - COLVARS_BUG_ERROR); - } - + auto const pwd = cvm::main()->proxy->get_current_work_dir(); replica_list_file = - (std::string(pwd)+std::string(PATHSEP)+ - this->name+"."+replica_id+".files.txt"); + cvm::main()->proxy->join_paths(pwd, this->name + "." + replica_id + ".files.txt"); // replica_hills_file and replica_state_file are those written // by the current replica; within the mirror biases, they are // those by another replica - replica_hills_file = - (std::string(pwd)+std::string(PATHSEP)+ - cvm::output_prefix()+".colvars."+this->name+"."+replica_id+".hills"); - replica_state_file = - (std::string(pwd)+std::string(PATHSEP)+ - cvm::output_prefix()+".colvars."+this->name+"."+replica_id+".state"); - delete[] pwd; + replica_hills_file = cvm::main()->proxy->join_paths( + pwd, cvm::output_prefix() + ".colvars." + this->name + "." + replica_id + ".hills"); + + replica_state_file = cvm::main()->proxy->join_paths( + pwd, cvm::output_prefix() + ".colvars." + this->name + "." + replica_id + ".state"); // now register this replica @@ -1842,7 +1819,7 @@ template OST &colvarbias_meta::write_state_data_template_(OST &os // this is a very good time to project hills, if you haven't done // it already! - project_hills(new_hills_begin, hills.end(), hills_energy, hills_energy_gradients); + project_hills(new_hills_begin, hills.end(), hills_energy.get(), hills_energy_gradients.get()); new_hills_begin = hills.end(); // write down the grids to the restart file diff --git a/lib/colvars/colvarbias_meta.h b/lib/colvars/colvarbias_meta.h index a765a60c71..57aa21ed6b 100644 --- a/lib/colvars/colvarbias_meta.h +++ b/lib/colvars/colvarbias_meta.h @@ -10,12 +10,16 @@ #ifndef COLVARBIAS_META_H #define COLVARBIAS_META_H -#include -#include #include +#include +#include +#include #include "colvarbias.h" -#include "colvargrid.h" + +class colvar_grid_scalar; +class colvar_grid_gradient; + /// Metadynamics bias (implementation of \link colvarbias \endlink) @@ -123,8 +127,7 @@ protected: hill_iter new_hills_off_grid_begin; /// Regenerate the hills_off_grid list - void recount_hills_off_grid(hill_iter h_first, hill_iter h_last, - colvar_grid_scalar *ge); + void recount_hills_off_grid(hill_iter h_first, hill_iter h_last); template OST &write_hill_template_(OST &os, colvarbias_meta::hill const &h); @@ -211,7 +214,7 @@ protected: bool ebmeta; /// Target distribution for EBmeta - colvar_grid_scalar* target_dist; + std::unique_ptr target_dist; /// Number of equilibration steps for EBmeta cvm::step_number ebmeta_equil_steps; @@ -223,15 +226,14 @@ protected: bool safely_read_restart; /// Hill energy, cached on a grid - colvar_grid_scalar *hills_energy; + std::shared_ptr hills_energy; /// Hill forces, cached on a grid - colvar_grid_gradient *hills_energy_gradients; + std::shared_ptr hills_energy_gradients; - /// \brief Project the selected hills onto grids - void project_hills(hill_iter h_first, hill_iter h_last, - colvar_grid_scalar *ge, colvar_grid_gradient *gf, - bool print_progress = false); + /// Project the selected hills onto grids + void project_hills(hill_iter h_first, hill_iter h_last, colvar_grid_scalar *ge, + colvar_grid_gradient *gf, bool print_progress = false); // Multiple Replicas variables and functions diff --git a/lib/colvars/colvarbias_opes.cpp b/lib/colvars/colvarbias_opes.cpp new file mode 100644 index 0000000000..9caeb967e0 --- /dev/null +++ b/lib/colvars/colvarbias_opes.cpp @@ -0,0 +1,1996 @@ +// This code is mainly adapted from the PLUMED opes module, which uses the +// LGPLv3 license as shown below: +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Copyright (c) 2020-2021 of Michele Invernizzi. + + This file is part of the OPES plumed module. + + The OPES plumed module is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + The OPES plumed module is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with plumed. If not, see . ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ + +#include "colvarbias_opes.h" +#include "colvarbias.h" +#include "colvardeps.h" +#include "colvarproxy.h" +#include "colvars_memstream.h" +#include "colvargrid.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +colvarbias_opes::colvarbias_opes(char const *key): + colvarbias(key), m_kbt(0), m_barrier(0), m_biasfactor(0), + m_bias_prefactor(0), m_temperature(0), + m_pace(0), m_adaptive_sigma_stride(0), + m_adaptive_counter(0), m_counter(1), + m_compression_threshold(0), m_compression_threshold2(0), + m_adaptive_sigma(false), m_fixed_sigma(false), + m_no_zed(false), m_nlist(false), m_recursive_merge(true), + m_nlist_param(2, 0), m_epsilon(0), m_sum_weights(0), + m_sum_weights2(0), m_cutoff(0), m_cutoff2(0), + m_zed(1), m_old_kdenorm(0), m_kdenorm(0), + m_val_at_cutoff(0), m_nlist_center(0), m_nlist_index(0), + m_nlist_steps(0), m_nlist_update(false), + m_nlist_pace_reset(false), m_nker(0), m_calc_work(false), + m_work(0), comm(single_replica), m_num_walkers(1), + m_num_threads(1), m_nlker(0), m_traj_output_frequency(0), + m_traj_line(traj_line{0}), m_is_first_step(true), + m_pmf_grid_on(false), m_reweight_grid(nullptr), + m_pmf_grid(nullptr), m_pmf_hist_freq(0), m_pmf_shared(true), + m_explore(false), m_inf_biasfactor(false) +{ +#ifdef OPES_THREADING + provide(f_cvb_smp, cvm::proxy->get_smp_mode() == colvarproxy_smp::smp_mode_t::inner_loop); + if (is_available(f_cv_smp)){ + enable(f_cvb_smp); // Enabled by default + } +#endif +} + +int colvarbias_opes::init(const std::string& conf) { + int error_code = colvarbias::init(conf); + enable(f_cvb_scalar_variables); + get_keyval_feature(this, conf, "applyBias", f_cvb_apply_force, true); + m_temperature = cvm::proxy->target_temperature(); + m_kbt = m_temperature * cvm::proxy->boltzmann(); + get_keyval(conf, "newHillFrequency", m_pace); + get_keyval(conf, "barrier", m_barrier); + get_keyval(conf, "explore", m_explore, false); + if (m_barrier < 0) { + return cvm::error("the barrier should be greater than zero", COLVARS_INPUT_ERROR); + } + std::string biasfactor_str; + get_keyval(conf, "biasfactor", biasfactor_str); + if ((cvm::proxy->target_temperature() == 0.0) && cvm::proxy->simulation_running()) { + cvm::log("WARNING: OPES should not be run without a thermostat or at 0 Kelvin!\n"); + } + m_biasfactor = m_barrier / m_kbt; + m_inf_biasfactor = biasfactor_str == "inf" || biasfactor_str == "INF"; + if (m_inf_biasfactor) { + m_biasfactor = std::numeric_limits::infinity(); + m_bias_prefactor = 1; + if (m_explore) { + return cvm::error("biasfactor cannot be infinity in the explore mode."); + } + } else { + if (biasfactor_str.size() > 0) { + try { + m_biasfactor = std::stod(biasfactor_str); + } catch (const std::exception& e) { + return cvm::error(e.what(), COLVARS_INPUT_ERROR); + } + } + if (m_biasfactor <= 1.0) { + return cvm::error("biasfactor must be greater than one (use \"inf\" for uniform target)"); + } + m_bias_prefactor = 1 - 1.0 / m_biasfactor; + } + if (m_explore) { + m_bias_prefactor = m_biasfactor - 1; + } + get_keyval(conf, "adaptiveSigma", m_adaptive_sigma, false); + m_sigma0.resize(num_variables()); + get_keyval(conf, "gaussianSigma", m_sigma0, std::vector(num_variables())); + m_av_cv.assign(num_variables(), 0); + m_av_M2.assign(num_variables(), 0); + if (m_adaptive_sigma) { + get_keyval(conf, "adaptiveSigmaStride", m_adaptive_sigma_stride, 0); + if (m_inf_biasfactor) { + return cvm::error("cannot use infinite biasfactor with adaptive sigma", + COLVARS_INPUT_ERROR); + } + if (m_adaptive_sigma_stride == 0) { + m_adaptive_sigma_stride = m_pace * 10; + } + if (m_adaptive_sigma_stride < m_pace) { + return cvm::error("It is better to choose an adaptiveSigmaStride >= newHillFrequency.\n", COLVARS_INPUT_ERROR); + } + } else { + if (m_sigma0.size() != num_variables()) { + return cvm::error("number of sigma parameters does not match the number of variables", + COLVARS_INPUT_ERROR); + } + if (m_explore) { + for (size_t i = 0; i < num_variables(); ++i) { + m_sigma0[i] *= std::sqrt(m_biasfactor); + } + } + } + get_keyval(conf, "gaussianSigmaMin", m_sigma_min); + if ((m_sigma_min.size() != 0) && (m_sigma_min.size() != num_variables())) { + return cvm::error("incorrect number of parameters of gaussianSigmaMin"); + } + if (m_sigma_min.size() > 0 && !m_adaptive_sigma) { + for (size_t i = 0; i < num_variables(); ++i) { + if (m_sigma_min[i] > m_sigma0[i]) { + return cvm::error("gaussianSigmaMin of variable " + cvm::to_str(i) + " should be smaller than sigma"); + } + } + } + get_keyval(conf, "epsilon", m_epsilon, std::exp(-m_barrier/m_bias_prefactor/m_kbt)); + if (m_epsilon <= 0) { + return cvm::error("you must choose a value of epsilon greater than zero"); + } + m_sum_weights = std::pow(m_epsilon, m_bias_prefactor); + m_sum_weights2 = m_sum_weights * m_sum_weights; + if (m_explore) { + get_keyval(conf, "kernelCutoff", m_cutoff, std::sqrt(2.0*m_barrier/m_kbt)); + } else { + get_keyval(conf, "kernelCutoff", m_cutoff, std::sqrt(2.0*m_barrier/m_bias_prefactor/m_kbt)); + } + if (m_cutoff <= 0) { + return cvm::error("you must choose a value of kernelCutoff greater than zero"); + } + m_cutoff2 = m_cutoff * m_cutoff; + m_val_at_cutoff = std::exp(-0.5 * m_cutoff2); + get_keyval(conf, "compressionThreshold", m_compression_threshold, 1); + if (m_compression_threshold != 0) { + if (m_compression_threshold < 0 || m_compression_threshold > m_cutoff) { + return cvm::error("compressionThreshold cannot be smaller than 0 or larger than kernelCutoff", COLVARS_INPUT_ERROR); + } + } + m_compression_threshold2 = m_compression_threshold * m_compression_threshold; + get_keyval(conf, "neighborList", m_nlist, false); + if (m_nlist) { + get_keyval(conf, "neighborListNewHillReset", m_nlist_pace_reset, false); + std::vector nlist_param; + get_keyval(conf, "neighborListParameters", nlist_param, std::vector()); + if (nlist_param.empty()) { + m_nlist_param[0] = 3.0; //*cutoff2_ -> max distance of neighbors + m_nlist_param[1] = 0.5; //*nlist_dev2_[i] -> condition for rebuilding + } else { + if (nlist_param.size() != 2) { + return cvm::error("two cutoff parameters are needed for the neighbor list", COLVARS_INPUT_ERROR); + } + if (nlist_param[0] <= 1.0) { + return cvm::error("the first of neighborListParam must be greater than 1.0. The smaller the first, the smaller should be the second as well", COLVARS_INPUT_ERROR); + } + const cvm::real min_PARAM_1 = (1.-1./std::sqrt(nlist_param[0]))+0.16; + if (nlist_param[1] <= 0) { + return cvm::error("the second of neighborListParam must be greater than 0", COLVARS_INPUT_ERROR); + } + if (nlist_param[1] > min_PARAM_1) { + return cvm::error("the second of neighborListParam must be smaller to avoid systematic errors. Largest suggested value is: 1.16-1/sqrt(param_0) = " + cvm::to_str(min_PARAM_1), COLVARS_INPUT_ERROR); + } + m_nlist_param = nlist_param; + } + m_nlist_center.resize(num_variables()); + m_nlist_dev2.resize(num_variables(), 0); + m_nlist_steps = 0; + m_nlist_update = true; + } + get_keyval(conf, "noZed", m_no_zed, false); + if (m_no_zed) { + m_sum_weights = 1; + m_sum_weights2 = 1; + } + get_keyval(conf, "fixedGaussianSigma", m_fixed_sigma, false); + get_keyval(conf, "recursiveMerge", m_recursive_merge, true); + get_keyval(conf, "calcWork", m_calc_work, false); + bool b_replicas = false; + get_keyval(conf, "multipleReplicas", b_replicas, false); + +#ifdef OPES_THREADING + get_keyval_feature(this, conf, "smp", f_cvb_smp, is_enabled(f_cvb_smp)); + if (is_enabled(f_cv_smp)) { + m_num_threads = cvm::proxy->smp_num_threads(); + } else { + m_num_threads = 1; + } +#else + // if (m_num_threads > 1) { + // return cvm::error("Multithreading in OPES is not compiled.\n"); + // } + m_num_threads = 1; +#endif + bool serial = false; + get_keyval(conf, "serial", serial, false); + if (serial) m_num_threads = 1; + comm = b_replicas ? multiple_replicas : single_replica; + if (comm == multiple_replicas) { + colvarproxy *proxy = cvm::main()->proxy; + get_keyval(conf, "replicaID", replica_id, replica_id); + get_keyval(conf, "sharedFreq", shared_freq, output_freq); + if (!replica_id.size()) { + if (proxy->check_replicas_enabled() == COLVARS_OK) { + // Obtain replicaID from the communicator + replica_id = cvm::to_str(proxy->replica_index()); + cvm::log("Setting replicaID from communication layer: replicaID = "+ + replica_id+".\n"); + } else { + return cvm::error("Error: using more than one replica, but replicaID " + "could not be obtained.\n", COLVARS_INPUT_ERROR); + } + } + m_num_walkers = proxy->num_replicas(); + } + get_keyval(conf, "pmf", m_pmf_grid_on, false); + if (m_pmf_grid_on) { + std::vector pmf_cv_name; + get_keyval(conf, "pmfColvars", pmf_cv_name); + for (auto it = pmf_cv_name.begin(); it != pmf_cv_name.end(); ++it) { + bool found = false; + for (size_t i = 0; i < num_variables(); ++i) { + if (variables(i)->name == (*it)) { + if (variables(i)->enable(f_cv_grid) != COLVARS_OK) { + return cvm::error("CV " + (*it) + " does not support grid\n"); + } + m_pmf_cvs.push_back(variables(i)); + found = true; + break; + } + } + if (!found) { + return cvm::error("CV " + (*it) + " not found\n"); + } + } + key_lookup(conf, "grid", &grid_conf); + m_reweight_grid.reset(new colvar_grid_scalar(m_pmf_cvs, nullptr, false, grid_conf)); + m_pmf_grid.reset(new colvar_grid_scalar(m_pmf_cvs, m_reweight_grid)); + get_keyval(conf, "pmfHistoryFrequency", m_pmf_hist_freq, 0); + if (comm == multiple_replicas) { + get_keyval(conf, "pmfShared", m_pmf_shared, true); + if (m_pmf_shared) { + m_global_reweight_grid.reset(new colvar_grid_scalar(m_pmf_cvs, m_reweight_grid)); + m_global_pmf_grid.reset(new colvar_grid_scalar(m_pmf_cvs, m_reweight_grid)); + } + } + } + m_kdenorm = m_explore? m_counter : m_sum_weights; + m_old_kdenorm = m_kdenorm; + m_traj_line.rct = m_kbt * cvm::logn(m_sum_weights / m_counter); + m_traj_line.zed = m_zed; + m_traj_line.neff = (1 + m_sum_weights) * (1 + m_sum_weights) / (1 + m_sum_weights2); + m_traj_line.nker = m_kernels.size(); + get_keyval(conf, "printTrajectoryFrequency", m_traj_output_frequency, cvm::cv_traj_freq); + m_cv.resize(num_variables(), 0); + showInfo(); + return error_code; +} + +void colvarbias_opes::showInfo() const { + // Print information about this bias + auto printInfo = [&](const std::string& info, const std::string& val){ + cvm::log(this->name + ": " + info + val + "\n"); + }; + printInfo("temperature = ", cvm::to_str(m_kbt / cvm::proxy->boltzmann())); + printInfo("beta = ", cvm::to_str(1.0 / m_kbt)); + printInfo("depositing new kernels with newHillFrequency = ", cvm::to_str(m_pace)); + printInfo("expected barrier is ", cvm::to_str(m_barrier)); + printInfo("using target distribution with biasfactor (gamma) = ", m_inf_biasfactor ? "inf" : cvm::to_str(m_biasfactor)); + if (m_inf_biasfactor) { + cvm::log(" (thus a uniform flat target distribution, no well-tempering)\n"); + cvm::log(this->name + ": " + "the equivalent bias temperature = inf\n"); + } else { + cvm::log(this->name + ": " + "the equivalent bias temperature = " + cvm::to_str(cvm::proxy->target_temperature() * (m_biasfactor - 1))); + } + if (m_adaptive_sigma) { + printInfo("adaptive sigma will be used, with adaptiveSigmaStride = ", cvm::to_str(m_adaptive_sigma_stride)); + size_t x = std::ceil(m_adaptive_sigma_stride / m_pace); + printInfo(" thus the first x kernel depositions will be skipped, x = adaptiveSigmaStride/newHillFrequency = ", cvm::to_str(x)); + } else { + std::string sigmas; + for (size_t i = 0; i < num_variables(); ++i) { + sigmas += " " + cvm::to_str(m_sigma0[i]); + } + cvm::log(this->name + ": kernels have initial gaussianSigma = " + sigmas + "\n"); + } + if (m_fixed_sigma) { + cvm::log(this->name + " fixedGaussianSigma: gaussianSigma will not decrease as the simulation proceeds\n"); + } + printInfo("kernels are truncated with kernelCutoff = ", cvm::to_str(m_cutoff)); + if (m_cutoff < 3.5) { + cvm::log(this->name + " +++ WARNING +++ probably kernels are truncated too much\n"); + } + printInfo("the value at cutoff is = ", cvm::to_str(m_val_at_cutoff)); + printInfo("regularization epsilon = ", cvm::to_str(m_epsilon)); + if (m_val_at_cutoff > m_epsilon*(1+1e-6)) { + cvm::log(this->name + " +++ WARNING +++ the kernelCutoff might be too small for the given epsilon\n"); + } + printInfo("kernels will be compressed when closer than compression_threshold = ", cvm::to_str(m_compression_threshold)); + if (m_compression_threshold2 == 0) { + cvm::log(this->name + " +++ WARNING +++ kernels will never merge, expect slowdowns\n"); + } + if (!m_recursive_merge) { + cvm::log(this->name + " -- RECURSIVE_MERGE_OFF: only one merge for each new kernel will be attempted. This is faster only if total number of kernels does not grow too much\n"); + } + if (m_nlist) { + cvm::log(this->name + " neighborList: using neighbor list for kernels, with parameters: " + cvm::to_str(m_nlist_param[0]) + " " + cvm::to_str(m_nlist_param[1]) + "\n"); + if (m_nlist_pace_reset) { + cvm::log(this->name + " neighborListNewHillReset: forcing the neighbor list to update every time when depositing a new hill\n"); + } + } + if (m_no_zed) { + printInfo("noZed: using fixed normalization factor = ", cvm::to_str(m_zed)); + } + if (comm == multiple_replicas && m_num_walkers > 1) { + cvm::log(this->name + " if multiple replicas are present, they will share the same bias\n"); + } + if (m_num_threads > 1) { + printInfo("using multiple threads per simulation: ", cvm::to_str(m_num_threads)); + } + cvm::main()->cite_feature("OPES"); + if (m_adaptive_sigma || m_explore) { + cvm::main()->cite_feature("OPES explore or adaptive kernels"); + } +} + +cvm::real colvarbias_opes::evaluateKernel( + const colvarbias_opes::kernel& G, + const std::vector& x) const { + cvm::real norm2 = 0; + for (size_t i = 0; i < num_variables(); ++i) { + const cvm::real dist2_i = variables(i)->dist2(G.m_center[i], x[i]) / (G.m_sigma[i] * G.m_sigma[i]); + norm2 += dist2_i; + if (norm2 >= m_cutoff2) { + return 0; + } + } + return G.m_height * (std::exp(-0.5 * norm2) - m_val_at_cutoff); +} + +cvm::real colvarbias_opes::evaluateKernel( + const colvarbias_opes::kernel& G, + const std::vector& x, + std::vector& accumulated_derivative, + std::vector& dist) const { + cvm::real norm2 = 0; + for (size_t i = 0; i < num_variables(); ++i) { + dist[i] = 0.5 * variables(i)->dist2_lgrad(x[i], G.m_center[i]) / G.m_sigma[i]; + norm2 += dist[i] * dist[i]; + if (norm2 >= m_cutoff2) { + return 0; + } + } + const cvm::real val = G.m_height * (std::exp(-0.5 * norm2) - m_val_at_cutoff); + // The derivative of norm2 with respect to x + for (size_t i = 0; i < num_variables(); ++i) { + accumulated_derivative[i] -= val * dist[i] / G.m_sigma[i]; + } + return val; +} + +cvm::real colvarbias_opes::getProbAndDerivatives( + const std::vector& cv, std::vector& der_prob) const { + double prob = 0.0; + std::vector dist(num_variables(), 0); + if (!m_nlist) { + if (m_num_threads == 1 || m_kernels.size() < 2 * m_num_threads) { + for (size_t k = 0; k < m_kernels.size(); ++k) { + prob += evaluateKernel(m_kernels[k], cv, der_prob, dist); + } + } else { +#if defined(_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + std::vector omp_deriv(der_prob.size(), 0); + std::vector tmp_dist(num_variables()); + #pragma omp for reduction(+:prob) nowait + for (int k = 0; k < static_cast(m_kernels.size()); ++k) { + prob += evaluateKernel(m_kernels[k], cv, omp_deriv, tmp_dist); + } + #pragma omp critical + for (int i = 0; i < static_cast(num_variables()); ++i) { + der_prob[i]+=omp_deriv[i]; + } + #pragma omp single + for (int i = 0; i < static_cast(num_variables()); ++i) { + dist[i] = tmp_dist[i]; + } + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + // TODO: Test this once fine-grained parallelization is enabled + std::vector> derivs(m_num_threads, std::vector(num_variables(), 0)); + std::vector> dists(m_num_threads, std::vector(num_variables(), 0)); + auto worker = [&](int start, int end, void* result){ + const int tid = cvm::proxy->smp_thread_id(); + double tmp_prob = 0; + for (int i = start; i <= end; ++i) { + tmp_prob += evaluateKernel(m_kernels[i], cv, derivs[tid], dists[tid]); + } + *(double *)result = tmp_prob; + }; + const size_t numChunks = m_kernels.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, &prob, CKLOOP_DOUBLE_SUM, NULL); + for (size_t i = 0; i < num_variables(); ++i) { + for (size_t j = 0; j < m_num_threads; ++j) { + if (j == 0) dist[i] = dists[j][i]; + der_prob[i] += derivs[j][i]; + } + } +#else + cvm::error("multiple threads required in OPES, but this binary is not linked with a supported threading library.\n"); +#endif + } + } else { + if (m_num_threads == 1 || m_nlist_index.size() < 2 * m_num_threads) { + for (size_t nk = 0; nk < m_nlist_index.size(); ++nk) { + const size_t k = m_nlist_index[nk]; + prob += evaluateKernel(m_kernels[k], cv, der_prob, dist); + } + } else { +#if defined(_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + std::vector omp_deriv(der_prob.size(), 0); + std::vector tmp_dist(num_variables()); + #pragma omp for reduction(+:prob) nowait + for (int nk = 0; nk < static_cast(m_nlist_index.size()); ++nk) { + const size_t k = m_nlist_index[nk]; + prob += evaluateKernel(m_kernels[k], cv, omp_deriv, tmp_dist); + } + #pragma omp critical + for (int i = 0; i < static_cast(num_variables()); ++i) { + der_prob[i]+=omp_deriv[i]; + } + #pragma omp single + for (int i = 0; i < static_cast(num_variables()); ++i) { + dist[i] = tmp_dist[i]; + } + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + // TODO: Test this once fine-grained parallelization is enabled + std::vector> derivs(m_num_threads, std::vector(num_variables(), 0)); + std::vector> dists(m_num_threads, std::vector(num_variables(), 0)); + auto worker = [&](int start, int end, void* result){ + const int tid = cvm::proxy->smp_thread_id(); + double tmp_prob = 0; + for (int i = start; i <= end; ++i) { + const size_t k = m_nlist_index[i]; + tmp_prob += evaluateKernel(m_kernels[k], cv, derivs[tid], dists[tid]); + } + *(double *)result = tmp_prob; + }; + const size_t numChunks = m_nlist_index.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, &prob, CKLOOP_DOUBLE_SUM, NULL); + for (size_t i = 0; i < num_variables(); ++i) { + for (size_t j = 0; j < m_num_threads; ++j) { + if (j == 0) dist[i] = dists[j][i]; + der_prob[i] += derivs[j][i]; + } + } +#else + cvm::error("multiple threads required in OPES, but this binary is not linked with a supported threading library.\n"); +#endif + } + } + prob /= m_kdenorm; + for (size_t i = 0; i < num_variables(); ++i) { + der_prob[i] /= m_kdenorm; + } + return prob; +} + +int colvarbias_opes::calculate_opes() { + if (m_nlist) { + ++m_nlist_steps; + const bool exchange_step = + (comm == multiple_replicas) && + cvm::step_absolute() % shared_freq == 0; + if (exchange_step) { + m_nlist_update = true; + } else { + for (size_t i = 0; i < num_variables(); ++i) { + const cvm::real diff_i2 = variables(i)->dist2(m_cv[i], m_nlist_center[i]); + if (diff_i2 > m_nlist_param[1] * m_nlist_dev2[i]) { + m_nlist_update = true; + break; + } + } + } + if (m_nlist_update) { + updateNlist(m_cv); + } + } + std::vector der_prob(num_variables(), 0); + const cvm::real prob = getProbAndDerivatives(m_cv, der_prob); + const cvm::real bias = m_kbt * m_bias_prefactor * cvm::logn(prob / m_zed + m_epsilon); + bias_energy = bias; + if (is_enabled(f_cvb_apply_force)) { + for (size_t i = 0; i < num_variables(); ++i) { + colvar_forces[i] = -m_kbt * m_bias_prefactor / (prob / m_zed + m_epsilon) * der_prob[i] / m_zed; + } + } + return COLVARS_OK; +} + +int colvarbias_opes::update_opes() { + if (m_adaptive_sigma) { + m_adaptive_counter++; + cvm::step_number tau = m_adaptive_sigma_stride; + if (m_adaptive_counter < m_adaptive_sigma_stride) tau = m_adaptive_counter; + for (size_t i = 0; i < num_variables(); ++i) { + // Welford's online algorithm for standard deviation + const cvm::real diff_i = 0.5 * variables(i)->dist2_lgrad(m_cv[i], m_av_cv[i]); + m_av_cv[i] += diff_i / tau; + m_av_M2[i] += diff_i * 0.5 * variables(i)->dist2_lgrad(m_cv[i], m_av_cv[i]); + } + if (m_adaptive_counter < m_adaptive_sigma_stride && m_counter == 1) { + return COLVARS_OK;; + } + } + if (cvm::step_absolute() % m_pace == 0) { + m_old_kdenorm = m_kdenorm; + m_delta_kernels.clear(); + const size_t old_nker = m_kernels.size(); + // TODO: how could I account for extra biases in Colvars? + const cvm::real log_weight = bias_energy / m_kbt; + cvm::real height = cvm::exp(log_weight); + cvm::real sum_heights = height; + cvm::real sum_heights2 = height * height; + if (m_num_walkers > 1) { + std::vector replica_sum_heights(cvm::proxy->num_replicas() - 1, 0); + // Send all sum_heights to PE 0 + if (cvm::proxy->replica_index() == 0) { + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_recv((char*)&(replica_sum_heights[p - 1]), sizeof(cvm::real), p) != sizeof(cvm::real)) { + return cvm::error("Error: receiving sum of weights from replica " + cvm::to_str(p)); + } + } + } else { + if (cvm::proxy->replica_comm_send((char*)&sum_heights, sizeof(cvm::real), 0) != sizeof(cvm::real)) { + return cvm::error("Error: sending sum of weights to replica 0."); + } + } + cvm::proxy->replica_comm_barrier(); + // PE 0 sum all sum_heights and broadcast + if (cvm::proxy->replica_index() == 0) { + for (auto it = replica_sum_heights.begin(); it != replica_sum_heights.end(); ++it) { + sum_heights += (*it); + } + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_send((char*)&sum_heights, sizeof(cvm::real), p) != sizeof(cvm::real)) { + return cvm::error("Error: sending sum of weights to replica " + cvm::to_str(p)); + } + } + } else { + if (cvm::proxy->replica_comm_recv((char*)&sum_heights, sizeof(cvm::real), 0) != sizeof(cvm::real)) { + return cvm::error("Error: receiving sum of weights from replica 0."); + } + } + cvm::proxy->replica_comm_barrier(); + // Send all sum_heights2 to PE 0 + std::vector replica_sum_heights2(cvm::proxy->num_replicas() - 1, 0); + if (cvm::proxy->replica_index() == 0) { + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_recv((char*)&(replica_sum_heights2[p - 1]), sizeof(cvm::real), p) != sizeof(cvm::real)) { + return cvm::error("Error: getting sum of weights2 from replica " + cvm::to_str(p)); + } + } + } else { + if (cvm::proxy->replica_comm_send((char*)&sum_heights2, sizeof(cvm::real), 0) != sizeof(cvm::real)) { + return cvm::error("Error: sending sum of weights2 from replica."); + } + } + cvm::proxy->replica_comm_barrier(); + // PE 0 sum all sum_heights2 and broadcast + if (cvm::proxy->replica_index() == 0) { + for (auto it = replica_sum_heights2.begin(); it != replica_sum_heights2.end(); ++it) { + sum_heights2 += (*it); + } + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_send((char*)&sum_heights2, sizeof(cvm::real), p) != sizeof(cvm::real)) { + return cvm::error("Error: sending sum of weights2 to replica " + cvm::to_str(p)); + } + } + } else { + if (cvm::proxy->replica_comm_recv((char*)&sum_heights2, sizeof(cvm::real), 0) != sizeof(cvm::real)) { + return cvm::error("Error: receiving sum of weights2 from replica."); + } + } + cvm::proxy->replica_comm_barrier(); + } + m_counter += m_num_walkers; + m_sum_weights += sum_heights; + m_sum_weights2 += sum_heights2; + m_neff = (1 + m_sum_weights) * (1 + m_sum_weights) / (1 + m_sum_weights2); + m_rct = m_kbt * cvm::logn(m_sum_weights / m_counter); + m_traj_line.neff = m_neff; + m_traj_line.rct = m_rct; + if (m_explore) { + m_kdenorm = m_counter; + height = 1.0; + } else { + m_kdenorm = m_sum_weights; + } + std::vector sigma = m_sigma0; + if (m_adaptive_sigma) { + const cvm::real factor = m_explore ? 1.0 : m_biasfactor; + if (m_counter == 1 + m_num_walkers) { + for (size_t i = 0; i < num_variables(); ++i) { + m_av_M2[i] *= m_biasfactor; + } + for (size_t i = 0; i < num_variables(); ++i) { + m_sigma0[i] = std::sqrt(m_av_M2[i] / m_adaptive_counter / factor); + } + if (m_sigma_min.size() == 0) { + for (size_t i = 0; i < num_variables(); ++i) { + if (m_sigma0[i] < 1e-6) { + cvm::error("Adaptive sigma is suspiciously small for CV " + cvm::to_str(i) + "\nManually provide sigma or set a safe sigma_min to avoid possible issues\n"); + return COLVARS_ERROR; + } + } + } else { + for (size_t i = 0; i < num_variables(); ++i) { + m_sigma0[i] = std::max(m_sigma0[i], m_sigma_min[i]); + } + } + } + for (size_t i = 0; i < num_variables(); ++i) { + sigma[i] = std::sqrt(m_av_M2[i] / m_adaptive_counter / factor); + } + if (m_sigma_min.size() == 0) { + bool sigma_less_than_threshold = false; + for (size_t i = 0; i < num_variables(); ++i) { + if (sigma[i] < 1e-6) { + cvm::log("The adaptive sigma is suspiciously small, you should set a safe sigma_min. 1e-6 will be used here\n"); + sigma[i] = 1e-6; + sigma_less_than_threshold = true; + } + } + if (sigma_less_than_threshold) { + m_sigma_min.assign(num_variables(), 1e-6); + } + } else { + for (size_t i = 0; i < num_variables(); ++i) { + sigma[i] = std::max(sigma[i], m_sigma_min[i]); + } + } + } + if (!m_fixed_sigma) { + const cvm::real size = m_explore ? m_counter : m_neff; + const size_t ncv = num_variables(); + const cvm::real s_rescaling = std::pow(size * (ncv + 2.0) / 4, -1.0 / (4.0 + ncv)); + for (size_t i = 0; i < num_variables(); ++i) { + sigma[i] *= s_rescaling; + } + if (m_sigma_min.size() > 0) { + for (size_t i = 0; i < num_variables(); ++i) { + sigma[i] = std::max(sigma[i], m_sigma_min[i]); + } + } + } + // the height should be divided by sqrt(2*pi)*sigma0_, + // but this overall factor would be canceled when dividing by Zed + // thus we skip it altogether, but keep any other sigma rescaling + for (size_t i = 0; i < num_variables(); ++i) { + height *= (m_sigma0[i] / sigma[i]); + } + if (m_num_walkers == 1) { + addKernel(height, m_cv, sigma, log_weight); + } else { + std::vector all_height(m_num_walkers, 0.0); + std::vector all_center(m_num_walkers * num_variables(), 0.0); + std::vector all_sigma(m_num_walkers * num_variables(), 0.0); + std::vector all_logweight(m_num_walkers, 0.0); + const int my_replica = cvm::proxy->replica_index(); + + // Allgather of heights + if (my_replica == 0) { + all_height[0] = height; + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_recv((char*)&(all_height[p]), sizeof(decltype(all_height)::value_type), p) != sizeof(decltype(all_height)::value_type)) { + return cvm::error("Error: on receiving height on replica 0 from replica " + cvm::to_str(p)); + } + } + } else { + if (cvm::proxy->replica_comm_send((char*)&height, sizeof(decltype(height)), 0) != sizeof(cvm::real)) { + return cvm::error("Error: on sending height to replica 0 from replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + // Broadcast heights + if (my_replica == 0) { + const int send_size = sizeof(decltype(all_height)::value_type) * all_height.size(); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_send((char*)all_height.data(), send_size, p) != send_size) { + return cvm::error("Error: on sending heights from replica 0 to replica " + cvm::to_str(p)); + } + } + } else { + const int recv_size = sizeof(decltype(all_height)::value_type) * all_height.size(); + if (cvm::proxy->replica_comm_recv((char*)all_height.data(), recv_size, 0) != recv_size) { + return cvm::error("Error: on receiving heights from replica 0 to replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + + // Allgather of centers + if (my_replica == 0) { + std::copy(m_cv.begin(), m_cv.end(), all_center.begin()); + const int recv_size = sizeof(decltype(m_cv)::value_type) * m_cv.size(); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + cvm::real* recv_start_ptr = &(all_center[p * m_cv.size()]); + if (cvm::proxy->replica_comm_recv((char*)recv_start_ptr, recv_size, p) != recv_size) { + return cvm::error("Error on receiving centers from replica 0 to replica " + cvm::to_str(p)); + } + } + } else { + const int send_size = sizeof(decltype(m_cv)::value_type) * m_cv.size(); + if (cvm::proxy->replica_comm_send((char*)m_cv.data(), send_size, 0) != send_size) { + return cvm::error("Error on sending centers to replica 0 from replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + // Broadcast centers + if (my_replica == 0) { + const int send_size = sizeof(decltype(all_center)::value_type) * all_center.size(); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_send((char*)all_center.data(), send_size, p) != send_size) { + return cvm::error("Error on sending centers from replica 0 to replica " + cvm::to_str(p)); + } + } + } else { + const int recv_size = sizeof(decltype(all_center)::value_type) * all_center.size(); + if (cvm::proxy->replica_comm_recv((char*)all_center.data(), recv_size, 0) != recv_size) { + return cvm::error("Error on receiving centers from replica 0 to replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + + // Allgather of sigmas + if (my_replica == 0) { + std::copy(sigma.begin(), sigma.end(), all_sigma.begin()); + const int recv_size = sizeof(decltype(sigma)::value_type) * sigma.size(); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + cvm::real* recv_start_ptr = &(all_sigma[p * m_cv.size()]); + if (cvm::proxy->replica_comm_recv((char*)recv_start_ptr, recv_size, p) != recv_size) { + return cvm::error("Error on receiving sigmas from replica 0 to replica " + cvm::to_str(p)); + } + } + } else { + const int send_size = sizeof(decltype(sigma)::value_type) * sigma.size(); + if (cvm::proxy->replica_comm_send((char*)sigma.data(), send_size, 0) != send_size) { + return cvm::error("Error on sending sigmas to replica 0 from replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + // Broadcast sigmas + if (my_replica == 0) { + const int send_size = sizeof(decltype(all_sigma)::value_type) * all_sigma.size(); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_send((char*)all_sigma.data(), send_size, p) != send_size) { + return cvm::error("Error on sending sigmas from replica 0 to replica " + cvm::to_str(p)); + } + } + } else { + const int recv_size = sizeof(decltype(all_sigma)::value_type) * all_sigma.size(); + if (cvm::proxy->replica_comm_recv((char*)all_sigma.data(), recv_size, 0) != recv_size) { + return cvm::error("Error on receiving sigmas from replica 0 to replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + + // Allgather of logweights + if (my_replica == 0) { + all_logweight[0] = log_weight; + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_recv((char*)&(all_logweight[p]), sizeof(decltype(all_logweight)::value_type), p) != sizeof(decltype(all_logweight)::value_type)) { + return cvm::error("Error on receiving log_weight on replica 0 from replica " + cvm::to_str(p)); + } + } + } else { + if (cvm::proxy->replica_comm_send((char*)&log_weight, sizeof(decltype(log_weight)), 0) != sizeof(cvm::real)) { + return cvm::error("Error on sending log_weight to replica 0 from replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + // Broadcast log_weight + if (my_replica == 0) { + const int send_size = sizeof(decltype(all_logweight)::value_type) * all_logweight.size(); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_send((char*)all_logweight.data(), send_size, p) != send_size) { + return cvm::error("Error on sending log_weight from replica 0 to replica " + cvm::to_str(p)); + } + } + } else { + const int recv_size = sizeof(decltype(all_logweight)::value_type) * all_logweight.size(); + if (cvm::proxy->replica_comm_recv((char*)all_logweight.data(), recv_size, 0) != recv_size) { + return cvm::error("Error on receiving log_weight from replica 0 to replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + + if (m_nlist) { + std::vector all_nlist_size(m_num_walkers); + const int my_replica = cvm::proxy->replica_index(); + // Get the size of the neighbor list of each replica + if (my_replica == 0) { + all_nlist_size[0] = m_nlist_index.size(); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_recv((char*)&(all_nlist_size[p]), sizeof(int), p) != sizeof(int)) { + return cvm::error("Error on receiving neighbor list size from replica " + cvm::to_str(p)); + } + } + } else { + const int nlist_size = m_nlist_index.size(); + if (cvm::proxy->replica_comm_send((char*)&nlist_size, sizeof(int), 0) != sizeof(int)) { + return cvm::error("Error on sending neighbor list size from replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + // Broadcast the neighbor list sizes to all replicas + if (my_replica == 0) { + const int send_size = sizeof(int) * all_nlist_size.size(); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_send((char*)all_nlist_size.data(), send_size, p) != send_size) { + return cvm::error("Error on sending neighbor list sizes from replica 0 to replica " + cvm::to_str(p)); + } + } + } else { + const int recv_size = sizeof(int) * all_nlist_size.size(); + if (cvm::proxy->replica_comm_recv((char*)all_nlist_size.data(), recv_size, 0) != recv_size) { + return cvm::error("Error on receiving neighbor list sizes to replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + // Gather all neighbor lists from replicas + const int tot_size = std::accumulate(all_nlist_size.begin(), all_nlist_size.end(), 0); + if (tot_size > 0) { + // Allgatherv all neighbor lists from replicas + std::vector all_nlist_index(tot_size); + if (my_replica == 0) { + std::vector recv_start(m_num_walkers); + // Accumulative sum + recv_start[0] = 0; + std::partial_sum(all_nlist_size.begin(), all_nlist_size.end() - 1, recv_start.begin() + 1); + std::copy(m_nlist_index.begin(), m_nlist_index.end(), all_nlist_index.begin()); + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + size_t* recv_start_ptr = &(all_nlist_index[recv_start[p]]); + const int recv_size = all_nlist_size[p] * sizeof(decltype(all_nlist_index)::value_type); + if (cvm::proxy->replica_comm_recv((char*)recv_start_ptr, recv_size, p) != recv_size) { + return cvm::error("Error on receiving neighbor list from replica " + cvm::to_str(p)); + } + } + } else { + const int send_size = sizeof(decltype(m_nlist_index)::value_type) * m_nlist_index.size(); + if (cvm::proxy->replica_comm_send((char*)m_nlist_index.data(), send_size, 0) != send_size) { + return cvm::error("Error on sending neighbor list from replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + // Broadcast the neighbor list + if (my_replica == 0) { + const int send_size = sizeof(decltype(all_nlist_index)::value_type) * tot_size; + for (int p = 1; p < cvm::proxy->num_replicas(); ++p) { + if (cvm::proxy->replica_comm_send((char*)all_nlist_index.data(), send_size, p) != send_size) { + return cvm::error("Error on sending total neighbor list to replica " + cvm::to_str(p)); + } + } + } else { + const int recv_size = sizeof(decltype(all_nlist_index)::value_type) * tot_size; + if (cvm::proxy->replica_comm_recv((char*)all_nlist_index.data(), recv_size, 0) != recv_size) { + return cvm::error("Error on receiving total neighbor list on replica " + cvm::to_str(my_replica)); + } + } + cvm::proxy->replica_comm_barrier(); + // Deduplicate and sort the merged neighbor list + std::unordered_set all_nlist_index_set; + for (auto it = all_nlist_index.cbegin(); it != all_nlist_index.cend(); ++it) { + all_nlist_index_set.insert(*it); + } + m_nlist_index.assign(all_nlist_index_set.begin(), all_nlist_index_set.end()); + std::sort(m_nlist_index.begin(), m_nlist_index.end()); + } + } + for (size_t w = 0; w < m_num_walkers; ++w) { + std::vector center_w( + all_center.begin() + num_variables() * w, + all_center.begin() + num_variables() * (w + 1)); + std::vector sigma_w( + all_sigma.begin() + num_variables() * w, + all_sigma.begin() + num_variables() * (w + 1)); + addKernel(all_height[w], center_w, sigma_w, all_logweight[w]); + } + } + m_nker = m_kernels.size(); + m_traj_line.nker = m_nker; + if (m_nlist) { + m_nlker = m_nlist_index.size(); + m_traj_line.nlker = m_nlker; + if (m_nlist_pace_reset) { + m_nlist_update = true; + } + } + if (!m_no_zed) { + cvm::real sum_uprob = 0; + const size_t ks = m_kernels.size(); + const size_t ds = m_delta_kernels.size(); + const int num_parallel = 1; // Always 1 + const bool few_kernels = (ks * ks < (3 * ks * ds + 2 * ds * ds * num_parallel + 100)); + if (few_kernels) { + if (m_num_threads == 1) { + for (size_t k = 0; k < m_kernels.size(); ++k) { + for (size_t kk = 0; kk < m_kernels.size(); ++kk) { + sum_uprob += evaluateKernel(m_kernels[kk], m_kernels[k].m_center); + } + } + } else { +#if defined(_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + #pragma omp for reduction(+:sum_uprob) nowait + for (int k = 0; k < static_cast(m_kernels.size()); ++k) { + for (int kk = 0; kk < static_cast(m_kernels.size()); ++kk) { + sum_uprob += evaluateKernel(m_kernels[kk], m_kernels[k].m_center); + } + } + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + // TODO: Does this work?? + auto worker = [&](int start, int end, void* result) { + double tmp_prob = 0; + for (int i = start; i <= end; ++i) { + for (size_t kk = 0; kk < m_kernels.size(); ++kk) { + tmp_prob += evaluateKernel(m_kernels[kk], m_kernels[i].m_center); + } + } + *(double *)result = tmp_prob; + }; + const size_t numChunks = m_kernels.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, &sum_uprob, CKLOOP_DOUBLE_SUM, NULL); +#else + cvm::error("OPES cannot run because this binary is not linked with a supported threading library.\n"); +#endif + } + if (num_parallel > 1) { + return cvm::error("Unimplemented feature: OPES in parallel running.\n"); + } + } else { + cvm::real delta_sum_uprob = 0; + if (!m_nlist) { + if (m_num_threads == 1) { + for (size_t i = 0; i < m_kernels.size(); ++i) { + for (size_t d = 0; d < m_delta_kernels.size(); ++d) { + const int sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + delta_sum_uprob += evaluateKernel(m_delta_kernels[d], m_kernels[i].m_center) + sign * evaluateKernel(m_kernels[i], m_delta_kernels[d].m_center); + } + } + } else { +#if defined(_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + #pragma omp for reduction(+:delta_sum_uprob) nowait + for (int i = 0; i < static_cast(m_kernels.size()); ++i) { + for (int d = 0; d < static_cast(m_delta_kernels.size()); ++d) { + const int sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + delta_sum_uprob += evaluateKernel(m_delta_kernels[d], m_kernels[i].m_center) + sign * evaluateKernel(m_kernels[i], m_delta_kernels[d].m_center); + } + } + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + auto worker = [&](int start, int end, void* result) { + double tmp_prob = 0; + for (int i = start; i <= end; ++i) { + for (size_t d = 0; d < m_delta_kernels.size(); ++d) { + const int sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + tmp_prob += evaluateKernel(m_delta_kernels[d], m_kernels[i].m_center) + sign * evaluateKernel(m_kernels[i], m_delta_kernels[d].m_center); + } + } + *(double *)result = tmp_prob; + }; + const size_t numChunks = m_kernels.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, &delta_sum_uprob, CKLOOP_DOUBLE_SUM, NULL); +#else + cvm::error("OPES cannot run because this binary is not linked with a supported threading library.\n"); +#endif + } + } else { + if (m_num_threads == 1) { + for (size_t i = 0; i < m_nlist_index.size(); ++i) { + const size_t k = m_nlist_index[i]; + for (size_t d = 0; d < m_delta_kernels.size(); ++d) { + const double sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + delta_sum_uprob += evaluateKernel(m_delta_kernels[d], m_kernels[k].m_center) + sign * evaluateKernel(m_kernels[k], m_delta_kernels[d].m_center); + } + } + } else { +#if defined(_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + #pragma omp for reduction(+:delta_sum_uprob) nowait + for (int i = 0; i < static_cast(m_nlist_index.size()); ++i) { + const size_t k = m_nlist_index[i]; + for (int d = 0; d < static_cast(m_delta_kernels.size()); ++d) { + const double sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + delta_sum_uprob += evaluateKernel(m_delta_kernels[d], m_kernels[k].m_center) + sign * evaluateKernel(m_kernels[k], m_delta_kernels[d].m_center); + } + } + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + auto worker = [&](int start, int end, void* result) { + double tmp_prob = 0; + for (int i = start; i <= end; ++i) { + const size_t k = m_nlist_index[i]; + for (size_t d = 0; d < m_delta_kernels.size(); ++d) { + const double sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + tmp_prob += evaluateKernel(m_delta_kernels[d], m_kernels[k].m_center) + sign * evaluateKernel(m_kernels[k], m_delta_kernels[d].m_center); + } + } + *(double *)result = tmp_prob; + }; + const size_t numChunks = m_nlist_index.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, &delta_sum_uprob, CKLOOP_DOUBLE_SUM, NULL); +#else + cvm::error("OPES cannot run because this binary is not linked with a supported threading library.\n"); +#endif + } + } + if (num_parallel > 1) { + return cvm::error("Unimplemented feature: OPES in parallel running.\n"); + } + if (m_num_threads == 1) { + for (size_t d = 0; d < m_delta_kernels.size(); ++d) { + for (size_t dd = 0; dd < m_delta_kernels.size(); ++dd) { + const int sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + delta_sum_uprob -= sign *evaluateKernel(m_delta_kernels[dd], m_delta_kernels[d].m_center); + } + } + } else { +#if defined(_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + #pragma omp for reduction(+:delta_sum_uprob) + for (int d = 0; d < static_cast(m_delta_kernels.size()); ++d) { + for (int dd = 0; dd < static_cast(m_delta_kernels.size()); ++dd) { + const int sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + delta_sum_uprob -= sign * evaluateKernel(m_delta_kernels[dd], m_delta_kernels[d].m_center); + } + } + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + auto worker = [&](int start, int end, void* result) { + double tmp_prob = 0; + for (int d = start; d <= end; ++d) { + for (size_t dd = 0; dd < m_delta_kernels.size(); ++dd) { + const int sign = m_delta_kernels[d].m_height < 0 ? -1 : 1; + tmp_prob += sign * evaluateKernel(m_delta_kernels[dd], m_delta_kernels[d].m_center); + } + } + *(double *)result = tmp_prob; + }; + const size_t numChunks = m_delta_kernels.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + double tmp = 0; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, &tmp, CKLOOP_DOUBLE_SUM, NULL); + delta_sum_uprob -= tmp; +#else + cvm::error("OPES cannot run because this binary is not linked with a supported threading library.\n"); +#endif + } + sum_uprob = m_zed * m_old_kdenorm * old_nker + delta_sum_uprob; + } + m_zed = sum_uprob / m_kdenorm / m_kernels.size(); + m_traj_line.zed = m_zed; + } + if (m_calc_work) { + std::vector dummy(num_variables()); + const cvm::real prob = getProbAndDerivatives(m_cv, dummy); + const cvm::real new_bias = m_kbt * m_bias_prefactor * cvm::logn(prob / m_zed + m_epsilon); + m_work += new_bias - bias_energy; + m_traj_line.work = m_work; + } + } + return COLVARS_OK; +} + +void colvarbias_opes::save_state() { + if (cvm::step_absolute() % cvm::restart_out_freq == 0) { + m_saved_zed = m_zed; + m_saved_sum_weights = m_sum_weights; + m_saved_sum_weights2 = m_sum_weights2; + m_saved_kernels = m_kernels; + } +} + +int colvarbias_opes::update() { + int error_code = COLVARS_OK; + for (size_t i = 0; i < num_variables(); ++i) { + m_cv[i] = variables(i)->value(); + } + error_code |= calculate_opes(); + // NOTE: I don't think that calling dumpStateToFile() after update in + // the PLUMED implementation is correct for step 0, so I save the + // data after calculate() that does not modify the internal state + // of the bias. + save_state(); + if (error_code != COLVARS_OK) return error_code; + if (m_is_first_step) { + // NOTE: Colvars does not allow chainned biases, so I have to implement + // the PRINT here. Even if OPESmetad::update() is skipped we should + // still call Print::update() + writeTrajBuffer(); + if (m_pmf_grid_on) error_code |= collectSampleToPMFGrid(); + m_is_first_step = false; + return COLVARS_OK; + } + error_code |= update_opes(); + if (error_code != COLVARS_OK) return error_code; + writeTrajBuffer(); // Print::update() + if (m_pmf_grid_on) error_code |= collectSampleToPMFGrid(); + return error_code; +} + +int colvarbias_opes::collectSampleToPMFGrid() { + if (m_reweight_grid) { + // Get the bin index + std::vector bin(m_pmf_cvs.size(), 0); + for (size_t i = 0; i < m_pmf_cvs.size(); ++i) { + bin[i] = m_reweight_grid->current_bin_scalar(i); + } + const cvm::real reweighting_factor = cvm::exp(bias_energy / m_kbt); + if (m_reweight_grid->index_ok(bin)) { + m_reweight_grid->acc_value(bin, reweighting_factor); + } + } + return COLVARS_OK; +} + +template OST& colvarbias_opes::write_state_data_template_(OST &os) const { + std::ios_base::fmtflags f; + const bool formatted = !std::is_same::value; + if (formatted) { + f = os.flags(); + os.setf(std::ios::scientific, std::ios::floatfield); + } + write_state_data_key(os, "opes_metad_" + this->name); + auto printFieldReal = [&](const std::string& s, cvm::real x){ + write_state_data_key(os, s, false); + if (formatted) + os << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width); + os << x; + if (formatted) + os << "\n"; + }; + auto printFieldULL = [&](const std::string& s, unsigned long long x){ + write_state_data_key(os, s, false); + if (formatted) + os << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width); + os << x; + if (formatted) + os << "\n"; + }; + auto printFieldString = [&](const std::string& s, const std::string& x){ + write_state_data_key(os, s, false); + if (formatted) + os << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width); + os << x; + if (formatted) + os << "\n"; + }; + std::ostringstream oss; + if (m_inf_biasfactor) { + oss << "inf"; + } else { + oss << m_biasfactor; + } + printFieldString("biasfactor", oss.str()); + printFieldReal("epsilon", m_epsilon); + printFieldReal("kernel_cutoff", cvm::sqrt(m_cutoff2)); + printFieldReal("compression_threshold", m_compression_threshold); + printFieldReal("zed", m_saved_zed); + printFieldReal("sum_weights", m_saved_sum_weights); + printFieldReal("sum_weights2", m_saved_sum_weights2); + printFieldULL("counter", m_counter); + if (m_adaptive_sigma) { + printFieldULL("adaptive_counter", m_adaptive_counter); + for (size_t i = 0; i < num_variables(); ++i) { + printFieldReal("sigma0_" + variables(i)->name, m_sigma0[i]); + printFieldReal("av_cv_" + variables(i)->name, m_av_cv[i]); + printFieldReal("av_M2_" + variables(i)->name, m_av_M2[i]); + } + } + printFieldULL("num_hills", m_saved_kernels.size()); + write_state_data_key(os, "hills", false); + if (formatted) os << "{\n"; + for (size_t k = 0; k < m_saved_kernels.size(); ++k) { + if (formatted) os << "{ "; + os << k; + if (formatted) os << " "; + for (size_t i = 0; i < num_variables(); ++i) { + os << m_saved_kernels[k].m_center[i]; + if (formatted) os << " "; + } + for (size_t i = 0; i < num_variables(); ++i) { + os << m_saved_kernels[k].m_sigma[i]; + if (formatted) os << " "; + } + os << m_saved_kernels[k].m_height; + if (formatted) os << " }\n"; + } + if (formatted) os << "}\n"; + if (formatted) os.setf(f); + if (m_pmf_grid_on) { + write_state_data_key(os, "probability_grid"); + m_reweight_grid->write_raw(os, 8); + } + return os; +} + +std::ostream& colvarbias_opes::write_state_data(std::ostream &os) { + try { + auto& s = write_state_data_template_(os); + return s; + } catch (const std::exception& e) { + cvm::error(e.what()); + } + return os; +} + +cvm::memory_stream& colvarbias_opes::write_state_data(cvm::memory_stream& os) { + try { + auto& s = write_state_data_template_(os); + return s; + } catch (const std::exception& e) { + cvm::error(e.what()); + } + return os; +} + +template IST& colvarbias_opes::read_state_data_template_(IST &is) { + bool const formatted = !std::is_same::value; + std::string tmp_name; + is >> tmp_name; + if (tmp_name.rfind("opes_metad_", 0) != 0) { + throw std::runtime_error("Unknown action name: " + tmp_name + "\n"); + } + auto readFieldString = [&](const std::string& s, std::string& x){ + std::string field; + is >> field; + if (field.compare(s) == 0) { + is >> x; + } else { + throw std::runtime_error("Expect field \"" + s + "\" , but got \"" + field + "\"\n"); + } + }; + auto readFieldReal = [&](const std::string& s, cvm::real& x){ + std::string field; + is >> field; + if (field.compare(s) == 0) { + is >> x; + } else { + throw std::runtime_error("Expect field \"" + s + "\" , but got \"" + field + "\"\n"); + } + }; + auto readFieldULL = [&](const std::string& s, unsigned long long& x){ + std::string field; + is >> field; + if (field.compare(s) == 0) { + is >> x; + } else { + throw std::runtime_error("Expect field \"" + s + "\" , but got \"" + field + "\"\n"); + } + }; + std::string old_biasfactor_str; + cvm::real old_biasfactor; + readFieldString("biasfactor", old_biasfactor_str); + if (old_biasfactor_str == "inf" || old_biasfactor_str == "-inf" || old_biasfactor_str == "+inf" || + old_biasfactor_str == "INF" || old_biasfactor_str == "-INF" || old_biasfactor_str == "+INF") { + old_biasfactor = std::numeric_limits::infinity(); + m_inf_biasfactor = true; + } else { + old_biasfactor = std::stod(old_biasfactor_str); + m_inf_biasfactor = false; + } + if (std::abs(old_biasfactor - m_biasfactor) > 1e-6 * m_biasfactor) { + cvm::log("WARNING: previous bias factor was " + cvm::to_str(old_biasfactor) + + " while now it is " + cvm::to_str(m_biasfactor) + + " (the new one is used).\n"); + } + cvm::real old_epsilon; + readFieldReal("epsilon", old_epsilon); + if (std::abs(old_epsilon - m_epsilon) > 1e-6 * m_epsilon) { + cvm::log("WARNING: previous epsilon was " + cvm::to_str(old_epsilon) + + " while now it is " + cvm::to_str(m_epsilon) + + " (the new one is used).\n"); + } + cvm::real old_cutoff; + readFieldReal("kernel_cutoff", old_cutoff); + if (std::abs(old_cutoff - m_cutoff) > 1e-6 * m_cutoff) { + cvm::log("WARNING: previous cutoff was " + cvm::to_str(old_cutoff) + + " while now it is " + cvm::to_str(m_cutoff) + + " (the new one is used).\n"); + } + m_cutoff2 = m_cutoff * m_cutoff; + cvm::real old_compression_threshold; + readFieldReal("compression_threshold", old_compression_threshold); + if (std::abs(old_compression_threshold - m_compression_threshold) > 1e-6 * m_compression_threshold) { + cvm::log("WARNING: previous cutoff was " + cvm::to_str(old_compression_threshold) + + " while now it is " + cvm::to_str(m_compression_threshold) + + " (the new one is used).\n"); + } + m_compression_threshold2 = m_compression_threshold * m_compression_threshold; + readFieldReal("zed", m_zed); + readFieldReal("sum_weights", m_sum_weights); + readFieldReal("sum_weights2", m_sum_weights2); + unsigned long long tmp_counter = 1; + readFieldULL("counter", tmp_counter); + m_counter = tmp_counter; + if (m_adaptive_sigma) { + readFieldULL("adaptive_counter", tmp_counter); + m_adaptive_counter = tmp_counter; + for (size_t i = 0; i < num_variables(); ++i) { + readFieldReal("sigma0_" + variables(i)->name, m_sigma0[i]); + readFieldReal("av_cv_" + variables(i)->name, m_av_cv[i]); + readFieldReal("av_M2_" + variables(i)->name, m_av_M2[i]); + } + } + unsigned long long kernel_size = 0; + readFieldULL("num_hills", kernel_size); + if (kernel_size > 0) m_kernels.resize(kernel_size); + read_state_data_key(is, "hills"); + auto consume = [&](const std::string& expected_token){ + if (formatted) { + std::string field; + is >> field; + if (field.compare(expected_token) != 0) { + throw std::runtime_error("Expect " + expected_token + " but got " + field + "\n"); + } + } + }; + consume("{"); + for (size_t k = 0; k < m_kernels.size(); ++k) { + consume("{"); + unsigned long long tmp_k = 0; + is >> tmp_k; + if (formatted && k != tmp_k) { + throw std::runtime_error("Corrupt hill data\n"); + } + kernel current_kernel; + current_kernel.m_center.resize(num_variables()); + current_kernel.m_sigma.resize(num_variables()); + for (size_t i = 0; i < num_variables(); ++i) { + is >> current_kernel.m_center[i]; + } + for (size_t i = 0; i < num_variables(); ++i) { + is >> current_kernel.m_sigma[i]; + } + is >> current_kernel.m_height; + m_kernels[k] = current_kernel; + consume("}"); + } + consume("}"); + if (m_pmf_grid_on) { + read_state_data_key(is, "probability_grid"); + m_reweight_grid->read_raw(is); + } + m_kdenorm = m_explore ? m_counter : m_sum_weights; + m_traj_line.rct = m_kbt * cvm::logn(m_sum_weights / m_counter); + m_traj_line.zed = m_zed; + m_traj_line.neff = (1 + m_sum_weights) * (1 + m_sum_weights) / (1 + m_sum_weights2); + m_traj_line.nker = m_kernels.size(); + showInfo(); + return is; +} + +std::istream& colvarbias_opes::read_state_data(std::istream &is) { + try { + auto& ret = read_state_data_template_(is); + return ret; + } catch (const std::exception& e) { + cvm::error(e.what()); + } + return is; +} + +cvm::memory_stream& colvarbias_opes::read_state_data(cvm::memory_stream &is) { + try { + auto& ret = read_state_data_template_(is); + return ret; + } catch (const std::exception& e) { + cvm::error(e.what()); + } + return is; +} + +void colvarbias_opes::addKernel(const double height, const std::vector& center, const std::vector& sigma, const double logweight) { + addKernel(height,center,sigma); + const std::ios_base::fmtflags f = m_kernels_output.flags(); + m_kernels_output << std::right; + // simulation time in ps + m_kernels_output << std::setw(24) << (cvm::step_absolute() * cvm::dt()) * 1e-3; + for (size_t i = 0; i < num_variables(); ++i) { + m_kernels_output << " " << std::setw(24) << std::setprecision(16) << center[i]; + } + for (size_t i = 0; i < num_variables(); ++i) { + m_kernels_output << " " << std::setw(24) << std::setprecision(16) << sigma[i]; + } + m_kernels_output << " " << std::setw(24) << std::setprecision(16) << height; + m_kernels_output << " " << std::setw(24) << std::setprecision(16) << logweight; + m_kernels_output << std::endl; + m_kernels_output.flags(f); +} + +void colvarbias_opes::addKernel(const double height, const std::vector& center, const std::vector& sigma) { + bool no_match = true; + if (m_compression_threshold2 != 0) { + size_t taker_k = getMergeableKernel(center, m_kernels.size()); + if (taker_k < m_kernels.size()) { + no_match = false; + m_delta_kernels.emplace_back(-1 * m_kernels[taker_k].m_height, m_kernels[taker_k].m_center, m_kernels[taker_k].m_sigma); + mergeKernels(m_kernels[taker_k], kernel(height, center, sigma)); + m_delta_kernels.push_back(m_kernels[taker_k]); + if (m_recursive_merge) { + size_t giver_k = taker_k; + taker_k = getMergeableKernel(m_kernels[giver_k].m_center, giver_k); + while (taker_k < m_kernels.size()) { + m_delta_kernels.pop_back(); + m_delta_kernels.emplace_back(-1 * m_kernels[taker_k].m_height, m_kernels[taker_k].m_center, m_kernels[taker_k].m_sigma); + if (taker_k > giver_k) std::swap(taker_k, giver_k); + mergeKernels(m_kernels[taker_k], m_kernels[giver_k]); + m_delta_kernels.push_back(m_kernels[taker_k]); + m_kernels.erase(m_kernels.begin() + giver_k); + if (m_nlist) { + size_t giver_nk = 0; + bool found_giver = false; + for (size_t nk = 0; nk < m_nlist_index.size(); ++nk) { + if (found_giver) m_nlist_index[nk]--; + if (m_nlist_index[nk] == giver_k) { + giver_nk = nk; + found_giver = true; + } + } + if (found_giver == false) { + cvm::error("problem with merging and nlist\n"); + } + m_nlist_index.erase(m_nlist_index.begin() + giver_nk); + } + giver_k = taker_k; + taker_k = getMergeableKernel(m_kernels[giver_k].m_center, giver_k); + } + } + } + } + if (no_match) { + m_kernels.emplace_back(height, center, sigma); + m_delta_kernels.emplace_back(height, center, sigma); + if (m_nlist) m_nlist_index.push_back(m_kernels.size() - 1); + } +} + +void colvarbias_opes::mergeKernels(kernel& k1, const kernel& k2) const { + const double h = k1.m_height + k2.m_height; + for (size_t i = 0; i < k1.m_center.size(); ++i) { + const bool isPeriodic_i = variables(i)->is_enabled(f_cv_periodic); + if (isPeriodic_i) { + k1.m_center[i] = k2.m_center[i] + 0.5 * variables(i)->dist2_lgrad(k1.m_center[i], k2.m_center[i]).real_value; + } + const cvm::real c_i = (k1.m_height * k1.m_center[i] + + k2.m_height * k2.m_center[i]) / h; + const cvm::real ss_k1_part = k1.m_height * (k1.m_sigma[i] * k1.m_sigma[i] + k1.m_center[i] * k1.m_center[i]); + const cvm::real ss_k2_part = k2.m_height * (k2.m_sigma[i] * k2.m_sigma[i] + k2.m_center[i] * k2.m_center[i]); + const cvm::real ss_i = (ss_k1_part + ss_k2_part) / h - c_i * c_i; + if (isPeriodic_i) { + colvarvalue tmp(c_i); + variables(i)->wrap(tmp); + k1.m_center[i] = tmp.real_value; + } else { + k1.m_center[i] = c_i; + } + k1.m_sigma[i] = cvm::sqrt(ss_i); + } + k1.m_height = h; +} + +size_t colvarbias_opes::getMergeableKernel(const std::vector& giver_center, const size_t giver_k) const { + size_t min_k = m_kernels.size(); + cvm::real min_norm2 = m_compression_threshold2; + const int num_parallel = 1; + if (!m_nlist) { + if (m_num_threads == 1) { + for (size_t k = 0; k < m_kernels.size(); ++k) { + if (k == giver_k) continue; + double norm2 = 0; + for (size_t i = 0; i < num_variables(); ++i) { + norm2 += variables(i)->dist2(giver_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + if (norm2 >= min_norm2) break; + } + if (norm2 < min_norm2) { + min_norm2 = norm2; + min_k = k; + } + } + } else { +#if defined(_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + int min_k_omp = min_k; + cvm::real min_norm2_omp = m_compression_threshold2; + #pragma omp for nowait + for (int k = 0; k < static_cast(m_kernels.size()); ++k) { + if (k == static_cast(giver_k)) continue; + double norm2 = 0; + for (int i = 0; i < static_cast(num_variables()); ++i) { + norm2 += variables(i)->dist2( giver_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + if (norm2 >= min_norm2_omp) break; + } + if (norm2 < min_norm2_omp) { + min_norm2_omp = norm2; + min_k_omp = k; + } + } + #pragma omp critical + { + if (min_norm2_omp < min_norm2) { + min_norm2 = min_norm2_omp; + min_k = min_k_omp; + } + } + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + // NOTE: No existing reduction type for finding the minimum, so I have + // to use such a workaround. + std::vector min_k_smp(m_num_threads, min_k); + std::vector min_norm2_smp(m_num_threads, m_compression_threshold2); + auto worker = [&](int start, int end, void* unused) { + const int tid = cvm::proxy->smp_thread_id(); + for (int k = start; k <= end; ++k) { + if (k == giver_k) continue; + double norm2 = 0; + for (size_t j = 0; j < num_variables(); ++j) { + norm2 += variables(i)->dist2( giver_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + if (norm2 >= min_norm2_smp[tid]) break; + } + if (norm2 < min_norm2_smp[tid]) { + min_norm2_smp[tid] = norm2; + min_k_smp[tid] = k; + } + } + }; + const size_t numChunks = m_kernels.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, NULL, CKLOOP_NONE, NULL); + const auto it_min = std::min_element(min_norm2_smp.begin(), min_norm2_smp.end()); + min_norm2 = *it_min; + min_k = min_k_smp[std::distance(min_norm2_smp.begin(), it_min)]; +#else + cvm::error("OPES cannot run because this binary is not linked with a supported threading library.\n"); +#endif + } + } else { + if (m_num_threads == 1) { + // size_t min_k_omp = min_k; + // cvm::real min_norm2_omp = m_compression_threshold2; + for (size_t nk = 0; nk < m_nlist_index.size(); ++nk) { + const size_t k = m_nlist_index[nk]; + if (k == giver_k) continue; + double norm2 = 0; + for (size_t i = 0; i < num_variables(); ++i) { + norm2 += variables(i)->dist2(giver_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + if (norm2 >= min_norm2) break; + } + if (norm2 < min_norm2) { + min_norm2 = norm2; + min_k = k; + } + } + } else { +#if defined(_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + size_t min_k_omp = min_k; + cvm::real min_norm2_omp = m_compression_threshold2; + #pragma omp for nowait + for (int nk = 0; nk < static_cast(m_nlist_index.size()); ++nk) { + const size_t k = m_nlist_index[nk]; + if (k == giver_k) continue; + double norm2 = 0; + for (int i = 0; i < static_cast(num_variables()); ++i) { + norm2 += variables(i)->dist2(giver_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + if (norm2 >= min_norm2_omp) break; + } + if (norm2 < min_norm2_omp) { + min_norm2_omp = norm2; + min_k_omp = k; + } + } + #pragma omp critical + { + if (min_norm2_omp < min_norm2) { + min_norm2 = min_norm2_omp; + min_k = min_k_omp; + } + } + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + // NOTE: No existing reduction type for finding the minimum, so I have + // to use such a workaround. + std::vector min_k_smp(m_num_threads, min_k); + std::vector min_norm2_smp(m_num_threads, m_compression_threshold2); + auto worker = [&](int start, int end, void* unused) { + const int tid = cvm::proxy->smp_thread_id(); + for (int nk = start; nk <= end; ++nk) { + const size_t k = m_nlist_index[nk]; + if (k == giver_k) continue; + double norm2 = 0; + for (size_t j = 0; j < num_variables(); ++j) { + norm2 += variables(i)->dist2( giver_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + if (norm2 >= min_norm2_smp[tid]) break; + } + if (norm2 < min_norm2_smp[tid]) { + min_norm2_smp[tid] = norm2; + min_k_smp[tid] = k; + } + } + }; + const size_t numChunks = m_nlist_index.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, NULL, CKLOOP_NONE, NULL); + const auto it_min = std::min_element(min_norm2_smp.begin(), min_norm2_smp.end()); + min_norm2 = *it_min; + min_k = min_k_smp[std::distance(min_norm2_smp.begin(), it_min)]; +#else + cvm::error("OPES cannot run because this binary is not linked with a supported threading library.\n"); +#endif + } + } + if (num_parallel > 1) { + cvm::error("The Colvars OPES implementation does not support running OPES in parallel across nodes.\n"); + } + return min_k; +} + +std::string const colvarbias_opes::traj_file_name(const std::string& suffix) const { + return std::string(cvm::output_prefix()+ + ".colvars."+this->name+ + ( (comm != single_replica) ? + ("."+replica_id) : + ("") )+ + suffix); +} + +int colvarbias_opes::write_output_files() { + int error_code = COLVARS_OK; + thread_local static bool firsttime = true; + // Write the kernels + const std::string kernels_filename = traj_file_name(".kernels.dat"); + std::ostream& os_kernels = cvm::proxy->output_stream(kernels_filename, "kernels file"); + const std::ios_base::fmtflags format_kernels = os_kernels.flags(); + if (firsttime) { + os_kernels << "#! FIELDS time "; + for (size_t i = 0; i < num_variables(); ++i) { + os_kernels << variables(i)->name + " "; + } + for (size_t i = 0; i < num_variables(); ++i) { + os_kernels << "sigma_" + variables(i)->name + " "; + } + os_kernels << "height logweight\n"; + // Make sure the action name compatible with the script in https://github.com/invemichele/opes/blob/master/postprocessing/State_from_Kernels.py + if (m_explore) os_kernels << "#! SET action OPES_METAD_EXPLORE_kernels\n"; + else os_kernels << "#! SET action OPES_METAD_kernels\n"; + if (m_inf_biasfactor) { + os_kernels << "#! SET biasfactor " << "inf" << "\n"; + } else { + os_kernels << "#! SET biasfactor " << m_biasfactor << "\n"; + } + os_kernels << "#! SET epsilon " << m_epsilon << "\n"; + os_kernels << "#! SET kernel_cutoff " << m_cutoff << "\n"; + os_kernels << "#! SET compression_threshold " << m_compression_threshold << "\n"; + for (size_t i = 0; i < num_variables(); ++i) { + if (variables(i)->is_enabled(f_cv_periodic)) { + if (variables(i)->is_enabled(f_cv_lower_boundary)) { + os_kernels << "#! SET min_" + variables(i)->name + " " << variables(i)->lower_boundary.real_value << "\n"; + } + if (variables(i)->is_enabled(f_cv_upper_boundary)) { + os_kernels << "#! SET max_" + variables(i)->name + " " << variables(i)->upper_boundary.real_value << "\n"; + } + } + } + } + os_kernels << m_kernels_output.str(); + os_kernels.setf(format_kernels); + error_code |= cvm::proxy->flush_output_stream(kernels_filename); + m_kernels_output.str(""); + m_kernels_output.clear(); + + // Write the trajectory + const std::string traj_filename = traj_file_name(".misc.traj"); + std::ostream& os_traj = cvm::proxy->output_stream(traj_filename, "trajectory of various OPES properties"); + const std::ios_base::fmtflags format_traj = os_traj.flags(); + if (firsttime) { + os_traj << "#! FIELDS time "; + for (size_t i = 0; i < num_variables(); ++i) { + os_traj << variables(i)->name + " "; + } + os_traj << this->name + ".bias "; + os_traj << this->name + ".rct "; + if (!m_no_zed) os_traj << this->name + ".zed "; + os_traj << this->name + ".neff "; + if (m_calc_work) if (!m_no_zed) os_traj << this->name + ".work "; + os_traj << this->name + ".nker "; + if (m_nlist) os_traj << this->name + ".nlker "; + if (m_nlist) os_traj << this->name + ".nlsteps "; + os_traj << "\n"; + for (size_t i = 0; i < num_variables(); ++i) { + if (variables(i)->is_enabled(f_cv_lower_boundary)) { + os_traj << "#! SET min_" + variables(i)->name + " " << variables(i)->lower_boundary.real_value << "\n"; + } + if (variables(i)->is_enabled(f_cv_upper_boundary)) { + os_traj << "#! SET max_" + variables(i)->name + " " << variables(i)->upper_boundary.real_value << "\n"; + } + } + } + os_traj << m_traj_oss.str(); + os_traj.setf(format_traj); + error_code |= cvm::proxy->flush_output_stream(traj_filename); + m_traj_oss.str(""); + m_traj_oss.clear(); + if (firsttime) firsttime = false; + if (m_pmf_grid_on) { + error_code |= computePMF(); + const std::string pmf_filename = traj_file_name(".pmf"); + error_code |= writePMF(m_pmf_grid, pmf_filename, false); + if (comm == multiple_replicas && m_pmf_shared) { + if (cvm::proxy->replica_index() == 0) { + const std::string global_pmf_filename = traj_file_name(".global.pmf"); + error_code |= writePMF(m_global_pmf_grid, global_pmf_filename, false); + } + } + if (m_pmf_hist_freq > 0 && cvm::step_absolute() % m_pmf_hist_freq == 0) { + const std::string pmf_hist_filename = traj_file_name(".hist.pmf"); + error_code |= writePMF(m_pmf_grid, pmf_hist_filename, true); + if (comm == multiple_replicas && m_pmf_shared) { + if (cvm::proxy->replica_index() == 0) { + const std::string global_hist_pmf_filename = traj_file_name(".global.hist.pmf"); + error_code |= writePMF(m_global_pmf_grid, global_hist_pmf_filename, true); + } + } + } + } + // To prevent the case that one replica exits earlier and then destroys all streams + if (comm == multiple_replicas) cvm::proxy->replica_comm_barrier(); + return error_code; +} + +void hist_to_pmf(const cvm::real kbt, const colvar_grid_scalar *hist, std::unique_ptr& pmf) { + // Get the sum of probabilities of all grids + cvm::real norm_factor = 0; + cvm::real max_prob = 0; + auto& prob_data = hist->data; + for (auto it = prob_data.begin(); it != prob_data.end(); ++it) { + norm_factor += (*it); + if ((*it) > max_prob) max_prob = (*it); + } + if (norm_factor > 0) { + const cvm::real min_pmf = (max_prob > 0) ? -1.0 * kbt * cvm::logn(max_prob / norm_factor) : 0; + auto& pmf_data = pmf->data; + for (size_t i = 0; i < pmf_data.size(); ++i) { + if (prob_data[i] > 0) { + pmf_data[i] = -1.0 * kbt * cvm::logn(prob_data[i] / norm_factor) - min_pmf; + } + } + auto max_pmf = *std::max_element(pmf_data.begin(), pmf_data.end()); + for (size_t i = 0; i < pmf_data.size(); ++i) { + if (!(prob_data[i] > 0)) { + pmf_data[i] = max_pmf; + } + } + } +} + +int colvarbias_opes::computePMF() { + // Multiple replica: collect all samples from other replicas + if (comm == multiple_replicas && m_pmf_shared) { + const size_t samples_n = m_reweight_grid->raw_data_num(); + const int msg_size = samples_n * sizeof(cvm::real); + std::vector buffer; + if (cvm::main()->proxy->replica_index() == 0) { + buffer.resize(samples_n * (cvm::proxy->num_replicas() - 1)); + for (int p = 1; p < cvm::proxy->num_replicas(); p++) { + const size_t start_pos = (p - 1) * samples_n; + if (cvm::proxy->replica_comm_recv((char*)&(buffer[start_pos]), msg_size, p) != msg_size) { + return cvm::error("Error getting shared OPES reweighting histogram from replica " + cvm::to_str(p)); + } + } + } else { + if (cvm::proxy->replica_comm_send((char*)(&(m_reweight_grid->data[0])), msg_size, 0) != msg_size) { + return cvm::error("Error sending shared OPES reweighting histogram from replica " + cvm::to_str(cvm::main()->proxy->replica_index())); + } + } + cvm::proxy->replica_comm_barrier(); + // Broadcast m_reweight_grid to all replicas + auto& global_data = m_global_reweight_grid->data; + if (cvm::main()->proxy->replica_index() == 0) { + global_data = m_reweight_grid->data; + // Sum the samples on PE 0 + for (int p = 1; p < cvm::proxy->num_replicas(); p++) { + const size_t start_pos = (p - 1) * samples_n; + for (size_t i = 0 ; i < samples_n; ++i) { + global_data[i] += buffer[start_pos+i]; + } + } + } + } + // Get the sum of probabilities of all grids + hist_to_pmf(m_kbt, m_reweight_grid.get(), m_pmf_grid); + if (comm == multiple_replicas && m_pmf_shared) { + if (cvm::main()->proxy->replica_index() == 0) { + hist_to_pmf(m_kbt, m_global_reweight_grid.get(), m_global_pmf_grid); + } + } + if (comm == multiple_replicas) { + cvm::proxy->replica_comm_barrier(); + } + return COLVARS_OK; +} + +int colvarbias_opes::writePMF(const std::unique_ptr& pmf_grid, const std::string &filename, bool keep_open) { + std::ostream& os = cvm::proxy->output_stream(filename, "output stream of " + filename); + if (!os) { + return COLVARS_FILE_ERROR; + } + pmf_grid->write_multicol(os); + if (!keep_open) { + cvm::proxy->close_output_stream(filename); + } else { + cvm::proxy->flush_output_stream(filename); + } + return COLVARS_OK; +} + +void colvarbias_opes::writeTrajBuffer() { + if (m_traj_output_frequency > 0 && cvm::step_absolute() % m_traj_output_frequency == 0) { + m_traj_oss << std::right; + m_traj_oss << std::scientific << " " << std::setw(cvm::cv_width) << std::setprecision(cvm::cv_prec) << (cvm::step_absolute() * cvm::dt()) * 1e-3; + for (size_t i = 0; i < num_variables(); ++i) { + m_traj_oss << std::scientific << " " << std::setw(cvm::cv_width) << std::setprecision(cvm::cv_prec) << variables(i)->value().real_value; + } + m_traj_oss << std::scientific << " " << std::setw(cvm::cv_width) << std::setprecision(cvm::cv_prec) << bias_energy; + m_traj_oss << std::scientific << " " << std::setw(cvm::cv_width) << std::setprecision(cvm::cv_prec) << m_traj_line.rct; + if (!m_no_zed) m_traj_oss << std::scientific << " " << std::setw(cvm::cv_width) << std::setprecision(cvm::cv_prec) << m_traj_line.zed; + m_traj_oss << std::scientific << " " << std::setw(cvm::cv_width) << std::setprecision(cvm::cv_prec) << m_traj_line.neff; + if (m_calc_work) m_traj_oss << std::scientific << " " << std::setw(cvm::cv_width) << std::setprecision(cvm::cv_prec) << m_traj_line.work; + m_traj_oss << " " << m_traj_line.nker; + if (m_nlist) m_traj_oss << " " << m_traj_line.nlker; + if (m_nlist) m_traj_oss << " " << m_traj_line.nlsteps; + m_traj_oss << "\n"; + } +} + +void colvarbias_opes::updateNlist(const std::vector& center) { + if (m_kernels.empty()) return; + m_nlist_center = center; + m_nlist_index.clear(); + if (m_num_threads == 1 || m_kernels.size() < 2 * m_num_threads) { + for (size_t k = 0; k < m_kernels.size(); ++k) { + cvm::real norm2_k = 0; + for (size_t i = 0; i < num_variables(); ++i) { + norm2_k += variables(i)->dist2(m_nlist_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + } + if (norm2_k <= m_nlist_param[0] * m_cutoff2) { + m_nlist_index.push_back(k); + } + } + } else { +#if defined (_OPENMP) + #pragma omp parallel num_threads(m_num_threads) + { + std::vector private_nlist_index; + #pragma omp for nowait + for (int k = 0; k < static_cast(m_kernels.size()); ++k) { + cvm::real norm2_k = 0; + for (int i = 0; i < static_cast(num_variables()); ++i) { + norm2_k += variables(i)->dist2(m_nlist_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + } + if (norm2_k <= m_nlist_param[0] * m_cutoff2) { + private_nlist_index.push_back(static_cast(k)); + } + } + #pragma omp critical + m_nlist_index.insert(m_nlist_index.end(), private_nlist_index.begin(), private_nlist_index.end()); + } +#elif defined(CMK_SMP) && defined(USE_CKLOOP) + std::vector> private_nlist_index(m_num_threads); + auto worker = [&](int start, int end, void* unused){ + const int tid = cvm::proxy->smp_thread_id(); + for (int k = start; k <= end; ++k) { + cvm::real norm2_k = 0; + for (size_t i = 0; i < num_variables(); ++i) { + norm2_k += variables(i)->dist2(m_nlist_center[i], m_kernels[k].m_center[i]) / (m_kernels[k].m_sigma[i] * m_kernels[k].m_sigma[i]); + } + if (norm2_k <= m_nlist_param[0] * m_cutoff2) { + private_nlist_index[tid].push_back(k); + } + } + }; + const size_t numChunks = m_kernels.size(); + const size_t lowerRange = 0; + const size_t upperRange = numChunks - 1; + CkLoop_Parallelize( + numChunks, lowerRange, upperRange, + worker, NULL, CKLOOP_NONE, NULL); + for (size_t j = 0; j < m_num_threads; ++j) { + m_nlist_index.insert(m_nlist_index.end(), private_nlist_index[i].begin(), private_nlist_index.end()); + } +#else + cvm::error("OPES cannot run because this binary is not linked with a supported threading library.\n"); +#endif + if (m_recursive_merge) { + std::sort(m_nlist_index.begin(), m_nlist_index.end()); + } + } + std::vector dev2(num_variables(), 0); + for (size_t k = 0; k < m_nlist_index.size(); ++k) { + for (size_t i = 0; i < num_variables(); ++i) { + dev2[i] += variables(i)->dist2(m_nlist_center[i], m_kernels[m_nlist_index[k]].m_center[i]); + } + } + for (size_t i = 0; i < num_variables(); ++i) { + if (m_nlist_index.empty()) { + m_nlist_dev2[i] = m_kernels.back().m_sigma[i] * m_kernels.back().m_sigma[i]; + } else { + m_nlist_dev2[i] = dev2[i] / m_nlist_index.size(); + } + } + m_traj_line.nlker = m_nlist_index.size(); + m_traj_line.nlsteps = m_nlist_steps; + m_nlist_steps = 0; + m_nlist_update = false; +} diff --git a/lib/colvars/colvarbias_opes.h b/lib/colvars/colvarbias_opes.h new file mode 100644 index 0000000000..0c52ba2413 --- /dev/null +++ b/lib/colvars/colvarbias_opes.h @@ -0,0 +1,176 @@ +#ifndef COLVARBIAS_OPES_H +#define COLVARBIAS_OPES_H + +// This code is mainly adapted from the PLUMED opes module, which uses the +// LGPLv3 license as shown below: +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Copyright (c) 2020-2021 of Michele Invernizzi. + + This file is part of the OPES plumed module. + + The OPES plumed module is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + The OPES plumed module is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with plumed. If not, see . ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ + +#include "colvarbias.h" + +#include +#include + +// OPES_METAD implementation: swiped from OPESmetad.cpp of PLUMED +class colvarbias_opes: public colvarbias { +public: + /// The Gaussian kernel data structure + struct kernel { + cvm::real m_height; + std::vector m_center; + std::vector m_sigma; + kernel() {} + kernel(cvm::real h, const std::vector& c, + const std::vector& s): + m_height(h), m_center(c), m_sigma(s) {} + }; + /// Communication between different replicas + enum Communication { + /// One replica (default) + single_replica, + /// Hills added concurrently by several replicas + multiple_replicas + }; + /// Constructor + colvarbias_opes(char const *key); + /// Initializer + int init(std::string const &conf) override; + /// Per-timestep update + int update() override; + /// Save the state to a text file for restarting + std::ostream &write_state_data(std::ostream &os) override; + /// Read the state from a text file for restarting + std::istream &read_state_data(std::istream &is) override; + /// Save the state to a binary file for restarting + cvm::memory_stream &write_state_data(cvm::memory_stream &os) override; + /// Read the state from a binary file for restarting + cvm::memory_stream &read_state_data(cvm::memory_stream &is) override; + /// Write to files at restart steps + int write_output_files() override; +private: + int update_opes(); + int calculate_opes(); + void save_state(); + cvm::real getProbAndDerivatives(const std::vector& cv, std::vector& der_prob) const; + cvm::real evaluateKernel(const kernel& G, const std::vector& x) const; + cvm::real evaluateKernel(const kernel& G, const std::vector& x, std::vector& accumulated_derivative, std::vector& dist) const; + void addKernel(const double height, const std::vector& center, const std::vector& sigma, const double logweight); + void addKernel(const double height, const std::vector& center, const std::vector& sigma); + size_t getMergeableKernel(const std::vector& giver_center, const size_t giver_k) const; + void mergeKernels(kernel& k1, const kernel& k2) const; + void updateNlist(const std::vector& center); + struct traj_line { + double rct; + double zed; + double neff; + double work; + size_t nker; + size_t nlker; + size_t nlsteps; + }; + void writeTrajBuffer(); + void showInfo() const; + template OST &write_state_data_template_(OST &os) const; + template IST &read_state_data_template_(IST &os); + std::string const traj_file_name(const std::string& suffix) const; + int collectSampleToPMFGrid(); + int computePMF(); + int writePMF(const std::unique_ptr& pmf_grid, const std::string &filename, bool keep_open); +private: + cvm::real m_kbt; + cvm::real m_barrier; + cvm::real m_biasfactor; + cvm::real m_bias_prefactor; + cvm::real m_temperature; + cvm::step_number m_pace; + cvm::step_number m_adaptive_sigma_stride; + cvm::step_number m_adaptive_counter; + unsigned long long m_counter; + cvm::real m_compression_threshold; + cvm::real m_compression_threshold2; + bool m_adaptive_sigma; + bool m_fixed_sigma; + bool m_no_zed; + // bool m_restart; + bool m_nlist; + bool m_recursive_merge; + std::vector m_nlist_param; + std::vector m_sigma0; + std::vector m_sigma_min; + cvm::real m_epsilon; + cvm::real m_sum_weights; + cvm::real m_sum_weights2; + cvm::real m_cutoff; + cvm::real m_cutoff2; + cvm::real m_zed; + cvm::real m_old_kdenorm; + cvm::real m_kdenorm; + cvm::real m_val_at_cutoff; + cvm::real m_rct; + cvm::real m_neff; + std::vector m_kernels; + std::vector m_delta_kernels; + std::vector m_av_cv; + std::vector m_av_M2; + std::ostringstream m_kernels_output; + std::vector m_nlist_center; + std::vector m_nlist_index; + std::vector m_nlist_dev2; + size_t m_nlist_steps; + bool m_nlist_update; + bool m_nlist_pace_reset; + size_t m_nker; + bool m_calc_work; + cvm::real m_work; + /// Communication between different replicas + Communication comm; + /// \brief Identifier for this replica + std::string replica_id; + size_t m_num_walkers; + size_t shared_freq; + size_t m_num_threads; + size_t m_nlker; + // size_t m_state_stride; + // std::unordered_map m_kernel_output_components; + std::string m_kernels_output_headers; + cvm::step_number m_traj_output_frequency; + traj_line m_traj_line; + std::ostringstream m_traj_oss; + bool m_is_first_step; + std::vector m_cv; + // For saving states + decltype(m_zed) m_saved_zed; + decltype(m_sum_weights) m_saved_sum_weights; + decltype(m_sum_weights2) m_saved_sum_weights2; + decltype(m_kernels) m_saved_kernels; + // PMF grid from reweighting + bool m_pmf_grid_on; + std::vector m_pmf_cvs; + std::string grid_conf; + std::shared_ptr m_reweight_grid; + std::unique_ptr m_pmf_grid; + cvm::step_number m_pmf_hist_freq; + bool m_pmf_shared; // shared PMF among replicas + std::unique_ptr m_global_reweight_grid; + std::unique_ptr m_global_pmf_grid; + bool m_explore; + bool m_inf_biasfactor; +}; + +#endif // COLVARBIAS_OPES_H diff --git a/lib/colvars/colvarcomp.cpp b/lib/colvars/colvarcomp.cpp index e6729f43a7..9a056f7dd3 100644 --- a/lib/colvars/colvarcomp.cpp +++ b/lib/colvars/colvarcomp.cpp @@ -261,7 +261,6 @@ int colvar::cvc::init_dependencies() { require_feature_children(f_cvc_explicit_gradient, f_ag_explicit_gradient); init_feature(f_cvc_inv_gradient, "inverse_gradient", f_type_dynamic); - require_feature_self(f_cvc_inv_gradient, f_cvc_gradient); init_feature(f_cvc_debug_gradient, "debug_gradient", f_type_user); require_feature_self(f_cvc_debug_gradient, f_cvc_gradient); @@ -525,7 +524,7 @@ void colvar::cvc::calc_force_invgrads() void colvar::cvc::calc_Jacobian_derivative() { - cvm::error("Error: calculation of inverse gradients is not implemented " + cvm::error("Error: calculation of Jacobian derivatives is not implemented " "for colvar components of type \""+function_type()+"\".\n", COLVARS_NOT_IMPLEMENTED); } @@ -533,8 +532,10 @@ void colvar::cvc::calc_Jacobian_derivative() void colvar::cvc::calc_fit_gradients() { - for (size_t ig = 0; ig < atom_groups.size(); ig++) { - atom_groups[ig]->calc_fit_gradients(); + if (is_enabled(f_cvc_explicit_gradient)) { + for (size_t ig = 0; ig < atom_groups.size(); ig++) { + atom_groups[ig]->calc_fit_gradients(); + } } } diff --git a/lib/colvars/colvarcomp.h b/lib/colvars/colvarcomp.h index 334fdc1f6e..53755576c2 100644 --- a/lib/colvars/colvarcomp.h +++ b/lib/colvars/colvarcomp.h @@ -233,8 +233,14 @@ public: /// Forcibly set value of CVC - useful for driving an external coordinate, /// eg. lambda dynamics - inline void set_value(colvarvalue const &new_value) { + inline void set_value(colvarvalue const &new_value, bool now=false) { x = new_value; + // Cache value to be communicated to back-end between time steps + cvm::proxy->set_alch_lambda(x.real_value); + if (now) { + // If requested (e.g. upon restarting), sync to back-end + cvm::proxy->send_alch_lambda(); + } } protected: @@ -1212,9 +1218,11 @@ protected: // No atom groups needed public: alch_lambda(); + int init_alchemy(int time_step_factor); virtual ~alch_lambda() {} virtual void calc_value(); - virtual void calc_gradients(); + virtual void calc_force_invgrads(); + virtual void calc_Jacobian_derivative(); virtual void apply_force(colvarvalue const &force); }; diff --git a/lib/colvars/colvarcomp_alchlambda.cpp b/lib/colvars/colvarcomp_alchlambda.cpp index a175ea43e8..29168d87ce 100644 --- a/lib/colvars/colvarcomp_alchlambda.cpp +++ b/lib/colvars/colvarcomp_alchlambda.cpp @@ -20,22 +20,46 @@ colvar::alch_lambda::alch_lambda() { set_function_type("alchLambda"); - disable(f_cvc_explicit_gradient); - disable(f_cvc_gradient); + provide(f_cvc_explicit_gradient, false); + provide(f_cvc_gradient, false); // Cannot apply forces on this CVC + provide(f_cvc_collect_atom_ids, false); + + provide(f_cvc_inv_gradient); // Projected force is TI derivative + provide(f_cvc_Jacobian); // Zero x.type(colvarvalue::type_scalar); - // Query initial value from back-end + + // Query initial value from back-end; will be overwritten if restarting from a state file cvm::proxy->get_alch_lambda(&x.real_value); } +int colvar::alch_lambda::init_alchemy(int factor) +{ + // We need calculation every time step + // default in Tinker-HP and NAMD2, must be enforced in NAMD3 + // Also checks back-end settings, ie. that alchemy is enabled + // (in NAMD3: alchType TI, computeEnergies at the right frequency) + + // Forbid MTS until fully implemented + if (factor != 1) { + return cvm::error("Error: timeStepFactor > 1 is not yet supported for alchemical variables."); + } + cvm::proxy->request_alch_energy_freq(factor); + + return COLVARS_OK; +} + + void colvar::alch_lambda::calc_value() { - // Special workflow: - // at the beginning of the timestep we get a force instead of calculating the value + // By default, follow external parameter + // This might get overwritten by driving extended dynamics + // (in apply_force() below) + cvm::proxy->get_alch_lambda(&x.real_value); cvm::proxy->get_dE_dlambda(&ft.real_value); - ft.real_value *= -1.0; // Energy derivative to force + ft.real_value *= -1.0; // Convert energy derivative to force // Include any force due to bias on Flambda ft.real_value += cvm::proxy->indirect_lambda_biasing_force; @@ -43,19 +67,24 @@ void colvar::alch_lambda::calc_value() } -void colvar::alch_lambda::calc_gradients() +void colvar::alch_lambda::calc_force_invgrads() { + // All the work is done in calc_value() +} + + +void colvar::alch_lambda::calc_Jacobian_derivative() +{ + jd = 0.0; } void colvar::alch_lambda::apply_force(colvarvalue const & /* force */) { - // new value will be cached and sent at end of timestep - cvm::proxy->set_alch_lambda(x.real_value); + // Forces, if any, are applied in colvar::update_extended_Lagrangian() } - colvar::alch_Flambda::alch_Flambda() { set_function_type("alch_Flambda"); diff --git a/lib/colvars/colvarcomp_angles.cpp b/lib/colvars/colvarcomp_angles.cpp index 56894e9f5c..0e7aed65ed 100644 --- a/lib/colvars/colvarcomp_angles.cpp +++ b/lib/colvars/colvarcomp_angles.cpp @@ -267,74 +267,22 @@ void colvar::dihedral::calc_value() void colvar::dihedral::calc_gradients() { - cvm::rvector A = cvm::rvector::outer(r12, r23); - cvm::real rA = A.norm(); - cvm::rvector B = cvm::rvector::outer(r23, r34); - cvm::real rB = B.norm(); - cvm::rvector C = cvm::rvector::outer(r23, A); - cvm::real rC = C.norm(); + // Eqs. (27i) ~ (27l) from https://doi.org/10.1002/(SICI)1096-987X(19960715)17:9<1132::AID-JCC5>3.0.CO;2-T. - cvm::real const cos_phi = (A*B)/(rA*rB); - cvm::real const sin_phi = (C*B)/(rC*rB); + const cvm::rvector A = cvm::rvector::outer(r12, r23); + const cvm::rvector B = cvm::rvector::outer(r23, r34); + const cvm::real nG = r23.norm(); + const cvm::real A2 = A.norm2(); + const cvm::real B2 = B.norm2(); - cvm::rvector f1, f2, f3; - - rB = 1.0/rB; - B *= rB; - - if (cvm::fabs(sin_phi) > 0.1) { - rA = 1.0/rA; - A *= rA; - cvm::rvector const dcosdA = rA*(cos_phi*A-B); - cvm::rvector const dcosdB = rB*(cos_phi*B-A); - // rA = 1.0; - - cvm::real const K = (1.0/sin_phi) * (180.0/PI); - - f1 = K * cvm::rvector::outer(r23, dcosdA); - f3 = K * cvm::rvector::outer(dcosdB, r23); - f2 = K * (cvm::rvector::outer(dcosdA, r12) - + cvm::rvector::outer(r34, dcosdB)); - } - else { - rC = 1.0/rC; - C *= rC; - cvm::rvector const dsindC = rC*(sin_phi*C-B); - cvm::rvector const dsindB = rB*(sin_phi*B-C); - // rC = 1.0; - - cvm::real const K = (-1.0/cos_phi) * (180.0/PI); - - f1.x = K*((r23.y*r23.y + r23.z*r23.z)*dsindC.x - - r23.x*r23.y*dsindC.y - - r23.x*r23.z*dsindC.z); - f1.y = K*((r23.z*r23.z + r23.x*r23.x)*dsindC.y - - r23.y*r23.z*dsindC.z - - r23.y*r23.x*dsindC.x); - f1.z = K*((r23.x*r23.x + r23.y*r23.y)*dsindC.z - - r23.z*r23.x*dsindC.x - - r23.z*r23.y*dsindC.y); - - f3 = cvm::rvector::outer(dsindB, r23); - f3 *= K; - - f2.x = K*(-(r23.y*r12.y + r23.z*r12.z)*dsindC.x - +(2.0*r23.x*r12.y - r12.x*r23.y)*dsindC.y - +(2.0*r23.x*r12.z - r12.x*r23.z)*dsindC.z - +dsindB.z*r34.y - dsindB.y*r34.z); - f2.y = K*(-(r23.z*r12.z + r23.x*r12.x)*dsindC.y - +(2.0*r23.y*r12.z - r12.y*r23.z)*dsindC.z - +(2.0*r23.y*r12.x - r12.y*r23.x)*dsindC.x - +dsindB.x*r34.z - dsindB.z*r34.x); - f2.z = K*(-(r23.x*r12.x + r23.y*r12.y)*dsindC.z - +(2.0*r23.z*r12.x - r12.z*r23.x)*dsindC.x - +(2.0*r23.z*r12.y - r12.z*r23.y)*dsindC.y - +dsindB.y*r34.x - dsindB.x*r34.y); - } + const cvm::real K = 180.0/PI; + const cvm::rvector f1 = K * nG / A2 * A; + const cvm::rvector f2 = K * ((r12 * r23 / (A2 * nG)) * A + (r34 * r23 / (B2 * nG)) * B); + const cvm::rvector f3 = K * nG / B2 * B; group1->set_weighted_gradient(-f1); - group2->set_weighted_gradient(-f2 + f1); - group3->set_weighted_gradient(-f3 + f2); + group2->set_weighted_gradient( f2 + f1); + group3->set_weighted_gradient(-f3 - f2); group4->set_weighted_gradient(f3); } diff --git a/lib/colvars/colvarcomp_distances.cpp b/lib/colvars/colvarcomp_distances.cpp index 319190c385..6de68264c3 100644 --- a/lib/colvars/colvarcomp_distances.cpp +++ b/lib/colvars/colvarcomp_distances.cpp @@ -384,32 +384,30 @@ void colvar::distance_dir::apply_force(colvarvalue const &force) cvm::real const iprod = force.rvector_value * x.rvector_value; cvm::rvector const force_tang = force.rvector_value - iprod * x.rvector_value; - if (!group1->noforce) - group1->apply_force(-1.0 * force_tang); - - if (!group2->noforce) - group2->apply_force( force_tang); + if (!group1->noforce) { + group1->apply_force(-1.0 / dist_v.norm() * force_tang); + } + if (!group2->noforce) { + group2->apply_force( 1.0 / dist_v.norm() * force_tang); + } } -cvm::real colvar::distance_dir::dist2(colvarvalue const &x1, - colvarvalue const &x2) const +cvm::real colvar::distance_dir::dist2(colvarvalue const &x1, colvarvalue const &x2) const { - return (x1.rvector_value - x2.rvector_value).norm2(); + return x1.dist2(x2); } -colvarvalue colvar::distance_dir::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const +colvarvalue colvar::distance_dir::dist2_lgrad(colvarvalue const &x1, colvarvalue const &x2) const { - return colvarvalue((x1.rvector_value - x2.rvector_value), colvarvalue::type_unit3vectorderiv); + return x1.dist2_grad(x2); } -colvarvalue colvar::distance_dir::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const +colvarvalue colvar::distance_dir::dist2_rgrad(colvarvalue const &x1, colvarvalue const &x2) const { - return colvarvalue((x2.rvector_value - x1.rvector_value), colvarvalue::type_unit3vectorderiv); + return x2.dist2_grad(x1); } @@ -1005,7 +1003,7 @@ void colvar::rmsd::calc_Jacobian_derivative() for (size_t ia = 0; ia < atoms->size(); ia++) { // Gradient of optimal quaternion wrt current Cartesian position - atoms->rot_deriv->calc_derivative_wrt_group1(ia, nullptr, &dq); + atoms->rot_deriv->calc_derivative_wrt_group1(ia, nullptr, &dq); g11 = 2.0 * (atoms->rot.q)[1]*dq[1]; g22 = 2.0 * (atoms->rot.q)[2]*dq[2]; @@ -1304,7 +1302,7 @@ void colvar::eigenvector::calc_Jacobian_derivative() // Gradient of optimal quaternion wrt current Cartesian position // trick: d(R^-1)/dx = d(R^t)/dx = (dR/dx)^t // we can just transpose the derivatives of the direct matrix - atoms->rot_deriv->calc_derivative_wrt_group1(ia, nullptr, &dq_1); + atoms->rot_deriv->calc_derivative_wrt_group1(ia, nullptr, &dq_1); g11 = 2.0 * quat0[1]*dq_1[1]; g22 = 2.0 * quat0[2]*dq_1[2]; @@ -1403,11 +1401,12 @@ void colvar::cartesian::apply_force(colvarvalue const &force) size_t ia, j; if (!atoms->noforce) { cvm::rvector f; + auto ag_force = atoms->get_group_force_object(); for (ia = 0; ia < atoms->size(); ia++) { for (j = 0; j < dim; j++) { f[axes[j]] = force.vector1d_value[dim*ia + j]; } - (*atoms)[ia].apply_force(f); + ag_force.add_atom_force(ia, f); } } } diff --git a/lib/colvars/colvarcomp_protein.cpp b/lib/colvars/colvarcomp_protein.cpp index f782095148..832005e2a7 100644 --- a/lib/colvars/colvarcomp_protein.cpp +++ b/lib/colvars/colvarcomp_protein.cpp @@ -28,34 +28,58 @@ colvar::alpha_angles::alpha_angles() int colvar::alpha_angles::init(std::string const &conf) { int error_code = cvc::init(conf); + if (error_code != COLVARS_OK) return error_code; std::string segment_id; - get_keyval(conf, "psfSegID", segment_id, std::string("MAIN")); - std::vector residues; - { - std::string residues_conf = ""; - key_lookup(conf, "residueRange", &residues_conf); + + bool b_use_index_groups = false; + cvm::atom_group group_CA, group_N, group_O; + + std::string residues_conf = ""; + std::string prefix; + + // residueRange is mandatory for the topology-based case + if (key_lookup(conf, "residueRange", &residues_conf)) { if (residues_conf.size()) { std::istringstream is(residues_conf); int initial, final; char dash; if ( (is >> initial) && (initial > 0) && - (is >> dash) && (dash == '-') && - (is >> final) && (final > 0) ) { + (is >> dash) && (dash == '-') && + (is >> final) && (final > 0) ) { for (int rnum = initial; rnum <= final; rnum++) { residues.push_back(rnum); } } } else { - error_code |= - cvm::error("Error: no residues defined in \"residueRange\".\n", COLVARS_INPUT_ERROR); + return cvm::error("Error: no residues defined in \"residueRange\".\n", COLVARS_INPUT_ERROR); } - } - if (residues.size() < 5) { - error_code |= cvm::error("Error: not enough residues defined in \"residueRange\".\n", - COLVARS_INPUT_ERROR); + if (residues.size() < 5) { + return cvm::error("Error: not enough residues defined in \"residueRange\".\n", COLVARS_INPUT_ERROR); + } + get_keyval(conf, "psfSegID", segment_id, std::string("MAIN")); + + } else { + b_use_index_groups = true; + get_keyval(conf, "prefix", prefix, "alpha_"); + + // Not all groups are mandatory, parse silently + group_CA.add_index_group(prefix + "CA", true); + group_N.add_index_group(prefix + "N", true); + group_O.add_index_group(prefix + "O", true); + int na = group_CA.size(); + int nn = group_N.size(); + int no = group_O.size(); + if ((nn != 0 || no != 0) && (nn != no)) { + return cvm::error("Error: If either is provided, atom groups " + prefix + "N and " + prefix + "O must have the same number of atoms.", + COLVARS_INPUT_ERROR); + } + if (nn != 0 && na != 0 && nn != na) { + return cvm::error("Error: If both are provided, atom groups " + prefix + "N and " + prefix + "CA must have the same number of atoms.", + COLVARS_INPUT_ERROR); + } } std::string const &sid = segment_id; @@ -64,8 +88,7 @@ int colvar::alpha_angles::init(std::string const &conf) get_keyval(conf, "hBondCoeff", hb_coeff, hb_coeff); if ((hb_coeff < 0.0) || (hb_coeff > 1.0)) { - error_code |= - cvm::error("Error: hBondCoeff must be defined between 0 and 1.\n", COLVARS_INPUT_ERROR); + return cvm::error("Error: hBondCoeff must be defined between 0 and 1.\n", COLVARS_INPUT_ERROR); } @@ -73,14 +96,29 @@ int colvar::alpha_angles::init(std::string const &conf) get_keyval(conf, "angleTol", theta_tol, theta_tol); if (hb_coeff < 1.0) { - - for (size_t i = 0; i < residues.size()-2; i++) { - theta.push_back(new colvar::angle(cvm::atom(r[i ], "CA", sid), - cvm::atom(r[i+1], "CA", sid), - cvm::atom(r[i+2], "CA", sid))); - register_atom_group(theta.back()->atom_groups[0]); - register_atom_group(theta.back()->atom_groups[1]); - register_atom_group(theta.back()->atom_groups[2]); + if (b_use_index_groups) { + if (group_CA.size() < 5) { + return cvm::error("Not enough atoms (" + cvm::to_str(group_CA.size()) + ") in index group \"" + prefix + "CA\"", + COLVARS_INPUT_ERROR); + } + for (size_t i = 0; i < group_CA.size()-2; i++) { + // Note: the angle constructor constructs copies of the atom objects + theta.push_back(new colvar::angle(group_CA[i], + group_CA[i+1], + group_CA[i+2])); + register_atom_group(theta.back()->atom_groups[0]); + register_atom_group(theta.back()->atom_groups[1]); + register_atom_group(theta.back()->atom_groups[2]); + } + } else { + for (size_t i = 0; i < residues.size()-2; i++) { + theta.push_back(new colvar::angle(cvm::atom(r[i ], "CA", sid), + cvm::atom(r[i+1], "CA", sid), + cvm::atom(r[i+2], "CA", sid))); + register_atom_group(theta.back()->atom_groups[0]); + register_atom_group(theta.back()->atom_groups[1]); + register_atom_group(theta.back()->atom_groups[2]); + } } } else { @@ -93,14 +131,27 @@ int colvar::alpha_angles::init(std::string const &conf) get_keyval(conf, "hBondExpDenom", ed, ed); if (hb_coeff > 0.0) { - - for (size_t i = 0; i < residues.size()-4; i++) { - hb.push_back(new colvar::h_bond(cvm::atom(r[i ], "O", sid), - cvm::atom(r[i+4], "N", sid), - r0, en, ed)); - register_atom_group(hb.back()->atom_groups[0]); + if (b_use_index_groups) { + if (group_N.size() < 5) { + return cvm::error("Not enough atoms (" + cvm::to_str(group_N.size()) + ") in index group \"" + prefix + "N\"", + COLVARS_INPUT_ERROR); + } + for (size_t i = 0; i < group_N.size()-4; i++) { + // Note: we need to call the atom copy constructor here because + // the h_bond constructor does not make copies of the provided atoms + hb.push_back(new colvar::h_bond(cvm::atom(group_O[i]), + cvm::atom(group_N[i+4]), + r0, en, ed)); + register_atom_group(hb.back()->atom_groups[0]); + } + } else { + for (size_t i = 0; i < residues.size()-4; i++) { + hb.push_back(new colvar::h_bond(cvm::atom(r[i ], "O", sid), + cvm::atom(r[i+4], "N", sid), + r0, en, ed)); + register_atom_group(hb.back()->atom_groups[0]); + } } - } else { cvm::log("The hBondCoeff specified will disable the hydrogen bond terms.\n"); } @@ -290,41 +341,62 @@ int colvar::dihedPC::init(std::string const &conf) if (cvm::debug()) cvm::log("Initializing dihedral PC object.\n"); + bool b_use_index_groups = false; std::string segment_id; - get_keyval(conf, "psfSegID", segment_id, std::string("MAIN")); - std::vector residues; - { - std::string residues_conf = ""; - key_lookup(conf, "residueRange", &residues_conf); + size_t n_residues; + std::string residues_conf = ""; + std::string prefix; + cvm::atom_group group_CA, group_N, group_C; + + // residueRange is mandatory for the topology-based case + if (key_lookup(conf, "residueRange", &residues_conf)) { if (residues_conf.size()) { std::istringstream is(residues_conf); int initial, final; char dash; if ( (is >> initial) && (initial > 0) && - (is >> dash) && (dash == '-') && - (is >> final) && (final > 0) ) { + (is >> dash) && (dash == '-') && + (is >> final) && (final > 0) ) { for (int rnum = initial; rnum <= final; rnum++) { residues.push_back(rnum); } } } else { - error_code |= - cvm::error("Error: no residues defined in \"residueRange\".\n", COLVARS_INPUT_ERROR); + return cvm::error("Error: no residues defined in \"residueRange\".\n", COLVARS_INPUT_ERROR); } - } + n_residues = residues.size(); + get_keyval(conf, "psfSegID", segment_id, std::string("MAIN")); - if (residues.size() < 2) { + } else { + + b_use_index_groups = true; + get_keyval(conf, "prefix", prefix, "dihed_"); + + // All three groups are required + group_CA.add_index_group(prefix + "CA"); + group_N.add_index_group(prefix + "N"); + group_C.add_index_group(prefix + "C"); + int na = group_CA.size(); + int nn = group_N.size(); + int nc = group_C.size(); + if ((nn != na || na != nc)) { + return cvm::error("Error: atom groups " + prefix + "N, " + prefix + "CA, and " + prefix + + "C must have the same number of atoms.", COLVARS_INPUT_ERROR); + } + n_residues = nn; + } + if (n_residues < 2) { error_code |= - cvm::error("Error: dihedralPC requires at least two residues.\n", COLVARS_INPUT_ERROR); + cvm::error("Error: dihedralPC requires at least two residues.\n", COLVARS_INPUT_ERROR); } std::string const &sid = segment_id; std::vector const &r = residues; std::string vecFileName; - int vecNumber; if (get_keyval(conf, "vectorFile", vecFileName, vecFileName)) { + int vecNumber; get_keyval(conf, "vectorNumber", vecNumber, 0); if (vecNumber < 1) { error_code |= @@ -339,9 +411,8 @@ int colvar::dihedPC::init(std::string const &conf) } // TODO: adapt to different formats by setting this flag - bool eigenvectors_as_columns = true; - - if (eigenvectors_as_columns) { + // bool eigenvectors_as_columns = true; + // if (eigenvectors_as_columns) { // Carma-style dPCA file std::string line; cvm::real c; @@ -352,9 +423,7 @@ int colvar::dihedPC::init(std::string const &conf) for (int i=0; i> c; coeffs.push_back(c); } - } -/* TODO Uncomment this when different formats are recognized - else { + /* } else { // Uncomment this when different formats are recognized // Eigenvectors as lines // Skip to the right line for (int i = 1; iatom_groups[0]); register_atom_group(theta.back()->atom_groups[1]); register_atom_group(theta.back()->atom_groups[2]); register_atom_group(theta.back()->atom_groups[3]); // Phi (next res) - theta.push_back(new colvar::dihedral(cvm::atom(r[i ], "C", sid), - cvm::atom(r[i+1], "N", sid), - cvm::atom(r[i+1], "CA", sid), - cvm::atom(r[i+1], "C", sid))); + if (b_use_index_groups) { + theta.push_back(new colvar::dihedral(group_C[i], + group_N[i+1], + group_CA[i+1], + group_C[i+1])); + } else { + theta.push_back(new colvar::dihedral(cvm::atom(r[i ], "C", sid), + cvm::atom(r[i+1], "N", sid), + cvm::atom(r[i+1], "CA", sid), + cvm::atom(r[i+1], "C", sid))); + } register_atom_group(theta.back()->atom_groups[0]); register_atom_group(theta.back()->atom_groups[1]); register_atom_group(theta.back()->atom_groups[2]); diff --git a/lib/colvars/colvarcomp_rotations.cpp b/lib/colvars/colvarcomp_rotations.cpp index a04ace851a..766a0870d1 100644 --- a/lib/colvars/colvarcomp_rotations.cpp +++ b/lib/colvars/colvarcomp_rotations.cpp @@ -137,11 +137,14 @@ void colvar::orientation::apply_force(colvarvalue const &force) if (!atoms->noforce) { rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq); cvm::vector1d dq0_2; + auto ag_force = atoms->get_group_force_object(); for (size_t ia = 0; ia < atoms->size(); ia++) { - rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); - for (size_t i = 0; i < 4; i++) { - (*atoms)[ia].apply_force(FQ[i] * dq0_2[i]); - } + rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); + const auto f_ia = FQ[0] * dq0_2[0] + + FQ[1] * dq0_2[1] + + FQ[2] * dq0_2[2] + + FQ[3] * dq0_2[3]; + ag_force.add_atom_force(ia, f_ia); } } } @@ -205,7 +208,7 @@ void colvar::orientation_angle::calc_gradients() rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq); cvm::vector1d dq0_2; for (size_t ia = 0; ia < atoms->size(); ia++) { - rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); + rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); (*atoms)[ia].grad = (dxdq0 * dq0_2[0]); } } @@ -265,7 +268,7 @@ void colvar::orientation_proj::calc_gradients() rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq); cvm::vector1d dq0_2; for (size_t ia = 0; ia < atoms->size(); ia++) { - rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); + rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); (*atoms)[ia].grad = (dxdq0 * dq0_2[0]); } } @@ -314,7 +317,7 @@ void colvar::tilt::calc_gradients() cvm::vector1d dq0_2; for (size_t ia = 0; ia < atoms->size(); ia++) { (*atoms)[ia].grad = cvm::rvector(0.0, 0.0, 0.0); - rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); + rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); for (size_t iq = 0; iq < 4; iq++) { (*atoms)[ia].grad += (dxdq[iq] * dq0_2[iq]); } @@ -351,7 +354,7 @@ void colvar::spin_angle::calc_gradients() cvm::vector1d dq0_2; for (size_t ia = 0; ia < atoms->size(); ia++) { (*atoms)[ia].grad = cvm::rvector(0.0, 0.0, 0.0); - rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); + rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); for (size_t iq = 0; iq < 4; iq++) { (*atoms)[ia].grad += (dxdq[iq] * dq0_2[iq]); } @@ -399,7 +402,7 @@ void colvar::euler_phi::calc_gradients() rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq); cvm::vector1d dq0_2; for (size_t ia = 0; ia < atoms->size(); ia++) { - rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); + rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); (*atoms)[ia].grad = (dxdq0 * dq0_2[0]) + (dxdq1 * dq0_2[1]) + (dxdq2 * dq0_2[2]) + @@ -448,7 +451,7 @@ void colvar::euler_psi::calc_gradients() rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq); cvm::vector1d dq0_2; for (size_t ia = 0; ia < atoms->size(); ia++) { - rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); + rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); (*atoms)[ia].grad = (dxdq0 * dq0_2[0]) + (dxdq1 * dq0_2[1]) + (dxdq2 * dq0_2[2]) + @@ -495,7 +498,7 @@ void colvar::euler_theta::calc_gradients() rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq); cvm::vector1d dq0_2; for (size_t ia = 0; ia < atoms->size(); ia++) { - rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); + rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2); (*atoms)[ia].grad = (dxdq0 * dq0_2[0]) + (dxdq1 * dq0_2[1]) + (dxdq2 * dq0_2[2]) + diff --git a/lib/colvars/colvarcomp_torchann.cpp b/lib/colvars/colvarcomp_torchann.cpp new file mode 100644 index 0000000000..7b83baf9b6 --- /dev/null +++ b/lib/colvars/colvarcomp_torchann.cpp @@ -0,0 +1,233 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + +#include "colvar.h" +#include "colvarcomp.h" +#include "colvarmodule.h" +#include "colvarparse.h" +#include "colvarvalue.h" + +#include "colvarcomp_torchann.h" + + +#ifdef COLVARS_TORCH + +colvar::torchANN::torchANN() +{ + set_function_type("torchANN"); + provide(f_cvc_periodic); +} + +colvar::torchANN::~torchANN() {} + + +int colvar::torchANN::init(std::string const &conf) { + + int error_code = linearCombination::init(conf); + + std::string model_file ; + get_keyval(conf, "modelFile", model_file, std::string("")); + try { + nn = torch::jit::load(model_file); + nn.to(torch::kCPU); + cvm::log("torch model loaded.") ; + } catch (const std::exception & e) { + return cvm::error("Error: couldn't load libtorch model (see below).\n" + cvm::to_str(e.what()), + COLVARS_INPUT_ERROR); + } + + auto const legacy_keyword = get_keyval(conf, "m_output_index", m_output_index, m_output_index); + if (legacy_keyword) { + cvm::log("Warning: m_output_index is a deprecated keyword, please use output_component instead.\n"); + } + get_keyval(conf, "output_component", m_output_index, m_output_index); + + get_keyval(conf, "doubleInputTensor", use_double_input, use_double_input); + //get_keyval(conf, "useGPU", use_gpu, false); + + cvc_indices.resize(cv.size(),0); + + size_t num_inputs = 0; + // compute total number of inputs of neural network + for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) + { + num_inputs += cv[i_cv]->value().size() ; + if (i_cv < cv.size() - 1) + cvc_indices[i_cv+1] = num_inputs; + } + cvm::log("Input dimension of model: " + cvm::to_str(num_inputs)); + + // initialize the input tensor + auto options = torch::TensorOptions().dtype(torch::kFloat32).requires_grad(true); + + /* + if (use_gpu) { + if (torch::cuda::is_available()) { + try { + nn.to(torch::kCUDA); + } catch(const std::exception & e) { + cvm::error("Failed to move model to GPU."); + use_gpu = false; + } + } else { + use_gpu = false; + cvm::log("GPU not available."); + } + } + + if (use_gpu) { + options = options.device(torch::kCUDA); + if (use_double_input) { + cvm::log("Data type reset to Float for GPU computation!"); + use_double_input = false; + } + } + */ + + if (use_double_input) { // set type to double + options = options.dtype(torch::kFloat64); + nn.to(torch::kFloat64); + cvm::log("Model's dtype: kFloat64."); + } else { + cvm::log("Model's dtype: kFloat32."); + } + + input_tensor = torch::zeros({1,(long int) num_inputs}, options); + + try { // test the model + std::vector inputs={input_tensor}; + nn_outputs = nn.forward(inputs).toTensor()[0][m_output_index]; + cvm::log("Evaluating model with zero tensor succeeded."); + } catch (const std::exception & e) { + error_code |= cvm::error("Error: evaluating model with zero tensor failed (see below).\n" + + cvm::to_str(e.what()), + COLVARS_INPUT_ERROR); + } + + return error_code; +} + + +void colvar::torchANN::calc_value() { + + for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) + cv[i_cv]->calc_value(); + + /* + if (use_gpu) + input_tensor = input_tensor.to(torch::kCPU); + */ + + // set input tensor with no_grad + { + torch::NoGradGuard no_grad; + size_t l = 0; + for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) { + const colvarvalue& current_cv_value = cv[i_cv]->value(); + if (current_cv_value.type() == colvarvalue::type_scalar) { + input_tensor[0][l++] = cv[i_cv]->sup_coeff * (cvm::pow(current_cv_value.real_value, cv[i_cv]->sup_np)); + } else { + for (size_t j_elem = 0; j_elem < current_cv_value.size(); ++j_elem) + input_tensor[0][l++] = cv[i_cv]->sup_coeff * current_cv_value[j_elem]; + } + } + } + + /* + if (use_gpu) + input_tensor = input_tensor.to(torch::kCUDA); + */ + + std::vector inputs={input_tensor}; + + // evaluate the value of function + nn_outputs = nn.forward(inputs).toTensor()[0][m_output_index]; + + input_grad = torch::autograd::grad({nn_outputs}, {input_tensor})[0][0]; + + /* + if (use_gpu) + input_grad = input_grad.to(torch::kCPU); + */ + + x = nn_outputs.item() ; + + this->wrap(x); + +} + +void colvar::torchANN::calc_gradients() { + for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) { + cv[i_cv]->calc_gradients(); + if (cv[i_cv]->is_enabled(f_cvc_explicit_gradient)) { + const cvm::real factor_polynomial = getPolynomialFactorOfCVGradient(i_cv); + // get the initial index of this cvc + size_t l = cvc_indices[i_cv]; + for (size_t j_elem = 0; j_elem < cv[i_cv]->value().size(); ++j_elem) { + // get derivative of neural network wrt its input + const cvm::real factor = input_grad[l+j_elem].item(); + for (size_t k_ag = 0 ; k_ag < cv[i_cv]->atom_groups.size(); ++k_ag) { + for (size_t l_atom = 0; l_atom < (cv[i_cv]->atom_groups)[k_ag]->size(); ++l_atom) { + (*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad = factor_polynomial * factor * (*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad; + } + } + } + } + } +} + +void colvar::torchANN::apply_force(colvarvalue const &force) { + + for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) { + // If this CV uses explicit gradients, then atomic gradients is already calculated + // We can apply the force to atom groups directly + if (cv[i_cv]->is_enabled(f_cvc_explicit_gradient)) { + for (size_t k_ag = 0 ; k_ag < cv[i_cv]->atom_groups.size(); ++k_ag) { + (cv[i_cv]->atom_groups)[k_ag]->apply_colvar_force(force.real_value); + } + } else { + const colvarvalue& current_cv_value = cv[i_cv]->value(); + colvarvalue cv_force(current_cv_value); + cv_force.reset(); + const cvm::real factor_polynomial = getPolynomialFactorOfCVGradient(i_cv); + // get the initial index of this cvc + size_t l = cvc_indices[i_cv]; + for (size_t j_elem = 0; j_elem < current_cv_value.size(); ++j_elem) { + cv_force[j_elem] = factor_polynomial * input_grad[l+j_elem].item() * force.real_value; + } + cv[i_cv]->apply_force(cv_force); + } + } +} + + +#else + +colvar::torchANN::torchANN() +{ + set_function_type("torchANN"); +} + +colvar::torchANN::~torchANN() {} + +int colvar::torchANN::init(std::string const &conf) { + + return cvm::error( + "torchANN requires the libtorch library, but it is not enabled during compilation.\n" + "Please refer to the Compilation Notes section of the Colvars manual for more " + "information.\n", + COLVARS_NOT_IMPLEMENTED); + +} + +void colvar::torchANN::calc_value() +{ +} + +#endif diff --git a/lib/colvars/colvarcomp_torchann.h b/lib/colvars/colvarcomp_torchann.h new file mode 100644 index 0000000000..ae241edbcc --- /dev/null +++ b/lib/colvars/colvarcomp_torchann.h @@ -0,0 +1,63 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. +// +#ifndef COLVARCOMP_TORCH_H +#define COLVARCOMP_TORCH_H + +// Declaration of torchann + +#include + +#include "colvar.h" +#include "colvarcomp.h" +#include "colvarmodule.h" + +#ifdef COLVARS_TORCH + +#include +#include + +class colvar::torchANN + : public colvar::linearCombination +{ +protected: + torch::jit::script::Module nn; + /// the index of nn output component + size_t m_output_index = 0; + bool use_double_input = false; + //bool use_gpu; + // 1d tensor, concatenation of values of sub-cvcs + torch::Tensor input_tensor; + torch::Tensor nn_outputs; + torch::Tensor input_grad; + // record the initial index of of sub-cvcs in input_tensor + std::vector cvc_indices; +public: + torchANN(); + virtual ~torchANN(); + virtual int init(std::string const &conf); + virtual void calc_value(); + virtual void calc_gradients(); + virtual void apply_force(colvarvalue const &force); +}; + +#else + +class colvar::torchANN + : public colvar::cvc +{ +public: + torchANN(); + virtual ~torchANN(); + virtual int init(std::string const &conf); + virtual void calc_value(); +}; +#endif // COLVARS_TORCH checking + +#endif diff --git a/lib/colvars/colvardeps.cpp b/lib/colvars/colvardeps.cpp index 46b7917569..3ba3209000 100644 --- a/lib/colvars/colvardeps.cpp +++ b/lib/colvars/colvardeps.cpp @@ -92,6 +92,8 @@ void colvardeps::restore_children_deps() { void colvardeps::provide(int feature_id, bool truefalse) { feature_states[feature_id].available = truefalse; + // Make sure that we don't leave this feature enabled + if (!truefalse) disable(feature_id); } @@ -123,8 +125,9 @@ bool colvardeps::get_keyval_feature(colvarparse *cvp, int colvardeps::enable(int feature_id, - bool dry_run /* default: false */, - bool toplevel /* default: true */) + bool dry_run /* default: false */, + bool toplevel /* default: true */, + bool error /*default: false */) { int res; size_t i, j; @@ -137,9 +140,12 @@ int colvardeps::enable(int feature_id, feature *f = features()[feature_id]; feature_state *fs = &feature_states[feature_id]; + // dry_run can be true because parent object is not active, yet we are displaying an error message + // then error is set to true + if (cvm::debug()) { cvm::log("DEPS: " + description + - (dry_run ? " testing " : " enabling ") + + (dry_run ? " testing " : " enabling ") + (error ? " [error] " : "") + "\"" + f->description +"\"\n"); } @@ -159,7 +165,7 @@ int colvardeps::enable(int feature_id, (is_dynamic(feature_id) ? "Dynamic" : "User-controlled"); if (!fs->available) { - if (!dry_run) { + if (!dry_run || error) { if (toplevel) { cvm::error("Error: " + feature_type_descr + " feature unavailable: \"" + f->description + "\" in " + description + ".\n"); @@ -172,7 +178,7 @@ int colvardeps::enable(int feature_id, } if (!toplevel && !is_dynamic(feature_id)) { - if (!dry_run) { + if (!dry_run || error) { cvm::log(feature_type_descr + " feature \"" + f->description + "\" cannot be enabled automatically in " + description + ".\n"); if (is_user(feature_id)) { @@ -189,7 +195,7 @@ int colvardeps::enable(int feature_id, if (cvm::debug()) cvm::log(f->description + " requires exclude " + g->description + "\n"); if (is_enabled(f->requires_exclude[i])) { - if (!dry_run) { + if (!dry_run || error) { cvm::log("Feature \"" + f->description + "\" is incompatible with \"" + g->description + "\" in " + description + ".\n"); if (toplevel) { @@ -204,10 +210,14 @@ int colvardeps::enable(int feature_id, for (i=0; irequires_self.size(); i++) { if (cvm::debug()) cvm::log(f->description + " requires self " + features()[f->requires_self[i]]->description + "\n"); - res = enable(f->requires_self[i], dry_run, false); + res = enable(f->requires_self[i], dry_run, false, error); if (res != COLVARS_OK) { - if (!dry_run) { - cvm::log("...required by \"" + f->description + "\" in " + description + "\n"); + if (!dry_run || error) { + if (toplevel) { + cvm::log("Cannot enable \"" + f->description + "\" in " + description + "\n"); + } else { + cvm::log("...required by \"" + f->description + "\" in " + description + "\n"); + } if (toplevel) { cvm::error("Error: Failed dependency in " + description + ".\n"); } @@ -225,11 +235,11 @@ int colvardeps::enable(int feature_id, int g = f->requires_alt[i][j]; if (cvm::debug()) cvm::log(f->description + " requires alt " + features()[g]->description + "\n"); - res = enable(g, true, false); // see if available + res = enable(g, true, false, error); // see if available if (res == COLVARS_OK) { ok = true; - if (!dry_run) { - enable(g, false, false); // Require again, for real + if (!dry_run || error) { + enable(g, false, false, error); // Require again, for real fs->alternate_refs.push_back(g); // We remember we enabled this // so we can free it if this feature gets disabled } @@ -245,7 +255,7 @@ int colvardeps::enable(int feature_id, for (j=0; jrequires_alt[i].size(); j++) { int g = f->requires_alt[i][j]; cvm::log(cvm::to_str(j+1) + ". " + features()[g]->description + "\n"); - enable(g, false, false); // Just for printing error output + enable(g, false, false, true); // Just for printing error output } cvm::decrease_depth(); cvm::log("-----------------------------------------\n"); @@ -264,10 +274,14 @@ int colvardeps::enable(int feature_id, for (i=0; irequires_children.size(); i++) { int g = f->requires_children[i]; for (j=0; jenable(g, dry_run || !is_enabled(), false); + res = children[j]->enable(g, dry_run || !is_enabled(), false, error); if (res != COLVARS_OK) { - if (!dry_run) { - cvm::log("...required by \"" + f->description + "\" in " + description + "\n"); + if (!dry_run || error) { + if (toplevel) { + cvm::log("Cannot enable \"" + f->description + "\" in " + description + "\n"); + } else { + cvm::log("...required by \"" + f->description + "\" in " + description + "\n"); + } if (toplevel) { cvm::error("Error: Failed dependency in " + description + ".\n"); } diff --git a/lib/colvars/colvardeps.h b/lib/colvars/colvardeps.h index 1bd304b545..92e7a88326 100644 --- a/lib/colvars/colvardeps.h +++ b/lib/colvars/colvardeps.h @@ -198,7 +198,9 @@ public: /// \param toplevel False if this is called as part of a chain of dependency resolution. /// This is used to diagnose failed dependencies by displaying the full stack: /// only the toplevel dependency will throw a fatal error. - int enable(int f, bool dry_run = false, bool toplevel = true); + /// \param error Recursively enable, printing error messages along the way + /// Necessary when propagating errors across alternate dependencies + int enable(int f, bool dry_run = false, bool toplevel = true, bool error = false); /// Disable a feature, decrease the reference count of its dependencies /// and recursively disable them as applicable @@ -255,6 +257,8 @@ public: f_cvb_scale_biasing_force, /// \brief whether this bias is applied to one or more ext-Lagrangian colvars f_cvb_extended, + /// Process this bias's data in parallel over multiple CPU threads + f_cvb_smp, f_cvb_ntot }; @@ -263,8 +267,11 @@ public: f_cv_active, /// \brief Colvar is awake (active on its own accord) this timestep f_cv_awake, - /// \brief Gradients are calculated and temporarily stored, so - /// that external forces can be applied + /// \brief External force can be applied, either to atoms or to an + /// extended DOF + f_cv_apply_force, + /// \brief Gradients are calculated and temporarily stored, + /// so that external forces can be propagated to atoms f_cv_gradient, /// \brief Collect atomic gradient data from all cvcs into vector /// atomic_gradient @@ -277,7 +284,10 @@ public: /// forces on the inverse gradient f_cv_total_force, /// \brief Calculate total force from atomic forces + /// or get it from the back-end for an external parameter f_cv_total_force_calc, + /// \brief Total force is that of current time step + f_cv_total_force_current_step, /// \brief Subtract the applied force from the total force f_cv_subtract_applied_force, /// \brief Estimate Jacobian derivative @@ -289,8 +299,10 @@ public: /// center with fictitious mass; bias forces will be applied to /// the center f_cv_extended_Lagrangian, - /// \brief An extended variable that sets an external variable in the - /// back-end (eg. an alchemical coupling parameter for lambda-dynamics) + /// \brief A variable that constrains or follows an external parameter + /// in the back-end (eg. an alchemical coupling parameter for lambda-dynamics) + /// If extended Lagrangian, then we drive the external parameter + /// Otherwise we follow it /// Can have a single component f_cv_external, /// \brief The extended system coordinate undergoes Langevin dynamics diff --git a/lib/colvars/colvargrid.cpp b/lib/colvars/colvargrid.cpp index 11693a7587..ad42966943 100644 --- a/lib/colvars/colvargrid.cpp +++ b/lib/colvars/colvargrid.cpp @@ -24,15 +24,14 @@ colvar_grid_count::colvar_grid_count() mult = 1; } -colvar_grid_count::colvar_grid_count(std::vector const &nx_i, - size_t const &def_count) - : colvar_grid(nx_i, def_count, 1) +colvar_grid_count::colvar_grid_count(std::vector &colvars, + std::string config) + : colvar_grid(colvars, 0, 1, false, nullptr, config) {} colvar_grid_count::colvar_grid_count(std::vector &colvars, - size_t const &def_count, - bool margin) - : colvar_grid(colvars, def_count, 1, margin) + std::shared_ptr params) + : colvar_grid(colvars, 0, 1, false, params) {} std::string colvar_grid_count::get_state_params() const @@ -132,13 +131,17 @@ colvar_grid_scalar::colvar_grid_scalar(colvar_grid_scalar const &g) { } -colvar_grid_scalar::colvar_grid_scalar(std::vector const &nx_i) - : colvar_grid(nx_i, 0.0, 1), samples(NULL) +colvar_grid_scalar::colvar_grid_scalar(std::vector &colvars, + std::shared_ptr params, + bool add_extra_bin, + std::string config) + : colvar_grid(colvars, 0.0, 1, add_extra_bin, params, config), samples(NULL) { } -colvar_grid_scalar::colvar_grid_scalar(std::vector &colvars, bool margin) - : colvar_grid(colvars, 0.0, 1, margin), samples(NULL) +colvar_grid_scalar::colvar_grid_scalar(std::string const &filename) + : colvar_grid(filename, 1), + samples(nullptr) { } @@ -330,89 +333,37 @@ cvm::real colvar_grid_scalar::grid_rmsd(colvar_grid_scalar const &other_grid) co colvar_grid_gradient::colvar_grid_gradient() - : colvar_grid(), samples(NULL), full_samples(0), min_samples(0) + : colvar_grid(), samples(NULL) {} -colvar_grid_gradient::colvar_grid_gradient(std::vector const &nx_i) - : colvar_grid(nx_i, 0.0, nx_i.size()), samples(NULL), full_samples(0), min_samples(0) -{} +// colvar_grid_gradient::colvar_grid_gradient(std::vector &colvars, std::string config) +// : colvar_grid(colvars, 0.0, colvars.size(), false, nullptr, config), samples(NULL) +// {} +// colvar_grid_gradient::colvar_grid_gradient(std::vector &colvars, +// std::shared_ptr samples_in) +// : colvar_grid(colvars, 0.0, colvars.size(), false, samples_in), samples(samples_in) +// { +// if (samples_in) +// samples_in->has_parent_data = true; +// } -colvar_grid_gradient::colvar_grid_gradient(std::vector &colvars) - : colvar_grid(colvars, 0.0, colvars.size()), samples(NULL), full_samples(0), min_samples(0) -{} - - -colvar_grid_gradient::colvar_grid_gradient(std::vector &colvars, std::shared_ptr samples_in) - : colvar_grid(colvars, 0.0, colvars.size()), samples(samples_in), full_samples(0), min_samples(0) +colvar_grid_gradient::colvar_grid_gradient(std::vector &colvars, + std::shared_ptr samples_in, + std::shared_ptr params, + std::string config) + : colvar_grid(colvars, 0.0, colvars.size(), false, params, config), samples(samples_in) { - samples_in->has_parent_data = true; + if (samples_in) + samples_in->has_parent_data = true; } -colvar_grid_gradient::colvar_grid_gradient(std::string &filename) - : colvar_grid(), - samples(NULL) +colvar_grid_gradient::colvar_grid_gradient(std::string const &filename) + : colvar_grid(filename, 0), + samples(nullptr) { - std::istream &is = cvm::main()->proxy->input_stream(filename, - "gradient file"); - if (!is) { - return; - } - - // Data in the header: nColvars, then for each - // xiMin, dXi, nPoints, periodic flag - - std::string hash; - size_t i; - - if ( !(is >> hash) || (hash != "#") ) { - cvm::error("Error reading grid at position "+ - cvm::to_str(static_cast(is.tellg()))+ - " in stream(read \"" + hash + "\")\n"); - return; - } - - is >> nd; - - if (nd > 50) { - cvm::error("Error: excessive number of dimensions in file \""+ - filename+"\". Please ensure that the file is not corrupt.\n", - COLVARS_INPUT_ERROR); - return; - } - - mult = nd; - std::vector lower_in(nd), widths_in(nd); - std::vector nx_in(nd); - std::vector periodic_in(nd); - - for (i = 0; i < nd; i++ ) { - if ( !(is >> hash) || (hash != "#") ) { - cvm::error("Error reading grid at position "+ - cvm::to_str(static_cast(is.tellg()))+ - " in stream(read \"" + hash + "\")\n"); - return; - } - - is >> lower_in[i] >> widths_in[i] >> nx_in[i] >> periodic_in[i]; - } - - this->setup(nx_in, 0., mult); - - widths = widths_in; - - for (i = 0; i < nd; i++ ) { - lower_boundaries.push_back(colvarvalue(lower_in[i])); - periodic.push_back(static_cast(periodic_in[i])); - } - - // Reset the istream for read_multicol, which expects the whole file - is.clear(); - is.seekg(0); - read_multicol(is); - cvm::main()->proxy->close_input_stream(filename); } std::string colvar_grid_gradient::get_state_params() const @@ -586,12 +537,13 @@ cvm::real colvar_grid_gradient::grid_rmsd(colvar_grid_gradient const &other_grid } -integrate_potential::integrate_potential(std::vector &colvars, std::shared_ptr gradients) - : colvar_grid_scalar(colvars, true), +integrate_potential::integrate_potential(std::vector &colvars, + std::shared_ptr gradients) + : colvar_grid_scalar(colvars, gradients, true), b_smoothed(false), gradients(gradients) { - // parent class colvar_grid_scalar is constructed with margin option set to true + // parent class colvar_grid_scalar is constructed with add_extra_bin option set to true // hence PMF grid is wider than gradient grid if non-PBC if (nd > 1) { diff --git a/lib/colvars/colvargrid.h b/lib/colvars/colvargrid.h index 4cbbb10961..697b46a560 100644 --- a/lib/colvars/colvargrid.h +++ b/lib/colvars/colvargrid.h @@ -19,17 +19,13 @@ #include "colvarparse.h" -/// \brief Grid of values of a function of several collective -/// variables \param T The data type -/// -/// Only scalar colvars supported so far: vector colvars are treated as arrays -template class colvar_grid : public colvarparse { - - //protected: -public: // TODO create accessors for these after all instantiations work +/// \brief Unified base class for grid of values of a function of several collective +/// variables +class colvar_grid_params { +public: /// Number of dimensions - size_t nd; + size_t nd = 0; /// Number of points along each dimension std::vector nx; @@ -37,6 +33,27 @@ public: // TODO create accessors for these after all instantiations work /// Cumulative number of points along each dimension std::vector nxc; + /// Lower boundaries of the colvars in this grid + std::vector lower_boundaries; + + /// Upper boundaries of the colvars in this grid + std::vector upper_boundaries; + + /// Widths of the colvars in this grid + std::vector widths; +}; + + +/// \brief Grid of values of a function of several collective +/// variables \param T The data type +/// +/// Only scalar colvars supported so far: vector colvars are treated as arrays +/// All common, type-independent members are collected in the base class colvar_grid_base +template class colvar_grid : public colvar_grid_params, public colvarparse { + + //protected: +public: // TODO create accessors for these after all instantiations work + /// \brief Multiplicity of each datum (allow the binning of /// non-scalar types such as atomic gradients) size_t mult; @@ -73,13 +90,6 @@ public: // TODO create accessors for these after all instantiations work } public: - - /// Lower boundaries of the colvars in this grid - std::vector lower_boundaries; - - /// Upper boundaries of the colvars in this grid - std::vector upper_boundaries; - /// Whether some colvars are periodic std::vector periodic; @@ -89,9 +99,6 @@ public: /// Whether some colvars have hard upper boundaries std::vector hard_upper_boundaries; - /// Widths of the colvars in this grid - std::vector widths; - /// True if this is a count grid related to another grid of data bool has_parent_data; @@ -218,19 +225,15 @@ public: /// \brief "Almost copy-constructor": only copies configuration /// parameters from another grid, but doesn't reallocate stuff; /// setup() must be called after that; - colvar_grid(colvar_grid const &g) : colvarparse(), - nd(g.nd), - nx(g.nx), + colvar_grid(colvar_grid const &g) : colvar_grid_params(colvar_grid_params(g)), + colvarparse(), mult(g.mult), data(), cv(g.cv), use_actual_value(g.use_actual_value), - lower_boundaries(g.lower_boundaries), - upper_boundaries(g.upper_boundaries), periodic(g.periodic), hard_lower_boundaries(g.hard_lower_boundaries), hard_upper_boundaries(g.hard_upper_boundaries), - widths(g.widths), has_parent_data(false), has_data(false) {} @@ -247,22 +250,31 @@ public: this->setup(nx_i, t, mult_i); } - /// \brief Constructor from a vector of colvars + /// \brief Constructor from a vector of colvars or an optional grid config string /// \param add_extra_bin requests that non-periodic dimensions are extended /// by 1 bin to accommodate the integral (PMF) of another gridded quantity (gradient) colvar_grid(std::vector const &colvars, T const &t = T(), size_t mult_i = 1, - bool add_extra_bin = false) + bool add_extra_bin = false, + std::shared_ptr params = nullptr, + std::string config = std::string()) : has_parent_data(false), has_data(false) { (void) t; - this->init_from_colvars(colvars, mult_i, add_extra_bin); + this->init_from_colvars(colvars, mult_i, add_extra_bin, params, config); } + /// \brief Constructor from a multicol file + /// \param filename multicol file containing data to be read + /// \param multi_i multiplicity of the data - if 0, assume gradient multiplicity (mult = nd) + colvar_grid(std::string const &filename, size_t mult_i = 1); + int init_from_colvars(std::vector const &colvars, size_t mult_i = 1, - bool add_extra_bin = false) + bool add_extra_bin = false, + std::shared_ptr params = nullptr, + std::string config = std::string()) { if (cvm::debug()) { cvm::log("Reading grid configuration from collective variables.\n"); @@ -279,8 +291,7 @@ public: " collective variables, multiplicity = "+cvm::to_str(mult_i)+".\n"); } - for (i = 0; i < cv.size(); i++) { - + for (i = 0; i < nd; i++) { if (cv[i]->value().type() != colvarvalue::type_scalar) { cvm::error("Colvar grids can only be automatically " "constructed for scalar variables. " @@ -298,7 +309,6 @@ public: widths.push_back(cv[i]->width); hard_lower_boundaries.push_back(cv[i]->is_enabled(colvardeps::f_cv_hard_lower_boundary)); hard_upper_boundaries.push_back(cv[i]->is_enabled(colvardeps::f_cv_hard_upper_boundary)); - periodic.push_back(cv[i]->periodic_boundaries()); // By default, get reported colvar value (for extended Lagrangian colvars) use_actual_value.push_back(false); @@ -310,22 +320,55 @@ public: use_actual_value[i-1] = true; } + // This needs to work if the boundaries are undefined in the colvars + lower_boundaries.push_back(cv[i]->lower_boundary); + upper_boundaries.push_back(cv[i]->upper_boundary); + } + + // Replace widths and boundaries with optional custom configuration + if (!config.empty()) { + this->parse_params(config); + this->check_keywords(config, "grid"); + + if (params) { + cvm::error("Error: init_from_colvars was passed both a grid config and a template grid.", COLVARS_BUG_ERROR); + return COLVARS_BUG_ERROR; + } + } else if (params) { + // Match grid sizes with template + + if (params->nd != nd) { + cvm::error("Trying to initialize grid from template with wrong dimension (" + + cvm::to_str(params->nd) + " instead of " + + cvm::to_str(this->nd) + ")."); + return COLVARS_ERROR; + } + + widths =params->widths; + lower_boundaries =params->lower_boundaries; + upper_boundaries =params->upper_boundaries; + } + + // Only now can we determine periodicity + for (i = 0; i < nd; i++) { + periodic.push_back(cv[i]->periodic_boundaries(lower_boundaries[i].real_value, + upper_boundaries[i].real_value)); + if (add_extra_bin) { + // Shift the grid by half the bin width (values at edges instead of center of bins) + lower_boundaries[i] -= 0.5 * widths[i]; + if (periodic[i]) { - // Shift the grid by half the bin width (values at edges instead of center of bins) - lower_boundaries.push_back(cv[i]->lower_boundary.real_value - 0.5 * widths[i]); - upper_boundaries.push_back(cv[i]->upper_boundary.real_value - 0.5 * widths[i]); + // Just shift + upper_boundaries[i] -= 0.5 * widths[i]; } else { - // Make this grid larger by one bin width - lower_boundaries.push_back(cv[i]->lower_boundary.real_value - 0.5 * widths[i]); - upper_boundaries.push_back(cv[i]->upper_boundary.real_value + 0.5 * widths[i]); + // Widen grid by one bin width + upper_boundaries[i] += 0.5 * widths[i]; } - } else { - lower_boundaries.push_back(cv[i]->lower_boundary); - upper_boundaries.push_back(cv[i]->upper_boundary); } } + // Reset grid sizes based on widths and boundaries this->init_from_boundaries(); return this->setup(); } @@ -966,14 +1009,12 @@ public: virtual ~colvar_grid_count() {} - /// Constructor - colvar_grid_count(std::vector const &nx_i, - size_t const &def_count = 0); - - /// Constructor from a vector of colvars + /// Constructor from a vector of colvars or a config string colvar_grid_count(std::vector &colvars, - size_t const &def_count = 0, - bool add_extra_bin = false); + std::shared_ptr params = nullptr); + + colvar_grid_count(std::vector &colvars, + std::string config); /// Increment the counter at given position inline void incr_count(std::vector const &ix) @@ -1255,12 +1296,14 @@ public: /// Destructor virtual ~colvar_grid_scalar(); - /// Constructor from specific sizes arrays - colvar_grid_scalar(std::vector const &nx_i); - /// Constructor from a vector of colvars colvar_grid_scalar(std::vector &colvars, - bool add_extra_bin = false); + std::shared_ptr params = nullptr, + bool add_extra_bin = false, + std::string config = std::string()); + + /// Constructor from a multicol file + colvar_grid_scalar(std::string const &filename); /// Accumulate the value inline void acc_value(std::vector const &ix, @@ -1334,8 +1377,8 @@ public: /// \brief Return the gradient of the scalar field from finite differences /// Input coordinates are those of gradient grid, shifted wrt scalar grid - /// Should not be called on edges of scalar grid, provided the latter has margins - /// wrt gradient grid + /// Should not be called on edges of scalar grid, provided the latter has + /// margins (extra bins) wrt gradient grid inline void vector_gradient_finite_diff( const std::vector &ix0, std::vector &grad) { cvm::real A0, A1; @@ -1566,17 +1609,21 @@ public: virtual ~colvar_grid_gradient() {} - /// Constructor from specific sizes arrays - colvar_grid_gradient(std::vector const &nx_i); + // /// Constructor from specific sizes arrays + // colvar_grid_gradient(std::vector const &nx_i); - /// Constructor from a vector of colvars - colvar_grid_gradient(std::vector &colvars); + // /// Constructor from a vector of colvars + // colvar_grid_gradient(std::vector &colvars, + // std::string config = std::string()); /// Constructor from a multicol file - colvar_grid_gradient(std::string &filename); + colvar_grid_gradient(std::string const &filename); /// Constructor from a vector of colvars and a pointer to the count grid - colvar_grid_gradient(std::vector &colvars, std::shared_ptr samples_in); + colvar_grid_gradient(std::vector &colvars, + std::shared_ptr samples_in = nullptr, + std::shared_ptr params = nullptr, + std::string config = std::string()); /// Parameters for smoothing data with low sampling int full_samples; @@ -1829,7 +1876,8 @@ class integrate_potential : public colvar_grid_scalar {} /// Constructor from a vector of colvars + gradient grid - integrate_potential(std::vector &colvars, std::shared_ptr gradients); + integrate_potential(std::vector &colvars, + std::shared_ptr gradients); /// Constructor from a gradient grid (for processing grid files without a Colvars config) integrate_potential(std::shared_ptr gradients); diff --git a/lib/colvars/colvargrid_def.h b/lib/colvars/colvargrid_def.h index fa6531271b..96075e1ffe 100644 --- a/lib/colvars/colvargrid_def.h +++ b/lib/colvars/colvargrid_def.h @@ -22,6 +22,62 @@ #include "colvars_memstream.h" +template +colvar_grid::colvar_grid(std::string const &filename, size_t mult_i) +{ +std::istream &is = cvm::main()->proxy->input_stream(filename, "multicol grid file"); +if (!is) { + return; +} + +// Data in the header: nColvars, then for each +// xiMin, dXi, nPoints, periodic flag + +std::string hash; +size_t i; + +if ( !(is >> hash) || (hash != "#") ) { + cvm::error("Error reading grid at position "+ + cvm::to_str(static_cast(is.tellg()))+ + " in stream(read \"" + hash + "\")\n"); + return; +} + +is >> nd; +mult = (mult_i == 0) ? nd : mult_i; + +std::vector lower_in(nd), widths_in(nd); +std::vector nx_in(nd); +std::vector periodic_in(nd); + +for (i = 0; i < nd; i++ ) { + if ( !(is >> hash) || (hash != "#") ) { + cvm::error("Error reading grid at position "+ + cvm::to_str(static_cast(is.tellg()))+ + " in stream(read \"" + hash + "\")\n"); + return; + } + + is >> lower_in[i] >> widths_in[i] >> nx_in[i] >> periodic_in[i]; +} + +this->setup(nx_in, 0., mult); + +widths = widths_in; + +for (i = 0; i < nd; i++ ) { + lower_boundaries.push_back(colvarvalue(lower_in[i])); + periodic.push_back(static_cast(periodic_in[i])); +} + +// Reset the istream for read_multicol, which expects the whole file +is.clear(); +is.seekg(0); +read_multicol(is); +cvm::main()->proxy->close_input_stream(filename); +} + + template IST &read_restart_template_(colvar_grid &g, IST &is) { auto const start_pos = is.tellg(); @@ -203,14 +259,16 @@ template int colvar_grid::parse_params(std::string const &conf, lower_boundaries, lower_boundaries, colvarparse::parse_silent); colvarparse::get_keyval(conf, "upper_boundaries", upper_boundaries, upper_boundaries, colvarparse::parse_silent); + // plural form is used in state file + colvarparse::get_keyval(conf, "widths", widths, widths, colvarparse::parse_silent); // camel case keywords are used in config file - colvarparse::get_keyval(conf, "lowerBoundaries", + colvarparse::get_keyval(conf, "lowerBoundary", lower_boundaries, lower_boundaries, parse_mode); - colvarparse::get_keyval(conf, "upperBoundaries", + colvarparse::get_keyval(conf, "upperBoundary", upper_boundaries, upper_boundaries, parse_mode); - colvarparse::get_keyval(conf, "widths", widths, widths, parse_mode); + colvarparse::get_keyval(conf, "width", widths, widths, parse_mode); // only used in state file colvarparse::get_keyval(conf, "sizes", nx, nx, colvarparse::parse_silent); diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp index 25b1efe209..34485d7883 100644 --- a/lib/colvars/colvarmodule.cpp +++ b/lib/colvars/colvarmodule.cpp @@ -24,6 +24,7 @@ #include "colvarbias_histogram_reweight_amd.h" #include "colvarbias_meta.h" #include "colvarbias_restraint.h" +#include "colvarbias_opes.h" #include "colvarscript.h" #include "colvaratoms.h" #include "colvarcomp.h" @@ -109,23 +110,23 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in) " https://doi.org/10.1080/00268976.2013.813594\n" "as well as all other papers listed below for individual features used.\n"); -#if (__cplusplus >= 201103L) - cvm::log("This version was built with the C++11 standard or higher.\n"); -#else - cvm::log("This version was built without the C++11 standard: some features are disabled.\n" - "Please see the following link for details:\n" - " https://colvars.github.io/README-c++11.html\n"); -#endif - cvm::log("Summary of compile-time features available in this build:\n"); - if (proxy->check_smp_enabled() == COLVARS_NOT_IMPLEMENTED) { - cvm::log(" - SMP parallelism: not available\n"); + std::string cxx_lang_msg(" - C++ language version: " + cvm::to_str(__cplusplus)); +#if defined(_WIN32) && !defined(__CYGWIN__) + cxx_lang_msg += std::string(" (warning: may not be accurate for this build)"); +#endif + cxx_lang_msg += std::string("\n"); + cvm::log(cxx_lang_msg); + + if (proxy->check_replicas_enabled() == COLVARS_NOT_IMPLEMENTED) { + cvm::log(" - Multiple replicas: not available\n"); } else { - if (proxy->check_smp_enabled() == COLVARS_OK) { - cvm::log(" - SMP parallelism: enabled (num. threads = " + to_str(proxy->smp_num_threads()) + ")\n"); + if (proxy->check_replicas_enabled() == COLVARS_OK) { + cvm::log(" - Multiple replicas: enabled (replica number " + + to_str(proxy->replica_index() + 1) + " of " + to_str(proxy->num_replicas()) + ")\n"); } else { - cvm::log(" - SMP parallelism: available, but not enabled\n"); + cvm::log(" - Multiple replicas: available, but not (yet) enabled\n"); } } @@ -201,6 +202,20 @@ std::vector *colvarmodule::variables_active_smp_items() } +int colvarmodule::calc_component_smp(int i) +{ + colvar *x = (*(variables_active_smp()))[i]; + int x_item = (*(variables_active_smp_items()))[i]; + if (cvm::debug()) { + cvm::log("Thread "+cvm::to_str(proxy->smp_thread_id())+"/"+ + cvm::to_str(proxy->smp_num_threads())+ + ": calc_component_smp(), i = "+cvm::to_str(i)+", cv = "+ + x->name+", cvc = "+cvm::to_str(x_item)+"\n"); + } + return x->calc_cvcs(x_item, 1); +} + + std::vector *colvarmodule::biases_active() { return &(biases_active_); @@ -387,8 +402,26 @@ int colvarmodule::parse_global_params(std::string const &conf) } } - if (parse->get_keyval(conf, "smp", proxy->b_smp_active, proxy->b_smp_active)) { - if (proxy->b_smp_active == false) { + std::string smp; + if (parse->get_keyval(conf, "smp", smp, "cvcs")) { + if (smp == "cvcs" || smp == "on" || smp == "yes") { + if (proxy->set_smp_mode(colvarproxy_smp::smp_mode_t::cvcs) != COLVARS_OK) { + cvm::error("Colvars component-based parallelism is not implemented.\n"); + return COLVARS_INPUT_ERROR; + } else { + cvm::log("SMP parallelism will be applied to Colvars components.\n"); + cvm::log(" - SMP parallelism: enabled (num. threads = " + to_str(proxy->smp_num_threads()) + ")\n"); + } + } else if (smp == "inner_loop") { + if (proxy->set_smp_mode(colvarproxy_smp::smp_mode_t::inner_loop) != COLVARS_OK) { + cvm::error("SMP parallelism inside the calculation of Colvars components is not implemented.\n"); + return COLVARS_INPUT_ERROR; + } else { + cvm::log("SMP parallelism will be applied inside the Colvars components.\n"); + cvm::log(" - SMP parallelism: enabled (num. threads = " + to_str(proxy->smp_num_threads()) + ")\n"); + } + } else { + proxy->set_smp_mode(colvarproxy_smp::smp_mode_t::none); cvm::log("SMP parallelism has been disabled.\n"); } } @@ -589,6 +622,9 @@ int colvarmodule::parse_biases(std::string const &conf) /// initialize reweightaMD instances parse_biases_type(conf, "reweightaMD"); + /// initialize OPES instances + parse_biases_type(conf, "opes_metad"); + if (use_scripted_forces) { cvm::log(cvm::line_marker); cvm::increase_depth(); @@ -922,7 +958,7 @@ int colvarmodule::calc_colvars() } // if SMP support is available, split up the work - if (proxy->check_smp_enabled() == COLVARS_OK) { + if (proxy->get_smp_mode() == colvarproxy_smp::smp_mode_t::cvcs) { // first, calculate how much work (currently, how many active CVCs) each colvar has @@ -948,8 +984,10 @@ int colvarmodule::calc_colvars() } cvm::decrease_depth(); - // calculate colvar components in parallel - error_code |= proxy->smp_colvars_loop(); + // calculate active colvar components in parallel + error_code |= proxy->smp_loop(variables_active_smp()->size(), [](int i) { + return cvm::main()->calc_component_smp(i); + }); cvm::increase_depth(); for (cvi = variables_active()->begin(); cvi != variables_active()->end(); cvi++) { @@ -1013,7 +1051,7 @@ int colvarmodule::calc_biases() } // If SMP support is available, split up the work (unless biases need to use main thread's memory) - if (proxy->check_smp_enabled() == COLVARS_OK && !biases_need_main_thread) { + if (proxy->get_smp_mode() == colvarproxy::smp_mode_t::cvcs && !biases_need_main_thread) { if (use_scripted_forces && !scripting_after_biases) { // calculate biases and scripted forces in parallel @@ -1097,7 +1135,7 @@ int colvarmodule::update_colvar_forces() cvm::log("Communicating forces from the colvars to the atoms.\n"); cvm::increase_depth(); for (cvi = variables_active()->begin(); cvi != variables_active()->end(); cvi++) { - if ((*cvi)->is_enabled(colvardeps::f_cv_gradient)) { + if ((*cvi)->is_enabled(colvardeps::f_cv_apply_force)) { (*cvi)->communicate_forces(); if (cvm::get_error()) { return COLVARS_ERROR; @@ -1986,7 +2024,7 @@ size_t & colvarmodule::depth() { // NOTE: do not call log() or error() here, to avoid recursion colvarmodule *cv = cvm::main(); - if (proxy->check_smp_enabled() == COLVARS_OK) { + if (proxy->get_smp_mode() == colvarproxy::smp_mode_t::cvcs) { int const nt = proxy->smp_num_threads(); if (int(cv->depth_v.size()) != nt) { proxy->smp_lock(); diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h index fa84b1ad75..5f042767dc 100644 --- a/lib/colvars/colvarmodule.h +++ b/lib/colvars/colvarmodule.h @@ -18,6 +18,11 @@ #define COLVARS_DEBUG false #endif +#if defined(__FAST_MATH__) +// NOTE: This is used for fixing https://github.com/Colvars/colvars/issues/767 +#define COLVARS_BOUNDED_INV_TRIGONOMETRIC_FUNC +#endif + /*! \mainpage Main page This is the Developer's documentation for the Collective Variables module (Colvars). @@ -147,17 +152,44 @@ public: return ::cos(static_cast(x)); } - /// Reimplemented to work around MS compiler issues - static inline real asin(real const &x) - { - return ::asin(static_cast(x)); - } +#ifndef PI +#define PI 3.14159265358979323846 +#endif +#ifndef PI_2 +#define PI_2 1.57079632679489661923 +#endif - /// Reimplemented to work around MS compiler issues - static inline real acos(real const &x) - { +/// Reimplemented to work around compiler issues; return hard-coded values for boundary conditions +static inline real asin(real const &x) +{ +#ifdef COLVARS_BOUNDED_INV_TRIGONOMETRIC_FUNC + if (x <= -1.0) { + return -PI_2; + } else if (x >= 1.0) { + return PI_2; + } else { + return ::asin(static_cast(x)); + } +#else + return ::asin(static_cast(x)); +#endif +} + +/// Reimplemented to work around compiler issues; return hard-coded values for boundary conditions +static inline real acos(real const &x) +{ +#ifdef COLVARS_BOUNDED_INV_TRIGONOMETRIC_FUNC + if (x <= -1.0) { + return PI; + } else if (x >= 1.0) { + return 0.0; + } else { + return ::acos(static_cast(x)); + } +#else return ::acos(static_cast(x)); - } +#endif +} /// Reimplemented to work around MS compiler issues static inline real atan2(real const &x, real const &y) @@ -307,6 +339,9 @@ public: /// Indexes of the items to calculate for each colvar std::vector *variables_active_smp_items(); + /// Calculate the value of the specified component (to be called in a SMP loop) + int calc_component_smp(int i); + /// Array of collective variable biases std::vector biases; diff --git a/lib/colvars/colvarmodule_refs.h b/lib/colvars/colvarmodule_refs.h index 2e9615e3b4..0317567502 100644 --- a/lib/colvars/colvarmodule_refs.h +++ b/lib/colvars/colvarmodule_refs.h @@ -129,6 +129,23 @@ " url = {https://doi.org/10.1002/jcc.26075}\n" "}\n"; + paper_count_[std::string("Fiorin2024")] = 0; + paper_url_[std::string("Fiorin2024")] = "https://doi.org/10.1021/acs.jpcb.4c05604"; + paper_bibtex_[std::string("Fiorin2024")] = + "\n" + "@article{Fiorin2024,\n" + " author = {Fiorin, Giacomo and Marinelli, Fabrizio and Forrest, Lucy R. and Chen, Haochuan and Chipot, Christophe and Kohlmeyer, Axel and Santuz, Hubert and H{\\'e}nin, J{\\'e}rôme},\n" + " title = {Expanded Functionality and Portability for the Colvars Library},\n" + " journal = {J. Phys. Chem. {B}},\n" + " volume = {128},\n" + " number = {45},\n" + " pages = {11108--11123},\n" + " year = {2024},\n" + " doi = {10.1021/acs.jpcb.4c05604},\n" + " pmid = 39501453,\n" + " url = { https://doi.org/10.1021/acs.jpcb.4c05604}\n" + "}\n"; + paper_count_[std::string("Fu2016")] = 0; paper_url_[std::string("Fu2016")] = "https://doi.org/10.1021/acs.jctc.6b00447"; paper_bibtex_[std::string("Fu2016")] = @@ -227,6 +244,20 @@ " url = {https://doi.org/10.1016/0263-7855(96)00018-5}\n" "}\n"; + paper_count_[std::string("Lagardere2023")] = 0; + paper_url_[std::string("Lagardere2023")] = "https://arxiv.org/abs/2307.08006"; + paper_bibtex_[std::string("Lagardere2023")] = + "\n" + "@misc{Lagardere2023,\n" + " title={Lambda-ABF: Simplified, Accurate and Cost-effective Alchemical Free Energy Computations},\n" + " author={Louis Lagard\\`ere and Lise Maurin and Olivier Adjoua and Krystel El Hage and Pierre Monmarch\\'e and Jean-Philip Piquemal and J\\'er\\^ome H\\'enin},\n" + " year={2023},\n" + " eprint={2307.08006},\n" + " archivePrefix={arXiv},\n" + " primaryClass={physics.chem-ph},\n" + " url = {https://arxiv.org/abs/2307.08006}\n" + "}\n"; + paper_count_[std::string("Lesage2017")] = 0; paper_url_[std::string("Lesage2017")] = "https://doi.org/10.1021/acs.jpcb.6b10055"; paper_bibtex_[std::string("Lesage2017")] = @@ -344,6 +375,45 @@ " url = {https://doi.org/10.1021/ct500320c}\n" "}\n"; + paper_count_[std::string("Invernizzi2020")] = 0; + paper_url_[std::string("Invernizzi2020")] = "https://pubs.acs.org/doi/10.1021/acs.jpclett.0c00497"; + paper_bibtex_[std::string("Invernizzi2020")] = + "\n" + "@article{Invernizzi2020,\n" + " title = {Rethinking {Metadynamics}: {From} {Bias} {Potentials} to {Probability} {Distributions}},\n" + " volume = {11},\n" + " issn = {1948-7185, 1948-7185},\n" + " shorttitle = {Rethinking {Metadynamics}},\n" + " url = {https://pubs.acs.org/doi/10.1021/acs.jpclett.0c00497},\n" + " doi = {10.1021/acs.jpclett.0c00497},\n" + " number = {7},\n" + " urldate = {2020-09-30},\n" + " journal = {J. Phys. Chem. Lett.},\n" + " author = {Invernizzi, Michele and Parrinello, Michele},\n" + " month = apr,\n" + " year = {2020},\n" + " pages = {2731--2736},\n" + "}\n"; + + paper_count_[std::string("Invernizzi2022")] = 0; + paper_url_[std::string("Invernizzi2022")] = "https://doi.org/10.1021/acs.jctc.2c00152"; + paper_bibtex_[std::string("Invernizzi2022")] = + "\n" + "@article{Invernizzi2022,\n" + " title = {Exploration vs {Convergence} {Speed} in {Adaptive}-{Bias} {Enhanced} {Sampling}},\n" + " volume = {18},\n" + " issn = {1549-9618},\n" + " url = {https://doi.org/10.1021/acs.jctc.2c00152},\n" + " doi = {10.1021/acs.jctc.2c00152},\n" + " number = {6},\n" + " urldate = {2024-07-02},\n" + " journal = {J. Chem. Theory Comput.},\n" + " author = {Invernizzi, Michele and Parrinello, Michele},\n" + " month = jun,\n" + " year = {2022},\n" + " pages = {3988--3996},\n" + "}\n"; + paper_count_[std::string("n/a")] = 0; paper_url_[std::string("n/a")] = ""; paper_bibtex_[std::string("n/a")] = ""; @@ -489,6 +559,42 @@ feature_count_[std::string("Multi-Map collective variables")] = 0; feature_paper_map_[std::string("Multi-Map collective variables")] = "Fiorin2020"; + feature_count_[std::string("Colvars-GROMACS interface")] = 0; + feature_paper_map_[std::string("Colvars-GROMACS interface")] = "Fiorin2024"; + + feature_count_[std::string("gspath colvar component")] = 0; + feature_paper_map_[std::string("gspath colvar component")] = "Fiorin2024"; + + feature_count_[std::string("gzpath colvar component")] = 0; + feature_paper_map_[std::string("gzpath colvar component")] = "Fiorin2024"; + + feature_count_[std::string("linearCombination colvar component")] = 0; + feature_paper_map_[std::string("linearCombination colvar component")] = "Fiorin2024"; + + feature_count_[std::string("gspathCV colvar component")] = 0; + feature_paper_map_[std::string("gspathCV colvar component")] = "Fiorin2024"; + + feature_count_[std::string("gzpathCV colvar component")] = 0; + feature_paper_map_[std::string("gzpathCV colvar component")] = "Fiorin2024"; + + feature_count_[std::string("aspathCV colvar component")] = 0; + feature_paper_map_[std::string("aspathCV colvar component")] = "Fiorin2024"; + + feature_count_[std::string("azpathCV colvar component")] = 0; + feature_paper_map_[std::string("azpathCV colvar component")] = "Fiorin2024"; + + feature_count_[std::string("Custom functions (Lepton)")] = 0; + feature_paper_map_[std::string("Custom functions (Lepton)")] = "Fiorin2024"; + + feature_count_[std::string("Scripted functions (Tcl)")] = 0; + feature_paper_map_[std::string("Scripted functions (Tcl)")] = "Fiorin2024"; + + feature_count_[std::string("ABMD bias")] = 0; + feature_paper_map_[std::string("ABMD bias")] = "Fiorin2024"; + + feature_count_[std::string("Updated multiple-walker ABF implementation")] = 0; + feature_paper_map_[std::string("Updated multiple-walker ABF implementation")] = "Fiorin2024"; + feature_count_[std::string("Umbrella-integration eABF estimator")] = 0; feature_paper_map_[std::string("Umbrella-integration eABF estimator")] = "Fu2016"; @@ -525,6 +631,15 @@ feature_count_[std::string("VMD engine")] = 0; feature_paper_map_[std::string("VMD engine")] = "Humphrey1996"; + feature_count_[std::string("alchLambda colvar component")] = 0; + feature_paper_map_[std::string("alchLambda colvar component")] = "Lagardere2023"; + + feature_count_[std::string("alchFLambda colvar component")] = 0; + feature_paper_map_[std::string("alchFLambda colvar component")] = "Lagardere2023"; + + feature_count_[std::string("Tinker-HP interface")] = 0; + feature_paper_map_[std::string("Tinker-HP interface")] = "Lagardere2023"; + feature_count_[std::string("eABF implementation")] = 0; feature_paper_map_[std::string("eABF implementation")] = "Lesage2017"; @@ -555,38 +670,14 @@ feature_count_[std::string("ALB colvar bias implementation")] = 0; feature_paper_map_[std::string("ALB colvar bias implementation")] = "White2014"; - feature_count_[std::string("Colvars-GROMACS interface")] = 0; - feature_paper_map_[std::string("Colvars-GROMACS interface")] = "n/a"; + feature_count_[std::string("OPES")] = 0; + feature_paper_map_[std::string("OPES")] = "Invernizzi2020"; - feature_count_[std::string("gspath colvar component")] = 0; - feature_paper_map_[std::string("gspath colvar component")] = "n/a"; - - feature_count_[std::string("gzpath colvar component")] = 0; - feature_paper_map_[std::string("gzpath colvar component")] = "n/a"; - - feature_count_[std::string("linearCombination colvar component")] = 0; - feature_paper_map_[std::string("linearCombination colvar component")] = "n/a"; - - feature_count_[std::string("gspathCV colvar component")] = 0; - feature_paper_map_[std::string("gspathCV colvar component")] = "n/a"; - - feature_count_[std::string("gzpathCV colvar component")] = 0; - feature_paper_map_[std::string("gzpathCV colvar component")] = "n/a"; - - feature_count_[std::string("aspathCV colvar component")] = 0; - feature_paper_map_[std::string("aspathCV colvar component")] = "n/a"; - - feature_count_[std::string("azpathCV colvar component")] = 0; - feature_paper_map_[std::string("azpathCV colvar component")] = "n/a"; + feature_count_[std::string("OPES explore or adaptive kernels")] = 0; + feature_paper_map_[std::string("OPES explore or adaptive kernels")] = "Invernizzi2022"; feature_count_[std::string("coordNum pairlist")] = 0; feature_paper_map_[std::string("coordNum pairlist")] = "n/a"; - feature_count_[std::string("Custom functions (Lepton)")] = 0; - feature_paper_map_[std::string("Custom functions (Lepton)")] = "n/a"; - - feature_count_[std::string("Scripted functions (Tcl)")] = 0; - feature_paper_map_[std::string("Scripted functions (Tcl)")] = "n/a"; - - feature_count_[std::string("ABMD bias")] = 0; - feature_paper_map_[std::string("ABMD bias")] = "n/a"; + feature_count_[std::string("torchANN colvar component")] = 0; + feature_paper_map_[std::string("torchANN colvar component")] = "n/a"; diff --git a/lib/colvars/colvarparse.cpp b/lib/colvars/colvarparse.cpp index 76b5c694c1..cf3096ba50 100644 --- a/lib/colvars/colvarparse.cpp +++ b/lib/colvars/colvarparse.cpp @@ -592,7 +592,7 @@ int colvarparse::check_keywords(std::string &conf, char const *key) { if (cvm::debug()) cvm::log("Configuration string for \""+std::string(key)+ - "\": \"\n"+conf+"\".\n"); + "\":\n\""+conf+"\".\n"); strip_values(conf); // after stripping, the config string has either empty lines, or @@ -833,7 +833,8 @@ bool colvarparse::key_lookup(std::string const &conf, data_end) + 1; } - if (data != NULL) { + // data_end < data_begin means that the data or block contains only whitespace + if (data != NULL && data_end > data_begin) { data->append(line, data_begin, (data_end-data_begin)); if (cvm::debug()) { diff --git a/lib/colvars/colvarproxy.cpp b/lib/colvars/colvarproxy.cpp index 588b7c68d8..1ed7a55552 100644 --- a/lib/colvars/colvarproxy.cpp +++ b/lib/colvars/colvarproxy.cpp @@ -243,7 +243,7 @@ void colvarproxy_atom_groups::compute_max_atom_groups_applied_force() colvarproxy_smp::colvarproxy_smp() { - b_smp_active = true; // May be disabled by user option + smp_mode = smp_mode_t::cvcs; // May be disabled by user option omp_lock_state = NULL; #if defined(_OPENMP) if (omp_get_thread_num() == 0) { @@ -265,41 +265,45 @@ colvarproxy_smp::~colvarproxy_smp() #endif } - -int colvarproxy_smp::check_smp_enabled() -{ +colvarproxy::smp_mode_t colvarproxy_smp::get_smp_mode() const { #if defined(_OPENMP) - if (b_smp_active) { - return COLVARS_OK; - } - return COLVARS_ERROR; + return smp_mode; #else - return COLVARS_NOT_IMPLEMENTED; + return colvarproxy::smp_mode_t::none; +#endif +} + +int colvarproxy_smp::set_smp_mode(smp_mode_t mode) { +#if defined(_OPENMP) + smp_mode = mode; + return COLVARS_OK; +#else + if (mode != colvarproxy::smp_mode_t::none) { + return COLVARS_NOT_IMPLEMENTED; + } else { + smp_mode = colvarproxy::smp_mode_t::none; + } + return COLVARS_OK; #endif } -int colvarproxy_smp::smp_colvars_loop() +int colvarproxy_smp::smp_loop(int n_items, std::function const &worker) { + int error_code = COLVARS_OK; #if defined(_OPENMP) - colvarmodule *cv = cvm::main(); - colvarproxy *proxy = cv->proxy; + cvm::increase_depth(); #pragma omp parallel for - for (int i = 0; i < static_cast(cv->variables_active_smp()->size()); i++) { - colvar *x = (*(cv->variables_active_smp()))[i]; - int x_item = (*(cv->variables_active_smp_items()))[i]; - if (cvm::debug()) { - cvm::log("["+cvm::to_str(proxy->smp_thread_id())+"/"+ - cvm::to_str(proxy->smp_num_threads())+ - "]: calc_colvars_items_smp(), i = "+cvm::to_str(i)+", cv = "+ - x->name+", cvc = "+cvm::to_str(x_item)+"\n"); - } - x->calc_cvcs(x_item, 1); + for (int i = 0; i < n_items; i++) { + int const retcode = worker(i); +#pragma omp atomic + error_code |= retcode; } - return cvm::get_error(); + cvm::decrease_depth(); #else - return COLVARS_NOT_IMPLEMENTED; + error_code |= COLVARS_NOT_IMPLEMENTED; #endif + return error_code; } @@ -470,8 +474,8 @@ colvarproxy::~colvarproxy() bool colvarproxy::io_available() { - return (check_smp_enabled() == COLVARS_OK && smp_thread_id() == 0) || - (check_smp_enabled() != COLVARS_OK); + return ((get_smp_mode() != smp_mode_t::none) && smp_thread_id() == 0) || + (get_smp_mode() == smp_mode_t::none); } diff --git a/lib/colvars/colvarproxy.h b/lib/colvars/colvarproxy.h index 91db6011e9..353f354efa 100644 --- a/lib/colvars/colvarproxy.h +++ b/lib/colvars/colvarproxy.h @@ -10,9 +10,12 @@ #ifndef COLVARPROXY_H #define COLVARPROXY_H +#include + #include "colvarmodule.h" #include "colvartypes.h" #include "colvarproxy_io.h" +#include "colvarproxy_replicas.h" #include "colvarproxy_system.h" #include "colvarproxy_tcl.h" #include "colvarproxy_volmaps.h" @@ -447,21 +450,22 @@ class colvarproxy_smp { public: + enum class smp_mode_t {cvcs, inner_loop, none}; + /// Constructor colvarproxy_smp(); /// Destructor virtual ~colvarproxy_smp(); - /// Whether threaded parallelization should be used (TODO: make this a - /// cvm::deps feature) - bool b_smp_active; + /// Get the current SMP mode + virtual smp_mode_t get_smp_mode() const; - /// Whether threaded parallelization is available (TODO: make this a cvm::deps feature) - virtual int check_smp_enabled(); + /// Set the current SMP mode + virtual int set_smp_mode(smp_mode_t mode); - /// Distribute calculation of colvars (and their components) across threads - virtual int smp_colvars_loop(); + /// Distribute computation over threads using OpenMP, unless overridden in the backend (e.g. NAMD) + virtual int smp_loop(int n_items, std::function const &worker); /// Distribute calculation of biases across threads virtual int smp_biases_loop(); @@ -488,38 +492,10 @@ protected: /// Lock state for OpenMP omp_lock_t *omp_lock_state; -}; - - -/// \brief Methods for multiple-replica communication -class colvarproxy_replicas { - -public: - - /// Constructor - colvarproxy_replicas(); - - /// Destructor - virtual ~colvarproxy_replicas(); - - /// \brief Indicate if multi-replica support is available and active - virtual int replica_enabled(); - - /// \brief Index of this replica - virtual int replica_index(); - - /// \brief Total number of replicas - virtual int num_replicas(); - - /// \brief Synchronize replica with others - virtual void replica_comm_barrier(); - - /// \brief Receive data from other replica - virtual int replica_comm_recv(char* msg_data, int buf_len, int src_rep); - - /// \brief Send data to other replica - virtual int replica_comm_send(char* msg_data, int msg_len, int dest_rep); + /// Whether threaded parallelization should be used (TODO: make this a + /// cvm::deps feature) + smp_mode_t smp_mode; }; diff --git a/lib/colvars/colvarproxy_io.cpp b/lib/colvars/colvarproxy_io.cpp index 4cfdfeec26..0327ed36f0 100644 --- a/lib/colvars/colvarproxy_io.cpp +++ b/lib/colvars/colvarproxy_io.cpp @@ -7,10 +7,28 @@ // If you wish to distribute your changes, please submit them to the // Colvars repository at GitHub. + +#if defined(_WIN32) && !defined(__CYGWIN__) + // Using access() to check if a file exists (until we can assume C++14/17) -#if !defined(_WIN32) || defined(__CYGWIN__) -#include +#include + +#if defined(__has_include) +# if __has_include() +# include // MSVC only defines __cpp_lib_filesystem after include +# endif #endif + +#else + +#include + +#ifdef __cpp_lib_filesystem +#include +#endif + +#endif + #if defined(_WIN32) #include #endif @@ -64,6 +82,53 @@ int colvarproxy_io::set_frame(long int) } +std::string colvarproxy_io::get_current_work_dir() const +{ +#ifdef __cpp_lib_filesystem + + return std::filesystem::current_path().string(); + +#else + + // Legacy code + size_t constexpr buf_size = 3001; + char buf[buf_size]; + +#if defined(_WIN32) && !defined(__CYGWIN__) + char *getcwd_result = ::_getcwd(buf, buf_size); +#else + char *getcwd_result = ::getcwd(buf, buf_size); +#endif + + if (getcwd_result == nullptr) { + cvm::error("Error: cannot read the current working directory.\n", COLVARS_INPUT_ERROR); + return std::string(""); + } + + return std::string(getcwd_result); +#endif +} + + +std::string colvarproxy_io::join_paths(std::string const &path1, std::string const &path2) const +{ +#ifdef __cpp_lib_filesystem + + return (std::filesystem::path(path1) / std::filesystem::path(path2)).string(); + +#else + + // Legacy code +#if defined(_WIN32) && !defined(__CYGWIN__) + return (path1 + "\\" + path2); +#else + return (path1 + "/" + path2); +#endif + +#endif +} + + int colvarproxy_io::backup_file(char const *filename) { // Simplified version of NAMD_file_exists() diff --git a/lib/colvars/colvarproxy_io.h b/lib/colvars/colvarproxy_io.h index 726f915c97..eaf750366d 100644 --- a/lib/colvars/colvarproxy_io.h +++ b/lib/colvars/colvarproxy_io.h @@ -38,6 +38,12 @@ public: // Returns error code virtual int set_frame(long int); + /// Get the current working directory of this process + std::string get_current_work_dir() const; + + /// Join two paths using the operating system's path separation + std::string join_paths(std::string const &path1, std::string const &path2) const; + /// \brief Rename the given file, before overwriting it virtual int backup_file(char const *filename); diff --git a/lib/colvars/colvarproxy_replicas.cpp b/lib/colvars/colvarproxy_replicas.cpp index 1f336d3e44..ec7ffdd8d5 100644 --- a/lib/colvars/colvarproxy_replicas.cpp +++ b/lib/colvars/colvarproxy_replicas.cpp @@ -7,50 +7,103 @@ // If you wish to distribute your changes, please submit them to the // Colvars repository at GitHub. + #include "colvarmodule.h" -#include "colvarproxy.h" +#include "colvarproxy_replicas.h" -colvarproxy_replicas::colvarproxy_replicas() {} +colvarproxy_replicas::colvarproxy_replicas() +{ +#ifdef COLVARS_MPI + replicas_mpi_comm = MPI_COMM_NULL; +#endif +} colvarproxy_replicas::~colvarproxy_replicas() {} -int colvarproxy_replicas::replica_enabled() +void colvarproxy_replicas::set_replicas_mpi_communicator(replicas_mpi_comm_t comm) { + replicas_mpi_comm = comm; +#ifdef COLVARS_MPI + if (comm != MPI_COMM_NULL) { + MPI_Comm_rank(comm, &replicas_mpi_rank); + MPI_Comm_size(comm, &replicas_mpi_num); + cvm::log("Enabling multiple replicas: this is replica number " + + cvm::to_str(replica_index() + 1) + " of " + cvm::to_str(num_replicas()) + ".\n"); + } +#endif +} + + +int colvarproxy_replicas::check_replicas_enabled() +{ +#ifdef COLVARS_MPI + if (replicas_mpi_comm != MPI_COMM_NULL) { + return num_replicas() > 1 ? COLVARS_OK : COLVARS_ERROR; + } + return COLVARS_ERROR; +#else return COLVARS_NOT_IMPLEMENTED; +#endif } int colvarproxy_replicas::replica_index() { - return 0; + return replicas_mpi_rank; } int colvarproxy_replicas::num_replicas() { - return 1; + return replicas_mpi_num; } -void colvarproxy_replicas::replica_comm_barrier() {} - - -int colvarproxy_replicas::replica_comm_recv(char* /* msg_data */, - int /* buf_len */, - int /* src_rep */) +void colvarproxy_replicas::replica_comm_barrier() { - return COLVARS_NOT_IMPLEMENTED; +#ifdef COLVARS_MPI + MPI_Barrier(replicas_mpi_comm); +#endif } -int colvarproxy_replicas::replica_comm_send(char* /* msg_data */, - int /* msg_len */, - int /* dest_rep */) +int colvarproxy_replicas::replica_comm_recv(char *buffer, int buffer_length, int source_rank) { +#ifdef COLVARS_MPI + MPI_Status status; + int retval = MPI_Recv(buffer, buffer_length, MPI_CHAR, source_rank, 0, replicas_mpi_comm, &status); + if (retval == MPI_SUCCESS) { + MPI_Get_count(&status, MPI_CHAR, &retval); + } else { + retval = 0; + } + return retval; +#else + (void)buffer; + (void)buffer_length; + (void)source_rank; return COLVARS_NOT_IMPLEMENTED; +#endif } +int colvarproxy_replicas::replica_comm_send(char *buffer, int buffer_length, int destination_rank) +{ +#ifdef COLVARS_MPI + int retval = MPI_Send(buffer, buffer_length, MPI_CHAR, destination_rank, 0, replicas_mpi_comm); + if (retval == MPI_SUCCESS) { + retval = buffer_length; + } else { + retval = 0; + } + return retval; +#else + (void)buffer; + (void)buffer_length; + (void)destination_rank; + return COLVARS_NOT_IMPLEMENTED; +#endif +} diff --git a/lib/colvars/colvarproxy_replicas.h b/lib/colvars/colvarproxy_replicas.h new file mode 100644 index 0000000000..b58c80bf5e --- /dev/null +++ b/lib/colvars/colvarproxy_replicas.h @@ -0,0 +1,66 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + +#ifndef COLVARPROXY_REPLICAS_H +#define COLVARPROXY_REPLICAS_H + + +#ifdef COLVARS_MPI +#include +typedef MPI_Comm replicas_mpi_comm_t; +#else +typedef void * replicas_mpi_comm_t; +#endif + + +/// \brief Methods for multiple-replica communication +class colvarproxy_replicas { + +public: + + /// Constructor + colvarproxy_replicas(); + + /// Destructor + virtual ~colvarproxy_replicas(); + + /// Set the multiple replicas communicator + virtual void set_replicas_mpi_communicator(replicas_mpi_comm_t comm); + + /// Indicate if multi-replica support is available and active + virtual int check_replicas_enabled(); + + /// Index of this replica + virtual int replica_index(); + + /// Total number of replicas + virtual int num_replicas(); + + /// Synchronize replica with others + virtual void replica_comm_barrier(); + + /// Receive data from other replica + virtual int replica_comm_recv(char* msg_data, int buf_len, int src_rep); + + /// Send data to other replica + virtual int replica_comm_send(char* msg_data, int msg_len, int dest_rep); + +protected: + + /// MPI communicator containint 1 root proc from each world + replicas_mpi_comm_t replicas_mpi_comm; + + /// Index (rank) of this replica in the MPI implementation + int replicas_mpi_rank = 0; + + /// Number of replicas in the MPI implementation + int replicas_mpi_num = 1; +}; + +#endif diff --git a/lib/colvars/colvarproxy_system.h b/lib/colvars/colvarproxy_system.h index 67d0938e54..bf2ad2ea8b 100644 --- a/lib/colvars/colvarproxy_system.h +++ b/lib/colvars/colvarproxy_system.h @@ -94,6 +94,7 @@ public: virtual bool total_forces_enabled() const; /// Are total forces from the current step available? + /// in which case they are really system forces virtual bool total_forces_same_step() const; /// Get the molecule ID when called in VMD; raise error otherwise @@ -109,6 +110,11 @@ public: /// Send cached value of alchemical lambda parameter to back-end (if available) virtual int send_alch_lambda(); + /// Request energy computation every freq steps (necessary for NAMD3, not all back-ends) + virtual int request_alch_energy_freq(int const freq) { + return COLVARS_OK; + } + /// Get energy derivative with respect to lambda (if available) virtual int get_dE_dlambda(cvm::real* dE_dlambda); diff --git a/lib/colvars/colvars_memstream.h b/lib/colvars/colvars_memstream.h index 0d80d2794d..c9564a3c41 100644 --- a/lib/colvars/colvars_memstream.h +++ b/lib/colvars/colvars_memstream.h @@ -108,6 +108,9 @@ public: /// Ignore formatting operators inline void setf(decltype(std::ios::fmtflags(0)), decltype(std::ios::floatfield)) {} + /// Ignore formatting operators + inline void setf(decltype(std::ios::fmtflags(0))) {} + /// Ignore formatting operators inline void flags(decltype(std::ios::fmtflags(0))) {} diff --git a/lib/colvars/colvars_version.h b/lib/colvars/colvars_version.h index d50a00fff5..02f949b517 100644 --- a/lib/colvars/colvars_version.h +++ b/lib/colvars/colvars_version.h @@ -1,3 +1,3 @@ #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2024-06-04" +#define COLVARS_VERSION "2025-04-30" #endif diff --git a/lib/colvars/colvarscript_commands.h b/lib/colvars/colvarscript_commands.h index bdad74e433..191724dd0f 100644 --- a/lib/colvars/colvarscript_commands.h +++ b/lib/colvars/colvarscript_commands.h @@ -541,6 +541,15 @@ CVSCRIPT(cv_printframe, return COLVARS_OK; ) +CVSCRIPT(cv_patchversion, + "Get the Colvars patch version number (used for bugfixes only)\n" + "version : string - Colvars version", + 0, 0, + "", + script->set_result_int(cvm::main()->patch_version_number()); + return COLVARS_OK; + ) + CVSCRIPT(cv_printframelabels, "Return the labels that would be written to colvars.traj\n" "Labels : string - The labels", @@ -656,7 +665,7 @@ CVSCRIPT(cv_update, ) CVSCRIPT(cv_version, - "Get the Colvars Module version string\n" + "Get the Colvars version string\n" "version : string - Colvars version", 0, 0, "", @@ -665,7 +674,7 @@ CVSCRIPT(cv_version, ) // This guard allows compiling colvar and bias function bodies in their -// respecitve files instead of colvarscript_commands.o +// respective files instead of colvarscript_commands.o #ifndef COLVARSCRIPT_COMMANDS_GLOBAL #include "colvarscript_commands_colvar.h" #include "colvarscript_commands_bias.h" diff --git a/lib/colvars/colvarscript_commands_colvar.h b/lib/colvars/colvarscript_commands_colvar.h index f6bb6b8c98..c641b321d0 100644 --- a/lib/colvars/colvarscript_commands_colvar.h +++ b/lib/colvars/colvarscript_commands_colvar.h @@ -23,6 +23,7 @@ CVSCRIPT(colvar_addforce, script->add_error_msg("addforce : error parsing force value"); return COLVARSCRIPT_ERROR; } + this_colvar->enable(colvardeps::f_cv_apply_force); this_colvar->add_bias_force(force); script->set_result_colvarvalue(force); return COLVARS_OK; diff --git a/lib/colvars/colvartypes.cpp b/lib/colvars/colvartypes.cpp index f51791d015..6c65f1f5a6 100644 --- a/lib/colvars/colvartypes.cpp +++ b/lib/colvars/colvartypes.cpp @@ -137,71 +137,6 @@ std::istream & operator >> (std::istream &is, colvarmodule::quaternion &q) } -cvm::quaternion -cvm::quaternion::position_derivative_inner(cvm::rvector const &pos, - cvm::rvector const &vec) const -{ - cvm::quaternion result(0.0, 0.0, 0.0, 0.0); - - - result.q0 = 2.0 * pos.x * q0 * vec.x - +2.0 * pos.y * q0 * vec.y - +2.0 * pos.z * q0 * vec.z - - -2.0 * pos.y * q3 * vec.x - +2.0 * pos.z * q2 * vec.x - - +2.0 * pos.x * q3 * vec.y - -2.0 * pos.z * q1 * vec.y - - -2.0 * pos.x * q2 * vec.z - +2.0 * pos.y * q1 * vec.z; - - - result.q1 = +2.0 * pos.x * q1 * vec.x - -2.0 * pos.y * q1 * vec.y - -2.0 * pos.z * q1 * vec.z - - +2.0 * pos.y * q2 * vec.x - +2.0 * pos.z * q3 * vec.x - - +2.0 * pos.x * q2 * vec.y - -2.0 * pos.z * q0 * vec.y - - +2.0 * pos.x * q3 * vec.z - +2.0 * pos.y * q0 * vec.z; - - - result.q2 = -2.0 * pos.x * q2 * vec.x - +2.0 * pos.y * q2 * vec.y - -2.0 * pos.z * q2 * vec.z - - +2.0 * pos.y * q1 * vec.x - +2.0 * pos.z * q0 * vec.x - - +2.0 * pos.x * q1 * vec.y - +2.0 * pos.z * q3 * vec.y - - -2.0 * pos.x * q0 * vec.z - +2.0 * pos.y * q3 * vec.z; - - - result.q3 = -2.0 * pos.x * q3 * vec.x - -2.0 * pos.y * q3 * vec.y - +2.0 * pos.z * q3 * vec.z - - -2.0 * pos.y * q0 * vec.x - +2.0 * pos.z * q1 * vec.x - - +2.0 * pos.x * q0 * vec.y - +2.0 * pos.z * q2 * vec.y - - +2.0 * pos.x * q1 * vec.z - +2.0 * pos.y * q2 * vec.z; - - return result; -} - #ifdef COLVARS_LAMMPS namespace { inline void *new_Jacobi_solver(int size) { @@ -336,7 +271,7 @@ void colvarmodule::rotation::compute_overlap_matrix() #ifndef COLVARS_LAMMPS namespace NR { -void diagonalize_matrix(cvm::real m[4][4], +int diagonalize_matrix(cvm::real m[4][4], cvm::real eigval[4], cvm::real eigvec[4][4]) { @@ -347,9 +282,7 @@ void diagonalize_matrix(cvm::real m[4][4], int jac_nrot = 0; if (NR_Jacobi::jacobi(m, eigval, eigvec, &jac_nrot) != COLVARS_OK) { - cvm::error("Too many iterations in jacobi diagonalization.\n" - "This is usually the result of an ill-defined set of atoms for " - "rotational alignment (RMSD, rotateReference, etc).\n"); + return COLVARS_ERROR; } NR_Jacobi::eigsrt(eigval, eigvec); // jacobi saves eigenvectors by columns @@ -367,6 +300,7 @@ void diagonalize_matrix(cvm::real m[4][4], eigvec[ie][i] /= norm; } } + return COLVARS_OK; } } @@ -429,14 +363,25 @@ void colvarmodule::rotation::calc_optimal_rotation_impl() { cvm::real[4][4]> *>(jacobi); int ierror = ecalc->Diagonalize(S, S_eigval, S_eigvec); +#else + int ierror = NR::diagonalize_matrix(S, S_eigval, S_eigvec); +#endif if (ierror) { + cvm::log("Failed to diagonalize the following overlapping matrix:\n"); + for (size_t i = 0; i < 4; ++i) { + for (size_t j = 0; j < 4; ++j) { + cvm::log(cvm::to_str(S[i][j]) + " "); + } + cvm::log("\n"); + } + cvm::log("The corresponding correlation matrix is:\n"); + cvm::log(" " + cvm::to_str(C.xx) + " " + cvm::to_str(C.xy) + " " + cvm::to_str(C.xz)); + cvm::log(" " + cvm::to_str(C.yx) + " " + cvm::to_str(C.yy) + " " + cvm::to_str(C.yz)); + cvm::log(" " + cvm::to_str(C.zx) + " " + cvm::to_str(C.zy) + " " + cvm::to_str(C.zz) + "\n"); cvm::error("Too many iterations in jacobi diagonalization.\n" "This is usually the result of an ill-defined set of atoms for " "rotational alignment (RMSD, rotateReference, etc).\n"); } -#else - NR::diagonalize_matrix(S, S_eigval, S_eigvec); -#endif q = cvm::quaternion{S_eigvec[0][0], S_eigvec[0][1], S_eigvec[0][2], S_eigvec[0][3]}; if (cvm::rotation::monitor_crossings) { diff --git a/lib/colvars/colvartypes.h b/lib/colvars/colvartypes.h index 455e628f1b..db5827990b 100644 --- a/lib/colvars/colvartypes.h +++ b/lib/colvars/colvartypes.h @@ -20,10 +20,6 @@ #include "colvarmodule.h" -#ifndef PI -#define PI 3.14159265358979323846 -#endif - // ---------------------------------------------------------------------- /// Linear algebra functions and data types used in the collective /// variables implemented so far @@ -1221,8 +1217,57 @@ public: /// \brief Multiply the given vector by the derivative of the given /// (rotated) position with respect to the quaternion - cvm::quaternion position_derivative_inner(cvm::rvector const &pos, - cvm::rvector const &vec) const; + /// \param pos The position \f$\mathbf{x}\f$. + /// \param vec The vector \f$\mathbf{v}\f$. + /// \return A quaternion (see the detailed documentation below). + /// + /// This function is mainly used for projecting the gradients or forces on + /// the rotated atoms to the forces on quaternion. Assume this rotation can + /// be represented as \f$R(\mathbf{q})\f$, + /// where \f$\mathbf{q} := (q_0, q_1, q_2, q_3)\f$ + /// is the current quaternion, the function returns the following new + /// quaternion: + /// \f[ + /// \left(\mathbf{v}^\mathrm{T}\frac{\partial R(\mathbf{q})}{\partial q_0}\mathbf{x}, + /// \mathbf{v}^\mathrm{T}\frac{\partial R(\mathbf{q})}{\partial q_1}\mathbf{x}, + /// \mathbf{v}^\mathrm{T}\frac{\partial R(\mathbf{q})}{\partial q_2}\mathbf{x}, + /// \mathbf{v}^\mathrm{T}\frac{\partial R(\mathbf{q})}{\partial q_3}\mathbf{x}\right) + /// \f] + /// where \f$\mathbf{v}\f$ is usually the gradient of \f$\xi\f$ with respect to + /// the rotated frame \f$\tilde{\mathbf{X}}\f$, + /// \f$\partial \xi / \partial \tilde{\mathbf{X}}\f$, or the force acting on it + /// (\f$\mathbf{F}_{\tilde{\mathbf{X}}}\f$). + /// By using the following loop in pseudo C++ code, + /// either \f$\partial \xi / \partial \tilde{\mathbf{X}}\f$ + /// or \f$\mathbf{F}_{\tilde{\mathbf{X}}}\f$, can be projected to + /// \f$\partial \xi / \partial \mathbf{q}\f$ or \f$\mathbf{F}_q\f$ into `sum_dxdq`: + /// @code + /// cvm::real sum_dxdq[4] = {0, 0, 0, 0}; + /// for (size_t i = 0; i < main_group_size(); ++i) { + /// const cvm::rvector v = grad_or_force_on_rotated_main_group(i); + /// const cvm::rvector x = unrotated_main_group_positions(i); + /// cvm::quaternion const dxdq = position_derivative_inner(x, v); + /// sum_dxdq[0] += dxdq[0]; + /// sum_dxdq[1] += dxdq[1]; + /// sum_dxdq[2] += dxdq[2]; + /// sum_dxdq[3] += dxdq[3]; + /// } + /// @endcode + inline cvm::quaternion position_derivative_inner(cvm::rvector const &pos, + cvm::rvector const &vec) const { + return cvm::quaternion(2.0 * (vec.x * ( q0 * pos.x - q3 * pos.y + q2 * pos.z) + + vec.y * ( q3 * pos.x + q0 * pos.y - q1 * pos.z) + + vec.z * (-q2 * pos.x + q1 * pos.y + q0 * pos.z)), + 2.0 * (vec.x * ( q1 * pos.x + q2 * pos.y + q3 * pos.z) + + vec.y * ( q2 * pos.x - q1 * pos.y - q0 * pos.z) + + vec.z * ( q3 * pos.x + q0 * pos.y - q1 * pos.z)), + 2.0 * (vec.x * (-q2 * pos.x + q1 * pos.y + q0 * pos.z) + + vec.y * ( q1 * pos.x + q2 * pos.y + q3 * pos.z) + + vec.z * (-q0 * pos.x + q3 * pos.y - q2 * pos.z)), + 2.0 * (vec.x * (-q3 * pos.x - q0 * pos.y + q1 * pos.z) + + vec.y * ( q0 * pos.x - q3 * pos.y + q2 * pos.z) + + vec.z * ( q1 * pos.x + q2 * pos.y + q3 * pos.z))); + } /// \brief Return the cosine between the orientation frame @@ -1301,7 +1346,7 @@ public: #ifndef COLVARS_LAMMPS namespace NR { -void diagonalize_matrix(cvm::real m[4][4], +int diagonalize_matrix(cvm::real m[4][4], cvm::real eigval[4], cvm::real eigvec[4][4]); } diff --git a/lib/colvars/colvarvalue.cpp b/lib/colvars/colvarvalue.cpp index 3b8077d2e7..66baf35eeb 100644 --- a/lib/colvars/colvarvalue.cpp +++ b/lib/colvars/colvarvalue.cpp @@ -153,29 +153,6 @@ std::string const colvarvalue::type_keyword(Type t) } -size_t colvarvalue::num_df(Type t) -{ - switch (t) { - case colvarvalue::type_notset: - default: - return 0; break; - case colvarvalue::type_scalar: - return 1; break; - case colvarvalue::type_3vector: - return 3; break; - case colvarvalue::type_unit3vector: - case colvarvalue::type_unit3vectorderiv: - return 2; break; - case colvarvalue::type_quaternion: - case colvarvalue::type_quaternionderiv: - return 3; break; - case colvarvalue::type_vector: - // the size of a vector is unknown without its object - return 0; break; - } -} - - size_t colvarvalue::num_dimensions(Type t) { switch (t) { @@ -591,34 +568,132 @@ cvm::real operator * (colvarvalue const &x1, } +cvm::real colvarvalue::norm2() const +{ + switch (value_type) { + case colvarvalue::type_scalar: + return (this->real_value)*(this->real_value); + case colvarvalue::type_3vector: + case colvarvalue::type_unit3vector: + case colvarvalue::type_unit3vectorderiv: + return (this->rvector_value).norm2(); + case colvarvalue::type_quaternion: + case colvarvalue::type_quaternionderiv: + return (this->quaternion_value).norm2(); + case colvarvalue::type_vector: + if (elem_types.size() > 0) { + // if we have information about non-scalar types, use it + cvm::real result = 0.0; + size_t i; + for (i = 0; i < elem_types.size(); i++) { + result += (this->get_elem(i)).norm2(); + } + return result; + } else { + return vector1d_value.norm2(); + } + break; + case colvarvalue::type_notset: + default: + return 0.0; + } +} + + +cvm::real colvarvalue::sum() const +{ + switch (value_type) { + case colvarvalue::type_scalar: + return (this->real_value); + case colvarvalue::type_3vector: + case colvarvalue::type_unit3vector: + case colvarvalue::type_unit3vectorderiv: + return (this->rvector_value).x + (this->rvector_value).y + + (this->rvector_value).z; + case colvarvalue::type_quaternion: + case colvarvalue::type_quaternionderiv: + return (this->quaternion_value).q0 + (this->quaternion_value).q1 + + (this->quaternion_value).q2 + (this->quaternion_value).q3; + case colvarvalue::type_vector: + return (this->vector1d_value).sum(); + case colvarvalue::type_notset: + default: + return 0.0; + } +} + + +cvm::real colvarvalue::dist2(colvarvalue const &x2) const +{ + colvarvalue::check_types(*this, x2); + + switch (this->type()) { + case colvarvalue::type_scalar: + return (this->real_value - x2.real_value) * (this->real_value - x2.real_value); + case colvarvalue::type_3vector: + return (this->rvector_value - x2.rvector_value).norm2(); + case colvarvalue::type_unit3vector: { + cvm::rvector const &v1 = this->rvector_value; + cvm::rvector const &v2 = x2.rvector_value; + cvm::real const theta = cvm::acos(v1 * v2); + return theta * theta; + } + case colvarvalue::type_quaternion: + // angle between (*this) and x2 is the distance, the quaternion + // object has it implemented internally + return this->quaternion_value.dist2(x2.quaternion_value); + case colvarvalue::type_vector: + return (this->vector1d_value - x2.vector1d_value).norm2(); + case colvarvalue::type_unit3vectorderiv: + case colvarvalue::type_quaternionderiv: + cvm::error("Error: computing a squared-distance between two variables of type \"" + + type_desc(this->type()) + "\", for which it is not defined.\n", + COLVARS_BUG_ERROR); + case colvarvalue::type_notset: + default: + this->undef_op(); + return 0.0; + }; + + return 0.0; +} + + colvarvalue colvarvalue::dist2_grad(colvarvalue const &x2) const { colvarvalue::check_types(*this, x2); + // Compute derivative with respect to (*this) + switch (this->value_type) { case colvarvalue::type_scalar: return 2.0 * (this->real_value - x2.real_value); case colvarvalue::type_3vector: return 2.0 * (this->rvector_value - x2.rvector_value); - case colvarvalue::type_unit3vector: - case colvarvalue::type_unit3vectorderiv: - { - cvm::rvector const &v1 = this->rvector_value; - cvm::rvector const &v2 = x2.rvector_value; - cvm::real const cos_t = v1 * v2; - return colvarvalue(2.0 * (cos_t * v1 - v2), colvarvalue::type_unit3vectorderiv); - } + case colvarvalue::type_unit3vector: { + cvm::rvector const &v1 = this->rvector_value; + cvm::rvector const &v2 = x2.rvector_value; + cvm::real const cos_t = v1 * v2; + return colvarvalue(2.0 * cvm::acos(cos_t) * -1.0 / cvm::sqrt(1.0 - cos_t * cos_t) * v2, + colvarvalue::type_unit3vectorderiv); + } case colvarvalue::type_quaternion: - case colvarvalue::type_quaternionderiv: return this->quaternion_value.dist2_grad(x2.quaternion_value); case colvarvalue::type_vector: return colvarvalue(2.0 * (this->vector1d_value - x2.vector1d_value), colvarvalue::type_vector); break; + case colvarvalue::type_unit3vectorderiv: + case colvarvalue::type_quaternionderiv: + cvm::error("Error: computing a squared-distance gradient between two variables of type \"" + + type_desc(this->type()) + "\", for which it is not defined.\n", + COLVARS_BUG_ERROR); case colvarvalue::type_notset: default: this->undef_op(); return colvarvalue(colvarvalue::type_notset); }; + + return colvarvalue(colvarvalue::type_notset); } diff --git a/lib/colvars/colvarvalue.h b/lib/colvars/colvarvalue.h index e8a6a849d3..61f1bf718b 100644 --- a/lib/colvars/colvarvalue.h +++ b/lib/colvars/colvarvalue.h @@ -109,9 +109,6 @@ public: /// User keywords for specifying value types in the configuration static std::string const type_keyword(Type t); - /// Number of degrees of freedom for each supported type - static size_t num_df(Type t); - /// Number of dimensions for each supported type (used to allocate vector1d_value) static size_t num_dimensions(Type t); @@ -671,87 +668,4 @@ inline cvm::vector1d const colvarvalue::as_vector() const } -inline cvm::real colvarvalue::norm2() const -{ - switch (value_type) { - case colvarvalue::type_scalar: - return (this->real_value)*(this->real_value); - case colvarvalue::type_3vector: - case colvarvalue::type_unit3vector: - case colvarvalue::type_unit3vectorderiv: - return (this->rvector_value).norm2(); - case colvarvalue::type_quaternion: - case colvarvalue::type_quaternionderiv: - return (this->quaternion_value).norm2(); - case colvarvalue::type_vector: - if (elem_types.size() > 0) { - // if we have information about non-scalar types, use it - cvm::real result = 0.0; - size_t i; - for (i = 0; i < elem_types.size(); i++) { - result += (this->get_elem(i)).norm2(); - } - return result; - } else { - return vector1d_value.norm2(); - } - break; - case colvarvalue::type_notset: - default: - return 0.0; - } -} - - -inline cvm::real colvarvalue::sum() const -{ - switch (value_type) { - case colvarvalue::type_scalar: - return (this->real_value); - case colvarvalue::type_3vector: - case colvarvalue::type_unit3vector: - case colvarvalue::type_unit3vectorderiv: - return (this->rvector_value).x + (this->rvector_value).y + - (this->rvector_value).z; - case colvarvalue::type_quaternion: - case colvarvalue::type_quaternionderiv: - return (this->quaternion_value).q0 + (this->quaternion_value).q1 + - (this->quaternion_value).q2 + (this->quaternion_value).q3; - case colvarvalue::type_vector: - return (this->vector1d_value).sum(); - case colvarvalue::type_notset: - default: - return 0.0; - } -} - - -inline cvm::real colvarvalue::dist2(colvarvalue const &x2) const -{ - colvarvalue::check_types(*this, x2); - - switch (this->type()) { - case colvarvalue::type_scalar: - return (this->real_value - x2.real_value)*(this->real_value - x2.real_value); - case colvarvalue::type_3vector: - return (this->rvector_value - x2.rvector_value).norm2(); - case colvarvalue::type_unit3vector: - case colvarvalue::type_unit3vectorderiv: - // angle between (*this) and x2 is the distance - return cvm::acos(this->rvector_value * x2.rvector_value) * cvm::acos(this->rvector_value * x2.rvector_value); - case colvarvalue::type_quaternion: - case colvarvalue::type_quaternionderiv: - // angle between (*this) and x2 is the distance, the quaternion - // object has it implemented internally - return this->quaternion_value.dist2(x2.quaternion_value); - case colvarvalue::type_vector: - return (this->vector1d_value - x2.vector1d_value).norm2(); - case colvarvalue::type_notset: - default: - this->undef_op(); - return 0.0; - }; -} - - #endif diff --git a/lib/gpu/lal_eam.cpp b/lib/gpu/lal_eam.cpp index 0a2ed21ab3..08b5f7e9b7 100644 --- a/lib/gpu/lal_eam.cpp +++ b/lib/gpu/lal_eam.cpp @@ -61,7 +61,7 @@ int EAMT::init(const int ntypes, double host_cutforcesq, int **host_type2rhor, if (onetype>0) onetype=-1; else if (onetype==0) - onetype=i*max_shared_types+i; + onetype=i; } if (onetype<0) onetype=0; #endif @@ -109,7 +109,7 @@ int EAMT::init(const int ntypes, double host_cutforcesq, int **host_type2rhor, int lj_types=ntypes; shared_types=false; - if (lj_types<=max_shared_types && this->_block_size>=max_shared_types) { + if (lj_types<=max_shared_types && this->_block_size>=max_shared_types*max_shared_types) { lj_types=max_shared_types; shared_types=true; } diff --git a/lib/scafacos/Install.py b/lib/scafacos/Install.py index 28bcf43086..9766d4fc1e 100644 --- a/lib/scafacos/Install.py +++ b/lib/scafacos/Install.py @@ -16,11 +16,12 @@ parser = ArgumentParser(prog='Install.py', description="LAMMPS library build wra # settings -version = "1.0.1" +version = "1.0.4" # known checksums for different ScaFaCoS versions. used to validate the download. checksums = { \ - '1.0.1' : 'bd46d74e3296bd8a444d731bb10c1738' \ + '1.0.1' : 'bd46d74e3296bd8a444d731bb10c1738', \ + '1.0.4' : '23867540ec32e63ce71d6ecc105278d2', \ } # extra help message diff --git a/lib/voronoi/voro-make.patch b/lib/voronoi/voro-make.patch index f51bd08614..f2811e3adb 100644 --- a/lib/voronoi/voro-make.patch +++ b/lib/voronoi/voro-make.patch @@ -1,5 +1,35 @@ ---- src/Makefile.orig 2020-05-03 03:50:23.501557199 -0400 -+++ src/Makefile 2020-05-03 03:53:32.147681674 -0400 +--- Makefile.orig 2025-06-04 12:16:01.056286325 -0400 ++++ Makefile 2025-06-04 12:18:47.454879006 -0400 +@@ -11,8 +11,7 @@ + + # Build all of the executable files + all: +- $(MAKE) -C src +- $(MAKE) -C examples ++ $(MAKE) -C src depend libvoro++.a + + # Build the help files (with Doxygen) + help: +@@ -24,16 +23,12 @@ + $(MAKE) -C examples clean + + # Install the executable, man page, and shared library +-install: +- $(MAKE) -C src +- $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/bin ++install: all + $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/lib + $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/man + $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/man/man1 + $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/include + $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/include/voro++ +- $(INSTALL) $(IFLAGS_EXEC) src/voro++ $(PREFIX)/bin +- $(INSTALL) $(IFLAGS) man/voro++.1 $(PREFIX)/man/man1 + $(INSTALL) $(IFLAGS) src/libvoro++.a $(PREFIX)/lib + $(INSTALL) $(IFLAGS) src/voro++.hh $(PREFIX)/include/voro++ + $(INSTALL) $(IFLAGS) src/c_loops.hh $(PREFIX)/include/voro++ +--- src/Makefile.orig 2013-10-17 13:54:13.000000000 -0400 ++++ src/Makefile 2025-06-04 12:16:47.293104880 -0400 @@ -10,10 +10,10 @@ # List of the common source files objs=cell.o common.o container.o unitcell.o v_compute.o c_loops.o \ diff --git a/src/.gitignore b/src/.gitignore index 5debdebc50..c39dfbdfeb 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -875,6 +875,8 @@ /fix_freeze.h /fix_gcmc.cpp /fix_gcmc.h +/fix_gjf.cpp +/fix_gjf.h /fix_gld.cpp /fix_gld.h /fix_gle.cpp @@ -924,6 +926,8 @@ /fix_msst.h /fix_neb.cpp /fix_neb.h +/fix_neighbor_swap.cpp +/fix_neighbor_swap.h /fix_nh_asphere.cpp /fix_nh_asphere.h /fix_nph_asphere.cpp @@ -1801,4 +1805,6 @@ /pair_smtbq.h /pair_vashishta*.cpp /pair_vashishta*.h +/pair_lj_pirani.cpp +/pair_lj_pirani.h diff --git a/src/AMOEBA/angle_amoeba.cpp b/src/AMOEBA/angle_amoeba.cpp index e2d26dd047..bf3bc179bc 100644 --- a/src/AMOEBA/angle_amoeba.cpp +++ b/src/AMOEBA/angle_amoeba.cpp @@ -834,13 +834,13 @@ double AngleAmoeba::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/BPM/bond_bpm.cpp b/src/BPM/bond_bpm.cpp index 284626464e..c47614afff 100644 --- a/src/BPM/bond_bpm.cpp +++ b/src/BPM/bond_bpm.cpp @@ -352,7 +352,7 @@ double BondBPM::equilibrium_distance(int /*i*/) delx = x[i][0] - x[j][0]; dely = x[i][1] - x[j][1]; delz = x[i][2] - x[j][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); r = sqrt(delx * delx + dely * dely + delz * delz); if (r > r0_max_estimate) r0_max_estimate = r; diff --git a/src/BPM/bond_bpm_rotational.cpp b/src/BPM/bond_bpm_rotational.cpp index b1e6163d97..0e8f822a6d 100644 --- a/src/BPM/bond_bpm_rotational.cpp +++ b/src/BPM/bond_bpm_rotational.cpp @@ -177,7 +177,7 @@ void BondBPMRotational::store_data() } // Get closest image in case bonded with ghost - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); r = sqrt(delx * delx + dely * dely + delz * delz); rinv = 1.0 / r; diff --git a/src/BPM/bond_bpm_spring.cpp b/src/BPM/bond_bpm_spring.cpp index a5c31ea1b2..f5094ffbcb 100644 --- a/src/BPM/bond_bpm_spring.cpp +++ b/src/BPM/bond_bpm_spring.cpp @@ -140,7 +140,7 @@ void BondBPMSpring::store_data() delz = x[i][2] - x[j][2]; // Get closest image in case bonded with ghost - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); r = sqrt(delx * delx + dely * dely + delz * delz); fix_bond_history->update_atom_value(i, m, 0, r); diff --git a/src/BPM/bond_bpm_spring_plastic.cpp b/src/BPM/bond_bpm_spring_plastic.cpp index 21ef0f12fb..8ef8ef63c7 100644 --- a/src/BPM/bond_bpm_spring_plastic.cpp +++ b/src/BPM/bond_bpm_spring_plastic.cpp @@ -148,7 +148,7 @@ void BondBPMSpringPlastic::store_data() delz = x[i][2] - x[j][2]; // Get closest image in case bonded with ghost - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); r = sqrt(delx * delx + dely * dely + delz * delz); fix_bond_history->update_atom_value(i, m, 0, r); diff --git a/src/CG-SPICA/angle_spica.cpp b/src/CG-SPICA/angle_spica.cpp index 08e4217483..5f198f6d76 100644 --- a/src/CG-SPICA/angle_spica.cpp +++ b/src/CG-SPICA/angle_spica.cpp @@ -458,13 +458,13 @@ double AngleSPICA::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; @@ -479,7 +479,7 @@ double AngleSPICA::single(int type, int i1, int i2, int i3) double delx3 = x[i1][0] - x[i3][0]; double dely3 = x[i1][1] - x[i3][1]; double delz3 = x[i1][2] - x[i3][2]; - domain->minimum_image(delx3,dely3,delz3); + domain->minimum_image(FLERR, delx3,dely3,delz3); const int type1 = atom->type[i1]; const int type3 = atom->type[i3]; diff --git a/src/CLASS2/angle_class2.cpp b/src/CLASS2/angle_class2.cpp index 04b7a9238c..7d345dac85 100644 --- a/src/CLASS2/angle_class2.cpp +++ b/src/CLASS2/angle_class2.cpp @@ -436,13 +436,13 @@ double AngleClass2::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/CLASS2/dihedral_class2.cpp b/src/CLASS2/dihedral_class2.cpp index 9c4c1ad871..3ca8c52717 100644 --- a/src/CLASS2/dihedral_class2.cpp +++ b/src/CLASS2/dihedral_class2.cpp @@ -946,3 +946,18 @@ void DihedralClass2::write_data(FILE *fp) at_theta0_1[i]*180.0/MY_PI,at_theta0_2[i]*180.0/MY_PI); } +/* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralClass2::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "k1") == 0) return (void *) k1; + if (strcmp(str, "k2") == 0) return (void *) k2; + if (strcmp(str, "k3") == 0) return (void *) k3; + if (strcmp(str, "phi1") == 0) return (void *) phi1; + if (strcmp(str, "phi2") == 0) return (void *) phi2; + if (strcmp(str, "phi3") == 0) return (void *) phi3; + return nullptr; + } diff --git a/src/CLASS2/dihedral_class2.h b/src/CLASS2/dihedral_class2.h index ad42c5c3a1..d87dfb8a7b 100644 --- a/src/CLASS2/dihedral_class2.h +++ b/src/CLASS2/dihedral_class2.h @@ -33,6 +33,7 @@ class DihedralClass2 : public Dihedral { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k1, *k2, *k3; diff --git a/src/COLVARS/colvarproxy_lammps.cpp b/src/COLVARS/colvarproxy_lammps.cpp index 265dc34f43..29b9cbfcd0 100644 --- a/src/COLVARS/colvarproxy_lammps.cpp +++ b/src/COLVARS/colvarproxy_lammps.cpp @@ -33,12 +33,9 @@ colvarproxy_lammps::colvarproxy_lammps(LAMMPS_NS::LAMMPS *lmp) : _lmp(lmp), _ra previous_step = -1; do_exit = false; - inter_me = 0; - inter_num = 1; bias_energy = 0.0; engine_ready_ = false; - inter_comm = MPI_COMM_NULL; } /* ---------------------------------------------------------------------- */ @@ -83,19 +80,6 @@ void colvarproxy_lammps::set_random_seed(int seed) _random = new LAMMPS_NS::RanPark(_lmp, seed); } -/* ---------------------------------------------------------------------- */ - -void colvarproxy_lammps::set_replicas_communicator(MPI_Comm root2root) -{ - inter_comm = root2root; - - // initialize multi-replica support, if available - if (replica_enabled() == COLVARS_OK) { - MPI_Comm_rank(inter_comm, &inter_me); - MPI_Comm_size(inter_comm, &inter_num); - } -} - /* ---------------------------------------------------------------------- re-initialize data where needed ------------------------------------------------------------------------- */ @@ -204,7 +188,7 @@ cvm::rvector colvarproxy_lammps::position_distance(cvm::atom_pos const &pos1, double xtmp = pos2.x - pos1.x; double ytmp = pos2.y - pos1.y; double ztmp = pos2.z - pos1.z; - _lmp->domain->minimum_image_big(xtmp,ytmp,ztmp); + _lmp->domain->minimum_image_big(FLERR, xtmp,ytmp,ztmp); return {xtmp, ytmp, ztmp}; } @@ -255,63 +239,7 @@ int colvarproxy_lammps::set_unit_system(std::string const &units_in, bool /*chec return COLVARS_OK; } -/* ---------------------------------------------------------------------- - multi-replica support -------------------------------------------------------------------------- */ -int colvarproxy_lammps::replica_enabled() -{ - return (inter_comm != MPI_COMM_NULL) ? COLVARS_OK : COLVARS_NOT_IMPLEMENTED; -} - -/* ---------------------------------------------------------------------- */ - -int colvarproxy_lammps::replica_index() -{ - return inter_me; -} - -/* ---------------------------------------------------------------------- */ - -int colvarproxy_lammps::num_replicas() -{ - return inter_num; -} - -/* ---------------------------------------------------------------------- */ - -void colvarproxy_lammps::replica_comm_barrier() -{ - MPI_Barrier(inter_comm); -} - -/* ---------------------------------------------------------------------- */ - -int colvarproxy_lammps::replica_comm_recv(char* msg_data, int buf_len, int src_rep) -{ - MPI_Status status; - int retval; - - retval = MPI_Recv(msg_data,buf_len,MPI_CHAR,src_rep,0,inter_comm,&status); - if (retval == MPI_SUCCESS) { - MPI_Get_count(&status, MPI_CHAR, &retval); - } else retval = 0; - return retval; -} - -/* ---------------------------------------------------------------------- */ - -int colvarproxy_lammps::replica_comm_send(char* msg_data, int msg_len, int dest_rep) -{ - int retval; - retval = MPI_Send(msg_data,msg_len,MPI_CHAR,dest_rep,0,inter_comm); - if (retval == MPI_SUCCESS) { - retval = msg_len; - } else retval = 0; - return retval; -} - -/* ---------------------------------------------------------------------- */ int colvarproxy_lammps::check_atom_id(int atom_number) { diff --git a/src/COLVARS/colvarproxy_lammps.h b/src/COLVARS/colvarproxy_lammps.h index d98be37b09..06bda4252e 100644 --- a/src/COLVARS/colvarproxy_lammps.h +++ b/src/COLVARS/colvarproxy_lammps.h @@ -45,9 +45,6 @@ class colvarproxy_lammps : public colvarproxy { std::vector atoms_types; - MPI_Comm inter_comm; // MPI comm with 1 root proc from each world - int inter_me, inter_num; // rank for the inter replica comm - public: friend class cvm::atom; @@ -59,9 +56,6 @@ class colvarproxy_lammps : public colvarproxy { /// Set the internal seed used by \link rand_gaussian() \endlink void set_random_seed(int seed); - /// Set the multiple replicas communicator - void set_replicas_communicator(MPI_Comm root2root); - int setup() override; // disable default and copy constructor @@ -72,7 +66,8 @@ class colvarproxy_lammps : public colvarproxy { // methods for lammps to move data or trigger actions in the proxy public: bool total_forces_enabled() const override { return total_force_requested; }; - bool total_forces_same_step() const override { return true; }; + // Total forces are saved at end of step, only processed at the next step + bool total_forces_same_step() const override { return false; }; bool want_exit() const { return do_exit; }; // perform colvars computation. returns biasing energy @@ -102,14 +97,6 @@ class colvarproxy_lammps : public colvarproxy { int check_atom_id(int atom_number) override; inline std::vector *modify_atom_types() { return &atoms_types; } - - int replica_enabled() override; - int replica_index() override; - int num_replicas() override; - - void replica_comm_barrier() override; - int replica_comm_recv(char *msg_data, int buf_len, int src_rep) override; - int replica_comm_send(char *msg_data, int msg_len, int dest_rep) override; }; #endif diff --git a/src/COLVARS/colvarproxy_lammps_version.h b/src/COLVARS/colvarproxy_lammps_version.h index 5901044b1e..1c16217679 100644 --- a/src/COLVARS/colvarproxy_lammps_version.h +++ b/src/COLVARS/colvarproxy_lammps_version.h @@ -1,3 +1,3 @@ #ifndef COLVARPROXY_VERSION -#define COLVARPROXY_VERSION "2024-07-05" +#define COLVARPROXY_VERSION "2025-03-31" #endif diff --git a/src/COLVARS/fix_colvars.cpp b/src/COLVARS/fix_colvars.cpp index d5a8806eed..247ad2ef8b 100644 --- a/src/COLVARS/fix_colvars.cpp +++ b/src/COLVARS/fix_colvars.cpp @@ -267,6 +267,7 @@ void FixColvars::init() if (init_flag) return; init_flag = 1; +#if defined(COLVARS_MPI) if (universe->nworlds > 1) { // create inter root communicator int color = 1; @@ -275,9 +276,10 @@ void FixColvars::init() } MPI_Comm_split(universe->uworld, color, universe->iworld, &root2root); if (me == 0) { - proxy->set_replicas_communicator(root2root); + proxy->set_replicas_mpi_communicator(root2root); } } +#endif } diff --git a/src/DIELECTRIC/fix_polarize_functional.cpp b/src/DIELECTRIC/fix_polarize_functional.cpp index dd0c0eb648..2d2b1cb35e 100644 --- a/src/DIELECTRIC/fix_polarize_functional.cpp +++ b/src/DIELECTRIC/fix_polarize_functional.cpp @@ -652,7 +652,7 @@ void FixPolarizeFunctional::calculate_Rww_cutoff() double delx = xtmp - x[k][0]; double dely = ytmp - x[k][1]; double delz = ztmp - x[k][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); int mk = tag2mat[tag[k]]; // G1ww[mi][mk] = calculate_greens_ewald(delx, dely, delz); @@ -861,7 +861,7 @@ void FixPolarizeFunctional::calculate_qiRqw_cutoff() delx = xtmp - x[k][0]; dely = ytmp - x[k][1]; delz = ztmp - x[k][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); r = sqrt(delx * delx + dely * dely + delz * delz); int mk = tag2mat[tag[k]]; @@ -902,7 +902,7 @@ void FixPolarizeFunctional::calculate_qiRqw_cutoff() delx = x[i][0] - xtmp; dely = x[i][1] - ytmp; delz = x[i][2] - ztmp; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); int mi = tag2mat_ions[tag[i]]; //ion_idx[i]; diff --git a/src/DIELECTRIC/pppm_dielectric.cpp b/src/DIELECTRIC/pppm_dielectric.cpp index e5b0c5abb1..40ebbe4794 100644 --- a/src/DIELECTRIC/pppm_dielectric.cpp +++ b/src/DIELECTRIC/pppm_dielectric.cpp @@ -282,7 +282,7 @@ void PPPMDielectric::qsum_qsq(int warning_flag) double qsqsume; #if defined(_OPENMP) -#pragma omp parallel for default(shared) reduction(+:qsum_local,qsqsum_local) +#pragma omp parallel for default(shared) reduction(+:qsum_local,qsqsum_local,qsqsume_local) #endif for (int i = 0; i < nlocal; i++) { qsum_local += q[i]; diff --git a/src/DIELECTRIC/pppm_disp_dielectric.cpp b/src/DIELECTRIC/pppm_disp_dielectric.cpp index 052b617351..e0652195b7 100644 --- a/src/DIELECTRIC/pppm_disp_dielectric.cpp +++ b/src/DIELECTRIC/pppm_disp_dielectric.cpp @@ -556,7 +556,7 @@ void PPPMDispDielectric::qsum_qsq(int warning_flag) double qsqsume; #if defined(_OPENMP) -#pragma omp parallel for default(shared) reduction(+:qsum_local,qsqsum_local) +#pragma omp parallel for default(shared) reduction(+:qsum_local,qsqsum_local,qsqsume_local) #endif for (int i = 0; i < nlocal; i++) { qsum_local += q[i]; diff --git a/src/DIPOLE/angle_dipole.cpp b/src/DIPOLE/angle_dipole.cpp index 530f23f844..00e55bbbcc 100644 --- a/src/DIPOLE/angle_dipole.cpp +++ b/src/DIPOLE/angle_dipole.cpp @@ -251,7 +251,7 @@ double AngleDipole::single(int type, int iRef, int iDip, int /*iDummy*/) double dely = x[iRef][1] - x[iDip][1]; double delz = x[iRef][2] - x[iDip][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); double r = sqrt(delx * delx + dely * dely + delz * delz); if (r < SMALL) return 0.0; diff --git a/src/DPD-REACT/npair_half_bin_newton_ssa.cpp b/src/DPD-REACT/npair_half_bin_newton_ssa.cpp index 7393e54f78..850330aeaa 100644 --- a/src/DPD-REACT/npair_half_bin_newton_ssa.cpp +++ b/src/DPD-REACT/npair_half_bin_newton_ssa.cpp @@ -99,12 +99,12 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) MyPage *ipage = list->ipage; auto ns_ssa = dynamic_cast(ns); - if (!ns_ssa) error->one(FLERR, "NStencil wasn't a NStencilSSA object"); + if (!ns_ssa) error->one(FLERR, Error::NOLASTLINE, "NStencil wasn't a NStencilSSA object"); int *nstencil_ssa = &(ns_ssa->nstencil_ssa[0]); int nstencil_full = ns_ssa->nstencil; auto nb_ssa = dynamic_cast(nb); - if (!nb_ssa) error->one(FLERR, "NBin wasn't a NBinSSA object"); + if (!nb_ssa) error->one(FLERR, Error::NOLASTLINE, "NBin wasn't a NBinSSA object"); int *bins = nb_ssa->bins; int *binhead = nb_ssa->binhead; int *gairhead_ssa = &(nb_ssa->gairhead_ssa[0]); @@ -160,7 +160,7 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) for (zbin = lbinzlo + zoff; zbin < lbinzhi; zbin += sz1) { for (ybin = lbinylo + yoff - ns_ssa->sy; ybin < lbinyhi; ybin += sy1) { for (xbin = lbinxlo + xoff - ns_ssa->sx; xbin < lbinxhi; xbin += sx1) { - if (workItem >= phaseLenEstimate) error->one(FLERR,"phaseLenEstimate was too small"); + if (workItem >= phaseLenEstimate) error->one(FLERR, Error::NOLASTLINE, "phaseLenEstimate was too small"); ssa_itemLoc[workPhase][workItem] = inum; // record where workItem starts in ilist for (int subphase = 0; subphase < 4; subphase++) { @@ -203,10 +203,9 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], - onemols[imol]->nspecial[iatom], - tag[j]-tagprev); + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if (domain->minimum_image_check(delx,dely,delz)) @@ -224,7 +223,7 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) } ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } // record where workItem ends in ilist @@ -240,7 +239,7 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) } } - if (ssa_phaseCt != workPhase) error->one(FLERR,"ssa_phaseCt was wrong"); + if (ssa_phaseCt != workPhase) error->one(FLERR, Error::NOLASTLINE, "ssa_phaseCt was wrong"); list->inum = inum; @@ -286,11 +285,11 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) which = find_special(special[j],nspecial[j],tag[i]); else { int jmol = molindex[j]; - if (jmol >= 0) { + if ((jmol >= 0) && onemols[jmol]->special) { int jatom = molatom[j]; which = find_special(onemols[jmol]->special[jatom], - onemols[jmol]->nspecial[jatom], - tag[i] - (tag[j] - jatom - 1)); + onemols[jmol]->nspecial[jatom], + tag[i] - (tag[j] - jatom - 1)); } else which = 0; } if (which == 0) neighptr[n++] = j; @@ -310,7 +309,7 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) } ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor (ghost) list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor (ghost) list overflow, boost neigh_modify one" + utils::errorurl(36)); } ssa_gitemLen[workPhase][0] = locAIRct; ssa_gphaseLen[workPhase] = 1; diff --git a/src/Depend.sh b/src/Depend.sh index 9ddb29450d..ba55deb62c 100755 --- a/src/Depend.sh +++ b/src/Depend.sh @@ -146,6 +146,7 @@ fi if (test $1 = "MC") then depend MISC + depend VORONOI fi if (test $1 = "MEAM") then diff --git a/src/EXTRA-COMPUTE/compute_born_matrix.cpp b/src/EXTRA-COMPUTE/compute_born_matrix.cpp index 26dcedcf55..c9967f9a46 100644 --- a/src/EXTRA-COMPUTE/compute_born_matrix.cpp +++ b/src/EXTRA-COMPUTE/compute_born_matrix.cpp @@ -764,7 +764,7 @@ void ComputeBornMatrix::compute_bonds() dx = x[atom2][0] - x[atom1][0]; dy = x[atom2][1] - x[atom1][1]; dz = x[atom2][2] - x[atom1][2]; - domain->minimum_image(dx, dy, dz); + domain->minimum_image(FLERR, dx, dy, dz); rsq = dx * dx + dy * dy + dz * dz; rij[0] = dx; rij[1] = dy; @@ -870,7 +870,7 @@ void ComputeBornMatrix::compute_angles() delx1 = x[atom1][0] - x[atom2][0]; dely1 = x[atom1][1] - x[atom2][1]; delz1 = x[atom1][2] - x[atom2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); del1[0] = delx1; del1[1] = dely1; del1[2] = delz1; @@ -882,7 +882,7 @@ void ComputeBornMatrix::compute_angles() delx2 = x[atom3][0] - x[atom2][0]; dely2 = x[atom3][1] - x[atom2][1]; delz2 = x[atom3][2] - x[atom2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); del2[0] = delx2; del2[1] = dely2; del2[2] = delz2; @@ -1046,7 +1046,7 @@ void ComputeBornMatrix::compute_dihedrals() vb1x = x[atom2][0] - x[atom1][0]; vb1y = x[atom2][1] - x[atom1][1]; vb1z = x[atom2][2] - x[atom1][2]; - domain->minimum_image(vb1x, vb1y, vb1z); + domain->minimum_image(FLERR, vb1x, vb1y, vb1z); b1[0] = vb1x; b1[1] = vb1y; b1[2] = vb1z; @@ -1055,7 +1055,7 @@ void ComputeBornMatrix::compute_dihedrals() vb2x = x[atom3][0] - x[atom2][0]; vb2y = x[atom3][1] - x[atom2][1]; vb2z = x[atom3][2] - x[atom2][2]; - domain->minimum_image(vb2x, vb2y, vb2z); + domain->minimum_image(FLERR, vb2x, vb2y, vb2z); b2[0] = vb2x; b2[1] = vb2y; b2[2] = vb2z; @@ -1064,7 +1064,7 @@ void ComputeBornMatrix::compute_dihedrals() vb3x = x[atom4][0] - x[atom3][0]; vb3y = x[atom4][1] - x[atom3][1]; vb3z = x[atom4][2] - x[atom3][2]; - domain->minimum_image(vb3x, vb3y, vb3z); + domain->minimum_image(FLERR, vb3x, vb3y, vb3z); b3[0] = vb3x; b3[1] = vb3y; b3[2] = vb3z; diff --git a/src/EXTRA-COMPUTE/compute_stress_cartesian.cpp b/src/EXTRA-COMPUTE/compute_stress_cartesian.cpp index 9d3bcb92ca..5a59c7a175 100644 --- a/src/EXTRA-COMPUTE/compute_stress_cartesian.cpp +++ b/src/EXTRA-COMPUTE/compute_stress_cartesian.cpp @@ -480,7 +480,7 @@ void ComputeStressCartesian::compute_pressure(double fpair, double xi, double yi tmp1[dir1] = (bin1 + 1) * bin_width1 - xi; else tmp1[dir1] = bin1 * bin_width1 - xi; - domain->minimum_image(tmp1[0],tmp1[1],tmp1[2]); + domain->minimum_image(FLERR, tmp1[0],tmp1[1],tmp1[2]); l1 = tmp1[dir1] / rij1; double l2; @@ -489,7 +489,7 @@ void ComputeStressCartesian::compute_pressure(double fpair, double xi, double yi tmp2[dir2] = (bin2 + 1) * bin_width2 - yi; else tmp2[dir2] = bin2 * bin_width2 - yi; - domain->minimum_image(tmp2[0],tmp2[1],tmp2[2]); + domain->minimum_image(FLERR, tmp2[0],tmp2[1],tmp2[2]); l2 = tmp2[dir2] / rij2; if ((dims == 1 || l1 < l2 || l2 < lb + SMALL) && l1 <= 1.0 && l1 > lb) { diff --git a/src/EXTRA-COMPUTE/compute_stress_mop.cpp b/src/EXTRA-COMPUTE/compute_stress_mop.cpp index 6f96debd40..d362fe657d 100644 --- a/src/EXTRA-COMPUTE/compute_stress_mop.cpp +++ b/src/EXTRA-COMPUTE/compute_stress_mop.cpp @@ -82,7 +82,7 @@ ComputeStressMop::ComputeStressMop(LAMMPS *lmp, int narg, char **arg) : Compute( error->warning(FLERR, "The specified initial plane lies outside of the simulation box"); double dx[3] = {0.0, 0.0, 0.0}; dx[dir] = pos - 0.5 * (domain->boxhi[dir] + domain->boxlo[dir]); - domain->minimum_image(dx[0], dx[1], dx[2]); + domain->minimum_image(FLERR, dx[0], dx[1], dx[2]); pos = 0.5 * (domain->boxhi[dir] + domain->boxlo[dir]) + dx[dir]; if ((pos > domain->boxhi[dir]) || (pos < domain->boxlo[dir])) @@ -478,7 +478,7 @@ void ComputeStressMop::compute_pairs() // minimum image of xi with respect to the plane xi[dir] -= pos; - domain->minimum_image(xi[0], xi[1], xi[2]); + domain->minimum_image(FLERR, xi[0], xi[1], xi[2]); xi[dir] += pos; //velocities at t @@ -601,7 +601,7 @@ void ComputeStressMop::compute_bonds() dx[1] = x[atom1][1]; dx[2] = x[atom1][2]; dx[dir] -= pos; - domain->minimum_image(dx[0], dx[1], dx[2]); + domain->minimum_image(FLERR, dx[0], dx[1], dx[2]); x_bond_1[0] = dx[0]; x_bond_1[1] = dx[1]; x_bond_1[2] = dx[2]; @@ -612,7 +612,7 @@ void ComputeStressMop::compute_bonds() dx[0] = x[atom2][0] - x_bond_1[0]; dx[1] = x[atom2][1] - x_bond_1[1]; dx[2] = x[atom2][2] - x_bond_1[2]; - domain->minimum_image(dx[0], dx[1], dx[2]); + domain->minimum_image(FLERR, dx[0], dx[1], dx[2]); x_bond_2[0] = x_bond_1[0] + dx[0]; x_bond_2[1] = x_bond_1[1] + dx[1]; x_bond_2[2] = x_bond_1[2] + dx[2]; @@ -728,7 +728,7 @@ void ComputeStressMop::compute_angles() dx[1] = x[atom1][1]; dx[2] = x[atom1][2]; dx[dir] -= pos; - domain->minimum_image(dx[0], dx[1], dx[2]); + domain->minimum_image(FLERR, dx[0], dx[1], dx[2]); x_angle_left[0] = dx[0]; x_angle_left[1] = dx[1]; x_angle_left[2] = dx[2]; @@ -739,7 +739,7 @@ void ComputeStressMop::compute_angles() dx_left[0] = x[atom2][0] - x_angle_left[0]; dx_left[1] = x[atom2][1] - x_angle_left[1]; dx_left[2] = x[atom2][2] - x_angle_left[2]; - domain->minimum_image(dx_left[0], dx_left[1], dx_left[2]); + domain->minimum_image(FLERR, dx_left[0], dx_left[1], dx_left[2]); x_angle_middle[0] = x_angle_left[0] + dx_left[0]; x_angle_middle[1] = x_angle_left[1] + dx_left[1]; x_angle_middle[2] = x_angle_left[2] + dx_left[2]; @@ -749,7 +749,7 @@ void ComputeStressMop::compute_angles() dx_right[0] = x[atom3][0] - x_angle_middle[0]; dx_right[1] = x[atom3][1] - x_angle_middle[1]; dx_right[2] = x[atom3][2] - x_angle_middle[2]; - domain->minimum_image(dx_right[0], dx_right[1], dx_right[2]); + domain->minimum_image(FLERR, dx_right[0], dx_right[1], dx_right[2]); x_angle_right[0] = x_angle_middle[0] + dx_right[0]; x_angle_right[1] = x_angle_middle[1] + dx_right[1]; x_angle_right[2] = x_angle_middle[2] + dx_right[2]; @@ -920,14 +920,14 @@ void ComputeStressMop::compute_dihedrals() x_atom_1[1] = x[atom1][1]; x_atom_1[2] = x[atom1][2]; x_atom_1[dir] -= pos; - domain->minimum_image(x_atom_1[0], x_atom_1[1], x_atom_1[2]); + domain->minimum_image(FLERR, x_atom_1[0], x_atom_1[1], x_atom_1[2]); x_atom_1[dir] += pos; // minimum image of atom2 with respect to atom1 diffx[0] = x[atom2][0] - x_atom_1[0]; diffx[1] = x[atom2][1] - x_atom_1[1]; diffx[2] = x[atom2][2] - x_atom_1[2]; - domain->minimum_image(diffx[0], diffx[1], diffx[2]); + domain->minimum_image(FLERR, diffx[0], diffx[1], diffx[2]); x_atom_2[0] = x_atom_1[0] + diffx[0]; x_atom_2[1] = x_atom_1[1] + diffx[1]; x_atom_2[2] = x_atom_1[2] + diffx[2]; @@ -936,7 +936,7 @@ void ComputeStressMop::compute_dihedrals() diffx[0] = x[atom3][0] - x_atom_2[0]; diffx[1] = x[atom3][1] - x_atom_2[1]; diffx[2] = x[atom3][2] - x_atom_2[2]; - domain->minimum_image(diffx[0], diffx[1], diffx[2]); + domain->minimum_image(FLERR, diffx[0], diffx[1], diffx[2]); x_atom_3[0] = x_atom_2[0] + diffx[0]; x_atom_3[1] = x_atom_2[1] + diffx[1]; x_atom_3[2] = x_atom_2[2] + diffx[2]; @@ -945,7 +945,7 @@ void ComputeStressMop::compute_dihedrals() diffx[0] = x[atom4][0] - x_atom_3[0]; diffx[1] = x[atom4][1] - x_atom_3[1]; diffx[2] = x[atom4][2] - x_atom_3[2]; - domain->minimum_image(diffx[0], diffx[1], diffx[2]); + domain->minimum_image(FLERR, diffx[0], diffx[1], diffx[2]); x_atom_4[0] = x_atom_3[0] + diffx[0]; x_atom_4[1] = x_atom_3[1] + diffx[1]; x_atom_4[2] = x_atom_3[2] + diffx[2]; diff --git a/src/EXTRA-COMPUTE/compute_stress_mop_profile.cpp b/src/EXTRA-COMPUTE/compute_stress_mop_profile.cpp index c8087b60a9..a6bf661a9e 100644 --- a/src/EXTRA-COMPUTE/compute_stress_mop_profile.cpp +++ b/src/EXTRA-COMPUTE/compute_stress_mop_profile.cpp @@ -537,14 +537,14 @@ void ComputeStressMopProfile::compute_pairs() // minimum image of xi with respect to the plane xi[dir] -= pos; - domain->minimum_image(xi[0], xi[1], xi[2]); + domain->minimum_image(FLERR, xi[0], xi[1], xi[2]); xi[dir] += pos; // minimum image of xj with respect to xi xj[0] -= xi[0]; xj[1] -= xi[1]; xj[2] -= xi[2]; - domain->minimum_image(xi[0], xi[1], xi[2]); + domain->minimum_image(FLERR, xj[0], xj[1], xj[2]); xj[0] += xi[0]; xj[1] += xi[1]; xj[2] += xi[2]; @@ -649,7 +649,7 @@ void ComputeStressMopProfile::compute_bonds() dx[1] = x[atom1][1]; dx[2] = x[atom1][2]; dx[dir] -= pos; - domain->minimum_image(dx[0], dx[1], dx[2]); + domain->minimum_image(FLERR, dx[0], dx[1], dx[2]); x_bond_1[0] = dx[0]; x_bond_1[1] = dx[1]; x_bond_1[2] = dx[2]; @@ -660,7 +660,7 @@ void ComputeStressMopProfile::compute_bonds() dx[0] = x[atom2][0] - x_bond_1[0]; dx[1] = x[atom2][1] - x_bond_1[1]; dx[2] = x[atom2][2] - x_bond_1[2]; - domain->minimum_image(dx[0], dx[1], dx[2]); + domain->minimum_image(FLERR, dx[0], dx[1], dx[2]); x_bond_2[0] = x_bond_1[0] + dx[0]; x_bond_2[1] = x_bond_1[1] + dx[1]; x_bond_2[2] = x_bond_1[2] + dx[2]; @@ -783,7 +783,7 @@ void ComputeStressMopProfile::compute_angles() dx[1] = x[atom1][1]; dx[2] = x[atom1][2]; dx[dir] -= pos; - domain->minimum_image(dx[0], dx[1], dx[2]); + domain->minimum_image(FLERR, dx[0], dx[1], dx[2]); x_angle_left[0] = dx[0]; x_angle_left[1] = dx[1]; x_angle_left[2] = dx[2]; @@ -793,7 +793,7 @@ void ComputeStressMopProfile::compute_angles() dx_left[0] = x[atom2][0] - x_angle_left[0]; dx_left[1] = x[atom2][1] - x_angle_left[1]; dx_left[2] = x[atom2][2] - x_angle_left[2]; - domain->minimum_image(dx_left[0], dx_left[1], dx_left[2]); + domain->minimum_image(FLERR, dx_left[0], dx_left[1], dx_left[2]); x_angle_middle[0] = x_angle_left[0] + dx_left[0]; x_angle_middle[1] = x_angle_left[1] + dx_left[1]; x_angle_middle[2] = x_angle_left[2] + dx_left[2]; @@ -802,7 +802,7 @@ void ComputeStressMopProfile::compute_angles() dx_right[0] = x[atom3][0] - x_angle_middle[0]; dx_right[1] = x[atom3][1] - x_angle_middle[1]; dx_right[2] = x[atom3][2] - x_angle_middle[2]; - domain->minimum_image(dx_right[0], dx_right[1], dx_right[2]); + domain->minimum_image(FLERR, dx_right[0], dx_right[1], dx_right[2]); x_angle_right[0] = x_angle_middle[0] + dx_right[0]; x_angle_right[1] = x_angle_middle[1] + dx_right[1]; x_angle_right[2] = x_angle_middle[2] + dx_right[2]; @@ -971,14 +971,14 @@ void ComputeStressMopProfile::compute_dihedrals() x_atom_1[1] = x[atom1][1]; x_atom_1[2] = x[atom1][2]; x_atom_1[dir] -= pos; - domain->minimum_image(x_atom_1[0], x_atom_1[1], x_atom_1[2]); + domain->minimum_image(FLERR, x_atom_1[0], x_atom_1[1], x_atom_1[2]); x_atom_1[dir] += pos; // minimum image of atom2 with respect to atom1 diffx[0] = x[atom2][0] - x_atom_1[0]; diffx[1] = x[atom2][1] - x_atom_1[1]; diffx[2] = x[atom2][2] - x_atom_1[2]; - domain->minimum_image(diffx[0], diffx[1], diffx[2]); + domain->minimum_image(FLERR, diffx[0], diffx[1], diffx[2]); x_atom_2[0] = x_atom_1[0] + diffx[0]; x_atom_2[1] = x_atom_1[1] + diffx[1]; x_atom_2[2] = x_atom_1[2] + diffx[2]; @@ -987,7 +987,7 @@ void ComputeStressMopProfile::compute_dihedrals() diffx[0] = x[atom3][0] - x_atom_2[0]; diffx[1] = x[atom3][1] - x_atom_2[1]; diffx[2] = x[atom3][2] - x_atom_2[2]; - domain->minimum_image(diffx[0], diffx[1], diffx[2]); + domain->minimum_image(FLERR, diffx[0], diffx[1], diffx[2]); x_atom_3[0] = x_atom_2[0] + diffx[0]; x_atom_3[1] = x_atom_2[1] + diffx[1]; x_atom_3[2] = x_atom_2[2] + diffx[2]; @@ -996,7 +996,7 @@ void ComputeStressMopProfile::compute_dihedrals() diffx[0] = x[atom4][0] - x_atom_3[0]; diffx[1] = x[atom4][1] - x_atom_3[1]; diffx[2] = x[atom4][2] - x_atom_3[2]; - domain->minimum_image(diffx[0], diffx[1], diffx[2]); + domain->minimum_image(FLERR, diffx[0], diffx[1], diffx[2]); x_atom_4[0] = x_atom_3[0] + diffx[0]; x_atom_4[1] = x_atom_3[1] + diffx[1]; x_atom_4[2] = x_atom_3[2] + diffx[2]; diff --git a/src/EXTRA-FIX/fix_ave_moments.cpp b/src/EXTRA-FIX/fix_ave_moments.cpp new file mode 100644 index 0000000000..882aaa7f28 --- /dev/null +++ b/src/EXTRA-FIX/fix_ave_moments.cpp @@ -0,0 +1,636 @@ +// clang-format off +/* ---------------------------------------------------------------------- + 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: Sebastian Huetter (OvGU) +------------------------------------------------------------------------- */ + +#include "fix_ave_moments.h" + +#include "arg_info.h" +#include "compute.h" +#include "error.h" +#include "input.h" +#include "math_special.h" +#include "memory.h" +#include "modify.h" +#include "update.h" +#include "variable.h" + +#include +#include + +using namespace LAMMPS_NS; +using namespace FixConst; +using MathSpecial::square; +using MathSpecial::cube; + +enum { MEAN, STDDEV, VARIANCE, SKEW, KURTOSIS }; + +/* ---------------------------------------------------------------------- */ + +FixAveMoments::FixAveMoments(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), nvalues(0), result_list(nullptr), window_list(nullptr) +{ + // this fix's data is always accessible (but might be meaningless) + global_freq = 1; + dynamic_group_allow = 1; + time_depend = 1; + + // EXAMPLE: + // fix ID group-ID ave/moments Nevery Nrepeat Nfreq value1 ... valueN moment1 ... momentM keyword value ... + + // the first six arguments are fixed & need at least one input and moment + const int nfixedargs = 6; + if (narg < nfixedargs + 2) utils::missing_cmd_args(FLERR, "fix ave/moments", error); + + nevery = utils::inumeric(FLERR,arg[3],false,lmp); + nrepeat = utils::inumeric(FLERR,arg[4],false,lmp); + nfreq = utils::inumeric(FLERR,arg[5],false,lmp); + + // scan values to count them + + nvalues = 0; + // first input name is position after the fixed args + int iarg = nfixedargs; + while (iarg < narg) { + if (utils::strmatch(arg[iarg],"^[cfv]_")) { + nvalues++; + iarg++; + } else break; + } + if (nvalues == 0) + error->all(FLERR, nfixedargs, + "No values from computes, fixes, or variables used in fix ave/moments command"); + + // next, the moments + iarg = consume_moments(iarg, narg, arg); + if (moments.empty()) + error->all(FLERR, nfixedargs, + "No values from computes, fixes, or variables used in fix ave/moments command"); + + // parse optional keywords which must follow the data + + options(iarg,narg,arg); + + // expand args if any have wildcard character "*" + // this can reset nvalues + + int expand = 0; + char **earg; + int *amap = nullptr; + nvalues = utils::expand_args(FLERR, nvalues, &arg[nfixedargs], /* mode=scalar */ 0, earg, lmp, &amap); + + if (earg != &arg[nfixedargs]) expand = 1; + arg = earg; + + // parse values + + values.clear(); + for (int i = 0; i < nvalues; i++) { + ArgInfo argi(arg[i]); + + value_t val; + val.keyword = arg[i]; + val.which = argi.get_type(); + + val.argindex = argi.get_index1(); + val.iarg = (expand ? amap[i] : i) + nfixedargs; + val.varlen = 0; + val.id = argi.get_name(); + val.val.c = nullptr; + + if ((val.which == ArgInfo::NONE) || (val.which == ArgInfo::UNKNOWN) || (argi.get_dim() > 1)) + error->all(FLERR, val.iarg, "Invalid fix ave/moments argument: {}", arg[i]); + + values.push_back(std::move(val)); + } + if (nvalues != (int)values.size()) + error->all(FLERR, Error::NOPOINTER, + "Could not parse value data consistently for fix ave/moments"); + + // setup and error check + // for fix inputs, check that fix frequency is acceptable + + if (nevery <= 0) error->all(FLERR, 3, "Illegal fix ave/moments nevery value: {}", nevery); + if (nrepeat <= 0) error->all(FLERR, 4, "Illegal fix ave/moments nrepeat value: {}", nrepeat); + if (nfreq <= 0) error->all(FLERR, 5, "Illegal fix ave/moments nfreq value: {}", nfreq); + + for (auto &val : values) { + switch (val.which) { + case ArgInfo::COMPUTE: + val.val.c = modify->get_compute_by_id(val.id); + if (!val.val.c) + error->all(FLERR, val.iarg, "Compute ID {} for fix ave/moments does not exist", val.id); + if (val.argindex == 0 && (val.val.c->scalar_flag == 0)) + error->all(FLERR, val.iarg, "Fix ave/moments compute {} does not calculate a scalar", val.id); + if (val.argindex && (val.val.c->vector_flag == 0)) + error->all(FLERR, val.iarg, "Fix ave/moments compute {} does not calculate a vector", val.id); + if (val.argindex && (val.argindex > val.val.c->size_vector) && + (val.val.c->size_vector_variable == 0)) + error->all(FLERR, val.iarg, "Fix ave/moments compute {} vector is accessed out-of-range{}", + val.id, utils::errorurl(20)); + if (val.argindex && val.val.c->size_vector_variable) val.varlen = 1; + break; + + case ArgInfo::FIX: + val.val.f = modify->get_fix_by_id(val.id); + if (!val.val.f) error->all(FLERR,"Fix ID {} for fix ave/moments does not exist", val.id); + if ((val.argindex == 0) && (val.val.f->scalar_flag == 0)) + error->all(FLERR, val.iarg, "Fix ave/moments fix {} does not calculate a scalar", val.id); + if (val.argindex && (val.val.f->vector_flag == 0)) + error->all(FLERR, val.iarg, "Fix ave/moments fix {} does not calculate a vector", val.id); + if (val.argindex && (val.val.f->size_vector_variable)) + error->all(FLERR, val.iarg, "Fix ave/moments fix {} vector cannot be variable length", val.id); + if (val.argindex && (val.argindex > val.val.f->size_vector)) + error->all(FLERR, val.iarg, "Fix ave/moments fix {} vector is accessed out-of-range{}", + val.id, utils::errorurl(20)); + if (nevery % val.val.f->global_freq) + error->all(FLERR, val.iarg, "Fix {} for fix ave/moments not computed at compatible time{}", + val.id, utils::errorurl(7)); + break; + + case ArgInfo::VARIABLE: + int ivariable = input->variable->find(val.id.c_str()); + if (ivariable < 0) + error->all(FLERR, val.iarg, "Variable name {} for fix ave/moments does not exist", val.id); + if ((val.argindex == 0) && (input->variable->equalstyle(ivariable) == 0)) + error->all(FLERR, val.iarg, "Fix ave/moments variable {} is not equal-style variable", val.id); + if ((val.argindex) && (input->variable->vectorstyle(ivariable) == 0)) + error->all(FLERR, val.iarg, "Fix ave/moments variable {} is not vector-style variable", + val.id); + break; + } + } + + // if wildcard expansion occurred, free earg memory from expand_args() + // wait to do this until after file comment lines are printed + + if (expand) { + for (int i = 0; i < nvalues; i++) delete[] earg[i]; + memory->sfree(earg); + memory->sfree(amap); + } + + // allocate memory for averaging + + window_list = nullptr; + result_list = nullptr; + + // one window of nvalues columns and nrepeat rows (=all scalars of one value are consecutive) + memory->create(window_list, nvalues, nrepeat, "ave/moments:window_list"); + for (int i = 0; i < nvalues; i++) + for (int j = 0; j < nrepeat; j++) + window_list[i][j] = 0.0; + + // this fix produces a global vector and array + + vector_flag = 1; + size_vector = nvalues * moments.size(); + array_flag = 1; + size_array_rows = size_vector; + size_array_cols = nhistory; + + // produce nmoments outputs per value with nhistory depth + memory->create(result_list, nhistory, size_vector, "ave/moments:result_list"); + for (int i = 0; i < nhistory; i++) + for (int j = 0; j < size_vector; j++) + result_list[i][j] = 0.0; + + // intensive/extensive flags set by compute,fix,variable that produces value + + extvector = -1; + extarray = -2; + extlist = new int[size_vector]; + int extvalue = 0; + int i = 0; + for (auto &val : values) { + switch (val.which) { + case ArgInfo::COMPUTE: + if (val.argindex == 0) extvalue = val.val.c->extscalar; + else if (val.val.f->extvector >= 0) extvalue = val.val.c->extvector; + else extvalue = val.val.c->extlist[val.argindex-1]; + break; + + case ArgInfo::FIX: + if (val.argindex == 0) extvalue = val.val.f->extscalar; + else if (val.val.f->extvector >= 0) extvalue = val.val.f->extvector; + else extvalue = val.val.f->extlist[val.argindex-1]; + break; + + case ArgInfo::VARIABLE: + extvalue = 0; + break; + } + if (extvalue == -1) + error->all(FLERR, Error::NOLASTLINE, "Fix ave/moments cannot set output array " + "intensive/extensive from these inputs"); + if (extarray < -1) extarray = extvalue; + else if (extvalue != extarray) + error->all(FLERR, Error::NOLASTLINE, "Fix ave/moments cannot set output array " + "intensive/extensive from these inputs"); + for (int j=0; j < (int)moments.size(); j++) + extlist[i + j] = extvalue; + i += moments.size(); + } + + // initializations + + iwindow = window_filled = 0; + iresult = 0; + + // nvalid = next step on which end_of_step does something + // add nvalid to all computes that store invocation times + // since don't know a priori which are invoked by this fix + // once in end_of_step() can set timestep for ones actually invoked + + nvalid_comp_next = -1; + nvalid = -1; + setnextvalid(); + modify->addstep_compute_all(nvalid); +} + +/* ---------------------------------------------------------------------- */ + +FixAveMoments::~FixAveMoments() +{ + values.clear(); + moments.clear(); + delete[] extlist; + + memory->destroy(window_list); + memory->destroy(result_list); +} + +/* ---------------------------------------------------------------------- */ + +int FixAveMoments::setmask() +{ + int mask = 0; + mask |= END_OF_STEP; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixAveMoments::init() +{ + // update indices/pointers for all computes,fixes,variables + + for (auto &val : values) { + switch (val.which) { + case ArgInfo::COMPUTE: + val.val.c = modify->get_compute_by_id(val.id); + if (!val.val.c) + error->all(FLERR, Error::NOLASTLINE, "Compute ID {} for fix ave/moments does not exist", + val.id); + break; + + case ArgInfo::FIX: + val.val.f = modify->get_fix_by_id(val.id); + if (!val.val.f) + error->all(FLERR, Error::NOLASTLINE, "Fix ID {} for fix ave/moments does not exist", val.id); + break; + + case ArgInfo::VARIABLE: + val.val.v = input->variable->find(val.id.c_str()); + if (val.val.v < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable name {} for fix ave/moments does not exist", + val.id); + break; + } + } + + // need to reset nvalid if nvalid < ntimestep b/c minimize was performed + + if (nvalid < update->ntimestep) { + setnextvalid(); + modify->addstep_compute_all(nvalid); + } +} + +/* ---------------------------------------------------------------------- + only does something if nvalid = current timestep +------------------------------------------------------------------------- */ + +void FixAveMoments::setup(int /*vflag*/) +{ + end_of_step(); +} + +/* ---------------------------------------------------------------------- */ + +void FixAveMoments::end_of_step() +{ + // skip if not step which requires doing something + + bigint ntimestep = update->ntimestep; + if (ntimestep != nvalid) return; + + // always take new values + append_values(); + + // if window boundary reached, do a compute, otherwise just schedule next take + if (ntimestep == nvalid_comp_next) { + update_results(); + setnextvalid(); + } else { + nvalid += nevery; + } + + modify->addstep_compute(nvalid); +} + +/* ---------------------------------------------------------------------- + return scalar value +------------------------------------------------------------------------- */ + +double FixAveMoments::compute_scalar() +{ + return 0.0; +} + +/* ---------------------------------------------------------------------- + return Ith vector value +------------------------------------------------------------------------- */ + +double FixAveMoments::compute_vector(int i) +{ + return compute_array(i, 0); +} + +/* ---------------------------------------------------------------------- + return I,J array value +------------------------------------------------------------------------- */ + +double FixAveMoments::compute_array(int i, int j) +{ + if (i >= size_vector) return 0.0; + if (j >= nhistory) return 0.0; + // locate the j'th previous result in the ring buffer, relative to the + // row before iresult (the current insert cursor) + int row = (iresult - 1 - j + nhistory) % nhistory; + return result_list[row][i]; +} + +/* ---------------------------------------------------------------------- + parse moment names +------------------------------------------------------------------------- */ + +int FixAveMoments::consume_moments(int iarg, int narg, char **arg) +{ + moments.clear(); + + while (iarg < narg) { + if (strcmp(arg[iarg],"mean") == 0) + moments.push_back(MEAN); + else if (strcmp(arg[iarg],"stddev") == 0) + moments.push_back(STDDEV); + else if (strcmp(arg[iarg],"variance") == 0) + moments.push_back(VARIANCE); + else if (strcmp(arg[iarg],"skew") == 0) + moments.push_back(SKEW); + else if (strcmp(arg[iarg],"kurtosis") == 0) + moments.push_back(KURTOSIS); + else + break; + iarg++; + } + return iarg; +} + +/* ---------------------------------------------------------------------- + parse optional args +------------------------------------------------------------------------- */ + +void FixAveMoments::options(int iarg, int narg, char **arg) +{ + // option defaults + + nhistory = 1; + startstep = 0; + + // optional args + + while (iarg < narg) { + if (strcmp(arg[iarg],"history") == 0) { + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix ave/moments history", error); + nhistory = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (nhistory <= 0) + error->all(FLERR, iarg+2, "Illegal ave/moments history argument {}; must be > 0", + nhistory); + iarg += 2; + } else if (strcmp(arg[iarg],"start") == 0) { + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix ave/moments start", error); + startstep = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; + } else error->all(FLERR,"Unknown fix ave/moments keyword {}", arg[iarg]); + } +} + +/* ---------------------------------------------------------------------- + return next timestep no earlier than `after`, rounded to next + multiple of freq +------------------------------------------------------------------------- */ + +bigint next_after(const bigint ts, const bigint after, const int freq) +{ + if (ts >= after) return ts; + return ts + ((after - ts) / freq + 1) * freq; +} + +/* ---------------------------------------------------------------------- + calculate nvalid = next step on which end_of_step does something + this is either a step to take data + or a step to take and compute the values (nfreq multiple) + startstep is lower bound on nfreq multiple +------------------------------------------------------------------------- */ + +void FixAveMoments::setnextvalid() +{ + bigint ntimestep = update->ntimestep; + + if (nvalid_comp_next > ntimestep) { + // next window end boundary is still in the future, just increment + nvalid = ntimestep + nevery; + return; + } + + // get next window end first + bigint next_comp = (ntimestep/nfreq)*nfreq + nfreq; + nvalid_comp_next = next_after(next_comp, startstep, nfreq); + + // from there, calculate the first time we have to take a value + bigint ntake = nvalid_comp_next - static_cast(nrepeat-1)*nevery; + nvalid = next_after(ntake, ntimestep, nevery); +} + +/* ---------------------------------------------------------------------- */ + +void FixAveMoments::get_values(std::vector& scalars) +{ + // accumulate results of computes,fixes,variables to local copy + int i = 0; + double scalar = 0.0; + for (auto &val : values) { + switch (val.which) { + case ArgInfo::COMPUTE: + // invoke compute if not previously invoked + // ensure no out-of-range access to variable-length compute vector + if (val.argindex == 0) { + if (!(val.val.c->invoked_flag & Compute::INVOKED_SCALAR)) { + val.val.c->compute_scalar(); + val.val.c->invoked_flag |= Compute::INVOKED_SCALAR; + } + scalar = val.val.c->scalar; + } else { + if (!(val.val.c->invoked_flag & Compute::INVOKED_VECTOR)) { + val.val.c->compute_vector(); + val.val.c->invoked_flag |= Compute::INVOKED_VECTOR; + } + if (val.varlen && (val.val.c->size_vector < val.argindex)) scalar = 0.0; + else scalar = val.val.c->vector[val.argindex-1]; + } + break; + + case ArgInfo::FIX: + // access fix fields, guaranteed to be ready + if (val.argindex == 0) + scalar = val.val.f->compute_scalar(); + else + scalar = val.val.f->compute_vector(val.argindex-1); + break; + + case ArgInfo::VARIABLE: + // evaluate equal-style or vector-style variable + // if index exceeds vector length, use a zero value + // this can be useful if vector length is not known a priori + if (val.argindex == 0) + scalar = input->variable->compute_equal(val.val.v); + else { + double *varvec; + int nvec = input->variable->compute_vector(val.val.v,&varvec); + if (val.argindex > nvec) scalar = 0.0; + else scalar = varvec[val.argindex-1]; + } + break; + } + + scalars[i] = scalar; + ++i; + } +} + +/* ---------------------------------------------------------------------- */ + +void FixAveMoments::append_values() +{ + // accumulate results of computes,fixes,variables to local copy + // compute/fix/variable may invoke computes so wrap with clear/add + + modify->clearstep_compute(); + + std::vector scalars(nvalues); + get_values(scalars); + + // transpose for faster access later + for (int i=0; i= nrepeat) { + window_filled = 1; + iwindow = 0; + } +} + +void FixAveMoments::update_results() +{ + const int count = window_filled ? nrepeat : iwindow; + // Delay until we can safely do all moments. Avoids branching in the hot loop. + if (count<3) return; + + double *result = result_list[iresult]; + + // zero out previous values + + for (int i = 0; i < size_vector; i++) + result[i] = 0.0; + + const double inv_n = 1.0 / count; + const double fk2 = (double)count / (count - 1); + const double fk3 = square((double)count) / ((count - 1) * (count - 2)); + const double np1_nm3 = (count+1.0)/(count-3.0); + const double _3_nm1_nm3 = 3.0 * (count-1.0)/(count-3.0); + + // Each value is a series that can be processed individually + for (int i = 0; i < nvalues; i++) { + const double* series = window_list[i]; + + // first pass: mean + double mean = 0.0; + for (int j = 0; j= nhistory) + iresult = 0; +} diff --git a/src/EXTRA-FIX/fix_ave_moments.h b/src/EXTRA-FIX/fix_ave_moments.h new file mode 100644 index 0000000000..30b3565ac8 --- /dev/null +++ b/src/EXTRA-FIX/fix_ave_moments.h @@ -0,0 +1,78 @@ +/* -*- 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 FIX_CLASS +// clang-format off +FixStyle(ave/moments,FixAveMoments); +// clang-format on +#else + +#ifndef LMP_FIX_AVE_MOMENTS_H +#define LMP_FIX_AVE_MOMENTS_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixAveMoments : public Fix { + public: + FixAveMoments(class LAMMPS *, int, char **); + ~FixAveMoments() override; + int setmask() override; + void init() override; + void setup(int) override; + void end_of_step() override; + double compute_scalar() override; + double compute_vector(int) override; + double compute_array(int, int) override; + + private: + struct value_t { + int which; // type of data: COMPUTE, FIX, VARIABLE + int argindex; // 1-based index if data is vector, else 0 + int iarg; // argument index in original argument list + int varlen; // 1 if value is from variable-length compute + std::string id; // compute/fix/variable ID + std::string keyword; // column keyword in output + union { + class Compute *c; + class Fix *f; + int v; + } val; + }; + std::vector values; + std::vector moments; + + int nrepeat, nfreq; + int nvalues; + bigint nvalid, nvalid_comp_next; + + int startstep; + + int nhistory, iresult; + double **result_list; + + int iwindow, window_filled; + double **window_list; + + int consume_moments(int iarg, int narg, char **arg); + void options(int, int, char **); + void setnextvalid(); + + void get_values(std::vector& scalars); + void append_values(); + void update_results(); +}; +} // namespace LAMMPS_NS +#endif +#endif diff --git a/src/EXTRA-FIX/fix_drag.cpp b/src/EXTRA-FIX/fix_drag.cpp index 45143fb665..d45342e07b 100644 --- a/src/EXTRA-FIX/fix_drag.cpp +++ b/src/EXTRA-FIX/fix_drag.cpp @@ -114,7 +114,7 @@ void FixDrag::post_force(int /*vflag*/) if (!xflag) dx = 0.0; if (!yflag) dy = 0.0; if (!zflag) dz = 0.0; - domain->minimum_image(dx,dy,dz); + domain->minimum_image(FLERR, dx,dy,dz); r = sqrt(dx*dx + dy*dy + dz*dz); if (r > delta) { prefactor = f_mag/r; diff --git a/src/EXTRA-FIX/fix_filter_corotate.cpp b/src/EXTRA-FIX/fix_filter_corotate.cpp index 872ebd1772..24376448a3 100644 --- a/src/EXTRA-FIX/fix_filter_corotate.cpp +++ b/src/EXTRA-FIX/fix_filter_corotate.cpp @@ -547,17 +547,17 @@ void FixFilterCorotate::pre_neighbor() del1[0] = x[atom1][0]-x[oxy][0]; del1[1] = x[atom1][1]-x[oxy][1]; del1[2] = x[atom1][2]-x[oxy][2]; - domain->minimum_image(del1); + domain->minimum_image(FLERR, del1); del2[0] = x[atom2][0]-x[atom1][0]; del2[1] = x[atom2][1]-x[atom1][1]; del2[2] = x[atom2][2]-x[atom1][2]; - domain->minimum_image(del2); + domain->minimum_image(FLERR, del2); del3[0] = x[atom3][0]-x[atom1][0]; del3[1] = x[atom3][1]-x[atom1][1]; del3[2] = x[atom3][2]-x[atom1][2]; - domain->minimum_image(del3); + domain->minimum_image(FLERR, del3); double a = (del2[1])*(del3[2]) - (del2[2])*(del3[1]); double b = (del2[2])*(del3[0]) - (del2[0])*(del3[2]); @@ -620,17 +620,17 @@ void FixFilterCorotate::pre_neighbor() del1[0] = x[atom1][0]-x[oxy][0]; del1[1] = x[atom1][1]-x[oxy][1]; del1[2] = x[atom1][2]-x[oxy][2]; - domain->minimum_image(del1); + domain->minimum_image(FLERR, del1); del2[0] = x[atom2][0]-x[atom1][0]; del2[1] = x[atom2][1]-x[atom1][1]; del2[2] = x[atom2][2]-x[atom1][2]; - domain->minimum_image(del2); + domain->minimum_image(FLERR, del2); del3[0] = x[atom3][0]-x[atom1][0]; del3[1] = x[atom3][1]-x[atom1][1]; del3[2] = x[atom3][2]-x[atom1][2]; - domain->minimum_image(del3); + domain->minimum_image(FLERR, del3); double a = (del2[1])*(del3[2]) - (del2[2])*(del3[1]); double b = (del2[2])*(del3[0]) - (del2[0])*(del3[2]); @@ -1414,7 +1414,7 @@ void FixFilterCorotate::general_cluster(int index, int index_in_list) del[i][0] = x[list_cluster[i]][0] - x[list_cluster[0]][0]; del[i][1] = x[list_cluster[i]][1] - x[list_cluster[0]][1]; del[i][2] = x[list_cluster[i]][2] - x[list_cluster[0]][2]; - domain->minimum_image(del[i]); + domain->minimum_image(FLERR, del[i]); r[i] = 1.0/sqrt(del[i][0]*del[i][0]+del[i][1]*del[i][1]+ del[i][2]*del[i][2]); } diff --git a/src/EXTRA-FIX/fix_gjf.cpp b/src/EXTRA-FIX/fix_gjf.cpp new file mode 100644 index 0000000000..f602e6181d --- /dev/null +++ b/src/EXTRA-FIX/fix_gjf.cpp @@ -0,0 +1,687 @@ +/* ---------------------------------------------------------------------- + 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 authors: Tim Linke & Niels Gronbech-Jensen (UC Davis) +------------------------------------------------------------------------- */ + +#include "fix_gjf.h" + +#include "atom.h" +#include "citeme.h" +#include "comm.h" +#include "compute.h" +#include "error.h" +#include "force.h" +#include "group.h" +#include "input.h" +#include "memory.h" +#include "modify.h" +#include "random_mars.h" +#include "respa.h" +#include "update.h" +#include "variable.h" + +#include +#include + +using namespace LAMMPS_NS; +using namespace FixConst; + +enum { NOBIAS, BIAS }; +enum { CONSTANT, EQUAL, ATOM }; + +static const char cite_gjf[] = + "GJ methods: doi:10.1080/00268976.2019.1662506\n\n" + "@Article{gronbech-jensen_complete_2020,\n" + "title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations},\n" + "volume = {118},\n" + "number = {8},\n" + "url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506},\n" + "doi = {10.1080/00268976.2019.1662506},\n" + "journal = {Molecular Physics},\n" + "author = {Grønbech-Jensen, Niels},\n" + "year = {2020}\n" + "}\n\n"; + +static const char cite_gjf_7[] = + "GJ-VII method: doi:10.1063/5.0066008\n\n" + "@Article{finkelstein_2021,\n" + "title = {Bringing discrete-time Langevin splitting methods into agreement with thermodynamics},\n" + "volume = {155},\n" + "number = {18},\n" + "url = {https://doi.org/10.1063/5.0066008},\n" + "doi = {10.1063/5.0066008},\n" + "journal = {J. Chem. Phys.},\n" + "author = {Finkelstein, Joshua and Cheng, Chungho and Fiorin, Giacomo and Seibold, Benjamin and Grønbech-Jensen, Niels},\n" + "year = {2021},\n" + "pages = {184104}\n" + "}\n\n"; + +static const char cite_gjf_8[] = + "GJ-VIII method: doi:10.1007/s10955-024-03345-1\n\n" + "@Article{gronbech_jensen_2024,\n" + "title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations},\n" + "volume = {191},\n" + "number = {10},\n" + "url = {https://doi.org/10.1007/s10955-024-03345-1},\n" + "doi = {10.1007/s10955-024-03345-1},\n" + "journal = {J. Stat. Phys.},\n" + "author = {Gronbech-Jensen, Niels},\n" + "year = {2024},\n" + "pages = {137}\n" + "}\n\n"; + +static const char cite_gjf_vhalf[] = + "GJ-I vhalf method: doi:10.1080/00268976.2019.1570369\n\n" + "@Article{jensen_accurate_2019,\n" + "title = {Accurate configurational and kinetic statistics in discrete-time Langevin systems},\n" + "volume = {117},\n" + "url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1570369},\n" + "doi = {10.1080/00268976.2019.1570369},\n" + "number = {18},\n" + "journal = {Molecular Physics},\n" + "author = {Jensen, Lucas Frese Grønbech and Grønbech-Jensen, Niels},\n" + "year = {2019}\n" + "}\n\n"; + +static const char cite_gjf_vfull[] = + "GJ-I vfull method: doi:10.1080/00268976.2012.760055\n\n" + "@Article{gronbech-jensen_simple_2013,\n" + "title = {A simple and effective Verlet-type algorithm for simulating Langevin dynamics},\n" + "volume = {111},\n" + "url = {http://www.tandfonline.com/doi/abs/10.1080/00268976.2012.760055},\n" + "doi = {10.1080/00268976.2012.760055},\n" + "pages = {983-991},\n" + "number = {8},\n" + "journal = {Molecular Physics},\n" + "author = {Grønbech-Jensen, Niels and Farago, Oded},\n" + "year = {2013}\n" + "}\n\n"; + +/* ---------------------------------------------------------------------- */ + +FixGJF::FixGJF(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), tstr(nullptr), tforce(nullptr), lv(nullptr), id_temp(nullptr), random(nullptr) +{ + if (lmp->citeme) lmp->citeme->add(cite_gjf); + if (narg < 7) error->all(FLERR, "Illegal fix gjf command"); + + time_integrate = 1; + global_freq = 1; + nevery = 1; + + if (utils::strmatch(arg[3], "^v_")) { + tstr = utils::strdup(arg[3] + 2); + } else { + t_start = utils::numeric(FLERR, arg[3], false, lmp); + t_target = t_start; + tstyle = CONSTANT; + } + + t_stop = utils::numeric(FLERR, arg[4], false, lmp); + t_period = utils::numeric(FLERR, arg[5], false, lmp); + seed = utils::inumeric(FLERR, arg[6], false, lmp); + + if (t_period <= 0.0) error->all(FLERR, "Fix gjf period must be > 0.0"); + if (seed <= 0) error->all(FLERR, "Illegal fix gjf command"); + + // initialize Marsaglia RNG with processor-unique seed + random = new RanMars(lmp, seed + comm->me); + + int GJmethods = 8; // number of currently implemented GJ methods + maxatom = 0; + + // optional args + // per default, use half step and GJ-I + + osflag = 0; + GJmethod = 1; + lv_allocated = 0; + + int iarg = 7; + while (iarg < narg) { + if (strcmp(arg[iarg], "vel") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix gjf command"); + if (strcmp(arg[iarg + 1], "vfull") == 0) { + osflag = 1; + } else if (strcmp(arg[iarg + 1], "vhalf") == 0) { + osflag = 0; + } else + error->all(FLERR, "Illegal fix gjf command"); + iarg += 2; + } else if (strcmp(arg[iarg], "method") == 0) { + GJmethod = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); + if (GJmethod == 7) { + if (iarg + 3 > narg) error->all(FLERR, "Illegal fix gjf command for GJ-VII"); + gjfc2 = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + if (gjfc2 < 0 || gjfc2 > 1) error->all(FLERR, "Choice of c2 in GJ-VII must be 0≤c2≤1"); + iarg += 3; + if (lmp->citeme) lmp->citeme->add(cite_gjf_7); + } + else { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix gjf command"); + if (GJmethod < 0 || GJmethod > GJmethods) error->all(FLERR, "Invalid GJ method choice in gjf command"); + if (GJmethod == 8) if (lmp->citeme) lmp->citeme->add(cite_gjf_8); + iarg += 2; + } + } else + error->all(FLERR, "Illegal fix gjf command"); + } + if (GJmethod == 1 && osflag == 0) if (lmp->citeme) lmp->citeme->add(cite_gjf_vhalf); + if (GJmethod == 1 && osflag == 1) if (lmp->citeme) lmp->citeme->add(cite_gjf_vfull); + + // set temperature = nullptr, user can override via fix_modify if wants bias + id_temp = nullptr; + temperature = nullptr; + + lv = nullptr; + tforce = nullptr; + + // setup atom-based array for lv + // register with Atom class + // no need to set peratom_flag, b/c data is for internal use only + + + FixGJF::grow_arrays(atom->nmax); + atom->add_callback(Atom::GROW); + + // initialize lv to onsite velocity + int nlocal = atom->nlocal; + for (int i = 0; i < nlocal; i++) { + lv[i][0] = 0.0; + lv[i][1] = 0.0; + lv[i][2] = 0.0; + } +} + +/* ---------------------------------------------------------------------- */ + +FixGJF::~FixGJF() +{ + if (copymode) return; + + delete random; + delete[] tstr; + delete[] id_temp; + memory->destroy(tforce); + + memory->destroy(lv); + if (modify->get_fix_by_id(id)) atom->delete_callback(id, Atom::GROW); +} + +/* ---------------------------------------------------------------------- */ + +int FixGJF::setmask() +{ + int mask = 0; + mask |= INITIAL_INTEGRATE; + mask |= FINAL_INTEGRATE; + if (!osflag) mask |= END_OF_STEP; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixGJF::init() +{ + if (id_temp) { + temperature = modify->get_compute_by_id(id_temp); + if (!temperature) { + error->all(FLERR, "Temperature compute ID {} for fix {} does not exist", id_temp, style); + } else { + if (temperature->tempflag == 0) + error->all(FLERR, "Compute ID {} for fix {} does not compute temperature", id_temp, style); + } + } + // check variable + + if (tstr) { + tvar = input->variable->find(tstr); + if (tvar < 0) error->all(FLERR, "Variable name {} for fix gjf does not exist", tstr); + if (input->variable->equalstyle(tvar)) + tstyle = EQUAL; + else if (input->variable->atomstyle(tvar)) + tstyle = ATOM; + else + error->all(FLERR, "Variable {} for fix gjf is invalid style", tstr); + } + + if (utils::strmatch(update->integrate_style, "^respa")) { + error->all(FLERR, "Fix gjf and run style respa are not compatible"); + } + + if (temperature && temperature->tempbias) + tbiasflag = BIAS; + else + tbiasflag = NOBIAS; + + // Complete set of thermostats is given in Gronbech-Jensen, Molecular Physics, 118 (2020) + switch (GJmethod) { + case 1: + gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); + break; + case 2: + gjfc2 = exp(-update->dt / t_period); + break; + case 3: + gjfc2 = 1.0 - update->dt / t_period; + break; + case 4: + gjfc2 = ( sqrt(1.0 + 4.0 * (update->dt / t_period) ) - 1.0 ) / ( 2.0 * update->dt / t_period ); + break; + case 5: + gjfc2 = 1.0 / (1.0 + update->dt / t_period); + break; + case 6: + gjfc2 = (1.0 / (1.0 + update->dt / 2.0 / t_period)) * (1.0 / (1.0 + update->dt / 2.0 / t_period)); + break; + case 7: // provided in Finkelstein (2021) + update->dt = (1.0 + gjfc2) / (1.0 - gjfc2) * log(gjfc2) * log(gjfc2) * 0.5 * t_period; + break; + case 8: // provided in Gronbech-Jensen (2024) + gjfc2 = sqrt( (update->dt / t_period) * (update->dt / t_period) + 1.0 ) - update->dt / t_period; + break; + case 0: + gjfc2 = 0.0; + break; + default: + error->all(FLERR, "Fix gjf method not found"); + break; + } + gjfc1 = (1.0 + gjfc2) / 2.0; + gjfc3 = (1.0 - gjfc2) * t_period / update->dt; +} + +/* ---------------------------------------------------------------------- + integrate position and velocity according to the GJ methods + in Grønbech-Jensen, J Stat Phys 191, 137 (2024). The general workflow is + 1. GJ Initial Integration + 2. Force Update + 3. GJ Final Integration + 4. Velocity Choice in end_of_step() +------------------------------------------------------------------------- */ + +void FixGJF::initial_integrate(int /* vflag */) +{ + // This function provides the integration of the GJ formulation 24 a-e + double **x = atom->x; + double **v = atom->v; + double **f = atom->f; + double *mass = atom->mass; + double *rmass = atom->rmass; + int *type = atom->type; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double fran[3]; + + double boltz = force->boltz; + double dt = update->dt; + double mvv2e = force->mvv2e; + double ftm2v = force->ftm2v; + + double dtf = 0.5 * dt * ftm2v; + double dtfm; + double c1sqrt = sqrt(gjfc1); + double c3sqrt = sqrt(gjfc3); + double csq = sqrt(gjfc3 / gjfc1); + double m, beta; + + // If user elected vhalf, v needs to be reassigned to onsite velocity for integration + if (!osflag && lv_allocated) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + // lv is Eq. 24f from previous time step + v[i][0] = lv[i][0]; + v[i][1] = lv[i][1]; + v[i][2] = lv[i][2]; + } + } + + compute_target(); + if (tbiasflag) temperature->compute_scalar(); + + if (rmass) { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + if (tstyle == ATOM) tsqrt = sqrt(tforce[i]); + m = rmass[i]; + beta = tsqrt * sqrt(2.0*dt*m*boltz/t_period/mvv2e) / ftm2v; + + fran[0] = beta*random->gaussian(); + fran[1] = beta*random->gaussian(); + fran[2] = beta*random->gaussian(); + + // First integration delivers Eq. 24a and 24b: + dtfm = dtf / m; + v[i][0] += csq * dtfm * f[i][0]; + v[i][1] += csq * dtfm * f[i][1]; + v[i][2] += csq * dtfm * f[i][2]; + x[i][0] += 0.5 * csq * dt * v[i][0]; + x[i][1] += 0.5 * csq * dt * v[i][1]; + x[i][2] += 0.5 * csq * dt * v[i][2]; + + if (tbiasflag) temperature->remove_bias(i, v[i]); + + // Calculate Eq. 24c: + lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c3sqrt / (2.0 * m)) * fran[0]; + lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c3sqrt / (2.0 * m)) * fran[1]; + lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c3sqrt / (2.0 * m)) * fran[2]; + + // Calculate Eq. 24d + v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * csq * (0.5 / m) * fran[0]; + v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * csq * (0.5 / m) * fran[1]; + v[i][2] = (gjfc2 / c1sqrt) * lv[i][2] + ftm2v * csq * (0.5 / m) * fran[2]; + + if (tbiasflag) temperature->restore_bias(i, v[i]); + if (tbiasflag) temperature->restore_bias(i, lv[i]); + + // Calculate Eq. 24e. Final integrator then calculates Eq. 24f after force update. + x[i][0] += 0.5 * csq * dt * v[i][0]; + x[i][1] += 0.5 * csq * dt * v[i][1]; + x[i][2] += 0.5 * csq * dt * v[i][2]; + } + } + } else { + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + if (tstyle == ATOM) tsqrt = sqrt(tforce[i]); + m = mass[type[i]]; + beta = tsqrt * sqrt(2.0*dt*m*boltz/t_period/mvv2e) / ftm2v; + + fran[0] = beta*random->gaussian(); + fran[1] = beta*random->gaussian(); + fran[2] = beta*random->gaussian(); + + // First integration delivers Eq. 24a and 24b: + dtfm = dtf / m; + v[i][0] += csq * dtfm * f[i][0]; + v[i][1] += csq * dtfm * f[i][1]; + v[i][2] += csq * dtfm * f[i][2]; + x[i][0] += 0.5 * csq * dt * v[i][0]; + x[i][1] += 0.5 * csq * dt * v[i][1]; + x[i][2] += 0.5 * csq * dt * v[i][2]; + + if (tbiasflag) temperature->remove_bias(i, v[i]); + + // Calculate Eq. 24c: + lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c3sqrt / (2.0 * m)) * fran[0]; + lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c3sqrt / (2.0 * m)) * fran[1]; + lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c3sqrt / (2.0 * m)) * fran[2]; + + // Calculate Eq. 24d + v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * csq * (0.5 / m) * fran[0]; + v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * csq * (0.5 / m) * fran[1]; + v[i][2] = (gjfc2 / c1sqrt) * lv[i][2] + ftm2v * csq * (0.5 / m) * fran[2]; + + if (tbiasflag) temperature->restore_bias(i, v[i]); + if (tbiasflag) temperature->restore_bias(i, lv[i]); + + // Calculate Eq. 24e. Final integrator then calculates Eq. 24f after force update. + x[i][0] += 0.5 * csq * dt * v[i][0]; + x[i][1] += 0.5 * csq * dt * v[i][1]; + x[i][2] += 0.5 * csq * dt * v[i][2]; + } + } + } +} + +void FixGJF::final_integrate() +{ + double **v = atom->v; + double **f = atom->f; + double *rmass = atom->rmass; + double *mass = atom->mass; + int *type = atom->type; + int *mask = atom->mask; + int nlocal = atom->nlocal; + if (igroup == atom->firstgroup) nlocal = atom->nfirst; + + double dtfm; + double dtf = 0.5 * update->dt * force->ftm2v; + double csq = sqrt(gjfc3 / gjfc1); + + // Calculate Eq. 24f. + if (rmass) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + dtfm = dtf / rmass[i]; + v[i][0] += csq * dtfm * f[i][0]; + v[i][1] += csq * dtfm * f[i][1]; + v[i][2] += csq * dtfm * f[i][2]; + } + + } else { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + dtfm = dtf / mass[type[i]]; + v[i][0] += csq * dtfm * f[i][0]; + v[i][1] += csq * dtfm * f[i][1]; + v[i][2] += csq * dtfm * f[i][2]; + } + } + + lv_allocated = 1; +} + +/* ---------------------------------------------------------------------- + set current t_target and t_sqrt +------------------------------------------------------------------------- */ + +void FixGJF::compute_target() +{ + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double delta = update->ntimestep - update->beginstep; + if (delta != 0.0) delta /= update->endstep - update->beginstep; + + // if variable temp, evaluate variable, wrap with clear/add + // reallocate tforce array if necessary + + if (tstyle == CONSTANT) { + t_target = t_start + delta * (t_stop-t_start); + tsqrt = sqrt(t_target); + } else { + modify->clearstep_compute(); + if (tstyle == EQUAL) { + t_target = input->variable->compute_equal(tvar); + if (t_target < 0.0) + error->one(FLERR, "Fix gjf variable returned negative temperature"); + tsqrt = sqrt(t_target); + } else { + if (atom->nmax > maxatom) { + maxatom = atom->nmax; + memory->destroy(tforce); + memory->create(tforce,maxatom,"gjf:tforce"); + } + input->variable->compute_atom(tvar,igroup,tforce,1,0); + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + if (tforce[i] < 0.0) + error->one(FLERR, "Fix gjf variable returned negative temperature"); + } + modify->addstep_compute(update->ntimestep + 1); + } +} + +/* ---------------------------------------------------------------------- + select velocity for GJ +------------------------------------------------------------------------- */ + +void FixGJF::end_of_step() +{ + double **v = atom->v; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + // After the final integrator delivers 24f, either the on-site or half-step + // velocity is used in remaining simulation tasks, depending on user input + double tmp[3]; + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + // v is Eq. 24f + tmp[0] = v[i][0]; + tmp[1] = v[i][1]; + tmp[2] = v[i][2]; + // Move on with half-step velocity + v[i][0] = lv[i][0]; + v[i][1] = lv[i][1]; + v[i][2] = lv[i][2]; + // store Eq. 24f in lv for next timestep + lv[i][0] = tmp[0]; + lv[i][1] = tmp[1]; + lv[i][2] = tmp[2]; + } +} + +// clang-format on +/* ---------------------------------------------------------------------- */ + +void FixGJF::reset_target(double t_new) +{ + t_target = t_start = t_stop = t_new; +} + +/* ---------------------------------------------------------------------- */ + +void FixGJF::reset_dt() +{ + // Complete set of thermostats is given in Gronbech-Jensen, Molecular Physics, 118 (2020) + switch (GJmethod) { + case 1: + gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); + break; + case 2: + gjfc2 = exp(-update->dt / t_period); + break; + case 3: + gjfc2 = 1.0 - update->dt / t_period; + break; + case 4: + gjfc2 = ( sqrt(1.0 + 4.0 * (update->dt / t_period) ) - 1.0 ) / ( 2.0 * update->dt / t_period ); + break; + case 5: + gjfc2 = 1.0 / (1.0 + update->dt / t_period); + break; + case 6: + gjfc2 = (1.0 / (1.0 + update->dt / 2.0 / t_period)) * (1.0 / (1.0 + update->dt / 2.0 / t_period)); + break; + case 7: // provided in Finkelstein (2021) + update->dt = (1.0 + gjfc2) / (1.0 - gjfc2) * log(gjfc2) * log(gjfc2) * 0.5 * t_period; + break; + case 8: // provided in Gronbech-Jensen (2024) + gjfc2 = sqrt( (update->dt / t_period)*(update->dt / t_period) + 1.0 ) - update->dt / t_period; + break; + case 0: + gjfc2 = 0.0; + break; + default: + error->all(FLERR, "Fix gjf method not found"); + break; + } + gjfc1 = (1.0 + gjfc2) / 2.0; + gjfc3 = (1.0 - gjfc2) * t_period / update->dt; +} + +/* ---------------------------------------------------------------------- */ + +int FixGJF::modify_param(int narg, char **arg) +{ + if (strcmp(arg[0], "temp") == 0) { + if (narg < 2) utils::missing_cmd_args(FLERR, "fix_modify", error); + delete[] id_temp; + id_temp = utils::strdup(arg[1]); + temperature = modify->get_compute_by_id(id_temp); + if (!temperature) + error->all(FLERR, "Could not find fix_modify temperature compute ID: {}", id_temp); + + if (temperature->tempflag == 0) + error->all(FLERR, "Fix_modify temperature compute {} does not compute temperature", id_temp); + if (temperature->igroup != igroup && comm->me == 0) + error->warning(FLERR, "Group for fix_modify temp != fix group: {} vs {}", + group->names[igroup], group->names[temperature->igroup]); + return 2; + } + return 0; +} + +/* ---------------------------------------------------------------------- + extract thermostat properties +------------------------------------------------------------------------- */ + +void *FixGJF::extract(const char *str, int &dim) +{ + dim = 0; + if (strcmp(str, "t_target") == 0) { return &t_target; } + return nullptr; +} + +/* ---------------------------------------------------------------------- + memory usage of tally array +------------------------------------------------------------------------- */ + +double FixGJF::memory_usage() +{ + double bytes = 0.0; + bytes += (double) atom->nmax * 3 * sizeof(double); + if (tforce) bytes += (double) atom->nmax * sizeof(double); + return bytes; +} + +/* ---------------------------------------------------------------------- + allocate atom-based array for lv +------------------------------------------------------------------------- */ + +void FixGJF::grow_arrays(int nmax) +{ + memory->grow(lv, nmax, 3, "fix_gjf:lv"); +} + +/* ---------------------------------------------------------------------- + copy values within local atom-based array +------------------------------------------------------------------------- */ + +void FixGJF::copy_arrays(int i, int j, int /*delflag*/) +{ + lv[j][0] = lv[i][0]; + lv[j][1] = lv[i][1]; + lv[j][2] = lv[i][2]; +} + +/* ---------------------------------------------------------------------- + pack values in local atom-based array for exchange with another proc +------------------------------------------------------------------------- */ + +int FixGJF::pack_exchange(int i, double *buf) +{ + int n = 0; + buf[n++] = lv[i][0]; + buf[n++] = lv[i][1]; + buf[n++] = lv[i][2]; + return n; +} + +/* ---------------------------------------------------------------------- + unpack values in local atom-based array from exchange with another proc +------------------------------------------------------------------------- */ + +int FixGJF::unpack_exchange(int nlocal, double *buf) +{ + int n = 0; + lv[nlocal][0] = buf[n++]; + lv[nlocal][1] = buf[n++]; + lv[nlocal][2] = buf[n++]; + return n; +} diff --git a/src/EXTRA-FIX/fix_gjf.h b/src/EXTRA-FIX/fix_gjf.h new file mode 100644 index 0000000000..154f6543da --- /dev/null +++ b/src/EXTRA-FIX/fix_gjf.h @@ -0,0 +1,68 @@ +/* -*- 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 FIX_CLASS +// clang-format off +FixStyle(gjf,FixGJF); +// clang-format on +#else + +#ifndef LMP_FIX_GJF_H +#define LMP_FIX_GJF_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixGJF : public Fix { + public: + FixGJF(class LAMMPS *, int, char **); + ~FixGJF() override; + int setmask() override; + void init() override; + void initial_integrate(int) override; + void final_integrate() override; + void end_of_step() override; + void reset_target(double) override; + void reset_dt() override; + int modify_param(int, char **) override; + double memory_usage() override; + void *extract(const char *, int &) override; + void grow_arrays(int) override; + void copy_arrays(int, int, int) override; + int pack_exchange(int, double *) override; + int unpack_exchange(int, double *) override; + + protected: + int osflag, tbiasflag, GJmethod, maxatom, lv_allocated; + double t_start, t_stop, t_period, t_target, tsqrt; + double gjfc1, gjfc2, gjfc3; + int tstyle, tvar; + char *tstr; + + double *tforce; + double **lv; //half step velocity + + char *id_temp; + class Compute *temperature; + + class RanMars *random; + int seed; + + void compute_target(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/EXTRA-FIX/fix_pafi.cpp b/src/EXTRA-FIX/fix_pafi.cpp index 05ee6b90da..fb39e2e48d 100644 --- a/src/EXTRA-FIX/fix_pafi.cpp +++ b/src/EXTRA-FIX/fix_pafi.cpp @@ -261,7 +261,7 @@ void FixPAFI::post_force(int /*vflag*/) deviation[0] = x[i][0]-path[i][0]; // x-path deviation[1] = x[i][1]-path[i][1]; // x-path deviation[2] = x[i][2]-path[i][2]; // x-path - domain->minimum_image(deviation); + domain->minimum_image(FLERR, deviation); proj[3] += path[i][6]*deviation[0]; // (x-path).dn/nn = psi proj[3] += path[i][7]*deviation[1]; // (x-path).dn/nn = psi @@ -424,7 +424,7 @@ void FixPAFI::min_post_force(int /*vflag*/) deviation[0] = x[i][0]-path[i][0]; // x-path deviation[1] = x[i][1]-path[i][1]; // x-path deviation[2] = x[i][2]-path[i][2]; // x-path - domain->minimum_image(deviation); + domain->minimum_image(FLERR, deviation); proj[3] += path[i][6]*deviation[0]; // (x-path).dn/nn = psi proj[3] += path[i][7]*deviation[1]; // (x-path).dn/nn = psi diff --git a/src/EXTRA-MOLECULE/angle_cosine_delta.cpp b/src/EXTRA-MOLECULE/angle_cosine_delta.cpp index 56dd6da88d..43092876dc 100644 --- a/src/EXTRA-MOLECULE/angle_cosine_delta.cpp +++ b/src/EXTRA-MOLECULE/angle_cosine_delta.cpp @@ -155,13 +155,13 @@ double AngleCosineDelta::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; @@ -185,13 +185,13 @@ void AngleCosineDelta::born_matrix(int type, int i1, int i2, int i3, double &du, double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/EXTRA-MOLECULE/angle_cosine_periodic.cpp b/src/EXTRA-MOLECULE/angle_cosine_periodic.cpp index e0e7f31f39..c0ae868576 100644 --- a/src/EXTRA-MOLECULE/angle_cosine_periodic.cpp +++ b/src/EXTRA-MOLECULE/angle_cosine_periodic.cpp @@ -284,13 +284,13 @@ double AngleCosinePeriodic::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; @@ -311,13 +311,13 @@ void AngleCosinePeriodic::born_matrix(int type, int i1, int i2, int i3, double & double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/EXTRA-MOLECULE/angle_cosine_shift.cpp b/src/EXTRA-MOLECULE/angle_cosine_shift.cpp index 14640a5e12..9ac6fb9ba3 100644 --- a/src/EXTRA-MOLECULE/angle_cosine_shift.cpp +++ b/src/EXTRA-MOLECULE/angle_cosine_shift.cpp @@ -258,13 +258,13 @@ double AngleCosineShift::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/EXTRA-MOLECULE/angle_cosine_shift_exp.cpp b/src/EXTRA-MOLECULE/angle_cosine_shift_exp.cpp index 185adea37d..34768652d9 100644 --- a/src/EXTRA-MOLECULE/angle_cosine_shift_exp.cpp +++ b/src/EXTRA-MOLECULE/angle_cosine_shift_exp.cpp @@ -297,13 +297,13 @@ double AngleCosineShiftExp::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/EXTRA-MOLECULE/angle_cosine_squared_restricted.cpp b/src/EXTRA-MOLECULE/angle_cosine_squared_restricted.cpp index 37003b5b05..6c8a27d13d 100644 --- a/src/EXTRA-MOLECULE/angle_cosine_squared_restricted.cpp +++ b/src/EXTRA-MOLECULE/angle_cosine_squared_restricted.cpp @@ -242,13 +242,13 @@ double AngleCosineSquaredRestricted::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; @@ -272,13 +272,13 @@ void AngleCosineSquaredRestricted::born_matrix(int type, int i1, int i2, int i3, double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/EXTRA-MOLECULE/angle_fourier.cpp b/src/EXTRA-MOLECULE/angle_fourier.cpp index f6cd9f4c80..ca643bd57b 100644 --- a/src/EXTRA-MOLECULE/angle_fourier.cpp +++ b/src/EXTRA-MOLECULE/angle_fourier.cpp @@ -263,13 +263,13 @@ double AngleFourier::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; @@ -291,13 +291,13 @@ void AngleFourier::born_matrix(int type, int i1, int i2, int i3, double &du, dou double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/EXTRA-MOLECULE/angle_fourier_simple.cpp b/src/EXTRA-MOLECULE/angle_fourier_simple.cpp index e3497b5e81..0dc6cbad04 100644 --- a/src/EXTRA-MOLECULE/angle_fourier_simple.cpp +++ b/src/EXTRA-MOLECULE/angle_fourier_simple.cpp @@ -269,13 +269,13 @@ double AngleFourierSimple::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; @@ -297,13 +297,13 @@ void AngleFourierSimple::born_matrix(int type, int i1, int i2, int i3, double &d double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/EXTRA-MOLECULE/angle_gaussian.cpp b/src/EXTRA-MOLECULE/angle_gaussian.cpp index 1272ada0bb..17a3cb3b29 100644 --- a/src/EXTRA-MOLECULE/angle_gaussian.cpp +++ b/src/EXTRA-MOLECULE/angle_gaussian.cpp @@ -325,13 +325,13 @@ double AngleGaussian::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/EXTRA-MOLECULE/angle_mwlc.cpp b/src/EXTRA-MOLECULE/angle_mwlc.cpp index 804627cfa3..0853708e24 100644 --- a/src/EXTRA-MOLECULE/angle_mwlc.cpp +++ b/src/EXTRA-MOLECULE/angle_mwlc.cpp @@ -260,13 +260,13 @@ double AngleMWLC::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; @@ -289,12 +289,12 @@ void AngleMWLC::born_matrix(int type, int i1, int i2, int i3, double &du, double double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; c /= sqrt((delx1 * delx1 + dely1 * dely1 + delz1 * delz1) * diff --git a/src/EXTRA-MOLECULE/angle_quartic.cpp b/src/EXTRA-MOLECULE/angle_quartic.cpp index 92e84e79a5..87e3d6a662 100644 --- a/src/EXTRA-MOLECULE/angle_quartic.cpp +++ b/src/EXTRA-MOLECULE/angle_quartic.cpp @@ -269,13 +269,13 @@ double AngleQuartic::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; @@ -299,13 +299,13 @@ void AngleQuartic::born_matrix(int type, int i1, int i2, int i3, double &du, dou double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/EXTRA-MOLECULE/bond_harmonic_restrain.cpp b/src/EXTRA-MOLECULE/bond_harmonic_restrain.cpp index 2a9a1e4e7f..0fc9f5d981 100644 --- a/src/EXTRA-MOLECULE/bond_harmonic_restrain.cpp +++ b/src/EXTRA-MOLECULE/bond_harmonic_restrain.cpp @@ -74,7 +74,7 @@ void BondHarmonicRestrain::compute(int eflag, int vflag) delx = x0[i1][0] - x0[i2][0]; dely = x0[i1][1] - x0[i2][1]; delz = x0[i1][2] - x0[i2][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); rsq = delx * delx + dely * dely + delz * delz; r0 = sqrt(rsq); @@ -235,7 +235,7 @@ double BondHarmonicRestrain::single(int type, double rsq, int i, int j, double & double delx = x0[i][0] - x0[j][0]; double dely = x0[i][1] - x0[j][1]; double delz = x0[i][2] - x0[j][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); double r0 = sqrt(delx * delx + dely * dely + delz * delz); double r = sqrt(rsq); diff --git a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp index d8e34189d9..ae82a7873d 100644 --- a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp +++ b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp @@ -393,3 +393,15 @@ void DihedralCosineSquaredRestricted::born_matrix(int nd, int i1, int i2, int i3 du2 = 2 * k[type] * numerator / denominator; } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralCosineSquaredRestricted::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "phi0") == 0) return (void *) phi0; + return nullptr; +} diff --git a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.h b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.h index b9e2e1d9d8..f44d893cd0 100644 --- a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.h +++ b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.h @@ -34,6 +34,7 @@ class DihedralCosineSquaredRestricted : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *k, *phi0; diff --git a/src/EXTRA-MOLECULE/dihedral_helix.cpp b/src/EXTRA-MOLECULE/dihedral_helix.cpp index 4693d29cd7..55ac8ee776 100644 --- a/src/EXTRA-MOLECULE/dihedral_helix.cpp +++ b/src/EXTRA-MOLECULE/dihedral_helix.cpp @@ -430,3 +430,16 @@ void DihedralHelix::born_matrix(int nd, int i1, int i2, int i3, int i4, du2 = -(9.0*bphi[type]*cos(3.0*phi) + cphi[type]*cos(phi + MY_PI4))*siinv*siinv + (3.0*bphi[type]*sin(3.0*phi) + cphi[type]*sin(phi + MY_PI4))*c*siinv*siinv*siinv; } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralHelix::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "a") == 0) return (void *) aphi; + if (strcmp(str, "b") == 0) return (void *) bphi; + if (strcmp(str, "c") == 0) return (void *) cphi; + return nullptr; + } diff --git a/src/EXTRA-MOLECULE/dihedral_helix.h b/src/EXTRA-MOLECULE/dihedral_helix.h index 172a8c3469..be7263f900 100644 --- a/src/EXTRA-MOLECULE/dihedral_helix.h +++ b/src/EXTRA-MOLECULE/dihedral_helix.h @@ -34,6 +34,7 @@ class DihedralHelix : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *aphi, *bphi, *cphi; diff --git a/src/EXTRA-MOLECULE/dihedral_quadratic.cpp b/src/EXTRA-MOLECULE/dihedral_quadratic.cpp index 2350095f0d..27cf6e2ab6 100644 --- a/src/EXTRA-MOLECULE/dihedral_quadratic.cpp +++ b/src/EXTRA-MOLECULE/dihedral_quadratic.cpp @@ -435,3 +435,15 @@ void DihedralQuadratic::born_matrix(int nd, int i1, int i2, int i3, int i4, du = - 2.0 * k[type] * dphi * siinv; du2 = 2.0 * k[type] * siinv * siinv * ( 1.0 - dphi * c * siinv) ; } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralQuadratic::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "phi0") == 0) return (void *) phi0; + return nullptr; +} diff --git a/src/EXTRA-MOLECULE/dihedral_quadratic.h b/src/EXTRA-MOLECULE/dihedral_quadratic.h index 89f6fa3b25..c584f1ae09 100644 --- a/src/EXTRA-MOLECULE/dihedral_quadratic.h +++ b/src/EXTRA-MOLECULE/dihedral_quadratic.h @@ -34,6 +34,7 @@ class DihedralQuadratic : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *k, *phi0; diff --git a/src/EXTRA-MOLECULE/dihedral_spherical.cpp b/src/EXTRA-MOLECULE/dihedral_spherical.cpp index 15e403ef03..0d66a6bbf0 100644 --- a/src/EXTRA-MOLECULE/dihedral_spherical.cpp +++ b/src/EXTRA-MOLECULE/dihedral_spherical.cpp @@ -110,9 +110,9 @@ static double Phi(double const *x1, //array holding x,y,z coords atom 1 } //Consider periodic boundary conditions: - domain->minimum_image(vb12[0], vb12[1], vb12[2]); - domain->minimum_image(vb23[0], vb23[1], vb23[2]); - domain->minimum_image(vb34[0], vb34[1], vb34[2]); + domain->minimum_image(FLERR, vb12[0], vb12[1], vb12[2]); + domain->minimum_image(FLERR, vb23[0], vb23[1], vb23[2]); + domain->minimum_image(FLERR, vb34[0], vb34[1], vb34[2]); //--- Compute the normal to the planes formed by atoms 1,2,3 and 2,3,4 --- diff --git a/src/EXTRA-MOLECULE/improper_distance.cpp b/src/EXTRA-MOLECULE/improper_distance.cpp index ec55abaf2b..de9a8f9a7b 100644 --- a/src/EXTRA-MOLECULE/improper_distance.cpp +++ b/src/EXTRA-MOLECULE/improper_distance.cpp @@ -94,31 +94,31 @@ void ImproperDistance::compute(int eflag, int vflag) xab = x[i2][0] - x[i1][0]; yab = x[i2][1] - x[i1][1]; zab = x[i2][2] - x[i1][2]; - domain->minimum_image(xab,yab,zab); + domain->minimum_image(FLERR, xab,yab,zab); // bond 1->3 xac = x[i3][0] - x[i1][0]; yac = x[i3][1] - x[i1][1]; zac = x[i3][2] - x[i1][2]; - domain->minimum_image(xac,yac,zac); + domain->minimum_image(FLERR, xac,yac,zac); // bond 1->4 xad = x[i4][0] - x[i1][0]; yad = x[i4][1] - x[i1][1]; zad = x[i4][2] - x[i1][2]; - domain->minimum_image(xad,yad,zad); + domain->minimum_image(FLERR, xad,yad,zad); // bond 2-3 xbc = x[i3][0] - x[i2][0]; ybc = x[i3][1] - x[i2][1]; zbc = x[i3][2] - x[i2][2]; - domain->minimum_image(xbc,ybc,zbc); + domain->minimum_image(FLERR, xbc,ybc,zbc); // bond 2-4 xbd = x[i4][0] - x[i2][0]; ybd = x[i4][1] - x[i2][1]; zbd = x[i4][2] - x[i2][2]; - domain->minimum_image(xbd,ybd,zbd); + domain->minimum_image(FLERR, xbd,ybd,zbd); xna = ybc*zbd - zbc*ybd; yna = -(xbc*zbd - zbc*xbd); diff --git a/src/EXTRA-PAIR/pair_lj_pirani.cpp b/src/EXTRA-PAIR/pair_lj_pirani.cpp new file mode 100644 index 0000000000..e2ece45578 --- /dev/null +++ b/src/EXTRA-PAIR/pair_lj_pirani.cpp @@ -0,0 +1,886 @@ +/* ---------------------------------------------------------------------- + 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: Mateo Rodríguez (mateorsuarez@gmail.com) (IFF-CSIC) + Work done at the Molecular Interactions Group (INTERMOL) of the + Fundamental Physics Institute (http://intermol.iff.csic.es/). + Optimization of the code: Axel Kohlmeyer (Temple U) +------------------------------------------------------------------------- */ + +#include "pair_lj_pirani.h" + +#include "atom.h" +#include "comm.h" +#include "error.h" +#include "force.h" +#include "math_special.h" +#include "memory.h" +#include "neigh_list.h" +#include "neighbor.h" +#include "respa.h" +#include "update.h" + +#include +#include + +using namespace LAMMPS_NS; +using MathSpecial::square; + +/* ---------------------------------------------------------------------- */ + +PairLJPirani::PairLJPirani(LAMMPS *lmp) : Pair(lmp), cut_respa(nullptr) +{ + respa_enable = 1; + born_matrix_enable = 0; + writedata = 1; +} +/* ---------------------------------------------------------------------- */ + +PairLJPirani::~PairLJPirani() +{ + if (copymode) return; + + if (allocated) { + memory->destroy(setflag); + memory->destroy(cutsq); + memory->destroy(cut); + memory->destroy(alpha); + memory->destroy(beta); + memory->destroy(gamma); + memory->destroy(rm); + memory->destroy(epsilon); + memory->destroy(offset); + } +} + +/* ---------------------------------------------------------------------- + allocate all arrays +------------------------------------------------------------------------- */ + +void PairLJPirani::allocate() +{ + allocated = 1; + int n = atom->ntypes + 1; + + memory->create(setflag, n, n, "pair:setflag"); + for (int i = 1; i < n; i++) + for (int j = i; j < n; j++) setflag[i][j] = 0; + + memory->create(cutsq, n, n, "pair:cutsq"); + + memory->create(cut, n, n, "pair:cut"); + memory->create(alpha, n, n, "pair:alpha"); + memory->create(beta, n, n, "pair:beta"); + memory->create(gamma, n, n, "pair:gamma"); + memory->create(rm, n, n, "pair:rm"); + memory->create(epsilon, n, n, "pair:epsilon"); + memory->create(offset, n, n, "pair:offset"); +} + +/* ---------------------------------------------------------------------- */ + +void PairLJPirani::compute(int eflag, int vflag) + +{ + int i, j, ii, jj, inum, jnum, itype, jtype; + double xtmp, ytmp, ztmp, delx, dely, delz, evdwl, fpair; + double rsq, factor_lj; + int *ilist, *jlist, *numneigh, **firstneigh; + + double r, rx, n_x; + double pow_rx_n_x, pow_rx_gamma; + double filj1, filj2, filj3, filj4, filj5, filj6, forceilj; + double ilj1, ilj2; + double fxtmp, fytmp, fztmp; + + evdwl = 0.0; + ev_init(eflag, vflag); + + double **x = atom->x; + double **f = atom->f; + int *type = atom->type; + int nlocal = atom->nlocal; + double *special_lj = force->special_lj; + int newton_pair = force->newton_pair; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + // loop over neighbors of my atoms + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + jlist = firstneigh[i]; + jnum = numneigh[i]; + fxtmp = fytmp = fztmp = 0.0; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + factor_lj = special_lj[sbmask(j)]; + j &= NEIGHMASK; + + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx * delx + dely * dely + delz * delz; + jtype = type[j]; + + if (rsq < cutsq[itype][jtype]) { + + r = sqrt(rsq); + + rx = r / rm[itype][jtype]; + n_x = alpha[itype][jtype] * rx * rx + beta[itype][jtype]; + pow_rx_n_x = pow(1.0 / rx, n_x); + pow_rx_gamma = pow(1.0 / rx, gamma[itype][jtype]); + + filj1 = -2.0 * alpha[itype][jtype] * gamma[itype][jtype] * rx * pow_rx_n_x / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj2 = +2.0 * alpha[itype][jtype] * rx * n_x * pow_rx_gamma / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj3 = -2.0 * alpha[itype][jtype] * rx * pow_rx_gamma / + (rm[itype][jtype] * (n_x - gamma[itype][jtype])); + + filj4 = +2.0 * alpha[itype][jtype] * gamma[itype][jtype] * (rx / rm[itype][jtype]) * + log(1 / rx) * pow_rx_n_x / (n_x - gamma[itype][jtype]); + + filj5 = -1.0 * gamma[itype][jtype] * n_x * pow_rx_n_x / (r * (n_x - gamma[itype][jtype])); + + filj6 = +1.0 * gamma[itype][jtype] * n_x * pow_rx_gamma / (r * (n_x - gamma[itype][jtype])); + + // F = -dV/dr + forceilj = -epsilon[itype][jtype] * (filj1 + filj2 + filj3 + filj4 + filj5 + filj6); + fpair = factor_lj * forceilj / r; // F_x = -x/r * dV/dr (chain rule) + + fxtmp += delx * fpair; + fytmp += dely * fpair; + fztmp += delz * fpair; + if (newton_pair || j < nlocal) { + f[j][0] -= delx * fpair; + f[j][1] -= dely * fpair; + f[j][2] -= delz * fpair; + } + + if (eflag) { + ilj1 = epsilon[itype][jtype] * gamma[itype][jtype] * pow(1 / rx, n_x) / + (n_x - gamma[itype][jtype]); + ilj2 = -epsilon[itype][jtype] * n_x * pow(1 / rx, gamma[itype][jtype]) / + (n_x - gamma[itype][jtype]); + + evdwl = ilj1 + ilj2 - offset[itype][jtype]; + evdwl *= factor_lj; + } + + if (evflag) ev_tally(i, j, nlocal, newton_pair, evdwl, 0.0, fpair, delx, dely, delz); + } + } + f[i][0] += fxtmp; + f[i][1] += fytmp; + f[i][2] += fztmp; + } + if (vflag_fdotr) virial_fdotr_compute(); +} + +/* ---------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- */ + +void PairLJPirani::compute_inner() +{ + int i, j, ii, jj, inum, jnum, itype, jtype; + double xtmp, ytmp, ztmp, delx, dely, delz, fpair; + double rsq, factor_lj, rsw; + int *ilist, *jlist, *numneigh, **firstneigh; + + double r, rx, n_x; + double pow_rx_n_x, pow_rx_gamma; + double filj1, filj2, filj3, filj4, filj5, filj6, forceilj; + double fxtmp, fytmp, fztmp; + + double **x = atom->x; + double **f = atom->f; + int *type = atom->type; + int nlocal = atom->nlocal; + double *special_lj = force->special_lj; + int newton_pair = force->newton_pair; + + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; + + double cut_out_on = cut_respa[0]; + double cut_out_off = cut_respa[1]; + + double cut_out_diff = cut_out_off - cut_out_on; + double cut_out_on_sq = cut_out_on * cut_out_on; + double cut_out_off_sq = cut_out_off * cut_out_off; + + // loop over neighbors of my atoms + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + jlist = firstneigh[i]; + jnum = numneigh[i]; + fxtmp = fytmp = fztmp = 0.0; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + factor_lj = special_lj[sbmask(j)]; + j &= NEIGHMASK; + + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx * delx + dely * dely + delz * delz; + + if (rsq < cut_out_off_sq) { + jtype = type[j]; + r = sqrt(rsq); + + rx = r / rm[itype][jtype]; + n_x = alpha[itype][jtype] * rx * rx + beta[itype][jtype]; + pow_rx_n_x = pow(1.0 / rx, n_x); + pow_rx_gamma = pow(1.0 / rx, gamma[itype][jtype]); + + filj1 = -2.0 * alpha[itype][jtype] * gamma[itype][jtype] * rx * pow_rx_n_x / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj2 = +2.0 * alpha[itype][jtype] * rx * n_x * pow_rx_gamma / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj3 = -2.0 * alpha[itype][jtype] * rx * pow_rx_gamma / + (rm[itype][jtype] * (n_x - gamma[itype][jtype])); + + filj4 = +2.0 * alpha[itype][jtype] * gamma[itype][jtype] * (rx / rm[itype][jtype]) * + log(1 / rx) * pow_rx_n_x / (n_x - gamma[itype][jtype]); + + filj5 = -1.0 * gamma[itype][jtype] * n_x * pow_rx_n_x / (r * (n_x - gamma[itype][jtype])); + + filj6 = +1.0 * gamma[itype][jtype] * n_x * pow_rx_gamma / (r * (n_x - gamma[itype][jtype])); + + // F = -dV/dr + forceilj = -epsilon[itype][jtype] * (filj1 + filj2 + filj3 + filj4 + filj5 + filj6); + fpair = factor_lj * forceilj / r; // F_x = -x/r * dV/dr (chain rule) + + if (rsq > cut_out_on_sq) { + rsw = (sqrt(rsq) - cut_out_on) / cut_out_diff; + fpair *= 1.0 - rsw * rsw * (3.0 - 2.0 * rsw); + } + + fxtmp += delx * fpair; + fytmp += dely * fpair; + fztmp += delz * fpair; + if (newton_pair || j < nlocal) { + f[j][0] -= delx * fpair; + f[j][1] -= dely * fpair; + f[j][2] -= delz * fpair; + } + } + } + f[i][0] += fxtmp; + f[i][1] += fytmp; + f[i][2] += fztmp; + } +} + +/* ---------------------------------------------------------------------- */ + +void PairLJPirani::compute_middle() + +{ + int i, j, ii, jj, inum, jnum, itype, jtype; + double xtmp, ytmp, ztmp, delx, dely, delz, fpair; + double rsq, factor_lj, rsw; + int *ilist, *jlist, *numneigh, **firstneigh; + + double r, rx, n_x; + double pow_rx_n_x, pow_rx_gamma; + double filj1, filj2, filj3, filj4, filj5, filj6, forceilj; + double fxtmp, fytmp, fztmp; + + double **x = atom->x; + double **f = atom->f; + int *type = atom->type; + int nlocal = atom->nlocal; + double *special_lj = force->special_lj; + int newton_pair = force->newton_pair; + + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; + + double cut_in_off = cut_respa[0]; + double cut_in_on = cut_respa[1]; + double cut_out_on = cut_respa[2]; + double cut_out_off = cut_respa[3]; + + double cut_in_diff = cut_in_on - cut_in_off; + double cut_out_diff = cut_out_off - cut_out_on; + double cut_in_off_sq = cut_in_off * cut_in_off; + double cut_in_on_sq = cut_in_on * cut_in_on; + double cut_out_on_sq = cut_out_on * cut_out_on; + double cut_out_off_sq = cut_out_off * cut_out_off; + + // loop over neighbors of my atoms + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + jlist = firstneigh[i]; + jnum = numneigh[i]; + fxtmp = fytmp = fztmp = 0.0; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + factor_lj = special_lj[sbmask(j)]; + j &= NEIGHMASK; + + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx * delx + dely * dely + delz * delz; + + if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { + jtype = type[j]; + r = sqrt(rsq); + + rx = r / rm[itype][jtype]; + n_x = alpha[itype][jtype] * rx * rx + beta[itype][jtype]; + pow_rx_n_x = pow(1.0 / rx, n_x); + pow_rx_gamma = pow(1.0 / rx, gamma[itype][jtype]); + + filj1 = -2.0 * alpha[itype][jtype] * gamma[itype][jtype] * rx * pow_rx_n_x / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj2 = +2.0 * alpha[itype][jtype] * rx * n_x * pow_rx_gamma / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj3 = -2.0 * alpha[itype][jtype] * rx * pow_rx_gamma / + (rm[itype][jtype] * (n_x - gamma[itype][jtype])); + + filj4 = +2.0 * alpha[itype][jtype] * gamma[itype][jtype] * (rx / rm[itype][jtype]) * + log(1 / rx) * pow_rx_n_x / (n_x - gamma[itype][jtype]); + + filj5 = -1.0 * gamma[itype][jtype] * n_x * pow_rx_n_x / (r * (n_x - gamma[itype][jtype])); + + filj6 = +1.0 * gamma[itype][jtype] * n_x * pow_rx_gamma / (r * (n_x - gamma[itype][jtype])); + + // F = -dV/dr + forceilj = -epsilon[itype][jtype] * (filj1 + filj2 + filj3 + filj4 + filj5 + filj6); + fpair = factor_lj * forceilj / r; + if (rsq < cut_in_on_sq) { + rsw = (sqrt(rsq) - cut_in_off) / cut_in_diff; + fpair *= rsw * rsw * (3.0 - 2.0 * rsw); + } + if (rsq > cut_out_on_sq) { + rsw = (sqrt(rsq) - cut_out_on) / cut_out_diff; + fpair *= 1.0 + rsw * rsw * (2.0 * rsw - 3.0); + } + + fxtmp += delx * fpair; + fytmp += dely * fpair; + fztmp += delz * fpair; + if (newton_pair || j < nlocal) { + f[j][0] -= delx * fpair; + f[j][1] -= dely * fpair; + f[j][2] -= delz * fpair; + } + } + } + f[i][0] += fxtmp; + f[i][1] += fytmp; + f[i][2] += fztmp; + } +} + +/* ---------------------------------------------------------------------- */ + +void PairLJPirani::compute_outer(int eflag, int vflag) + +{ + int i, j, ii, jj, inum, jnum, itype, jtype; + double xtmp, ytmp, ztmp, delx, dely, delz, evdwl, fpair; + double rsq, factor_lj, rsw; + int *ilist, *jlist, *numneigh, **firstneigh; + + double r, rx, n_x; + double pow_rx_n_x, pow_rx_gamma; + double filj1, filj2, filj3, filj4, filj5, filj6, forceilj; + double ilj1, ilj2; + double fxtmp, fytmp, fztmp; + + evdwl = 0.0; + ev_init(eflag, vflag); + + double **x = atom->x; + double **f = atom->f; + int *type = atom->type; + int nlocal = atom->nlocal; + double *special_lj = force->special_lj; + int newton_pair = force->newton_pair; + + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; + + double cut_in_off = cut_respa[2]; + double cut_in_on = cut_respa[3]; + + double cut_in_diff = cut_in_on - cut_in_off; + double cut_in_off_sq = cut_in_off * cut_in_off; + double cut_in_on_sq = cut_in_on * cut_in_on; + + // loop over neighbors of my atoms + + for (ii = 0; ii < inum; ii++) { + i = ilist[ii]; + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + jlist = firstneigh[i]; + jnum = numneigh[i]; + fxtmp = fytmp = fztmp = 0.0; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + factor_lj = special_lj[sbmask(j)]; + j &= NEIGHMASK; + + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx * delx + dely * dely + delz * delz; + jtype = type[j]; + + if (rsq < cutsq[itype][jtype]) { + if (rsq > cut_in_off_sq) { + r = sqrt(rsq); + + rx = r / rm[itype][jtype]; + n_x = alpha[itype][jtype] * rx * rx + beta[itype][jtype]; + pow_rx_n_x = pow(1.0 / rx, n_x); + pow_rx_gamma = pow(1.0 / rx, gamma[itype][jtype]); + + filj1 = -2.0 * alpha[itype][jtype] * gamma[itype][jtype] * rx * pow_rx_n_x / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj2 = +2.0 * alpha[itype][jtype] * rx * n_x * pow_rx_gamma / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj3 = -2.0 * alpha[itype][jtype] * rx * pow_rx_gamma / + (rm[itype][jtype] * (n_x - gamma[itype][jtype])); + + filj4 = +2.0 * alpha[itype][jtype] * gamma[itype][jtype] * (rx / rm[itype][jtype]) * + log(1 / rx) * pow_rx_n_x / (n_x - gamma[itype][jtype]); + + filj5 = -1.0 * gamma[itype][jtype] * n_x * pow_rx_n_x / (r * (n_x - gamma[itype][jtype])); + + filj6 = + +1.0 * gamma[itype][jtype] * n_x * pow_rx_gamma / (r * (n_x - gamma[itype][jtype])); + + // F = -dV/dr + forceilj = -epsilon[itype][jtype] * (filj1 + filj2 + filj3 + filj4 + filj5 + filj6); + fpair = factor_lj * forceilj / r; + if (rsq < cut_in_on_sq) { + rsw = (sqrt(rsq) - cut_in_off) / cut_in_diff; + fpair *= rsw * rsw * (3.0 - 2.0 * rsw); + } + + fxtmp += delx * fpair; + fytmp += dely * fpair; + fztmp += delz * fpair; + if (newton_pair || j < nlocal) { + f[j][0] -= delx * fpair; + f[j][1] -= dely * fpair; + f[j][2] -= delz * fpair; + } + } + + if (eflag) { + + r = sqrt(rsq); + + rx = r / rm[itype][jtype]; + n_x = alpha[itype][jtype] * rx * rx + beta[itype][jtype]; + + ilj1 = epsilon[itype][jtype] * gamma[itype][jtype] * pow(1 / rx, n_x) / + (n_x - gamma[itype][jtype]); + ilj2 = -epsilon[itype][jtype] * n_x * pow(1 / rx, gamma[itype][jtype]) / + (n_x - gamma[itype][jtype]); + + evdwl = ilj1 + ilj2 - offset[itype][jtype]; + evdwl *= factor_lj; + } + + if (vflag) { + if (rsq <= cut_in_off_sq) { + + r = sqrt(rsq); + + rx = r / rm[itype][jtype]; + n_x = alpha[itype][jtype] * rx * rx + beta[itype][jtype]; + pow_rx_n_x = pow(1.0 / rx, n_x); + pow_rx_gamma = pow(1.0 / rx, gamma[itype][jtype]); + + filj1 = -2.0 * alpha[itype][jtype] * gamma[itype][jtype] * rx * pow_rx_n_x / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj2 = +2.0 * alpha[itype][jtype] * rx * n_x * pow_rx_gamma / + (square(n_x - gamma[itype][jtype]) * rm[itype][jtype]); + + filj3 = -2.0 * alpha[itype][jtype] * rx * pow_rx_gamma / + (rm[itype][jtype] * (n_x - gamma[itype][jtype])); + + filj4 = +2.0 * alpha[itype][jtype] * gamma[itype][jtype] * (rx / rm[itype][jtype]) * + log(1 / rx) * pow_rx_n_x / (n_x - gamma[itype][jtype]); + + filj5 = + -1.0 * gamma[itype][jtype] * n_x * pow_rx_n_x / (r * (n_x - gamma[itype][jtype])); + + filj6 = + +1.0 * gamma[itype][jtype] * n_x * pow_rx_gamma / (r * (n_x - gamma[itype][jtype])); + + // F = -dV/dr + forceilj = -epsilon[itype][jtype] * (filj1 + filj2 + filj3 + filj4 + filj5 + filj6); + fpair = factor_lj * forceilj / r; + + } else if (rsq < cut_in_on_sq) + fpair = factor_lj * forceilj / r; + } + + if (evflag) ev_tally(i, j, nlocal, newton_pair, evdwl, 0.0, fpair, delx, dely, delz); + } + } + f[i][0] += fxtmp; + f[i][1] += fytmp; + f[i][2] += fztmp; + } +} + +/* ---------------------------------------------------------------------- + global settings +------------------------------------------------------------------------- */ + +void PairLJPirani::settings(int narg, char **arg) +{ + if (narg != 1) + error->all(FLERR, "Pair style ilj/cut must have exactly one argument: cutoff distance"); + + cut_global = utils::numeric(FLERR, arg[0], false, lmp); + + // reset cutoffs that have been explicitly set + + if (allocated) { + int i, j; + for (i = 1; i <= atom->ntypes; i++) + for (j = i; j <= atom->ntypes; j++) + if (setflag[i][j]) cut[i][j] = cut_global; + } +} + +/* ---------------------------------------------------------------------- + set coeffs for one or more type pairs +------------------------------------------------------------------------- */ +/* + +7 or 8 coefficients: 5 for the ILJ, 2 for the pair, 1 for the cutoff (optional) + +*/ +void PairLJPirani::coeff(int narg, char **arg) +{ + if (narg < 7 || narg > 8) error->all(FLERR, "Incorrect args for pair coefficients"); + if (!allocated) allocate(); + + int ilo, ihi, jlo, jhi; + utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error); + utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error); + + double alpha_one = utils::numeric(FLERR, arg[2], false, lmp); + double beta_one = utils::numeric(FLERR, arg[3], false, lmp); + double gamma_one = utils::numeric(FLERR, arg[4], false, lmp); + double rm_one = utils::numeric(FLERR, arg[5], false, lmp); + double epsilon_one = utils::numeric(FLERR, arg[6], false, lmp); + + double cut_one = cut_global; + if (narg == 8) cut_one = utils::numeric(FLERR, arg[7], false, lmp); + + if (rm_one <= 0.0 || epsilon_one < 0.0 || gamma_one <= 0.0) + error->all(FLERR, "Illegal ILJ coefficients"); + + int count = 0; + for (int i = ilo; i <= ihi; i++) { + for (int j = MAX(jlo, i); j <= jhi; j++) { + alpha[i][j] = alpha_one; + beta[i][j] = beta_one; + gamma[i][j] = gamma_one; + rm[i][j] = rm_one; + epsilon[i][j] = epsilon_one; + cut[i][j] = cut_one; + setflag[i][j] = 1; + count++; + } + } + + // Initialize symmetric entries + for (int i = ilo; i <= ihi; i++) { + for (int j = MAX(jlo, i); j <= jhi; j++) { + alpha[j][i] = alpha[i][j]; + beta[j][i] = beta[i][j]; + gamma[j][i] = gamma[i][j]; + rm[j][i] = rm[i][j]; + epsilon[j][i] = epsilon[i][j]; + cut[j][i] = cut[i][j]; + setflag[j][i] = setflag[i][j]; + } + } + + if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients"); +} + +/* ---------------------------------------------------------------------- + init specific to this pair style +------------------------------------------------------------------------- */ + +void PairLJPirani::init_style() +{ + // request regular or rRESPA neighbor list + + int list_style = NeighConst::REQ_DEFAULT; + + if (update->whichflag == 1 && utils::strmatch(update->integrate_style, "^respa")) { + auto respa = dynamic_cast(update->integrate); + if (respa->level_inner >= 0) list_style = NeighConst::REQ_RESPA_INOUT; + if (respa->level_middle >= 0) list_style = NeighConst::REQ_RESPA_ALL; + } + neighbor->add_request(this, list_style); + + // set rRESPA cutoffs + + if (utils::strmatch(update->integrate_style, "^respa") && + (dynamic_cast(update->integrate))->level_inner >= 0) + cut_respa = (dynamic_cast(update->integrate))->cutoff; + else + cut_respa = nullptr; +} + +/* ---------------------------------------------------------------------- + init for one type pair i,j and corresponding j,i +------------------------------------------------------------------------- */ + +double PairLJPirani::init_one(int i, int j) +{ + if (setflag[i][j] == 0) error->all(FLERR, "All pair coeffs are not set"); + + if (offset_flag && (cut[i][j] > 0.0)) { + double r = cut[i][j] / rm[i][j]; + double nx = alpha[i][j] * r * r + beta[i][j]; + offset[i][j] = epsilon[i][j] * + ((gamma[i][j] / (nx - gamma[i][j])) * pow(1 / r, nx) - + (nx / (nx - gamma[i][j])) * pow(1 / r, gamma[i][j])); + } else + offset[i][j] = 0.0; + + alpha[j][i] = alpha[i][j]; + beta[j][i] = beta[i][j]; + gamma[j][i] = gamma[i][j]; + rm[j][i] = rm[i][j]; + epsilon[j][i] = epsilon[i][j]; + offset[j][i] = offset[i][j]; + + // check interior rRESPA cutoff + + if (cut_respa && cut[i][j] < cut_respa[3]) + error->all(FLERR, "Pair cutoff < Respa interior cutoff"); + + return cut[i][j]; +} + +/* ---------------------------------------------------------------------- + proc 0 writes to restart file +------------------------------------------------------------------------- */ + +void PairLJPirani::write_restart(FILE *fp) +{ + write_restart_settings(fp); + + int i, j; + for (i = 1; i <= atom->ntypes; i++) + for (j = i; j <= atom->ntypes; j++) { + fwrite(&setflag[i][j], sizeof(int), 1, fp); + if (setflag[i][j]) { + fwrite(&alpha[i][j], sizeof(double), 1, fp); + fwrite(&beta[i][j], sizeof(double), 1, fp); + fwrite(&gamma[i][j], sizeof(double), 1, fp); + fwrite(&rm[i][j], sizeof(double), 1, fp); + fwrite(&epsilon[i][j], sizeof(double), 1, fp); + fwrite(&cut[i][j], sizeof(double), 1, fp); + } + } +} + +/* ---------------------------------------------------------------------- + proc 0 writes to restart file +------------------------------------------------------------------------- */ + +void PairLJPirani::write_restart_settings(FILE *fp) +{ + fwrite(&cut_global, sizeof(double), 1, fp); + fwrite(&offset_flag, sizeof(int), 1, fp); + fwrite(&mix_flag, sizeof(int), 1, fp); +} + +/* ---------------------------------------------------------------------- + proc 0 reads from restart file, bcasts +------------------------------------------------------------------------- */ + +void PairLJPirani::read_restart(FILE *fp) +{ + read_restart_settings(fp); + allocate(); + + int i, j; + int me = comm->me; + for (i = 1; i <= atom->ntypes; i++) + for (j = i; j <= atom->ntypes; j++) { + if (me == 0) utils::sfread(FLERR, &setflag[i][j], sizeof(int), 1, fp, nullptr, error); + MPI_Bcast(&setflag[i][j], 1, MPI_INT, 0, world); + if (setflag[i][j]) { + if (me == 0) { + utils::sfread(FLERR, &alpha[i][j], sizeof(double), 1, fp, nullptr, error); + utils::sfread(FLERR, &beta[i][j], sizeof(double), 1, fp, nullptr, error); + utils::sfread(FLERR, &gamma[i][j], sizeof(double), 1, fp, nullptr, error); + utils::sfread(FLERR, &rm[i][j], sizeof(double), 1, fp, nullptr, error); + utils::sfread(FLERR, &epsilon[i][j], sizeof(double), 1, fp, nullptr, error); + utils::sfread(FLERR, &cut[i][j], sizeof(double), 1, fp, nullptr, error); + } + MPI_Bcast(&alpha[i][j], 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&beta[i][j], 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&gamma[i][j], 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&rm[i][j], 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&epsilon[i][j], 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&cut[i][j], 1, MPI_DOUBLE, 0, world); + } + } +} + +/* ---------------------------------------------------------------------- + proc 0 reads from restart file, bcasts +------------------------------------------------------------------------- */ + +void PairLJPirani::read_restart_settings(FILE *fp) +{ + int me = comm->me; + if (me == 0) { + utils::sfread(FLERR, &cut_global, sizeof(double), 1, fp, nullptr, error); + utils::sfread(FLERR, &offset_flag, sizeof(int), 1, fp, nullptr, error); + utils::sfread(FLERR, &mix_flag, sizeof(int), 1, fp, nullptr, error); + } + MPI_Bcast(&cut_global, 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&offset_flag, 1, MPI_INT, 0, world); + MPI_Bcast(&mix_flag, 1, MPI_INT, 0, world); +} + +/* ---------------------------------------------------------------------- + proc 0 writes to data file +------------------------------------------------------------------------- */ + +void PairLJPirani::write_data(FILE *fp) +{ + for (int i = 1; i <= atom->ntypes; i++) + fprintf(fp, "%d %g %g %g %g %g\n", i, alpha[i][i], beta[i][i], gamma[i][i], rm[i][i], + epsilon[i][i]); +} + +/* ---------------------------------------------------------------------- + proc 0 writes all pairs to data file +------------------------------------------------------------------------- */ + +void PairLJPirani::write_data_all(FILE *fp) +{ + for (int i = 1; i <= atom->ntypes; i++) + for (int j = i; j <= atom->ntypes; j++) + fprintf(fp, "%d %d %g %g %g %g %g %g\n", i, j, alpha[i][j], beta[i][j], gamma[i][j], rm[i][j], + epsilon[i][j], cut[i][j]); +} + +/* ---------------------------------------------------------------------- */ + +double PairLJPirani::single(int /*i*/, int /*j*/, int itype, int jtype, double rsq, + double /*factor_coul*/, double factor_lj, double &fforce) +{ + double r, rx, n_x, filj1, filj2, filj3, filj4, filj5, filj6, forceilj; + double ilj1, ilj2; + + r = sqrt(rsq); + rx = r / rm[itype][jtype]; + n_x = alpha[itype][jtype] * rx * rx + beta[itype][jtype]; + filj1 = -2.0 * alpha[itype][jtype] * gamma[itype][jtype] * rx * pow(1 / rx, n_x) / + (pow(n_x - gamma[itype][jtype], 2.0) * rm[itype][jtype]); + + filj2 = +2.0 * alpha[itype][jtype] * rx * n_x * pow(1 / rx, gamma[itype][jtype]) / + (pow(n_x - gamma[itype][jtype], 2.0) * rm[itype][jtype]); + + filj3 = -2.0 * alpha[itype][jtype] * rx * pow(1 / rx, gamma[itype][jtype]) / + (rm[itype][jtype] * (n_x - gamma[itype][jtype])); + + filj4 = +2.0 * alpha[itype][jtype] * gamma[itype][jtype] * (rx / rm[itype][jtype]) * log(1 / rx) * + pow(1 / rx, n_x) / (n_x - gamma[itype][jtype]); + + filj5 = -1.0 * gamma[itype][jtype] * n_x * pow(1 / rx, n_x) / (r * (n_x - gamma[itype][jtype])); + + filj6 = +1.0 * gamma[itype][jtype] * n_x * pow(1 / rx, gamma[itype][jtype]) / + (r * (n_x - gamma[itype][jtype])); + + forceilj = -epsilon[itype][jtype] * (filj1 + filj2 + filj3 + filj4 + filj5 + filj6); + + fforce = factor_lj * forceilj / r; + + ilj1 = + epsilon[itype][jtype] * gamma[itype][jtype] * pow(1 / rx, n_x) / (n_x - gamma[itype][jtype]); + ilj2 = + -epsilon[itype][jtype] * n_x * pow(1 / rx, gamma[itype][jtype]) / (n_x - gamma[itype][jtype]); + return factor_lj * (ilj1 + ilj2 - offset[itype][jtype]); +} + +/* ---------------------------------------------------------------------- */ + +void *PairLJPirani::extract(const char *str, int &dim) +{ + dim = 2; + if (strcmp(str, "alpha") == 0) return (void *) alpha; + if (strcmp(str, "beta") == 0) return (void *) beta; + if (strcmp(str, "gamma") == 0) return (void *) gamma; + if (strcmp(str, "rm") == 0) return (void *) rm; + if (strcmp(str, "epsilon") == 0) return (void *) epsilon; + return nullptr; +} diff --git a/src/EXTRA-PAIR/pair_lj_pirani.h b/src/EXTRA-PAIR/pair_lj_pirani.h new file mode 100644 index 0000000000..0fa3a16fe9 --- /dev/null +++ b/src/EXTRA-PAIR/pair_lj_pirani.h @@ -0,0 +1,60 @@ +/* -*- 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 PAIR_CLASS +// clang-format off +PairStyle(lj/pirani,PairLJPirani); +// clang-format on +#else + +#ifndef LMP_PAIR_LJ_PIRANI_H +#define LMP_PAIR_LJ_PIRANI_H + +#include "pair.h" + +namespace LAMMPS_NS { + +class PairLJPirani : public Pair { + public: + PairLJPirani(class LAMMPS *); + virtual ~PairLJPirani() override; + void compute(int, int) override; + void settings(int, char **) override; + void coeff(int, char **) override; + void init_style() override; + double init_one(int, int) override; + void write_restart(FILE *) override; + void read_restart(FILE *) override; + void write_restart_settings(FILE *) override; + void read_restart_settings(FILE *) override; + void write_data(FILE *) override; + void write_data_all(FILE *) override; + double single(int, int, int, int, double, double, double, double &) override; + void *extract(const char *, int &) override; + void compute_inner() override; + void compute_middle() override; + void compute_outer(int, int) override; + + protected: + double cut_global; + double **cut; + double **alpha, **beta, **gamma, **rm, **epsilon; + double **offset; + double *cut_respa; + virtual void allocate(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/GRANULAR/fix_add_heat.cpp b/src/GRANULAR/fix_add_heat.cpp index 73bf8a9a26..330723700b 100644 --- a/src/GRANULAR/fix_add_heat.cpp +++ b/src/GRANULAR/fix_add_heat.cpp @@ -20,11 +20,13 @@ #include "atom.h" #include "error.h" #include "input.h" +#include "math_special.h" #include "memory.h" #include "variable.h" using namespace LAMMPS_NS; using namespace FixConst; +using MathSpecial::powint; enum { CONSTANT, EQUAL, ATOM }; enum { ADD, LINEAR, QUARTIC }; @@ -152,7 +154,7 @@ void FixAddHeat::post_force(int /*vflag*/) } else if (style == LINEAR) { heatflow[i] += prefactor * (vtmp - temperature[i]); } else if (style == QUARTIC) { - heatflow[i] += prefactor * (pow(vtmp, 4.0) - pow(temperature[i], 4.0)); + heatflow[i] += prefactor * (powint(vtmp, 4) - powint(temperature[i], 4)); } } } diff --git a/src/GRANULAR/fix_granular_mdr.cpp b/src/GRANULAR/fix_granular_mdr.cpp index 9efabdf465..0416edc432 100644 --- a/src/GRANULAR/fix_granular_mdr.cpp +++ b/src/GRANULAR/fix_granular_mdr.cpp @@ -29,6 +29,7 @@ #include "granular_model.h" #include "input.h" #include "math_const.h" +#include "math_special.h" #include "memory.h" #include "modify.h" #include "neigh_list.h" @@ -43,9 +44,10 @@ using namespace Granular_NS; using namespace Granular_MDR_NS; using namespace FixConst; using MathConst::MY_PI; +using MathSpecial::cube; static constexpr double EPSILON = 1e-16; -static constexpr double OVERLAP_LIMIT = 0.75; +static constexpr double OVERLAP_LIMIT = 0.95; enum { COMM_1, COMM_2 }; @@ -85,7 +87,7 @@ void FixGranularMDR::post_constructor() modify->add_fix( fmt::format("{} all property/atom d_Ro d_Vcaps d_Vgeo d_Velas d_eps_bar d_dRnumerator " "d_dRdenominator d_Acon0 d_Acon1 d_Atot d_Atot_sum d_ddelta_bar d_psi " - "d_history_setup_flag d_sigmaxx d_sigmayy d_sigmazz ghost yes", + "d_history_setup_flag d_sigmaxx d_sigmayy d_sigmazz d_dRavg ghost yes", id_fix)); index_Ro = atom->find_custom("Ro", tmp1, tmp2); @@ -105,6 +107,7 @@ void FixGranularMDR::post_constructor() index_sigmaxx = atom->find_custom("sigmaxx", tmp1, tmp2); index_sigmayy = atom->find_custom("sigmayy", tmp1, tmp2); index_sigmazz = atom->find_custom("sigmazz", tmp1, tmp2); + index_dRavg = atom->find_custom("dRavg", tmp1, tmp2); } /* ---------------------------------------------------------------------- */ @@ -153,31 +156,31 @@ void FixGranularMDR::setup_pre_force(int /*vflag*/) norm_model2 = dynamic_cast(fix->model->normal_model); - if (norm_model && norm_model2 && (norm_model->E != norm_model2->E)) + if (norm_model && norm_model2 && fabs(norm_model->get_emod() - norm_model2->get_emod()) > EPSILON) error->all( FLERR, Error::NOLASTLINE, "Young's modulus in pair style, {}, does not agree with value {} in fix gran/wall/region", - norm_model->E, norm_model2->E); - if (norm_model->nu != norm_model2->nu) + norm_model->get_emod(), norm_model2->get_emod()); + if (fabs(norm_model->get_poiss() - norm_model2->get_poiss()) > EPSILON) error->all( FLERR, Error::NOLASTLINE, "Poisson's ratio in pair style, {}, does not agree with value {} in fix gran/wall/region", - norm_model->nu, norm_model2->nu); - if (norm_model->Y != norm_model2->Y) + norm_model->get_poiss(), norm_model2->get_poiss()); + if (fabs(norm_model->Y - norm_model2->Y) > EPSILON) error->all( FLERR, Error::NOLASTLINE, "Yield stress in pair style, {}, does not agree with value {} in fix gran/wall/region", norm_model->Y, norm_model2->Y); - if (norm_model->psi_b != norm_model2->psi_b) + if (fabs(norm_model->psi_b - norm_model2->psi_b) > EPSILON) error->all(FLERR, Error::NOLASTLINE, "Bulk response trigger in pair style, {}, does not agree with value {} in fix " "gran/wall/region", norm_model->psi_b, norm_model2->psi_b); - if (norm_model->CoR != norm_model2->CoR) + if (fabs(norm_model->get_damp() - norm_model2->get_damp()) > EPSILON) error->all(FLERR, Error::NOLASTLINE, - "Coefficient of restitution in pair style, {}, does not agree with value {} in " + "Damping in pair style, {}, does not agree with value {} in " "fix gran/wall/region", - norm_model->CoR, norm_model2->CoR); + norm_model->get_damp(), norm_model2->get_damp()); } fix_history = dynamic_cast(modify->get_fix_by_id("NEIGH_HISTORY_GRANULAR")); @@ -208,6 +211,7 @@ void FixGranularMDR::pre_force(int) double *sigmayy = atom->dvector[index_sigmayy]; double *sigmazz = atom->dvector[index_sigmazz]; double *history_setup_flag = atom->dvector[index_history_setup_flag]; + double *dRavg = atom->dvector[index_dRavg]; int new_atom; int nlocal = atom->nlocal; @@ -241,17 +245,24 @@ void FixGranularMDR::pre_force(int) if (update->setupflag && (!new_atom)) continue; const double R = radius[i]; - const double Vo = 4.0 / 3.0 * MY_PI * pow(Ro[i], 3.0); - const double Vgeoi = 4.0 / 3.0 * MY_PI * pow(R, 3.0) - Vcaps[i]; + const double Rsq = R * R; + const double Vo = 4.0 / 3.0 * MY_PI * cube(Ro[i]); + const double Vgeoi = 4.0 / 3.0 * MY_PI * Rsq * R - Vcaps[i]; Vgeo[i] = MIN(Vgeoi, Vo); Velas[i] = Vo * (1.0 + eps_bar[i]); - Atot[i] = 4.0 * MY_PI * pow(R, 2.0) + Atot_sum[i]; + Atot[i] = 4.0 * MY_PI * Rsq + Atot_sum[i]; psi[i] = (Atot[i] - Acon1[i]) / Atot[i]; if (psi_b_coeff < psi[i]) { - const double dR = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0)), 0.0); - if ((radius[i] + dR) < (1.5 * Ro[i])) radius[i] += dR; + double w_confinement; + ( psi[i] > 0.1 ) ? w_confinement = 1.0 / (1.0 + exp(-75.0 * (psi[i] - 0.2))) : w_confinement = 0.0; + const double dR = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * Rsq) * w_confinement, 0.0); + + const double N_window = 10.0; + if (dR > 0.0) dRavg[i] += (dR - dRavg[i]) / N_window; + + if (((radius[i] + dR) < (1.5 * Ro[i])) && (dR > 0.0)) radius[i] += dRavg[i]; } Acon0[i] = Acon1[i]; } diff --git a/src/GRANULAR/fix_granular_mdr.h b/src/GRANULAR/fix_granular_mdr.h index f0ba76d155..fce727fe5d 100644 --- a/src/GRANULAR/fix_granular_mdr.h +++ b/src/GRANULAR/fix_granular_mdr.h @@ -51,7 +51,8 @@ namespace Granular_MDR_NS { PENALTY, // contact penalty DELTA_MAX, DELTAP_0, - DELTAP_1 + DELTAP_1, + DAMP_SCALE }; } // namespace Granular_MDR_NS @@ -97,8 +98,7 @@ class FixGranularMDR : public Fix { int index_sigmayy; // yy-component of the stress tensor, not necessary forforce calculation int index_sigmazz; // zz-component of the stress tensor, not necessary forforce calculation int index_history_setup_flag; // flag to check if history variables have beeninitialized - int index_contacts; // total contacts on particle - int index_adhesive_length; // total length of adhesive contact on a particle + int index_dRavg; // average radius update increment }; } // namespace LAMMPS_NS diff --git a/src/GRANULAR/fix_pour.cpp b/src/GRANULAR/fix_pour.cpp index 65cc356739..2d4090ea53 100644 --- a/src/GRANULAR/fix_pour.cpp +++ b/src/GRANULAR/fix_pour.cpp @@ -540,7 +540,7 @@ void FixPour::pre_exchange() delx = coords[m][0] - xnear[i][0]; dely = coords[m][1] - xnear[i][1]; delz = coords[m][2] - xnear[i][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); rsq = delx * delx + dely * dely + delz * delz; radsum = coords[m][3] + xnear[i][3]; if (rsq <= radsum * radsum) break; @@ -781,7 +781,7 @@ int FixPour::overlap(int i) double delx = x[0] - xc; double dely = x[1] - yc; double delz = 0.0; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); double rsq = delx * delx + dely * dely; double r = rc + delta; if (rsq > r * r) return 0; diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index 2fdd7e1f82..f85b866f8d 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -13,11 +13,14 @@ #include "gran_sub_mod_damping.h" +#include "error.h" #include "gran_sub_mod_normal.h" +#include "fix_granular_mdr.h" #include "granular_model.h" #include "math_special.h" #include "math_const.h" +#include "style_gran_sub_mod.h" // IWYU pragma: keep #include using namespace LAMMPS_NS; @@ -41,6 +44,9 @@ GranSubModDamping::GranSubModDamping(GranularModel *gm, LAMMPS *lmp) : GranSubMo void GranSubModDamping::init() { + if (gm->normal_model->name == "mdr") + error->all(FLERR, "Only damping mdr may be used with the mdr normal model"); + damp = gm->normal_model->get_damp(); } @@ -127,6 +133,9 @@ GranSubModDampingTsuji::GranSubModDampingTsuji(GranularModel *gm, LAMMPS *lmp) : void GranSubModDampingTsuji::init() { + if (gm->normal_model->name == "mdr") + error->all(FLERR, "Only damping mdr may be used with the mdr normal model"); + double tmp = gm->normal_model->get_damp(); damp = 1.2728 - 4.2783 * tmp + 11.087 * square(tmp); damp += -22.348 * cube(tmp) + 27.467 * powint(tmp, 4); @@ -160,6 +169,9 @@ GranSubModDampingCoeffRestitution::GranSubModDampingCoeffRestitution(GranularMod void GranSubModDampingCoeffRestitution::init() { + if (gm->normal_model->name == "mdr") + error->all(FLERR, "Only damping mdr may be used with the mdr normal model"); + // Calculate prefactor, assume Hertzian as default double cor = gm->normal_model->get_damp(); double logcor = log(cor); @@ -170,3 +182,48 @@ void GranSubModDampingCoeffRestitution::init() damp /= sqrt(MY_PI * MY_PI + logcor * logcor); } } + +/* ---------------------------------------------------------------------- + MDR damping +------------------------------------------------------------------------- */ + +GranSubModDampingMDR::GranSubModDampingMDR(GranularModel *gm, LAMMPS *lmp) : + GranSubModDamping(gm, lmp) +{ + num_coeffs = 1; +} + +void GranSubModDampingMDR::coeffs_to_local() +{ + damp_type = coeffs[0]; // damping type 1 = mdr stiffness or 2 = velocity + if (damp_type != 1 && damp_type != 2) + error->all(FLERR, "Illegal MDR damping model, damping type must an integer equal to 1 or 2"); +} + +/* ---------------------------------------------------------------------- */ + +void GranSubModDampingMDR::init() +{ + if (gm->normal_model->name != "mdr") + error->all(FLERR, "Damping mdr can only be used with mdr normal model"); + + damp = gm->normal_model->get_damp(); +} + +/* ---------------------------------------------------------------------- */ + +double GranSubModDampingMDR::calculate_forces() +{ + using namespace Granular_MDR_NS; + double *history = & gm->history[gm->normal_model->history_index]; + if (damp_type == 1) { + damp_prefactor = damp * history[DAMP_SCALE]; + } else if (damp_type == 2) { + if (history[DAMP_SCALE] == 0.0) { + damp_prefactor = 0.0; + } else { + damp_prefactor = damp; + } + } + return -damp_prefactor * gm->vnnr; +} diff --git a/src/GRANULAR/gran_sub_mod_damping.h b/src/GRANULAR/gran_sub_mod_damping.h index 98c31d680a..ac1363f64f 100644 --- a/src/GRANULAR/gran_sub_mod_damping.h +++ b/src/GRANULAR/gran_sub_mod_damping.h @@ -19,6 +19,7 @@ GranSubModStyle(mass_velocity,GranSubModDampingMassVelocity,DAMPING); GranSubModStyle(viscoelastic,GranSubModDampingViscoelastic,DAMPING); GranSubModStyle(tsuji,GranSubModDampingTsuji,DAMPING); GranSubModStyle(coeff_restitution,GranSubModDampingCoeffRestitution,DAMPING); +GranSubModStyle(mdr,GranSubModDampingMDR,DAMPING); // clang-format on #else @@ -48,7 +49,6 @@ namespace Granular_NS { class GranSubModDampingNone : public GranSubModDamping { public: GranSubModDampingNone(class GranularModel *, class LAMMPS *); - void init() override{}; double calculate_forces() override; }; @@ -95,6 +95,19 @@ namespace Granular_NS { /* ---------------------------------------------------------------------- */ + class GranSubModDampingMDR : public GranSubModDamping { + public: + GranSubModDampingMDR(class GranularModel *, class LAMMPS *); + void coeffs_to_local() override; + void init() override; + double calculate_forces() override; + + protected: + int damp_type; + }; + + /* ---------------------------------------------------------------------- */ + } // namespace Granular_NS } // namespace LAMMPS_NS diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index 226d26d86b..a4e2aecdc4 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -19,16 +19,18 @@ #include "fix_granular_mdr.h" #include "granular_model.h" #include "math_const.h" +#include "math_special.h" #include "modify.h" #include "update.h" #include -#include -#include using namespace LAMMPS_NS; using namespace Granular_NS; using namespace MathConst; +using MathSpecial::square; +using MathSpecial::cube; +using MathSpecial::powint; static constexpr double PISQ = 9.8696044010893579923; // PI^2 static constexpr double PIINV = 0.318309886183790691216; // 1/PI @@ -47,7 +49,7 @@ static constexpr int MDR_MAX_IT = 100; // Newton-Raphs static constexpr double MDR_EPSILON1 = 1e-10; // Newton-Raphson for MDR static constexpr double MDR_EPSILON2 = 1e-16; // Newton-Raphson for MDR static constexpr double MDR_EPSILON3 = 1e-20; // For precision checks -static constexpr double MDR_OVERLAP_LIMIT = 0.75; // Maximum contact overlap for MDR +static constexpr double MDR_OVERLAP_LIMIT = 0.95; // Maximum contact overlap for MDR static const char cite_mdr[] = "MDR contact model command: (i) https://doi.org/10.1016/j.jmps.2023.105492 || (ii) https://doi.org/10.1016/j.jmps.2023.105493 || (iii) https://doi.org/10.31224/4289\n\n" @@ -73,8 +75,9 @@ static const char cite_mdr[] = " author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken},\n" " title = {Experimentally validated DEM for large deformation powder compaction:\n" " mechanically-derived contact model and screening of non-physical contacts},\n" + " journal = {Powder Technology},\n" " year = {2025},\n" - " journal = {engrXiv},\n" + " pages = {120972},\n" "}\n\n"; /* ---------------------------------------------------------------------- @@ -442,9 +445,10 @@ GranSubModNormalMDR::GranSubModNormalMDR(GranularModel *gm, LAMMPS *lmp) : num_coeffs = 6; contact_radius_flag = 1; - size_history = 26; + size_history = 27; nsvector = 1; fix_mdr_flag = 0; + material_properties = 1; id_fix = nullptr; nondefault_history_transfer = 1; @@ -467,29 +471,30 @@ GranSubModNormalMDR::~GranSubModNormalMDR() void GranSubModNormalMDR::coeffs_to_local() { - E = coeffs[0]; // Young's modulus - nu = coeffs[1]; // Poisson's ratio - Y = coeffs[2]; // yield stress - gamma = coeffs[3]; // effective surface energy - psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total} - CoR = coeffs[5]; // coefficent of restitution + Emod = coeffs[0]; // Young's modulus + poiss = coeffs[1]; // Poisson's ratio + Y = coeffs[2]; // yield stress + gamma = coeffs[3]; // effective surface energy + psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total} + damp = coeffs[5]; // coefficent of restitution - if (E <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0"); - if (nu < 0.0 || nu > 0.5) error->all(FLERR, "Illegal MDR normal model, Poisson's ratio must be between 0 and 0.5"); + if (Emod <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0"); + if (poiss < 0.0 || poiss > 0.5) error->all(FLERR, "Illegal MDR normal model, Poisson's ratio must be between 0 and 0.5"); if (Y < 0.0) error->all(FLERR, "Illegal MDR normal model, yield stress must be greater than or equal to 0"); if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0"); if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0"); - if (CoR < 0.0 || CoR > 1.0) error->all(FLERR, "Illegal MDR normal model, coefficent of restitution must be between 0 and 1.0"); + if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than or equal to 0"); - G = E / (2.0 * (1.0 + nu)); // shear modulus - kappa = E / (3.0 * (1.0 - 2.0 * nu)); // bulk modulus - Eeff = E / (1.0 - pow(nu, 2.0)); // composite plane strain modulus + G = Emod / (2.0 * (1.0 + poiss)); // shear modulus + kappa = Emod / (3.0 * (1.0 - 2.0 * poiss)); // bulk modulus + Eeff = Emod / (1.0 - square(poiss)); // composite plane strain modulus // precomputing factors Eeffinv = 1.0 / Eeff; Eeffsq = Eeff * Eeff; Eeffsqinv = Eeffinv * Eeffinv; + Eeff2particle = 0.5 * Eeff; gammasq = gamma * gamma; gamma3 = gammasq * gamma; @@ -528,6 +533,7 @@ void GranSubModNormalMDR::init() index_sigmaxx = atom->find_custom("sigmaxx", tmp1, tmp2); // xx-component of the stress tensor, not necessary for force calculation index_sigmayy = atom->find_custom("sigmayy", tmp1, tmp2); // yy-component of the stress tensor, not necessary for force calculation index_sigmazz = atom->find_custom("sigmazz", tmp1, tmp2); // zz-component of the stress tensor, not necessary for force calculation + index_dRavg = atom->find_custom("dRavg", tmp1, tmp2); // radius update increment } /* ---------------------------------------------------------------------- */ @@ -566,6 +572,7 @@ double GranSubModNormalMDR::calculate_forces() double *sigmaxx = atom->dvector[index_sigmaxx]; double *sigmayy = atom->dvector[index_sigmayy]; double *sigmazz = atom->dvector[index_sigmazz]; + double *dRavg = atom->dvector[index_dRavg]; const int itag_true = atom->tag[gm->i]; // true i particle tag const int jtag_true = atom->tag[gm->j]; // true j particle tag @@ -579,6 +586,7 @@ double GranSubModNormalMDR::calculate_forces() double F1 = 0.0; // force on contact side 1 double delta = gm->delta; // apparent overlap double Ac_avg = 0.0; // average contact area across both sides + double a_damp = 0.0; // damping contact radius double *history = & gm->history[history_index]; // load in all history variables int history_update = gm->history_update; @@ -596,7 +604,6 @@ double GranSubModNormalMDR::calculate_forces() if (gm->delta >= *deltamax_offset) *deltamax_offset = gm->delta; double deltamax = *deltamax_offset; - for (int contactSide = 0; contactSide < 2; contactSide++) { double *delta_offset, *deltao_offset, *delta_MDR_offset, *delta_BULK_offset; @@ -607,17 +614,17 @@ double GranSubModNormalMDR::calculate_forces() // displacement partitioning only necessary for particle-particle contact // itag and jtag persist after neighbor list builds, use tags to compare to match - // contact history variables consistently across steps for a particle pair. + // contact history variables consistently across steps for a particle pair. if ((contactSide == 0 && itag_true > jtag_true) || (contactSide != 0 && itag_true < jtag_true)) { - gm->i = i_true; - gm->j = j_true; - gm->radi = radi_true; - gm->radj = radj_true; + gm->i = i_true; + gm->j = j_true; + gm->radi = radi_true; + gm->radj = radj_true; } else { - gm->i = j_true; - gm->j = i_true; - gm->radi = radj_true; - gm->radj = radi_true; + gm->i = j_true; + gm->j = i_true; + gm->radi = radj_true; + gm->radj = radi_true; } // determine the two maximum experienced geometric overlaps on either side of rigid flat @@ -715,7 +722,7 @@ double GranSubModNormalMDR::calculate_forces() if (history_update && phertz > pY) { *Yflag_offset = 1.0; *deltaY_offset = delta_MDR; - *cA_offset = MY_PI * (pow(*deltaY_offset, 2) - *deltaY_offset * R); + *cA_offset = MY_PI * (square(*deltaY_offset) - *deltaY_offset * R); } } @@ -737,7 +744,7 @@ double GranSubModNormalMDR::calculate_forces() amax = sqrt(deltamax_MDR * R); } else { // plastic contact - amax = sqrt(2.0 * deltamax_MDR * R - pow(deltamax_MDR, 2) + cA * PIINV); + amax = sqrt(2.0 * deltamax_MDR * R - square(deltamax_MDR) + cA * PIINV); amaxsq = amax * amax; A = 4.0 * pY * Eeffinv * amax; Ainv = 1.0 / A; @@ -748,13 +755,13 @@ double GranSubModNormalMDR::calculate_forces() // force caused by full submersion of elliptical indenter to depth of A/2 double Fmax = Eeff * (A * B * 0.25) * acos(1 - 2 * deltae1Dmax * Ainv); - Fmax -= (2 - 4 * deltae1Dmax * Ainv) * sqrt(deltae1Dmax * Ainv - pow(deltae1Dmax * Ainv, 2)); + Fmax -= (2 - 4 * deltae1Dmax * Ainv) * sqrt(deltae1Dmax * Ainv - square(deltae1Dmax * Ainv)); // depth of particle center const double zR = R - (deltamax_MDR - deltae1Dmax); - deltaR = 2 * amaxsq * (-1 + nu) - (-1 + 2 * nu) * zR * (-zR + sqrt(amaxsq + pow(zR, 2))); - deltaR *= Fmax / (MY_2PI * amaxsq * G * sqrt(amaxsq + pow(zR, 2))); + deltaR = 2 * amaxsq * (-1 + poiss) - (-1 + 2 * poiss) * zR * (-zR + sqrt(amaxsq + square(zR))); + deltaR *= Fmax / (MY_2PI * amaxsq * G * sqrt(amaxsq + square(zR))); // transformed elastic displacement deltae1D = (delta_MDR - deltamax_MDR + deltae1Dmax + deltaR) / (1 + deltaR / deltae1Dmax); @@ -805,17 +812,17 @@ double GranSubModNormalMDR::calculate_forces() } if (std::isnan(F_MDR)) - error->one(FLERR, "F_MDR is NaN, case 1: no tensile springs"); + error->one(FLERR, "F_MDR is NaN, case 1: no tensile springs for atoms {} and {}", itag_true, jtag_true); if (history_update) *aAdh_offset = a_fac * a_na; } else { // case 2+3, tensile springs const double lmax = sqrt(MY_2PI * aAdh * gamma * Eeffinv); - g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - pow(aAdh, 2)); + g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - square(aAdh)); g_aAdh = round_up_negative_epsilon(g_aAdh); double tmp = 27 * A4 * B4 * gamma * Eeffinv; - tmp -= 2 * pow(B, 6) * gamma3 * PISQ * pow(Eeffinv, 3); + tmp -= 2 * powint(B, 6) * gamma3 * PISQ * cube(Eeffinv); tmp += sqrt(27) * Asq * B4 * sqrt(27 * A4 * Eeffsq * gammasq - 4 * Bsq * gamma4 * PISQ) * Eeffsqinv; tmp = cbrt(tmp); @@ -843,12 +850,12 @@ double GranSubModNormalMDR::calculate_forces() double aAdh_tmp = aAdh; double fa, fa2, fa_tmp, dfda; for (int lv1 = 0; lv1 < MDR_MAX_IT; ++lv1) { - fa_tmp = deltae1D - A * 0.5 + A * sqrt(Bsq * 0.25 - pow(aAdh_tmp, 2)) * Binv; + fa_tmp = deltae1D - A * 0.5 + A * sqrt(Bsq * 0.25 - square(aAdh_tmp)) * Binv; fa = fa_tmp + sqrt(MY_2PI * aAdh_tmp * gamma * Eeffinv); if (abs(fa) < MDR_EPSILON1) { break; } - dfda = -aAdh_tmp * A / (B * sqrt(-pow(aAdh_tmp, 2) + Bsq * 0.25)); + dfda = -aAdh_tmp * A / (B * sqrt(-square(aAdh_tmp) + Bsq * 0.25)); dfda += gamma * SQRTHALFPI / sqrt(aAdh_tmp * gamma * Eeff); aAdh_tmp = aAdh_tmp - fa / dfda; fa2 = fa_tmp + sqrt(MY_2PI * aAdh_tmp * gamma * Eeffinv); @@ -861,15 +868,20 @@ double GranSubModNormalMDR::calculate_forces() } aAdh = aAdh_tmp; - g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - pow(aAdh, 2)); - g_aAdh = round_up_negative_epsilon(g_aAdh); + if (aAdh < acrit) { + aAdh = 0.0; + F_MDR = 0.0; + } else { + g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - square(aAdh)); + g_aAdh = round_up_negative_epsilon(g_aAdh); - const double deltaeAdh = g_aAdh; - const double F_na = calculate_nonadhesive_mdr_force(deltaeAdh, Ainv, Eeff, A, B); - const double F_Adhes = 2.0 * Eeff * (deltae1D - deltaeAdh) * aAdh; - F_MDR = F_na + F_Adhes; - if (std::isnan(F_MDR)) - error->one(FLERR, "F_MDR is NaN, case 3: tensile springs exceed critical length"); + const double deltaeAdh = g_aAdh; + const double F_na = calculate_nonadhesive_mdr_force(deltaeAdh, Ainv, Eeff, A, B); + const double F_Adhes = 2.0 * Eeff * (deltae1D - deltaeAdh) * aAdh; + F_MDR = F_na + F_Adhes; + if (std::isnan(F_MDR)) + error->one(FLERR, "F_MDR is NaN, case 3: tensile springs exceed critical length"); + } } if (history_update) *aAdh_offset = aAdh; } @@ -883,7 +895,7 @@ double GranSubModNormalMDR::calculate_forces() // area related calculations double Ac; - (*Yflag_offset == 0.0) ? Ac = MY_PI * delta * R : Ac = MY_PI * (2.0 * delta * R - pow(delta, 2)) + cA; + (*Yflag_offset == 0.0) ? Ac = MY_PI * delta * R : Ac = MY_PI * (2.0 * delta * R - square(delta)) + cA; if (Ac < 0.0) Ac = 0.0; if (history_update) { Atot_sum[i] += wij * (Ac - MY_2PI * R * (deltamax_MDR + delta_BULK)); @@ -891,6 +903,9 @@ double GranSubModNormalMDR::calculate_forces() } Ac_avg += wij * Ac; + // contact radius for damping + (gamma > 0.0) ? a_damp += aAdh : a_damp += a_na; + // bulk force calculation double F_BULK; (delta_BULK <= 0.0) ? F_BULK = 0.0 : F_BULK = (1.0 / Vgeo[i]) * Acon0[i] * delta_BULK * kappa * Ac; @@ -903,7 +918,7 @@ double GranSubModNormalMDR::calculate_forces() *Ac_offset = wij * Ac; // radius update scheme quantity calculation - Vcaps[i] += MY_PI * THIRD * pow(delta, 2) * (3.0 * R - delta); + Vcaps[i] += MY_PI * THIRD * square(delta) * (3.0 * R - delta); } const double Fntmp = wij * (F_MDR + F_BULK); @@ -917,9 +932,9 @@ double GranSubModNormalMDR::calculate_forces() if (history_update) eps_bar[i] += eps_bar_contact; if (history_update && delta_MDR == deltamax_MDR && *Yflag_offset > 0.0 && F_MDR > 0.0) { - const double Vo = FOURTHIRDS * MY_PI * pow(Ro, 3); + const double Vo = FOURTHIRDS * MY_PI * cube(Ro); dRnumerator[i] -= Vo * (eps_bar_contact - *eps_bar_offset); - dRnumerator[i] -= wij * MY_PI * ddeltao * (2 * deltao * Ro - pow(deltao, 2) + pow(R, 2) - pow(Ro, 2)); + dRnumerator[i] -= wij * MY_PI * ddeltao * (2 * deltao * Ro - square(deltao) + square(R) - square(Ro)); dRdenominator[i] += wij * 2.0 * MY_PI * R * (deltao + R - Ro); } @@ -944,41 +959,32 @@ double GranSubModNormalMDR::calculate_forces() const double wij = MAX(1.0 - pij, 0.0); // assign final force + double damp_scale; if (gm->contact_type != PAIR) { - F = wij * F0; + a_damp = a_damp/2.0; + damp_scale = sqrt(gm->meff * 2.0 * Eeff2particle * a_damp); + double *deltao_offset = &history[DELTAO_0]; + const double wfm = std::exp(10.7 * (*deltao_offset) / Rinitial[gm->i] - 10.0) + 1.0; // wall force magnifier + F = wij * F0 * wfm; } else { + damp_scale = sqrt(gm->meff * 2.0 * Eeff * a_damp); F = wij * (F0 + F1) * 0.5; } - // calculate damping force - if (F > 0.0) { - double Eeff2; - double Reff2; - if (gm->contact_type == PAIR) { - Eeff2 = E / (2.0 * (1.0 - pow(nu, 2))); - Reff2 = 1.0 / ((1.0 / gm->radi + 1.0 / gm->radj)); - } else { - Eeff2 = E / (1.0 - pow(nu, 2)); - Reff2 = gm->radi; - } - const double kn = Eeff2 * Reff2; - const double beta = -log(CoR) / sqrt(pow(log(CoR), 2) + PISQ); - const double damp_prefactor = beta * sqrt(gm->meff * kn); - const double F_DAMP = -damp_prefactor * gm->vnnr; - - F += wij * F_DAMP; + if (history_update) { + double *damp_scale_offset = & history[DAMP_SCALE]; + (a_damp <= 0.0) ? *damp_scale_offset = 0.0 : *damp_scale_offset = damp_scale; } return F; } - /* ---------------------------------------------------------------------- */ double GranSubModNormalMDR::calculate_nonadhesive_mdr_force(double delta, double Ainv, double Eeff, double A, double B) { double F_na = acos(1.0 - 2.0 * delta * Ainv); - F_na -= (2 - 4 * delta * Ainv) * sqrt(delta * Ainv - pow(delta * Ainv, 2)); + F_na -= (2 - 4 * delta * Ainv) * sqrt(delta * Ainv - square(delta * Ainv)); F_na *= 0.25 * Eeff * A * B; return F_na; diff --git a/src/GRANULAR/gran_sub_mod_normal.h b/src/GRANULAR/gran_sub_mod_normal.h index db96227f13..9805bd81c0 100644 --- a/src/GRANULAR/gran_sub_mod_normal.h +++ b/src/GRANULAR/gran_sub_mod_normal.h @@ -143,11 +143,11 @@ namespace Granular_NS { void coeffs_to_local() override; void init() override; double calculate_forces() override; - double E, nu, Y, gamma, CoR, psi_b; // specified coeffs + double Y, gamma, psi_b; // specified coeffs protected: double G, kappa, Eeff; // derived coeffs - double Eeffsq, Eeffinv, Eeffsqinv; + double Eeffsq, Eeffinv, Eeffsqinv, Eeff2particle; double gammasq, gamma3, gamma4; int warn_flag; @@ -155,6 +155,7 @@ namespace Granular_NS { int index_Ro, index_Vgeo, index_Velas, index_Vcaps, index_eps_bar, index_dRnumerator; int index_dRdenominator, index_Acon0, index_Acon1, index_Atot, index_Atot_sum, index_ddelta_bar; int index_psi, index_sigmaxx, index_sigmayy, index_sigmazz, index_contacts, index_adhesive_length; + int index_dRavg; int fix_mdr_flag; char *id_fix; diff --git a/src/GRANULAR/granular_model.cpp b/src/GRANULAR/granular_model.cpp index e96debd59e..1a3a46b12e 100644 --- a/src/GRANULAR/granular_model.cpp +++ b/src/GRANULAR/granular_model.cpp @@ -250,12 +250,7 @@ void GranularModel::init() // Must have valid normal, damping, and tangential models if (normal_model->name == "none") error->all(FLERR, "Must specify normal granular model"); - if (normal_model->name == "mdr") { - if (damping_model->name != "none") - error->all(FLERR, "MDR require 'none' damping model. To damp, specify a coefficient of restitution < 1."); - } else { - if (damping_model->name == "none") error->all(FLERR, "Must specify damping granular model"); - } + if (damping_model->name == "none") error->all(FLERR, "Must specify damping granular model"); if (tangential_model->name == "none") error->all(FLERR, "Must specify tangential granular model"); // Twisting, rolling, and heat are optional diff --git a/src/INTEL/fix_intel.cpp b/src/INTEL/fix_intel.cpp index 7e82d3a63b..398b7be8b4 100644 --- a/src/INTEL/fix_intel.cpp +++ b/src/INTEL/fix_intel.cpp @@ -942,7 +942,7 @@ void FixIntel::add_off_results(const ft * _noalias const f_in, int nlocal = atom->nlocal; if (neighbor->ago == 0) { if (_off_overflow_flag[LMP_OVERFLOW]) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); _offload_nlocal = _off_overflow_flag[LMP_LOCAL_MAX] + 1; _offload_min_ghost = _off_overflow_flag[LMP_GHOST_MIN]; _offload_nghost = _off_overflow_flag[LMP_GHOST_MAX] + 1 - diff --git a/src/INTEL/npair_halffull_intel.cpp b/src/INTEL/npair_halffull_intel.cpp index 134b768cc5..f88d01a24c 100644 --- a/src/INTEL/npair_halffull_intel.cpp +++ b/src/INTEL/npair_halffull_intel.cpp @@ -149,7 +149,7 @@ void NPairHalffullNewtonIntel::build_t(NeighList *list, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_full; @@ -223,7 +223,7 @@ void NPairHalffullNewtonIntel::build_t3(NeighList *list, int *numhalf) ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_full; @@ -396,7 +396,7 @@ void NPairHalffullTrimNewtonIntel::build_t(NeighList *list, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_full; @@ -490,7 +490,7 @@ void NPairHalffullTrimNewtonIntel::build_t3(NeighList *list, int *numhalf, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_full; diff --git a/src/INTEL/npair_skip_intel.cpp b/src/INTEL/npair_skip_intel.cpp index 9353a6f520..b14e045f54 100644 --- a/src/INTEL/npair_skip_intel.cpp +++ b/src/INTEL/npair_skip_intel.cpp @@ -170,7 +170,7 @@ void NPairSkipIntel::build_t(NeighList *list, int *numhalf, int *cnumneigh, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } _inum_counts[tid] = my_inum; } @@ -415,7 +415,7 @@ void NPairSkipTrimIntel::build_t(NeighList *list, int *numhalf, int *cnumneigh, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } _inum_counts[tid] = my_inum; diff --git a/src/INTEL/npair_trim_intel.cpp b/src/INTEL/npair_trim_intel.cpp index dcf10a3c87..7dd0ab2fb2 100644 --- a/src/INTEL/npair_trim_intel.cpp +++ b/src/INTEL/npair_trim_intel.cpp @@ -116,7 +116,7 @@ void NPairTrimIntel::build_t(NeighList *list, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_copy; diff --git a/src/INTERLAYER/pair_ilp_graphene_hbn.cpp b/src/INTERLAYER/pair_ilp_graphene_hbn.cpp index 5cddbc5edf..fe7b4990b4 100644 --- a/src/INTERLAYER/pair_ilp_graphene_hbn.cpp +++ b/src/INTERLAYER/pair_ilp_graphene_hbn.cpp @@ -692,11 +692,11 @@ void PairILPGrapheneHBN::ILP_neigh() ILP_firstneigh[i] = neighptr; ILP_numneigh[i] = n; if (n > 3) - error->one(FLERR, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for some atoms, please check your configuration"); ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -835,7 +835,7 @@ void PairILPGrapheneHBN::calc_normal() // the magnitude of the normal vector nn2 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = n1[0] / nn; normal[i][1] = n1[1] / nn; @@ -970,7 +970,7 @@ void PairILPGrapheneHBN::calc_normal() // the magnitude of the normal vector nn2 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = n1[0] / nn; normal[i][1] = n1[1] / nn; @@ -1007,7 +1007,7 @@ void PairILPGrapheneHBN::calc_normal() } } } else { - error->one(FLERR, "There are too many neighbors for calculating normals"); + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals"); } //############################################################################################## diff --git a/src/INTERLAYER/pair_ilp_tmd.cpp b/src/INTERLAYER/pair_ilp_tmd.cpp index 73f89803c2..4d058e889c 100644 --- a/src/INTERLAYER/pair_ilp_tmd.cpp +++ b/src/INTERLAYER/pair_ilp_tmd.cpp @@ -372,7 +372,7 @@ void PairILPTMD::ILP_neigh() ILP_numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -490,7 +490,7 @@ void PairILPTMD::calc_normal() vect[0][1] = x[jH2][1] - ytp; vect[0][2] = x[jH2][2] - ztp; } else { - error->one(FLERR, "The order of atoms in water molecule should be O H H !"); + error->one(FLERR, Error::NOLASTLINE, "The order of atoms in water molecule should be O H H !"); } } Nave[0] = vect[0][0]; @@ -499,7 +499,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -576,7 +576,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -652,7 +652,7 @@ void PairILPTMD::calc_normal() cont = 2; } else { - error->one(FLERR, "The order of atoms in water molecule should be O H H !"); + error->one(FLERR, Error::NOLASTLINE, "The order of atoms in water molecule should be O H H !"); } } if (cont == 2) { @@ -662,7 +662,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -717,7 +717,7 @@ void PairILPTMD::calc_normal() } } else if (cont >= 3) { - error->one(FLERR, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals of water molecules"); } } @@ -762,7 +762,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -867,7 +867,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -911,7 +911,7 @@ void PairILPTMD::calc_normal() } } // end of cont == 3 else - error->one(FLERR, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals of B/N/C/H atoms"); } // for B/N/C/H } // end of if(contone(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0.0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -1008,7 +1008,7 @@ void PairILPTMD::calc_normal() } } } else { - error->one(FLERR, "There are too many neighbors for calculating normals of TMD atoms"); + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals of TMD atoms"); } // end of four cases of cont } // end of i loop } diff --git a/src/INTERLAYER/pair_kolmogorov_crespi_full.cpp b/src/INTERLAYER/pair_kolmogorov_crespi_full.cpp index be6cefa62a..e72db7f62e 100644 --- a/src/INTERLAYER/pair_kolmogorov_crespi_full.cpp +++ b/src/INTERLAYER/pair_kolmogorov_crespi_full.cpp @@ -673,11 +673,11 @@ void PairKolmogorovCrespiFull::KC_neigh() KC_firstneigh[i] = neighptr; KC_numneigh[i] = n; if (n > 3) - error->one(FLERR, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for some atoms, please check your configuration"); ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -815,7 +815,7 @@ void PairKolmogorovCrespiFull::calc_normal() // the magnitude of the normal vector nn2 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = n1[0] / nn; normal[i][1] = n1[1] / nn; @@ -955,7 +955,7 @@ void PairKolmogorovCrespiFull::calc_normal() // the magnitude of the normal vector nn2 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = n1[0] / nn; normal[i][1] = n1[1] / nn; @@ -992,7 +992,7 @@ void PairKolmogorovCrespiFull::calc_normal() } } } else { - error->one(FLERR, "There are too many neighbors for calculating normals"); + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals"); } //############################################################################################## diff --git a/src/KOKKOS/dynamical_matrix_kokkos.cpp b/src/KOKKOS/dynamical_matrix_kokkos.cpp index e4c454c7f2..d59bdc233d 100644 --- a/src/KOKKOS/dynamical_matrix_kokkos.cpp +++ b/src/KOKKOS/dynamical_matrix_kokkos.cpp @@ -118,7 +118,7 @@ void DynamicalMatrixKokkos::setup() force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); update->setupflag = 0; lmp->kokkos->auto_sync = 0; diff --git a/src/KOKKOS/fix_acks2_reaxff_kokkos.cpp b/src/KOKKOS/fix_acks2_reaxff_kokkos.cpp index 5f82b778c1..2720b74578 100644 --- a/src/KOKKOS/fix_acks2_reaxff_kokkos.cpp +++ b/src/KOKKOS/fix_acks2_reaxff_kokkos.cpp @@ -58,12 +58,6 @@ FixACKS2ReaxFFKokkos(LAMMPS *lmp, int narg, char **arg) : allocated_flag = 0; nprev = 4; - memory->destroy(s_hist); - memory->destroy(s_hist_X); - memory->destroy(s_hist_last); - grow_arrays(atom->nmax); - memoryKK->create_kokkos(k_s_hist_last,s_hist_last,2,nprev,"acks2/reax:s_hist_last"); - d_s_hist_last = k_s_hist_last.template view(); buf = new double[2*nprev]; prev_last_rows_rank = 0; @@ -87,6 +81,19 @@ FixACKS2ReaxFFKokkos::~FixACKS2ReaxFFKokkos() /* ---------------------------------------------------------------------- */ +template +void FixACKS2ReaxFFKokkos::post_constructor() +{ + memory->destroy(s_hist); + grow_arrays(atom->nmax); + memoryKK->create_kokkos(k_s_hist_last,s_hist_last,2,nprev,"acks2/reax:s_hist_last"); + d_s_hist_last = k_s_hist_last.template view(); + + pertype_parameters(pertype_option); +} + +/* ---------------------------------------------------------------------- */ + template void FixACKS2ReaxFFKokkos::init() { diff --git a/src/KOKKOS/fix_acks2_reaxff_kokkos.h b/src/KOKKOS/fix_acks2_reaxff_kokkos.h index d3e4dff53c..afae47816c 100644 --- a/src/KOKKOS/fix_acks2_reaxff_kokkos.h +++ b/src/KOKKOS/fix_acks2_reaxff_kokkos.h @@ -64,8 +64,9 @@ class FixACKS2ReaxFFKokkos : public FixACKS2ReaxFF, public KokkosBase { typedef double value_type; typedef ArrayTypes AT; FixACKS2ReaxFFKokkos(class LAMMPS *, int, char **); - ~FixACKS2ReaxFFKokkos(); + ~FixACKS2ReaxFFKokkos() override; + void post_constructor() override; void init() override; void setup_pre_force(int) override; void pre_force(int) override; diff --git a/src/KOKKOS/fix_minimize_kokkos.cpp b/src/KOKKOS/fix_minimize_kokkos.cpp index 585c357992..f1bd218bfa 100644 --- a/src/KOKKOS/fix_minimize_kokkos.cpp +++ b/src/KOKKOS/fix_minimize_kokkos.cpp @@ -121,7 +121,7 @@ void FixMinimizeKokkos::reset_coords() double dx = dx0; double dy = dy0; double dz = dz0; - // domain->minimum_image(dx,dy,dz); + // domain->minimum_image(FLERR, dx,dy,dz); { if (triclinic == 0) { if (xperiodic) { @@ -175,7 +175,7 @@ void FixMinimizeKokkos::reset_coords() } } } - } // end domain->minimum_image(dx,dy,dz); + } // end domain->minimum_image(FLERR, dx,dy,dz); if (dx != dx0) l_x0[n] = l_x(i,0) - dx; if (dy != dy0) l_x0[n+1] = l_x(i,1) - dy; if (dz != dz0) l_x0[n+2] = l_x(i,2) - dz; diff --git a/src/KOKKOS/meam_dens_init_kokkos.h b/src/KOKKOS/meam_dens_init_kokkos.h index dd63be96bd..23985c7082 100644 --- a/src/KOKKOS/meam_dens_init_kokkos.h +++ b/src/KOKKOS/meam_dens_init_kokkos.h @@ -236,7 +236,6 @@ MEAMKokkos::meam_dens_init(int inum_half, int ntype, typename AT::t_ this->d_neighbors_half = d_neighbors_half; this->d_neighbors_full = d_neighbors_full; this->d_offset = d_offset; - this->nlocal = nlocal; if (need_dup) { dup_rho0 = Kokkos::Experimental::create_scatter_view(d_rho0); diff --git a/src/KOKKOS/meam_force_kokkos.h b/src/KOKKOS/meam_force_kokkos.h index 1875e22dcf..703bee23d7 100644 --- a/src/KOKKOS/meam_force_kokkos.h +++ b/src/KOKKOS/meam_force_kokkos.h @@ -17,7 +17,6 @@ void MEAMKokkos::meam_force( { EV_FLOAT ev; - this->eflag_either = eflag_either; this->eflag_global = eflag_global; this->eflag_atom = eflag_atom; this->vflag_global = vflag_global; diff --git a/src/KOKKOS/memory_kokkos.h b/src/KOKKOS/memory_kokkos.h index a94d9eb1e6..b57a048db7 100644 --- a/src/KOKKOS/memory_kokkos.h +++ b/src/KOKKOS/memory_kokkos.h @@ -1,4 +1,3 @@ -// clang-format off /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories @@ -11,6 +10,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +// clang-format off #ifndef LMP_MEMORY_KOKKOS_H #define LMP_MEMORY_KOKKOS_H @@ -35,8 +35,7 @@ class MemoryKokkos : public Memory { ------------------------------------------------------------------------- */ template -TYPE create_kokkos(TYPE &data, typename TYPE::value_type *&array, - int n1, const char *name) +TYPE create_kokkos(TYPE &data, typename TYPE::value_type *&array, int n1, const char *name) { data = TYPE(name,n1); array = data.h_view.data(); @@ -44,8 +43,7 @@ TYPE create_kokkos(TYPE &data, typename TYPE::value_type *&array, } template - TYPE create_kokkos(TYPE &data, HTYPE &h_data, - typename TYPE::value_type *&array, int n1, + TYPE create_kokkos(TYPE &data, HTYPE &h_data, typename TYPE::value_type *&array, int n1, const char *name) { data = TYPE(std::string(name),n1); @@ -56,8 +54,7 @@ template template - TYPE create_kokkos(TYPE &data, HTYPE &h_data, - int n1, const char *name) + TYPE create_kokkos(TYPE &data, HTYPE &h_data, int n1, const char *name) { data = TYPE(std::string(name),n1); h_data = Kokkos::create_mirror_view(data); @@ -69,8 +66,7 @@ template ------------------------------------------------------------------------- */ template -TYPE grow_kokkos(TYPE &data, typename TYPE::value_type *&array, - int n1, const char *name) +TYPE grow_kokkos(TYPE &data, typename TYPE::value_type *&array, int n1, const char *name) { if (array == nullptr) return create_kokkos(data,array,n1,name); @@ -96,12 +92,11 @@ void destroy_kokkos(TYPE data, typename TYPE::value_type* &array) ------------------------------------------------------------------------- */ template - TYPE create_kokkos(TYPE &data, HTYPE &h_data, int n1, int n2, - const char *name) + TYPE create_kokkos(TYPE &data, HTYPE &h_data, int n1, int n2, const char *name) { data = TYPE(std::string(name),n1,n2); h_data = Kokkos::create_mirror_view(data); - //printf(">>> name: %s\n", name); + return data; } @@ -112,7 +107,6 @@ TYPE create_kokkos(TYPE &data, typename TYPE::value_type **&array, data = TYPE(std::string(name),n1,n2); bigint nbytes = ((bigint) sizeof(typename TYPE::value_type *)) * n1; array = (typename TYPE::value_type **) smalloc(nbytes,name); - //printf(">>> name %s nbytes %d\n", name, nbytes); for (int i = 0; i < n1; i++) { if (n2 == 0) diff --git a/src/KOKKOS/min_kokkos.cpp b/src/KOKKOS/min_kokkos.cpp index fca7a16e62..4bd983221b 100644 --- a/src/KOKKOS/min_kokkos.cpp +++ b/src/KOKKOS/min_kokkos.cpp @@ -172,7 +172,7 @@ void MinKokkos::setup(int flag) force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); if (atom->molecular != Atom::ATOMIC) { if (force->bond) { @@ -203,7 +203,7 @@ void MinKokkos::setup(int flag) atomKK->sync(force->kspace->execution_space,force->kspace->datamask_read); force->kspace->compute(eflag,vflag); atomKK->modified(force->kspace->execution_space,force->kspace->datamask_modify); - } else force->kspace->compute_dummy(eflag,vflag); + } else force->kspace->compute_dummy(eflag,vflag,0); } modify->setup_pre_reverse(eflag,vflag); @@ -281,7 +281,7 @@ void MinKokkos::setup_minimal(int flag) force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); if (atom->molecular != Atom::ATOMIC) { if (force->bond) { @@ -312,7 +312,7 @@ void MinKokkos::setup_minimal(int flag) atomKK->sync(force->kspace->execution_space,force->kspace->datamask_read); force->kspace->compute(eflag,vflag); atomKK->modified(force->kspace->execution_space,force->kspace->datamask_modify); - } else force->kspace->compute_dummy(eflag,vflag); + } else force->kspace->compute_dummy(eflag,vflag,0); } modify->setup_pre_reverse(eflag,vflag); diff --git a/src/KOKKOS/mliap_descriptor_so3_kokkos.cpp b/src/KOKKOS/mliap_descriptor_so3_kokkos.cpp index 9f18078ac6..815d2696a9 100644 --- a/src/KOKKOS/mliap_descriptor_so3_kokkos.cpp +++ b/src/KOKKOS/mliap_descriptor_so3_kokkos.cpp @@ -28,6 +28,7 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ + template MLIAPDescriptorSO3Kokkos::MLIAPDescriptorSO3Kokkos(LAMMPS *lmp, char *paramfilename) // TODO: why take self as param, shouldn't be needed @@ -39,6 +40,14 @@ MLIAPDescriptorSO3Kokkos::MLIAPDescriptorSO3Kokkos(LAMMPS *lmp, char /* ---------------------------------------------------------------------- */ +template +MLIAPDescriptorSO3Kokkos::~MLIAPDescriptorSO3Kokkos() +{ + delete so3ptr_kokkos; +} + +/* ---------------------------------------------------------------------- */ + template void MLIAPDescriptorSO3Kokkos::compute_descriptors(class MLIAPData *data_) { diff --git a/src/KOKKOS/mliap_descriptor_so3_kokkos.h b/src/KOKKOS/mliap_descriptor_so3_kokkos.h index 6676b60004..26b3462508 100644 --- a/src/KOKKOS/mliap_descriptor_so3_kokkos.h +++ b/src/KOKKOS/mliap_descriptor_so3_kokkos.h @@ -29,6 +29,7 @@ class MLIAPDescriptorSO3Kokkos : public MLIAPDescriptorKokkos { public: MLIAPDescriptorSO3Kokkos(LAMMPS *, char *); + ~MLIAPDescriptorSO3Kokkos() override; void compute_descriptors(class MLIAPData *) override; void compute_forces(class MLIAPData *) override; diff --git a/src/KOKKOS/mliap_model_python_kokkos.h b/src/KOKKOS/mliap_model_python_kokkos.h index 4f56ecb0ab..76b4a9d42a 100644 --- a/src/KOKKOS/mliap_model_python_kokkos.h +++ b/src/KOKKOS/mliap_model_python_kokkos.h @@ -29,7 +29,7 @@ class MLIAPModelPythonKokkos : public MLIAPModelPython, public MLIAPModelKokkos< public: MLIAPModelPythonKokkos(LAMMPS *, char * = nullptr); ~MLIAPModelPythonKokkos(); - void read_coeffs(char *fname); + void read_coeffs(char *fname) override; void compute_gradients(class MLIAPData *) override; void compute_gradgrads(class MLIAPData *) override; diff --git a/src/KOKKOS/mliap_unified_couple_kokkos.pyx b/src/KOKKOS/mliap_unified_couple_kokkos.pyx index 16fdefdb83..91dce645ac 100644 --- a/src/KOKKOS/mliap_unified_couple_kokkos.pyx +++ b/src/KOKKOS/mliap_unified_couple_kokkos.pyx @@ -498,7 +498,7 @@ cdef public object mliap_unified_connect_kokkos(char *fname, MLIAPDummyModel * m unified = LOADED_MODEL elif str_fname.endswith(".pt") or str_fname.endswith('.pth'): import torch - unified = torch.load(str_fname) + unified = torch.load(str_fname,weights_only=False) else: with open(str_fname, 'rb') as pfile: unified = pickle.load(pfile) @@ -543,6 +543,8 @@ cdef public object mliap_unified_connect_kokkos(char *fname, MLIAPDummyModel * m unified_int.descriptor.set_elements(elements, nelements) unified_int.model.nelements = nelements + for i, elem in enumerate(unified.element_types): + free(elements[i]) free(elements) return unified_int diff --git a/src/KOKKOS/mliap_unified_kokkos.cpp b/src/KOKKOS/mliap_unified_kokkos.cpp index 1e57b8888c..bf7d6b46d5 100644 --- a/src/KOKKOS/mliap_unified_kokkos.cpp +++ b/src/KOKKOS/mliap_unified_kokkos.cpp @@ -107,17 +107,14 @@ void MLIAPDummyDescriptorKokkos::init() double cut; cutmax = 0.0; memory->create(cutsq, nelements, nelements, "mliap/descriptor/dummy:cutsq"); - memory->create(cutghost, nelements, nelements, "mliap/descriptor/dummy:cutghost"); for (int ielem = 0; ielem < nelements; ielem++) { // rcutfac set from python, is global cutoff for all elements cut = 2.0 * radelem[ielem] * rcutfac; if (cut > cutmax) cutmax = cut; cutsq[ielem][ielem] = cut * cut; - cutghost[ielem][ielem] = cut * cut; for (int jelem = ielem + 1; jelem < nelements; jelem++) { cut = (radelem[ielem] + radelem[jelem]) * rcutfac; cutsq[ielem][jelem] = cutsq[jelem][ielem] = cut * cut; - cutghost[ielem][jelem] = cutghost[jelem][ielem] = cut * cut; } } } diff --git a/src/KOKKOS/npair_copy_kokkos.cpp b/src/KOKKOS/npair_copy_kokkos.cpp index 6485319883..29687f8221 100644 --- a/src/KOKKOS/npair_copy_kokkos.cpp +++ b/src/KOKKOS/npair_copy_kokkos.cpp @@ -116,7 +116,7 @@ void NPairCopyKokkos::copy_to_cpu(NeighList *list) firstneigh[i] = neighptr; ipage->vgot(jnum); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/KOKKOS/npair_trim_kokkos.cpp b/src/KOKKOS/npair_trim_kokkos.cpp index d04d8676d7..578e62c2c5 100644 --- a/src/KOKKOS/npair_trim_kokkos.cpp +++ b/src/KOKKOS/npair_trim_kokkos.cpp @@ -184,7 +184,7 @@ void NPairTrimKokkos::trim_to_cpu(NeighList *list) numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/KOKKOS/pair_coul_long_kokkos.cpp b/src/KOKKOS/pair_coul_long_kokkos.cpp index 0452a08b8f..abbe46e660 100644 --- a/src/KOKKOS/pair_coul_long_kokkos.cpp +++ b/src/KOKKOS/pair_coul_long_kokkos.cpp @@ -378,6 +378,7 @@ void PairCoulLongKokkos::init_style() PairCoulLong::init_style(); Kokkos::deep_copy(d_cut_coulsq,cut_coulsq); + Kokkos::deep_copy(d_cut_ljsq,cut_coulsq); // error if rRESPA with inner levels @@ -415,6 +416,7 @@ double PairCoulLongKokkos::init_one(int i, int j) m_params[i][j] = m_params[j][i] = k_params.h_view(i,j); m_cutsq[j][i] = m_cutsq[i][j] = cutone*cutone; m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsq; + m_cut_ljsq[j][i] = m_cut_ljsq[i][j] = cut_coulsq; } k_cutsq.h_view(i,j) = cutone*cutone; diff --git a/src/KOKKOS/pair_kokkos.h b/src/KOKKOS/pair_kokkos.h index 399142dfaf..63e637c108 100644 --- a/src/KOKKOS/pair_kokkos.h +++ b/src/KOKKOS/pair_kokkos.h @@ -961,7 +961,7 @@ EV_FLOAT pair_compute_neighlist (PairStyle* fpair, std::enable_if_t<(NEIGHFLAG&P lastcall = fpair->lmp->update->ntimestep; vectorsize = GetMaxNeighs(list); if (vectorsize == 0) vectorsize = 1; - vectorsize = MathSpecial::powint(2,(int(log2(vectorsize) + 0.5))); // round to nearest power of 2 + vectorsize = MathSpecial::powint(2.0,(int(log2(double(vectorsize)) + 0.5))); // round to nearest power of 2 #if defined(KOKKOS_ENABLE_HIP) int max_vectorsize = 64; diff --git a/src/KOKKOS/pair_mliap_kokkos.cpp b/src/KOKKOS/pair_mliap_kokkos.cpp index bd029e04a2..e91d1bea9d 100644 --- a/src/KOKKOS/pair_mliap_kokkos.cpp +++ b/src/KOKKOS/pair_mliap_kokkos.cpp @@ -37,7 +37,7 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ template -PairMLIAPKokkos::PairMLIAPKokkos(class LAMMPS* l) : PairMLIAP(l) +PairMLIAPKokkos::PairMLIAPKokkos(class LAMMPS *lmp) : PairMLIAP(lmp) { kokkosable = 1; execution_space = ExecutionSpaceFromDevice::space; @@ -45,7 +45,6 @@ PairMLIAPKokkos::PairMLIAPKokkos(class LAMMPS* l) : PairMLIAP(l) is_child=true; reverse_comm_device = 1; comm_type=COMM_TYPE::UNSET; - } /* ---------------------------------------------------------------------- */ @@ -58,6 +57,7 @@ PairMLIAPKokkos::~PairMLIAPKokkos() memoryKK->destroy_kokkos(k_setflag, setflag); memoryKK->destroy_kokkos(k_eatom, eatom); memoryKK->destroy_kokkos(k_vatom, vatom); + if (ghostneigh) memoryKK->destroy_kokkos(k_cutghost, cutghost); delete model; delete descriptor; model=nullptr; @@ -84,10 +84,10 @@ void PairMLIAPKokkos::compute(int eflag, int vflag) if (data->nelements != model->nelements) error->all(FLERR, "Incompatible model and descriptor element count"); - ev_init(eflag, vflag); + ev_init(eflag, vflag, 0); if (eflag_atom && (int)k_eatom.h_view.extent(0) < maxeatom) { - memoryKK->destroy_kokkos(k_eatom,eatom); - memoryKK->create_kokkos(k_eatom,eatom,maxeatom,"pair:eatom"); + memoryKK->destroy_kokkos(k_eatom,eatom); + memoryKK->create_kokkos(k_eatom,eatom,maxeatom,"pair:eatom"); } if (vflag_atom && (int)k_vatom.h_view.extent(0) < maxeatom) { @@ -148,6 +148,7 @@ void PairMLIAPKokkos::allocate() memoryKK->create_kokkos(k_cutsq, cutsq, n+1, n+1, "pair_mliap:cutsq"); memoryKK->create_kokkos(k_setflag, setflag, n+1, n+1, "pair_mliap:setflag"); + if (ghostneigh) memoryKK->create_kokkos(k_cutghost, cutghost, n+1, n+1, "pair_mliap:cutghost"); // this is for the base class so it doesn't double delete allocated = 1; } @@ -217,10 +218,7 @@ void PairMLIAPKokkos::settings(int narg, char ** arg) template void PairMLIAPKokkos::coeff(int narg, char **arg) { if (narg < 3) error->all(FLERR,"Incorrect args for pair coefficients" + utils::errorurl(21)); - if (!allocated) { - PairMLIAP::allocate(); - allocate(); - } + if (!allocated) allocate(); char* type1 = arg[0]; char* type2 = arg[1]; @@ -242,7 +240,6 @@ void PairMLIAPKokkos::coeff(int narg, char **arg) { if (strcmp(elemname,descriptor->elements[jelem]) == 0) break; - //printf(">>> nelements: %d\n", descriptor->nelements); if (jelem < descriptor->nelements) map[i] = jelem; else if (strcmp(elemname,"NULL") == 0) map[i] = -1; diff --git a/src/KOKKOS/pair_mliap_kokkos.h b/src/KOKKOS/pair_mliap_kokkos.h index cbef6e5966..b0d160133e 100644 --- a/src/KOKKOS/pair_mliap_kokkos.h +++ b/src/KOKKOS/pair_mliap_kokkos.h @@ -31,6 +31,7 @@ PairStyle(mliap/kk/host,PairMLIAPKokkos); #include "kokkos_type.h" #include "kokkos_base.h" #include "comm.h" + #include namespace LAMMPS_NS { @@ -108,6 +109,7 @@ public: typename AT::t_f_array f; DAT::tdual_int_1d k_map; DAT::tdual_double_2d k_cutsq; + DAT::tdual_double_2d k_cutghost; DAT::tdual_int_2d k_setflag; DAT::tdual_efloat_1d k_eatom; DAT::tdual_double_2d k_vatom; diff --git a/src/KOKKOS/pair_pace_extrapolation_kokkos.cpp b/src/KOKKOS/pair_pace_extrapolation_kokkos.cpp index 746055f28c..4595843477 100644 --- a/src/KOKKOS/pair_pace_extrapolation_kokkos.cpp +++ b/src/KOKKOS/pair_pace_extrapolation_kokkos.cpp @@ -37,15 +37,9 @@ #include +// prototype repeated from base class implementation namespace LAMMPS_NS { struct ACEALImpl { - ACEALImpl() : basis_set(nullptr), ace(nullptr) {} - - ~ACEALImpl() { - delete basis_set; - delete ace; - } - ACEBBasisSet *basis_set; ACEBEvaluator *ace; }; diff --git a/src/KOKKOS/pair_pace_kokkos.cpp b/src/KOKKOS/pair_pace_kokkos.cpp index 0afbb7540e..577f77ba8b 100644 --- a/src/KOKKOS/pair_pace_kokkos.cpp +++ b/src/KOKKOS/pair_pace_kokkos.cpp @@ -38,14 +38,9 @@ #include +// prototype repeated from base class implementation namespace LAMMPS_NS { struct ACEImpl { - ACEImpl() : basis_set(nullptr), ace(nullptr) {} - ~ACEImpl() - { - delete basis_set; - delete ace; - } ACECTildeBasisSet *basis_set; ACERecursiveEvaluator *ace; }; diff --git a/src/KOKKOS/third_order_kokkos.cpp b/src/KOKKOS/third_order_kokkos.cpp index 569a94a773..761165d99a 100644 --- a/src/KOKKOS/third_order_kokkos.cpp +++ b/src/KOKKOS/third_order_kokkos.cpp @@ -118,7 +118,7 @@ void ThirdOrderKokkos::setup() force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); update->setupflag = 0; lmp->kokkos->auto_sync = 0; diff --git a/src/KOKKOS/verlet_kokkos.cpp b/src/KOKKOS/verlet_kokkos.cpp index a492b5a9c9..b711d8108f 100644 --- a/src/KOKKOS/verlet_kokkos.cpp +++ b/src/KOKKOS/verlet_kokkos.cpp @@ -122,8 +122,7 @@ void VerletKokkos::setup(int flag) atomKK->sync(force->pair->execution_space,force->pair->datamask_read); force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); - } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + } else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); if (atom->molecular != Atom::ATOMIC) { if (force->bond) { @@ -154,7 +153,7 @@ void VerletKokkos::setup(int flag) atomKK->sync(force->kspace->execution_space,force->kspace->datamask_read); force->kspace->compute(eflag,vflag); atomKK->modified(force->kspace->execution_space,force->kspace->datamask_modify); - } else force->kspace->compute_dummy(eflag,vflag); + } else force->kspace->compute_dummy(eflag,vflag,0); } modify->setup_pre_reverse(eflag,vflag); @@ -213,8 +212,7 @@ void VerletKokkos::setup_minimal(int flag) atomKK->sync(force->pair->execution_space,force->pair->datamask_read); force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); - } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + } else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); if (atom->molecular != Atom::ATOMIC) { if (force->bond) { @@ -245,7 +243,7 @@ void VerletKokkos::setup_minimal(int flag) atomKK->sync(force->kspace->execution_space,force->kspace->datamask_read); force->kspace->compute(eflag,vflag); atomKK->modified(force->kspace->execution_space,force->kspace->datamask_modify); - } else force->kspace->compute_dummy(eflag,vflag); + } else force->kspace->compute_dummy(eflag,vflag,0); } modify->setup_pre_reverse(eflag,vflag); diff --git a/src/LATBOLTZ/fix_lb_fluid.cpp b/src/LATBOLTZ/fix_lb_fluid.cpp index 286b56cab5..d5161bba42 100644 --- a/src/LATBOLTZ/fix_lb_fluid.cpp +++ b/src/LATBOLTZ/fix_lb_fluid.cpp @@ -2344,7 +2344,7 @@ void FixLbFluid::SetupBuffers() MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &dump_file_handle_raw); MPI_File_set_size(dump_file_handle_raw, 0); - MPI_File_set_view(dump_file_handle_raw, 0, MPI_DOUBLE, dump_file_mpitype, "native", + MPI_File_set_view(dump_file_handle_raw, 0, MPI_DOUBLE, dump_file_mpitype, (char *)"native", MPI_INFO_NULL); } } diff --git a/src/LEPTON/angle_lepton.cpp b/src/LEPTON/angle_lepton.cpp index 4907086ab1..08d1ea9a83 100644 --- a/src/LEPTON/angle_lepton.cpp +++ b/src/LEPTON/angle_lepton.cpp @@ -395,13 +395,13 @@ double AngleLepton::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/LEPTON/dihedral_lepton.cpp b/src/LEPTON/dihedral_lepton.cpp index 2cee9fba8a..912896254b 100644 --- a/src/LEPTON/dihedral_lepton.cpp +++ b/src/LEPTON/dihedral_lepton.cpp @@ -508,9 +508,9 @@ double DihedralLepton::get_phi(double const *x1, //array holding x,y,z coords } //Consider periodic boundary conditions: - domain->minimum_image(vb12[0], vb12[1], vb12[2]); - domain->minimum_image(vb23[0], vb23[1], vb23[2]); - domain->minimum_image(vb34[0], vb34[1], vb34[2]); + domain->minimum_image(FLERR, vb12[0], vb12[1], vb12[2]); + domain->minimum_image(FLERR, vb23[0], vb23[1], vb23[2]); + domain->minimum_image(FLERR, vb34[0], vb34[1], vb34[2]); //--- Compute the normal to the planes formed by atoms 1,2,3 and 2,3,4 --- diff --git a/src/MACHDYN/pair_smd_hertz.cpp b/src/MACHDYN/pair_smd_hertz.cpp index fcdaae76bd..0c2444618f 100644 --- a/src/MACHDYN/pair_smd_hertz.cpp +++ b/src/MACHDYN/pair_smd_hertz.cpp @@ -145,7 +145,7 @@ void PairHertz::compute(int eflag, int vflag) { dely0 = x0[j][1] - x0[i][1]; delz0 = x0[j][2] - x0[i][2]; if (periodic) { - domain->minimum_image(delx0, dely0, delz0); + domain->minimum_image(FLERR, delx0, dely0, delz0); } rSq0 = delx0 * delx0 + dely0 * dely0 + delz0 * delz0; // initial distance sphCut = sph_radius[i] + sph_radius[j]; diff --git a/src/MACHDYN/pair_smd_tlsph.cpp b/src/MACHDYN/pair_smd_tlsph.cpp index 72ea1b4d5f..4c2f56eb48 100644 --- a/src/MACHDYN/pair_smd_tlsph.cpp +++ b/src/MACHDYN/pair_smd_tlsph.cpp @@ -220,7 +220,7 @@ void PairTlsph::PreCompute() { dx = xj - xi; if (periodic) - domain->minimum_image(dx0(0), dx0(1), dx0(2)); + domain->minimum_image(FLERR, dx0(0), dx0(1), dx0(2)); r0Sq = dx0.squaredNorm(); h = irad + radius[j]; @@ -488,7 +488,7 @@ void PairTlsph::ComputeForces(int eflag, int vflag) { } if (periodic) - domain->minimum_image(dx0(0), dx0(1), dx0(2)); + domain->minimum_image(FLERR, dx0(0), dx0(1), dx0(2)); // check that distance between i and j (in the reference config) is less than cutoff dx0 = x0j - x0i; diff --git a/src/MACHDYN/pair_smd_triangulated_surface.cpp b/src/MACHDYN/pair_smd_triangulated_surface.cpp index c50b7700f6..cded66e644 100644 --- a/src/MACHDYN/pair_smd_triangulated_surface.cpp +++ b/src/MACHDYN/pair_smd_triangulated_surface.cpp @@ -154,7 +154,7 @@ void PairTriSurf::compute(int eflag, int vflag) { x4(2) = x[particle][2]; dx = x_center - x4; // if (periodic) { - domain->minimum_image(dx(0), dx(1), dx(2)); + domain->minimum_image(FLERR, dx(0), dx(1), dx(2)); } rsq = dx.squaredNorm(); diff --git a/src/MANYBODY/pair_airebo.cpp b/src/MANYBODY/pair_airebo.cpp index 705fa34f8b..150eeef9f6 100644 --- a/src/MANYBODY/pair_airebo.cpp +++ b/src/MANYBODY/pair_airebo.cpp @@ -406,7 +406,7 @@ void PairAIREBO::REBO_neigh() REBO_numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/MANYBODY/pair_comb.cpp b/src/MANYBODY/pair_comb.cpp index f3cd29b43d..553e912064 100644 --- a/src/MANYBODY/pair_comb.cpp +++ b/src/MANYBODY/pair_comb.cpp @@ -2015,7 +2015,7 @@ void PairComb::Short_neigh() sht_num[i] = nj; ipage->vgot(nj); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/MANYBODY/pair_comb3.cpp b/src/MANYBODY/pair_comb3.cpp index bc74bf6361..b657c74c4b 100644 --- a/src/MANYBODY/pair_comb3.cpp +++ b/src/MANYBODY/pair_comb3.cpp @@ -772,7 +772,7 @@ void PairComb3::Short_neigh() sht_num[i] = nj; ipage->vgot(nj); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } // communicating coordination number to all nodes diff --git a/src/MANYBODY/pair_eam.cpp b/src/MANYBODY/pair_eam.cpp index b5a0ca0f77..fcef67b985 100644 --- a/src/MANYBODY/pair_eam.cpp +++ b/src/MANYBODY/pair_eam.cpp @@ -39,6 +39,7 @@ PairEAM::PairEAM(LAMMPS *lmp) : Pair(lmp) { restartinfo = 0; manybody_flag = 1; + atomic_energy_enable = 1; embedstep = -1; unit_convert_flag = utils::get_supported_conversions(utils::ENERGY); @@ -340,6 +341,70 @@ void PairEAM::compute(int eflag, int vflag) if (vflag_fdotr) virial_fdotr_compute(); } +/********************************************************************* + * Calculates the atomic energy of atom i + *********************************************************************/ +double PairEAM::compute_atomic_energy(int i, NeighList *neighborList) +{ + double p; + int m; + double* coeff; + double Ei = 0.0; + double rhoi = 0.0; + + double xi = atom->x[i][0]; + double yi = atom->x[i][1]; + double zi = atom->x[i][2]; + int itype = atom->type[i]; + + // loop over all neighbors of the selected atom. + + int* jlist = neighborList->firstneigh[i]; + int jnum = neighborList->numneigh[i]; + + for(int jj = 0; jj < jnum; jj++) { + int j = jlist[jj]; + + double delx = xi - atom->x[j][0]; + double dely = yi - atom->x[j][1]; + double delz = zi - atom->x[j][2]; + double rsq = delx*delx + dely*dely + delz*delz; + if(rsq >= cutforcesq) continue; + + int jtype = atom->type[j]; + double r = sqrt(rsq); + + p = r * rdr + 1.0; + m = static_cast(p); + m = MIN(m, nr - 1); + p -= m; + p = MIN(p, 1.0); + + // sum pair energy ij + // divide by 2 to avoid double counting energy + + coeff = z2r_spline[type2z2r[jtype][itype]][m]; + double z2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6]; + Ei += 0.5*z2 / r; + + // sum rho_ij to rho_i + coeff = rhor_spline[type2rhor[jtype][itype]][m]; + rhoi += ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6]; + } + + // compute the change in embedding energy of atom i. + + p = rhoi * rdrho + 1.0; + m = static_cast(p); + m = MAX(1, MIN(m, nrho - 1)); + p -= m; + p = MIN(p, 1.0); + coeff = frho_spline[type2frho[itype]][m]; + Ei += ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6]; + + return Ei; +} + /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ diff --git a/src/MANYBODY/pair_eam.h b/src/MANYBODY/pair_eam.h index 24221a07ce..6a112a3221 100644 --- a/src/MANYBODY/pair_eam.h +++ b/src/MANYBODY/pair_eam.h @@ -47,6 +47,7 @@ class PairEAM : public Pair { PairEAM(class LAMMPS *); ~PairEAM() override; void compute(int, int) override; + double compute_atomic_energy(int, NeighList *) override; void settings(int, char **) override; void coeff(int, char **) override; void init_style() override; diff --git a/src/MANYBODY/pair_extep.cpp b/src/MANYBODY/pair_extep.cpp index 6915ee81cb..1d8242127d 100644 --- a/src/MANYBODY/pair_extep.cpp +++ b/src/MANYBODY/pair_extep.cpp @@ -161,11 +161,10 @@ void PairExTeP::SR_neigh() } } } - //printf("SR_neigh : N[%d] = %f\n",i,N[i]); ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/MANYBODY/pair_gw.h b/src/MANYBODY/pair_gw.h index 15ddaa21a8..f098bfa082 100644 --- a/src/MANYBODY/pair_gw.h +++ b/src/MANYBODY/pair_gw.h @@ -94,8 +94,6 @@ class PairGW : public Pair { const double gw_d = param->d * param->d; const double hcth = param->h - costheta; - //printf("gw_gijk: gw_c=%f gw_d=%f hcth=%f=%f-%f\n", gw_c, gw_d, hcth, param->h, costheta); - return param->gamma * (1.0 + gw_c / gw_d - gw_c / (gw_d + hcth * hcth)); } diff --git a/src/MANYBODY/pair_lcbop.cpp b/src/MANYBODY/pair_lcbop.cpp index 3e8020c3af..3325918b82 100644 --- a/src/MANYBODY/pair_lcbop.cpp +++ b/src/MANYBODY/pair_lcbop.cpp @@ -278,7 +278,7 @@ void PairLCBOP::SR_neigh() SR_numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } // calculate M_i diff --git a/src/MANYBODY/pair_rebomos.cpp b/src/MANYBODY/pair_rebomos.cpp index d912c37290..f76cdc4e49 100644 --- a/src/MANYBODY/pair_rebomos.cpp +++ b/src/MANYBODY/pair_rebomos.cpp @@ -349,7 +349,7 @@ void PairREBOMoS::REBO_neigh() REBO_numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/MC/Install.sh b/src/MC/Install.sh index ccf6767c4d..efe6b7c07b 100755 --- a/src/MC/Install.sh +++ b/src/MC/Install.sh @@ -51,6 +51,8 @@ action fix_charge_regulation.cpp action fix_charge_regulation.h action fix_gcmc.cpp action fix_gcmc.h +action fix_neighbor_swap.cpp compute_voronoi_atom.cpp +action fix_neighbor_swap.h compute_voronoi_atom.h action fix_mol_swap.cpp action fix_mol_swap.h action fix_sgcmc.cpp pair_eam.cpp diff --git a/src/MC/fix_bond_break.cpp b/src/MC/fix_bond_break.cpp index 94ec5a89bb..f5b34ac356 100644 --- a/src/MC/fix_bond_break.cpp +++ b/src/MC/fix_bond_break.cpp @@ -439,11 +439,6 @@ void FixBondBreak::update_topology() ndihedrals = 0; nimpropers = 0; - //printf("NBREAK %d: ",nbreak); - //for (i = 0; i < nbreak; i++) - // printf(" %d %d,",broken[i][0],broken[i][1]); - //printf("\n"); - for (i = 0; i < nlocal; i++) { influenced = 0; slist = special[i]; diff --git a/src/MC/fix_bond_swap.cpp b/src/MC/fix_bond_swap.cpp index ff90b81695..1e0b20a2d7 100644 --- a/src/MC/fix_bond_swap.cpp +++ b/src/MC/fix_bond_swap.cpp @@ -723,7 +723,7 @@ double FixBondSwap::dist_rsq(int i, int j) double delx = x[i][0] - x[j][0]; double dely = x[i][1] - x[j][1]; double delz = x[i][2] - x[j][2]; - domain->minimum_image(delx,dely,delz); + domain->minimum_image(FLERR, delx,dely,delz); return (delx*delx + dely*dely + delz*delz); } diff --git a/src/MC/fix_neighbor_swap.cpp b/src/MC/fix_neighbor_swap.cpp new file mode 100644 index 0000000000..0fedfc460e --- /dev/null +++ b/src/MC/fix_neighbor_swap.cpp @@ -0,0 +1,921 @@ +/* ---------------------------------------------------------------------- + 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 authors: Jacob Tavenner +------------------------------------------------------------------------- */ + +#include "fix_neighbor_swap.h" + +#include "angle.h" +#include "atom.h" +#include "bond.h" +#include "citeme.h" +#include "comm.h" +#include "compute.h" +#include "compute_voronoi_atom.h" +#include "dihedral.h" +#include "domain.h" +#include "error.h" +#include "fix.h" +#include "force.h" +#include "group.h" +#include "improper.h" +#include "kspace.h" +#include "math_extra.h" +#include "math_special.h" +#include "memory.h" +#include "modify.h" +#include "neighbor.h" +#include "pair.h" +#include "random_park.h" +#include "region.h" +#include "update.h" + +#include +#include +#include +#include + +using namespace LAMMPS_NS; +using namespace FixConst; +using MathExtra::distsq3; +using MathSpecial::square; + +static const char cite_fix_neighbor_swap[] = + "fix neighbor/swap command: doi:10.1016/j.commatsci.2022.111929\n\n" + "@Article{Tavenner2023111929,\n" + " author = {Jacob P. Tavenner and Mikhail I. Mendelev and John W. Lawson},\n" + " title = {Molecular dynamics based kinetic Monte Carlo simulation for accelerated " + "diffusion},\n" + " journal = {Computational Materials Science},\n" + " year = {2023},\n" + " volume = {218},\n" + " pages = {111929}\n" + " url = {https://dx.doi.org/10.1016/j.commatsci.2022.111929}\n" + "}\n\n"; + +/* ---------------------------------------------------------------------- */ + +FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), region(nullptr), idregion(nullptr), type_list(nullptr), rate_list(nullptr), + qtype(nullptr), sqrt_mass_ratio(nullptr), voro_neighbor_list(nullptr), + local_swap_iatom_list(nullptr), local_swap_neighbor_list(nullptr), + local_swap_type_list(nullptr), local_swap_probability(nullptr), random_equal(nullptr), + id_voro(nullptr), c_voro(nullptr), c_pe(nullptr) +{ + if (narg < 10) utils::missing_cmd_args(FLERR, "fix neighbor/swap", error); + + dynamic_group_allow = 1; + + vector_flag = 1; + size_vector = 2; + global_freq = 1; + extvector = 0; + restart_global = 1; + time_depend = 1; + + ke_flag = 1; + diff_flag = 0; + rates_flag = 0; + nswaptypes = 0; + + if (lmp->citeme) lmp->citeme->add(cite_fix_neighbor_swap); + + // required args + + nevery = utils::inumeric(FLERR, arg[3], false, lmp); + ncycles = utils::inumeric(FLERR, arg[4], false, lmp); + seed = utils::inumeric(FLERR, arg[5], false, lmp); + double temperature = utils::numeric(FLERR, arg[6], false, lmp); + double r_0 = utils::inumeric(FLERR, arg[7], false, lmp); + + if (nevery <= 0) + error->all(FLERR, 3, "Illegal fix neighbor/swap command nevery value: {}", nevery); + if (ncycles < 0) + error->all(FLERR, 4, "Illegal fix neighbor/swap command ncycles value: {}", ncycles); + if (seed <= 0) error->all(FLERR, 5, "Illegal fix neighbor/swap command seed value: {}", seed); + if (temperature <= 0.0) + error->all(FLERR, 6, "Illegal fix neighbor/swap command temperature value: {}", temperature); + if (r_0 <= 0.0) error->all(FLERR, 7, "Illegal fix neighbor/swap command R0 value: {}", r_0); + + // Voro compute check + + id_voro = utils::strdup(arg[8]); + c_voro = modify->get_compute_by_id(id_voro); + if (!c_voro) error->all(FLERR, 8, "Could not find compute voronoi ID {}", id_voro); + if (c_voro->local_flag == 0) + error->all(FLERR, 8, "Voronoi compute {} does not compute local info", id_voro); + if (c_voro->size_local_cols != 3) + error->all(FLERR, 8, "Voronoi compute {} does not compute i, j, sizes as expected", id_voro); + + beta = 1.0 / (force->boltz * temperature); + inv_r_0 = 1.0 / r_0; + + memory->create(type_list, atom->ntypes, "neighbor/swap:type_list"); + memory->create(rate_list, atom->ntypes, "neighbor/swap:rate_list"); + + // read options from end of input line + + options(narg - 9, &arg[9]); + + // random number generator, same for all procs + + random_equal = new RanPark(lmp, seed); + + // set up reneighboring + + force_reneighbor = 1; + next_reneighbor = update->ntimestep + 1; + + // zero out counters + + nswap_attempts = 0.0; + nswap_successes = 0.0; + + atom_swap_nmax = 0; + + // set comm size needed by this Fix + + if (atom->q_flag) + comm_forward = 2; + else + comm_forward = 1; +} + +/* ---------------------------------------------------------------------- */ + +FixNeighborSwap::~FixNeighborSwap() +{ + memory->destroy(type_list); + memory->destroy(rate_list); + memory->destroy(qtype); + memory->destroy(sqrt_mass_ratio); + memory->destroy(local_swap_iatom_list); + memory->destroy(local_swap_neighbor_list); + memory->destroy(local_swap_probability); + memory->destroy(local_swap_type_list); + delete[] idregion; + delete[] id_voro; + delete random_equal; +} + +/* ---------------------------------------------------------------------- + parse optional parameters at end of input line +------------------------------------------------------------------------- */ + +static const std::unordered_set known_keywords = {"region", "ke", "types", "diff", + "rates"}; +static bool is_keyword(const std::string &arg) +{ + return known_keywords.find(arg) != known_keywords.end(); +} + +void FixNeighborSwap::options(int narg, char **arg) +{ + if (narg < 0) utils::missing_cmd_args(FLERR, "fix neighbor/swap", error); + + int ioffset = 9; // first 9 arguments are fixed and handled in constructor + int iarg = 0; + while (iarg < narg) { + if (strcmp(arg[iarg], "region") == 0) { + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "fix neighbor/swap region", error); + delete[] idregion; + idregion = utils::strdup(arg[iarg + 1]); + region = domain->get_region_by_id(idregion); + if (!region) + error->all(FLERR, iarg + 1 + ioffset, "Region ID {} for fix neighbor/swap does not exist", + idregion); + iarg += 2; + } else if (strcmp(arg[iarg], "ke") == 0) { + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "fix neighbor/swap ke", error); + ke_flag = utils::logical(FLERR, arg[iarg + 1], false, lmp); + iarg += 2; + } else if (strcmp(arg[iarg], "types") == 0) { + if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "fix neighbor/swap types", error); + if (diff_flag) + error->all(FLERR, iarg + ioffset, "Cannot use 'diff' and 'types' keywords together"); + iarg++; + nswaptypes = 0; + while (iarg < narg) { + if (is_keyword(arg[iarg])) break; + if (nswaptypes >= atom->ntypes) + error->all(FLERR, iarg + ioffset, "Too many arguments to fix neighbor/swap types"); + type_list[nswaptypes] = utils::expand_type_int(FLERR, arg[iarg], Atom::ATOM, lmp); + nswaptypes++; + iarg++; + } + } else if (strcmp(arg[iarg], "diff") == 0) { + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "fix neighbor/swap diff", error); + if (diff_flag) error->all(FLERR, iarg + ioffset, "Cannot use 'diff' keyword multiple times"); + if (nswaptypes != 0) + error->all(FLERR, iarg + ioffset, "Cannot use 'diff' and 'types' keywords together"); + type_list[nswaptypes] = utils::numeric(FLERR, arg[iarg + 1], false, lmp); + diff_flag = 1; + nswaptypes++; + iarg += 2; + } else if (strcmp(arg[iarg], "rates") == 0) { + if (iarg + atom->ntypes >= narg) + utils::missing_cmd_args(FLERR, "fix neighbor/swap rates", error); + iarg++; + int i = 0; + while (iarg < narg) { + if (is_keyword(arg[iarg])) break; + if (i >= atom->ntypes) error->all(FLERR, "Too many values for fix neighbor/swap rates"); + rate_list[i] = utils::numeric(FLERR, arg[iarg], false, lmp); + i++; + iarg++; + } + rates_flag = 1; + if (i != atom->ntypes) + error->all(FLERR, "Fix neighbor/swap rates keyword must have exactly {} arguments", + atom->ntypes); + } else { + error->all(FLERR, "Unknown fix neighbor/swap keyword: {}", arg[iarg]); + } + } + + // checks + if (!nswaptypes && !diff_flag) + error->all(FLERR, Error::NOLASTLINE, + "Must specify at either 'types' or 'diff' keyword with fix neighbor/swap"); + + if (nswaptypes < 2 && !diff_flag) + error->all(FLERR, Error::NOLASTLINE, + "Must specify at least 2 atom types in fix neighbor/swap 'types' keyword"); +} + +/* ---------------------------------------------------------------------- */ + +int FixNeighborSwap::setmask() +{ + int mask = 0; + mask |= PRE_EXCHANGE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixNeighborSwap::init() +{ + c_pe = modify->get_compute_by_id("thermo_pe"); + if (!c_pe) error->all(FLERR, Error::NOLASTLINE, "Could not find 'thermo_pe' compute"); + + c_voro = modify->get_compute_by_id(id_voro); + if (!c_voro) + error->all(FLERR, Error::NOLASTLINE, "Could not find compute voronoi ID {}", id_voro); + + // set index and check validity of region + + if (idregion) { + region = domain->get_region_by_id(idregion); + if (!region) + error->all(FLERR, Error::NOLASTLINE, "Region {} for fix neighbor/swap does not exist", + idregion); + } + + for (int iswaptype = 0; iswaptype < nswaptypes; iswaptype++) + if (type_list[iswaptype] <= 0 || type_list[iswaptype] > atom->ntypes) + error->all(FLERR, Error::NOLASTLINE, "Invalid atom type in fix neighbor/swap command"); + + int *type = atom->type; + if (atom->q_flag) { + double qmax, qmin; + int firstall, first; + memory->create(qtype, nswaptypes, "neighbor/swap:qtype"); + for (int iswaptype = 0; iswaptype < nswaptypes; iswaptype++) { + first = 1; + for (int i = 0; i < atom->nlocal; i++) { + if (atom->mask[i] & groupbit) { + if (type[i] == type_list[iswaptype]) { + if (first > 0) { + qtype[iswaptype] = atom->q[i]; + first = 0; + } else if (qtype[iswaptype] != atom->q[i]) + first = -1; + } + } + } + MPI_Allreduce(&first, &firstall, 1, MPI_INT, MPI_MIN, world); + if (firstall < 0) + error->all(FLERR, Error::NOLASTLINE, + "All atoms of a swapped type must have the same charge"); + if (firstall > 0) + error->all(FLERR, Error::NOLASTLINE, + "At least one atom of each swapped type must be present to define charges"); + if (first) qtype[iswaptype] = -DBL_MAX; + MPI_Allreduce(&qtype[iswaptype], &qmax, 1, MPI_DOUBLE, MPI_MAX, world); + if (first) qtype[iswaptype] = DBL_MAX; + MPI_Allreduce(&qtype[iswaptype], &qmin, 1, MPI_DOUBLE, MPI_MIN, world); + if (qmax != qmin) + error->all(FLERR, Error::NOLASTLINE, "All atoms of a swapped type must have same charge."); + } + } + + memory->create(sqrt_mass_ratio, atom->ntypes + 1, atom->ntypes + 1, + "neighbor/swap:sqrt_mass_ratio"); + for (int itype = 1; itype <= atom->ntypes; itype++) + for (int jtype = 1; jtype <= atom->ntypes; jtype++) + sqrt_mass_ratio[itype][jtype] = sqrt(atom->mass[itype] / atom->mass[jtype]); + + // check to see if itype and jtype cutoffs are the same + // if not, reneighboring will be needed between swaps + + double **cutsq = force->pair->cutsq; + unequal_cutoffs = false; + for (int iswaptype = 0; iswaptype < nswaptypes; iswaptype++) + for (int jswaptype = 0; jswaptype < nswaptypes; jswaptype++) + for (int ktype = 1; ktype <= atom->ntypes; ktype++) + if (cutsq[type_list[iswaptype]][ktype] != cutsq[type_list[jswaptype]][ktype]) + unequal_cutoffs = true; + + // check that no swappable atoms are in atom->firstgroup + // swapping such an atom might not leave firstgroup atoms first + + if (atom->firstgroup >= 0) { + int *mask = atom->mask; + int firstgroupbit = group->bitmask[atom->firstgroup]; + + int flag = 0; + for (int i = 0; i < atom->nlocal; i++) + if ((mask[i] == groupbit) && (mask[i] && firstgroupbit)) flag = 1; + + int flagall; + MPI_Allreduce(&flag, &flagall, 1, MPI_INT, MPI_SUM, world); + if (flagall) + error->all(FLERR, Error::NOLASTLINE, + "Cannot use fix neighbor/swap on atoms in atom_modify first group"); + } +} + +/* ---------------------------------------------------------------------- + attempt Monte Carlo swaps +------------------------------------------------------------------------- */ + +void FixNeighborSwap::pre_exchange() +{ + // just return if should not be called on this timestep + + if (next_reneighbor != update->ntimestep) return; + + // ensure current system is ready to compute energy + + if (domain->triclinic) domain->x2lamda(atom->nlocal); + domain->pbc(); + comm->exchange(); + comm->borders(); + if (domain->triclinic) domain->lamda2x(atom->nlocal + atom->nghost); + if (modify->n_pre_neighbor) modify->pre_neighbor(); + neighbor->build(1); + + // energy_stored = energy of current state + // will be updated after accepted swaps + + energy_stored = energy_full(); + + // attempt Ncycle atom swaps + + int nsuccess = 0; + update_iswap_atoms_list(); + for (int i = 0; i < ncycles; i++) nsuccess += attempt_swap(); + + // udpate MC stats + + nswap_attempts += ncycles; + nswap_successes += nsuccess; + + next_reneighbor = update->ntimestep + nevery; +} + +/* ---------------------------------------------------------------------- + attempt a swap of a pair of atoms + compare before/after energy and accept/reject the swap +------------------------------------------------------------------------- */ + +int FixNeighborSwap::attempt_swap() +{ + if (niswap == 0) return 0; + + // pre-swap energy + + double energy_before = energy_stored; + + // pick a random atom i + + int i = pick_i_swap_atom(); + + // build nearest-neighbor list based on atom i + + build_i_neighbor_list(i); + if (njswap <= 0) return 0; + + // pick a neighbor atom j based on i neighbor list + jtype_selected = -1; + int j = pick_j_swap_neighbor(); + + int itype = type_list[0]; + int jtype = jtype_selected; + + // Accept swap if types are equal, no change to system + if (itype == jtype) { return 1; } + + // swap their properties + if (i >= 0) { + atom->type[i] = jtype; + if (atom->q_flag) atom->q[i] = qtype[jtype_selected]; + } + if (j >= 0) { + atom->type[j] = itype; + if (atom->q_flag) atom->q[j] = qtype[0]; + } + + // if unequal_cutoffs, call comm->borders() and rebuild neighbor list + // else communicate ghost atoms + // call to comm->exchange() is a no-op but clears ghost atoms + + if (unequal_cutoffs) { + if (domain->triclinic) domain->x2lamda(atom->nlocal); + domain->pbc(); + comm->exchange(); + comm->borders(); + if (domain->triclinic) domain->lamda2x(atom->nlocal + atom->nghost); + if (modify->n_pre_neighbor) modify->pre_neighbor(); + neighbor->build(1); + } else { + comm->forward_comm(this); + } + + // post-swap energy + + double energy_after = energy_full(); + + // if swap accepted, return 1 + // if ke_flag, rescale atom velocities + + if (random_equal->uniform() < exp(beta * (energy_before - energy_after))) { + update_iswap_atoms_list(); + if (ke_flag) { + if (i >= 0) { + atom->v[i][0] *= sqrt_mass_ratio[itype][jtype]; + atom->v[i][1] *= sqrt_mass_ratio[itype][jtype]; + atom->v[i][2] *= sqrt_mass_ratio[itype][jtype]; + } + if (j >= 0) { + atom->v[j][0] *= sqrt_mass_ratio[jtype][itype]; + atom->v[j][1] *= sqrt_mass_ratio[jtype][itype]; + atom->v[j][2] *= sqrt_mass_ratio[jtype][itype]; + } + } + energy_stored = energy_after; + return 1; + } + + // swap not accepted, return 0 + // restore the swapped itype & jtype atoms + // do not need to re-call comm->borders() and rebuild neighbor list + // since will be done on next cycle or in Verlet when this fix finishes + + if (i >= 0) { + atom->type[i] = itype; + if (atom->q_flag) atom->q[i] = qtype[0]; + } + if (j >= 0) { + atom->type[j] = jtype; + if (atom->q_flag) atom->q[j] = qtype[jtype_selected]; + } + + return 0; +} + +/* ---------------------------------------------------------------------- + compute system potential energy +------------------------------------------------------------------------- */ + +double FixNeighborSwap::energy_full() +{ + int eflag = 1; + int vflag = 0; + + if (modify->n_pre_force) modify->pre_force(vflag); + + if (force->pair) force->pair->compute(eflag, vflag); + + if (atom->molecular != Atom::ATOMIC) { + if (force->bond) force->bond->compute(eflag, vflag); + if (force->angle) force->angle->compute(eflag, vflag); + if (force->dihedral) force->dihedral->compute(eflag, vflag); + if (force->improper) force->improper->compute(eflag, vflag); + } + + if (force->kspace) force->kspace->compute(eflag, vflag); + + if (modify->n_post_force_any) modify->post_force(vflag); + + update->eflag_global = update->ntimestep; + double total_energy = c_pe->compute_scalar(); + + return total_energy; +} + +/* ---------------------------------------------------------------------- +------------------------------------------------------------------------- */ + +int FixNeighborSwap::pick_i_swap_atom() +{ + tagint *id = atom->tag; + int i = -1; + + int iwhichglobal = static_cast(niswap * random_equal->uniform()); + if ((iwhichglobal >= niswap_before) && (iwhichglobal < niswap_before + niswap_local)) { + int iwhichlocal = iwhichglobal - niswap_before; + i = local_swap_iatom_list[iwhichlocal]; + MPI_Allreduce(&id[i], &id_center, 1, MPI_INT, MPI_MAX, world); + } else { + id_center = -1; + } + return i; +} + +/* ---------------------------------------------------------------------- +------------------------------------------------------------------------- */ + +int FixNeighborSwap::pick_j_swap_neighbor() +{ + int j = -1; + int jtype_selected_local = -1; + + // Generate random double from 0 to maximum global probability + double selected_prob = static_cast(global_probability * random_equal->uniform()); + + // Find which local swap atom corresponds to probability + if ((selected_prob >= prev_probability) && + (selected_prob < prev_probability + local_probability)) { + double search_prob = selected_prob - prev_probability; + for (int n = 0; n < njswap_local; n++) { + if (search_prob > local_swap_probability[n]) { + search_prob -= local_swap_probability[n]; + } else { + j = local_swap_neighbor_list[n]; + jtype_selected_local = local_swap_type_list[n]; + MPI_Allreduce(&jtype_selected_local, &jtype_selected, 1, MPI_INT, MPI_MAX, world); + return j; + } + } + error->all(FLERR, Error::NOLASTLINE, "Did not select local neighbor swap atom"); + } + + MPI_Allreduce(&jtype_selected_local, &jtype_selected, 1, MPI_INT, MPI_MAX, world); + return j; +} + +/* ---------------------------------------------------------------------- +------------------------------------------------------------------------- */ + +void FixNeighborSwap::build_i_neighbor_list(int i_center) +{ + int nghost = atom->nghost; + int nlocal = atom->nlocal; + int *type = atom->type; + double **x = atom->x; + tagint *id = atom->tag; + + // Allocate local_swap_neighbor_list size + + memory->sfree(local_swap_neighbor_list); + atom_swap_nmax = atom->nmax; + local_swap_neighbor_list = + (int *) memory->smalloc(atom_swap_nmax * sizeof(int), "MCSWAP:local_swap_neighbor_list"); + + memory->sfree(local_swap_probability); + local_swap_probability = (double *) memory->smalloc(atom_swap_nmax * sizeof(double), + "MCSWAP:local_swap_probability_list"); + + memory->sfree(local_swap_type_list); + local_swap_type_list = + (int *) memory->smalloc(atom_swap_nmax * sizeof(int), "MCSWAP:local_swap_type_list"); + + // Compute voronoi and access neighbor list + + c_voro->compute_local(); + + voro_neighbor_list = c_voro->array_local; + njswap_local = 0; + local_probability = 0.0; + + for (int n = 0; n < c_voro->size_local_rows; n++) { + + int temp_j_id = -1; + int temp_j = -1; + + // Find local voronoi entry with selected central atom + if ((int) voro_neighbor_list[n][0] == id_center) { + temp_j_id = voro_neighbor_list[n][1]; + temp_j = -1; + } else if (((int) voro_neighbor_list[n][1] == id_center) && (i_center < 0)) { + temp_j_id = voro_neighbor_list[n][0]; + temp_j = -1; + } else { + continue; + } + + // Find which local atom corresponds to neighbor + for (int j = 0; j < nlocal; j++) { + if (temp_j_id == id[j]) { + temp_j = j; + break; + } + } + + // If temp_j not on this processor, skip + if (temp_j < 0) continue; + + if (region) { + if (region->match(x[temp_j][0], x[temp_j][1], x[temp_j][2]) == 1) { + if (atom->mask[temp_j] & groupbit) { + if (diff_flag) { + // Calculate distance from i to each j, adjust probability of selection + + // Get distance if own center atom + double r = INFINITY; + + // Get local id of ghost center atom when ghost + for (int i = nlocal; i < nlocal + nghost; i++) { + double rtmp = sqrt(distsq3(x[temp_j], x[i])); + if ((id[i] == id_center) && (rtmp < r)) r = rtmp; + } + + if (rates_flag) { + local_swap_probability[njswap_local] = + rate_list[type[temp_j] - 1] * exp(-square(r * inv_r_0)); + } else { + local_swap_probability[njswap_local] = exp(-square(r * inv_r_0)); + } + local_probability += local_swap_probability[njswap_local]; + local_swap_type_list[njswap_local] = type[temp_j]; + local_swap_neighbor_list[njswap_local] = temp_j; + njswap_local++; + } else { + for (int jswaptype = 1; jswaptype < nswaptypes; jswaptype++) { + if (type[temp_j] == type_list[jswaptype]) { + // Calculate distance from i to each j, adjust probability of selection + // Get distance if own center atom + double r = INFINITY; + + // Get local id of ghost center atom when ghost + for (int i = nlocal; i < nlocal + nghost; i++) { + double rtmp = sqrt(distsq3(x[temp_j], x[i])); + if ((id[i] == id_center) && (rtmp < r)) r = rtmp; + } + + if (rates_flag) { + local_swap_probability[njswap_local] = + rate_list[type[temp_j] - 1] * exp(-square(r * inv_r_0)); + } else { + local_swap_probability[njswap_local] = exp(-square(r * inv_r_0)); + } + local_probability += local_swap_probability[njswap_local]; + + local_swap_type_list[njswap_local] = jswaptype; + local_swap_neighbor_list[njswap_local] = temp_j; + njswap_local++; + } + } + } + } + } + } else { + if (atom->mask[temp_j] & groupbit) { + if (diff_flag) { + // Calculate distance from i to each j, adjust probability of selection + // Get distance if own center atom + double r = INFINITY; + + // Get local id of ghost center atoms + for (int i = nlocal; i < nlocal + nghost; i++) { + double rtmp = sqrt(distsq3(x[temp_j], x[i])); + if ((id[i] == id_center) && (rtmp < r)) r = rtmp; + } + + if (rates_flag) { + local_swap_probability[njswap_local] = + rate_list[type[temp_j] - 1] * exp(-square(r * inv_r_0)); + } else { + local_swap_probability[njswap_local] = exp(-square(r * inv_r_0)); + } + local_probability += local_swap_probability[njswap_local]; + + local_swap_type_list[njswap_local] = type[temp_j]; + local_swap_neighbor_list[njswap_local] = temp_j; + njswap_local++; + } else { + for (int jswaptype = 1; jswaptype < nswaptypes; jswaptype++) { + if (type[temp_j] == type_list[jswaptype]) { + // Calculate distance from i to each j, adjust probability of selection + // Get distance if own center atom + double r = INFINITY; + + // Get local id of ghost center atom when ghost + for (int i = nlocal; i < nlocal + nghost; i++) { + double rtmp = sqrt(distsq3(x[temp_j], x[i])); + if ((id[i] == id_center) && (rtmp < r)) r = rtmp; + } + + if (rates_flag) { + local_swap_probability[njswap_local] = + rate_list[type[temp_j] - 1] * exp(-square(r * inv_r_0)); + } else { + local_swap_probability[njswap_local] = exp(-square(r * inv_r_0)); + } + local_probability += local_swap_probability[njswap_local]; + + local_swap_type_list[njswap_local] = jswaptype; + local_swap_neighbor_list[njswap_local] = temp_j; + njswap_local++; + } + } + } + } + } + } + + MPI_Allreduce(&njswap_local, &njswap, 1, MPI_INT, MPI_SUM, world); + MPI_Scan(&njswap_local, &njswap_before, 1, MPI_INT, MPI_SUM, world); + njswap_before -= njswap_local; + + MPI_Allreduce(&local_probability, &global_probability, 1, MPI_DOUBLE, MPI_SUM, world); + MPI_Scan(&local_probability, &prev_probability, 1, MPI_DOUBLE, MPI_SUM, world); + prev_probability -= local_probability; +} + +/* ---------------------------------------------------------------------- + update the list of swap atoms +------------------------------------------------------------------------- */ + +void FixNeighborSwap::update_iswap_atoms_list() +{ + int nlocal = atom->nlocal; + int *type = atom->type; + double **x = atom->x; + + if (atom->nmax > atom_swap_nmax) { + memory->sfree(local_swap_iatom_list); + atom_swap_nmax = atom->nmax; + local_swap_iatom_list = + (int *) memory->smalloc(atom_swap_nmax * sizeof(int), "MCSWAP:local_swap_iatom_list"); + } + + niswap_local = 0; + + if (region) { + + for (int i = 0; i < nlocal; i++) { + if (region->match(x[i][0], x[i][1], x[i][2]) == 1) { + if (atom->mask[i] & groupbit) { + if (type[i] == type_list[0]) { + local_swap_iatom_list[niswap_local] = i; + niswap_local++; + } + } + } + } + + } else { + for (int i = 0; i < nlocal; i++) { + if (atom->mask[i] & groupbit) { + if (type[i] == type_list[0]) { + local_swap_iatom_list[niswap_local] = i; + niswap_local++; + } + } + } + } + + MPI_Allreduce(&niswap_local, &niswap, 1, MPI_INT, MPI_SUM, world); + MPI_Scan(&niswap_local, &niswap_before, 1, MPI_INT, MPI_SUM, world); + niswap_before -= niswap_local; +} + +/* ---------------------------------------------------------------------- */ + +int FixNeighborSwap::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, + int * /*pbc*/) +{ + int i, j, m; + + int *type = atom->type; + double *q = atom->q; + + m = 0; + + if (atom->q_flag) { + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = type[j]; + buf[m++] = q[j]; + } + } else { + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = type[j]; + } + } + + return m; +} + +/* ---------------------------------------------------------------------- */ + +void FixNeighborSwap::unpack_forward_comm(int n, int first, double *buf) +{ + int i, m, last; + + int *type = atom->type; + double *q = atom->q; + + m = 0; + last = first + n; + + if (atom->q_flag) { + for (i = first; i < last; i++) { + type[i] = static_cast(buf[m++]); + q[i] = buf[m++]; + } + } else { + for (i = first; i < last; i++) type[i] = static_cast(buf[m++]); + } +} + +/* ---------------------------------------------------------------------- + return acceptance ratio +------------------------------------------------------------------------- */ + +double FixNeighborSwap::compute_vector(int n) +{ + if (n == 0) return nswap_attempts; + if (n == 1) return nswap_successes; + return 0.0; +} + +/* ---------------------------------------------------------------------- + memory usage of local atom-based arrays +------------------------------------------------------------------------- */ + +double FixNeighborSwap::memory_usage() +{ + double bytes = (double) atom_swap_nmax * sizeof(int); + return bytes; +} + +/* ---------------------------------------------------------------------- + pack entire state of Fix into one write +------------------------------------------------------------------------- */ + +void FixNeighborSwap::write_restart(FILE *fp) +{ + int n = 0; + double list[6]; + list[n++] = random_equal->state(); + list[n++] = ubuf(next_reneighbor).d; + list[n++] = nswap_attempts; + list[n++] = nswap_successes; + list[n++] = ubuf(update->ntimestep).d; + + if (comm->me == 0) { + int size = n * sizeof(double); + fwrite(&size, sizeof(int), 1, fp); + fwrite(list, sizeof(double), n, fp); + } +} + +/* ---------------------------------------------------------------------- + use state info from restart file to restart the Fix +------------------------------------------------------------------------- */ + +void FixNeighborSwap::restart(char *buf) +{ + int n = 0; + double *list = (double *) buf; + + seed = static_cast(list[n++]); + random_equal->reset(seed); + + next_reneighbor = (bigint) ubuf(list[n++]).i; + + nswap_attempts = static_cast(list[n++]); + nswap_successes = static_cast(list[n++]); + + bigint ntimestep_restart = (bigint) ubuf(list[n++]).i; + if (ntimestep_restart != update->ntimestep) + error->all(FLERR, Error::NOLASTLINE, + "Must not reset timestep when restarting fix neighbor/swap"); +} diff --git a/src/MC/fix_neighbor_swap.h b/src/MC/fix_neighbor_swap.h new file mode 100644 index 0000000000..f5d208f764 --- /dev/null +++ b/src/MC/fix_neighbor_swap.h @@ -0,0 +1,98 @@ +/* -*- 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 FIX_CLASS +// clang-format off +FixStyle(neighbor/swap,FixNeighborSwap); +// clang-format on +#else + +#ifndef LMP_FIX_NEIGH_SWAP_H +#define LMP_FIX_NEIGH_SWAP_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixNeighborSwap : public Fix { + public: + FixNeighborSwap(class LAMMPS *, int, char **); + ~FixNeighborSwap(); + int setmask(); + void init(); + void pre_exchange(); + int pack_forward_comm(int, int *, double *, int, int *); + void unpack_forward_comm(int, int, double *); + double compute_vector(int); + double memory_usage(); + void write_restart(FILE *); + void restart(char *); + + private: + int nevery, seed; + int ke_flag; // yes = conserve ke, no = do not conserve ke + int diff_flag; // yes = simulate diffusion of central atom, no = swap only to certain types + int rates_flag; // yes = use modified type rates, no = swap rates are equivilent across types + int ncycles; + int niswap, njswap; // # of i,j swap atoms on all procs + int niswap_local, njswap_local; // # of swap atoms on this proc + int niswap_before, njswap_before; // # of swap atoms on procs < this proc + class Region *region; // swap region + char *idregion; // swap region id + + int nswaptypes; + int jtype_selected; + int id_center; + double x_center; + double y_center; + double z_center; + int *type_list; + double *rate_list; + + double nswap_attempts; + double nswap_successes; + + bool unequal_cutoffs; + + int atom_swap_nmax; + double beta, inv_r_0; + double local_probability; // Total swap probability stored on this proc + double global_probability; // Total swap probability across all proc + double prev_probability; // Swap probability on proc < this proc + double *qtype; + double energy_stored; + double **sqrt_mass_ratio; + double **voro_neighbor_list; + int *local_swap_iatom_list; + int *local_swap_neighbor_list; + int *local_swap_type_list; // Type list index of atoms stored on this proc + double *local_swap_probability; + + class RanPark *random_equal; + + char *id_voro; + class Compute *c_voro, *c_pe; + + void options(int, char **); + int attempt_swap(); + double energy_full(); + int pick_i_swap_atom(); + int pick_j_swap_neighbor(); + void build_i_neighbor_list(int); + void update_iswap_atoms_list(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/MC/fix_sgcmc.cpp b/src/MC/fix_sgcmc.cpp index c405421b7f..c081d84f2d 100644 --- a/src/MC/fix_sgcmc.cpp +++ b/src/MC/fix_sgcmc.cpp @@ -124,6 +124,7 @@ FixSemiGrandCanonicalMC::FixSemiGrandCanonicalMC(LAMMPS *_lmp, int narg, char ** // Default values for optional parameters (where applicable). numSamplingWindowMoves = 8; seed = 324234; + atomicenergyflag = 0; // Parse extra/optional parameters while (iarg < narg) { @@ -175,7 +176,7 @@ FixSemiGrandCanonicalMC::FixSemiGrandCanonicalMC(LAMMPS *_lmp, int narg, char ** targetConcentration[i] = utils::numeric(FLERR, arg[iarg], false, lmp); targetConcentration[1] -= targetConcentration[i]; } - for (int i = 1; i <= atom->ntypes; i++, iarg++) { + for (int i = 1; i <= atom->ntypes; i++) { if ((targetConcentration[i] < 0.0) || (targetConcentration[i] > 1.0)) error->all(FLERR, "Target concentration {} for species {} is out of range", targetConcentration[i], i); @@ -183,7 +184,6 @@ FixSemiGrandCanonicalMC::FixSemiGrandCanonicalMC(LAMMPS *_lmp, int narg, char ** utils::logmesg(lmp, " SGC - Target concentration of species {}: {}\n", i, targetConcentration[i]); } - } else if (strcmp(arg[iarg], "serial") == 0) { // Switch off second rejection. serialMode = true; @@ -193,6 +193,12 @@ FixSemiGrandCanonicalMC::FixSemiGrandCanonicalMC(LAMMPS *_lmp, int narg, char ** if (comm->nprocs != 1) error->all(FLERR, "Cannot use serial mode Monte Carlo in a parallel simulation."); + + } else if (strcmp(arg[iarg],"atomic/energy") == 0) { + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, fmt::format("fix {} atomic/energy", style), error); + atomicenergyflag = utils::logical(FLERR,arg[iarg+1],false,lmp); + iarg += 2; + } else { error->all(FLERR, "Unknown fix sgcmc keyword: {}", arg[iarg]); } @@ -243,25 +249,40 @@ void FixSemiGrandCanonicalMC::init() if (modify->get_fix_by_style("sgcmc").size() > 1) error->all(FLERR, "More than one fix sgcmc defined."); - // Save a pointer to the EAM potential. - pairEAM = dynamic_cast(force->pair); - if (!pairEAM) { - if (comm->me == 0) - utils::logmesg(lmp, " SGC - Using naive total energy calculation for MC -> SLOW!\n"); + if (atomicenergyflag) { + // Save a pointer to the EAM potential. + if (comm->me == 0) utils::logmesg(lmp, " SGC - Using atomic energy method for SGCMC\n"); + if (!force->pair->atomic_energy_enable) { + error->all(FLERR, "SGC - Pair style does not support atomic energy method"); + } + } else { + // Save a pointer to the EAM potential. + pairEAM = dynamic_cast(force->pair); + if (!pairEAM) { - if (comm->nprocs > 1) - error->all(FLERR, "Can not run fix sgcmc with naive total energy calculation " - "and more than one MPI process."); + if (comm->me == 0) + utils::logmesg(lmp, " SGC - Using naive total energy calculation for MC -> SLOW!\n"); - // Get reference to a compute that will provide the total energy of the system. - // This is needed by computeTotalEnergy(). - compute_pe = modify->get_compute_by_id("thermo_pe"); + if (comm->nprocs > 1) + error->all(FLERR, "Can not run fix sgcmc with naive total energy calculation " + "and more than one MPI process."); + + // Get reference to a compute that will provide the total energy of the system. + // This is needed by computeTotalEnergy(). + compute_pe = modify->get_compute_by_id("thermo_pe"); + } } + interactionRadius = force->pair->cutforce; if (comm->me == 0) utils::logmesg(lmp, " SGC - Interaction radius: {}\n", interactionRadius); + // This fix needs a full neighbor list. - neighbor->add_request(this, NeighConst::REQ_FULL); + if (atomicenergyflag) + // for atomic energy method, need ghost neighbors + neighbor->add_request(this, NeighConst::REQ_FULL | NeighConst::REQ_GHOST); + else + neighbor->add_request(this, NeighConst::REQ_FULL); // Count local number of atoms from each species. const int *type = atom->type; @@ -379,11 +400,18 @@ void FixSemiGrandCanonicalMC::doMC() deltaN[newSpecies] = +1; // Compute the energy difference that swapping this atom would cost or gain. - if (pairEAM) { - deltaE = computeEnergyChangeEAM(selectedAtom, selectedAtomNL, oldSpecies, newSpecies); + + // Atomic energy method: + if(atomicenergyflag) { + deltaE = computeEnergyChangeEatom(selectedAtom, oldSpecies, newSpecies); } else { - // Generic case: - deltaE = computeEnergyChangeGeneric(selectedAtom, oldSpecies, newSpecies); + // EAM method: + if (pairEAM) { + deltaE = computeEnergyChangeEAM(selectedAtom, selectedAtomNL, oldSpecies, newSpecies); + } else { + // Generic method + deltaE = computeEnergyChangeGeneric(selectedAtom, oldSpecies, newSpecies); + } } // Perform inner MC acceptance test. @@ -440,10 +468,14 @@ void FixSemiGrandCanonicalMC::doMC() // Make accepted atom swap permanent. if (selectedAtom >= 0) { - if (pairEAM) - flipAtomEAM(selectedAtom, selectedAtomNL, oldSpecies, newSpecies); - else - flipAtomGeneric(selectedAtom, oldSpecies, newSpecies); + if(atomicenergyflag) { + flipAtomEatom(selectedAtom, oldSpecies, newSpecies); + } else { + if (pairEAM) + flipAtomEAM(selectedAtom, selectedAtomNL, oldSpecies, newSpecies); + else + flipAtomGeneric(selectedAtom, oldSpecies, newSpecies); + } nAcceptedSwapsLocal++; } else { nRejectedSwapsLocal++; @@ -989,6 +1021,67 @@ void FixSemiGrandCanonicalMC::flipAtomGeneric(int flipAtom, int oldSpecies, int changedAtoms[flipAtom] = true; } +/********************************************************************* + * Calculates the change in energy that swapping the given + * atom would produce. This routine uses a per-atom energy calculation + *********************************************************************/ + +double FixSemiGrandCanonicalMC::computeEnergyChangeEatom(int flipAtom, int oldSpecies, int newSpecies) +{ + double Eold, Enew, deltaE; + + // Calculate old atomic energy of selected atom + + Eold = force->pair->compute_atomic_energy(flipAtom, neighborList); + + // calculate the old per-atom energy of neighbors + + int* jlist = neighborList->firstneigh[flipAtom]; + int jnum = neighborList->numneigh[flipAtom]; + + for(int jj = 0; jj < jnum; jj++) { + int j = jlist[jj]; + Eold += force->pair->compute_atomic_energy(j, neighborList); + } + + // Calculate new per-atom energy of selected atom + + atom->type[flipAtom] = newSpecies; + + Enew = force->pair->compute_atomic_energy(flipAtom, neighborList); + + // calculate the new per-atom energy of neighbors + + for(int jj = 0; jj < jnum; jj++) { + int j = jlist[jj]; + Enew += force->pair->compute_atomic_energy(j, neighborList); + } + + atom->type[flipAtom] = oldSpecies; + + deltaE = Enew - Eold; + + return deltaE; +} + +/********************************************************************* + * Flips the type of one atom. + * This routine is for the per-atom energy case. + *********************************************************************/ + +void FixSemiGrandCanonicalMC::flipAtomEatom(int flipAtom, int oldSpecies, int newSpecies) +{ + atom->type[flipAtom] = newSpecies; + + // Rescale particle velocity vector to conserve kinetic energy. + double vScaleFactor = sqrt(atom->mass[oldSpecies] / atom->mass[newSpecies]); + atom->v[flipAtom][0] *= vScaleFactor; + atom->v[flipAtom][1] *= vScaleFactor; + atom->v[flipAtom][2] *= vScaleFactor; + + changedAtoms[flipAtom] = true; +} + /********************************************************************* * Lets the fix report one of its internal state variables to LAMMPS. *********************************************************************/ diff --git a/src/MC/fix_sgcmc.h b/src/MC/fix_sgcmc.h index 9ad3f65214..16ed23391f 100644 --- a/src/MC/fix_sgcmc.h +++ b/src/MC/fix_sgcmc.h @@ -75,6 +75,10 @@ class FixSemiGrandCanonicalMC : public Fix { // This routine should only be used for debugging purposes. double computeEnergyChangeGeneric(int flipAtom, int oldSpecies, int newSpecies); + // Calculates the change in energy that swapping the given atom would produce. + // This uses the atomic energy method + double computeEnergyChangeEatom(int flipAtom, int oldSpecies, int newSpecies); + // Lets LAMMPS calculate the total potential energy of the system. double computeTotalEnergy(); @@ -86,6 +90,10 @@ class FixSemiGrandCanonicalMC : public Fix { // This routine is for the generic case. void flipAtomGeneric(int flipAtom, int oldSpecies, int newSpecies); + // Flips the type of one atom. + // This routine is for the atomic energy method + void flipAtomEatom(int flipAtom, int oldSpecies, int newSpecies); + // Transfers the locally changed electron densities and atom types to the neighbors. void communicateRhoAndTypes(); @@ -181,6 +189,9 @@ class FixSemiGrandCanonicalMC : public Fix { // A compute used to compute the total potential energy of the system. class Compute *compute_pe; + + // Indicate whether or not atomic energy method is used + int atomicenergyflag; }; } // namespace LAMMPS_NS diff --git a/src/MDI/fix_mdi_qmmm.cpp b/src/MDI/fix_mdi_qmmm.cpp index dc5653bfce..d14c837cba 100644 --- a/src/MDI/fix_mdi_qmmm.cpp +++ b/src/MDI/fix_mdi_qmmm.cpp @@ -687,7 +687,7 @@ void FixMDIQMMM::pre_force(int vflag) double delx = xqm[i][0] - xqm[j][0]; double dely = xqm[i][1] - xqm[j][1]; double delz = xqm[i][2] - xqm[j][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); rsq = delx * delx + dely * dely + delz * delz; qpotential_mine[i] -= qqrd2e * qqm[j] / sqrt(rsq); } diff --git a/src/MESONT/angle_mesocnt.cpp b/src/MESONT/angle_mesocnt.cpp index 1394edc4c1..0e2ec7aa10 100644 --- a/src/MESONT/angle_mesocnt.cpp +++ b/src/MESONT/angle_mesocnt.cpp @@ -371,13 +371,13 @@ double AngleMesoCNT::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/MISC/fix_ipi.cpp b/src/MISC/fix_ipi.cpp index a571066b35..a713b9844b 100644 --- a/src/MISC/fix_ipi.cpp +++ b/src/MISC/fix_ipi.cpp @@ -399,7 +399,7 @@ void FixIPI::initial_integrate(int /*vflag*/) auto dely = x[i][1] - xhold[i][1]; auto delz = x[i][2] - xhold[i][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); x[i][0] = xhold[i][0] + delx; x[i][1] = xhold[i][1] + dely; diff --git a/src/ML-IAP/mliap_descriptor.cpp b/src/ML-IAP/mliap_descriptor.cpp index b8acd6329e..017d36e5e7 100644 --- a/src/ML-IAP/mliap_descriptor.cpp +++ b/src/ML-IAP/mliap_descriptor.cpp @@ -25,7 +25,7 @@ using namespace LAMMPS_NS; MLIAPDescriptor::MLIAPDescriptor(LAMMPS *lmp) : Pointers(lmp), ndescriptors(0), nelements(0), elements(nullptr), cutsq(nullptr), - cutghost(nullptr), radelem(nullptr), wjelem(nullptr) + radelem(nullptr), wjelem(nullptr) { cutmax = 0.0; allocated_elements = 0; @@ -35,10 +35,10 @@ MLIAPDescriptor::MLIAPDescriptor(LAMMPS *lmp) : MLIAPDescriptor::~MLIAPDescriptor() { - for (int i = 0; i < nelements; i++) delete[] elements[i]; + if (allocated_elements) + for (int i = 0; i < nelements; i++) delete[] elements[i]; delete[] elements; memory->destroy(cutsq); - memory->destroy(cutghost); memory->destroy(radelem); memory->destroy(wjelem); } diff --git a/src/ML-IAP/mliap_descriptor.h b/src/ML-IAP/mliap_descriptor.h index 6d66356960..676d5becbd 100644 --- a/src/ML-IAP/mliap_descriptor.h +++ b/src/ML-IAP/mliap_descriptor.h @@ -29,15 +29,14 @@ class MLIAPDescriptor : virtual protected Pointers { virtual void init() = 0; virtual double memory_usage(); - int ndescriptors; // number of descriptors - int nelements; // # of unique elements - int allocated_elements; // is the element array allocated - char **elements; // names of unique elements - double **cutsq; // nelem x nelem rcutsq values - double **cutghost; // cutoff for each ghost pair - double cutmax; // maximum cutoff needed - double *radelem; // element radii - double *wjelem; // elements weights + int ndescriptors; // number of descriptors + int nelements; // # of unique elements + int allocated_elements; // is the element array allocated + char **elements; // names of unique elements + double **cutsq; // nelem x nelem rcutsq values + double cutmax; // maximum cutoff needed + double *radelem; // element radii + double *wjelem; // elements weights protected: }; diff --git a/src/ML-IAP/mliap_descriptor_ace.cpp b/src/ML-IAP/mliap_descriptor_ace.cpp index b13699193c..9b5d473123 100644 --- a/src/ML-IAP/mliap_descriptor_ace.cpp +++ b/src/ML-IAP/mliap_descriptor_ace.cpp @@ -82,7 +82,7 @@ MLIAPDescriptorACE::MLIAPDescriptorACE(LAMMPS *_lmp, char *yacefilename) : for (int iielem = 0; iielem < nelements; iielem++) delete[] elements[iielem]; delete[] elements; allocated_elements = 0; - } else if (not allocated_elements) { + } else if (!allocated_elements) { elements = new char *[nelements]; for (int iielem = 0; iielem < nelements; iielem++) { elements[iielem] = utils::strdup(acemlimpl->basis_set->elements_name[iielem]); diff --git a/src/ML-IAP/mliap_descriptor_snap.cpp b/src/ML-IAP/mliap_descriptor_snap.cpp index e8f6eec977..90590d50d4 100644 --- a/src/ML-IAP/mliap_descriptor_snap.cpp +++ b/src/ML-IAP/mliap_descriptor_snap.cpp @@ -363,8 +363,10 @@ void MLIAPDescriptorSNAP::read_paramfile(char *paramfilename) int sinnerflag = 0; int dinnerflag = 0; - for (int i = 0; i < nelements; i++) delete[] elements[i]; - delete[] elements; + if (elements) { + for (int i = 0; i < nelements; i++) delete[] elements[i]; + delete[] elements; + } memory->destroy(radelem); memory->destroy(wjelem); memory->destroy(cutsq); @@ -422,6 +424,7 @@ void MLIAPDescriptorSNAP::read_paramfile(char *paramfilename) for (int ielem = 0; ielem < nelements; ielem++) elements[ielem] = utils::strdup(words.next()); elementsflag = 1; + allocated_elements = 1; } else if (keywd == "radelems") { for (int ielem = 0; ielem < nelements; ielem++) radelem[ielem] = utils::numeric(FLERR, words.next(), false, lmp); diff --git a/src/ML-IAP/mliap_descriptor_so3.cpp b/src/ML-IAP/mliap_descriptor_so3.cpp index 676c53a4a8..a8b086cc03 100644 --- a/src/ML-IAP/mliap_descriptor_so3.cpp +++ b/src/ML-IAP/mliap_descriptor_so3.cpp @@ -73,8 +73,10 @@ void MLIAPDescriptorSO3::read_paramfile(char *paramfilename) rfac0 = 0.99363; rmin0 = 0.0; - for (int i = 0; i < nelements; i++) delete[] elements[i]; - delete[] elements; + if (elements) { + for (int i = 0; i < nelements; i++) delete[] elements[i]; + delete[] elements; + } memory->destroy(radelem); memory->destroy(wjelem); memory->destroy(cutsq); @@ -138,6 +140,7 @@ void MLIAPDescriptorSO3::read_paramfile(char *paramfilename) } elementsflag = 1; + allocated_elements = 1; } else if (skeywd == "radelems") { for (int ielem = 0; ielem < nelements; ielem++) { radelem[ielem] = utils::numeric(FLERR, skeyval, false, lmp); diff --git a/src/ML-IAP/mliap_unified.cpp b/src/ML-IAP/mliap_unified.cpp index 9998ff2af4..d95bd060d7 100644 --- a/src/ML-IAP/mliap_unified.cpp +++ b/src/ML-IAP/mliap_unified.cpp @@ -95,17 +95,14 @@ void MLIAPDummyDescriptor::init() double cut; cutmax = 0.0; memory->create(cutsq, nelements, nelements, "mliap/descriptor/dummy:cutsq"); - memory->create(cutghost, nelements, nelements, "mliap/descriptor/dummy:cutghost"); for (int ielem = 0; ielem < nelements; ielem++) { // rcutfac set from python, is global cutoff for all elements cut = 2.0 * radelem[ielem] * rcutfac; if (cut > cutmax) cutmax = cut; cutsq[ielem][ielem] = cut * cut; - cutghost[ielem][ielem] = cut * cut; for (int jelem = ielem + 1; jelem < nelements; jelem++) { cut = (radelem[ielem] + radelem[jelem]) * rcutfac; cutsq[ielem][jelem] = cutsq[jelem][ielem] = cut * cut; - cutghost[ielem][jelem] = cutghost[jelem][ielem] = cut * cut; } } } @@ -114,7 +111,8 @@ void MLIAPDummyDescriptor::set_elements(char **elems, int nelems) { nelements = nelems; elements = new char *[nelems]; - for (int i = 0; i < nelems; i++) { elements[i] = utils::strdup(elems[i]); } + for (int i = 0; i < nelems; i++) elements[i] = utils::strdup(elems[i]); + allocated_elements = 1; } /* ---------------------------------------------------------------------- */ diff --git a/src/ML-IAP/mliap_unified_couple.pyx b/src/ML-IAP/mliap_unified_couple.pyx index 6c8331d0fa..36c3eddda7 100644 --- a/src/ML-IAP/mliap_unified_couple.pyx +++ b/src/ML-IAP/mliap_unified_couple.pyx @@ -363,7 +363,7 @@ cdef public object mliap_unified_connect(char *fname, MLIAPDummyModel * model, unified = LOADED_MODEL elif str_fname.endswith(".pt") or str_fname.endswith('.pth'): import torch - unified = torch.load(str_fname) + unified = torch.load(str_fname,weights_only=False) else: with open(str_fname, 'rb') as pfile: unified = pickle.load(pfile) @@ -411,6 +411,8 @@ cdef public object mliap_unified_connect(char *fname, MLIAPDummyModel * model, unified_int.descriptor.set_elements(elements, nelements) unified_int.model.nelements = nelements + for i, elem in enumerate(unified.element_types): + free(elements[i]) free(elements) return unified_int diff --git a/src/ML-IAP/pair_mliap.cpp b/src/ML-IAP/pair_mliap.cpp index a40a0a7afa..ecf216e8e0 100644 --- a/src/ML-IAP/pair_mliap.cpp +++ b/src/ML-IAP/pair_mliap.cpp @@ -72,8 +72,8 @@ PairMLIAP::~PairMLIAP() if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); - memory->destroy(cutghost); memory->destroy(map); + memory->destroy(cutghost); } } @@ -125,8 +125,8 @@ void PairMLIAP::allocate() memory->create(setflag,n+1,n+1,"pair:setflag"); memory->create(cutsq,n+1,n+1,"pair:cutsq"); - memory->create(cutghost,n+1,n+1,"pair:cutghost"); memory->create(map,n+1,"pair:map"); + if (ghostneigh) memory->create(cutghost, n+1, n+1, "pair:cutghost"); } /* ---------------------------------------------------------------------- @@ -338,7 +338,7 @@ void PairMLIAP::v_tally(int i, int j, double *fij, double *rij) void PairMLIAP::init_style() { if (force->newton_pair == 0) - error->all(FLERR,"Pair style MLIAP requires newton pair on"); + error->all(FLERR, Error::NOLASTLINE, "Pair style mliap requires newton pair on"); // need a full neighbor list @@ -361,7 +361,7 @@ double PairMLIAP::init_one(int i, int j) "All pair coeffs are not set. Status\n" + Info::get_pair_coeff_status(lmp)); double cutmax = sqrt(descriptor->cutsq[map[i]][map[j]]); - cutghost[i][j] = cutghost[j][i] = 2.0 * cutmax + neighbor->skin; + if (ghostneigh) cutghost[i][j] = cutghost[j][i] = cutmax; return cutmax; } @@ -376,7 +376,6 @@ double PairMLIAP::memory_usage() int n = atom->ntypes+1; bytes += (double)n*n*sizeof(int); // setflag bytes += (double)n*n*sizeof(int); // cutsq - bytes += (double)n*n*sizeof(int); // cutghost bytes += (double)n*sizeof(int); // map bytes += descriptor->memory_usage(); // Descriptor object bytes += model->memory_usage(); // Model object diff --git a/src/ML-PACE/pair_pace.cpp b/src/ML-PACE/pair_pace.cpp index 56dd34916f..c7b5414ef3 100644 --- a/src/ML-PACE/pair_pace.cpp +++ b/src/ML-PACE/pair_pace.cpp @@ -128,7 +128,8 @@ void PairPACE::compute(int eflag, int vflag) double fij[3]; int *ilist, *jlist, *numneigh, **firstneigh; - ev_init(eflag, vflag); + if (copymode) ev_init(eflag, vflag, 0); + else ev_init(eflag, vflag, 1); double **x = atom->x; double **f = atom->f; @@ -144,7 +145,7 @@ void PairPACE::compute(int eflag, int vflag) // ilist: list of "i" atoms for which neighbor lists exist ilist = list->ilist; - //numneigh: the length of each these neigbor list + //numneigh: the length of each these neighbor list numneigh = list->numneigh; // the pointer to the list of neighbors of "i" diff --git a/src/ML-PACE/pair_pace_extrapolation.cpp b/src/ML-PACE/pair_pace_extrapolation.cpp index 957e53d0ad..5ac857d748 100644 --- a/src/ML-PACE/pair_pace_extrapolation.cpp +++ b/src/ML-PACE/pair_pace_extrapolation.cpp @@ -131,7 +131,9 @@ void PairPACEExtrapolation::compute(int eflag, int vflag) double delx, dely, delz, evdwl; double fij[3]; int *ilist, *jlist, *numneigh, **firstneigh; - ev_init(eflag, vflag); + + if (copymode) ev_init(eflag, vflag, 0); + else ev_init(eflag, vflag, 1); // downwards modified by YL @@ -149,7 +151,7 @@ void PairPACEExtrapolation::compute(int eflag, int vflag) // ilist: list of "i" atoms for which neighbor lists exist ilist = list->ilist; - //numneigh: the length of each these neigbor list + //numneigh: the length of each these neighbor list numneigh = list->numneigh; // the pointer to the list of neighbors of "i" diff --git a/src/ML-POD/compute_podd_atom.cpp b/src/ML-POD/compute_podd_atom.cpp index 4ab6e23393..364bfb54ac 100644 --- a/src/ML-POD/compute_podd_atom.cpp +++ b/src/ML-POD/compute_podd_atom.cpp @@ -58,8 +58,8 @@ ComputePODDAtom::ComputePODDAtom(LAMMPS *lmp, int narg, char **arg) : pod = nullptr; elements = nullptr; - if (((((MAXBIGINT*3.0)*atom->natoms)*podptr->nClusters)*podptr->Mdesc) > (MAXSMALLINT*1.0)) - error->all(FLERR, "Per-atom data too large"); + if ((((3.0*atom->natoms)*podptr->nClusters)*podptr->Mdesc) > (MAXSMALLINT*1.0)) + error->all(FLERR, "Too many atoms ({}) for compute {}", atom->natoms, style); size_peratom_cols = 3 * atom->natoms * podptr->Mdesc * podptr->nClusters; peratom_flag = 1; } @@ -110,8 +110,8 @@ void ComputePODDAtom::compute_peratom() if (atom->natoms > nmax) { memory->destroy(pod); nmax = atom->natoms; - if (((((MAXBIGINT*3.0)*atom->natoms)*podptr->nClusters)*podptr->Mdesc) > (MAXSMALLINT*1.0)) - error->all(FLERR, "Per-atom data too large"); + if ((((3.0*atom->natoms)*podptr->nClusters)*podptr->Mdesc) > (MAXSMALLINT*1.0)) + error->all(FLERR, "Too many atoms ({}) for compute {}", atom->natoms, style); int numdesc = 3 * atom->natoms * podptr->Mdesc * podptr->nClusters; memory->create(pod, nmax, numdesc,"podd/atom:pod"); array_atom = pod; diff --git a/src/MOFFF/angle_class2_p6.cpp b/src/MOFFF/angle_class2_p6.cpp index d7cedb0bcf..15a10eebcc 100644 --- a/src/MOFFF/angle_class2_p6.cpp +++ b/src/MOFFF/angle_class2_p6.cpp @@ -453,13 +453,13 @@ double AngleClass2P6::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/MOFFF/angle_cosine_buck6d.cpp b/src/MOFFF/angle_cosine_buck6d.cpp index bf7390a6f8..bc6b8eb51a 100644 --- a/src/MOFFF/angle_cosine_buck6d.cpp +++ b/src/MOFFF/angle_cosine_buck6d.cpp @@ -365,13 +365,13 @@ double AngleCosineBuck6d::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/MOLECULE/angle_charmm.cpp b/src/MOLECULE/angle_charmm.cpp index 92f4d65723..78ce011d73 100644 --- a/src/MOLECULE/angle_charmm.cpp +++ b/src/MOLECULE/angle_charmm.cpp @@ -282,19 +282,19 @@ double AngleCharmm::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double delxUB = x[i3][0] - x[i1][0]; double delyUB = x[i3][1] - x[i1][1]; double delzUB = x[i3][2] - x[i1][2]; - domain->minimum_image(delxUB, delyUB, delzUB); + domain->minimum_image(FLERR, delxUB, delyUB, delzUB); double rUB = sqrt(delxUB * delxUB + delyUB * delyUB + delzUB * delzUB); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/MOLECULE/angle_cosine.cpp b/src/MOLECULE/angle_cosine.cpp index 6a6d838bc0..1faabfa5d7 100644 --- a/src/MOLECULE/angle_cosine.cpp +++ b/src/MOLECULE/angle_cosine.cpp @@ -222,13 +222,13 @@ double AngleCosine::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/MOLECULE/angle_cosine_squared.cpp b/src/MOLECULE/angle_cosine_squared.cpp index 2074b822eb..3f48eb712b 100644 --- a/src/MOLECULE/angle_cosine_squared.cpp +++ b/src/MOLECULE/angle_cosine_squared.cpp @@ -245,13 +245,13 @@ double AngleCosineSquared::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; @@ -273,13 +273,13 @@ void AngleCosineSquared::born_matrix(int type, int i1, int i2, int i3, double &d double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/MOLECULE/angle_harmonic.cpp b/src/MOLECULE/angle_harmonic.cpp index e04cecfe0d..db134de357 100644 --- a/src/MOLECULE/angle_harmonic.cpp +++ b/src/MOLECULE/angle_harmonic.cpp @@ -248,13 +248,13 @@ double AngleHarmonic::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; @@ -276,13 +276,13 @@ void AngleHarmonic::born_matrix(int type, int i1, int i2, int i3, double &du, do double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/MOLECULE/angle_table.cpp b/src/MOLECULE/angle_table.cpp index b1984a6918..3923231690 100644 --- a/src/MOLECULE/angle_table.cpp +++ b/src/MOLECULE/angle_table.cpp @@ -330,13 +330,13 @@ double AngleTable::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; diff --git a/src/MOLECULE/dihedral_charmm.cpp b/src/MOLECULE/dihedral_charmm.cpp index de6d59c1d4..ddce2dd66f 100644 --- a/src/MOLECULE/dihedral_charmm.cpp +++ b/src/MOLECULE/dihedral_charmm.cpp @@ -432,3 +432,16 @@ void DihedralCharmm::write_data(FILE *fp) for (int i = 1; i <= atom->ndihedraltypes; i++) fprintf(fp, "%d %g %d %d %g\n", i, k[i], multiplicity[i], shift[i], weight[i]); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralCharmm::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "n") == 0) return (void *) multiplicity; + if (strcmp(str, "d") == 0) return (void *) shift; + return nullptr; +} diff --git a/src/MOLECULE/dihedral_charmm.h b/src/MOLECULE/dihedral_charmm.h index 71e857d5f0..d9af7a56cf 100644 --- a/src/MOLECULE/dihedral_charmm.h +++ b/src/MOLECULE/dihedral_charmm.h @@ -34,6 +34,7 @@ class DihedralCharmm : public Dihedral { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k, *weight, *cos_shift, *sin_shift; diff --git a/src/MOLECULE/dihedral_charmmfsw.cpp b/src/MOLECULE/dihedral_charmmfsw.cpp index a46fb8680c..75e4f688b1 100644 --- a/src/MOLECULE/dihedral_charmmfsw.cpp +++ b/src/MOLECULE/dihedral_charmmfsw.cpp @@ -475,3 +475,16 @@ void DihedralCharmmfsw::write_data(FILE *fp) for (int i = 1; i <= atom->ndihedraltypes; i++) fprintf(fp, "%d %g %d %d %g\n", i, k[i], multiplicity[i], shift[i], weight[i]); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralCharmmfsw::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "n") == 0) return (void *) multiplicity; + if (strcmp(str, "d") == 0) return (void *) shift; + return nullptr; +} diff --git a/src/MOLECULE/dihedral_charmmfsw.h b/src/MOLECULE/dihedral_charmmfsw.h index 3930034356..660dafcd08 100644 --- a/src/MOLECULE/dihedral_charmmfsw.h +++ b/src/MOLECULE/dihedral_charmmfsw.h @@ -34,6 +34,7 @@ class DihedralCharmmfsw : public Dihedral { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: int implicit, weightflag, dihedflag; diff --git a/src/MOLECULE/dihedral_multi_harmonic.cpp b/src/MOLECULE/dihedral_multi_harmonic.cpp index a952d1ad41..ef75c6b5e7 100644 --- a/src/MOLECULE/dihedral_multi_harmonic.cpp +++ b/src/MOLECULE/dihedral_multi_harmonic.cpp @@ -407,3 +407,19 @@ void DihedralMultiHarmonic::born_matrix(int nd, int i1, int i2, int i3, int i4, du = a2[type] + c * (2.0 * a3[type] + c * (3.0 * a4[type] + c * 4.0 * a5[type])); du2 = 2.0 * a3[type] + 6.0 * c * (a4[type] + 2.0 * a5[type] * c); } + + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralMultiHarmonic::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "a1") == 0) return (void *) a1; + if (strcmp(str, "a2") == 0) return (void *) a2; + if (strcmp(str, "a3") == 0) return (void *) a3; + if (strcmp(str, "a4") == 0) return (void *) a4; + if (strcmp(str, "a5") == 0) return (void *) a5; + return nullptr; +} diff --git a/src/MOLECULE/dihedral_multi_harmonic.h b/src/MOLECULE/dihedral_multi_harmonic.h index b1f46bd4bf..1d0ef4a573 100644 --- a/src/MOLECULE/dihedral_multi_harmonic.h +++ b/src/MOLECULE/dihedral_multi_harmonic.h @@ -34,6 +34,7 @@ class DihedralMultiHarmonic : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *a1, *a2, *a3, *a4, *a5; diff --git a/src/MOLECULE/dihedral_opls.cpp b/src/MOLECULE/dihedral_opls.cpp index 1ec2f869a5..2b58f51366 100644 --- a/src/MOLECULE/dihedral_opls.cpp +++ b/src/MOLECULE/dihedral_opls.cpp @@ -431,3 +431,17 @@ void DihedralOPLS::born_matrix(int nd, int i1, int i2, int i3, int i4, double &d 16.0 * k4[type] * si * cos(4.0 * phi) - 4.0 * k4[type] * sin(4.0 * phi)) / (si * si * si); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralOPLS::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k1") == 0) return (void *) k1; + if (strcmp(str, "k2") == 0) return (void *) k2; + if (strcmp(str, "k3") == 0) return (void *) k3; + if (strcmp(str, "k4") == 0) return (void *) k4; + return nullptr; +} diff --git a/src/MOLECULE/dihedral_opls.h b/src/MOLECULE/dihedral_opls.h index 82180cf323..9a483960cc 100644 --- a/src/MOLECULE/dihedral_opls.h +++ b/src/MOLECULE/dihedral_opls.h @@ -34,6 +34,7 @@ class DihedralOPLS : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *k1, *k2, *k3, *k4; diff --git a/src/MOLECULE/dihedral_table.cpp b/src/MOLECULE/dihedral_table.cpp index a731a03b5e..eae7c36eeb 100644 --- a/src/MOLECULE/dihedral_table.cpp +++ b/src/MOLECULE/dihedral_table.cpp @@ -381,9 +381,9 @@ static double Phi(double const *x1, //array holding x,y,z coords atom 1 } //Consider periodic boundary conditions: - domain->minimum_image(vb12[0],vb12[1],vb12[2]); - domain->minimum_image(vb23[0],vb23[1],vb23[2]); - domain->minimum_image(vb34[0],vb34[1],vb34[2]); + domain->minimum_image(FLERR, vb12[0],vb12[1],vb12[2]); + domain->minimum_image(FLERR, vb23[0],vb23[1],vb23[2]); + domain->minimum_image(FLERR, vb34[0],vb34[1],vb34[2]); //--- Compute the normal to the planes formed by atoms 1,2,3 and 2,3,4 --- diff --git a/src/MOLECULE/pair_hbond_dreiding_lj.cpp b/src/MOLECULE/pair_hbond_dreiding_lj.cpp index 2de43b6215..4ec45b16cb 100644 --- a/src/MOLECULE/pair_hbond_dreiding_lj.cpp +++ b/src/MOLECULE/pair_hbond_dreiding_lj.cpp @@ -162,14 +162,14 @@ void PairHbondDreidingLJ::compute(int eflag, int vflag) delr1[0] = x[i][0] - x[k][0]; delr1[1] = x[i][1] - x[k][1]; delr1[2] = x[i][2] - x[k][2]; - domain->minimum_image(delr1); + domain->minimum_image(FLERR, delr1); rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2]; r1 = sqrt(rsq1); delr2[0] = x[j][0] - x[k][0]; delr2[1] = x[j][1] - x[k][1]; delr2[2] = x[j][2] - x[k][2]; - domain->minimum_image(delr2); + domain->minimum_image(FLERR, delr2); rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2]; r2 = sqrt(rsq2); @@ -540,14 +540,14 @@ double PairHbondDreidingLJ::single(int i, int j, int itype, int jtype, delr1[0] = x[i][0] - x[k][0]; delr1[1] = x[i][1] - x[k][1]; delr1[2] = x[i][2] - x[k][2]; - domain->minimum_image(delr1); + domain->minimum_image(FLERR, delr1); rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2]; r1 = sqrt(rsq1); delr2[0] = x[j][0] - x[k][0]; delr2[1] = x[j][1] - x[k][1]; delr2[2] = x[j][2] - x[k][2]; - domain->minimum_image(delr2); + domain->minimum_image(FLERR, delr2); rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2]; r2 = sqrt(rsq2); diff --git a/src/MOLECULE/pair_hbond_dreiding_morse.cpp b/src/MOLECULE/pair_hbond_dreiding_morse.cpp index c5465a076a..f238087f30 100644 --- a/src/MOLECULE/pair_hbond_dreiding_morse.cpp +++ b/src/MOLECULE/pair_hbond_dreiding_morse.cpp @@ -129,14 +129,14 @@ void PairHbondDreidingMorse::compute(int eflag, int vflag) delr1[0] = x[i][0] - x[k][0]; delr1[1] = x[i][1] - x[k][1]; delr1[2] = x[i][2] - x[k][2]; - domain->minimum_image(delr1); + domain->minimum_image(FLERR, delr1); rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2]; r1 = sqrt(rsq1); delr2[0] = x[j][0] - x[k][0]; delr2[1] = x[j][1] - x[k][1]; delr2[2] = x[j][2] - x[k][2]; - domain->minimum_image(delr2); + domain->minimum_image(FLERR, delr2); rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2]; r2 = sqrt(rsq2); @@ -434,14 +434,14 @@ double PairHbondDreidingMorse::single(int i, int j, int itype, int jtype, delr1[0] = x[i][0] - x[k][0]; delr1[1] = x[i][1] - x[k][1]; delr1[2] = x[i][2] - x[k][2]; - domain->minimum_image(delr1); + domain->minimum_image(FLERR, delr1); rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2]; r1 = sqrt(rsq1); delr2[0] = x[j][0] - x[k][0]; delr2[1] = x[j][1] - x[k][1]; delr2[2] = x[j][2] - x[k][2]; - domain->minimum_image(delr2); + domain->minimum_image(FLERR, delr2); rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2]; r2 = sqrt(rsq2); diff --git a/src/OPENMP/dihedral_table_omp.cpp b/src/OPENMP/dihedral_table_omp.cpp index df1ca292c9..5a815a4cc6 100644 --- a/src/OPENMP/dihedral_table_omp.cpp +++ b/src/OPENMP/dihedral_table_omp.cpp @@ -64,9 +64,9 @@ static double Phi(double const *x1, //array holding x,y,z coords atom 1 } //Consider periodic boundary conditions: - domain->minimum_image(vb12[0],vb12[1],vb12[2]); - domain->minimum_image(vb23[0],vb23[1],vb23[2]); - domain->minimum_image(vb34[0],vb34[1],vb34[2]); + domain->minimum_image(FLERR, vb12[0],vb12[1],vb12[2]); + domain->minimum_image(FLERR, vb23[0],vb23[1],vb23[2]); + domain->minimum_image(FLERR, vb34[0],vb34[1],vb34[2]); //--- Compute the normal to the planes formed by atoms 1,2,3 and 2,3,4 --- diff --git a/src/OPENMP/fix_neigh_history_omp.cpp b/src/OPENMP/fix_neigh_history_omp.cpp index 224bfc6bdc..34ba1deb8b 100644 --- a/src/OPENMP/fix_neigh_history_omp.cpp +++ b/src/OPENMP/fix_neigh_history_omp.cpp @@ -137,7 +137,7 @@ void FixNeighHistoryOMP::pre_exchange_onesided() partner[i] = ipg.get(n); valuepartner[i] = dpg.get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -274,7 +274,7 @@ void FixNeighHistoryOMP::pre_exchange_newton() partner[i] = ipg.get(n); valuepartner[i] = dpg.get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -287,7 +287,7 @@ void FixNeighHistoryOMP::pre_exchange_newton() partner[i] = ipg.get(n); valuepartner[i] = dpg.get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) { - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } } @@ -440,7 +440,7 @@ void FixNeighHistoryOMP::pre_exchange_no_newton() partner[i] = ipg.get(n); valuepartner[i] = dpg.get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/OPENMP/npair_bin_ghost_omp.cpp b/src/OPENMP/npair_bin_ghost_omp.cpp index 93dd7b1110..7d5ae62352 100644 --- a/src/OPENMP/npair_bin_ghost_omp.cpp +++ b/src/OPENMP/npair_bin_ghost_omp.cpp @@ -135,7 +135,7 @@ void NPairBinGhostOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -185,7 +185,7 @@ void NPairBinGhostOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_bin_omp.cpp b/src/OPENMP/npair_bin_omp.cpp index 7922d76612..abc2aafed0 100644 --- a/src/OPENMP/npair_bin_omp.cpp +++ b/src/OPENMP/npair_bin_omp.cpp @@ -207,9 +207,9 @@ void NPairBinOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol] ->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) @@ -230,9 +230,9 @@ void NPairBinOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) neighptr[n++] = j; @@ -252,7 +252,7 @@ void NPairBinOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_halffull_omp.cpp b/src/OPENMP/npair_halffull_omp.cpp index bc646accbc..4a18623932 100644 --- a/src/OPENMP/npair_halffull_omp.cpp +++ b/src/OPENMP/npair_halffull_omp.cpp @@ -149,7 +149,7 @@ void NPairHalffullOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = inum_full; diff --git a/src/OPENMP/npair_multi_old_omp.cpp b/src/OPENMP/npair_multi_old_omp.cpp index fa790e177a..9731887260 100644 --- a/src/OPENMP/npair_multi_old_omp.cpp +++ b/src/OPENMP/npair_multi_old_omp.cpp @@ -204,7 +204,7 @@ void NPairMultiOldOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -223,7 +223,7 @@ void NPairMultiOldOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -245,7 +245,7 @@ void NPairMultiOldOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_multi_omp.cpp b/src/OPENMP/npair_multi_omp.cpp index cbc21ebc29..a3f36f60e0 100644 --- a/src/OPENMP/npair_multi_omp.cpp +++ b/src/OPENMP/npair_multi_omp.cpp @@ -232,9 +232,9 @@ void NPairMultiOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) @@ -255,9 +255,9 @@ void NPairMultiOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) @@ -279,7 +279,7 @@ void NPairMultiOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_nsq_ghost_omp.cpp b/src/OPENMP/npair_nsq_ghost_omp.cpp index a270fbb84d..5cb7d49233 100644 --- a/src/OPENMP/npair_nsq_ghost_omp.cpp +++ b/src/OPENMP/npair_nsq_ghost_omp.cpp @@ -131,7 +131,7 @@ void NPairNsqGhostOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -172,7 +172,7 @@ void NPairNsqGhostOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_nsq_omp.cpp b/src/OPENMP/npair_nsq_omp.cpp index 5d6aa518b0..3319c2ef2a 100644 --- a/src/OPENMP/npair_nsq_omp.cpp +++ b/src/OPENMP/npair_nsq_omp.cpp @@ -181,7 +181,7 @@ void NPairNsqOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -200,7 +200,7 @@ void NPairNsqOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -221,7 +221,7 @@ void NPairNsqOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_respa_bin_omp.cpp b/src/OPENMP/npair_respa_bin_omp.cpp index a069affb06..ca15ebf6b0 100644 --- a/src/OPENMP/npair_respa_bin_omp.cpp +++ b/src/OPENMP/npair_respa_bin_omp.cpp @@ -204,7 +204,7 @@ void NPairRespaBinOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -244,20 +244,20 @@ void NPairRespaBinOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); ilist_inner[i] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage.vgot(n_inner); - if (ipage_inner.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_inner.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); if (respamiddle) { ilist_middle[i] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); - if (ipage_middle->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_middle->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } NPAIR_OMP_CLOSE; diff --git a/src/OPENMP/npair_respa_nsq_omp.cpp b/src/OPENMP/npair_respa_nsq_omp.cpp index deba473678..862f70f2b3 100644 --- a/src/OPENMP/npair_respa_nsq_omp.cpp +++ b/src/OPENMP/npair_respa_nsq_omp.cpp @@ -186,7 +186,7 @@ void NPairRespaNsqOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -224,20 +224,20 @@ void NPairRespaNsqOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); ilist_inner[i] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage.vgot(n_inner); - if (ipage_inner.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_inner.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); if (respamiddle) { ilist_middle[i] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); - if (ipage_middle->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_middle->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } NPAIR_OMP_CLOSE; diff --git a/src/OPENMP/npair_trim_omp.cpp b/src/OPENMP/npair_trim_omp.cpp index 0840c1a5f2..a69eb827c6 100644 --- a/src/OPENMP/npair_trim_omp.cpp +++ b/src/OPENMP/npair_trim_omp.cpp @@ -98,7 +98,7 @@ void NPairTrimOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = inum_copy; diff --git a/src/OPENMP/pair_airebo_omp.cpp b/src/OPENMP/pair_airebo_omp.cpp index 0effe79bc8..d1e283d278 100644 --- a/src/OPENMP/pair_airebo_omp.cpp +++ b/src/OPENMP/pair_airebo_omp.cpp @@ -174,7 +174,7 @@ void PairAIREBOOMP::REBO_neigh_thr() REBO_numneigh[i] = n; ipg.vgot(n); if (ipg.status()) - error->one(FLERR,"REBO list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "REBO list overflow, boost neigh_modify one" + utils::errorurl(36)); } } } diff --git a/src/OPENMP/pair_comb_omp.cpp b/src/OPENMP/pair_comb_omp.cpp index 87d467a846..705003379b 100644 --- a/src/OPENMP/pair_comb_omp.cpp +++ b/src/OPENMP/pair_comb_omp.cpp @@ -629,7 +629,7 @@ void PairCombOMP::Short_neigh_thr() sht_num[i] = nj; ipg.vgot(nj); if (ipg.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } } diff --git a/src/OPENMP/pair_hbond_dreiding_lj_omp.cpp b/src/OPENMP/pair_hbond_dreiding_lj_omp.cpp index 60ec8938fe..933b18a732 100644 --- a/src/OPENMP/pair_hbond_dreiding_lj_omp.cpp +++ b/src/OPENMP/pair_hbond_dreiding_lj_omp.cpp @@ -201,14 +201,14 @@ void PairHbondDreidingLJOMP::eval(int iifrom, int iito, ThrData * const thr) delr1[0] = xtmp - x[k].x; delr1[1] = ytmp - x[k].y; delr1[2] = ztmp - x[k].z; - domain->minimum_image(delr1); + domain->minimum_image(FLERR, delr1); rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2]; r1 = sqrt(rsq1); delr2[0] = x[j].x - x[k].x; delr2[1] = x[j].y - x[k].y; delr2[2] = x[j].z - x[k].z; - domain->minimum_image(delr2); + domain->minimum_image(FLERR, delr2); rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2]; r2 = sqrt(rsq2); diff --git a/src/OPENMP/pair_hbond_dreiding_morse_omp.cpp b/src/OPENMP/pair_hbond_dreiding_morse_omp.cpp index 7772ea69fa..1626988f75 100644 --- a/src/OPENMP/pair_hbond_dreiding_morse_omp.cpp +++ b/src/OPENMP/pair_hbond_dreiding_morse_omp.cpp @@ -202,14 +202,14 @@ void PairHbondDreidingMorseOMP::eval(int iifrom, int iito, ThrData * const thr) delr1[0] = xtmp - x[k].x; delr1[1] = ytmp - x[k].y; delr1[2] = ztmp - x[k].z; - domain->minimum_image(delr1); + domain->minimum_image(FLERR, delr1); rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2]; r1 = sqrt(rsq1); delr2[0] = x[j].x - x[k].x; delr2[1] = x[j].y - x[k].y; delr2[2] = x[j].z - x[k].z; - domain->minimum_image(delr2); + domain->minimum_image(FLERR, delr2); rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2]; r2 = sqrt(rsq2); diff --git a/src/OPENMP/pair_lj_pirani_omp.cpp b/src/OPENMP/pair_lj_pirani_omp.cpp new file mode 100644 index 0000000000..3a1fd3ea59 --- /dev/null +++ b/src/OPENMP/pair_lj_pirani_omp.cpp @@ -0,0 +1,194 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + 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 "pair_lj_pirani_omp.h" + +#include "atom.h" +#include "comm.h" +#include "force.h" +#include "math_special.h" +#include "neigh_list.h" +#include "suffix.h" + +#include "omp_compat.h" +using namespace LAMMPS_NS; +using MathSpecial::square; + +/* ---------------------------------------------------------------------- */ + +PairLJPiraniOMP::PairLJPiraniOMP(LAMMPS *lmp) : PairLJPirani(lmp), ThrOMP(lmp, THR_PAIR) +{ + suffix_flag |= Suffix::OMP; + respa_enable = 0; + cut_respa = nullptr; +} + +/* ---------------------------------------------------------------------- */ + +void PairLJPiraniOMP::compute(int eflag, int vflag) +{ + ev_init(eflag, vflag); + + const int nall = atom->nlocal + atom->nghost; + const int nthreads = comm->nthreads; + const int inum = list->inum; + +#if defined(_OPENMP) +#pragma omp parallel LMP_DEFAULT_NONE LMP_SHARED(eflag, vflag) +#endif + { + int ifrom, ito, tid; + + loop_setup_thr(ifrom, ito, tid, inum, nthreads); + ThrData *thr = fix->get_thr(tid); + thr->timer(Timer::START); + ev_setup_thr(eflag, vflag, nall, eatom, vatom, nullptr, thr); + + if (evflag) { + if (eflag) { + if (force->newton_pair) + eval<1, 1, 1>(ifrom, ito, thr); + else + eval<1, 1, 0>(ifrom, ito, thr); + } else { + if (force->newton_pair) + eval<1, 0, 1>(ifrom, ito, thr); + else + eval<1, 0, 0>(ifrom, ito, thr); + } + } else { + if (force->newton_pair) + eval<0, 0, 1>(ifrom, ito, thr); + else + eval<0, 0, 0>(ifrom, ito, thr); + } + thr->timer(Timer::PAIR); + reduce_thr(this, eflag, vflag, thr); + } // end of omp parallel region +} + +template +void PairLJPiraniOMP::eval(int iifrom, int iito, ThrData *const thr) +{ + const auto *_noalias const x = (dbl3_t *) atom->x[0]; + auto *_noalias const f = (dbl3_t *) thr->get_f()[0]; + const int *_noalias const type = atom->type; + const double *_noalias const special_lj = force->special_lj; + const int *_noalias const ilist = list->ilist; + const int *_noalias const numneigh = list->numneigh; + const int *const *const firstneigh = list->firstneigh; + + double xtmp, ytmp, ztmp, delx, dely, delz, fxtmp, fytmp, fztmp; + double rsq, forceilj, factor_lj, evdwl, fpair; + + const int nlocal = atom->nlocal; + int j, jj, jnum, jtype; + + evdwl = 0.0; + + // loop over neighbors of my atoms + + for (int ii = iifrom; ii < iito; ++ii) { + const int i = ilist[ii]; + const int itype = type[i]; + const int *_noalias const jlist = firstneigh[i]; + const double *_noalias const cutsqi = cutsq[itype]; + const double *_noalias const offseti = offset[itype]; + const double *_noalias const alphai = alpha[itype]; + const double *_noalias const betai = beta[itype]; + const double *_noalias const gammai = gamma[itype]; + const double *_noalias const rmi = rm[itype]; + const double *_noalias const epsiloni = epsilon[itype]; + + xtmp = x[i].x; + ytmp = x[i].y; + ztmp = x[i].z; + jnum = numneigh[i]; + fxtmp = fytmp = fztmp = 0.0; + + for (jj = 0; jj < jnum; jj++) { + j = jlist[jj]; + factor_lj = special_lj[sbmask(j)]; + j &= NEIGHMASK; + + delx = xtmp - x[j].x; + dely = ytmp - x[j].y; + delz = ztmp - x[j].z; + rsq = delx * delx + dely * dely + delz * delz; + jtype = type[j]; + + if (rsq < cutsqi[jtype]) { + const double r = sqrt(rsq); + + const double rx = r / rmi[jtype]; + const double n_x = alphai[jtype] * rx * rx + betai[jtype]; + const double pow_rx_n_x = pow(1.0 / rx, n_x); + const double pow_rx_gamma = pow(1.0 / rx, gammai[jtype]); + + double filj1 = -2.0 * alphai[jtype] * gammai[jtype] * rx * pow_rx_n_x / + (square(n_x - gammai[jtype]) * rmi[jtype]); + + double filj2 = 2.0 * alphai[jtype] * rx * n_x * pow_rx_gamma / + (square(n_x - gammai[jtype]) * rmi[jtype]); + + double filj3 = + -2.0 * alphai[jtype] * rx * pow_rx_gamma / (rmi[jtype] * (n_x - gammai[jtype])); + + double filj4 = 2.0 * alphai[jtype] * gammai[jtype] * (rx / rmi[jtype]) * log(1 / rx) * + pow_rx_n_x / (n_x - gammai[jtype]); + + double filj5 = -1.0 * gammai[jtype] * n_x * pow_rx_n_x / (r * (n_x - gammai[jtype])); + + double filj6 = 1.0 * gammai[jtype] * n_x * pow_rx_gamma / (r * (n_x - gammai[jtype])); + + // F = -dV/dr + forceilj = -epsiloni[jtype] * (filj1 + filj2 + filj3 + filj4 + filj5 + filj6); + fpair = factor_lj * forceilj / r; // F_x = -x/r * dV/dr (chain rule) + + fxtmp += delx * fpair; + fytmp += dely * fpair; + fztmp += delz * fpair; + if (NEWTON_PAIR || j < nlocal) { + f[j].x -= delx * fpair; + f[j].y -= dely * fpair; + f[j].z -= delz * fpair; + } + + if (EFLAG) { + double ilj1 = epsiloni[jtype] * gammai[jtype] * pow(1 / rx, n_x) / (n_x - gammai[jtype]); + double ilj2 = -epsiloni[jtype] * n_x * pow(1 / rx, gammai[jtype]) / (n_x - gammai[jtype]); + + evdwl = ilj1 + ilj2 - offseti[jtype]; + evdwl *= factor_lj; + } + + if (EVFLAG) + ev_tally_thr(this, i, j, nlocal, NEWTON_PAIR, evdwl, 0.0, fpair, delx, dely, delz, thr); + } + } + f[i].x += fxtmp; + f[i].y += fytmp; + f[i].z += fztmp; + } +} + +/* ---------------------------------------------------------------------- */ + +double PairLJPiraniOMP::memory_usage() +{ + double bytes = memory_usage_thr(); + bytes += PairLJPirani::memory_usage(); + + return bytes; +} diff --git a/src/OPENMP/pair_lj_pirani_omp.h b/src/OPENMP/pair_lj_pirani_omp.h new file mode 100644 index 0000000000..db19d0fbf6 --- /dev/null +++ b/src/OPENMP/pair_lj_pirani_omp.h @@ -0,0 +1,48 @@ +/* -*- 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) +------------------------------------------------------------------------- */ + +#ifdef PAIR_CLASS +// clang-format off +PairStyle(lj/pirani/omp,PairLJPiraniOMP); +// clang-format on +#else + +#ifndef LMP_PAIR_LJ_PIRANI_OMP_H +#define LMP_PAIR_LJ_PIRANI_OMP_H + +#include "pair_lj_pirani.h" +#include "thr_omp.h" + +namespace LAMMPS_NS { + +class PairLJPiraniOMP : public PairLJPirani, public ThrOMP { + + public: + PairLJPiraniOMP(class LAMMPS *); + + void compute(int, int) override; + double memory_usage() override; + + private: + template + void eval(int ifrom, int ito, ThrData *const thr); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/OPENMP/pair_peri_lps_omp.cpp b/src/OPENMP/pair_peri_lps_omp.cpp index c34f3ac236..2a4289fdf2 100644 --- a/src/OPENMP/pair_peri_lps_omp.cpp +++ b/src/OPENMP/pair_peri_lps_omp.cpp @@ -161,7 +161,7 @@ void PairPeriLPSOMP::eval(int iifrom, int iito, ThrData * const thr) delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0; jtype = type[j]; @@ -285,12 +285,12 @@ void PairPeriLPSOMP::eval(int iifrom, int iito, ThrData * const thr) delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - if (periodic) domain->minimum_image(delx,dely,delz); + if (periodic) domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); jtype = type[j]; delta = cut[itype][jtype]; r = sqrt(rsq); diff --git a/src/OPENMP/pair_peri_pmb_omp.cpp b/src/OPENMP/pair_peri_pmb_omp.cpp index 0b903272fa..eb5911b294 100644 --- a/src/OPENMP/pair_peri_pmb_omp.cpp +++ b/src/OPENMP/pair_peri_pmb_omp.cpp @@ -156,7 +156,7 @@ void PairPeriPMBOMP::eval(int iifrom, int iito, ThrData * const thr) delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0; jtype = type[j]; @@ -244,7 +244,7 @@ void PairPeriPMBOMP::eval(int iifrom, int iito, ThrData * const thr) delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - if (periodic) domain->minimum_image(delx,dely,delz); + if (periodic) domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; jtype = type[j]; delta = cut[itype][jtype]; diff --git a/src/OPENMP/pair_rebomos_omp.cpp b/src/OPENMP/pair_rebomos_omp.cpp index 06b979d41a..00dadde13e 100644 --- a/src/OPENMP/pair_rebomos_omp.cpp +++ b/src/OPENMP/pair_rebomos_omp.cpp @@ -186,7 +186,7 @@ void PairREBOMoSOMP::REBO_neigh_thr() REBO_numneigh[i] = n; ipg.vgot(n); if (ipg.status()) - error->one(FLERR,"REBO list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "REBO list overflow, boost neigh_modify one" + utils::errorurl(36)); } } } diff --git a/src/PERI/fix_peri_neigh.cpp b/src/PERI/fix_peri_neigh.cpp index 6adfc96f3f..1eba6006b8 100644 --- a/src/PERI/fix_peri_neigh.cpp +++ b/src/PERI/fix_peri_neigh.cpp @@ -279,7 +279,7 @@ void FixPeriNeigh::setup(int /*vflag*/) } } - // sanity check: does any atom appear twice in any neigborlist? + // sanity check: does any atom appear twice in any neighborlist? // should only be possible if using pbc and domain < 2*delta if (domain->xperiodic || domain->yperiodic || domain->zperiodic) { diff --git a/src/PERI/pair_peri.cpp b/src/PERI/pair_peri.cpp index 6606f36c6f..da761952fe 100644 --- a/src/PERI/pair_peri.cpp +++ b/src/PERI/pair_peri.cpp @@ -189,12 +189,12 @@ void PairPeri::compute_dilatation(int ifrom, int ito) delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - if (periodic) domain->minimum_image(delx, dely, delz); + if (periodic) domain->minimum_image(FLERR, delx, dely, delz); rsq = delx * delx + dely * dely + delz * delz; delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0, dely0, delz0); + if (periodic) domain->minimum_image(FLERR, delx0, dely0, delz0); r = sqrt(rsq); dr = r - r0[i][jj]; diff --git a/src/PERI/pair_peri_eps.cpp b/src/PERI/pair_peri_eps.cpp index c0732d48e4..11d9ee646b 100644 --- a/src/PERI/pair_peri_eps.cpp +++ b/src/PERI/pair_peri_eps.cpp @@ -124,7 +124,7 @@ void PairPeriEPS::compute(int eflag, int vflag) delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0; jtype = type[j]; @@ -262,12 +262,12 @@ void PairPeriEPS::compute(int eflag, int vflag) delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - if (periodic) domain->minimum_image(delx,dely,delz); + if (periodic) domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); jtype = type[j]; delta = cut[itype][jtype]; r = sqrt(rsq); @@ -514,12 +514,12 @@ double PairPeriEPS::compute_DeviatoricForceStateNorm(int i) delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - if (periodic) domain->minimum_image(delx,dely,delz); + if (periodic) domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); r = sqrt(rsq); dr = r - r0[i][jj]; if (fabs(dr) < NEAR_ZERO) dr = 0.0; diff --git a/src/PERI/pair_peri_lps.cpp b/src/PERI/pair_peri_lps.cpp index b7b7e6577a..bd0eb9651f 100644 --- a/src/PERI/pair_peri_lps.cpp +++ b/src/PERI/pair_peri_lps.cpp @@ -116,7 +116,7 @@ void PairPeriLPS::compute(int eflag, int vflag) delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0; jtype = type[j]; @@ -225,12 +225,12 @@ void PairPeriLPS::compute(int eflag, int vflag) delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - if (periodic) domain->minimum_image(delx,dely,delz); + if (periodic) domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); jtype = type[j]; delta = cut[itype][jtype]; r = sqrt(rsq); diff --git a/src/PERI/pair_peri_pmb.cpp b/src/PERI/pair_peri_pmb.cpp index 0bacb3a2f0..c17336b8cf 100644 --- a/src/PERI/pair_peri_pmb.cpp +++ b/src/PERI/pair_peri_pmb.cpp @@ -110,7 +110,7 @@ void PairPeriPMB::compute(int eflag, int vflag) delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0; jtype = type[j]; @@ -189,7 +189,7 @@ void PairPeriPMB::compute(int eflag, int vflag) delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - if (periodic) domain->minimum_image(delx,dely,delz); + if (periodic) domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; jtype = type[j]; delta = cut[itype][jtype]; @@ -361,7 +361,7 @@ double PairPeriPMB::single(int i, int j, int itype, int jtype, double rsq, dely0 = x0[i][1] - x0[j][1]; delz0 = x0[i][2] - x0[j][2]; int periodic = domain->xperiodic || domain->yperiodic || domain->zperiodic; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0; d_ij = MIN(0.9*sqrt(rsq0),1.35*lc); diff --git a/src/PERI/pair_peri_ves.cpp b/src/PERI/pair_peri_ves.cpp index d814ce6f05..be9967436e 100644 --- a/src/PERI/pair_peri_ves.cpp +++ b/src/PERI/pair_peri_ves.cpp @@ -121,7 +121,7 @@ void PairPeriVES::compute(int eflag, int vflag) delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0; jtype = type[j]; @@ -233,12 +233,12 @@ void PairPeriVES::compute(int eflag, int vflag) delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - if (periodic) domain->minimum_image(delx,dely,delz); + if (periodic) domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; delx0 = xtmp0 - x0[j][0]; dely0 = ytmp0 - x0[j][1]; delz0 = ztmp0 - x0[j][2]; - if (periodic) domain->minimum_image(delx0,dely0,delz0); + if (periodic) domain->minimum_image(FLERR, delx0,dely0,delz0); jtype = type[j]; delta = cut[itype][jtype]; r = sqrt(rsq); diff --git a/src/PHONON/fix_phonon.cpp b/src/PHONON/fix_phonon.cpp index 37f84b6f12..4669253401 100644 --- a/src/PHONON/fix_phonon.cpp +++ b/src/PHONON/fix_phonon.cpp @@ -400,7 +400,7 @@ void FixPhonon::end_of_step() ndim = sysdim; for (i = 1; i < nucell; ++i) { for (idim = 0; idim < sysdim; ++idim) dist2orig[idim] = Rnow[idx][ndim++] - Rnow[idx][idim]; - domain->minimum_image_big(dist2orig); + domain->minimum_image_big(FLERR, dist2orig); for (idim = 0; idim < sysdim; ++idim) basis[i][idim] += dist2orig[idim]; } } diff --git a/src/PHONON/third_order.cpp b/src/PHONON/third_order.cpp index e1d9161ef1..0facaecc9b 100644 --- a/src/PHONON/third_order.cpp +++ b/src/PHONON/third_order.cpp @@ -162,7 +162,7 @@ void ThirdOrder::command(int narg, char **arg) conversion = 1; folded = 0; - // set Neigborlist attributes to NULL + // set Neighborlist attributes to NULL ijnum = nullptr; neighbortags = nullptr; diff --git a/src/REACTION/fix_bond_react.cpp b/src/REACTION/fix_bond_react.cpp index 0a6ed3e34a..6ba6954541 100644 --- a/src/REACTION/fix_bond_react.cpp +++ b/src/REACTION/fix_bond_react.cpp @@ -1190,7 +1190,7 @@ void FixBondReact::far_partner() delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; - domain->minimum_image(delx,dely,delz); // ghost location fix + domain->minimum_image(FLERR, delx,dely,delz); // ghost location fix rsq = delx*delx + dely*dely + delz*delz; if (var_flag[RMIN][rxnID]) { @@ -1260,7 +1260,7 @@ void FixBondReact::close_partner() delx = x[i1][0] - x[i2][0]; dely = x[i1][1] - x[i2][1]; delz = x[i1][2] - x[i2][2]; - domain->minimum_image(delx,dely,delz); // ghost location fix + domain->minimum_image(FLERR, delx,dely,delz); // ghost location fix rsq = delx*delx + dely*dely + delz*delz; if (var_flag[RMIN][rxnID]) { @@ -1475,15 +1475,14 @@ void FixBondReact::superimpose_algorithm() int rxnflag = 0; int *delta_rxn; - memory->create(delta_rxn,nreacts,"bond/react:delta_rxn"); + memory->create(delta_rxn, nreacts, "bond/react:delta_rxn"); if (comm->me == 0) for (int i = 0; i < nreacts; i++) { delta_rxn[i] = reaction_count[i] + ghostly_rxn_count[i]; - reaction_count_total[i] += delta_rxn[i]; rxnflag += delta_rxn[i]; } - MPI_Bcast(&reaction_count_total[0], nreacts, MPI_INT, 0, world); + MPI_Bcast(&delta_rxn[0], nreacts, MPI_INT, 0, world); MPI_Bcast(&rxnflag, 1, MPI_INT, 0, world); if (!rxnflag) return; @@ -1495,12 +1494,12 @@ void FixBondReact::superimpose_algorithm() // check if we overstepped our reaction limit, via either max_rxn or rate_limit for (int i = 0; i < nreacts; i++) { int overstep = 0; - int max_rxn_overstep = reaction_count_total[i] - max_rxn[i]; + int max_rxn_overstep = reaction_count_total[i] + delta_rxn[i] - max_rxn[i]; overstep = MAX(overstep,max_rxn_overstep); if (rate_limit[0][i] == 1) { int myrxn_count = store_rxn_count[rate_limit[2][i]-1][i]; if (myrxn_count != -1) { - int nrxn_delta = reaction_count_total[i] - myrxn_count; + int nrxn_delta = reaction_count_total[i] + delta_rxn[i] - myrxn_count; int my_nrate; if (var_flag[NRATE][i] == 1) { my_nrate = input->variable->compute_equal(var_id[NRATE][i]); @@ -1540,7 +1539,6 @@ void FixBondReact::superimpose_algorithm() else all_localkeep[rxn_by_proc[j]]++; } memory->destroy(rxn_by_proc); - reaction_count_total[i] -= overstep; } MPI_Scatter(&all_localkeep[0],1,MPI_INT,&nlocalkeep[i],1,MPI_INT,0,world); MPI_Bcast(&nghostlykeep[i],1,MPI_INT,0,world); @@ -1548,7 +1546,6 @@ void FixBondReact::superimpose_algorithm() memory->destroy(all_localkeep); } } - MPI_Bcast(&reaction_count_total[0], nreacts, MPI_INT, 0, world); memory->destroy(delta_rxn); // this updates topology next step @@ -1975,7 +1972,7 @@ int FixBondReact::check_constraints() delx = x1[0] - x2[0]; dely = x1[1] - x2[1]; delz = x1[2] - x2[2]; - domain->minimum_image(delx,dely,delz); // ghost location fix + domain->minimum_image(FLERR, delx,dely,delz); // ghost location fix rsq = delx*delx + dely*dely + delz*delz; if (rsq < constraints[i][rxnID].par[0] || rsq > constraints[i][rxnID].par[1]) satisfied[i] = 0; } else if (constraints[i][rxnID].type == ANGLE) { @@ -1987,7 +1984,7 @@ int FixBondReact::check_constraints() delx1 = x1[0] - x2[0]; dely1 = x1[1] - x2[1]; delz1 = x1[2] - x2[2]; - domain->minimum_image(delx1,dely1,delz1); // ghost location fix + domain->minimum_image(FLERR, delx1,dely1,delz1); // ghost location fix rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1; r1 = sqrt(rsq1); @@ -1995,7 +1992,7 @@ int FixBondReact::check_constraints() delx2 = x3[0] - x2[0]; dely2 = x3[1] - x2[1]; delz2 = x3[2] - x2[2]; - domain->minimum_image(delx2,dely2,delz2); // ghost location fix + domain->minimum_image(FLERR, delx2,dely2,delz2); // ghost location fix rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2; r2 = sqrt(rsq2); @@ -2015,22 +2012,22 @@ int FixBondReact::check_constraints() vb1x = x1[0] - x2[0]; vb1y = x1[1] - x2[1]; vb1z = x1[2] - x2[2]; - domain->minimum_image(vb1x,vb1y,vb1z); + domain->minimum_image(FLERR, vb1x,vb1y,vb1z); vb2x = x3[0] - x2[0]; vb2y = x3[1] - x2[1]; vb2z = x3[2] - x2[2]; - domain->minimum_image(vb2x,vb2y,vb2z); + domain->minimum_image(FLERR, vb2x,vb2y,vb2z); vb2xm = -vb2x; vb2ym = -vb2y; vb2zm = -vb2z; - domain->minimum_image(vb2xm,vb2ym,vb2zm); + domain->minimum_image(FLERR, vb2xm,vb2ym,vb2zm); vb3x = x4[0] - x3[0]; vb3y = x4[1] - x3[1]; vb3z = x4[2] - x3[2]; - domain->minimum_image(vb3x,vb3y,vb3z); + domain->minimum_image(FLERR, vb3x,vb3y,vb3z); ax = vb1y*vb2zm - vb1z*vb2ym; ay = vb1z*vb2xm - vb1x*vb2zm; @@ -3103,18 +3100,16 @@ void FixBondReact::update_everything() if (create_atoms_flag[rxnID] == 1) { onemol = atom->molecules[unreacted_mol[rxnID]]; twomol = atom->molecules[reacted_mol[rxnID]]; - if (insert_atoms_setup(update_mega_glove,update_num_mega)) { - inserted_atoms_flag = 1; - } else { // create aborted - reaction_count_total[rxnID]--; - continue; - } + if (insert_atoms_setup(update_mega_glove,update_num_mega)) inserted_atoms_flag = 1; + else continue; } noccur[rxnID]++; if (rescale_charges_flag[rxnID]) sim_total_charges[update_num_mega] = local_mega_glove[1][i]; update_num_mega++; } + MPI_Allreduce(MPI_IN_PLACE, &noccur[0], nreacts, MPI_INT, MPI_SUM, world); + reaction_count_total[rxnID] += noccur[rxnID]; } else if (pass == 1) { for (int i = 0; i < global_megasize; i++) { rxnID = (int) global_mega_glove[0][i]; @@ -3129,17 +3124,15 @@ void FixBondReact::update_everything() // we can insert atoms here, now that reactions are finalized // can't do it any earlier, due to skipped reactions (max_rxn) // for MPI build, reactions that create atoms are always treated as 'global' + if (create_atoms_flag[rxnID] == 1) { onemol = atom->molecules[unreacted_mol[rxnID]]; twomol = atom->molecules[reacted_mol[rxnID]]; - if (insert_atoms_setup(update_mega_glove,update_num_mega)) { - inserted_atoms_flag = 1; - } else { // create aborted - reaction_count_total[rxnID]--; - continue; - } + if (insert_atoms_setup(update_mega_glove,update_num_mega)) inserted_atoms_flag = 1; + else continue; } noccur[rxnID]++; + reaction_count_total[rxnID]++; if (rescale_charges_flag[rxnID]) sim_total_charges[update_num_mega] = global_mega_glove[1][i]; update_num_mega++; @@ -3915,7 +3908,7 @@ int FixBondReact::insert_atoms_setup(tagint **my_update_mega_glove, int iupdate) delx = coords[m][0] - x[i][0]; dely = coords[m][1] - x[i][1]; delz = coords[m][2] - x[i][2]; - domain->minimum_image(delx,dely,delz); + domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; if (rsq < overlapsq[rxnID]) { abortflag = 1; @@ -3933,7 +3926,7 @@ int FixBondReact::insert_atoms_setup(tagint **my_update_mega_glove, int iupdate) delx = coords[m][0] - myaddatom.x[0]; dely = coords[m][1] - myaddatom.x[1]; delz = coords[m][2] - myaddatom.x[2]; - domain->minimum_image(delx,dely,delz); + domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; if (rsq < overlapsq[rxnID]) { abortflag = 1; diff --git a/src/REAXFF/fix_acks2_reaxff.cpp b/src/REAXFF/fix_acks2_reaxff.cpp index 4fd86605fa..2692d7eeca 100644 --- a/src/REAXFF/fix_acks2_reaxff.cpp +++ b/src/REAXFF/fix_acks2_reaxff.cpp @@ -80,6 +80,11 @@ FixACKS2ReaxFF::FixACKS2ReaxFF(LAMMPS *lmp, int narg, char **arg) : last_rows_rank = 0; last_rows_flag = (comm->me == last_rows_rank); + + if (lmp->citeme) lmp->citeme->add(cite_fix_acks2_reax); + + if (dual_enabled) + error->all(FLERR, Error::NOLASTLINE, "Dual keyword only supported with fix qeq/reax/omp"); } /* ---------------------------------------------------------------------- */ @@ -104,8 +109,6 @@ FixACKS2ReaxFF::~FixACKS2ReaxFF() void FixACKS2ReaxFF::post_constructor() { - if (lmp->citeme) lmp->citeme->add(cite_fix_acks2_reax); - memory->create(s_hist_last,2,nprev,"acks2/reax:s_hist_last"); for (int i = 0; i < 2; i++) for (int j = 0; j < nprev; ++j) @@ -117,8 +120,6 @@ void FixACKS2ReaxFF::post_constructor() s_hist[i][j] = s_hist_X[i][j] = 0.0; pertype_parameters(pertype_option); - if (dual_enabled) - error->all(FLERR,"Dual keyword only supported with fix qeq/reax/omp"); } /* ---------------------------------------------------------------------- */ @@ -128,7 +129,7 @@ void FixACKS2ReaxFF::pertype_parameters(char *arg) if (utils::strmatch(arg,"^reaxff")) { reaxflag = 1; Pair *pair = force->pair_match("^reaxff",0); - if (!pair) error->all(FLERR,"No reaxff pair style for fix acks2/reaxff"); + if (!pair) error->all(FLERR, Error::NOLASTLINE, "No reaxff pair style for fix acks2/reaxff"); int tmp; chi = (double *) pair->extract("chi",tmp); @@ -139,8 +140,8 @@ void FixACKS2ReaxFF::pertype_parameters(char *arg) if (chi == nullptr || eta == nullptr || gamma == nullptr || bcut_acks2 == nullptr || bond_softness_ptr == nullptr) - error->all(FLERR, - "Fix acks2/reaxff could not extract params from pair reaxff"); + error->all(FLERR, Error::NOLASTLINE, "Fix {} could not extract params from pair reaxff", + style); bond_softness = *bond_softness_ptr; return; } diff --git a/src/REAXFF/reaxff_tool_box.cpp b/src/REAXFF/reaxff_tool_box.cpp index aa6f831e95..e39a6c6654 100644 --- a/src/REAXFF/reaxff_tool_box.cpp +++ b/src/REAXFF/reaxff_tool_box.cpp @@ -101,6 +101,6 @@ void sfree(void *ptr) if (ptr == nullptr) return; free(ptr); - ptr = nullptr; + ptr = nullptr; // NOTE: this has no effect } } // namespace ReaxFF diff --git a/src/REPLICA/bosonic_exchange.cpp b/src/REPLICA/bosonic_exchange.cpp index 6ffbeb8eb7..261ba9d185 100644 --- a/src/REPLICA/bosonic_exchange.cpp +++ b/src/REPLICA/bosonic_exchange.cpp @@ -87,7 +87,7 @@ void BosonicExchange::diff_two_beads(const double *x1, int l1, const double *x2, double delx2 = x2[3 * l2 + 0] - x1[3 * l1 + 0]; double dely2 = x2[3 * l2 + 1] - x1[3 * l1 + 1]; double delz2 = x2[3 * l2 + 2] - x1[3 * l1 + 2]; - if (apply_minimum_image) { domain->minimum_image(delx2, dely2, delz2); } + if (apply_minimum_image) { domain->minimum_image(FLERR, delx2, dely2, delz2); } diff[0] = delx2; diff[1] = dely2; diff --git a/src/REPLICA/fix_neb.cpp b/src/REPLICA/fix_neb.cpp index 409c108628..181100b11b 100644 --- a/src/REPLICA/fix_neb.cpp +++ b/src/REPLICA/fix_neb.cpp @@ -348,7 +348,7 @@ void FixNEB::min_post_force(int /*vflag*/) delxp = x[i][0] - xprev[i][0]; delyp = x[i][1] - xprev[i][1]; delzp = x[i][2] - xprev[i][2]; - domain->minimum_image(delxp, delyp, delzp); + domain->minimum_image(FLERR, delxp, delyp, delzp); plen += delxp * delxp + delyp * delyp + delzp * delzp; dottangrad += delxp * f[i][0] + delyp * f[i][1] + delzp * f[i][2]; gradlen += f[i][0] * f[i][0] + f[i][1] * f[i][1] + f[i][2] * f[i][2]; @@ -368,7 +368,7 @@ void FixNEB::min_post_force(int /*vflag*/) delxn = xnext[i][0] - x[i][0]; delyn = xnext[i][1] - x[i][1]; delzn = xnext[i][2] - x[i][2]; - domain->minimum_image(delxn, delyn, delzn); + domain->minimum_image(FLERR, delxn, delyn, delzn); nlen += delxn * delxn + delyn * delyn + delzn * delzn; gradnextlen += fnext[i][0] * fnext[i][0] + fnext[i][1] * fnext[i][1] + fnext[i][2] * fnext[i][2]; @@ -396,13 +396,13 @@ void FixNEB::min_post_force(int /*vflag*/) delxp = x[i][0] - xprev[i][0]; delyp = x[i][1] - xprev[i][1]; delzp = x[i][2] - xprev[i][2]; - domain->minimum_image(delxp, delyp, delzp); + domain->minimum_image(FLERR, delxp, delyp, delzp); plen += delxp * delxp + delyp * delyp + delzp * delzp; delxn = xnext[i][0] - x[i][0]; delyn = xnext[i][1] - x[i][1]; delzn = xnext[i][2] - x[i][2]; - domain->minimum_image(delxn, delyn, delzn); + domain->minimum_image(FLERR, delxn, delyn, delzn); if (vnext > veng && veng > vprev) { tangent[i][0] = delxn; diff --git a/src/REPLICA/fix_pimd_nvt.cpp b/src/REPLICA/fix_pimd_nvt.cpp index d11bc34337..53a4b779ae 100644 --- a/src/REPLICA/fix_pimd_nvt.cpp +++ b/src/REPLICA/fix_pimd_nvt.cpp @@ -579,13 +579,13 @@ void FixPIMDNVT::spring_force() double dely1 = xlast[1] - x[i][1]; double delz1 = xlast[2] - x[i][2]; xlast += 3; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); double delx2 = xnext[0] - x[i][0]; double dely2 = xnext[1] - x[i][1]; double delz2 = xnext[2] - x[i][2]; xnext += 3; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); double ff = fbond * _mass[type[i]]; diff --git a/src/REPLICA/neb.cpp b/src/REPLICA/neb.cpp index a65fc9a58f..0226755778 100644 --- a/src/REPLICA/neb.cpp +++ b/src/REPLICA/neb.cpp @@ -83,7 +83,7 @@ NEB::NEB(LAMMPS *lmp, double etol_in, double ftol_in, int n1steps_in, int n2step delx = buf_final[ii] - buf_init[ii]; dely = buf_final[ii + 1] - buf_init[ii + 1]; delz = buf_final[ii + 2] - buf_init[ii + 2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); x[i][0] = buf_init[ii] + fraction * delx; x[i][1] = buf_init[ii + 1] + fraction * dely; x[i][2] = buf_init[ii + 2] + fraction * delz; @@ -529,7 +529,7 @@ void NEB::readfile(char *file, int flag) dely = values.next_double() - x[m][1]; delz = values.next_double() - x[m][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); if (flag == 0) { x[m][0] += fraction * delx; diff --git a/src/RHEO/compute_rheo_kernel.cpp b/src/RHEO/compute_rheo_kernel.cpp index 61aad6a9b8..e44e356133 100644 --- a/src/RHEO/compute_rheo_kernel.cpp +++ b/src/RHEO/compute_rheo_kernel.cpp @@ -227,7 +227,7 @@ double ComputeRHEOKernel::calc_dw(int i, int j, double delx, double dely, double int corrections_i = check_corrections(i); int corrections_j = check_corrections(j); - wp = calc_dw_scalar_quintic(delx, dely, delz, r); + wp = calc_dw_scalar_quintic(r); // Overwrite if there are corrections double dxij[3] = {delx, dely, delz}; @@ -279,7 +279,7 @@ double ComputeRHEOKernel::calc_w_quintic(double r) /* ---------------------------------------------------------------------- */ -double ComputeRHEOKernel::calc_dw_scalar_quintic(double delx, double dely, double delz, double r) +double ComputeRHEOKernel::calc_dw_scalar_quintic(double r) { double wp, tmp1, tmp2, tmp3, tmp1sq, tmp2sq, tmp3sq, s; @@ -312,7 +312,7 @@ double ComputeRHEOKernel::calc_dw_scalar_quintic(double delx, double dely, doubl double ComputeRHEOKernel::calc_dw_quintic(double delx, double dely, double delz, double r, double *dW1, double *dW2) { - double wp = calc_dw_scalar_quintic(delx, dely, delz, r); + double wp = calc_dw_scalar_quintic(r); double wprinv = wp / r; dW1[0] = delx * wprinv; diff --git a/src/RHEO/compute_rheo_kernel.h b/src/RHEO/compute_rheo_kernel.h index 037e9e3683..10f7baf425 100644 --- a/src/RHEO/compute_rheo_kernel.h +++ b/src/RHEO/compute_rheo_kernel.h @@ -40,7 +40,7 @@ class ComputeRHEOKernel : public Compute { double calc_w(int, int, double, double, double, double); double calc_dw(int, int, double, double, double, double); double calc_w_quintic(double); - double calc_dw_scalar_quintic(double, double, double, double); + double calc_dw_scalar_quintic(double); double calc_dw_quintic(double, double, double, double, double *, double *); double calc_w_wendlandc4(double); double calc_dw_wendlandc4(double, double, double, double, double *, double *); diff --git a/src/RHEO/fix_rheo_pressure.cpp b/src/RHEO/fix_rheo_pressure.cpp index 6088c44348..16a96ef430 100644 --- a/src/RHEO/fix_rheo_pressure.cpp +++ b/src/RHEO/fix_rheo_pressure.cpp @@ -289,7 +289,7 @@ double FixRHEOPressure::calc_rho(double p, int i) /* ---------------------------------------------------------------------- */ -double FixRHEOPressure::calc_csq(double p, int i) +double FixRHEOPressure::calc_csq(double /*p*/, int i) { int type = atom->type[i]; double csq2 = csq[type]; diff --git a/src/RIGID/fix_ehex.cpp b/src/RIGID/fix_ehex.cpp index 313bd3b59a..ceca4e8a47 100644 --- a/src/RIGID/fix_ehex.cpp +++ b/src/RIGID/fix_ehex.cpp @@ -434,7 +434,7 @@ bool FixEHEX::check_cluster(tagint *shake_atom, int n, Region *region) // take into account pbc - domain->minimum_image_big(xtemp); + domain->minimum_image_big(FLERR, xtemp); for (int k = 0; k < 3; k++) xcom[k] += mi * (x[lid[0]][k] + xtemp[k]); } diff --git a/src/RIGID/fix_rattle.cpp b/src/RIGID/fix_rattle.cpp index 5a85902609..f7673194a9 100644 --- a/src/RIGID/fix_rattle.cpp +++ b/src/RIGID/fix_rattle.cpp @@ -248,9 +248,9 @@ void FixRattle::vrattle3angle(int m) // take into account periodicity - domain->minimum_image(r01); - domain->minimum_image(r02); - domain->minimum_image(r12); + domain->minimum_image(FLERR, r01); + domain->minimum_image(FLERR, r02); + domain->minimum_image(FLERR, r12); // v01,v02,v12 = velocity differences @@ -323,7 +323,7 @@ void FixRattle::vrattle2(int m) // r01 = distance vec between atoms, with PBC MathExtra::sub3(x[i1],x[i0],r01); - domain->minimum_image(r01); + domain->minimum_image(FLERR, r01); // v01 = distance vectors for velocities @@ -375,8 +375,8 @@ void FixRattle::vrattle3(int m) MathExtra::sub3(x[i1],x[i0],r01); MathExtra::sub3(x[i2],x[i0],r02); - domain->minimum_image(r01); - domain->minimum_image(r02); + domain->minimum_image(FLERR, r01); + domain->minimum_image(FLERR, r02); // vp01,vp02 = distance vectors between velocities @@ -446,9 +446,9 @@ void FixRattle::vrattle4(int m) MathExtra::sub3(x[i2],x[i0],r02); MathExtra::sub3(x[i3],x[i0],r03); - domain->minimum_image(r01); - domain->minimum_image(r02); - domain->minimum_image(r03); + domain->minimum_image(FLERR, r01); + domain->minimum_image(FLERR, r02); + domain->minimum_image(FLERR, r03); // vp01,vp02,vp03 = distance vectors between velocities @@ -828,7 +828,7 @@ bool FixRattle::check2(double **v, int m, bool checkr, bool checkv) tagint i1 = atom->map(shake_atom[m][1]); MathExtra::sub3(x[i1],x[i0],r01); - domain->minimum_image(r01); + domain->minimum_image(FLERR, r01); MathExtra::sub3(v[i1],v[i0],v01); stat = !checkr || (fabs(sqrt(MathExtra::dot3(r01,r01)) - bond1) <= tol); @@ -857,8 +857,8 @@ bool FixRattle::check3(double **v, int m, bool checkr, bool checkv) MathExtra::sub3(x[i1],x[i0],r01); MathExtra::sub3(x[i2],x[i0],r02); - domain->minimum_image(r01); - domain->minimum_image(r02); + domain->minimum_image(FLERR, r01); + domain->minimum_image(FLERR, r02); MathExtra::sub3(v[i1],v[i0],v01); MathExtra::sub3(v[i2],v[i0],v02); @@ -893,9 +893,9 @@ bool FixRattle::check4(double **v, int m, bool checkr, bool checkv) MathExtra::sub3(x[i2],x[i0],r02); MathExtra::sub3(x[i3],x[i0],r03); - domain->minimum_image(r01); - domain->minimum_image(r02); - domain->minimum_image(r03); + domain->minimum_image(FLERR, r01); + domain->minimum_image(FLERR, r02); + domain->minimum_image(FLERR, r03); MathExtra::sub3(v[i1],v[i0],v01); MathExtra::sub3(v[i2],v[i0],v02); @@ -932,9 +932,9 @@ bool FixRattle::check3angle(double **v, int m, bool checkr, bool checkv) MathExtra::sub3(x[i2],x[i0],r02); MathExtra::sub3(x[i2],x[i1],r12); - domain->minimum_image(r01); - domain->minimum_image(r02); - domain->minimum_image(r12); + domain->minimum_image(FLERR, r01); + domain->minimum_image(FLERR, r02); + domain->minimum_image(FLERR, r12); MathExtra::sub3(v[i1],v[i0],v01); MathExtra::sub3(v[i2],v[i0],v02); diff --git a/src/RIGID/fix_rigid.cpp b/src/RIGID/fix_rigid.cpp index b0c6d46ee4..95c274e8e3 100644 --- a/src/RIGID/fix_rigid.cpp +++ b/src/RIGID/fix_rigid.cpp @@ -1516,6 +1516,11 @@ void FixRigid::set_xv() MathExtra::omega_to_angmom(omega[ibody],exone,eyone,ezone, inertiaatom,angmom_one[i]); } + if (atom->quat_flag) { + quatatom = atom->quat[i]; + MathExtra::quatquat(quat[ibody],orient[i],quatatom); + MathExtra::qnormalize(quatatom); + } if (eflags[i] & DIPOLE) { MathExtra::quat_to_mat(quat[ibody],p); MathExtra::matvec(p,dorient[i],mu[i]); @@ -1713,7 +1718,7 @@ void FixRigid::setup_bodies_static() } // grow extended arrays and set extended flags for each particle - // orientflag = 4 if any particle stores ellipsoid or tri orientation + // orientflag = 4 if any particle stores ellipsoid or tri orientation or quat // orientflag = 1 if any particle stores line orientation // dorientflag = 1 if any particle stores dipole orientation @@ -1721,6 +1726,7 @@ void FixRigid::setup_bodies_static() if (atom->ellipsoid_flag) orientflag = 4; if (atom->line_flag) orientflag = 1; if (atom->tri_flag) orientflag = 4; + if (atom->quat_flag) orientflag = 4; if (atom->mu_flag) dorientflag = 1; grow_arrays(atom->nmax); @@ -2061,7 +2067,12 @@ void FixRigid::setup_bodies_static() ez_space[ibody],delta,displace[i]); if (extended) { - if (eflags[i] & ELLIPSOID) { + if (atom->quat_flag) { + quatatom = atom->quat[i]; + MathExtra::qconjugate(quat[ibody],qc); + MathExtra::quatquat(qc,quatatom,orient[i]); + MathExtra::qnormalize(orient[i]); + } else if (eflags[i] & ELLIPSOID) { quatatom = ebonus[ellipsoid[i]].quat; MathExtra::qconjugate(quat[ibody],qc); MathExtra::quatquat(qc,quatatom,orient[i]); diff --git a/src/RIGID/fix_rigid_small.cpp b/src/RIGID/fix_rigid_small.cpp index 6ba2e5eb1c..e6abda2dcf 100644 --- a/src/RIGID/fix_rigid_small.cpp +++ b/src/RIGID/fix_rigid_small.cpp @@ -1409,6 +1409,11 @@ void FixRigidSmall::set_xv() MathExtra::omega_to_angmom(b->omega,exone,eyone,ezone, inertiaatom,angmom[i]); } + if (atom->quat_flag) { + quatatom = atom->quat[i]; + MathExtra::quatquat(b->quat,orient[i],quatatom); + MathExtra::qnormalize(quatatom); + } if (eflags[i] & DIPOLE) { MathExtra::quat_to_mat(b->quat,p); MathExtra::matvec(p,dorient[i],mu[i]); @@ -1849,7 +1854,7 @@ void FixRigidSmall::setup_bodies_static() } // grow extended arrays and set extended flags for each particle - // orientflag = 4 if any particle stores ellipsoid or tri orientation + // orientflag = 4 if any particle stores ellipsoid or tri orientation or quat // orientflag = 1 if any particle stores line orientation // dorientflag = 1 if any particle stores dipole orientation @@ -1857,6 +1862,7 @@ void FixRigidSmall::setup_bodies_static() if (atom->ellipsoid_flag) orientflag = 4; if (atom->line_flag) orientflag = 1; if (atom->tri_flag) orientflag = 4; + if (atom->quat_flag) orientflag = 4; if (atom->mu_flag) dorientflag = 1; grow_arrays(atom->nmax); @@ -2174,7 +2180,7 @@ void FixRigidSmall::setup_bodies_static() xgc = body[ibody].xgc; double delta[3]; MathExtra::sub3(xgc,xcm,delta); - domain->minimum_image_big(delta); + domain->minimum_image_big(FLERR, delta); MathExtra::transpose_matvec(ex,ey,ez,delta,body[ibody].xgc_body); MathExtra::add3(xcm,delta,xgc); } @@ -2209,7 +2215,12 @@ void FixRigidSmall::setup_bodies_static() delta,displace[i]); if (extended) { - if (eflags[i] & ELLIPSOID) { + if (atom->quat_flag) { + quatatom = atom->quat[i]; + MathExtra::qconjugate(b->quat,qc); + MathExtra::quatquat(qc,quatatom,orient[i]); + MathExtra::qnormalize(orient[i]); + } else if (eflags[i] & ELLIPSOID) { quatatom = ebonus[ellipsoid[i]].quat; MathExtra::qconjugate(b->quat,qc); MathExtra::quatquat(qc,quatatom,orient[i]); diff --git a/src/VORONOI/compute_voronoi_atom.cpp b/src/VORONOI/compute_voronoi_atom.cpp index 12ea173a23..f6de73e73e 100644 --- a/src/VORONOI/compute_voronoi_atom.cpp +++ b/src/VORONOI/compute_voronoi_atom.cpp @@ -40,10 +40,9 @@ static constexpr int FACESDELTA = 10000; /* ---------------------------------------------------------------------- */ ComputeVoronoi::ComputeVoronoi(LAMMPS *lmp, int narg, char **arg) : - Compute(lmp, narg, arg), con_mono(nullptr), con_poly(nullptr), - radstr(nullptr), voro(nullptr), edge(nullptr), sendvector(nullptr), - rfield(nullptr), tags(nullptr), occvec(nullptr), sendocc(nullptr), - lroot(nullptr), lnext(nullptr), faces(nullptr) + Compute(lmp, narg, arg), con_mono(nullptr), con_poly(nullptr), radstr(nullptr), + voro(nullptr), edge(nullptr), sendvector(nullptr), rfield(nullptr), tags(nullptr), + occvec(nullptr), lroot(nullptr), lnext(nullptr), faces(nullptr) { int sgroup; @@ -156,9 +155,6 @@ ComputeVoronoi::~ComputeVoronoi() memory->destroy(lroot); memory->destroy(lnext); memory->destroy(occvec); -#ifdef NOTINPLACE - memory->destroy(sendocc); -#endif memory->destroy(tags); memory->destroy(faces); } @@ -211,9 +207,6 @@ void ComputeVoronoi::compute_peratom() oldnatoms = atom->natoms; oldmaxtag = atom->map_tag_max; memory->create(occvec,oldmaxtag,"voronoi/atom:occvec"); -#ifdef NOTINPLACE - memory->create(sendocc,oldmaxtag,"voronoi/atom:sendocc"); -#endif } // get the occupation of each original voronoi cell @@ -429,12 +422,7 @@ void ComputeVoronoi::checkOccupation() // MPI sum occupation -#ifdef NOTINPLACE - memcpy(sendocc, occvec, oldnatoms*sizeof(*occvec)); - MPI_Allreduce(sendocc, occvec, oldnatoms, MPI_INT, MPI_SUM, world); -#else MPI_Allreduce(MPI_IN_PLACE, occvec, oldnatoms, MPI_INT, MPI_SUM, world); -#endif // determine the total number of atoms in this atom's currently occupied cell diff --git a/src/VORONOI/compute_voronoi_atom.h b/src/VORONOI/compute_voronoi_atom.h index fbcf14c9bc..717928b054 100644 --- a/src/VORONOI/compute_voronoi_atom.h +++ b/src/VORONOI/compute_voronoi_atom.h @@ -61,7 +61,7 @@ class ComputeVoronoi : public Compute { bool onlyGroup, occupation; tagint *tags, oldmaxtag; - int *occvec, *sendocc, *lroot, *lnext, lmax, oldnatoms, oldnall; + int *occvec, *lroot, *lnext, lmax, oldnatoms, oldnall; int faces_flag, nfaces, nfacesmax; double **faces; }; diff --git a/src/YAFF/angle_cross.cpp b/src/YAFF/angle_cross.cpp index 0ff3580715..3013885b3f 100644 --- a/src/YAFF/angle_cross.cpp +++ b/src/YAFF/angle_cross.cpp @@ -318,13 +318,13 @@ double AngleCross::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/YAFF/angle_mm3.cpp b/src/YAFF/angle_mm3.cpp index 9cc53e21de..bce4607caa 100644 --- a/src/YAFF/angle_mm3.cpp +++ b/src/YAFF/angle_mm3.cpp @@ -260,13 +260,13 @@ double AngleMM3::single(int type, int i1, int i2, int i3) double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; @@ -297,13 +297,13 @@ void AngleMM3::born_matrix(int type, int i1, int i2, int i3, double &du, double double delx1 = x[i1][0] - x[i2][0]; double dely1 = x[i1][1] - x[i2][1]; double delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); double c = delx1*delx2 + dely1*dely2 + delz1*delz2; diff --git a/src/YAFF/improper_distharm.cpp b/src/YAFF/improper_distharm.cpp index 69d14cc997..0230ae54e0 100644 --- a/src/YAFF/improper_distharm.cpp +++ b/src/YAFF/improper_distharm.cpp @@ -94,37 +94,37 @@ void ImproperDistHarm::compute(int eflag, int vflag) xab = x[i2][0] - x[i1][0]; yab = x[i2][1] - x[i1][1]; zab = x[i2][2] - x[i1][2]; - domain->minimum_image(xab,yab,zab); + domain->minimum_image(FLERR, xab,yab,zab); // bond 1->3 xac = x[i3][0] - x[i1][0]; yac = x[i3][1] - x[i1][1]; zac = x[i3][2] - x[i1][2]; - domain->minimum_image(xac,yac,zac); + domain->minimum_image(FLERR, xac,yac,zac); // bond 1->4 xad = x[i4][0] - x[i1][0]; yad = x[i4][1] - x[i1][1]; zad = x[i4][2] - x[i1][2]; - domain->minimum_image(xad,yad,zad); + domain->minimum_image(FLERR, xad,yad,zad); // bond 2-3 xbc = x[i3][0] - x[i2][0]; ybc = x[i3][1] - x[i2][1]; zbc = x[i3][2] - x[i2][2]; - domain->minimum_image(xbc,ybc,zbc); + domain->minimum_image(FLERR, xbc,ybc,zbc); // bond 2-4 xbd = x[i4][0] - x[i2][0]; ybd = x[i4][1] - x[i2][1]; zbd = x[i4][2] - x[i2][2]; - domain->minimum_image(xbd,ybd,zbd); + domain->minimum_image(FLERR, xbd,ybd,zbd); // bond 3-4 xcd = x[i4][0] - x[i3][0]; ycd = x[i4][1] - x[i3][1]; zcd = x[i4][2] - x[i3][2]; - domain->minimum_image(xcd,ycd,zcd); + domain->minimum_image(FLERR, xcd,ycd,zcd); xna = ybc*zcd - zbc*ycd; yna = -(xbc*zcd - zbc*xcd); diff --git a/src/YAFF/improper_sqdistharm.cpp b/src/YAFF/improper_sqdistharm.cpp index 1981c61f38..b7b699059c 100644 --- a/src/YAFF/improper_sqdistharm.cpp +++ b/src/YAFF/improper_sqdistharm.cpp @@ -94,37 +94,37 @@ void ImproperSQDistHarm::compute(int eflag, int vflag) xab = x[i2][0] - x[i1][0]; yab = x[i2][1] - x[i1][1]; zab = x[i2][2] - x[i1][2]; - domain->minimum_image(xab,yab,zab); + domain->minimum_image(FLERR, xab,yab,zab); // bond 1->3 xac = x[i3][0] - x[i1][0]; yac = x[i3][1] - x[i1][1]; zac = x[i3][2] - x[i1][2]; - domain->minimum_image(xac,yac,zac); + domain->minimum_image(FLERR, xac,yac,zac); // bond 1->4 xad = x[i4][0] - x[i1][0]; yad = x[i4][1] - x[i1][1]; zad = x[i4][2] - x[i1][2]; - domain->minimum_image(xad,yad,zad); + domain->minimum_image(FLERR, xad,yad,zad); // bond 2-3 xbc = x[i3][0] - x[i2][0]; ybc = x[i3][1] - x[i2][1]; zbc = x[i3][2] - x[i2][2]; - domain->minimum_image(xbc,ybc,zbc); + domain->minimum_image(FLERR, xbc,ybc,zbc); // bond 2-4 xbd = x[i4][0] - x[i2][0]; ybd = x[i4][1] - x[i2][1]; zbd = x[i4][2] - x[i2][2]; - domain->minimum_image(xbd,ybd,zbd); + domain->minimum_image(FLERR, xbd,ybd,zbd); // bond 3-4 xcd = x[i4][0] - x[i3][0]; ycd = x[i4][1] - x[i3][1]; zcd = x[i4][2] - x[i3][2]; - domain->minimum_image(xcd,ycd,zcd); + domain->minimum_image(FLERR, xcd,ycd,zcd); xna = ybc*zcd - zbc*ycd; yna = -(xbc*zcd - zbc*xcd); diff --git a/src/atom.cpp b/src/atom.cpp index 0e0b1350ac..ac9ebb1634 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -2874,6 +2874,8 @@ void Atom::remove_custom(int index, int flag, int cols) } } +// TODO: complete list of exported properties. + /** Provide access to internal data of the Atom class by keyword * \verbatim embed:rst @@ -3035,7 +3037,6 @@ void *Atom::extract(const char *name) if (strcmp(name,"x") == 0) return (void *) x; if (strcmp(name,"v") == 0) return (void *) v; if (strcmp(name,"f") == 0) return (void *) f; - if (strcmp(name,"molecule") == 0) return (void *) molecule; if (strcmp(name,"q") == 0) return (void *) q; if (strcmp(name,"mu") == 0) return (void *) mu; if (strcmp(name,"omega") == 0) return (void *) omega; @@ -3051,6 +3052,33 @@ void *Atom::extract(const char *name) if (strcmp(name,"temperature") == 0) return (void *) temperature; if (strcmp(name,"heatflow") == 0) return (void *) heatflow; + // MOLECULE PACKAGE + + if (strcmp(name,"molecule") == 0) return (void *) molecule; + if (strcmp(name,"molindex") == 0) return (void *) molindex; + if (strcmp(name,"nspecial") == 0) return (void *) nspecial; + if (strcmp(name,"special") == 0) return (void *) special; + if (strcmp(name,"num_bond") == 0) return (void *) num_bond; + if (strcmp(name,"bond_type") == 0) return (void *) bond_type; + if (strcmp(name,"bond_atom") == 0) return (void *) bond_atom; + if (strcmp(name,"num_angle") == 0) return (void *) num_angle; + if (strcmp(name,"angle_type") == 0) return (void *) angle_type; + if (strcmp(name,"angle_atom1") == 0) return (void *) angle_atom1; + if (strcmp(name,"angle_atom2") == 0) return (void *) angle_atom2; + if (strcmp(name,"angle_atom3") == 0) return (void *) angle_atom3; + if (strcmp(name,"num_dihedral") == 0) return (void *) num_dihedral; + if (strcmp(name,"dihedral_type") == 0) return (void *) dihedral_type; + if (strcmp(name,"dihedral_atom1") == 0) return (void *) dihedral_atom1; + if (strcmp(name,"dihedral_atom2") == 0) return (void *) dihedral_atom2; + if (strcmp(name,"dihedral_atom3") == 0) return (void *) dihedral_atom3; + if (strcmp(name,"dihedral_atom4") == 0) return (void *) dihedral_atom4; + if (strcmp(name,"num_improper") == 0) return (void *) num_improper; + if (strcmp(name,"improper_type") == 0) return (void *) improper_type; + if (strcmp(name,"improper_atom1") == 0) return (void *) improper_atom1; + if (strcmp(name,"improper_atom2") == 0) return (void *) improper_atom2; + if (strcmp(name,"improper_atom3") == 0) return (void *) improper_atom3; + if (strcmp(name,"improper_atom4") == 0) return (void *) improper_atom4; + // PERI PACKAGE if (strcmp(name,"vfrac") == 0) return (void *) vfrac; @@ -3172,7 +3200,6 @@ int Atom::extract_datatype(const char *name) if (strcmp(name,"x") == 0) return LAMMPS_DOUBLE_2D; if (strcmp(name,"v") == 0) return LAMMPS_DOUBLE_2D; if (strcmp(name,"f") == 0) return LAMMPS_DOUBLE_2D; - if (strcmp(name,"molecule") == 0) return LAMMPS_TAGINT; if (strcmp(name,"q") == 0) return LAMMPS_DOUBLE; if (strcmp(name,"mu") == 0) return LAMMPS_DOUBLE_2D; if (strcmp(name,"omega") == 0) return LAMMPS_DOUBLE_2D; @@ -3188,6 +3215,34 @@ int Atom::extract_datatype(const char *name) if (strcmp(name,"temperature") == 0) return LAMMPS_DOUBLE; if (strcmp(name,"heatflow") == 0) return LAMMPS_DOUBLE; + // MOLECULE package + + if (strcmp(name,"molecule") == 0) return LAMMPS_TAGINT; + if (strcmp(name,"molindex") == 0) return LAMMPS_INT; + if (strcmp(name,"molatom") == 0) return LAMMPS_INT; + if (strcmp(name,"nspecial") == 0) return LAMMPS_INT_2D; + if (strcmp(name,"special") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"num_bond") == 0) return LAMMPS_INT; + if (strcmp(name,"bond_type") == 0) return LAMMPS_INT_2D; + if (strcmp(name,"bond_atom") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"num_angle") == 0) return LAMMPS_INT; + if (strcmp(name,"angle_type") == 0) return LAMMPS_INT_2D; + if (strcmp(name,"angle_atom1") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"angle_atom2") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"angle_atom3") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"num_dihedral") == 0) return LAMMPS_INT; + if (strcmp(name,"dihedral_type") == 0) return LAMMPS_INT_2D; + if (strcmp(name,"dihedral_atom1") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"dihedral_atom2") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"dihedral_atom3") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"dihedral_atom4") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"num_improper") == 0) return LAMMPS_INT; + if (strcmp(name,"improper_type") == 0) return LAMMPS_INT_2D; + if (strcmp(name,"improper_atom1") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"improper_atom2") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"improper_atom3") == 0) return LAMMPS_TAGINT_2D; + if (strcmp(name,"improper_atom4") == 0) return LAMMPS_TAGINT_2D; + // PERI package (and in part MACHDYN) if (strcmp(name,"vfrac") == 0) return LAMMPS_DOUBLE; diff --git a/src/comm_brick.cpp b/src/comm_brick.cpp index 1e9bfe6aca..4720694759 100644 --- a/src/comm_brick.cpp +++ b/src/comm_brick.cpp @@ -209,8 +209,8 @@ void CommBrick::setup() double cut = get_comm_cutoff(); if ((cut == 0.0) && (me == 0)) - error->warning(FLERR,"Communication cutoff is 0.0. No ghost atoms " - "will be generated. Atoms may get lost."); + error->warning(FLERR,"Communication cutoff is 0.0. No ghost atoms will be generated. " + "Energies and forces may be wrong and atoms may get lost."); if (mode == Comm::MULTI) { double **cutcollectionsq = neighbor->cutcollectionsq; diff --git a/src/comm_tiled.cpp b/src/comm_tiled.cpp index bc4674a6b6..6a20728790 100644 --- a/src/comm_tiled.cpp +++ b/src/comm_tiled.cpp @@ -280,8 +280,8 @@ void CommTiled::setup() double cut = get_comm_cutoff(); if ((cut == 0.0) && (me == 0)) - error->warning(FLERR,"Communication cutoff is 0.0. No ghost atoms " - "will be generated. Atoms may get lost."); + error->warning(FLERR,"Communication cutoff is 0.0. No ghost atoms will be generated. " + "Energies and forces may be wrong and atoms may get lost."); if (triclinic == 0) cutghost[0] = cutghost[1] = cutghost[2] = cut; else { diff --git a/src/compute_angle_local.cpp b/src/compute_angle_local.cpp index b4a9334416..426f25953d 100644 --- a/src/compute_angle_local.cpp +++ b/src/compute_angle_local.cpp @@ -263,7 +263,7 @@ int ComputeAngleLocal::compute_angles(int flag) delx1 = x[atom1][0] - x[atom2][0]; dely1 = x[atom1][1] - x[atom2][1]; delz1 = x[atom1][2] - x[atom2][2]; - domain->minimum_image(delx1, dely1, delz1); + domain->minimum_image(FLERR, delx1, dely1, delz1); rsq1 = delx1 * delx1 + dely1 * dely1 + delz1 * delz1; r1 = sqrt(rsq1); @@ -271,7 +271,7 @@ int ComputeAngleLocal::compute_angles(int flag) delx2 = x[atom3][0] - x[atom2][0]; dely2 = x[atom3][1] - x[atom2][1]; delz2 = x[atom3][2] - x[atom2][2]; - domain->minimum_image(delx2, dely2, delz2); + domain->minimum_image(FLERR, delx2, dely2, delz2); rsq2 = delx2 * delx2 + dely2 * dely2 + delz2 * delz2; r2 = sqrt(rsq2); diff --git a/src/compute_bond_local.cpp b/src/compute_bond_local.cpp index e9632d254f..54c8c734c7 100644 --- a/src/compute_bond_local.cpp +++ b/src/compute_bond_local.cpp @@ -344,7 +344,7 @@ int ComputeBondLocal::compute_bonds(int flag) dx = x[atom1][0] - x[atom2][0]; dy = x[atom1][1] - x[atom2][1]; dz = x[atom1][2] - x[atom2][2]; - domain->minimum_image(dx, dy, dz); + domain->minimum_image(FLERR, dx, dy, dz); rsq = dx * dx + dy * dy + dz * dz; if (btype == 0) { @@ -428,22 +428,19 @@ int ComputeBondLocal::compute_bonds(int flag) if (dstr) input->variable->internal_set(dvar, sqrt(rsq)); } - // to make sure dx, dy and dz are always from the lower to the higher id - double directionCorrection = tag[atom1] > tag[atom2] ? -1.0 : 1.0; - for (int n = 0; n < nvalues; n++) { switch (bstyle[n]) { case DIST: ptr[n] = sqrt(rsq); break; case DX: - ptr[n] = dx * directionCorrection; + ptr[n] = dx; break; case DY: - ptr[n] = dy * directionCorrection; + ptr[n] = dy; break; case DZ: - ptr[n] = dz * directionCorrection; + ptr[n] = dz; break; case ENGPOT: ptr[n] = engpot; diff --git a/src/compute_dihedral_local.cpp b/src/compute_dihedral_local.cpp index bd1e389e85..56718aa201 100644 --- a/src/compute_dihedral_local.cpp +++ b/src/compute_dihedral_local.cpp @@ -252,22 +252,22 @@ int ComputeDihedralLocal::compute_dihedrals(int flag) vb1x = x[atom1][0] - x[atom2][0]; vb1y = x[atom1][1] - x[atom2][1]; vb1z = x[atom1][2] - x[atom2][2]; - domain->minimum_image(vb1x, vb1y, vb1z); + domain->minimum_image(FLERR, vb1x, vb1y, vb1z); vb2x = x[atom3][0] - x[atom2][0]; vb2y = x[atom3][1] - x[atom2][1]; vb2z = x[atom3][2] - x[atom2][2]; - domain->minimum_image(vb2x, vb2y, vb2z); + domain->minimum_image(FLERR, vb2x, vb2y, vb2z); vb2xm = -vb2x; vb2ym = -vb2y; vb2zm = -vb2z; - domain->minimum_image(vb2xm, vb2ym, vb2zm); + domain->minimum_image(FLERR, vb2xm, vb2ym, vb2zm); vb3x = x[atom4][0] - x[atom3][0]; vb3y = x[atom4][1] - x[atom3][1]; vb3z = x[atom4][2] - x[atom3][2]; - domain->minimum_image(vb3x, vb3y, vb3z); + domain->minimum_image(FLERR, vb3x, vb3y, vb3z); ax = vb1y * vb2zm - vb1z * vb2ym; ay = vb1z * vb2xm - vb1x * vb2zm; diff --git a/src/compute_improper_local.cpp b/src/compute_improper_local.cpp index ff8f069a03..fe5e373789 100644 --- a/src/compute_improper_local.cpp +++ b/src/compute_improper_local.cpp @@ -183,17 +183,17 @@ int ComputeImproperLocal::compute_impropers(int flag) vb1x = x[atom1][0] - x[atom2][0]; vb1y = x[atom1][1] - x[atom2][1]; vb1z = x[atom1][2] - x[atom2][2]; - domain->minimum_image(vb1x, vb1y, vb1z); + domain->minimum_image(FLERR, vb1x, vb1y, vb1z); vb2x = x[atom3][0] - x[atom2][0]; vb2y = x[atom3][1] - x[atom2][1]; vb2z = x[atom3][2] - x[atom2][2]; - domain->minimum_image(vb2x, vb2y, vb2z); + domain->minimum_image(FLERR, vb2x, vb2y, vb2z); vb3x = x[atom4][0] - x[atom3][0]; vb3y = x[atom4][1] - x[atom3][1]; vb3z = x[atom4][2] - x[atom3][2]; - domain->minimum_image(vb3x, vb3y, vb3z); + domain->minimum_image(FLERR, vb3x, vb3y, vb3z); ss1 = 1.0 / (vb1x * vb1x + vb1y * vb1y + vb1z * vb1z); ss2 = 1.0 / (vb2x * vb2x + vb2y * vb2y + vb2z * vb2z); diff --git a/src/compute_pair_local.cpp b/src/compute_pair_local.cpp index 57f15264f0..fa5d164844 100644 --- a/src/compute_pair_local.cpp +++ b/src/compute_pair_local.cpp @@ -277,22 +277,19 @@ int ComputePairLocal::compute_pairs(int flag) else ptr = alocal[m]; - // to make sure dx, dy and dz are always from the lower to the higher id - double directionCorrection = itag > jtag ? -1.0 : 1.0; - for (n = 0; n < nvalues; n++) { switch (pstyle[n]) { case DIST: ptr[n] = sqrt(rsq); break; case DX: - ptr[n] = delx * directionCorrection; + ptr[n] = delx; break; case DY: - ptr[n] = dely * directionCorrection; + ptr[n] = dely; break; case DZ: - ptr[n] = delz * directionCorrection; + ptr[n] = delz; break; case ENG: ptr[n] = eng; diff --git a/src/compute_rdf.cpp b/src/compute_rdf.cpp index c1e7dda2bb..9d7f4306d6 100644 --- a/src/compute_rdf.cpp +++ b/src/compute_rdf.cpp @@ -159,6 +159,7 @@ ComputeRDF::~ComputeRDF() delete[] ihi; delete[] jlo; delete[] jhi; + delete[] rev; memory->destroy(hist); memory->destroy(histall); memory->destroy(array); diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index 7be67f4c49..68ab376692 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -23,6 +23,7 @@ #include "comm.h" #include "domain.h" #include "error.h" +#include "group.h" #include "input.h" #include "irregular.h" #include "lattice.h" @@ -64,18 +65,43 @@ enum { NONE, RATIO, SUBSET }; enum { BISECTION, QUASIRANDOM }; static constexpr const char *mesh_name[] = {"recursive bisection", "quasi-random"}; + /* ---------------------------------------------------------------------- */ -CreateAtoms::CreateAtoms(LAMMPS *lmp) : Command(lmp), basistype(nullptr) {} +CreateAtoms::CreateAtoms(LAMMPS *lmp) : + Command(lmp), basistype(nullptr), xmol(nullptr), vstr(nullptr), xstr(nullptr), ystr(nullptr), + zstr(nullptr), groupname(nullptr), region(nullptr), onemol(nullptr), ranmol(nullptr), + ranlatt(nullptr) +{ +} + +/* ---------------------------------------------------------------------- */ + +CreateAtoms::~CreateAtoms() +{ + delete[] basistype; + memory->destroy(xmol); + + delete[] vstr; + delete[] xstr; + delete[] ystr; + delete[] zstr; + delete[] groupname; + + delete ranmol; + delete ranlatt; +} /* ---------------------------------------------------------------------- */ void CreateAtoms::command(int narg, char **arg) { if (domain->box_exist == 0) - error->all(FLERR, "Create_atoms command before simulation box is defined" + utils::errorurl(33)); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms command before simulation box is defined" + utils::errorurl(33)); if (modify->nfix_restart_peratom) - error->all(FLERR, "Cannot create_atoms after reading restart file with per-atom info"); + error->all(FLERR, Error::NOLASTLINE, + "Cannot create_atoms after reading restart file with per-atom info"); // check for compatible lattice @@ -83,10 +109,10 @@ void CreateAtoms::command(int narg, char **arg) if (domain->dimension == 2) { if (latsty == Lattice::SC || latsty == Lattice::BCC || latsty == Lattice::FCC || latsty == Lattice::HCP || latsty == Lattice::DIAMOND) - error->all(FLERR, "Lattice style incompatible with simulation dimension"); + error->all(FLERR, Error::NOLASTLINE, "Lattice style incompatible with simulation dimension"); } else { if (latsty == Lattice::SQ || latsty == Lattice::SQ2 || latsty == Lattice::HEX) - error->all(FLERR, "Lattice style incompatible with simulation dimension"); + error->all(FLERR, Error::NOLASTLINE, "Lattice style incompatible with simulation dimension"); } // parse arguments @@ -115,15 +141,16 @@ void CreateAtoms::command(int narg, char **arg) xone[1] = utils::numeric(FLERR, arg[3], false, lmp); xone[2] = utils::numeric(FLERR, arg[4], false, lmp); if (domain->dimension == 2 && xone[2] != 0.0) - error->all(FLERR, "Create_atoms single for 2d simulation requires z coord = 0.0"); + error->all(FLERR, 4, "Create_atoms single for 2d simulation requires z coord = 0.0"); iarg = 5; } else if (strcmp(arg[1], "random") == 0) { style = RANDOM; if (narg < 5) utils::missing_cmd_args(FLERR, "create_atoms random", error); nrandom = utils::inumeric(FLERR, arg[2], false, lmp); - if (nrandom < 0) error->all(FLERR, "Illegal create_atoms number of random atoms {}", nrandom); + if (nrandom < 0) + error->all(FLERR, 2, "Illegal create_atoms number of random atoms {}", nrandom); seed = utils::inumeric(FLERR, arg[3], false, lmp); - if (seed <= 0) error->all(FLERR, "Illegal create_atoms random seed {}", seed); + if (seed <= 0) error->all(FLERR, 3, "Illegal create_atoms random seed {}", seed); if (strcmp(arg[4], "NULL") == 0) region = nullptr; else { @@ -162,8 +189,10 @@ void CreateAtoms::command(int narg, char **arg) mesh_density = 1.0; nbasis = domain->lattice->nbasis; - basistype = new int[nbasis]; - for (int i = 0; i < nbasis; i++) basistype[i] = ntype; + if (nbasis > 0) { + basistype = new int[nbasis]; + for (int i = 0; i < nbasis; i++) basistype[i] = ntype; + } while (iarg < narg) { if (strcmp(arg[iarg], "basis") == 0) { @@ -171,8 +200,8 @@ void CreateAtoms::command(int narg, char **arg) int ibasis = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); int itype = utils::expand_type_int(FLERR, arg[iarg + 2], Atom::ATOM, lmp); if (ibasis <= 0 || ibasis > nbasis || itype <= 0 || itype > atom->ntypes) - error->all(FLERR, "Out of range basis setting '{} {}' in create_atoms command", ibasis, - itype); + error->all(FLERR, iarg + 1, "Out of range basis setting '{} {}' in create_atoms command", + ibasis, itype); basistype[ibasis - 1] = itype; iarg += 3; } else if (strcmp(arg[iarg], "remap") == 0) { @@ -183,7 +212,8 @@ void CreateAtoms::command(int narg, char **arg) if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "create_atoms mol", error); int imol = atom->find_molecule(arg[iarg + 1]); if (imol == -1) - error->all(FLERR, "Molecule template ID {} for create_atoms does not exist", arg[iarg + 1]); + error->all(FLERR, iarg + 1, "Molecule template ID {} for create_atoms does not exist", + arg[iarg + 1]); if ((atom->molecules[imol]->nset > 1) && (comm->me == 0)) error->warning(FLERR, "Molecule template for create_atoms has multiple molecule sets. " @@ -199,11 +229,11 @@ void CreateAtoms::command(int narg, char **arg) else if (strcmp(arg[iarg + 1], "lattice") == 0) scaleflag = 1; else - error->all(FLERR, "Unknown create_atoms units option {}", arg[iarg + 1]); + error->all(FLERR, iarg + 1, "Unknown create_atoms units option {}", arg[iarg + 1]); iarg += 2; } else if (strcmp(arg[iarg], "var") == 0) { if (style == SINGLE) - error->all(FLERR, "Cannot use 'var' keyword with 'single' style for create_atoms"); + error->all(FLERR, iarg, "Cannot use 'var' keyword with 'single' style for create_atoms"); if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms var", error); delete[] vstr; vstr = utils::strdup(arg[iarg + 1]); @@ -221,7 +251,7 @@ void CreateAtoms::command(int narg, char **arg) delete[] zstr; zstr = utils::strdup(arg[iarg + 2]); } else - error->all(FLERR, "Unknown create_atoms set option {}", arg[iarg + 2]); + error->all(FLERR, iarg + 2, "Unknown create_atoms set option {}", arg[iarg + 2]); iarg += 3; } else if (strcmp(arg[iarg], "rotate") == 0) { if (iarg + 5 > narg) utils::missing_cmd_args(FLERR, "create_atoms rotate", error); @@ -233,9 +263,9 @@ void CreateAtoms::command(int narg, char **arg) axisone[1] = utils::numeric(FLERR, arg[iarg + 3], false, lmp); axisone[2] = utils::numeric(FLERR, arg[iarg + 4], false, lmp); if (axisone[0] == 0.0 && axisone[1] == 0.0 && axisone[2] == 0.0) - error->all(FLERR, "Illegal create_atoms rotate arguments"); + error->all(FLERR, Error::NOPOINTER, "Illegal create_atoms rotate arguments"); if (domain->dimension == 2 && (axisone[0] != 0.0 || axisone[1] != 0.0)) - error->all(FLERR, "Invalid create_atoms rotation vector for 2d model"); + error->all(FLERR, Error::NOPOINTER, "Invalid create_atoms rotation vector for 2d model"); MathExtra::norm3(axisone); MathExtra::axisangle_to_quat(axisone, thetaone, quatone); iarg += 5; @@ -245,7 +275,7 @@ void CreateAtoms::command(int narg, char **arg) subsetfrac = utils::numeric(FLERR, arg[iarg + 1], false, lmp); subsetseed = utils::inumeric(FLERR, arg[iarg + 2], false, lmp); if (subsetfrac <= 0.0 || subsetfrac > 1.0 || subsetseed <= 0) - error->all(FLERR, "Illegal create_atoms ratio settings"); + error->all(FLERR, Error::NOPOINTER, "Illegal create_atoms ratio settings"); iarg += 3; } else if (strcmp(arg[iarg], "subset") == 0) { if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "create_atoms subset", error); @@ -253,26 +283,36 @@ void CreateAtoms::command(int narg, char **arg) nsubset = utils::bnumeric(FLERR, arg[iarg + 1], false, lmp); subsetseed = utils::inumeric(FLERR, arg[iarg + 2], false, lmp); if ((nsubset <= 0) || (subsetseed <= 0)) - error->all(FLERR, "Illegal create_atoms subset settings"); + error->all(FLERR, Error::NOPOINTER, "Illegal create_atoms subset settings"); iarg += 3; + } else if (strcmp(arg[iarg], "group") == 0) { + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms group", error); + if (strcmp(arg[iarg + 1], "none") == 0) { + delete[] groupname; + groupname = nullptr; + } else { + groupname = utils::strdup(arg[iarg + 1]); + } + iarg += 2; } else if (strcmp(arg[iarg], "overlap") == 0) { if (style != RANDOM) - error->all(FLERR, "Create_atoms overlap can only be used with random style"); - if (iarg + 2 > narg) error->all(FLERR, "Illegal create_atoms command"); + error->all(FLERR, iarg, "Create_atoms overlap can only be used with random style"); + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms overlap", error); overlap = utils::numeric(FLERR, arg[iarg + 1], false, lmp); - if (overlap <= 0) error->all(FLERR, "Illegal create_atoms overlap value: {}", overlap); + if (overlap <= 0) + error->all(FLERR, iarg + 1, "Illegal create_atoms overlap value: {}", overlap); overlapflag = 1; iarg += 2; } else if (strcmp(arg[iarg], "maxtry") == 0) { if (style != RANDOM) - error->all(FLERR, "Create_atoms maxtry can only be used with random style"); - if (iarg + 2 > narg) error->all(FLERR, "Illegal create_atoms command"); + error->all(FLERR, iarg, "Create_atoms maxtry can only be used with random style"); + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms maxtry", error); maxtry = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); - if (maxtry <= 0) error->all(FLERR, "Illegal create_atoms command"); + if (maxtry <= 0) error->all(FLERR, iarg + 1, "Illegal create_atoms maxtry value {}", maxtry); iarg += 2; } else if (strcmp(arg[iarg], "meshmode") == 0) { if (style != MESH) - error->all(FLERR, "Create_atoms meshmode can only be used with mesh style"); + error->all(FLERR, iarg, "Create_atoms meshmode can only be used with mesh style"); if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "create_atoms meshmode", error); if (strcmp(arg[iarg + 1], "bisect") == 0) { mesh_style = BISECTION; @@ -281,16 +321,17 @@ void CreateAtoms::command(int narg, char **arg) mesh_style = QUASIRANDOM; mesh_density = utils::numeric(FLERR, arg[iarg + 2], false, lmp); } else - error->all(FLERR, "Unknown create_atoms meshmode {}", arg[iarg + 2]); + error->all(FLERR, iarg + 2, "Unknown create_atoms meshmode {}", arg[iarg + 2]); iarg += 3; } else if (strcmp(arg[iarg], "radscale") == 0) { if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms radscale", error); if (style != MESH) - error->all(FLERR, "Create_atoms radscale can only be used with mesh style"); + error->all(FLERR, iarg, "Create_atoms radscale can only be used with mesh style"); if (!atom->radius_flag) - error->all(FLERR, "Must have atom attribute radius to set radscale factor"); + error->all(FLERR, iarg, "Must have atom attribute radius to set radscale factor"); radscale = utils::numeric(FLERR, arg[iarg + 1], false, lmp); - if (radscale <= 0.0) error->all(FLERR, "Illegal create_atoms radscale value: {}", radscale); + if (radscale <= 0.0) + error->all(FLERR, iarg + 1, "Illegal create_atoms radscale value: {}", radscale); iarg += 2; } else error->all(FLERR, "Illegal create_atoms command option {}", arg[iarg]); @@ -300,16 +341,20 @@ void CreateAtoms::command(int narg, char **arg) if (mode == ATOM) { if ((ntype <= 0) || (ntype > atom->ntypes)) - error->all(FLERR, "Invalid atom type in create_atoms command"); + error->all(FLERR, Error::NOLASTLINE, "Invalid atom type in create_atoms command"); } else if (mode == MOLECULE) { - if (onemol->xflag == 0) error->all(FLERR, "Create_atoms molecule must have coordinates"); - if (onemol->typeflag == 0) error->all(FLERR, "Create_atoms molecule must have atom types"); + if (onemol->xflag == 0) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms molecule must have coordinates"); + if (onemol->typeflag == 0) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms molecule must have atom types"); if (ntype + onemol->ntypes <= 0 || ntype + onemol->ntypes > atom->ntypes) - error->all(FLERR, "Invalid atom type in create_atoms mol command"); + error->all(FLERR, Error::NOLASTLINE, "Invalid atom type in create_atoms mol command"); if (onemol->tag_require && !atom->tag_enable) - error->all(FLERR, "Create_atoms molecule has atom IDs, but system does not"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms molecule has atom IDs, but system does not"); if (atom->molecular == Atom::TEMPLATE && onemol != atom->avec->onemols[0]) - error->all(FLERR, "Create_atoms molecule template ID must be same as atom style template ID"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms molecule template ID must be same as atom style template ID"); onemol->check_attributes(); @@ -323,8 +368,10 @@ void CreateAtoms::command(int narg, char **arg) if (style == MESH) { if (mode == MOLECULE) - error->all(FLERR, "Create_atoms mesh is not compatible with the 'mol' option"); - if (scaleflag) error->all(FLERR, "Create_atoms mesh must use 'units box' option"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms mesh is not compatible with the 'mol' option"); + if (scaleflag) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms mesh must use 'units box' option"); } ranlatt = nullptr; @@ -333,40 +380,44 @@ void CreateAtoms::command(int narg, char **arg) // error check and further setup for variable test if (!vstr && (xstr || ystr || zstr)) - error->all(FLERR, "Incomplete use of variables in create_atoms command"); + error->all(FLERR, Error::NOLASTLINE, "Incomplete use of variables in create_atoms command"); if (vstr && (!xstr && !ystr && !zstr)) - error->all(FLERR, "Incomplete use of variables in create_atoms command"); + error->all(FLERR, Error::NOLASTLINE, "Incomplete use of variables in create_atoms command"); if (varflag) { vvar = input->variable->find(vstr); if (vvar < 0) error->all(FLERR, "Variable {} for create_atoms does not exist", vstr); if (!input->variable->equalstyle(vvar)) - error->all(FLERR, "Variable for create_atoms is invalid style"); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", vstr); if (xstr) { xvar = input->variable->find(xstr); - if (xvar < 0) error->all(FLERR, "Variable {} for create_atoms does not exist", xstr); + if (xvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", xstr); if (!input->variable->internalstyle(xvar)) - error->all(FLERR, "Variable for create_atoms is invalid style"); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", xstr); } if (ystr) { yvar = input->variable->find(ystr); - if (yvar < 0) error->all(FLERR, "Variable {} for create_atoms does not exist", ystr); + if (yvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", ystr); if (!input->variable->internalstyle(yvar)) - error->all(FLERR, "Variable for create_atoms is invalid style"); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", ystr); } if (zstr) { zvar = input->variable->find(zstr); - if (zvar < 0) error->all(FLERR, "Variable {} for create_atoms does not exist", zstr); + if (zvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", zstr); if (!input->variable->internalstyle(zvar)) - error->all(FLERR, "Variable for create_atoms is invalid style"); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", zstr); } } // require non-none lattice be defined for BOX or REGION styles if ((style == BOX) || (style == REGION)) { - if (nbasis == 0) error->all(FLERR, "Cannot create atoms with undefined lattice"); + if (nbasis == 0) + error->all(FLERR, Error::NOLASTLINE, "Cannot create atoms with undefined lattice"); } // apply scaling factor for styles that use distance-dependent factors @@ -492,7 +543,8 @@ void CreateAtoms::command(int narg, char **arg) bigint nblocal = atom->nlocal; MPI_Allreduce(&nblocal, &atom->natoms, 1, MPI_LMP_BIGINT, MPI_SUM, world); - if (atom->natoms < 0 || atom->natoms >= MAXBIGINT) error->all(FLERR, "Too many total atoms"); + if ((atom->natoms < 0) || (atom->natoms >= MAXBIGINT)) + error->all(FLERR, Error::NOLASTLINE, "Too many total atoms"); // add IDs for newly created atoms // check that atom IDs are valid @@ -644,18 +696,6 @@ void CreateAtoms::command(int narg, char **arg) if (domain->triclinic) domain->lamda2x(atom->nlocal); } - // clean up - - delete ranmol; - delete ranlatt; - - delete[] basistype; - delete[] vstr; - delete[] xstr; - delete[] ystr; - delete[] zstr; - if (mode == MOLECULE) memory->destroy(xmol); - // for MOLECULE mode: // create special bond lists for molecular systems, // but not for atom style template @@ -668,6 +708,13 @@ void CreateAtoms::command(int narg, char **arg) } } + // add atoms to group + + if (groupname) { + int groupbit = group->bitmask[group->find_or_create(groupname)]; + for (int i = nlocal_previous; i < atom->nlocal; ++i) atom->mask[i] |= groupbit; + } + // print status MPI_Barrier(world); @@ -778,7 +825,7 @@ void CreateAtoms::add_random() } if (xlo > xhi || ylo > yhi || zlo > zhi) - error->all(FLERR, "No overlap of box and region for create_atoms"); + error->all(FLERR, Error::NOLASTLINE, "No overlap of box and region for create_atoms"); // insert Nrandom new atom/molecule into simulation box @@ -828,7 +875,7 @@ void CreateAtoms::add_random() delx = xone[0] - x[i][0]; dely = xone[1] - x[i][1]; delz = xone[2] - x[i][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); distsq = delx * delx + dely * dely + delz * delz; if (distsq < odistsq) { reject = 1; @@ -844,7 +891,7 @@ void CreateAtoms::add_random() delx = xmol[j][0] - x[i][0]; dely = xmol[j][1] - x[i][1]; delz = xmol[j][2] - x[i][2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); distsq = delx * delx + dely * dely + delz * delz; if (distsq < odistsq) { reject = 1; @@ -1085,7 +1132,8 @@ void CreateAtoms::add_mesh(const char *filename) SafeFilePtr fp = fopen(filename, "rb"); if (fp == nullptr) - error->one(FLERR, "Cannot open STL mesh file {}: {}", filename, utils::getsyserror()); + error->one(FLERR, Error::NOLASTLINE, "Cannot open STL mesh file {}: {}", filename, + utils::getsyserror()); // first try reading the file in ASCII format @@ -1159,7 +1207,8 @@ void CreateAtoms::add_mesh(const char *filename) title[79] = '\0'; count = fread(&ntri, sizeof(ntri), 1, fp); if (count <= 0) { - error->all(FLERR, "Error reading STL file {}: {}", filename, utils::getsyserror()); + error->all(FLERR, Error::NOLASTLINE, "Error reading STL file {}: {}", filename, + utils::getsyserror()); } else { if (comm->me == 0) utils::logmesg(lmp, "Reading STL object {} from binary file {}\n", utils::trim(title), @@ -1169,7 +1218,8 @@ void CreateAtoms::add_mesh(const char *filename) for (uint32_t i = 0U; i < ntri; ++i) { count = fread(triangle, sizeof(float), 12, fp); if (count != 12) - error->all(FLERR, "Error reading STL file {}: {}", filename, utils::getsyserror()); + error->all(FLERR, Error::NOLASTLINE, "Error reading STL file {}: {}", filename, + utils::getsyserror()); count = fread(&attr, sizeof(attr), 1, fp); for (int j = 0; j < 3; ++j) @@ -1186,7 +1236,8 @@ void CreateAtoms::add_mesh(const char *filename) } } } else { - error->all(FLERR, "Error reading triangles from STL mesh file {}: {}", filename, e.what()); + error->all(FLERR, Error::NOLASTLINE, "Error reading triangles from STL mesh file {}: {}", + filename, e.what()); } } @@ -1209,10 +1260,11 @@ void CreateAtoms::add_lattice() // verify lattice was defined with triclinic/general option if (!domain->triclinic_general && domain->lattice->is_general_triclinic()) - error->all(FLERR, + error->all(FLERR, Error::NOLASTLINE, "Create_atoms for non general triclinic box cannot use triclinic/general lattice"); if (domain->triclinic_general && !domain->lattice->is_general_triclinic()) - error->all(FLERR, "Create_atoms for general triclinic box requires triclinic/general lattice"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms for general triclinic box requires triclinic/general lattice"); // convert 8 corners of my subdomain from box coords to lattice coords // for orthogonal, use corner pts of my subbox @@ -1353,7 +1405,8 @@ void CreateAtoms::add_lattice() int overflow; MPI_Allreduce(&nlatt_overflow, &overflow, 1, MPI_INT, MPI_SUM, world); - if (overflow) error->all(FLERR, "Create_atoms lattice size overflow on 1 or more procs"); + if (overflow) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms lattice size overflow on 1 or more procs"); bigint nadd; @@ -1367,7 +1420,8 @@ void CreateAtoms::add_lattice() bigint bnlattall; MPI_Allreduce(&bnlatt, &bnlattall, 1, MPI_LMP_BIGINT, MPI_SUM, world); if (subsetflag == RATIO) nsubset = static_cast(subsetfrac * bnlattall); - if (nsubset > bnlattall) error->all(FLERR, "Create_atoms subset size > # of lattice sites"); + if (nsubset > bnlattall) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms subset size > # of lattice sites"); if (comm->nprocs == 1) nadd = nsubset; else @@ -1438,7 +1492,8 @@ void CreateAtoms::loop_lattice(int action) domain->general_to_restricted_coords(x); if (dimension == 2) { if (fabs(x[2]) > EPS_ZCOORD) - error->all(FLERR, "Create_atoms atom z coord is non-zero for 2d simulation"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms atom z coord is non-zero for 2d simulation"); x[2] = 0.0; } } diff --git a/src/create_atoms.h b/src/create_atoms.h index f839e3f0df..a1881f38b9 100644 --- a/src/create_atoms.h +++ b/src/create_atoms.h @@ -27,6 +27,7 @@ namespace LAMMPS_NS { class CreateAtoms : public Command { public: CreateAtoms(class LAMMPS *); + ~CreateAtoms() override; void command(int, char **) override; private: @@ -45,7 +46,7 @@ class CreateAtoms : public Command { int varflag, vvar, xvar, yvar, zvar; char *vstr, *xstr, *ystr, *zstr; - char *xstr_copy, *ystr_copy, *zstr_copy; + char *groupname; int ilo, ihi, jlo, jhi, klo, khi; diff --git a/src/dihedral.cpp b/src/dihedral.cpp index 14b59d2542..a6e66ac9cf 100644 --- a/src/dihedral.cpp +++ b/src/dihedral.cpp @@ -33,6 +33,7 @@ Dihedral::Dihedral(LAMMPS *_lmp) : Pointers(_lmp) { energy = 0.0; writedata = 0; + reinitflag = 1; allocated = 0; suffix_flag = Suffix::NONE; @@ -428,3 +429,15 @@ double Dihedral::memory_usage() bytes += (double) comm->nthreads * maxcvatom * 9 * sizeof(double); return bytes; } + +/* ----------------------------------------------------------------------- + reset all type-based dihedral params via init() +-------------------------------------------------------------------------- */ + +void Dihedral::reinit() +{ + if (!reinitflag) + error->all(FLERR, "Fix adapt interface to this dihedral style not supported"); + + init(); +} diff --git a/src/dihedral.h b/src/dihedral.h index 03a5690a49..7ca3379e44 100644 --- a/src/dihedral.h +++ b/src/dihedral.h @@ -37,6 +37,9 @@ class Dihedral : protected Pointers { // CENTROID_AVAIL = different and implemented // CENTROID_NOTAVAIL = different, not yet implemented + int reinitflag; // 0 if not compatible with fix adapt + // extract() method may still need to be added + // KOKKOS host/device flag and data masks ExecutionSpace execution_space; @@ -62,6 +65,8 @@ class Dihedral : protected Pointers { du = 0.0; du2 = 0.0; } + virtual void *extract(const char *, int &) { return nullptr; } + void reinit(); protected: int suffix_flag; // suffix compatibility flag diff --git a/src/dihedral_hybrid.cpp b/src/dihedral_hybrid.cpp index 3671391f5d..6210009170 100644 --- a/src/dihedral_hybrid.cpp +++ b/src/dihedral_hybrid.cpp @@ -326,6 +326,14 @@ void DihedralHybrid::init_style() if (styles[m]) styles[m]->init_style(); } +/* ---------------------------------------------------------------------- */ + +int DihedralHybrid::check_itype(int itype, char *substyle) +{ + if (strcmp(keywords[map[itype]], substyle) == 0) return 1; + return 0; +} + /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ diff --git a/src/dihedral_hybrid.h b/src/dihedral_hybrid.h index debc8a9d8d..4dcadcb67a 100644 --- a/src/dihedral_hybrid.h +++ b/src/dihedral_hybrid.h @@ -40,6 +40,8 @@ class DihedralHybrid : public Dihedral { void read_restart(FILE *) override; double memory_usage() override; + int check_itype(int, char *); + protected: int *map; // which style each dihedral type points to diff --git a/src/displace_atoms.cpp b/src/displace_atoms.cpp index b9eb121b3d..3ab9fd665d 100644 --- a/src/displace_atoms.cpp +++ b/src/displace_atoms.cpp @@ -125,7 +125,7 @@ void DisplaceAtoms::command(int narg, char **arg) else if (strcmp(arg[2],"y") == 0) d_dim = 1; else if (strcmp(arg[2],"z") == 0) d_dim = 2; else error->all(FLERR, 2, "Unknown displace_atoms ramp dimension {}", arg[2]); - if ((domain->dimension == 2) && (d_dim = 2)) + if ((domain->dimension == 2) && (d_dim == 2)) error->all(FLERR, 2, "Must not displace atoms in z-direction with 2d system"); double d_lo,d_hi; diff --git a/src/domain.cpp b/src/domain.cpp index 31350482bd..33764d70cc 100644 --- a/src/domain.cpp +++ b/src/domain.cpp @@ -1136,7 +1136,7 @@ void Domain::box_too_small_check() delx = x[i][0] - x[k][0]; dely = x[i][1] - x[k][1]; delz = x[i][2] - x[k][2]; - minimum_image(delx,dely,delz); + minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; maxbondme = MAX(maxbondme,rsq); } @@ -1205,6 +1205,7 @@ void Domain::subbox_too_small_check(double thresh) "could lead to lost atoms"); } +// clang-format on /* ---------------------------------------------------------------------- minimum image convention in periodic dimensions use 1/2 of box size as test @@ -1218,39 +1219,45 @@ void Domain::subbox_too_small_check(double thresh) ------------------------------------------------------------------------- */ static constexpr double MAXIMGCOUNT = 16; - -void Domain::minimum_image(double &dx, double &dy, double &dz) const +void Domain::minimum_image(const std::string &file, int line, double &dx, double &dy, + double &dz) const { if (triclinic == 0) { if (xperiodic) { if (fabs(dx) > (MAXIMGCOUNT * xprd)) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dx); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dx); while (fabs(dx) > xprd_half) { - if (dx < 0.0) dx += xprd; - else dx -= xprd; + if (dx < 0.0) + dx += xprd; + else + dx -= xprd; } } if (yperiodic) { if (fabs(dy) > (MAXIMGCOUNT * yprd)) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dy); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dy); while (fabs(dy) > yprd_half) { - if (dy < 0.0) dy += yprd; - else dy -= yprd; + if (dy < 0.0) + dy += yprd; + else + dy -= yprd; } } if (zperiodic) { if (fabs(dz) > (MAXIMGCOUNT * zprd)) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dz); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dz); while (fabs(dz) > zprd_half) { - if (dz < 0.0) dz += zprd; - else dz -= zprd; + if (dz < 0.0) + dz += zprd; + else + dz -= zprd; } } } else { if (zperiodic) { if (fabs(dz) > (MAXIMGCOUNT * zprd)) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dz); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dz); while (fabs(dz) > zprd_half) { if (dz < 0.0) { dz += zprd; @@ -1265,7 +1272,7 @@ void Domain::minimum_image(double &dx, double &dy, double &dz) const } if (yperiodic) { if (fabs(dy) > (MAXIMGCOUNT * yprd)) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dy); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dy); while (fabs(dy) > yprd_half) { if (dy < 0.0) { dy += yprd; @@ -1278,10 +1285,12 @@ void Domain::minimum_image(double &dx, double &dy, double &dz) const } if (xperiodic) { if (fabs(dx) > (MAXIMGCOUNT * xprd)) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dx); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dx); while (fabs(dx) > xprd_half) { - if (dx < 0.0) dx += xprd; - else dx -= xprd; + if (dx < 0.0) + dx += xprd; + else + dx -= xprd; } } } @@ -1298,61 +1307,63 @@ void Domain::minimum_image(double &dx, double &dy, double &dz) const this applies for example to fix rigid/small ------------------------------------------------------------------------- */ -void Domain::minimum_image_big(double &dx, double &dy, double &dz) const +void Domain::minimum_image_big(const std::string &file, int line, double &dx, double &dy, + double &dz) const { if (triclinic == 0) { if (xperiodic) { - double dfactor = dx/xprd + 0.5; + double dfactor = dx / xprd + 0.5; if (dx < 0) dfactor -= 1.0; if (dfactor > MAXSMALLINT) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dx); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dx); dx -= xprd * static_cast(dfactor); } if (yperiodic) { - double dfactor = dy/yprd + 0.5; + double dfactor = dy / yprd + 0.5; if (dy < 0) dfactor -= 1.0; if (dfactor > MAXSMALLINT) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dy); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dy); dy -= yprd * static_cast(dfactor); } if (zperiodic) { - double dfactor = dz/zprd + 0.5; + double dfactor = dz / zprd + 0.5; if (dz < 0) dfactor -= 1.0; if (dfactor > MAXSMALLINT) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dz); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dz); dz -= zprd * static_cast(dfactor); } } else { if (zperiodic) { - double dfactor = dz/zprd + 0.5; + double dfactor = dz / zprd + 0.5; if (dz < 0) dfactor -= 1.0; if (dfactor > MAXSMALLINT) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dz); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dz); int factor = static_cast(dfactor); dz -= zprd * factor; dy -= yz * factor; dx -= xz * factor; } if (yperiodic) { - double dfactor = dy/yprd + 0.5; + double dfactor = dy / yprd + 0.5; if (dy < 0) dfactor -= 1.0; if (dfactor > MAXSMALLINT) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dy); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dy); int factor = static_cast(dfactor); dy -= yprd * factor; dx -= xy * factor; } if (xperiodic) { - double dfactor = dx/xprd + 0.5; + double dfactor = dx / xprd + 0.5; if (dx < 0) dfactor -= 1.0; if (dfactor > MAXSMALLINT) - error->one(FLERR, "Atoms have moved too far apart ({}) for minimum image\n", dx); + error->one(file, line, "Atoms have moved too far apart ({}) for minimum image\n", dx); dx -= xprd * static_cast(dfactor); } } } +// clang-format off /* ---------------------------------------------------------------------- return local index of atom J or any of its images that is closest to atom I if J is not a valid index like -1, just return it diff --git a/src/domain.h b/src/domain.h index 9c745f05b8..f2e6c0632e 100644 --- a/src/domain.h +++ b/src/domain.h @@ -127,10 +127,16 @@ class Domain : protected Pointers { void image_check(); void box_too_small_check(); void subbox_too_small_check(double); - void minimum_image(double &, double &, double &) const; - void minimum_image(double *delta) const { minimum_image(delta[0], delta[1], delta[2]); } - void minimum_image_big(double &, double &, double &) const; - void minimum_image_big(double *delta) const { minimum_image_big(delta[0], delta[1], delta[2]); } + void minimum_image(const std::string &, int, double &, double &, double &) const; + void minimum_image(const std::string &file, int line, double *delta) const + { + minimum_image(file, line, delta[0], delta[1], delta[2]); + } + void minimum_image_big(const std::string &, int, double &, double &, double &) const; + void minimum_image_big(const std::string &file, int line, double *delta) const + { + minimum_image_big(file, line, delta[0], delta[1], delta[2]); + } int closest_image(int, int); int closest_image(const double *const, int); void closest_image(const double *const, const double *const, double *const); @@ -185,7 +191,7 @@ class Domain : protected Pointers { // but is a far-away image that should be treated as an unbonded neighbor // inline since called from neighbor build inner loop - inline int minimum_image_check(double dx, double dy, double dz) + inline int minimum_image_check(double dx, double dy, double dz) const { if (xperiodic && fabs(dx) > xprd_half) return 1; if (yperiodic && fabs(dy) > yprd_half) return 1; diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp index 56836b8446..273b39525c 100644 --- a/src/dump_custom.cpp +++ b/src/dump_custom.cpp @@ -78,8 +78,8 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) : int ioffset = 5; expand = 0; - nfield = nargnew = utils::expand_args(FLERR,narg-5,&arg[5],1,earg,lmp); - if (earg != &arg[5]) expand = 1; + nfield = nargnew = utils::expand_args(FLERR,narg-ioffset,&arg[ioffset],1,earg,lmp); + if (earg != &arg[ioffset]) expand = 1; // allocate field vectors diff --git a/src/dump_image.cpp b/src/dump_image.cpp index 609223a9ec..83f4999f43 100644 --- a/src/dump_image.cpp +++ b/src/dump_image.cpp @@ -1245,7 +1245,7 @@ void DumpImage::create_image() delz = x[atom2][2] - x[atom1][2]; if (bcolor == ATOM || domain->minimum_image_check(delx,dely,delz)) { - domain->minimum_image(delx,dely,delz); + domain->minimum_image(FLERR, delx,dely,delz); xmid[0] = x[atom1][0] + 0.5*delx; xmid[1] = x[atom1][1] + 0.5*dely; xmid[2] = x[atom1][2] + 0.5*delz; diff --git a/src/fix_adapt.cpp b/src/fix_adapt.cpp index eb7125caf7..6af96ae29e 100644 --- a/src/fix_adapt.cpp +++ b/src/fix_adapt.cpp @@ -19,6 +19,8 @@ #include "atom.h" #include "bond.h" #include "bond_hybrid.h" +#include "dihedral.h" +#include "dihedral_hybrid.h" #include "domain.h" #include "error.h" #include "fix_store_atom.h" @@ -43,14 +45,14 @@ using namespace LAMMPS_NS; using namespace FixConst; using namespace MathConst; -enum{PAIR, KSPACE, ATOM, BOND, ANGLE, IMPROPER}; +enum{PAIR, KSPACE, ATOM, BOND, ANGLE, DIHEDRAL, IMPROPER}; enum{DIAMETER, CHARGE}; /* ---------------------------------------------------------------------- */ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), nadapt(0), anypair(0), anybond(0), anyangle(0), - anyimproper(0), id_fix_diam(nullptr), id_fix_chg(nullptr), adapt(nullptr) + anydihedral(0), anyimproper(0), id_fix_diam(nullptr), id_fix_chg(nullptr), adapt(nullptr) { if (narg < 5) utils::missing_cmd_args(FLERR,"fix adapt", error); nevery = utils::inumeric(FLERR,arg[3],false,lmp); @@ -85,6 +87,10 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : if (iarg+5 > narg) utils::missing_cmd_args(FLERR,"fix adapt angle", error); nadapt++; iarg += 5; + } else if (strcmp(arg[iarg],"dihedral") == 0) { + if (iarg+5 > narg) utils::missing_cmd_args(FLERR,"fix adapt dihedral", error); + nadapt++; + iarg += 5; } else if (strcmp(arg[iarg],"improper") == 0) { if (iarg+5 > narg) utils::missing_cmd_args(FLERR,"fix adapt improper", error); nadapt++; @@ -155,6 +161,19 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : nadapt++; iarg += 5; + } else if (strcmp(arg[iarg],"dihedral") == 0) { + adapt[nadapt].which = DIHEDRAL; + adapt[nadapt].dihedral = nullptr; + adapt[nadapt].dstyle = utils::strdup(arg[iarg+1]); + adapt[nadapt].dparam = utils::strdup(arg[iarg+2]); + utils::bounds_typelabel(FLERR, arg[iarg+3], 1, atom->ndihedraltypes, + adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::DIHEDRAL); + if (utils::strmatch(arg[iarg+4],"^v_")) { + adapt[nadapt].var = utils::strdup(arg[iarg+4]+2); + } else error->all(FLERR,"Argument #{} must be variable not {}", iarg+5, arg[iarg+4]); + nadapt++; + iarg += 5; + } else if (strcmp(arg[iarg],"improper") == 0) { adapt[nadapt].which = IMPROPER; adapt[nadapt].improper = nullptr; @@ -246,6 +265,12 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : // allocate improper style arrays: + n = atom->ndihedraltypes; + for (int m = 0; m < nadapt; ++m) + if (adapt[m].which == DIHEDRAL) memory->create(adapt[m].vector_orig,n+1,"adapt:vector_orig"); + + // allocate improper style arrays: + n = atom->nimpropertypes; for (int m = 0; m < nadapt; ++m) if (adapt[m].which == IMPROPER) memory->create(adapt[m].vector_orig,n+1,"adapt:vector_orig"); @@ -270,6 +295,10 @@ FixAdapt::~FixAdapt() delete[] adapt[m].astyle; delete[] adapt[m].aparam; memory->destroy(adapt[m].vector_orig); + } else if (adapt[m].which == DIHEDRAL) { + delete[] adapt[m].dstyle; + delete[] adapt[m].dparam; + memory->destroy(adapt[m].vector_orig); } else if (adapt[m].which == IMPROPER) { delete[] adapt[m].istyle; delete[] adapt[m].iparam; @@ -368,6 +397,7 @@ void FixAdapt::init() anypair = 0; anybond = 0; anyangle = 0; + anydihedral = 0; anyimproper = 0; for (int m = 0; m < nadapt; m++) { @@ -509,6 +539,40 @@ void FixAdapt::init() delete[] astyle; + } else if (ad->which == DIHEDRAL) { + ad->dihedral = nullptr; + anydihedral = 1; + + char *dstyle = utils::strdup(ad->dstyle); + if (lmp->suffix_enable) + ad->dihedral = force->dihedral_match(fmt::format("{}/{}",dstyle,lmp->suffix)); + + if (ad->dihedral == nullptr) ad->dihedral = force->dihedral_match(dstyle); + if (ad->dihedral == nullptr ) + error->all(FLERR,"Fix adapt dihedral style {} does not exist", dstyle); + + void *ptr = ad->dihedral->extract(ad->dparam,ad->ddim); + + if (ptr == nullptr) + error->all(FLERR,"Fix adapt dihedral style parameter {} not supported", ad->dparam); + + // for dihedral styles, use a vector + + if (ad->ddim == 1) ad->vector = (double *) ptr; + + if (utils::strmatch(force->dihedral_style,"^hybrid")) { + auto dihedral = dynamic_cast(force->dihedral); + if (dihedral) { + for (i = ad->ilo; i <= ad->ihi; i++) { + if (!dihedral->check_itype(i,dstyle)) + error->all(FLERR,"Fix adapt type dihedral range is not valid " + "for dihedral hybrid sub-style {}", dstyle); + } + } + } + + delete[] dstyle; + } else if (ad->which == IMPROPER) { ad->improper = nullptr; anyimproper = 1; @@ -569,7 +633,7 @@ void FixAdapt::init() if (restart_reset) restart_reset = 0; - // make copy of original pair/bond/angle/improper array values + // make copy of original pair/bond/angle/dihedral/improper array values for (int m = 0; m < nadapt; m++) { Adapt *ad = &adapt[m]; @@ -588,6 +652,10 @@ void FixAdapt::init() for (i = ad->ilo; i <= ad->ihi; ++i ) ad->vector_orig[i] = ad->vector[i]; + } else if (ad->which == DIHEDRAL && ad->ddim == 1) { + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector_orig[i] = ad->vector[i]; + } else if (ad->which == IMPROPER && ad->idim == 1) { for (i = ad->ilo; i <= ad->ihi; ++i ) ad->vector_orig[i] = ad->vector[i]; @@ -710,6 +778,18 @@ void FixAdapt::change_settings() ad->vector[i] = value; } + // set dihedral type array values: + + } else if (ad->which == DIHEDRAL) { + if (ad->ddim == 1) { + if (scaleflag) + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector[i] = value*ad->vector_orig[i]; + else + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector[i] = value; + } + // set improper type array values: } else if (ad->which == IMPROPER) { @@ -797,6 +877,7 @@ void FixAdapt::change_settings() if (anypair) force->pair->reinit(); if (anybond) force->bond->reinit(); if (anyangle) force->angle->reinit(); + if (anydihedral) force->dihedral->reinit(); if (anyimproper) force->improper->reinit(); // reset KSpace charges if charges have changed @@ -832,6 +913,12 @@ void FixAdapt::restore_settings() ad->vector[i] = ad->vector_orig[i]; } + } else if (ad->which == DIHEDRAL) { + if (ad->ddim == 1) { + for (int i = ad->ilo; i <= ad->ihi; i++) + ad->vector[i] = ad->vector_orig[i]; + } + } else if (ad->which == IMPROPER) { if (ad->idim == 1) { for (int i = ad->ilo; i <= ad->ihi; i++) @@ -878,6 +965,7 @@ void FixAdapt::restore_settings() if (anypair) force->pair->reinit(); if (anybond) force->bond->reinit(); if (anyangle) force->angle->reinit(); + if (anydihedral) force->dihedral->reinit(); if (anyimproper) force->improper->reinit(); if (chgflag && force->kspace) force->kspace->qsum_qsq(); } diff --git a/src/fix_adapt.h b/src/fix_adapt.h index 9f064a163e..5ed6559ef1 100644 --- a/src/fix_adapt.h +++ b/src/fix_adapt.h @@ -44,7 +44,7 @@ class FixAdapt : public Fix { private: int nadapt, resetflag, scaleflag, massflag; - int anypair, anybond, anyangle, anyimproper; + int anypair, anybond, anyangle, anydihedral, anyimproper; int nlevels_respa; char *id_fix_diam, *id_fix_chg; class FixStoreAtom *fix_diam, *fix_chg; @@ -57,9 +57,10 @@ class FixAdapt : public Fix { char *pstyle, *pparam; char *bstyle, *bparam; char *astyle, *aparam; + char *dstyle, *dparam; char *istyle, *iparam; int ilo, ihi, jlo, jhi; - int pdim, bdim, adim, idim; + int pdim, bdim, adim, ddim, idim; double *scalar, scalar_orig; double *vector, *vector_orig; double **array, **array_orig; @@ -67,6 +68,7 @@ class FixAdapt : public Fix { class Pair *pair; class Bond *bond; class Angle *angle; + class Dihedral *dihedral; class Improper *improper; }; diff --git a/src/fix_deposit.cpp b/src/fix_deposit.cpp index c9d09fa8b7..46a8adad7b 100644 --- a/src/fix_deposit.cpp +++ b/src/fix_deposit.cpp @@ -401,7 +401,7 @@ void FixDeposit::pre_exchange() delx = coord[0] - x[i][0]; dely = coord[1] - x[i][1]; delz = 0.0; - domain->minimum_image(delx,dely,delz); + domain->minimum_image(FLERR, delx,dely,delz); if (dimension == 2) rsq = delx*delx; else rsq = delx*delx + dely*dely; if (rsq > deltasq) continue; @@ -476,7 +476,7 @@ void FixDeposit::pre_exchange() delx = coords[m][0] - x[i][0]; dely = coords[m][1] - x[i][1]; delz = coords[m][2] - x[i][2]; - domain->minimum_image(delx,dely,delz); + domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; if (rsq < nearsq) flag = 1; } diff --git a/src/fix_indent.cpp b/src/fix_indent.cpp index 05aaf321a7..608708ce6d 100644 --- a/src/fix_indent.cpp +++ b/src/fix_indent.cpp @@ -273,7 +273,7 @@ void FixIndent::post_force(int /*vflag*/) delx = x[i][0] - ctr[0]; dely = x[i][1] - ctr[1]; delz = x[i][2] - ctr[2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); r = sqrt(delx * delx + dely * dely + delz * delz); if (side == OUTSIDE) { dr = r - radius; @@ -313,7 +313,7 @@ void FixIndent::post_force(int /*vflag*/) if (mask[i] & groupbit) { double del[3] = {x[i][0] - ctr[0], x[i][1] - ctr[1], x[i][2] - ctr[2]}; del[cdim] = 0; - domain->minimum_image(del[0], del[1], del[2]); + domain->minimum_image(FLERR, del[0], del[1], del[2]); r = sqrt(del[0] * del[0] + del[1] * del[1] + del[2] * del[2]); if (side == OUTSIDE) { dr = r - radius; @@ -360,7 +360,7 @@ void FixIndent::post_force(int /*vflag*/) delx = x[i][0] - ctr[0]; dely = x[i][1] - ctr[1]; delz = x[i][2] - ctr[2]; - domain->minimum_image(delx, dely, delz); + domain->minimum_image(FLERR, delx, dely, delz); double x0[3] = {delx + ctr[0], dely + ctr[1], delz + ctr[2]}; r = sqrt(delx * delx + dely * dely + delz * delz); diff --git a/src/fix_langevin.cpp b/src/fix_langevin.cpp index 60a55bbbb4..5f754b6d2b 100644 --- a/src/fix_langevin.cpp +++ b/src/fix_langevin.cpp @@ -170,6 +170,9 @@ FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) : // no need to set peratom_flag, b/c data is for internal use only if (gjfflag) { + if (comm->me == 0) + error->warning(FLERR, "The GJF formulation in fix {} is deprecated and will be removed soon. " + "\nPlease use fix gjf instead: https://docs.lammps.org/fix_gjf.html", style); FixLangevin::grow_arrays(atom->nmax); atom->add_callback(Atom::GROW); diff --git a/src/fix_minimize.cpp b/src/fix_minimize.cpp index e011c79d9d..5b537303dd 100644 --- a/src/fix_minimize.cpp +++ b/src/fix_minimize.cpp @@ -119,7 +119,7 @@ void FixMinimize::reset_coords() dx = dx0 = x[i][0] - x0[n]; dy = dy0 = x[i][1] - x0[n+1]; dz = dz0 = x[i][2] - x0[n+2]; - domain->minimum_image(dx,dy,dz); + domain->minimum_image(FLERR, dx,dy,dz); if (dx != dx0) x0[n] = x[i][0] - dx; if (dy != dy0) x0[n+1] = x[i][1] - dy; if (dz != dz0) x0[n+2] = x[i][2] - dz; diff --git a/src/fix_neigh_history.cpp b/src/fix_neigh_history.cpp index cdf8fb0527..911dee2984 100644 --- a/src/fix_neigh_history.cpp +++ b/src/fix_neigh_history.cpp @@ -286,7 +286,7 @@ void FixNeighHistory::pre_exchange_onesided() partner[i] = ipage_atom->get(n); valuepartner[i] = dpage_atom->get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } // 2nd loop over neighbor list, I = sphere, J = tri @@ -394,7 +394,7 @@ void FixNeighHistory::pre_exchange_newton() partner[i] = ipage_atom->get(n); valuepartner[i] = dpage_atom->get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) { - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -403,7 +403,7 @@ void FixNeighHistory::pre_exchange_newton() partner[i] = ipage_atom->get(n); valuepartner[i] = dpage_atom->get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) { - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -519,7 +519,7 @@ void FixNeighHistory::pre_exchange_no_newton() partner[i] = ipage_atom->get(n); valuepartner[i] = dpage_atom->get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } // 2nd loop over neighbor list diff --git a/src/fix_restrain.cpp b/src/fix_restrain.cpp index 9b157ee90f..8900d68a3c 100644 --- a/src/fix_restrain.cpp +++ b/src/fix_restrain.cpp @@ -284,7 +284,7 @@ void FixRestrain::restrain_bond(int m) delx = x[i1][0] - x[i2][0]; dely = x[i1][1] - x[i2][1]; delz = x[i1][2] - x[i2][2]; - domain->minimum_image(delx,dely,delz); + domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; r = sqrt(rsq); @@ -357,7 +357,7 @@ void FixRestrain::restrain_lbound(int m) delx = x[i1][0] - x[i2][0]; dely = x[i1][1] - x[i2][1]; delz = x[i1][2] - x[i2][2]; - domain->minimum_image(delx,dely,delz); + domain->minimum_image(FLERR, delx,dely,delz); rsq = delx*delx + dely*dely + delz*delz; r = sqrt(rsq); @@ -442,7 +442,7 @@ void FixRestrain::restrain_angle(int m) delx1 = x[i1][0] - x[i2][0]; dely1 = x[i1][1] - x[i2][1]; delz1 = x[i1][2] - x[i2][2]; - domain->minimum_image(delx1,dely1,delz1); + domain->minimum_image(FLERR, delx1,dely1,delz1); rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1; r1 = sqrt(rsq1); @@ -452,7 +452,7 @@ void FixRestrain::restrain_angle(int m) delx2 = x[i3][0] - x[i2][0]; dely2 = x[i3][1] - x[i2][1]; delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); + domain->minimum_image(FLERR, delx2,dely2,delz2); rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2; r2 = sqrt(rsq2); @@ -564,26 +564,26 @@ void FixRestrain::restrain_dihedral(int m) vb1x = x[i1][0] - x[i2][0]; vb1y = x[i1][1] - x[i2][1]; vb1z = x[i1][2] - x[i2][2]; - domain->minimum_image(vb1x,vb1y,vb1z); + domain->minimum_image(FLERR, vb1x,vb1y,vb1z); // 2nd bond vb2x = x[i3][0] - x[i2][0]; vb2y = x[i3][1] - x[i2][1]; vb2z = x[i3][2] - x[i2][2]; - domain->minimum_image(vb2x,vb2y,vb2z); + domain->minimum_image(FLERR, vb2x,vb2y,vb2z); vb2xm = -vb2x; vb2ym = -vb2y; vb2zm = -vb2z; - domain->minimum_image(vb2xm,vb2ym,vb2zm); + domain->minimum_image(FLERR, vb2xm,vb2ym,vb2zm); // 3rd bond vb3x = x[i4][0] - x[i3][0]; vb3y = x[i4][1] - x[i3][1]; vb3z = x[i4][2] - x[i3][2]; - domain->minimum_image(vb3x,vb3y,vb3z); + domain->minimum_image(FLERR, vb3x,vb3y,vb3z); ax = vb1y*vb2zm - vb1z*vb2ym; ay = vb1z*vb2xm - vb1x*vb2zm; diff --git a/src/fix_set.cpp b/src/fix_set.cpp new file mode 100644 index 0000000000..ac4400c1a9 --- /dev/null +++ b/src/fix_set.cpp @@ -0,0 +1,85 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +#include "fix_set.h" + +#include "atom.h" +#include "error.h" +#include "set.h" +#include "update.h" + +using namespace LAMMPS_NS; +using namespace FixConst; + +enum{SETCOMMAND,FIXSET}; // also used in Set class + +/* ---------------------------------------------------------------------- */ + +FixSet::FixSet(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) +{ + if (narg < 8) error->all(FLERR, 1, "Illegal fix set command: need at least eight arguments"); + + nevery = utils::inumeric(FLERR, arg[3], false, lmp); + if (nevery <= 0) error->all(FLERR, "Fix {} Nevery must be > 0", style); + + reneighbor = utils::inumeric(FLERR, arg[4], false, lmp); + if (reneighbor < 0 || reneighbor > 1) + error->all(FLERR, "Fix {} rnflag must be 0/1", style); + + // create instance of Set class + + set = new Set(lmp); + + // pass remaining args to Set class + // only keywords which use per-atom variables are currently allowed + // NOTE: could also allow when set style = region, + // since atoms may move in/out of regions + + set->process_args(FIXSET,narg-5,&arg[5]); +} + +/* ---------------------------------------------------------------------- */ + +FixSet::~FixSet() +{ + delete set; +} + +/* ---------------------------------------------------------------------- */ + +int FixSet::setmask() +{ + int mask = 0; + mask |= END_OF_STEP; + return mask; +} + +/* ---------------------------------------------------------------------- + use the Set instance to update per-atom properties + NOTE: could return count of updated atoms from Set for use as fix output +---------------------------------------------------------------------- */ + +void FixSet::end_of_step() +{ + // select which atoms to act on + + set->selection(atom->nlocal); + + // loop over list of actions to reset atom attributes + + set->invoke_actions(); + + // trigger reneighboring on next timestep if requested + + if (reneighbor) next_reneighbor = update->ntimestep + 1; +} diff --git a/src/fix_set.h b/src/fix_set.h new file mode 100644 index 0000000000..7328ebd144 --- /dev/null +++ b/src/fix_set.h @@ -0,0 +1,43 @@ +/* -*- 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 FIX_CLASS +// clang-format off +FixStyle(set,FixSet); +// clang-format on +#else + +#ifndef LMP_FIX_SET_H +#define LMP_FIX_SET_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixSet : public Fix { + public: + FixSet(class LAMMPS *, int, char **); + ~FixSet() override; + int setmask() override; + void end_of_step() override; + + private: + int reneighbor; + + class Set *set; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/fmt/core.h b/src/fmt/core.h index 6a53b8c52c..d715fe18ac 100644 --- a/src/fmt/core.h +++ b/src/fmt/core.h @@ -219,6 +219,9 @@ # define FMT_UNICODE !FMT_MSC_VERSION #endif +// LAMMPS customization: avoid problems with consteval altogether +#define FMT_CONSTEVAL + #ifndef FMT_CONSTEVAL # if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \ (!defined(__apple_build_version__) || \ diff --git a/src/info.cpp b/src/info.cpp index 57930f9d77..39ad7b2788 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -34,6 +34,7 @@ #include "group.h" #include "improper.h" #include "input.h" +#include "json.h" #include "lmpfftsettings.h" #include "modify.h" #include "neighbor.h" @@ -43,7 +44,9 @@ #include "region.h" #include "update.h" #include "variable.h" +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR #include "fmt/chrono.h" +#endif #include #include @@ -269,8 +272,16 @@ void Info::command(int narg, char **arg) if (out == nullptr) return; fputs("\nInfo-Info-Info-Info-Info-Info-Info-Info-Info-Info-Info\n",out); +#if defined(FMT_STATIC_THOUSANDS_SEPARATOR) + { + time_t tv = time(nullptr); + struct tm *now = localtime(&tv); + utils::print(out, "Printed on {}", asctime(now)); + } +#else std::tm now = fmt::localtime(std::time(nullptr)); utils::print(out,"Printed on {}", std::asctime(&now)); +#endif if (flags & CONFIG) { utils::print(out,"\nLAMMPS version: {} / {}\n", lmp->version, lmp->num_ver); @@ -291,6 +302,7 @@ void Info::command(int narg, char **arg) utils::print(out,"\nCompiler: {} with {}\nC++ standard: {}\n", platform::compiler_info(),platform::openmp_standard(),platform::cxx_standard()); fputs(get_fmt_info().c_str(), out); + fputs(get_json_info().c_str(), out); fputs("\nActive compile time flags:\n\n",out); if (has_gzip_support()) fputs("-DLAMMPS_GZIP\n",out); @@ -1320,6 +1332,16 @@ std::string Info::get_fmt_info() /* ---------------------------------------------------------------------- */ +std::string Info::get_json_info() +{ + return fmt::format("Embedded JSON class version: {}.{}.{}\n", + NLOHMANN_JSON_VERSION_MAJOR, + NLOHMANN_JSON_VERSION_MINOR, + NLOHMANN_JSON_VERSION_PATCH); +} + +/* ---------------------------------------------------------------------- */ + void Info::get_memory_info(double *meminfo) { double bytes = 0; diff --git a/src/info.h b/src/info.h index 77566b0dcc..8ef38b3c9d 100644 --- a/src/info.h +++ b/src/info.h @@ -50,6 +50,7 @@ class Info : public Command { const std::string &); static std::string get_fft_info(); static std::string get_fmt_info(); + static std::string get_json_info(); static bool has_gpu_device(); static std::string get_gpu_device_info(); static std::string get_accelerator_info(const std::string &pkg = ""); diff --git a/src/input.cpp b/src/input.cpp index bc9a55052c..ae2c9f0874 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -585,7 +585,6 @@ void Input::substitute(char *&str, char *&str2, int &max, int &max2, int flag) int i,n,paren_count,nchars; char immediate[256]; char *var,*value,*beyond; - int quoteflag = 0; char *ptrmatch; char *ptr = str; @@ -599,7 +598,7 @@ void Input::substitute(char *&str, char *&str2, int &max, int &max2, int flag) // variable substitution - if (*ptr == '$' && !quoteflag) { + if (*ptr == '$') { // value = ptr to expanded variable // variable name between curly braces, e.g. ${a} diff --git a/src/json.h b/src/json.h new file mode 100644 index 0000000000..2f364b445e --- /dev/null +++ b/src/json.h @@ -0,0 +1,25 @@ +/* -*- 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_JSON_H +#define LMP_JSON_H + +// wrapper around including the JSON parsing and writing class +// Do NOT include in any header file + +#include "nlohmann/json.hpp" + +namespace LAMMPS_NS { +using json = ::nlohmann_lmp::json; +} +#endif diff --git a/src/kspace.cpp b/src/kspace.cpp index 2de25d6e86..8ab7a11eda 100644 --- a/src/kspace.cpp +++ b/src/kspace.cpp @@ -181,9 +181,9 @@ void KSpace::triclinic_check() /* ---------------------------------------------------------------------- */ -void KSpace::compute_dummy(int eflag, int vflag) +void KSpace::compute_dummy(int eflag, int vflag, int alloc) { - ev_init(eflag,vflag); + ev_init(eflag,vflag,alloc); } /* ---------------------------------------------------------------------- diff --git a/src/kspace.h b/src/kspace.h index 86e9a29bd2..0a3db05ee7 100644 --- a/src/kspace.h +++ b/src/kspace.h @@ -141,7 +141,7 @@ class KSpace : protected Pointers { void triclinic_check(); void modify_params(int, char **); void *extract(const char *); - void compute_dummy(int, int); + void compute_dummy(int eflag, int vflag, int alloc = 1); // triclinic diff --git a/src/lammps.cpp b/src/lammps.cpp index 72a1b67fb2..c891cea14d 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -528,8 +528,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : if (helpflag == 0) { universe->ulogfile = fopen("log.lammps","w"); if (universe->ulogfile == nullptr) - error->universe_warn(FLERR,"Cannot open log.lammps for writing: " - + utils::getsyserror()); + error->universe_warn(FLERR,"Cannot open log.lammps for writing: " + utils::getsyserror()); } } else if (strcmp(arg[logflag],"none") == 0) universe->ulogfile = nullptr; @@ -661,8 +660,8 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : } if ((me == 0) && (!helpflag)) - utils::logmesg(this,"LAMMPS ({}{})\nProcessor partition = {}\n", version, - update_string, universe->iworld); + utils::logmesg(this,"LAMMPS ({}{})\nProcessor partition = {}\n", version, update_string, + universe->iworld); } // check consistency of datatype settings in lmptype.h @@ -1457,6 +1456,7 @@ void LAMMPS::print_config(FILE *fp) platform::compiler_info(),platform::openmp_standard(), platform::cxx_standard()); fputs(Info::get_fmt_info().c_str(),fp); + fputs(Info::get_json_info().c_str(),fp); int major,minor; std::string infobuf = platform::mpi_info(major,minor); diff --git a/src/library.cpp b/src/library.cpp index 01793612be..a8acbade52 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -24,6 +24,7 @@ #include "atom.h" #include "atom_vec.h" #include "comm.h" +#include "command.h" #include "compute.h" #include "domain.h" #include "dump.h" @@ -42,6 +43,7 @@ #include "molecule.h" #include "neigh_list.h" #include "neighbor.h" +#include "neigh_request.h" #include "output.h" #include "pair.h" #if defined(LMP_PLUGIN) @@ -1253,6 +1255,7 @@ be called without a valid LAMMPS object handle (it is ignored). * :ref:`Image masks ` * :ref:`System status ` * :ref:`System sizes ` +* :ref:`Neighbor list settings ` * :ref:`Atom style flags ` .. _extract_integer_sizes: @@ -1384,6 +1387,16 @@ internally by the :doc:`Fortran interface ` and are not likely to be us - number of dihedral types * - nimpropertypes - number of improper types + * - bond_per_atom + - size of per-atom bond data arrays + * - angle_per_atom + - size of per-atom angle data arrays + * - dihedral_per_atom + - size of per-atom dihedral data arrays + * - improper_per_atom + - size of per-atom improper data arrays + * - maxspecial + - size of per-atom special data array * - nellipsoids - number of atoms that have ellipsoid data * - nlines @@ -1393,6 +1406,31 @@ internally by the :doc:`Fortran interface ` and are not likely to be us * - nbodies - number of atoms that have body data (see :doc:`the Body particle HowTo `) +.. _extract_neighbor_settings: + +**Neighbor list settings** + +.. list-table:: + :header-rows: 1 + :widths: 17 83 + + * - neigh_every + - neighbor lists are rebuild every this many steps + * - neigh_delay + - neighbor lists are rebuild delayed this many steps + * - neigh_dist_check + - 0 if always rebuild, 1 rebuild after 1/2 skin + * - neigh_ago + - neighbor lists were rebuilt this many steps ago + * - nbondlist + - number of entries in bondlist (get list with :ref:`lammps_extract_global() `) + * - nanglelist + - number of entries in anglelist (get list with :ref:`lammps_extract_global() `) + * - ndihedrallist + - number of entries in dihedrallist (get list with :ref:`lammps_extract_global() `) + * - nimproperlist + - number of entries in improperlist (get list with :ref:`lammps_extract_global() `) + .. _extract_atom_flags: **Atom style flags** @@ -1477,11 +1515,25 @@ int lammps_extract_setting(void *handle, const char *keyword) if (strcmp(keyword,"nangletypes") == 0) return lmp->atom->nangletypes; if (strcmp(keyword,"ndihedraltypes") == 0) return lmp->atom->ndihedraltypes; if (strcmp(keyword,"nimpropertypes") == 0) return lmp->atom->nimpropertypes; + if (strcmp(keyword,"bond_per_atom") == 0) return lmp->atom->bond_per_atom; + if (strcmp(keyword,"angle_per_atom") == 0) return lmp->atom->angle_per_atom; + if (strcmp(keyword,"dihedral_per_atom") == 0) return lmp->atom->dihedral_per_atom; + if (strcmp(keyword,"improper_per_atom") == 0) return lmp->atom->improper_per_atom; + if (strcmp(keyword,"maxspecial") == 0) return lmp->atom->maxspecial; if (strcmp(keyword,"nellipsoids") == 0) return lmp->atom->nellipsoids; if (strcmp(keyword,"nlines") == 0) return lmp->atom->nlines; if (strcmp(keyword,"ntris") == 0) return lmp->atom->ntris; if (strcmp(keyword,"nbodies") == 0) return lmp->atom->nbodies; + if (strcmp(keyword,"neigh_every") == 0) return lmp->neighbor->every; + if (strcmp(keyword,"neigh_delay") == 0) return lmp->neighbor->delay; + if (strcmp(keyword,"neigh_dist_check") == 0) return lmp->neighbor->dist_check; + if (strcmp(keyword,"neigh_ago") == 0) return lmp->neighbor->ago; + if (strcmp(keyword,"nbondlist") == 0) return lmp->neighbor->nbondlist; + if (strcmp(keyword,"nanglelist") == 0) return lmp->neighbor->nanglelist; + if (strcmp(keyword,"ndihedrallist") == 0) return lmp->neighbor->ndihedrallist; + if (strcmp(keyword,"nimproperlist") == 0) return lmp->neighbor->nimproperlist; + if (strcmp(keyword,"molecule_flag") == 0) return lmp->atom->molecule_flag; if (strcmp(keyword,"q_flag") == 0) return lmp->atom->q_flag; if (strcmp(keyword,"mu_flag") == 0) return lmp->atom->mu_flag; @@ -1565,6 +1617,16 @@ int lammps_extract_global_datatype(void * /*handle*/, const char *name) if (strcmp(name,"special_lj") == 0) return LAMMPS_DOUBLE; if (strcmp(name,"special_coul") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"neigh_bondlist") == 0) return LAMMPS_INT_2D; + if (strcmp(name,"neigh_anglelist") == 0) return LAMMPS_INT_2D; + if (strcmp(name,"neigh_dihedrallist") == 0) return LAMMPS_INT_2D; + if (strcmp(name,"neigh_improperlist") == 0) return LAMMPS_INT_2D; + + if (strcmp(name,"eflag_global") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"eflag_atom") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"vflag_global") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"vflag_atom") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"map_style") == 0) return LAMMPS_INT; #if defined(LAMMPS_BIGBIG) if (strcmp(name,"map_tag_max") == 0) return LAMMPS_BIGINT; @@ -1649,6 +1711,8 @@ report the "native" data type. The following tables are provided: * :ref:`Timestep settings ` * :ref:`Simulation box settings ` * :ref:`System property settings ` +* :ref:`Neighbor topology data ` +* :ref:`Energy and virial tally settings ` * :ref:`Git revision and version settings ` * :ref:`Unit settings ` @@ -1701,6 +1765,18 @@ report the "native" data type. The following tables are provided: - Type - Length - Description + * - boxlo + - double + - 3 + - lower box boundaries in x-, y-, and z-direction; see :doc:`create_box`. + * - boxhi + - double + - 3 + - lower box boundaries in x-, y-, and z-direction; see :doc:`create_box`. + * - boxxlo + - double + - 1 + - lower box boundary in x-direction; see :doc:`create_box`. * - boxxhi - double - 1 @@ -1724,19 +1800,19 @@ report the "native" data type. The following tables are provided: * - sublo - double - 3 - - subbox lower boundaries + - subbox lower boundaries in x-, y-, and z-direction * - subhi - double - 3 - - subbox upper boundaries + - subbox upper boundaries in x-, y-, and z-direction * - sublo_lambda - double - 3 - - subbox lower boundaries in fractional coordinates (for triclinic cells) + - subbox lower boundaries in fractional coordinates (for triclinic cells only) * - subhi_lambda - double - 3 - - subbox upper boundaries in fractional coordinates (for triclinic cells) + - subbox upper boundaries in fractional coordinates (for triclinic cells only) * - periodicity - int - 3 @@ -1786,10 +1862,10 @@ report the "native" data type. The following tables are provided: - Type - Length - Description - * - ntypes - - int + * - natoms + - bigint - 1 - - number of atom types + - total number of atoms in the simulation. * - nbonds - bigint - 1 @@ -1806,10 +1882,6 @@ report the "native" data type. The following tables are provided: - bigint - 1 - total number of impropers in the simulation. - * - natoms - - bigint - - 1 - - total number of atoms in the simulation. * - nlocal - int - 1 @@ -1822,6 +1894,10 @@ report the "native" data type. The following tables are provided: - int - 1 - maximum of nlocal+nghost across all MPI ranks (for per-atom data array size). + * - ntypes + - int + - 1 + - number of atom types * - special_lj - double - 4 @@ -1883,6 +1959,66 @@ report the "native" data type. The following tables are provided: - 1 - string with the current KSpace style. +.. _extract_neighbor_lists: + +**Neighbor topology data** + +Get length of lists with :ref:`lammps_extract_setting() `. + +.. list-table:: + :header-rows: 1 + :widths: 20 12 16 52 + + * - Name + - Type + - Length + - Description + * - neigh_bondlist + - 2d int + - nbondlist + - list of bonds (atom1, atom2, type) + * - neigh_anglelist + - 2d int + - nanglelist + - list of angles (atom1, atom2, atom3, type) + * - neigh_dihedrallist + - 2d int + - ndihedrallist + - list of dihedrals (atom1, atom2, atom3, atom4, type) + * - neigh_improperlist + - 2d int + - nimproperlist + - list of impropers (atom1, atom2, atom3, atom4, type) + +.. _extract_tally_settings: + +**Energy and virial tally settings** + +.. list-table:: + :header-rows: 1 + :widths: 20 12 16 52 + + * - Name + - Type + - Length + - Description + * - eflag_global + - bigint + - 1 + - timestep global energy is tallied on + * - eflag_atom + - bigint + - 1 + - timestep per-atom energy is tallied on + * - vflag_global + - bigint + - 1 + - timestep global virial is tallied on + * - vflag_atom + - bigint + - 1 + - timestep per-atom virial is tallied on + .. _extract_git_settings: **Git revision and version settings** @@ -2080,7 +2216,6 @@ void *lammps_extract_global(void *handle, const char *name) return (void *) &lmp->comm->procgrid; if (strcmp(name,"natoms") == 0) return (void *) &lmp->atom->natoms; - if (strcmp(name,"ntypes") == 0) return (void *) &lmp->atom->ntypes; if (strcmp(name,"nbonds") == 0) return (void *) &lmp->atom->nbonds; if (strcmp(name,"nangles") == 0) return (void *) &lmp->atom->nangles; if (strcmp(name,"ndihedrals") == 0) return (void *) &lmp->atom->ndihedrals; @@ -2088,11 +2223,22 @@ void *lammps_extract_global(void *handle, const char *name) if (strcmp(name,"nlocal") == 0) return (void *) &lmp->atom->nlocal; if (strcmp(name,"nghost") == 0) return (void *) &lmp->atom->nghost; if (strcmp(name,"nmax") == 0) return (void *) &lmp->atom->nmax; + if (strcmp(name,"ntypes") == 0) return (void *) &lmp->atom->ntypes; if (strcmp(name,"special_lj") == 0) return (void *) lmp->force->special_lj; if (strcmp(name,"special_coul") == 0) return (void *) lmp->force->special_coul; if (strcmp(name,"q_flag") == 0) return (void *) &lmp->atom->q_flag; + if (strcmp(name,"neigh_bondlist") == 0) return (void *) lmp->neighbor->bondlist; + if (strcmp(name,"neigh_anglelist") == 0) return (void *) lmp->neighbor->anglelist; + if (strcmp(name,"neigh_dihedrallist") == 0) return (void *) lmp->neighbor->dihedrallist; + if (strcmp(name,"neigh_improperlist") == 0) return (void *) lmp->neighbor->improperlist; + + if (strcmp(name,"eflag_global") == 0) return (void *) &lmp->update->eflag_global; + if (strcmp(name,"eflag_atom") == 0) return (void *) &lmp->update->eflag_atom; + if (strcmp(name,"vflag_global") == 0) return (void *) &lmp->update->vflag_global; + if (strcmp(name,"vflag_atom") == 0) return (void *) &lmp->update->vflag_atom; + if (strcmp(name,"map_style") == 0) return (void *) &lmp->atom->map_style; if (strcmp(name,"map_tag_max") == 0) return (void *) &lmp->atom->map_tag_max; if (strcmp(name,"sametag") == 0) return (void *) lmp->atom->sametag; @@ -6107,6 +6253,96 @@ int lammps_find_compute_neighlist(void *handle, const char *id, int reqid) { /* ---------------------------------------------------------------------- */ +// helper Command class for a single neighbor list build + +namespace LAMMPS_NS { + class NeighProxy : protected Command + { + public: + NeighProxy(class LAMMPS *lmp) : Command(lmp), neigh_idx(-1) {}; + + void command(int, char **) override; + int get_index() const { return neigh_idx; } + protected: + int neigh_idx; +}; +} + +void NeighProxy::command(int narg, char **arg) +{ + neigh_idx = -1; + if (narg != 3) return; + auto *req = neighbor->add_request(this, arg[0]); + int flags = atoi(arg[1]); + double cutoff = atof(arg[2]); + req->apply_flags(flags); + if (cutoff > 0.0) req->set_cutoff(cutoff); + lmp->init(); + + // setup domain, communication and neighboring + // acquire ghosts and build standard neighbor lists + + if (domain->triclinic) domain->x2lamda(atom->nlocal); + domain->pbc(); + domain->reset_box(); + comm->setup(); + if (neighbor->style) neighbor->setup_bins(); + comm->exchange(); + comm->borders(); + if (domain->triclinic) domain->lamda2x(atom->nlocal + atom->nghost); + neighbor->build(1); + + // build neighbor list this command needs based on earlier request + + auto list = neighbor->find_list(this); + neighbor->build_one(list); + + // find neigh list + for (int i = 0; i < neighbor->nlist; i++) { + NeighList *list = neighbor->lists[i]; + if (this == list->requestor) { + neigh_idx = i; + break; + } + } +} + +/** Build a single neighbor list in between runs and return its index + * + * A neighbor list request is created and the neighbor list built from a + * proxy command. The request ID is typically 0, but will be + * > 0 in case a compute has multiple neighbor list requests. + * + * \param handle pointer to a previously created LAMMPS instance cast to ``void *``. + * \param id Identifier of neighbor list request + * \param flags Neighbor list flags + * \param cutoff Custom neighbor list cutoff if > 0, use default cutoff if < 0 + * \return return neighbor list index if valid, otherwise -1 */ + +int lammps_request_single_neighlist(void *handle, const char *id, int flags, double cutoff) { + auto lmp = (LAMMPS *)handle; + int idx = -1; + if (!lmp || !lmp->error || !lmp->neighbor) { + lammps_last_global_errormessage = fmt::format("ERROR: {}(): Invalid LAMMPS handle\n", FNERR); + return -1; + } + + BEGIN_CAPTURE + { + NeighProxy proxy(lmp); + std::vector args = {id, std::to_string(flags), std::to_string(cutoff)}; + std::vector c_args; + std::transform(args.begin(), args.end(), std::back_inserter(c_args), + [](const std::string& s) { return (char *)s.c_str(); }); + proxy.command(static_cast(c_args.size()), c_args.data()); + idx = proxy.get_index(); + } + END_CAPTURE + return idx; +} + +/* ---------------------------------------------------------------------- */ + /** Return the number of entries in the neighbor list with given index * * \param handle pointer to a previously created LAMMPS instance cast to ``void *``. diff --git a/src/library.h b/src/library.h index 0d57fdaf78..a4ca396628 100644 --- a/src/library.h +++ b/src/library.h @@ -109,6 +109,17 @@ enum _LMP_VAR_CONST { LMP_VAR_STRING = 3 /*!< return value will be a string (catch-all) */ }; +/** Neighbor list settings constants + * + * Must be kept in sync with the equivalent constants in ``python/lammps/constants.py``, + * ``fortran/lammps.f90``, ``tools/swig/lammps.i``, and + * ``examples/COUPLE/plugin/liblammpsplugin.h`` */ + +enum _LMP_NEIGH_CONST { + LMP_NEIGH_HALF = 0, /*!< request (default) half neighbor list */ + LMP_NEIGH_FULL = 1, /*!< request full neighbor list */ +}; + /* Ifdefs to allow this file to be included in C and C++ programs */ #ifdef __cplusplus @@ -235,6 +246,7 @@ int lammps_create_atoms(void *handle, int n, const int64_t *id, const int *type, int lammps_find_pair_neighlist(void *handle, const char *style, int exact, int nsub, int request); int lammps_find_fix_neighlist(void *handle, const char *id, int request); int lammps_find_compute_neighlist(void *handle, const char *id, int request); +int lammps_request_single_neighlist(void *handle, const char *id, int flags, double cutoff); int lammps_neighlist_num_elements(void *handle, int idx); void lammps_neighlist_element_neighbors(void *handle, int idx, int element, int *iatom, int *numneigh, int **neighbors); diff --git a/src/lmptype.h b/src/lmptype.h index 8927de429c..5796d4d18c 100644 --- a/src/lmptype.h +++ b/src/lmptype.h @@ -234,13 +234,13 @@ union ubuf { std::string str; for (int i = 0; i < 5; ++i) { switch (m[i].type) { - case multitype::DOUBLE: + case multitype::LAMMPS_DOUBLE: str += std::to_string(m[i].data.d) + ' '; break; - case multitype::INT: + case multitype::LAMMPS_INT: str += std::to_string(m[i].data.i) + ' '; break; - case multitype::BIGINT: + case multitype::LAMMPS_INT64: str += std::to_string(m[i].data.b) + ' '; break; default: diff --git a/src/main.cpp b/src/main.cpp index a1f9772455..951d828b51 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,14 +17,12 @@ #include "input.h" #include "library.h" +#include "json.h" + #include #include #include -#if defined(LAMMPS_TRAP_FPE) && defined(_GNU_SOURCE) -#include -#endif - // import MolSSI Driver Interface library #if defined(LMP_MDI) #include @@ -62,17 +60,6 @@ int main(int argc, char **argv) if (MDI_MPI_get_world_comm(&lammps_comm)) MPI_Abort(MPI_COMM_WORLD, 1); #endif -#if defined(LAMMPS_TRAP_FPE) && defined(_GNU_SOURCE) - // enable trapping selected floating point exceptions. - // this uses GNU extensions and is only tested on Linux - // therefore we make it depend on -D_GNU_SOURCE, too. - fesetenv(FE_NOMASK_ENV); - fedisableexcept(FE_ALL_EXCEPT); - feenableexcept(FE_DIVBYZERO); - feenableexcept(FE_INVALID); - feenableexcept(FE_OVERFLOW); -#endif - try { auto lammps = new LAMMPS(argc, argv, lammps_comm); lammps->input->file(); @@ -90,6 +77,11 @@ int main(int argc, char **argv) finalize(); MPI_Abort(MPI_COMM_WORLD, 1); exit(1); + } catch (json::exception &je) { + fprintf(stderr, "\nJSON library error %d: %s\n", je.id, je.what()); + finalize(); + MPI_Abort(MPI_COMM_WORLD, 1); + exit(1); } catch (std::bad_alloc &ae) { fprintf(stderr, "C++ memory allocation failed: %s\n", ae.what()); finalize(); diff --git a/src/memory.cpp b/src/memory.cpp index 84f052e447..c30b9933d4 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1,4 +1,3 @@ -// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories @@ -62,7 +61,7 @@ void *Memory::smalloc(bigint nbytes, const char *name) void *ptr = malloc(nbytes); #endif if (ptr == nullptr) - error->one(FLERR,"Failed to allocate {} bytes for array {}", nbytes,name); + error->one(FLERR, Error::NOLASTLINE, "Failed to allocate {} bytes for array {}", nbytes, name); return ptr; } @@ -80,28 +79,28 @@ void *Memory::srealloc(void *ptr, bigint nbytes, const char *name) #if defined(LMP_USE_TBB_ALLOCATOR) ptr = scalable_aligned_realloc(ptr, nbytes, LAMMPS_MEMALIGN); #elif defined(LMP_INTEL_NO_TBB) && defined(LAMMPS_MEMALIGN) && \ - (defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER)) + (defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER)) ptr = realloc(ptr, nbytes); - uintptr_t offset = ((uintptr_t)(const void *)(ptr)) % LAMMPS_MEMALIGN; + uintptr_t offset = ((uintptr_t) (const void *) (ptr)) % LAMMPS_MEMALIGN; if (offset) { void *optr = ptr; ptr = smalloc(nbytes, name); #if defined(__APPLE__) - memcpy(ptr, optr, MIN(nbytes,malloc_size(optr))); + memcpy(ptr, optr, MIN(nbytes, malloc_size(optr))); #elif defined(_WIN32) || defined(__MINGW32__) - memcpy(ptr, optr, MIN(nbytes,_msize(optr))); + memcpy(ptr, optr, MIN(nbytes, _msize(optr))); #else - memcpy(ptr, optr, MIN(nbytes,malloc_usable_size(optr))); + memcpy(ptr, optr, MIN(nbytes, malloc_usable_size(optr))); #endif free(optr); } #else - ptr = realloc(ptr,nbytes); + ptr = realloc(ptr, nbytes); #endif if (ptr == nullptr) - error->one(FLERR,"Failed to reallocate {} bytes for array {}", - nbytes,name); + error->one(FLERR, Error::NOLASTLINE, "Failed to reallocate {} bytes for array {}", nbytes, + name); return ptr; } @@ -112,11 +111,11 @@ void *Memory::srealloc(void *ptr, bigint nbytes, const char *name) void Memory::sfree(void *ptr) { if (ptr == nullptr) return; - #if defined(LMP_USE_TBB_ALLOCATOR) +#if defined(LMP_USE_TBB_ALLOCATOR) scalable_aligned_free(ptr); - #else +#else free(ptr); - #endif +#endif } /* ---------------------------------------------------------------------- @@ -125,5 +124,6 @@ void Memory::sfree(void *ptr) void Memory::fail(const char *name) { - error->one(FLERR,"Cannot create/grow a vector/array of pointers for {}",name); + error->one(FLERR, Error::NOLASTLINE, "Cannot create/grow a vector/array of pointers for {}", + name); } diff --git a/src/min.cpp b/src/min.cpp index e20e4c191f..bf36e0539a 100644 --- a/src/min.cpp +++ b/src/min.cpp @@ -113,7 +113,10 @@ void Min::init() // create fix needed for storing atom-based quantities // will delete it at end of run - fix_minimize = dynamic_cast(modify->add_fix("MINIMIZE all MINIMIZE")); + if (lmp->kokkos) + fix_minimize = dynamic_cast(modify->add_fix("MINIMIZE all MINIMIZE/kk")); + else + fix_minimize = dynamic_cast(modify->add_fix("MINIMIZE all MINIMIZE")); // clear out extra global and per-atom dof // will receive requests for new per-atom dof during pair init() diff --git a/src/my_page.cpp b/src/my_page.cpp index 88bc522f29..2f55f4f08c 100644 --- a/src/my_page.cpp +++ b/src/my_page.cpp @@ -33,18 +33,17 @@ using namespace LAMMPS_NS; * * The settings *maxchunk*, *pagesize*, and *pagedelta* control * the memory allocation strategy. The *maxchunk* value represents - * the expected largest number of items per chunk. If there is - * less space left on the current page, a new page is allocated - * for the next chunk. The *pagesize* value represents how many - * items can fit on a single page. It should have space for multiple - * chunks of size *maxchunk*. The combination of these two - * parameters determines how much memory is wasted by either switching - * to the next page too soon or allocating too large pages that never - * get properly used. An error is issued if a requested chunk is larger - * than *maxchunk*. The *pagedelta* parameter determines how many - * pages are allocated in one go. In combination with the *pagesize* - * setting, this determines how often blocks of memory get allocated - * (fewer allocations will result in faster execution). + * the largest number of items per chunk allowed; using more will + * trigger an error. If there is less space than *maxchunk* left + * on the current page, a new page is allocated for the next chunk. + * The *pagesize* value represents how many items can fit on a single + * page. It should have space for multiple chunks of size *maxchunk*. + * The combination of these two parameters determines how much memory + * is wasted by either switching to the next page too soon or allocating + * too large pages that never get fully used. The *pagedelta* parameter + * determines how many pages are allocated in one go. In combination + * with the *pagesize* setting, this determines how often blocks of memory + * get allocated (fewer allocations will result in faster execution). * * \note * This is a template class with explicit instantiation. If the class @@ -71,7 +70,7 @@ template MyPage::~MyPage() * This also frees all previously allocated storage and allocates * the first page(s). * - * \param user_maxchunk Expected maximum number of items for one chunk + * \param user_maxchunk Maximum allowed number of items for one chunk * \param user_pagesize Number of items on a single memory page * \param user_pagedelta Number of pages to allocate with one malloc * \return 1 if there were invalid parameters, 2 if there was an allocation error or 0 if successful */ diff --git a/src/neighbor.cpp b/src/neighbor.cpp index a2aa3f411b..fcedfd7613 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -188,8 +188,8 @@ pairclass(nullptr), pairnames(nullptr), pairmasks(nullptr) // topology lists + nbondlist = nanglelist = ndihedrallist = nimproperlist = 0; bondwhich = anglewhich = dihedralwhich = improperwhich = NONE; - neigh_bond = nullptr; neigh_angle = nullptr; neigh_dihedral = nullptr; diff --git a/src/nlohmann/json.hpp b/src/nlohmann/json.hpp new file mode 100644 index 0000000000..75014cae41 --- /dev/null +++ b/src/nlohmann/json.hpp @@ -0,0 +1,25523 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef LMP_NLOHMANN_JSON_HPP_ +#define LMP_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_DIAGNOSTIC_POSITIONS + #define JSON_DIAGNOSTIC_POSITIONS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_DIAGNOSTIC_POSITIONS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann_lmp::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann_lmp \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann_lmp +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L) + #define JSON_HAS_CPP_23 + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE +@since version 3.11.3 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE +@since version 3.11.3 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann_lmp::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann_lmp::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann_lmp::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann_lmp::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann_lmp::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann_lmp::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann_lmp::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann_lmp::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann_lmp::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann_lmp::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows calling any std function as if (e.g., with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann_lmp::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // char_traits +#include // tuple +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(std::char_traits::eof()); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(std::char_traits::eof()); + } +}; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& +is_complete_type < +detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template