diff --git a/.github/workflows/compile-msvc.yml b/.github/workflows/compile-msvc.yml new file mode 100644 index 0000000000..307dc81fe6 --- /dev/null +++ b/.github/workflows/compile-msvc.yml @@ -0,0 +1,33 @@ +# GitHub action to build LAMMPS on Windows with Visual C++ +name: "Native Windows Compilation" + +on: + push: + branches: [master] + +jobs: + build: + name: Windows Compilation Test + if: ${{ github.repository == 'lammps/lammps' }} + runs-on: windows-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 2 + + - name: Building LAMMPS via CMake + shell: bash + run: | + cmake -C cmake/presets/windows.cmake \ + -S cmake -B build \ + -D BUILD_SHARED_LIBS=on \ + -D LAMMPS_EXCEPTIONS=on + cmake --build build --config Release + + - name: Run LAMMPS executable + shell: bash + run: | + ./build/Release/lmp.exe -h + ./build/Release/lmp.exe -in bench/in.lj diff --git a/.gitignore b/.gitignore index ae708ff184..3fb3af0d13 100644 --- a/.gitignore +++ b/.gitignore @@ -37,8 +37,8 @@ vgcore.* .Trashes ehthumbs.db Thumbs.db -.clang-format .lammps_history +.vs #cmake /build* @@ -49,3 +49,8 @@ Thumbs.db /Testing /cmake_install.cmake /lmp +out/Debug +out/RelWithDebInfo +out/Release +out/x86 +out/x64 diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index af38a0db72..1f0f016cff 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -82,21 +82,39 @@ include(CheckIncludeFileCXX) # set required compiler flags and compiler/CPU arch specific optimizations if((CMAKE_CXX_COMPILER_ID STREQUAL "Intel") OR (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")) - 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") + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + 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") + else() + set(CMAKE_TUNE_DEFAULT "/QxHost") + endif() else() - set(CMAKE_TUNE_DEFAULT "-xHost") + 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") + else() + set(CMAKE_TUNE_DEFAULT "-xHost") + endif() endif() endif() -# we require C++11 without extensions +# we require C++11 without extensions. Kokkos requires at least C++14 (currently) set(CMAKE_CXX_STANDARD 11) +if(PKG_KOKKOS AND (CMAKE_CXX_STANDARD LESS 14)) + set(CMAKE_CXX_STANDARD 14) +endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Use compiler extensions") -# ugly hack for MSVC which by default always reports an old C++ standard in the __cplusplus macro +# ugly hacks for MSVC which by default always reports an old C++ standard in the __cplusplus macro +# and prints lots of pointless warnings about "unsafe" functions if(MSVC) add_compile_options(/Zc:__cplusplus) + add_compile_options(/wd4244) + add_compile_options(/wd4267) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() # export all symbols when building a .dll file on windows @@ -281,6 +299,11 @@ else() target_include_directories(mpi_stubs PUBLIC $) if(BUILD_SHARED_LIBS) target_link_libraries(lammps PRIVATE mpi_stubs) + if(MSVC) + target_link_libraries(lmp PRIVATE mpi_stubs) + target_include_directories(lmp INTERFACE $) + target_compile_definitions(lmp INTERFACE $) + endif(MSVC) target_include_directories(lammps INTERFACE $) target_compile_definitions(lammps INTERFACE $) else() @@ -468,9 +491,12 @@ foreach(HEADER cmath) endif(NOT FOUND_${HEADER}) endforeach(HEADER) -set(MATH_LIBRARIES "m" CACHE STRING "math library") -mark_as_advanced( MATH_LIBRARIES ) -target_link_libraries(lammps PRIVATE ${MATH_LIBRARIES}) +# make the standard math library overrideable and autodetected (for systems that don't have it) +find_library(STANDARD_MATH_LIB m DOC "Standard Math library") +mark_as_advanced(STANDARD_MATH_LIB) +if(STANDARD_MATH_LIB) + target_link_libraries(lammps PRIVATE ${STANDARD_MATH_LIB}) +endif() ###################################### # Generate Basic Style files @@ -608,7 +634,7 @@ endif() # and after everything else that is compiled locally ###################################################################### if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_link_libraries(lammps PRIVATE -lwsock32 -lpsapi) + target_link_libraries(lammps PRIVATE "wsock32;psapi") endif() ###################################################### diff --git a/cmake/CMakeSettings.json b/cmake/CMakeSettings.json new file mode 100644 index 0000000000..dada2f6752 --- /dev/null +++ b/cmake/CMakeSettings.json @@ -0,0 +1,55 @@ +{ + "configurations": [ + { + "name": "x64-Debug-MSVC", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${workspaceRoot}\\build\\${name}", + "installRoot": "${workspaceRoot}\\install\\${name}", + "cmakeCommandArgs": "-S ${workspaceRoot}\\cmake -C ${workspaceRoot}\\cmake\\presets\\windows.cmake", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [ + { + "name": "BUILD_SHARED_LIBS", + "value": "True", + "type": "BOOL" + }, + { + "name": "BUILD_TOOLS", + "value": "True", + "type": "BOOL" + }, + { + "name": "LAMMPS_EXCEPTIONS", + "value": "True", + "type": "BOOL" + } + ] + }, + { + "name": "x64-Debug-Clang", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${workspaceRoot}\\build\\${name}", + "installRoot": "${workspaceRoot}\\install\\${name}", + "cmakeCommandArgs": "-S ${workspaceRoot}\\cmake -C ${workspaceRoot}\\cmake\\presets\\windows.cmake", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64" ], + "variables": [ + { + "name": "BUILD_TOOLS", + "value": "True", + "type": "BOOL" + }, + { + "name": "LAMMPS_EXCEPTIONS", + "value": "True", + "type": "BOOL" + } + ] + } + ] +} \ No newline at end of file diff --git a/cmake/Modules/Packages/GPU.cmake b/cmake/Modules/Packages/GPU.cmake index aaa784ca8b..a57715d294 100644 --- a/cmake/Modules/Packages/GPU.cmake +++ b/cmake/Modules/Packages/GPU.cmake @@ -217,13 +217,20 @@ elseif(GPU_API STREQUAL "OPENCL") elseif(GPU_API STREQUAL "HIP") if(NOT DEFINED HIP_PATH) if(NOT DEFINED ENV{HIP_PATH}) - set(HIP_PATH "/opt/rocm/hip" CACHE PATH "Path to which HIP has been installed") + set(HIP_PATH "/opt/rocm/hip" CACHE PATH "Path to HIP installation") else() - set(HIP_PATH $ENV{HIP_PATH} CACHE PATH "Path to which HIP has been installed") + set(HIP_PATH $ENV{HIP_PATH} CACHE PATH "Path to HIP installation") endif() endif() - set(CMAKE_MODULE_PATH "${HIP_PATH}/cmake" ${CMAKE_MODULE_PATH}) - find_package(HIP REQUIRED) + if(NOT DEFINED ROCM_PATH) + if(NOT DEFINED ENV{ROCM_PATH}) + set(ROCM_PATH "/opt/rocm" CACHE PATH "Path to ROCm installation") + else() + set(ROCM_PATH $ENV{ROCM_PATH} CACHE PATH "Path to ROCm installation") + endif() + endif() + list(APPEND CMAKE_PREFIX_PATH ${HIP_PATH} ${ROCM_PATH}) + find_package(hip REQUIRED) option(HIP_USE_DEVICE_SORT "Use GPU sorting" ON) if(NOT DEFINED HIP_PLATFORM) @@ -325,10 +332,11 @@ elseif(GPU_API STREQUAL "HIP") set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${LAMMPS_LIB_BINARY_DIR}/gpu/*_cubin.h ${LAMMPS_LIB_BINARY_DIR}/gpu/*.cu.cpp") - hip_add_library(gpu STATIC ${GPU_LIB_SOURCES}) + add_library(gpu STATIC ${GPU_LIB_SOURCES}) target_include_directories(gpu PRIVATE ${LAMMPS_LIB_BINARY_DIR}/gpu) target_compile_definitions(gpu PRIVATE -D_${GPU_PREC_SETTING} -DMPI_GERYON -DUCL_NO_EXIT) target_compile_definitions(gpu PRIVATE -DUSE_HIP) + target_link_libraries(gpu PRIVATE hip::host) if(HIP_USE_DEVICE_SORT) # add hipCUB @@ -377,8 +385,9 @@ elseif(GPU_API STREQUAL "HIP") endif() endif() - hip_add_executable(hip_get_devices ${LAMMPS_LIB_SOURCE_DIR}/gpu/geryon/ucl_get_devices.cpp) + add_executable(hip_get_devices ${LAMMPS_LIB_SOURCE_DIR}/gpu/geryon/ucl_get_devices.cpp) target_compile_definitions(hip_get_devices PRIVATE -DUCL_HIP) + target_link_libraries(hip_get_devices hip::host) if(HIP_PLATFORM STREQUAL "nvcc") target_compile_definitions(gpu PRIVATE -D__HIP_PLATFORM_NVCC__) diff --git a/cmake/Modules/Packages/KOKKOS.cmake b/cmake/Modules/Packages/KOKKOS.cmake index a1cf680266..fe6c17801e 100644 --- a/cmake/Modules/Packages/KOKKOS.cmake +++ b/cmake/Modules/Packages/KOKKOS.cmake @@ -1,6 +1,8 @@ ######################################################################## # As of version 3.3.0 Kokkos requires C++14 -set(CMAKE_CXX_STANDARD 14) +if(CMAKE_CXX_STANDARD LESS 14) + message(FATAL_ERROR "The KOKKOS package requires the C++ standard to be set to at least C++14") +endif() ######################################################################## # consistency checks and Kokkos options/settings required by LAMMPS if(Kokkos_ENABLE_CUDA) diff --git a/cmake/Modules/Packages/LATTE.cmake b/cmake/Modules/Packages/LATTE.cmake index ddf31a68ed..a96e850f7e 100644 --- a/cmake/Modules/Packages/LATTE.cmake +++ b/cmake/Modules/Packages/LATTE.cmake @@ -19,6 +19,14 @@ if(DOWNLOAD_LATTE) set(LATTE_MD5 "820e73a457ced178c08c71389a385de7" CACHE STRING "MD5 checksum of LATTE tarball") mark_as_advanced(LATTE_URL) mark_as_advanced(LATTE_MD5) + + # CMake cannot pass BLAS or LAPACK library variable to external project if they are a list + list(LENGTH BLAS_LIBRARIES} NUM_BLAS) + list(LENGTH LAPACK_LIBRARIES NUM_LAPACK) + if((NUM_BLAS GREATER 1) OR (NUM_LAPACK GREATER 1)) + message(FATAL_ERROR "Cannot compile downloaded LATTE library due to a technical limitation") + endif() + include(ExternalProject) ExternalProject_Add(latte_build URL ${LATTE_URL} diff --git a/cmake/Modules/Packages/MACHDYN.cmake b/cmake/Modules/Packages/MACHDYN.cmake index fab532541e..8729d80dbf 100644 --- a/cmake/Modules/Packages/MACHDYN.cmake +++ b/cmake/Modules/Packages/MACHDYN.cmake @@ -7,8 +7,9 @@ endif() option(DOWNLOAD_EIGEN3 "Download Eigen3 instead of using an already installed one)" ${DOWNLOAD_EIGEN3_DEFAULT}) if(DOWNLOAD_EIGEN3) message(STATUS "Eigen3 download requested - we will build our own") - set(EIGEN3_URL "https://gitlab.com/libeigen/eigen/-/archive/3.3.9/eigen-3.3.9.tar.gz" CACHE STRING "URL for Eigen3 tarball") - set(EIGEN3_MD5 "609286804b0f79be622ccf7f9ff2b660" CACHE STRING "MD5 checksum of Eigen3 tarball") + + set(EIGEN3_URL "https://download.lammps.org/thirdparty/eigen-3.4.0.tar.gz" CACHE STRING "URL for Eigen3 tarball") + set(EIGEN3_MD5 "4c527a9171d71a72a9d4186e65bea559" CACHE STRING "MD5 checksum of Eigen3 tarball") mark_as_advanced(EIGEN3_URL) mark_as_advanced(EIGEN3_MD5) include(ExternalProject) diff --git a/cmake/Modules/Packages/ML-HDNNP.cmake b/cmake/Modules/Packages/ML-HDNNP.cmake index 44873b9929..e27b3a1410 100644 --- a/cmake/Modules/Packages/ML-HDNNP.cmake +++ b/cmake/Modules/Packages/ML-HDNNP.cmake @@ -45,12 +45,12 @@ if(DOWNLOAD_N2P2) # get path to MPI include directory when cross-compiling to windows if((CMAKE_SYSTEM_NAME STREQUAL Windows) AND CMAKE_CROSSCOMPILING) get_target_property(N2P2_MPI_INCLUDE MPI::MPI_CXX INTERFACE_INCLUDE_DIRECTORIES) - set(N2P2_PROJECT_OPTIONS "-I ${N2P2_MPI_INCLUDE} -DMPICH_SKIP_MPICXX=1") + set(N2P2_PROJECT_OPTIONS "-I${N2P2_MPI_INCLUDE}") set(MPI_CXX_COMPILER ${CMAKE_CXX_COMPILER}) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") get_target_property(N2P2_MPI_INCLUDE MPI::MPI_CXX INTERFACE_INCLUDE_DIRECTORIES) - set(N2P2_PROJECT_OPTIONS "-I ${N2P2_MPI_INCLUDE} -DMPICH_SKIP_MPICXX=1") + set(N2P2_PROJECT_OPTIONS "-I${N2P2_MPI_INCLUDE}") set(MPI_CXX_COMPILER ${CMAKE_CXX_COMPILER}) endif() endif() @@ -69,6 +69,12 @@ if(DOWNLOAD_N2P2) # echo final flag for debugging message(STATUS "N2P2 BUILD OPTIONS: ${N2P2_BUILD_OPTIONS}") + # must have "sed" command to compile n2p2 library (for now) + find_program(HAVE_SED sed) + if(NOT HAVE_SED) + message(FATAL_ERROR "Must have 'sed' program installed to compile 'n2p2' library for ML-HDNNP package") + endif() + # download compile n2p2 library. much patch MPI calls in LAMMPS interface to accommodate MPI-2 (e.g. for cross-compiling) include(ExternalProject) ExternalProject_Add(n2p2_build diff --git a/cmake/Modules/Packages/ML-QUIP.cmake b/cmake/Modules/Packages/ML-QUIP.cmake index 5a80e63d55..92418e8939 100644 --- a/cmake/Modules/Packages/ML-QUIP.cmake +++ b/cmake/Modules/Packages/ML-QUIP.cmake @@ -50,7 +50,7 @@ if(DOWNLOAD_QUIP) GIT_TAG origin/public GIT_SHALLOW YES GIT_PROGRESS YES - PATCH_COMMAND cp ${CMAKE_BINARY_DIR}/quip.config /arch/Makefile.lammps + PATCH_COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/quip.config /arch/Makefile.lammps CONFIGURE_COMMAND env QUIP_ARCH=lammps make config BUILD_COMMAND env QUIP_ARCH=lammps make libquip INSTALL_COMMAND "" diff --git a/cmake/Modules/Packages/SCAFACOS.cmake b/cmake/Modules/Packages/SCAFACOS.cmake index fd355420c3..de611a1edb 100644 --- a/cmake/Modules/Packages/SCAFACOS.cmake +++ b/cmake/Modules/Packages/SCAFACOS.cmake @@ -23,6 +23,11 @@ if(DOWNLOAD_SCAFACOS) 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} diff --git a/cmake/Modules/Packages/VORONOI.cmake b/cmake/Modules/Packages/VORONOI.cmake index 7feea4c52e..c010469677 100644 --- a/cmake/Modules/Packages/VORONOI.cmake +++ b/cmake/Modules/Packages/VORONOI.cmake @@ -26,6 +26,11 @@ if(DOWNLOAD_VORO) set(VORO_BUILD_OPTIONS CXX=${CMAKE_CXX_COMPILER} CFLAGS=${VORO_BUILD_CFLAGS}) endif() + find_program(HAVE_PATCH patch) + if(NOT HAVE_PATCH) + message(FATAL_ERROR "The 'patch' program is required to build the voro++ library") + endif() + ExternalProject_Add(voro_build URL ${VORO_URL} URL_MD5 ${VORO_MD5} diff --git a/cmake/Modules/Tools.cmake b/cmake/Modules/Tools.cmake index 146764dbd5..c3b0a0771d 100644 --- a/cmake/Modules/Tools.cmake +++ b/cmake/Modules/Tools.cmake @@ -25,7 +25,9 @@ if(BUILD_TOOLS) get_filename_component(MSI2LMP_SOURCE_DIR ${LAMMPS_TOOLS_DIR}/msi2lmp/src ABSOLUTE) file(GLOB MSI2LMP_SOURCES ${MSI2LMP_SOURCE_DIR}/[^.]*.c) add_executable(msi2lmp ${MSI2LMP_SOURCES}) - target_link_libraries(msi2lmp PRIVATE ${MATH_LIBRARIES}) + if(STANDARD_MATH_LIB) + target_link_libraries(msi2lmp PRIVATE ${STANDARD_MATH_LIB}) + endif() install(TARGETS msi2lmp DESTINATION ${CMAKE_INSTALL_BINDIR}) install(FILES ${LAMMPS_DOC_DIR}/msi2lmp.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) endif() diff --git a/cmake/presets/hip_amd.cmake b/cmake/presets/hip_amd.cmake new file mode 100644 index 0000000000..4b8945e0c7 --- /dev/null +++ b/cmake/presets/hip_amd.cmake @@ -0,0 +1,30 @@ +# preset that will enable hip (clang/clang++) with support for MPI and OpenMP (on Linux boxes) + +# prefer flang over gfortran, if available +find_program(CLANG_FORTRAN NAMES flang gfortran f95) +set(ENV{OMPI_FC} ${CLANG_FORTRAN}) + +set(CMAKE_CXX_COMPILER "hipcc" CACHE STRING "" FORCE) +set(CMAKE_C_COMPILER "hipcc" CACHE STRING "" FORCE) +set(CMAKE_Fortran_COMPILER ${CLANG_FORTRAN} CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Wextra -g" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-Wall -Wextra -g -O2 -DNDEBUG" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "" FORCE) +set(CMAKE_Fortran_FLAGS_DEBUG "-Wall -Wextra -g -std=f2003" CACHE STRING "" FORCE) +set(CMAKE_Fortran_FLAGS_RELWITHDEBINFO "-Wall -Wextra -g -O2 -DNDEBUG -std=f2003" CACHE STRING "" FORCE) +set(CMAKE_Fortran_FLAGS_RELEASE "-O3 -DNDEBUG -std=f2003" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -g" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Wall -Wextra -g -O2 -DNDEBUG" CACHE STRING "" FORCE) +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) + +unset(HAVE_OMP_H_INCLUDE CACHE) +set(OpenMP_C "hipcc" CACHE STRING "" FORCE) +set(OpenMP_C_FLAGS "-fopenmp" 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_LIB_NAMES "omp" CACHE STRING "" FORCE) +set(OpenMP_omp_LIBRARY "libomp.so" CACHE PATH "" FORCE) diff --git a/cmake/presets/windows.cmake b/cmake/presets/windows.cmake new file mode 100644 index 0000000000..d4e69c5fca --- /dev/null +++ b/cmake/presets/windows.cmake @@ -0,0 +1,64 @@ +set(WIN_PACKAGES + ASPHERE + BOCS + BODY + BROWNIAN + CG-DNA + CG-SDK + CLASS2 + COLLOID + COLVARS + CORESHELL + DIELECTRIC + DIFFRACTION + DIPOLE + DPD-BASIC + DPD-MESO + DPD-REACT + DPD-SMOOTH + DRUDE + EFF + EXTRA-COMPUTE + EXTRA-DUMP + EXTRA-FIX + EXTRA-MOLECULE + EXTRA-PAIR + FEP + GRANULAR + INTERLAYER + KSPACE + MANIFOLD + MANYBODY + MC + MEAM + MISC + ML-IAP + ML-SNAP + MOFFF + MOLECULE + MOLFILE + OPENMP + ORIENT + PERI + PHONON + POEMS + PTM + QEQ + QTB + REACTION + REAXFF + REPLICA + RIGID + SHOCK + SMTBQ + SPH + SPIN + SRD + TALLY + UEF + YAFF) + +foreach(PKG ${WIN_PACKAGES}) + set(PKG_${PKG} ON CACHE BOOL "" FORCE) +endforeach() + diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in index 49a271355f..d454898f4e 100644 --- a/doc/doxygen/Doxyfile.in +++ b/doc/doxygen/Doxyfile.in @@ -435,6 +435,8 @@ INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \ @LAMMPS_SOURCE_DIR@/my_pool_chunk.cpp \ @LAMMPS_SOURCE_DIR@/my_pool_chunk.h \ @LAMMPS_SOURCE_DIR@/math_eigen.h \ + @LAMMPS_SOURCE_DIR@/platform.h \ + @LAMMPS_SOURCE_DIR@/platform.cpp \ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/doc/lammps.1 b/doc/lammps.1 index fb79b8d774..c868a2a86f 100644 --- a/doc/lammps.1 +++ b/doc/lammps.1 @@ -1,4 +1,4 @@ -.TH LAMMPS "20 September 2021" "2021-09-20" +.TH LAMMPS "29 September 2021" "2021-09-29" .SH NAME .B LAMMPS \- Molecular Dynamics Simulator. diff --git a/doc/src/Build_settings.rst b/doc/src/Build_settings.rst index 074a6349e6..01bd8e2c80 100644 --- a/doc/src/Build_settings.rst +++ b/doc/src/Build_settings.rst @@ -71,7 +71,8 @@ LAMMPS can use them if they are available on your system. -D FFTW3_INCLUDE_DIR=path # path to FFTW3 include files -D FFTW3_LIBRARY=path # path to FFTW3 libraries - -D FFT_FFTW_THREADS=on # enable using threaded FFTW3 libraries + -D FFTW3_OMP_LIBRARY=path # path to FFTW3 OpenMP wrapper libraries + -D FFT_FFTW_THREADS=on # enable using OpenMP threaded FFTW3 libraries -D MKL_INCLUDE_DIR=path # ditto for Intel MKL library -D FFT_MKL_THREADS=on # enable using threaded FFTs with MKL libraries -D MKL_LIBRARY=path # path to MKL libraries @@ -353,8 +354,10 @@ Read or write compressed files ----------------------------------------- If this option is enabled, large files can be read or written with -gzip compression by several LAMMPS commands, including -:doc:`read_data `, :doc:`rerun `, and :doc:`dump `. +compression by ``gzip`` or similar tools by several LAMMPS commands, +including :doc:`read_data `, :doc:`rerun `, and +:doc:`dump `. Currently supported compression tools are: +``gzip``, ``bzip2``, ``zstd``, and ``lzma``. .. tabs:: @@ -363,8 +366,7 @@ gzip compression by several LAMMPS commands, including .. code-block:: bash -D WITH_GZIP=value # yes or no - # default is yes if CMake can find gzip, else no - -D GZIP_EXECUTABLE=path # path to gzip executable if CMake cannot find it + # default is yes if CMake can find the gzip program, else no .. tab:: Traditional make @@ -372,14 +374,15 @@ gzip compression by several LAMMPS commands, including LMP_INC = -DLAMMPS_GZIP -This option requires that your operating system fully supports the "popen()" -function in the standard runtime library and that a ``gzip`` executable can be -found by LAMMPS during a run. +This option requires that your operating system fully supports the +"popen()" function in the standard runtime library and that a ``gzip`` +or other executable can be found by LAMMPS in the standard search path +during a run. .. note:: - On some clusters with high-speed networks, using the "fork()" library - call (required by "popen()") can interfere with the fast communication + On clusters with high-speed networks, using the "fork()" library call + (required by "popen()") can interfere with the fast communication library and lead to simulations using compressed output or input to hang or crash. For selected operations, compressed file I/O is also available using a compression library instead, which is what the diff --git a/doc/src/Build_windows.rst b/doc/src/Build_windows.rst index 3a56f29d09..fa2296d302 100644 --- a/doc/src/Build_windows.rst +++ b/doc/src/Build_windows.rst @@ -4,6 +4,7 @@ Notes for building LAMMPS on Windows * :ref:`General remarks ` * :ref:`Running Linux on Windows ` * :ref:`Using GNU GCC ported to Windows ` +* :ref:`Using Visual Studio ` * :ref:`Using a cross-compiler ` ---------- @@ -31,13 +32,13 @@ pre-compiled Windows binary packages are sufficient for your needs. If it is necessary for you to compile LAMMPS on a Windows machine (e.g. because it is your main desktop), please also consider using a virtual machine software and compile and run LAMMPS in a Linux virtual -machine, or - if you have a sufficiently up-to-date Windows 10 -installation - consider using the Windows subsystem for Linux. This -optional Windows feature allows you to run the bash shell from Ubuntu -from within Windows and from there on, you can pretty much use that -shell like you are running on an Ubuntu Linux machine (e.g. installing -software via apt-get and more). For more details on that, please see -:doc:`this tutorial `. +machine, or - if you have a sufficiently up-to-date Windows 10 or +Windows 11 installation - consider using the Windows subsystem for +Linux. This optional Windows feature allows you to run the bash shell +from Ubuntu from within Windows and from there on, you can pretty much +use that shell like you are running on an Ubuntu Linux machine +(e.g. installing software via apt-get and more). For more details on +that, please see :doc:`this tutorial `. .. _gnu: @@ -67,6 +68,35 @@ requiring changes to the LAMMPS source code, or figure out corrections yourself, please report them on the lammps-users mailing list, or file them as an issue or pull request on the LAMMPS GitHub project. +.. _msvc: + +Using Microsoft Visual Studio +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Following the integration of the :doc:`platform namespace +` into the LAMMPS code base, portability of LAMMPS +to be compiled on Windows using Visual Studio has been significantly +improved. This has been tested with Visual Studio 2019 (aka version +16). Not all features and packages in LAMMPS are currently supported +out of the box, but a preset ``cmake/presets/windows.cmake`` is provided +that contains the packages that have been compiled successfully. You +must use the CMake based build procedure, and either use the integrated +CMake support of Visual Studio or use an external CMake installation to +create build files for the Visual Studio build system. Please note that +on launching Visual Studio it will scan the directory tree and likely +miss the correct master ``CMakeLists.txt``. Try to open the +``cmake/CMakeSettings.json`` and use those CMake configurations as a +starting point. It is also possible to configure and compile LAMMPS +from the command line with a CMake binary from `cmake.org `_. + +To support running in parallel you can compile with OpenMP enabled using +the OPENMP package or install Microsoft MPI (including the SDK) and compile +LAMMPS with MPI enabled. + +This is work in progress and you should contact the LAMMPS developers +via GitHub, the forum, or the mailing list, if you have questions or +LAMMPS specific problems. + .. _cross: Using a cross-compiler diff --git a/doc/src/Developer.rst b/doc/src/Developer.rst index f54bc4152f..fd4a44a8a0 100644 --- a/doc/src/Developer.rst +++ b/doc/src/Developer.rst @@ -11,10 +11,12 @@ of time and requests from the LAMMPS user community. :maxdepth: 1 Developer_org + Developer_parallel Developer_flow Developer_write Developer_notes Developer_plugins Developer_unittest Classes + Developer_platform Developer_utils diff --git a/doc/src/Developer_par_comm.rst b/doc/src/Developer_par_comm.rst new file mode 100644 index 0000000000..2e108dda13 --- /dev/null +++ b/doc/src/Developer_par_comm.rst @@ -0,0 +1,120 @@ +Communication +^^^^^^^^^^^^^ + +Following the partitioning scheme in use all per-atom data is +distributed across the MPI processes, which allows LAMMPS to handle very +large systems provided it uses a correspondingly large number of MPI +processes. Since The per-atom data (atom IDs, positions, velocities, +types, etc.) To be able to compute the short-range interactions MPI +processes need not only access to data of atoms they "own" but also +information about atoms from neighboring sub-domains, in LAMMPS referred +to as "ghost" atoms. These are copies of atoms storing required +per-atom data for up to the communication cutoff distance. The green +dashed-line boxes in the :ref:`domain-decomposition` figure illustrate +the extended ghost-atom sub-domain for one processor. + +This approach is also used to implement periodic boundary +conditions: atoms that lie within the cutoff distance across a periodic +boundary are also stored as ghost atoms and taken from the periodic +replication of the sub-domain, which may be the same sub-domain, e.g. if +running in serial. As a consequence of this, force computation in +LAMMPS is not subject to minimum image conventions and thus cutoffs may +be larger than half the simulation domain. + +.. _ghost-atom-comm: +.. figure:: img/ghost-comm.png + :align: center + + ghost atom communication + + This figure shows the ghost atom communication patterns between + sub-domains for "brick" (left) and "tiled" communication styles for + 2d simulations. The numbers indicate MPI process ranks. Here the + sub-domains are drawn spatially separated for clarity. The + dashed-line box is the extended sub-domain of processor 0 which + includes its ghost atoms. The red- and blue-shaded boxes are the + regions of communicated ghost atoms. + +Efficient communication patterns are needed to update the "ghost" atom +data, since that needs to be done at every MD time step or minimization +step. The diagrams of the `ghost-atom-comm` figure illustrate how ghost +atom communication is performed in two stages for a 2d simulation (three +in 3d) for both a regular and irregular partitioning of the simulation +box. For the regular case (left) atoms are exchanged first in the +*x*-direction, then in *y*, with four neighbors in the grid of processor +sub-domains. + +In the *x* stage, processor ranks 1 and 2 send owned atoms in their +red-shaded regions to rank 0 (and vice versa). Then in the *y* stage, +ranks 3 and 4 send atoms in their blue-shaded regions to rank 0, which +includes ghost atoms they received in the *x* stage. Rank 0 thus +acquires all its ghost atoms; atoms in the solid blue corner regions +are communicated twice before rank 0 receives them. + +For the irregular case (right) the two stages are similar, but a +processor can have more than one neighbor in each direction. In the +*x* stage, MPI ranks 1,2,3 send owned atoms in their red-shaded regions to +rank 0 (and vice versa). These include only atoms between the lower +and upper *y*-boundary of rank 0's sub-domain. In the *y* stage, ranks +4,5,6 send atoms in their blue-shaded regions to rank 0. This may +include ghost atoms they received in the *x* stage, but only if they +are needed by rank 0 to fill its extended ghost atom regions in the ++/-*y* directions (blue rectangles). Thus in this case, ranks 5 and +6 do not include ghost atoms they received from each other (in the *x* +stage) in the atoms they send to rank 0. The key point is that while +the pattern of communication is more complex in the irregular +partitioning case, it can still proceed in two stages (three in 3d) +via atom exchanges with only neighboring processors. + +When attributes of owned atoms are sent to neighboring processors to +become attributes of their ghost atoms, LAMMPS calls this a "forward" +communication. On timesteps when atoms migrate to new owning processors +and neighbor lists are rebuilt, each processor creates a list of its +owned atoms which are ghost atoms in each of its neighbor processors. +These lists are used to pack per-atom coordinates (for example) into +message buffers in subsequent steps until the next reneighboring. + +A "reverse" communication is when computed ghost atom attributes are +sent back to the processor who owns the atom. This is used (for +example) to sum partial forces on ghost atoms to the complete force on +owned atoms. The order of the two stages described in the +:ref:`ghost-atom-comm` figure is inverted and the same lists of atoms +are used to pack and unpack message buffers with per-atom forces. When +a received buffer is unpacked, the ghost forces are summed to owned atom +forces. As in forward communication, forces on atoms in the four blue +corners of the diagrams are sent, received, and summed twice (once at +each stage) before owning processors have the full force. + +These two operations are used many places within LAMMPS aside from +exchange of coordinates and forces, for example by manybody potentials +to share intermediate per-atom values, or by rigid-body integrators to +enable each atom in a body to access body properties. Here are +additional details about how these communication operations are +performed in LAMMPS: + +- When exchanging data with different processors, forward and reverse + communication is done using ``MPI_Send()`` and ``MPI_IRecv()`` calls. + If a processor is "exchanging" atoms with itself, only the pack and + unpack operations are performed, e.g. to create ghost atoms across + periodic boundaries when running on a single processor. + +- For forward communication of owned atom coordinates, periodic box + lengths are added and subtracted when the receiving processor is + across a periodic boundary from the sender. There is then no need to + apply a minimum image convention when calculating distances between + atom pairs when building neighbor lists or computing forces. + +- The cutoff distance for exchanging ghost atoms is typically equal to + the neighbor cutoff. But it can also chosen to be longer if needed, + e.g. half the diameter of a rigid body composed of multiple atoms or + over 3x the length of a stretched bond for dihedral interactions. It + can also exceed the periodic box size. For the regular communication + pattern (left), if the cutoff distance extends beyond a neighbor + processor's sub-domain, then multiple exchanges are performed in the + same direction. Each exchange is with the same neighbor processor, + but buffers are packed/unpacked using a different list of atoms. For + forward communication, in the first exchange a processor sends only + owned atoms. In subsequent exchanges, it sends ghost atoms received + in previous exchanges. For the irregular pattern (right) overlaps of + a processor's extended ghost-atom sub-domain with all other processors + in each dimension are detected. diff --git a/doc/src/Developer_par_long.rst b/doc/src/Developer_par_long.rst new file mode 100644 index 0000000000..f297cf3fa6 --- /dev/null +++ b/doc/src/Developer_par_long.rst @@ -0,0 +1,188 @@ +Long-range interactions +^^^^^^^^^^^^^^^^^^^^^^^ + +For charged systems, LAMMPS can compute long-range Coulombic +interactions via the FFT-based particle-particle/particle-mesh (PPPM) +method implemented in :doc:`kspace style pppm and its variants +`. For that Coulombic interactions are partitioned into +short- and long-range components. The short-ranged portion is computed +in real space as a loop over pairs of charges within a cutoff distance, +using neighbor lists. The long-range portion is computed in reciprocal +space using a kspace style. For the PPPM implementation the simulation +cell is overlaid with a regular FFT grid in 3d. It proceeds in several stages: + +a) each atom's point charge is interpolated to nearby FFT grid points, +b) a forward 3d FFT is performed, +c) a convolution operation is performed in reciprocal space, +d) one or more inverse 3d FFTs are performed, and +e) electric field values from grid points near each atom are interpolated to compute + its forces. + +For any of the spatial-decomposition partitioning schemes each processor +owns the brick-shaped portion of FFT grid points contained within its +sub-domain. The two interpolation operations use a stencil of grid +points surrounding each atom. To accommodate the stencil size, each +processor also stores a few layers of ghost grid points surrounding its +brick. Forward and reverse communication of grid point values is +performed similar to the corresponding :doc:`atom data communication +`. In this case, electric field values on owned +grid points are sent to neighboring processors to become ghost point +values. Likewise charge values on ghost points are sent and summed to +values on owned points. + +For triclinic simulation boxes, the FFT grid planes are parallel to +the box faces, but the mapping of charge and electric field values +to/from grid points is done in reduced coordinates where the tilted +box is conceptually a unit cube, so that the stencil and FFT +operations are unchanged. However the FFT grid size required for a +given accuracy is larger for triclinic domains than it is for +orthogonal boxes. + +.. _fft-parallel: +.. figure:: img/fft-decomp-parallel.png + :align: center + + parallel FFT in PPPM + + Stages of a parallel FFT for a simulation domain overlaid + with an 8x8x8 3d FFT grid, partitioned across 64 processors. + Within each of the 4 diagrams, grid cells of the same color are + owned by a single processor; for simplicity only cells owned by 4 + or 8 of the 64 processors are colored. The two images on the left + illustrate brick-to-pencil communication. The two images on the + right illustrate pencil-to-pencil communication, which in this + case transposes the *y* and *z* dimensions of the grid. + +Parallel 3d FFTs require substantial communication relative to their +computational cost. A 3d FFT is implemented by a series of 1d FFTs +along the *x-*, *y-*, and *z-*\ direction of the FFT grid. Thus the FFT +grid cannot be decomposed like atoms into 3 dimensions for parallel +processing of the FFTs but only in 1 (as planes) or 2 (as pencils) +dimensions and in between the steps the grid needs to be transposed to +have the FFT grid portion "owned" by each MPI process complete in the +direction of the 1d FFTs it has to perform. LAMMPS uses the +pencil-decomposition algorithm as shown in the :ref:`fft-parallel` figure. + +Initially (far left), each processor owns a brick of same-color grid +cells (actually grid points) contained within in its sub-domain. A +brick-to-pencil communication operation converts this layout to 1d +pencils in the *x*-dimension (center left). Again, cells of the same +color are owned by the same processor. Each processor can then compute +a 1d FFT on each pencil of data it wholly owns using a call to the +configured FFT library. A pencil-to-pencil communication then converts +this layout to pencils in the *y* dimension (center right) which +effectively transposes the *x* and *y* dimensions of the grid, followed +by 1d FFTs in *y*. A final transpose of pencils from *y* to *z* (far +right) followed by 1d FFTs in *z* completes the forward FFT. The data +is left in a *z*-pencil layout for the convolution operation. One or +more inverse FFTs then perform the sequence of 1d FFTs and communication +steps in reverse order; the final layout of resulting grid values is the +same as the initial brick layout. + +Each communication operation within the FFT (brick-to-pencil or +pencil-to-pencil or pencil-to-brick) converts one tiling of the 3d grid +to another, where a tiling in this context means an assignment of a +small brick-shaped subset of grid points to each processor, the union of +which comprise the entire grid. The parallel `fftMPI library +`_ written for LAMMPS allows arbitrary +definitions of the tiling so that an irregular partitioning of the +simulation domain can use it directly. Transforming data from one +tiling to another is implemented in `fftMPI` using point-to-point +communication, where each processor sends data to a few other +processors, since each tile in the initial tiling overlaps with a +handful of tiles in the final tiling. + +The transformations could also be done using collective communication +across all $P$ processors with a single call to ``MPI_Alltoall()``, but +this is typically much slower. However, for the specialized brick and +pencil tiling illustrated in :ref:`fft-parallel` figure, collective +communication across the entire MPI communicator is not required. In +the example an :math:`8^3` grid with 512 grid cells is partitioned +across 64 processors; each processor owns a 2x2x2 3d brick of grid +cells. The initial brick-to-pencil communication (upper left to upper +right) only requires collective communication within subgroups of 4 +processors, as illustrated by the 4 colors. More generally, a +brick-to-pencil communication can be performed by partitioning *P* +processors into :math:`P^{\frac{2}{3}}` subgroups of +:math:`P^{\frac{1}{3}}` processors each. Each subgroup performs +collective communication only within its subgroup. Similarly, +pencil-to-pencil communication can be performed by partitioning *P* +processors into :math:`P^{\frac{1}{2}}` subgroups of +:math:`P^{\frac{1}{2}}` processors each. This is illustrated in the +figure for the :math:`y \Rightarrow z` communication (center). An +eight-processor subgroup owns the front *yz* plane of data and performs +collective communication within the subgroup to transpose from a +*y*-pencil to *z*-pencil layout. + +LAMMPS invokes point-to-point communication by default, but also +provides the option of partitioned collective communication when using a +:doc:`kspace_modify collective yes ` command to switch to +that mode. In the latter case, the code detects the size of the +disjoint subgroups and partitions the single *P*-size communicator into +multiple smaller communicators, each of which invokes collective +communication. Testing on a large IBM Blue Gene/Q machine at Argonne +National Labs showed a significant improvement in FFT performance for +large processor counts; partitioned collective communication was faster +than point-to-point communication or global collective communication +involving all *P* processors. + +Here are some additional details about FFTs for long-range and related +grid/particle operations that LAMMPS supports: + +- The fftMPI library allows each grid dimension to be a multiple of + small prime factors (2,3,5), and allows any number of processors to + perform the FFT. The resulting brick and pencil decompositions are + thus not always as well-aligned but the size of subgroups of + processors for the two modes of communication (brick/pencil and + pencil/pencil) still scale as :math:`O(P^{\frac{1}{3}})` and + :math:`O(P^{\frac{1}{2}})`. + +- For efficiency in performing 1d FFTs, the grid transpose + operations illustrated in Figure \ref{fig:fft} also involve + reordering the 3d data so that a different dimension is contiguous + in memory. This reordering can be done during the packing or + unpacking of buffers for MPI communication. + +- For large systems and particularly a large number of MPI processes, + the dominant cost for parallel FFTs is often the communication, not + the computation of 1d FFTs, even though the latter scales as :math:`N + \log(N)` in the number of grid points *N* per grid direction. This is + due to the fact that only a 2d decomposition into pencils is possible + while atom data (and their corresponding short-range force and energy + computations) can be decomposed efficiently in 3d. + + This can be addressed by reducing the number of MPI processes involved + in the MPI communication by using :doc:`hybrid MPI + OpenMP + parallelization `. This will use OpenMP parallelization + inside the MPI domains and while that may have a lower parallel + efficiency, it reduces the communication overhead. + + As an alternative it is also possible to start a :ref:`multi-partition + ` calculation and then use the :doc:`verlet/split + integrator ` to perform the PPPM computation on a + dedicated, separate partition of MPI processes. This uses an integer + "1:*p*" mapping of *p* sub-domains of the atom decomposition to one + sub-domain of the FFT grid decomposition and where pairwise non-bonded + and bonded forces and energies are computed on the larger partition + and the PPPM kspace computation concurrently on the smaller partition. + +- LAMMPS also implements PPPM-based solvers for other long-range + interactions, dipole and dispersion (Lennard-Jones), which can be used + in conjunction with long-range Coulombics for point charges. + +- LAMMPS implements a ``GridComm`` class which overlays the simulation + domain with a regular grid, partitions it across processors in a + manner consistent with processor sub-domains, and provides methods for + forward and reverse communication of owned and ghost grid point + values. It is used for PPPM as an FFT grid (as outlined above) and + also for the MSM algorithm which uses a cascade of grid sizes from + fine to coarse to compute long-range Coulombic forces. The GridComm + class is also useful for models where continuum fields interact with + particles. For example, the two-temperature model (TTM) defines heat + transfer between atoms (particles) and electrons (continuum gas) where + spatial variations in the electron temperature are computed by finite + differences of a discretized heat equation on a regular grid. The + :doc:`fix ttm/grid ` command uses the ``GridComm`` class + internally to perform its grid operations on a distributed grid + instead of the original :doc:`fix ttm ` which uses a + replicated grid. diff --git a/doc/src/Developer_par_neigh.rst b/doc/src/Developer_par_neigh.rst new file mode 100644 index 0000000000..4b286d77d8 --- /dev/null +++ b/doc/src/Developer_par_neigh.rst @@ -0,0 +1,159 @@ +Neighbor lists +^^^^^^^^^^^^^^ + +To compute forces efficiently, each processor creates a Verlet-style +neighbor list which enumerates all pairs of atoms *i,j* (*i* = owned, +*j* = owned or ghost) with separation less than the applicable +neighbor list cutoff distance. In LAMMPS the neighbor lists are stored +in a multiple-page data structure; each page is a contiguous chunk of +memory which stores vectors of neighbor atoms *j* for many *i* atoms. +This allows pages to be incrementally allocated or deallocated in blocks +as needed. Neighbor lists typically consume the most memory of any data +structure in LAMMPS. The neighbor list is rebuilt (from scratch) once +every few timesteps, then used repeatedly each step for force or other +computations. The neighbor cutoff distance is :math:`R_n = R_f + +\Delta_s`, where :math:`R_f` is the (largest) force cutoff defined by +the interatomic potential for computing short-range pairwise or manybody +forces and :math:`\Delta_s` is a "skin" distance that allows the list to +be used for multiple steps assuming that atoms do not move very far +between consecutive time steps. Typically the code triggers +reneighboring when any atom has moved half the skin distance since the +last reneighboring; this and other options of the neighbor list rebuild +can be adjusted with the :doc:`neigh_modify ` command. + +On steps when reneighboring is performed, atoms which have moved outside +their owning processor's sub-domain are first migrated to new processors +via communication. Periodic boundary conditions are also (only) +enforced on these steps to ensure each atom is re-assigned to the +correct processor. After migration, the atoms owned by each processor +are stored in a contiguous vector. Periodically each processor +spatially sorts owned atoms within its vector to reorder it for improved +cache efficiency in force computations and neighbor list building. For +that atoms are spatially binned and then reordered so that atoms in the +same bin are adjacent in the vector. Atom sorting can be disabled or +its settings modified with the :doc:`atom_modify ` command. + +.. _neighbor-stencil: +.. figure:: img/neigh-stencil.png + :align: center + + neighbor list stencils + + A 2d simulation sub-domain (thick black line) and the corresponding + ghost atom cutoff region (dashed blue line) for both orthogonal + (left) and triclinic (right) domains. A regular grid of neighbor + bins (thin lines) overlays the entire simulation domain and need not + align with sub-domain boundaries; only the portion overlapping the + augmented sub-domain is shown. In the triclinic case it overlaps the + bounding box of the tilted rectangle. The blue- and red-shaded bins + represent a stencil of bins searched to find neighbors of a particular + atom (black dot). + +To build a local neighbor list in linear time, the simulation domain is +overlaid (conceptually) with a regular 3d (or 2d) grid of neighbor bins, +as shown in the :ref:`neighbor-stencil` figure for 2d models and a +single MPI processor's sub-domain. Each processor stores a set of +neighbor bins which overlap its sub-domain extended by the neighbor +cutoff distance :math:`R_n`. As illustrated, the bins need not align +with processor boundaries; an integer number in each dimension is fit to +the size of the entire simulation box. + +Most often LAMMPS builds what it calls a "half" neighbor list where +each *i,j* neighbor pair is stored only once, with either atom *i* or +*j* as the central atom. The build can be done efficiently by using a +pre-computed "stencil" of bins around a central origin bin which +contains the atom whose neighbors are being searched for. A stencil +is simply a list of integer offsets in *x,y,z* of nearby bins +surrounding the origin bin which are close enough to contain any +neighbor atom *j* within a distance :math:`R_n` from any atom *i* in the +origin bin. Note that for a half neighbor list, the stencil can be +asymmetric since each atom only need store half its nearby neighbors. + +These stencils are illustrated in the figure for a half list and a bin +size of :math:`\frac{1}{2} R_n`. There are 13 red+blue stencil bins in +2d (for the orthogonal case, 15 for triclinic). In 3d there would be +63, 13 in the plane of bins that contain the origin bin and 25 in each +of the two planes above it in the *z* direction (75 for triclinic). The +reason the triclinic stencil has extra bins is because the bins tile the +bounding box of the entire triclinic domain and thus are not periodic +with respect to the simulation box itself. The stencil and logic for +determining which *i,j* pairs to include in the neighbor list are +altered slightly to account for this. + +To build a neighbor list, a processor first loops over its "owned" plus +"ghost" atoms and assigns each to a neighbor bin. This uses an integer +vector to create a linked list of atom indices within each bin. It then +performs a triply-nested loop over its owned atoms *i*, the stencil of +bins surrounding atom *i*'s bin, and the *j* atoms in each stencil bin +(including ghost atoms). If the distance :math:`r_{ij} < R_n`, then +atom *j* is added to the vector of atom *i*'s neighbors. + +Here are additional details about neighbor list build options LAMMPS +supports: + +- The choice of bin size is an option; a size half of :math:`R_n` has + been found to be optimal for many typical cases. Smaller bins incur + additional overhead to loop over; larger bins require more distance + calculations. Note that for smaller bin sizes, the 2d stencil in the + figure would be more semi-circular in shape (hemispherical in 3d), + with bins near the corners of the square eliminated due to their + distance from the origin bin. + +- Depending on the interatomic potential(s) and other commands used in + an input script, multiple neighbor lists and stencils with different + attributes may be needed. This includes lists with different cutoff + distances, e.g. for force computation versus occasional diagnostic + computations such as a radial distribution function, or for the + r-RESPA time integrator which can partition pairwise forces by + distance into subsets computed at different time intervals. It + includes "full" lists (as opposed to half lists) where each *i,j* pair + appears twice, stored once with *i* and *j*, and which use a larger + symmetric stencil. It also includes lists with partial enumeration of + ghost atom neighbors. The full and ghost-atom lists are used by + various manybody interatomic potentials. Lists may also use different + criteria for inclusion of a pair interaction. Typically this simply + depends only on the distance between two atoms and the cutoff + distance. But for finite-size coarse-grained particles with + individual diameters (e.g. polydisperse granular particles), it can + also depend on the diameters of the two particles. + +- When using :doc:`pair style hybrid ` multiple sub-lists + of the master neighbor list for the full system need to be generated, + one for each sub-style, which contains only the *i,j* pairs needed to + compute interactions between subsets of atoms for the corresponding + potential. This means not all *i* or *j* atoms owned by a processor + are included in a particular sub-list. + +- Some models use different cutoff lengths for pairwise interactions + between different kinds of particles which are stored in a single + neighbor list. One example is a solvated colloidal system with large + colloidal particles where colloid/colloid, colloid/solvent, and + solvent/solvent interaction cutoffs can be dramatically different. + Another is a model of polydisperse finite-size granular particles; + pairs of particles interact only when they are in contact with each + other. Mixtures with particle size ratios as high as 10-100x may be + used to model realistic systems. Efficient neighbor list building + algorithms for these kinds of systems are available in LAMMPS. They + include a method which uses different stencils for different cutoff + lengths and trims the stencil to only include bins that straddle the + cutoff sphere surface. More recently a method which uses both + multiple stencils and multiple bin sizes was developed; it builds + neighbor lists efficiently for systems with particles of any size + ratio, though other considerations (timestep size, force computations) + may limit the ability to model systems with huge polydispersity. + +- For small and sparse systems and as a fallback method, LAMMPS also + supports neighbor list construction without binning by using a full + :math:`O(N^2)` loop over all *i,j* atom pairs in a sub-domain when + using the :doc:`neighbor nsq ` command. + +- Dependent on the "pair" setting of the :doc:`newton ` command, + the "half" neighbor lists may contain **all** pairs of atoms where + atom *j* is a ghost atom (i.e. when the newton pair setting is *off*) + For the newton pair *on* setting the atom *j* is only added to the + list if its *z* coordinate is larger, or if equal the *y* coordinate + is larger, and that is equal, too, the *x* coordinate is larger. For + homogeneously dense systems that will result in picking neighbors from + a same size sector in always the same direction relative to the + "owned" atom and thus it should lead to similar length neighbor lists + and thus reduce the chance of a load imbalance. diff --git a/doc/src/Developer_par_openmp.rst b/doc/src/Developer_par_openmp.rst new file mode 100644 index 0000000000..91c649a7b8 --- /dev/null +++ b/doc/src/Developer_par_openmp.rst @@ -0,0 +1,114 @@ +OpenMP Parallelism +^^^^^^^^^^^^^^^^^^ + +The styles in the INTEL, KOKKOS, and OPENMP package offer to use OpenMP +thread parallelism to predominantly distribute loops over local data +and thus follow an orthogonal parallelization strategy to the +decomposition into spatial domains used by the :doc:`MPI partitioning +`. For clarity, this section discusses only the +implementation in the OPENMP package as it is the simplest. The INTEL +and KOKKOS package offer additional options and are more complex since +they support more features and different hardware like co-processors +or GPUs. + +One of the key decisions when implementing the OPENMP package was to +keep the changes to the source code small, so that it would be easier to +maintain the code and keep it in sync with the non-threaded standard +implementation. this is achieved by a) making the OPENMP version a +derived class from the regular version (e.g. ``PairLJCutOMP`` from +``PairLJCut``) and overriding only methods that are multi-threaded or +need to be modified to support multi-threading (similar to what was done +in the OPT package), b) keeping the structure in the modified code very +similar so that side-by-side comparisons are still useful, and c) +offloading additional functionality and multi-thread support functions +into three separate classes ``ThrOMP``, ``ThrData``, and ``FixOMP``. +``ThrOMP`` provides additional, multi-thread aware functionality not +available in the corresponding base class (e.g. ``Pair`` for +``PairLJCutOMP``) like multi-thread aware variants of the "tally" +functions. Those functions are made available through multiple +inheritance so those new functions have to have unique names to avoid +ambiguities; typically ``_thr`` is appended to the name of the function. +``ThrData`` is a classes that manages per-thread data structures. +It is used instead of extending the corresponding storage to per-thread +arrays to avoid slowdowns due to "false sharing" when multiple threads +update adjacent elements in an array and thus force the CPU cache lines +to be reset and re-fetched. ``FixOMP`` finally manages the "multi-thread +state" like settings and access to per-thread storage, it is activated +by the :doc:`package omp ` command. + +Avoiding data races +""""""""""""""""""" + +A key problem when implementing thread parallelism in an MD code is +to avoid data races when updating accumulated properties like forces, +energies, and stresses. When interactions are computed, they always +involve multiple atoms and thus there are race conditions when multiple +threads want to update per-atom data of the same atoms. Five possible +strategies have been considered to avoid this: + +1) restructure the code so that there is no overlapping access possible + when computing in parallel, e.g. by breaking lists into multiple + parts and synchronizing threads in between. +2) have each thread be "responsible" for a specific group of atoms and + compute these interactions multiple times, once on each thread that + is responsible for a given atom and then have each thread only update + the properties of this atom. +3) use mutexes around functions and regions of code where the data race + could happen +4) use atomic operations when updating per-atom properties +5) use replicated per-thread data structures to accumulate data without + conflicts and then use a reduction to combine those results into the + data structures used by the regular style. + +Option 5 was chosen for the OPENMP package because it would retain the +performance for the case of 1 thread and the code would be more +maintainable. Option 1 would require extensive code changes, +particularly to the neighbor list code; options 2 would have incurred a +2x or more performance penalty for the serial case; option 3 causes +significant overhead and would enforce serialization of operations in +inner loops and thus defeat the purpose of multi-threading; option 4 +slows down the serial case although not quite as bad as option 2. The +downside of option 5 is that the overhead of the reduction operations +grows with the number of threads used, so there would be a crossover +point where options 2 or 4 would result in faster executing. That is +why option 2 for example is used in the GPU package because a GPU is a +processor with a massive number of threads. However, since the MPI +parallelization is generally more effective for typical MD systems, the +expectation is that thread parallelism is only used for a smaller number +of threads (2-8). At the time of its implementation, that number was +equivalent to the number of CPU cores per CPU socket on high-end +supercomputers. + +Thus arrays like the force array are dimensioned to the number of atoms +times the number of threads when enabling OpenMP support and inside the +compute functions a pointer to a different chunk is obtained by each thread. +Similarly, accumulators like potential energy or virial are kept in +per-thread instances of the ``ThrData`` class and then only reduced and +stored in their global counterparts at the end of the force computation. + + +Loop scheduling +""""""""""""""" + +Multi-thread parallelization is applied by distributing (outer) loops +statically across threads. Typically this would be the loop over local +atoms *i* when processing *i,j* pairs of atoms from a neighbor list. +The design of the neighbor list code results in atoms having a similar +number of neighbors for homogeneous systems and thus load imbalances +across threads are not common and typically happen for systems where +also the MPI parallelization would be unbalanced, which would typically +have a more pronounced impact on the performance. This same loop +scheduling scheme can also be applied to the reduction operations on +per-atom data to try and reduce the overhead of the reduction operation. + +Neighbor list parallelization +""""""""""""""""""""""""""""" + +In addition to the parallelization of force computations, also the +generation of the neighbor lists is parallelized. As explained +previously, neighbor lists are built by looping over "owned" atoms and +storing the neighbors in "pages". In the OPENMP variants of the +neighbor list code, each thread operates on a different chunk of "owned" +atoms and allocates and fills its own set of pages with neighbor list +data. This is achieved by each thread keeping its own instance of the +:cpp:class:`MyPage ` page allocator class. diff --git a/doc/src/Developer_par_part.rst b/doc/src/Developer_par_part.rst new file mode 100644 index 0000000000..f797f559e2 --- /dev/null +++ b/doc/src/Developer_par_part.rst @@ -0,0 +1,89 @@ +Partitioning +^^^^^^^^^^^^ + +The underlying spatial decomposition strategy used by LAMMPS for +distributed-memory parallelism is set with the :doc:`comm_style command +` and can be either "brick" (a regular grid) or "tiled". + +.. _domain-decomposition: +.. figure:: img/domain-decomp.png + :align: center + + domain decomposition + + This figure shows the different kinds of domain decomposition used + for MPI parallelization: "brick" on the left with an orthogonal + (left) and a triclinic (middle) simulation domain, and a "tiled" + decomposition (right). The black lines show the division into + sub-domains and the contained atoms are "owned" by the corresponding + MPI process. The green dashed lines indicate how sub-domains are + extended with "ghost" atoms up to the communication cutoff distance. + +The LAMMPS simulation box is a 3d or 2d volume, which can be orthogonal +or triclinic in shape, as illustrated in the :ref:`domain-decomposition` +figure for the 2d case. Orthogonal means the box edges are aligned with +the *x*, *y*, *z* Cartesian axes, and the box faces are thus all +rectangular. Triclinic allows for a more general parallelepiped shape +in which edges are aligned with three arbitrary vectors and the box +faces are parallelograms. In each dimension box faces can be periodic, +or non-periodic with fixed or shrink-wrapped boundaries. In the fixed +case, atoms which move outside the face are deleted; shrink-wrapped +means the position of the box face adjusts continuously to enclose all +the atoms. + +For distributed-memory MPI parallelism, the simulation box is spatially +decomposed (partitioned) into non-overlapping sub-domains which fill the +box. The default partitioning, "brick", is most suitable when atom +density is roughly uniform, as shown in the left-side images of the +:ref:`domain-decomposition` figure. The sub-domains comprise a regular +grid and all sub-domains are identical in size and shape. Both the +orthogonal and triclinic boxes can deform continuously during a +simulation, e.g. to compress a solid or shear a liquid, in which case +the processor sub-domains likewise deform. + + +For models with non-uniform density, the number of particles per +processor can be load-imbalanced with the default partitioning. This +reduces parallel efficiency, as the overall simulation rate is limited +by the slowest processor, i.e. the one with the largest computational +load. For such models, LAMMPS supports multiple strategies to reduce +the load imbalance: + +- The processor grid decomposition is by default based on the simulation + cell volume and tries to optimize the volume to surface ratio for the sub-domains. + This can be changed with the :doc:`processors command `. +- The parallel planes defining the size of the sub-domains can be shifted + with the :doc:`balance command `. Which can be done in addition + to choosing a more optimal processor grid. +- The recursive bisectioning algorithm in combination with the "tiled" + communication style can produce a partitioning with equal numbers of + particles in each sub-domain. + + +.. |decomp1| image:: img/decomp-regular.png + :width: 24% + +.. |decomp2| image:: img/decomp-processors.png + :width: 24% + +.. |decomp3| image:: img/decomp-balance.png + :width: 24% + +.. |decomp4| image:: img/decomp-rcb.png + :width: 24% + +|decomp1| |decomp2| |decomp3| |decomp4| + +The pictures above demonstrate different decompositions for a 2d system +with 12 MPI ranks. The atom colors indicate the load imbalance of each +sub-domain with green being optimal and red the least optimal. + +Due to the vacuum in the system, the default decomposition is unbalanced +with several MPI ranks without atoms (left). By forcing a 1x12x1 +processor grid, every MPI rank does computations now, but number of +atoms per sub-domain is still uneven and the thin slice shape increases +the amount of communication between sub-domains (center left). With a +2x6x1 processor grid and shifting the sub-domain divisions, the load +imbalance is further reduced and the amount of communication required +between sub-domains is less (center right). And using the recursive +bisectioning leads to further improved decomposition (right). diff --git a/doc/src/Developer_parallel.rst b/doc/src/Developer_parallel.rst new file mode 100644 index 0000000000..c7bfcfca9e --- /dev/null +++ b/doc/src/Developer_parallel.rst @@ -0,0 +1,28 @@ +Parallel algorithms +------------------- + +LAMMPS is designed to enable running simulations in parallel using the +MPI parallel communication standard with distributed data via domain +decomposition. The parallelization aims to be efficient result in good +strong scaling (= good speedup for the same system) and good weak +scaling (= the computational cost of enlarging the system is +proportional to the system size). Additional parallelization using GPUs +or OpenMP can also be applied within the sub-domain assigned to an MPI +process. For clarity, most of the following illustrations show the 2d +simulation case. The underlying algorithms in those cases, however, +apply to both 2d and 3d cases equally well. + +.. note:: + + The text and most of the figures in this chapter were adapted + for the manual from the section on parallel algorithms in the + :ref:`new LAMMPS paper `. + +.. toctree:: + :maxdepth: 1 + + Developer_par_part + Developer_par_comm + Developer_par_neigh + Developer_par_long + Developer_par_openmp diff --git a/doc/src/Developer_platform.rst b/doc/src/Developer_platform.rst new file mode 100644 index 0000000000..4cea36f94c --- /dev/null +++ b/doc/src/Developer_platform.rst @@ -0,0 +1,149 @@ +Platform abstraction functions +------------------------------ + +The ``platform`` sub-namespace inside the ``LAMMPS_NS`` namespace +provides a collection of wrapper and convenience functions and utilities +that perform common tasks for which platform specific code would be +required or for which a more high-level abstraction would be convenient +and reduce duplicated code. This reduces redundant implementations and +encourages consistent behavior and thus has some overlap with the +:doc:`"utils" sub-namespace `. + +Time functions +^^^^^^^^^^^^^^ + +.. doxygenfunction:: cputime + :project: progguide + +.. doxygenfunction:: walltime + :project: progguide + +.. doxygenfunction:: usleep + :project: progguide + +Platform information functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: os_info + :project: progguide + +.. doxygenfunction:: compiler_info + :project: progguide + +.. doxygenfunction:: cxx_standard + :project: progguide + +.. doxygenfunction:: openmp_standard + :project: progguide + +.. doxygenfunction:: mpi_vendor + :project: progguide + +.. doxygenfunction:: mpi_info + :project: progguide + + +File and path functions and global constants +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenvariable:: filepathsep + :project: progguide + +.. doxygenvariable:: pathvarsep + :project: progguide + +.. doxygenfunction:: guesspath + :project: progguide + +.. doxygenfunction:: path_basename + :project: progguide + +.. doxygenfunction:: path_join + :project: progguide + +.. doxygenfunction:: file_is_readable + :project: progguide + +.. doxygenfunction:: is_console + :project: progguide + +.. doxygenfunction:: path_is_directory + :project: progguide + +.. doxygenfunction:: current_directory + :project: progguide + +.. doxygenfunction:: list_directory + :project: progguide + +.. doxygenfunction:: chdir + :project: progguide + +.. doxygenfunction:: mkdir + :project: progguide + +.. doxygenfunction:: rmdir + :project: progguide + +.. doxygenfunction:: unlink + :project: progguide + +Standard I/O function wrappers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenvariable:: END_OF_FILE + :project: progguide + +.. doxygenfunction:: ftell + :project: progguide + +.. doxygenfunction:: fseek + :project: progguide + +.. doxygenfunction:: ftruncate + :project: progguide + +.. doxygenfunction:: popen + :project: progguide + +.. doxygenfunction:: pclose + :project: progguide + +Environment variable functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: putenv + :project: progguide + +.. doxygenfunction:: list_pathenv + :project: progguide + +.. doxygenfunction:: find_exe_path + :project: progguide + +Dynamically loaded object or library functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: dlopen + :project: progguide + +.. doxygenfunction:: dlclose + :project: progguide + +.. doxygenfunction:: dlsym + :project: progguide + +.. doxygenfunction:: dlerror + :project: progguide + +Compressed file I/O functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: has_compress_extension + :project: progguide + +.. doxygenfunction:: compressed_read + :project: progguide + +.. doxygenfunction:: compressed_write + :project: progguide diff --git a/doc/src/Developer_utils.rst b/doc/src/Developer_utils.rst index 17da8bef22..db47a9e3c3 100644 --- a/doc/src/Developer_utils.rst +++ b/doc/src/Developer_utils.rst @@ -7,7 +7,9 @@ a collection of convenience functions and utilities that perform common tasks that are required repeatedly throughout the LAMMPS code like reading or writing to files with error checking or translation of strings into specific types of numbers with checking for validity. This -reduces redundant implementations and encourages consistent behavior. +reduces redundant implementations and encourages consistent behavior and +thus has some overlap with the :doc:`"platform" sub-namespace +`. I/O with status check and similar functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,6 +62,9 @@ silently returning the result of a partial conversion or zero in cases where the string is not a valid number. This behavior allows to more easily detect typos or issues when processing input files. +Similarly the :cpp:func:`logical() ` function +will convert a string into a boolean and will only accept certain words. + The *do_abort* flag should be set to ``true`` in case this function is called only on a single MPI rank, as that will then trigger the a call to ``Error::one()`` for errors instead of ``Error::all()`` @@ -83,6 +88,9 @@ strings for compliance without conversion. .. doxygenfunction:: tnumeric :project: progguide +.. doxygenfunction:: logical + :project: progguide + String processing ^^^^^^^^^^^^^^^^^ @@ -95,6 +103,12 @@ and parsing files or arguments. .. doxygenfunction:: strdup :project: progguide +.. doxygenfunction:: lowercase + :project: progguide + +.. doxygenfunction:: uppercase + :project: progguide + .. doxygenfunction:: trim :project: progguide @@ -137,21 +151,6 @@ and parsing files or arguments. .. doxygenfunction:: is_double :project: progguide -File and path functions -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. doxygenfunction:: guesspath - :project: progguide - -.. doxygenfunction:: path_basename - :project: progguide - -.. doxygenfunction:: path_join - :project: progguide - -.. doxygenfunction:: file_is_readable - :project: progguide - Potential file functions ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/src/Howto_thermostat.rst b/doc/src/Howto_thermostat.rst index fbeb1f7785..fe53fff540 100644 --- a/doc/src/Howto_thermostat.rst +++ b/doc/src/Howto_thermostat.rst @@ -2,8 +2,8 @@ Thermostats =========== Thermostatting means controlling the temperature of particles in an MD -simulation. :doc:`Barostatting ` means controlling the -pressure. Since the pressure includes a kinetic component due to +simulation. :doc:`Barostatting ` means controlling +the pressure. Since the pressure includes a kinetic component due to particle velocities, both these operations require calculation of the temperature. Typically a target temperature (T) and/or pressure (P) is specified by the user, and the thermostat or barostat attempts to @@ -26,11 +26,13 @@ can be invoked via the *dpd/tstat* pair style: * :doc:`pair_style dpd/tstat ` :doc:`Fix nvt ` only thermostats the translational velocity of -particles. :doc:`Fix nvt/sllod ` also does this, except -that it subtracts out a velocity bias due to a deforming box and -integrates the SLLOD equations of motion. See the :doc:`Howto nemd ` page for further details. :doc:`Fix nvt/sphere ` and :doc:`fix nvt/asphere ` thermostat not only translation -velocities but also rotational velocities for spherical and aspherical -particles. +particles. :doc:`Fix nvt/sllod ` also does this, +except that it subtracts out a velocity bias due to a deforming box +and integrates the SLLOD equations of motion. See the :doc:`Howto +nemd ` page for further details. :doc:`Fix nvt/sphere +` and :doc:`fix nvt/asphere ` +thermostat not only translation velocities but also rotational +velocities for spherical and aspherical particles. .. note:: @@ -40,25 +42,31 @@ particles. e.g. molecular systems. The latter can be tricky to do correctly. DPD thermostatting alters pairwise interactions in a manner analogous -to the per-particle thermostatting of :doc:`fix langevin `. +to the per-particle thermostatting of :doc:`fix langevin +`. -Any of the thermostatting fixes can be instructed to use custom temperature -computes that remove bias which has two effects: first, the current -calculated temperature, which is compared to the requested target temperature, -is calculated with the velocity bias removed; second, the thermostat adjusts -only the thermal temperature component of the particle's velocities, which are -the velocities with the bias removed. The removed bias is then added back -to the adjusted velocities. See the doc pages for the individual -fixes and for the :doc:`fix_modify ` command for -instructions on how to assign a temperature compute to a -thermostatting fix. For example, you can apply a thermostat to only -the x and z components of velocity by using it in conjunction with -:doc:`compute temp/partial `. Of you could -thermostat only the thermal temperature of a streaming flow of -particles without affecting the streaming velocity, by using -:doc:`compute temp/profile `. +Any of the thermostatting fixes can be instructed to use custom +temperature computes that remove bias which has two effects: first, +the current calculated temperature, which is compared to the requested +target temperature, is calculated with the velocity bias removed; +second, the thermostat adjusts only the thermal temperature component +of the particle's velocities, which are the velocities with the bias +removed. The removed bias is then added back to the adjusted +velocities. See the doc pages for the individual fixes and for the +:doc:`fix_modify ` command for instructions on how to +assign a temperature compute to a thermostatting fix. -Below is a list of some custom temperature computes that can be used like that: +For example, you can apply a thermostat only to atoms in a spatial +region by using it in conjunction with :doc:`compute temp/region +`. Or you can apply a thermostat to only the x +and z components of velocity by using it with :doc:`compute +temp/partial `. Of you could thermostat only +the thermal temperature of a streaming flow of particles without +affecting the streaming velocity, by using :doc:`compute temp/profile +`. + +Below is a list of custom temperature computes that can be used like +that: * :doc:`compute_temp_asphere` * :doc:`compute_temp_body` @@ -72,8 +80,6 @@ Below is a list of some custom temperature computes that can be used like that: * :doc:`compute_temp_rotate` * :doc:`compute_temp_sphere` - - .. note:: Only the nvt fixes perform time integration, meaning they update @@ -86,17 +92,17 @@ Below is a list of some custom temperature computes that can be used like that: * :doc:`fix nve/sphere ` * :doc:`fix nve/asphere ` -Thermodynamic output, which can be setup via the -:doc:`thermo_style ` command, often includes temperature -values. As explained on the page for the -:doc:`thermo_style ` command, the default temperature is -setup by the thermo command itself. It is NOT the temperature -associated with any thermostatting fix you have defined or with any -compute you have defined that calculates a temperature. The doc pages -for the thermostatting fixes explain the ID of the temperature compute -they create. Thus if you want to view these temperatures, you need to -specify them explicitly via the :doc:`thermo_style custom ` command. Or you can use the -:doc:`thermo_modify ` command to re-define what +Thermodynamic output, which can be setup via the :doc:`thermo_style +` command, often includes temperature values. As +explained on the page for the :doc:`thermo_style ` +command, the default temperature is setup by the thermo command +itself. It is NOT the temperature associated with any thermostatting +fix you have defined or with any compute you have defined that +calculates a temperature. The doc pages for the thermostatting fixes +explain the ID of the temperature compute they create. Thus if you +want to view these temperatures, you need to specify them explicitly +via the :doc:`thermo_style custom ` command. Or you can +use the :doc:`thermo_modify ` command to re-define what temperature compute is used for default thermodynamic output. ---------- diff --git a/doc/src/Intro_citing.rst b/doc/src/Intro_citing.rst index 978def9f15..0e10b7559a 100644 --- a/doc/src/Intro_citing.rst +++ b/doc/src/Intro_citing.rst @@ -4,28 +4,41 @@ Citing LAMMPS Core Algorithms ^^^^^^^^^^^^^^^ -Since LAMMPS is a community project, there is not a single one -publication or reference that describes **all** of LAMMPS. -The canonical publication that describes the foundation, that is -the basic spatial decomposition approach, the neighbor finding, -and basic communications algorithms used in LAMMPS is: +The paper mentioned below is the best overview of LAMMPS, but there are +also publications describing particular models or algorithms implemented +in LAMMPS or complementary software that is has interfaces to. Please +see below for how to cite contributions to LAMMPS. - `S. Plimpton, Fast Parallel Algorithms for Short-Range Molecular Dynamics, J Comp Phys, 117, 1-19 (1995). `_ +.. _lammps_paper: -So any project using LAMMPS (or a derivative application using LAMMPS as -a simulation engine) should cite this paper. A new publication -describing the developments and improvements of LAMMPS in the 25 years -since then is currently in preparation. +The latest canonical publication that describes the basic features, the +source code design, the program structure, the spatial decomposition +approach, the neighbor finding, basic communications algorithms, and how +users and developers have contributed to LAMMPS is: + + `LAMMPS - A flexible simulation tool for particle-based materials modeling at the atomic, meso, and continuum scales, Comp. Phys. Comm. (accepted 09/2021), DOI:10.1016/j.cpc.2021.108171 `_ + +So a project using LAMMPS or a derivative application that uses LAMMPS +as a simulation engine should cite this paper. The paper is expected to +be published in its final form under the same DOI in the first half +of 2022. Please also give the URL of the LAMMPS website in your paper, +namely https://www.lammps.org. + +The original publication describing the parallel algorithms used in the +initial versions of LAMMPS is: + + `S. Plimpton, Fast Parallel Algorithms for Short-Range Molecular Dynamics, J Comp Phys, 117, 1-19 (1995). `_ DOI for the LAMMPS code ^^^^^^^^^^^^^^^^^^^^^^^ -LAMMPS developers use the `Zenodo service at CERN -`_ to create digital object identifies (DOI) for -stable releases of the LAMMPS code. There are two types of DOIs for the -LAMMPS source code: the canonical DOI for **all** versions of LAMMPS, -which will always point to the **latest** stable release version is: +LAMMPS developers use the `Zenodo service at CERN `_ +to create digital object identifies (DOI) for stable releases of the +LAMMPS source code. There are two types of DOIs for the LAMMPS source code. + +The canonical DOI for **all** versions of LAMMPS, which will always +point to the **latest** stable release version is: - DOI: `10.5281/zenodo.3726416 `_ @@ -45,11 +58,13 @@ about LAMMPS and its features. Citing contributions ^^^^^^^^^^^^^^^^^^^^ -LAMMPS has many features and that use either previously published -methods and algorithms or novel features. It also includes potential -parameter filed for specific models. Where available, a reminder about -references for optional features used in a specific run is printed to -the screen and log file. Style and output location can be selected with -the :ref:`-cite command-line switch `. Additional references are +LAMMPS has many features that use either previously published methods +and algorithms or novel features. It also includes potential parameter +files for specific models. Where available, a reminder about references +for optional features used in a specific run is printed to the screen +and log file. Style and output location can be selected with the +:ref:`-cite command-line switch `. Additional references are given in the documentation of the :doc:`corresponding commands -` or in the :doc:`Howto tutorials `. +` or in the :doc:`Howto tutorials `. So please +make certain, that you provide the proper acknowledgments and citations +in any published works using LAMMPS. diff --git a/doc/src/Library_create.rst b/doc/src/Library_create.rst index 3566cb3cc9..8043819891 100644 --- a/doc/src/Library_create.rst +++ b/doc/src/Library_create.rst @@ -34,7 +34,7 @@ simple example demonstrating its use: int lmpargc = sizeof(lmpargv)/sizeof(const char *); /* create LAMMPS instance */ - handle = lammps_open_no_mpi(lmpargc, lmpargv, NULL); + handle = lammps_open_no_mpi(lmpargc, (char **)lmpargv, NULL); if (handle == NULL) { printf("LAMMPS initialization failed"); lammps_mpi_finalize(); diff --git a/doc/src/PDF/colvars-refman-lammps.pdf b/doc/src/PDF/colvars-refman-lammps.pdf index 8b6e5bffdc..011b3d0f04 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/Run_basics.rst b/doc/src/Run_basics.rst index 3d57633df2..5f1211d093 100644 --- a/doc/src/Run_basics.rst +++ b/doc/src/Run_basics.rst @@ -2,17 +2,25 @@ Basics of running LAMMPS ======================== LAMMPS is run from the command line, reading commands from a file via -the -in command line flag, or from standard input. -Using the "-in in.file" variant is recommended: +the -in command line flag, or from standard input. Using the "-in +in.file" variant is recommended (see note below). The name of the +LAMMPS executable is either ``lmp`` or ``lmp_`` with +`` being the machine string used when compiling LAMMPS. This +is required when compiling LAMMPS with the traditional build system +(e.g. with ``make mpi``), but optional when using CMake to configure and +build LAMMPS: .. code-block:: bash $ lmp_serial -in in.file $ lmp_serial < in.file + $ lmp -in in.file + $ lmp < in.file $ /path/to/lammps/src/lmp_serial -i in.file $ mpirun -np 4 lmp_mpi -in in.file + $ mpiexec -np 4 lmp -in in.file $ mpirun -np 8 /path/to/lammps/src/lmp_mpi -in in.file - $ mpirun -np 6 /usr/local/bin/lmp -in in.file + $ mpiexec -n 6 /usr/local/bin/lmp -in in.file You normally run the LAMMPS command in the directory where your input script is located. That is also where output files are produced by @@ -23,7 +31,7 @@ executable itself can be placed elsewhere. .. note:: The redirection operator "<" will not always work when running - in parallel with mpirun; for those systems the -in form is required. + in parallel with mpirun or mpiexec; for those systems the -in form is required. As LAMMPS runs it prints info to the screen and a logfile named *log.lammps*\ . More info about output is given on the diff --git a/doc/src/fix_langevin.rst b/doc/src/fix_langevin.rst index c8be9afc31..5979155799 100644 --- a/doc/src/fix_langevin.rst +++ b/doc/src/fix_langevin.rst @@ -138,16 +138,18 @@ 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. removing the center-of-mass velocity from a -group of atoms or removing 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 commands ` to determine which ones -include a bias. In this case, the thermostat works in the following -manner: bias is removed from each atom, thermostatting is performed on -the remaining thermal degrees of freedom, and the bias is added back -in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. The *damp* parameter is specified in time units and determines how rapidly the temperature is relaxed. For example, a value of 100.0 means @@ -183,7 +185,8 @@ omega (which is derived from the angular momentum in the case of aspherical particles). The rotational temperature of the particles can be monitored by the -:doc:`compute temp/sphere ` and :doc:`compute temp/asphere ` commands with their rotate +:doc:`compute temp/sphere ` and :doc:`compute +temp/asphere ` commands with their rotate options. For the *omega* keyword there is also a scale factor of diff --git a/doc/src/fix_langevin_drude.rst b/doc/src/fix_langevin_drude.rst index 3486723a67..89ea28cf08 100644 --- a/doc/src/fix_langevin_drude.rst +++ b/doc/src/fix_langevin_drude.rst @@ -167,17 +167,20 @@ 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. -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. removing the center-of-mass velocity from a group of -atoms. 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 commands ` to determine which ones -include a bias. In this case, the thermostat works in the following -manner: bias is removed from each atom, thermostatting is performed on -the remaining thermal degrees of freedom, and the bias is added back -in. NOTE: this feature has not been tested. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. Note: The temperature thermostatting the core-Drude particle pairs should be chosen low enough, so as to mimic as closely as possible the diff --git a/doc/src/fix_nh.rst b/doc/src/fix_nh.rst index 46b343fdce..cb9e6ba61e 100644 --- a/doc/src/fix_nh.rst +++ b/doc/src/fix_nh.rst @@ -486,19 +486,20 @@ temperature or pressure during thermodynamic output via the compute-ID. It also means that changing attributes of *thermo_temp* or *thermo_press* will have no effect on this fix. -Like other fixes that perform thermostatting, fix nvt and fix npt can -be used with :doc:`compute commands ` that calculate a -temperature after removing a "bias" from the atom velocities. -E.g. removing the center-of-mass velocity from a group of atoms or -only calculating temperature on the x-component of velocity or only -calculating temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_npt_asphere.rst b/doc/src/fix_npt_asphere.rst index 28edb59f8d..64e1c45be7 100644 --- a/doc/src/fix_npt_asphere.rst +++ b/doc/src/fix_npt_asphere.rst @@ -48,8 +48,9 @@ can also have a bias velocity removed from them before thermostatting takes place; see the description below. Additional parameters affecting the thermostat and barostat are -specified by keywords and values documented with the :doc:`fix npt ` command. See, for example, discussion of the *temp*, -*iso*, *aniso*, and *dilate* keywords. +specified by keywords and values documented with the :doc:`fix npt +` command. See, for example, discussion of the *temp*, *iso*, +*aniso*, and *dilate* keywords. The particles in the fix group are the only ones whose velocities and positions are updated by the velocity/position update portion of the @@ -89,18 +90,19 @@ It also means that changing attributes of *thermo_temp* or *thermo_press* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_npt_body.rst b/doc/src/fix_npt_body.rst index d44870a4fb..ff98638b63 100644 --- a/doc/src/fix_npt_body.rst +++ b/doc/src/fix_npt_body.rst @@ -87,18 +87,19 @@ It also means that changing attributes of *thermo_temp* or *thermo_press* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_npt_cauchy.rst b/doc/src/fix_npt_cauchy.rst index 13b5b7bf70..6ff3dffba3 100644 --- a/doc/src/fix_npt_cauchy.rst +++ b/doc/src/fix_npt_cauchy.rst @@ -400,19 +400,20 @@ temperature or pressure during thermodynamic output via the compute-ID. It also means that changing attributes of *thermo_temp* or *thermo_press* will have no effect on this fix. -Like other fixes that perform thermostatting, fix npt/cauchy can -be used with :doc:`compute commands ` that calculate a -temperature after removing a "bias" from the atom velocities. -E.g. removing the center-of-mass velocity from a group of atoms or -only calculating temperature on the x-component of velocity or only -calculating temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_npt_sphere.rst b/doc/src/fix_npt_sphere.rst index 75e4c9a4ec..bd52ca9dc5 100644 --- a/doc/src/fix_npt_sphere.rst +++ b/doc/src/fix_npt_sphere.rst @@ -103,18 +103,19 @@ appropriate compute-ID. It also means that changing attributes of *thermo_temp* or *thermo_press* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_nvt_asphere.rst b/doc/src/fix_nvt_asphere.rst index 00f4588f7f..7ce3aec125 100644 --- a/doc/src/fix_nvt_asphere.rst +++ b/doc/src/fix_nvt_asphere.rst @@ -72,18 +72,19 @@ It also means that changing attributes of *thermo_temp* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_nvt_body.rst b/doc/src/fix_nvt_body.rst index 28ad3e7857..7b9e996a5b 100644 --- a/doc/src/fix_nvt_body.rst +++ b/doc/src/fix_nvt_body.rst @@ -69,18 +69,19 @@ It also means that changing attributes of *thermo_temp* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_nvt_sllod.rst b/doc/src/fix_nvt_sllod.rst index 3d041ca767..4bb4478991 100644 --- a/doc/src/fix_nvt_sllod.rst +++ b/doc/src/fix_nvt_sllod.rst @@ -37,15 +37,16 @@ trajectory consistent with the canonical ensemble. This thermostat is used for a simulation box that is changing size and/or shape, for example in a non-equilibrium MD (NEMD) simulation. -The size/shape change is induced by use of the :doc:`fix deform ` command, so each point in the simulation box -can be thought of as having a "streaming" velocity. This -position-dependent streaming velocity is subtracted from each atom's -actual velocity to yield a thermal velocity which is used for -temperature computation and thermostatting. For example, if the box -is being sheared in x, relative to y, then points at the bottom of the -box (low y) have a small x velocity, while points at the top of the -box (hi y) have a large x velocity. These velocities do not -contribute to the thermal "temperature" of the atom. +The size/shape change is induced by use of the :doc:`fix deform +` command, so each point in the simulation box can be +thought of as having a "streaming" velocity. This position-dependent +streaming velocity is subtracted from each atom's actual velocity to +yield a thermal velocity which is used for temperature computation and +thermostatting. For example, if the box is being sheared in x, +relative to y, then points at the bottom of the box (low y) have a +small x velocity, while points at the top of the box (hi y) have a +large x velocity. These velocities do not contribute to the thermal +"temperature" of the atom. .. note:: @@ -60,13 +61,15 @@ contribute to the thermal "temperature" of the atom. consistent. The SLLOD equations of motion, originally proposed by Hoover and Ladd -(see :ref:`(Evans and Morriss) `), were proven to be equivalent to -Newton's equations of motion for shear flow by :ref:`(Evans and Morriss) `. They were later shown to generate the desired -velocity gradient and the correct production of work by stresses for -all forms of homogeneous flow by :ref:`(Daivis and Todd) `. As -implemented in LAMMPS, they are coupled to a Nose/Hoover chain -thermostat in a velocity Verlet formulation, closely following the -implementation used for the :doc:`fix nvt ` command. +(see :ref:`(Evans and Morriss) `), were proven to be +equivalent to Newton's equations of motion for shear flow by +:ref:`(Evans and Morriss) `. They were later shown to generate +the desired velocity gradient and the correct production of work by +stresses for all forms of homogeneous flow by :ref:`(Daivis and Todd) +`. As implemented in LAMMPS, they are coupled to a +Nose/Hoover chain thermostat in a velocity Verlet formulation, closely +following the implementation used for the :doc:`fix nvt ` +command. .. note:: @@ -94,27 +97,28 @@ underscore + "temp", and the group for the new compute is the same as the fix group. Note that this is NOT the compute used by thermodynamic output (see -the :doc:`thermo_style ` command) with ID = *thermo_temp*. -This means you can change the attributes of this fix's temperature -(e.g. its degrees-of-freedom) via the -:doc:`compute_modify ` command or print this temperature -during thermodynamic output via the :doc:`thermo_style custom ` command using the appropriate compute-ID. -It also means that changing attributes of *thermo_temp* will have no -effect on this fix. +the :doc:`thermo_style ` command) with ID = +*thermo_temp*. This means you can change the attributes of this fix's +temperature (e.g. its degrees-of-freedom) via the :doc:`compute_modify +` command or print this temperature during +thermodynamic output via the :doc:`thermo_style custom ` +command using the appropriate compute-ID. It also means that changing +attributes of *thermo_temp* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_nvt_sphere.rst b/doc/src/fix_nvt_sphere.rst index 31c8d91889..91575d4c48 100644 --- a/doc/src/fix_nvt_sphere.rst +++ b/doc/src/fix_nvt_sphere.rst @@ -86,18 +86,19 @@ It also means that changing attributes of *thermo_temp* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_saed_vtk.rst b/doc/src/fix_saed_vtk.rst index a9e8f154e6..dd5db32966 100644 --- a/doc/src/fix_saed_vtk.rst +++ b/doc/src/fix_saed_vtk.rst @@ -28,7 +28,6 @@ Syntax Nstart = start averaging on this timestep *file* arg = filename filename = name of file to output time averages to - *overwrite* arg = none = overwrite output file with only latest output Examples """""""" @@ -161,10 +160,6 @@ the *file* keyword and this string is appended with _N.vtk where N is an index (0,1,2...) to account for situations with multiple diffraction intensity outputs. -The *overwrite* keyword will continuously overwrite the output file -with the latest output, so that it only contains one timestep worth of -output. This option can only be used with the *ave running* setting. - Restart, fix_modify, output, run start/stop, minimize info """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" diff --git a/doc/src/fix_temp_berendsen.rst b/doc/src/fix_temp_berendsen.rst index 89fc2392f4..473c30aced 100644 --- a/doc/src/fix_temp_berendsen.rst +++ b/doc/src/fix_temp_berendsen.rst @@ -102,18 +102,19 @@ It also means that changing attributes of *thermo_temp* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_temp_csvr.rst b/doc/src/fix_temp_csvr.rst index 81379f346b..5fc6e8eae7 100644 --- a/doc/src/fix_temp_csvr.rst +++ b/doc/src/fix_temp_csvr.rst @@ -110,28 +110,29 @@ during thermodynamic output via the :doc:`thermo_style custom ` co It also means that changing attributes of *thermo_temp* will have no effect on this fix. -Like other fixes that perform thermostatting, these fixes can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal degrees of freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. An important feature of these thermostats is that they have an -associated effective energy that is a constant of motion. -The effective energy is the total energy (kinetic + potential) plus -the accumulated kinetic energy changes due to the thermostat. The -latter quantity is the global scalar computed by these fixes. This -feature is useful to check the integration of the equations of motion -against discretization errors. In other words, the conservation of -the effective energy can be used to choose an appropriate integration +associated effective energy that is a constant of motion. The +effective energy is the total energy (kinetic + potential) plus the +accumulated kinetic energy changes due to the thermostat. The latter +quantity is the global scalar computed by these fixes. This feature is +useful to check the integration of the equations of motion against +discretization errors. In other words, the conservation of the +effective energy can be used to choose an appropriate integration :doc:`timestep `. This is similar to the usual paradigm of checking the conservation of the total energy in the microcanonical ensemble. diff --git a/doc/src/fix_temp_rescale.rst b/doc/src/fix_temp_rescale.rst index a61773d2a2..41ad8709cc 100644 --- a/doc/src/fix_temp_rescale.rst +++ b/doc/src/fix_temp_rescale.rst @@ -109,19 +109,19 @@ command using the appropriate compute-ID. It also means that changing attributes of *thermo_temp* will have no effect on this fix. Like other fixes that perform thermostatting, this fix can be used -with :doc:`compute commands ` that calculate a temperature -after removing a "bias" from the atom velocities. E.g. removing the -center-of-mass velocity from a group of atoms or only calculating -temperature on the x-component of velocity or only calculating -temperature for atoms in a geometric region. 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 commands -` to determine which ones include a bias. In this case, the -thermostat works in the following manner: the current temperature is -calculated taking the bias into account, bias is removed from each -atom, thermostatting is performed on the remaining thermal degrees of -freedom, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. ---------- diff --git a/doc/src/fix_tgnh_drude.rst b/doc/src/fix_tgnh_drude.rst index 7088692353..d1f5cf19a4 100644 --- a/doc/src/fix_tgnh_drude.rst +++ b/doc/src/fix_tgnh_drude.rst @@ -187,26 +187,32 @@ barostatting. ---------- -Like other fixes that perform thermostatting, these fixes can -be used with :doc:`compute commands ` that calculate a -temperature after removing a "bias" from the atom velocities. -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 commands ` to determine which ones include a bias. In -this case, the thermostat works in the following manner: the current -temperature is calculated taking the bias into account, bias is -removed from each atom, thermostatting is performed on the remaining -thermal DOF, and the bias is added back in. +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. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. .. note:: - However, not all temperature compute commands are valid to be used with these fixes. - Precisely, only temperature compute that does not modify the DOF of the group can be used. - E.g. :doc:`compute temp/ramp ` and :doc:`compute viscosity/cos ` - compute the kinetic energy after remove a velocity gradient without affecting the DOF of the group, - then they can be invoked in this way. - In contrast, :doc:`compute temp/partial ` may remove the DOF at one or more dimensions, - therefore it cannot be used with these fixes. + However, not all temperature compute commands are valid to be used + with these fixes. Precisely, only temperature compute that does + not modify the DOF of the group can be used. E.g. :doc:`compute + temp/ramp ` and :doc:`compute viscosity/cos + ` compute the kinetic energy after remove a + velocity gradient without affecting the DOF of the group, then they + can be invoked in this way. In contrast, :doc:`compute + temp/partial ` may remove the DOF at one or + more dimensions, therefore it cannot be used with these fixes. ---------- diff --git a/doc/src/group.rst b/doc/src/group.rst index e72eeb7c19..36559ba68a 100644 --- a/doc/src/group.rst +++ b/doc/src/group.rst @@ -38,7 +38,7 @@ Syntax *intersect* args = two or more group IDs *dynamic* args = parent-ID keyword value ... one or more keyword/value pairs may be appended - keyword = *region* or *var* or *every* + keyword = *region* or *var* or *property* or *every* *region* value = region-ID *var* value = name of variable *property* value = name of custom integer or floating point vector diff --git a/doc/src/img/decomp-balance.png b/doc/src/img/decomp-balance.png new file mode 100644 index 0000000000..eb00e8e89a Binary files /dev/null and b/doc/src/img/decomp-balance.png differ diff --git a/doc/src/img/decomp-processors.png b/doc/src/img/decomp-processors.png new file mode 100644 index 0000000000..0d68f3679f Binary files /dev/null and b/doc/src/img/decomp-processors.png differ diff --git a/doc/src/img/decomp-rcb.png b/doc/src/img/decomp-rcb.png new file mode 100644 index 0000000000..0e38efa7ea Binary files /dev/null and b/doc/src/img/decomp-rcb.png differ diff --git a/doc/src/img/decomp-regular.png b/doc/src/img/decomp-regular.png new file mode 100644 index 0000000000..a8c645033d Binary files /dev/null and b/doc/src/img/decomp-regular.png differ diff --git a/doc/src/img/domain-decomp.png b/doc/src/img/domain-decomp.png new file mode 100644 index 0000000000..a0a5cc06f2 Binary files /dev/null and b/doc/src/img/domain-decomp.png differ diff --git a/doc/src/img/fft-decomp-parallel.png b/doc/src/img/fft-decomp-parallel.png new file mode 100644 index 0000000000..80f69bd033 Binary files /dev/null and b/doc/src/img/fft-decomp-parallel.png differ diff --git a/doc/src/img/ghost-comm.png b/doc/src/img/ghost-comm.png new file mode 100644 index 0000000000..a402daa054 Binary files /dev/null and b/doc/src/img/ghost-comm.png differ diff --git a/doc/src/img/neigh-stencil.png b/doc/src/img/neigh-stencil.png new file mode 100644 index 0000000000..7d06f6ae14 Binary files /dev/null and b/doc/src/img/neigh-stencil.png differ diff --git a/doc/utils/requirements.txt b/doc/utils/requirements.txt index 7e4563a1ec..9b8e106875 100644 --- a/doc/utils/requirements.txt +++ b/doc/utils/requirements.txt @@ -1,4 +1,4 @@ -Sphinx==4.0.3 +Sphinx sphinxcontrib-spelling git+git://github.com/akohlmey/sphinx-fortran@parallel-read sphinx_tabs diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 5394cf92c1..ccc321c7e0 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -1135,6 +1135,7 @@ Germann Germano gerolf Gerolf +getrusage Gershgorin getter gettimeofday @@ -1222,6 +1223,7 @@ Guo gw gyromagnetic gz +gzip gzipped Haak Hafskjold @@ -1809,6 +1811,7 @@ lyon Lysogorskiy Lyulin lz +lzma Maaravi MACHDYN machdyn @@ -2262,6 +2265,7 @@ Nmols nn nnodes Nocedal +nO nocite nocoeff nodeless @@ -2761,6 +2765,7 @@ REAXFF ReaxFF reaxff rebo +recurse recursing Ree refactored @@ -3440,6 +3445,7 @@ usec uSemiParallel userguide username +usleep usr util utils @@ -3657,6 +3663,7 @@ Yc ycm Yeh yellowgreen +yEs Yethiraj yflag yhi diff --git a/examples/PACKAGES/charge_regulation/in.chreg-polymer b/examples/PACKAGES/charge_regulation/in.chreg-polymer index 0adab9b5e7..055032c018 100644 --- a/examples/PACKAGES/charge_regulation/in.chreg-polymer +++ b/examples/PACKAGES/charge_regulation/in.chreg-polymer @@ -8,7 +8,7 @@ bond_style harmonic bond_coeff 1 100 1.122462 # K R0 velocity all create 1.0 8008 loop geom -pair_style lj/cut/coul/long 1.122462 20 +pair_style lj/cut/coul/long/soft 2 0.5 10.0 1.122462 20 pair_coeff * * 1.0 1.0 1.122462 # charges kspace_style pppm 1.0e-3 pair_modify shift yes diff --git a/examples/plugins/CMakeLists.txt b/examples/plugins/CMakeLists.txt index 22bd09775f..ec0f6ade83 100644 --- a/examples/plugins/CMakeLists.txt +++ b/examples/plugins/CMakeLists.txt @@ -31,6 +31,15 @@ else() endif() endif() +# ugly hacks for MSVC which by default always reports an old C++ standard in the __cplusplus macro +# and prints lots of pointless warnings about "unsafe" functions +#if(MSVC) +# add_compile_options(/Zc:__cplusplus) +# add_compile_options(/wd4244) +# add_compile_options(/wd4267) +# add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +#endif() + # C++11 is required set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -40,11 +49,6 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "Intel") OR (CMAKE_CXX_COMPILER_ID STREQUAL " set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict") endif() -# bail out on windows -if(CMAKE_SYSTEM_NAME STREQUAL Windows) - message(FATAL_ERROR "LAMMPS plugins are currently not supported on Windows") -endif() - set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) include(CheckIncludeFileCXX) if(NOT LAMMPS_DIR) @@ -68,14 +72,23 @@ add_library(zero2plugin MODULE zero2plugin.cpp pair_zero2.cpp bond_zero2.cpp angle_zero2.cpp dihedral_zero2.cpp improper_zero2.cpp) target_link_libraries(zero2plugin PRIVATE lammps) -set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES - PREFIX "" - LINK_FLAGS "-rdynamic") +set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES PREFIX "") # MacOS seems to need this if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin + PROPERTIES LINK_FLAGS "-Wl,-undefined,dynamic_lookup") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") +# tell CMake to export all symbols to a .dll on Windows with special case for MinGW cross-compilers + set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin + PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) + if(CMAKE_CROSSCOMPILING) + set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin + PROPERTIES LINK_FLAGS "-Wl,--export-all-symbols") + endif() +else() set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES - LINK_FLAGS "-Wl,-undefined,dynamic_lookup") + LINK_FLAGS "-rdynamic") endif() add_custom_target(plugins ALL ${CMAKE_COMMAND} -E echo "Building Plugins" diff --git a/examples/plugins/LAMMPSInterfaceCXX.cmake b/examples/plugins/LAMMPSInterfaceCXX.cmake index 02f9159319..d52cf8f4e5 100644 --- a/examples/plugins/LAMMPSInterfaceCXX.cmake +++ b/examples/plugins/LAMMPSInterfaceCXX.cmake @@ -23,7 +23,9 @@ endfunction(validate_option) # LAMMPS C++ interface. We only need the header related parts. add_library(lammps INTERFACE) target_include_directories(lammps INTERFACE ${LAMMPS_HEADER_DIR}) - +if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND CMAKE_CROSSCOMPILING) + target_link_libraries(lammps INTERFACE ${CMAKE_BINARY_DIR}/../liblammps.dll.a) +endif() ################################################################################ # MPI configuration if(NOT CMAKE_CROSSCOMPILING) diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp index 405c68244b..ee14703726 100644 --- a/lib/colvars/colvarmodule.cpp +++ b/lib/colvars/colvarmodule.cpp @@ -1476,7 +1476,9 @@ int colvarmodule::write_output_files() bi != biases.end(); bi++) { // Only write output files if they have not already been written this time step - if ((*bi)->output_freq == 0 || (cvm::step_absolute() % (*bi)->output_freq) != 0) { + if ((*bi)->output_freq == 0 || + cvm::step_relative() == 0 || + (cvm::step_absolute() % (*bi)->output_freq) != 0) { error_code |= (*bi)->write_output_files(); } error_code |= (*bi)->write_state_to_replicas(); diff --git a/lib/colvars/colvars_version.h b/lib/colvars/colvars_version.h index dd56c39f3a..3f050c7e7c 100644 --- a/lib/colvars/colvars_version.h +++ b/lib/colvars/colvars_version.h @@ -1,3 +1,3 @@ #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2021-08-06" +#define COLVARS_VERSION "2021-09-21" #endif diff --git a/lib/gpu/geryon/ocl_device.h b/lib/gpu/geryon/ocl_device.h index e5efc239da..df53aff5b8 100644 --- a/lib/gpu/geryon/ocl_device.h +++ b/lib/gpu/geryon/ocl_device.h @@ -481,7 +481,7 @@ int UCL_Device::set_platform(int pid) { cl_device_id *subdevice_list = new cl_device_id[num_subdevices]; CL_SAFE_CALL(clCreateSubDevices(device_list[i], props, num_subdevices, subdevice_list, &num_subdevices)); - for (int j=0; j= 3.0) op.has_shuffle_support=true; } + delete[] buffer2; #endif _properties.push_back(op); @@ -830,7 +837,7 @@ int UCL_Device::auto_set_platform(const enum UCL_DEVICE_TYPE type, bool vendor_match=false; bool type_match=false; - int max_cus=0; + unsigned int max_cus=0; int best_platform=0; std::string vendor_upper=vendor; diff --git a/lib/gpu/lal_born_coul_long.cpp b/lib/gpu/lal_born_coul_long.cpp index 8c7084f4a4..36f46f2684 100644 --- a/lib/gpu/lal_born_coul_long.cpp +++ b/lib/gpu/lal_born_coul_long.cpp @@ -34,7 +34,7 @@ BornCoulLongT::BornCoulLong() : BaseCharge(), } template -BornCoulLongT::~BornCoulLongT() { +BornCoulLongT::~BornCoulLong() { clear(); } diff --git a/lib/gpu/lal_born_coul_wolf.cpp b/lib/gpu/lal_born_coul_wolf.cpp index 9aac866353..9a0653dd23 100644 --- a/lib/gpu/lal_born_coul_wolf.cpp +++ b/lib/gpu/lal_born_coul_wolf.cpp @@ -34,7 +34,7 @@ BornCoulWolfT::BornCoulWolf() : BaseCharge(), } template -BornCoulWolfT::~BornCoulWolfT() { +BornCoulWolfT::~BornCoulWolf() { clear(); } diff --git a/lib/gpu/lal_buck_coul_long.cpp b/lib/gpu/lal_buck_coul_long.cpp index 60205a2ad6..98c97ea908 100644 --- a/lib/gpu/lal_buck_coul_long.cpp +++ b/lib/gpu/lal_buck_coul_long.cpp @@ -34,7 +34,7 @@ BuckCoulLongT::BuckCoulLong() : BaseCharge(), } template -BuckCoulLongT::~BuckCoulLongT() { +BuckCoulLongT::~BuckCoulLong() { clear(); } diff --git a/lib/gpu/lal_device.cpp b/lib/gpu/lal_device.cpp index 9dbd02dd3e..59eac78483 100644 --- a/lib/gpu/lal_device.cpp +++ b/lib/gpu/lal_device.cpp @@ -333,6 +333,12 @@ int DeviceT::init_device(MPI_Comm world, MPI_Comm replica, const int ngpu, gpu_barrier(); } + // check if double precision support is available + #if defined(_SINGLE_DOUBLE) || defined(_DOUBLE_DOUBLE) + if (!gpu->double_precision()) + return -16; + #endif + // Setup auto bin size calculation for calls from atom::sort // - This is repeated in neighbor init with additional info if (_user_cell_size<0.0) { @@ -546,14 +552,9 @@ int DeviceT::init_nbor(Neighbor *nbor, const int nlocal, return -3; if (_user_cell_size<0.0) { - #ifndef LAL_USE_OLD_NEIGHBOR - _neighbor_shared.setup_auto_cell_size(true,cutoff,nbor->simd_size()); - #else _neighbor_shared.setup_auto_cell_size(false,cutoff,nbor->simd_size()); - #endif } else - _neighbor_shared.setup_auto_cell_size(false,_user_cell_size, - nbor->simd_size()); + _neighbor_shared.setup_auto_cell_size(false,_user_cell_size,nbor->simd_size()); nbor->set_cutoff(cutoff); return 0; diff --git a/lib/machdyn/Install.py b/lib/machdyn/Install.py index 2e90c9ca0f..8471316401 100644 --- a/lib/machdyn/Install.py +++ b/lib/machdyn/Install.py @@ -17,11 +17,12 @@ parser = ArgumentParser(prog='Install.py', # settings -version = '3.3.9' +version = '3.4.0' tarball = "eigen.tar.gz" # known checksums for different Eigen versions. used to validate the download. checksums = { \ + '3.4.0' : '4c527a9171d71a72a9d4186e65bea559', \ '3.3.9' : '609286804b0f79be622ccf7f9ff2b660', \ '3.3.7' : '9e30f67e8531477de4117506fe44669b' \ } @@ -35,7 +36,7 @@ Syntax from src dir: make lib-smd args="-b" Syntax from lib dir: python Install.py -b or: python Install.py -p /usr/include/eigen3" - or: python Install.py -v 3.3.7 -b + or: python Install.py -v 3.4.0 -b Example: @@ -77,7 +78,7 @@ if pathflag: if buildflag: print("Downloading Eigen ...") eigentar = os.path.join(homepath, tarball) - url = "https://gitlab.com/libeigen/eigen/-/archive/%s/eigen-%s.tar.gz" % (version,version) + url = "https://download.lammps.org/thirdparty/eigen-%s.tar.gz" % version geturl(url, eigentar) # verify downloaded archive integrity via md5 checksum, if known. diff --git a/lib/pace/Makefile b/lib/pace/Makefile index ac9f3a3151..c2e1892ddd 100644 --- a/lib/pace/Makefile +++ b/lib/pace/Makefile @@ -2,8 +2,8 @@ SHELL = /bin/sh # ------ FILES ------ -SRC_FILES = $(wildcard src/ML-PACE/*.cpp) -SRC = $(filter-out src/ML-PACE/pair_pace.cpp, $(SRC_FILES)) +SRC_FILES = $(wildcard src/USER-PACE/*.cpp) +SRC = $(filter-out src/USER-PACE/pair_pace.cpp, $(SRC_FILES)) # ------ DEFINITIONS ------ @@ -12,7 +12,7 @@ OBJ = $(SRC:.cpp=.o) # ------ SETTINGS ------ -CXXFLAGS = -O3 -fPIC -Isrc/ML-PACE +CXXFLAGS = -O3 -fPIC -Isrc/USER-PACE ARCHIVE = ar ARCHFLAG = -rc diff --git a/lib/pace/Makefile.lammps b/lib/pace/Makefile.lammps index 89761c1b4b..17820716df 100644 --- a/lib/pace/Makefile.lammps +++ b/lib/pace/Makefile.lammps @@ -1,3 +1,3 @@ -pace_SYSINC =-I../../lib/pace/src/ML-PACE +pace_SYSINC =-I../../lib/pace/src/USER-PACE pace_SYSLIB = -L../../lib/pace/ -lpace pace_SYSPATH = diff --git a/src/.gitignore b/src/.gitignore index 6c0a838c1b..1a87b9fa5c 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -27,6 +27,9 @@ /*_ssa.h /*_ssa.cpp +!accelerator_kokkos.h +!accelerator_omp.h + /fix_mdi_engine.cpp /fix_mdi_engine.h /library_mdi.cpp @@ -202,7 +205,6 @@ /plugin.cpp /plugin.h -/lammpsplugin.h /atom_vec_spin.cpp /atom_vec_spin.h @@ -265,8 +267,6 @@ /fix_drag.h /fix_numdiff.cpp /fix_numdiff.h -/fix_nve_noforce.cpp -/fix_nve_noforce.h /fix_spring_rg.cpp /fix_spring_rg.h /fix_temp_csld.cpp @@ -367,8 +367,6 @@ /atom_vec_dpd.h /atom_vec_electron.cpp /atom_vec_electron.h -/atom_vec_ellipsoid.cpp -/atom_vec_ellipsoid.h /atom_vec_full.cpp /atom_vec_full.h /atom_vec_full_hars.cpp @@ -535,8 +533,6 @@ /dihedral_harmonic.h /dihedral_helix.cpp /dihedral_helix.h -/dihedral_hybrid.cpp -/dihedral_hybrid.h /dihedral_multi_harmonic.cpp /dihedral_multi_harmonic.h /dihedral_nharmonic.cpp @@ -858,8 +854,6 @@ /fix_ti_rs.h /fix_ti_spring.cpp /fix_ti_spring.h -/fix_ttm.cpp -/fix_ttm.h /fix_tune_kspace.cpp /fix_tune_kspace.h /fix_wall_body_polygon.cpp @@ -885,8 +879,6 @@ /fix_widom.cpp /fix_widom.h /gpu_extra.h -/gridcomm.cpp -/gridcomm.h /group_ndx.cpp /group_ndx.h /gz_file_writer.cpp @@ -911,14 +903,13 @@ /improper_fourier.h /improper_harmonic.cpp /improper_harmonic.h -/improper_hybrid.cpp -/improper_hybrid.h /improper_inversion_harmonic.cpp /improper_inversion_harmonic.h /improper_ring.cpp /improper_ring.h /improper_umbrella.cpp /improper_umbrella.h +/interlayer_taper.h /kissfft.h /lj_sdk_common.h /math_complex.h @@ -933,7 +924,6 @@ /msm_cg.h /neb.cpp /neb.h - /pair_adp.cpp /pair_adp.h /pair_agni.cpp @@ -994,6 +984,8 @@ /pair_cosine_squared.h /pair_coul_diel.cpp /pair_coul_diel.h +/pair_coul_exclude.cpp +/pair_coul_exclude.h /pair_coul_long.cpp /pair_coul_long.h /pair_coul_msm.cpp @@ -1332,8 +1324,6 @@ /thr_data.h /verlet_split.cpp /verlet_split.h -/write_dump.cpp -/write_dump.h /xdr_compat.cpp /xdr_compat.h /zstd_file_writer.cpp @@ -1431,6 +1421,10 @@ /fix_srp.h /fix_tfmc.cpp /fix_tfmc.h +/fix_ttm.cpp +/fix_ttm.h +/fix_ttm_grid.cpp +/fix_ttm_grid.h /fix_ttm_mod.cpp /fix_ttm_mod.h /pair_born_coul_long_cs.cpp diff --git a/src/BOCS/fix_bocs.cpp b/src/BOCS/fix_bocs.cpp index a3ec4b6b56..786ff216b0 100644 --- a/src/BOCS/fix_bocs.cpp +++ b/src/BOCS/fix_bocs.cpp @@ -233,9 +233,7 @@ FixBocs::FixBocs(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"mtk") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix bocs command"); - if (strcmp(arg[iarg+1],"yes") == 0) mtk_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) mtk_flag = 0; - else error->all(FLERR,"Illegal fix bocs command"); + mtk_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"tloop") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix bocs command"); diff --git a/src/COLVARS/fix_colvars.cpp b/src/COLVARS/fix_colvars.cpp index 5ee77768c6..6d6799b43e 100644 --- a/src/COLVARS/fix_colvars.cpp +++ b/src/COLVARS/fix_colvars.cpp @@ -303,7 +303,7 @@ FixColvars::FixColvars(LAMMPS *lmp, int narg, char **arg) : me = comm->me; root2root = MPI_COMM_NULL; - conf_file = strdup(arg[3]); + conf_file = utils::strdup(arg[3]); rng_seed = 1966; unwrap_flag = 1; @@ -312,35 +312,29 @@ FixColvars::FixColvars(LAMMPS *lmp, int narg, char **arg) : tmp_name = nullptr; /* parse optional arguments */ - int argsdone = 4; - while (argsdone < narg) { + int iarg = 4; + while (iarg < narg) { // we have keyword/value pairs. check if value is missing - if (argsdone+1 == narg) + if (iarg+1 == narg) error->all(FLERR,"Missing argument to keyword"); - if (0 == strcmp(arg[argsdone], "input")) { - inp_name = strdup(arg[argsdone+1]); - } else if (0 == strcmp(arg[argsdone], "output")) { - out_name = strdup(arg[argsdone+1]); - } else if (0 == strcmp(arg[argsdone], "seed")) { - rng_seed = utils::inumeric(FLERR,arg[argsdone+1],false,lmp); - } else if (0 == strcmp(arg[argsdone], "unwrap")) { - if (0 == strcmp(arg[argsdone+1], "yes")) { - unwrap_flag = 1; - } else if (0 == strcmp(arg[argsdone+1], "no")) { - unwrap_flag = 0; - } else { - error->all(FLERR,"Incorrect fix colvars unwrap flag"); - } - } else if (0 == strcmp(arg[argsdone], "tstat")) { - tmp_name = strdup(arg[argsdone+1]); + if (0 == strcmp(arg[iarg], "input")) { + inp_name = utils::strdup(arg[iarg+1]); + } else if (0 == strcmp(arg[iarg], "output")) { + out_name = utils::strdup(arg[iarg+1]); + } else if (0 == strcmp(arg[iarg], "seed")) { + rng_seed = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + } else if (0 == strcmp(arg[iarg], "unwrap")) { + unwrap_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); + } else if (0 == strcmp(arg[iarg], "tstat")) { + tmp_name = utils::strdup(arg[iarg+1]); } else { error->all(FLERR,"Unknown fix colvars parameter"); } - ++argsdone; ++argsdone; + ++iarg; ++iarg; } - if (!out_name) out_name = strdup("out"); + if (!out_name) out_name = utils::strdup("out"); /* initialize various state variables. */ tstat_id = -1; @@ -365,10 +359,10 @@ FixColvars::FixColvars(LAMMPS *lmp, int narg, char **arg) : FixColvars::~FixColvars() { - memory->sfree(conf_file); - memory->sfree(inp_name); - memory->sfree(out_name); - memory->sfree(tmp_name); + delete[] conf_file; + delete[] inp_name; + delete[] out_name; + delete[] tmp_name; memory->sfree(comm_buf); if (proxy) { @@ -436,17 +430,15 @@ void FixColvars::one_time_init() // create and initialize the colvars proxy if (me == 0) { - if (screen) fputs("colvars: Creating proxy instance\n",screen); - if (logfile) fputs("colvars: Creating proxy instance\n",logfile); + utils::logmesg(lmp,"colvars: Creating proxy instance\n"); #ifdef LAMMPS_BIGBIG - if (screen) fputs("colvars: cannot handle atom ids > 2147483647\n",screen); - if (logfile) fputs("colvars: cannot handle atom ids > 2147483647\n",logfile); + utils::logmesg(lmp,"colvars: cannot handle atom ids > 2147483647\n"); #endif if (inp_name) { if (strcmp(inp_name,"NULL") == 0) { - memory->sfree(inp_name); + delete[] inp_name; inp_name = nullptr; } } @@ -464,8 +456,7 @@ void FixColvars::one_time_init() } } - proxy = new colvarproxy_lammps(lmp,inp_name,out_name, - rng_seed,t_target,root2root); + proxy = new colvarproxy_lammps(lmp,inp_name,out_name,rng_seed,t_target,root2root); proxy->init(conf_file); num_coords = (proxy->modify_atom_positions()->size()); diff --git a/src/COMPRESS/dump_atom_gz.cpp b/src/COMPRESS/dump_atom_gz.cpp index 38229a71bb..5f799054bb 100644 --- a/src/COMPRESS/dump_atom_gz.cpp +++ b/src/COMPRESS/dump_atom_gz.cpp @@ -33,7 +33,7 @@ DumpAtomGZ::~DumpAtomGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_atom_zstd.cpp b/src/COMPRESS/dump_atom_zstd.cpp index aa9d14b324..a23ea2025b 100644 --- a/src/COMPRESS/dump_atom_zstd.cpp +++ b/src/COMPRESS/dump_atom_zstd.cpp @@ -188,17 +188,11 @@ int DumpAtomZstd::modify_param(int narg, char **arg) try { if (strcmp(arg[0], "checksum") == 0) { if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); - if (strcmp(arg[1], "yes") == 0) - writer.setChecksum(true); - else if (strcmp(arg[1], "no") == 0) - writer.setChecksum(false); - else - error->all(FLERR, "Illegal dump_modify command"); + writer.setChecksum(utils::logical(FLERR, arg[1], false, lmp) == 1); return 2; } else if (strcmp(arg[0], "compression_level") == 0) { if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); - int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - writer.setCompressionLevel(compression_level); + writer.setCompressionLevel(utils::inumeric(FLERR, arg[1], false, lmp)); return 2; } } catch (FileWriterException &e) { diff --git a/src/COMPRESS/dump_cfg_gz.cpp b/src/COMPRESS/dump_cfg_gz.cpp index ea51ce87c3..8d6347d978 100644 --- a/src/COMPRESS/dump_cfg_gz.cpp +++ b/src/COMPRESS/dump_cfg_gz.cpp @@ -35,7 +35,7 @@ DumpCFGGZ::~DumpCFGGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_cfg_zstd.cpp b/src/COMPRESS/dump_cfg_zstd.cpp index 15ea1e540c..73ee3e7e11 100644 --- a/src/COMPRESS/dump_cfg_zstd.cpp +++ b/src/COMPRESS/dump_cfg_zstd.cpp @@ -233,17 +233,11 @@ int DumpCFGZstd::modify_param(int narg, char **arg) try { if (strcmp(arg[0], "checksum") == 0) { if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); - if (strcmp(arg[1], "yes") == 0) - writer.setChecksum(true); - else if (strcmp(arg[1], "no") == 0) - writer.setChecksum(false); - else - error->all(FLERR, "Illegal dump_modify command"); + writer.setChecksum(utils::logical(FLERR, arg[1], false, lmp) == 1); return 2; } else if (strcmp(arg[0], "compression_level") == 0) { if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); - int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - writer.setCompressionLevel(compression_level); + writer.setCompressionLevel(utils::inumeric(FLERR, arg[1], false, lmp)); return 2; } } catch (FileWriterException &e) { diff --git a/src/COMPRESS/dump_custom_gz.cpp b/src/COMPRESS/dump_custom_gz.cpp index 7cbab10cb4..f40cf8d3d1 100644 --- a/src/COMPRESS/dump_custom_gz.cpp +++ b/src/COMPRESS/dump_custom_gz.cpp @@ -33,7 +33,7 @@ DumpCustomGZ::~DumpCustomGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_custom_zstd.cpp b/src/COMPRESS/dump_custom_zstd.cpp index 3824709d5e..347c9c08e2 100644 --- a/src/COMPRESS/dump_custom_zstd.cpp +++ b/src/COMPRESS/dump_custom_zstd.cpp @@ -45,7 +45,7 @@ DumpCustomZstd::~DumpCustomZstd() /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -203,16 +203,13 @@ int DumpCustomZstd::modify_param(int narg, char **arg) int consumed = DumpCustom::modify_param(narg, arg); if (consumed == 0) { try { - if (strcmp(arg[0],"checksum") == 0) { - if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[1],"yes") == 0) writer.setChecksum(true); - else if (strcmp(arg[1],"no") == 0) writer.setChecksum(false); - else error->all(FLERR,"Illegal dump_modify command"); + if (strcmp(arg[0], "checksum") == 0) { + if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); + writer.setChecksum(utils::logical(FLERR, arg[1], false, lmp) == 1); return 2; - } else if (strcmp(arg[0],"compression_level") == 0) { - if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - writer.setCompressionLevel(compression_level); + } else if (strcmp(arg[0], "compression_level") == 0) { + if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); + writer.setCompressionLevel(utils::inumeric(FLERR, arg[1], false, lmp)); return 2; } } catch (FileWriterException &e) { diff --git a/src/COMPRESS/dump_local_gz.cpp b/src/COMPRESS/dump_local_gz.cpp index 206e2aeb09..a23fa1a1ac 100644 --- a/src/COMPRESS/dump_local_gz.cpp +++ b/src/COMPRESS/dump_local_gz.cpp @@ -33,7 +33,7 @@ DumpLocalGZ::~DumpLocalGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_local_zstd.cpp b/src/COMPRESS/dump_local_zstd.cpp index cf233aff19..1d3fc4756e 100644 --- a/src/COMPRESS/dump_local_zstd.cpp +++ b/src/COMPRESS/dump_local_zstd.cpp @@ -39,7 +39,7 @@ DumpLocalZstd::~DumpLocalZstd() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -190,17 +190,11 @@ int DumpLocalZstd::modify_param(int narg, char **arg) try { if (strcmp(arg[0], "checksum") == 0) { if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); - if (strcmp(arg[1], "yes") == 0) - writer.setChecksum(true); - else if (strcmp(arg[1], "no") == 0) - writer.setChecksum(false); - else - error->all(FLERR, "Illegal dump_modify command"); + writer.setChecksum(utils::logical(FLERR, arg[1], false, lmp) == 1); return 2; } else if (strcmp(arg[0], "compression_level") == 0) { if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); - int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - writer.setCompressionLevel(compression_level); + writer.setCompressionLevel(utils::inumeric(FLERR, arg[1], false, lmp)); return 2; } } catch (FileWriterException &e) { diff --git a/src/COMPRESS/dump_xyz_gz.cpp b/src/COMPRESS/dump_xyz_gz.cpp index a1acad7fc2..2d9548bf14 100644 --- a/src/COMPRESS/dump_xyz_gz.cpp +++ b/src/COMPRESS/dump_xyz_gz.cpp @@ -32,7 +32,7 @@ DumpXYZGZ::~DumpXYZGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_xyz_zstd.cpp b/src/COMPRESS/dump_xyz_zstd.cpp index d5c79d181b..b56488ec09 100644 --- a/src/COMPRESS/dump_xyz_zstd.cpp +++ b/src/COMPRESS/dump_xyz_zstd.cpp @@ -38,7 +38,7 @@ DumpXYZZstd::~DumpXYZZstd() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -156,17 +156,11 @@ int DumpXYZZstd::modify_param(int narg, char **arg) try { if (strcmp(arg[0], "checksum") == 0) { if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); - if (strcmp(arg[1], "yes") == 0) - writer.setChecksum(true); - else if (strcmp(arg[1], "no") == 0) - writer.setChecksum(false); - else - error->all(FLERR, "Illegal dump_modify command"); + writer.setChecksum(utils::logical(FLERR, arg[1], false, lmp) == 1); return 2; } else if (strcmp(arg[0], "compression_level") == 0) { if (narg < 2) error->all(FLERR, "Illegal dump_modify command"); - int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - writer.setCompressionLevel(compression_level); + writer.setCompressionLevel(utils::inumeric(FLERR, arg[1], false, lmp)); return 2; } } catch (FileWriterException &e) { diff --git a/src/DIELECTRIC/fix_polarize_bem_gmres.cpp b/src/DIELECTRIC/fix_polarize_bem_gmres.cpp index 538ce15575..f5f119f686 100644 --- a/src/DIELECTRIC/fix_polarize_bem_gmres.cpp +++ b/src/DIELECTRIC/fix_polarize_bem_gmres.cpp @@ -796,12 +796,7 @@ int FixPolarizeBEMGMRES::modify_param(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg], "kspace") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix_modify command"); - if (strcmp(arg[iarg + 1], "yes") == 0) - kspaceflag = 1; - else if (strcmp(arg[iarg + 1], "no") == 0) - kspaceflag = 0; - else - error->all(FLERR, "Illegal fix_modify command for fix polarize"); + kspaceflag = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "dielectrics") == 0) { if (iarg + 6 > narg) error->all(FLERR, "Illegal fix_modify command"); diff --git a/src/DIELECTRIC/fix_polarize_bem_icc.cpp b/src/DIELECTRIC/fix_polarize_bem_icc.cpp index 4c137878a2..35171c0a19 100644 --- a/src/DIELECTRIC/fix_polarize_bem_icc.cpp +++ b/src/DIELECTRIC/fix_polarize_bem_icc.cpp @@ -355,12 +355,7 @@ int FixPolarizeBEMICC::modify_param(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg], "kspace") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix_modify command"); - if (strcmp(arg[iarg + 1], "yes") == 0) - kspaceflag = 1; - else if (strcmp(arg[iarg + 1], "no") == 0) - kspaceflag = 0; - else - error->all(FLERR, "Illegal fix_modify command for fix polarize"); + kspaceflag = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "dielectrics") == 0) { if (iarg + 6 > narg) error->all(FLERR, "Illegal fix_modify command"); diff --git a/src/DIELECTRIC/fix_polarize_functional.cpp b/src/DIELECTRIC/fix_polarize_functional.cpp index 2d67bca0a7..2e43d40ba0 100644 --- a/src/DIELECTRIC/fix_polarize_functional.cpp +++ b/src/DIELECTRIC/fix_polarize_functional.cpp @@ -478,12 +478,7 @@ int FixPolarizeFunctional::modify_param(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg], "kspace") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix_modify command"); - if (strcmp(arg[iarg + 1], "yes") == 0) - kspaceflag = 1; - else if (strcmp(arg[iarg + 1], "no") == 0) - kspaceflag = 0; - else - error->all(FLERR, "Illegal fix_modify command for fix polarize/functional"); + kspaceflag = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "dielectrics") == 0) { if (iarg + 6 > narg) error->all(FLERR, "Illegal fix_modify command"); diff --git a/src/DIFFRACTION/compute_saed.cpp b/src/DIFFRACTION/compute_saed.cpp index e5af83ca92..e2df7fe3b8 100644 --- a/src/DIFFRACTION/compute_saed.cpp +++ b/src/DIFFRACTION/compute_saed.cpp @@ -31,7 +31,6 @@ #include #include -#include // for strcasecmp() #include "omp_compat.h" using namespace LAMMPS_NS; @@ -85,13 +84,13 @@ ComputeSAED::ComputeSAED(LAMMPS *lmp, int narg, char **arg) : ztype[i] = SAEDmaxType + 1; } for (int i=0; iall(FLERR,"Compute SAED: Invalid ASF atom type"); + } + if (ztype[i] == SAEDmaxType + 1) + error->all(FLERR,"Compute SAED: Invalid ASF atom type"); iarg++; } @@ -348,7 +347,7 @@ void ComputeSAED::compute_vector() if (me == 0 && echo) utils::logmesg(lmp,"-----\nComputing SAED intensities"); - double t0 = MPI_Wtime(); + double t0 = platform::walltime(); double *Fvec = new double[2*nRows]; // Strct factor (real & imaginary) // -- Note, vector entries correspond to different RELP @@ -491,7 +490,7 @@ void ComputeSAED::compute_vector() vector[i] = (scratch[2*i] * scratch[2*i] + scratch[2*i+1] * scratch[2*i+1]) / natoms; } - double t2 = MPI_Wtime(); + double t2 = platform::walltime(); // compute memory usage per processor double bytes = memory_usage(); diff --git a/src/DIFFRACTION/compute_xrd.cpp b/src/DIFFRACTION/compute_xrd.cpp index c6cf7be2ce..d798c2f4db 100644 --- a/src/DIFFRACTION/compute_xrd.cpp +++ b/src/DIFFRACTION/compute_xrd.cpp @@ -32,7 +32,6 @@ #include #include -#include // for strcasecmp() #include "omp_compat.h" using namespace LAMMPS_NS; @@ -87,7 +86,7 @@ ComputeXRD::ComputeXRD(LAMMPS *lmp, int narg, char **arg) : } for (int i = 0; i < ntypes; i++) { for (int j = 0; j < XRDmaxType; j++) { - if (strcasecmp(arg[iarg],XRDtypeList[j]) == 0) { + if (utils::lowercase(arg[iarg]) == utils::lowercase(XRDtypeList[j])) { ztype[i] = j; } } @@ -300,7 +299,7 @@ void ComputeXRD::compute_array() if (me == 0 && echo) utils::logmesg(lmp, "-----\nComputing XRD intensities"); - double t0 = MPI_Wtime(); + double t0 = platform::walltime(); double *Fvec = new double[2*size_array_rows]; // Strct factor (real & imaginary) // -- Note: array rows correspond to different RELP @@ -496,7 +495,7 @@ void ComputeXRD::compute_array() array[i][1] = (scratch[2*i] * scratch[2*i] + scratch[2*i+1] * scratch[2*i+1]) / natoms; } - double t2 = MPI_Wtime(); + double t2 = platform::walltime(); // compute memory usage per processor double bytes = memory_usage(); diff --git a/src/DIFFRACTION/fix_saed_vtk.cpp b/src/DIFFRACTION/fix_saed_vtk.cpp index 2e7d0897a6..89627b64ef 100644 --- a/src/DIFFRACTION/fix_saed_vtk.cpp +++ b/src/DIFFRACTION/fix_saed_vtk.cpp @@ -31,6 +31,7 @@ #include #include + using namespace LAMMPS_NS; using namespace FixConst; @@ -100,8 +101,6 @@ FixSAEDVTK::FixSAEDVTK(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR,"Illegal fix saed/vtk command"); if (nfreq % nevery || nrepeat*nevery > nfreq) error->all(FLERR,"Illegal fix saed/vtk command"); - if (ave != RUNNING && overwrite) - error->all(FLERR,"Illegal fix saed/vtk command"); // allocate memory for averaging @@ -315,7 +314,7 @@ void FixSAEDVTK::invoke_vector(bigint ntimestep) if (irepeat == 0) for (int i = 0; i < nrows; i++) - vector[i] = 0.0; + vector[i] = 0.0; // accumulate results of computes,fixes,variables to local copy // compute/fix/variable may invoke computes so wrap with clear/add @@ -369,7 +368,7 @@ void FixSAEDVTK::invoke_vector(bigint ntimestep) for (int i = 0; i < nrows; i++) { vector_total[i] += vector[i]; if (window_limit) vector_total[i] -= vector_list[iwindow][i]; - vector_list[iwindow][i] = vector[i]; + vector_list[iwindow][i] = vector[i]; } iwindow++; @@ -391,8 +390,7 @@ void FixSAEDVTK::invoke_vector(bigint ntimestep) fp = fopen(nName.c_str(),"w"); if (fp == nullptr) - error->one(FLERR,"Cannot open fix saed/vtk file {}: {}", - nName,utils::getsyserror()); + error->one(FLERR,"Cannot open fix saed/vtk file {}: {}", nName,utils::getsyserror()); } fprintf(fp,"# vtk DataFile Version 3.0 c_%s\n",ids); @@ -406,71 +404,68 @@ void FixSAEDVTK::invoke_vector(bigint ntimestep) fprintf(fp,"SCALARS intensity float\n"); fprintf(fp,"LOOKUP_TABLE default\n"); - filepos = ftell(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + // Finding the intersection of the reciprical space and Ewald sphere + int NROW1 = 0; + int NROW2 = 0; + double dinv2 = 0.0; + double r = 0.0; + double K[3]; - // Finding the intersection of the reciprical space and Ewald sphere - int NROW1 = 0; - int NROW2 = 0; - double dinv2 = 0.0; - double r = 0.0; - double K[3]; - - // Zone flag to capture entire recrocal space volume - if ((Zone[0] == 0) && (Zone[1] == 0) && (Zone[2] == 0)) { - for (int k = Knmin[2]; k <= Knmax[2]; k++) { - for (int j = Knmin[1]; j <= Knmax[1]; j++) { - for (int i = Knmin[0]; i <= Knmax[0]; i++) { - K[0] = i * dK[0]; - K[1] = j * dK[1]; - K[2] = k * dK[2]; - dinv2 = (K[0] * K[0] + K[1] * K[1] + K[2] * K[2]); - if (dinv2 < Kmax * Kmax) { - fprintf(fp,"%g\n",vector_total[NROW1]/norm); - fflush(fp); - NROW1++; - NROW2++; - } else { + // Zone flag to capture entire recrocal space volume + if ((Zone[0] == 0) && (Zone[1] == 0) && (Zone[2] == 0)) { + for (int k = Knmin[2]; k <= Knmax[2]; k++) { + for (int j = Knmin[1]; j <= Knmax[1]; j++) { + for (int i = Knmin[0]; i <= Knmax[0]; i++) { + K[0] = i * dK[0]; + K[1] = j * dK[1]; + K[2] = k * dK[2]; + dinv2 = (K[0] * K[0] + K[1] * K[1] + K[2] * K[2]); + if (dinv2 < Kmax * Kmax) { + fprintf(fp,"%g\n",vector_total[NROW1]/norm); + fflush(fp); + NROW1++; + NROW2++; + } else { fprintf(fp,"%d\n",-1); fflush(fp); NROW2++; - } } } } - } else { - for (int k = Knmin[2]; k <= Knmax[2]; k++) { - for (int j = Knmin[1]; j <= Knmax[1]; j++) { - for (int i = Knmin[0]; i <= Knmax[0]; i++) { - K[0] = i * dK[0]; - K[1] = j * dK[1]; - K[2] = k * dK[2]; - dinv2 = (K[0] * K[0] + K[1] * K[1] + K[2] * K[2]); - if (dinv2 < Kmax * Kmax) { - r=0.0; - for (int m=0; m<3; m++) r += pow(K[m] - Zone[m],2.0); - r = sqrt(r); - if ( (r > (R_Ewald - dR_Ewald) ) && (r < (R_Ewald + dR_Ewald) )) { - fprintf(fp,"%g\n",vector_total[NROW1]/norm); - fflush(fp); - NROW2++; - NROW1++; - } else { - fprintf(fp,"%d\n",-1); - fflush(fp); - NROW2++; - } + } + } else { + for (int k = Knmin[2]; k <= Knmax[2]; k++) { + for (int j = Knmin[1]; j <= Knmax[1]; j++) { + for (int i = Knmin[0]; i <= Knmax[0]; i++) { + K[0] = i * dK[0]; + K[1] = j * dK[1]; + K[2] = k * dK[2]; + dinv2 = (K[0] * K[0] + K[1] * K[1] + K[2] * K[2]); + if (dinv2 < Kmax * Kmax) { + r=0.0; + for (int m=0; m<3; m++) r += pow(K[m] - Zone[m],2.0); + r = sqrt(r); + if ( (r > (R_Ewald - dR_Ewald) ) && (r < (R_Ewald + dR_Ewald) )) { + fprintf(fp,"%g\n",vector_total[NROW1]/norm); + fflush(fp); + NROW2++; + NROW1++; } else { + fprintf(fp,"%d\n",-1); + fflush(fp); + NROW2++; + } + } else { fprintf(fp,"%d\n",-1); fflush(fp); NROW2++; - } } } } } } + } nOutput++; } @@ -497,7 +492,6 @@ void FixSAEDVTK::options(int narg, char **arg) fp = nullptr; ave = ONE; startstep = 0; - overwrite = 0; // optional args int iarg = 7; @@ -534,9 +528,6 @@ void FixSAEDVTK::options(int narg, char **arg) if (iarg+2 > narg) error->all(FLERR,"Illegal fix saed/vtk command"); startstep = utils::inumeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; - } else if (strcmp(arg[iarg],"overwrite") == 0) { - overwrite = 1; - iarg += 1; } else error->all(FLERR,"Illegal fix saed/vtk command"); } } diff --git a/src/DIFFRACTION/fix_saed_vtk.h b/src/DIFFRACTION/fix_saed_vtk.h index 07aebce63d..a5691ea986 100644 --- a/src/DIFFRACTION/fix_saed_vtk.h +++ b/src/DIFFRACTION/fix_saed_vtk.h @@ -43,8 +43,6 @@ class FixSAEDVTK : public Fix { int nrows; int ave, nwindow, nsum, startstep; - int overwrite; - long filepos; int norm, iwindow, window_limit; double *vector; diff --git a/src/DPD-MESO/pair_mdpd.cpp b/src/DPD-MESO/pair_mdpd.cpp index 9e704de2a7..53994800d0 100644 --- a/src/DPD-MESO/pair_mdpd.cpp +++ b/src/DPD-MESO/pair_mdpd.cpp @@ -19,19 +19,19 @@ #include "pair_mdpd.h" +#include "atom.h" +#include "citeme.h" +#include "comm.h" +#include "error.h" +#include "force.h" +#include "memory.h" +#include "neigh_list.h" +#include "neighbor.h" +#include "random_mars.h" +#include "update.h" + #include #include -#include "atom.h" -#include "comm.h" -#include "update.h" -#include "force.h" -#include "neighbor.h" -#include "neigh_list.h" -#include "random_mars.h" -#include "citeme.h" -#include "memory.h" -#include "error.h" - using namespace LAMMPS_NS; @@ -217,12 +217,13 @@ void PairMDPD::settings(int narg, char **arg) seed = utils::inumeric(FLERR,arg[2],false,lmp); // initialize Marsaglia RNG with processor-unique seed + // create a positive seed based on the system clock, if requested. if (seed <= 0) { - struct timespec time; - clock_gettime( CLOCK_REALTIME, &time ); - seed = time.tv_nsec; // if seed is non-positive, get the current time as the seed + constexpr double LARGE_NUM = 2<<30; + seed = int(fmod(platform::walltime() * LARGE_NUM, LARGE_NUM)) + 1; } + delete random; random = new RanMars(lmp,(seed + comm->me) % 900000000); diff --git a/src/DPD-MESO/pair_tdpd.cpp b/src/DPD-MESO/pair_tdpd.cpp index e99edfa5ff..70168c0e2a 100644 --- a/src/DPD-MESO/pair_tdpd.cpp +++ b/src/DPD-MESO/pair_tdpd.cpp @@ -18,19 +18,19 @@ ------------------------------------------------------------------------- */ #include "pair_tdpd.h" -#include -#include -#include "atom.h" -#include "comm.h" -#include "update.h" -#include "force.h" -#include "neighbor.h" -#include "neigh_list.h" -#include "random_mars.h" -#include "citeme.h" -#include "memory.h" -#include "error.h" +#include "atom.h" +#include "citeme.h" +#include "comm.h" +#include "error.h" +#include "force.h" +#include "memory.h" +#include "neigh_list.h" +#include "neighbor.h" +#include "random_mars.h" +#include "update.h" + +#include using namespace LAMMPS_NS; @@ -239,12 +239,13 @@ void PairTDPD::settings(int narg, char **arg) seed = utils::inumeric(FLERR,arg[2],false,lmp); // initialize Marsaglia RNG with processor-unique seed + // create a positive seed based on the system clock, if requested. if (seed <= 0) { - struct timespec time; - clock_gettime( CLOCK_REALTIME, &time ); - seed = time.tv_nsec; // if seed is non-positive, get the current time as the seed + constexpr double LARGE_NUM = 2<<30; + seed = int(fmod(platform::walltime() * LARGE_NUM, LARGE_NUM)) + 1; } + delete random; random = new RanMars(lmp,(seed + comm->me) % 900000000); diff --git a/src/DPD-REACT/fix_rx.cpp b/src/DPD-REACT/fix_rx.cpp index 526c2d508f..b14831ee8d 100644 --- a/src/DPD-REACT/fix_rx.cpp +++ b/src/DPD-REACT/fix_rx.cpp @@ -58,7 +58,7 @@ namespace /* anonymous */ { typedef double TimerType; -TimerType getTimeStamp() { return MPI_Wtime(); } +TimerType getTimeStamp() { return platform::walltime(); } double getElapsedTime( const TimerType &t0, const TimerType &t1) { return t1-t0; } } // end namespace @@ -126,7 +126,7 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR, errmsg); } - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { std::string msg = "FixRX: matrix format is "; if (useSparseKinetics) msg += std::string("sparse"); @@ -172,7 +172,7 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) : char *word = arg[iarg++]; minSteps = atoi( word ); - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { char msg[128]; sprintf(msg, "FixRX: RK4 numSteps= %d", minSteps); error->message(FLERR, msg); @@ -197,7 +197,7 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) : // maxIters must be at least minSteps. maxIters = std::max( minSteps, maxIters ); - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { //printf("FixRX: RKF45 minSteps= %d maxIters= %d absTol= %e relTol= %e\n", minSteps, maxIters, absTol, relTol); char msg[128]; sprintf(msg, "FixRX: RKF45 minSteps= %d maxIters= %d relTol= %.1e absTol= %.1e diagnosticFrequency= %d", minSteps, maxIters, relTol, absTol, diagnosticFrequency); @@ -371,7 +371,7 @@ void FixRX::initSparse() { const int Verbosity = 1; - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { for (int k = 0; k < nspecies; ++k) printf("atom->dvname[%d]= %s\n", k, atom->dvname[k]); @@ -421,7 +421,7 @@ void FixRX::initSparse() std::string pstr, rstr; bool allAreIntegral = true; for (int k = 0; k < nspecies; ++k) { - if (stoichReactants[i][k] == 0 and stoichProducts[i][k] == 0) + if (stoichReactants[i][k] == 0 && stoichProducts[i][k] == 0) nzeros++; if (stoichReactants[i][k] > 0.0) { @@ -448,7 +448,7 @@ void FixRX::initSparse() pstr += atom->dvname[k]; } } - if (comm->me == 0 and Verbosity > 1) + if (comm->me == 0 && Verbosity > 1) printf("rx%3d: %d %d %d ... %s %s %s\n", i, nreac_i, nprod_i, allAreIntegral, rstr.c_str(), /*reversible[i]*/ (false) ? "<=>" : "=", pstr.c_str()); mxreac = std::max( mxreac, nreac_i ); @@ -457,7 +457,7 @@ void FixRX::initSparse() if (allAreIntegral) nIntegral++; } - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { char msg[256]; sprintf(msg, "FixRX: Sparsity of Stoichiometric Matrix= %.1f%% non-zeros= %d nspecies= %d nreactions= %d maxReactants= %d maxProducts= %d maxSpecies= %d integralReactions= %d", 100*(double(nzeros) / (nspecies * nreactions)), nzeros, nspecies, nreactions, mxreac, mxprod, (mxreac + mxprod), SparseKinetics_enableIntegralReactions); error->message(FLERR, msg); @@ -539,7 +539,7 @@ void FixRX::initSparse() sparseKinetics_isIntegralReaction[i] = isIntegral_i; } - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { for (int i = 1; i < nu_bin.size(); ++i) if (nu_bin[i] > 0) printf("nu_bin[%d] = %d\n", i, nu_bin[i]); @@ -554,7 +554,7 @@ void FixRX::initSparse() rstr += " + "; char digit[6]; - if (SparseKinetics_enableIntegralReactions and sparseKinetics_isIntegralReaction[i]) + if (SparseKinetics_enableIntegralReactions && sparseKinetics_isIntegralReaction[i]) sprintf(digit,"%d ", sparseKinetics_inu[i][kk]); else sprintf(digit,"%4.1f ", sparseKinetics_nu[i][kk]); @@ -570,7 +570,7 @@ void FixRX::initSparse() pstr += " + "; char digit[6]; - if (SparseKinetics_enableIntegralReactions and sparseKinetics_isIntegralReaction[i]) + if (SparseKinetics_enableIntegralReactions && sparseKinetics_isIntegralReaction[i]) sprintf(digit,"%d ", sparseKinetics_inu[i][kk]); else sprintf(digit,"%4.1f ", sparseKinetics_nu[i][kk]); @@ -578,7 +578,7 @@ void FixRX::initSparse() pstr += atom->dvname[k]; } } - if (comm->me == 0 and Verbosity > 1) + if (comm->me == 0 && Verbosity > 1) printf("rx%3d: %s %s %s\n", i, rstr.c_str(), /*reversible[i]*/ (false) ? "<=>" : "=", pstr.c_str()); } // end for nreactions diff --git a/src/DPD-REACT/random_external_state.h b/src/DPD-REACT/random_external_state.h index 503118f0bf..9a69392a3b 100644 --- a/src/DPD-REACT/random_external_state.h +++ b/src/DPD-REACT/random_external_state.h @@ -78,8 +78,8 @@ namespace random_external_state { typedef uint64_t es_RNG_t; -enum { MAX_URAND = 0xffffffffU }; -enum { MAX_URAND64 = 0xffffffffffffffffULL - 1 }; +constexpr uint32_t MAX_URAND = 0xffffffffU; +constexpr uint64_t MAX_URAND64 = 0xffffffffffffffffULL - 1; LAMMPS_INLINE uint32_t es_urand(es_RNG_t &state_) diff --git a/src/DRUDE/fix_drude_transform.cpp b/src/DRUDE/fix_drude_transform.cpp index ed42d2b548..3f8b0cfe26 100644 --- a/src/DRUDE/fix_drude_transform.cpp +++ b/src/DRUDE/fix_drude_transform.cpp @@ -13,16 +13,18 @@ ------------------------------------------------------------------------- */ /** Fix Drude Transform ******************************************************/ + #include "fix_drude_transform.h" +#include "atom.h" +#include "comm.h" +#include "domain.h" +#include "error.h" +#include "fix_drude.h" +#include "modify.h" + #include #include -#include "fix_drude.h" -#include "atom.h" -#include "domain.h" -#include "comm.h" -#include "error.h" -#include "modify.h" using namespace LAMMPS_NS; using namespace FixConst; diff --git a/src/DRUDE/fix_drude_transform.h b/src/DRUDE/fix_drude_transform.h index 7ee85d2b42..495ec8b175 100644 --- a/src/DRUDE/fix_drude_transform.h +++ b/src/DRUDE/fix_drude_transform.h @@ -25,10 +25,10 @@ FixStyle(drude/transform/inverse,FixDrudeTransform); namespace LAMMPS_NS { -template class FixDrudeTransform : public Fix { +template class FixDrudeTransform: public Fix { public: - FixDrudeTransform(class LAMMPS *, int, char **); - ~FixDrudeTransform(); + FixDrudeTransform(class LAMMPS *, int, char **); + ~FixDrudeTransform(); int setmask(); void init(); void setup(int vflag); diff --git a/src/DRUDE/fix_langevin_drude.cpp b/src/DRUDE/fix_langevin_drude.cpp index 205b36ce51..dea2f9ce62 100644 --- a/src/DRUDE/fix_langevin_drude.cpp +++ b/src/DRUDE/fix_langevin_drude.cpp @@ -91,9 +91,7 @@ FixLangevinDrude::FixLangevinDrude(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"zero") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix langevin/drude command"); - if (strcmp(arg[iarg+1],"no") == 0) zero = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) zero = 1; - else error->all(FLERR,"Illegal fix langevin/drude command"); + zero = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else error->all(FLERR,"Illegal fix langevin/drude command"); } diff --git a/src/DRUDE/fix_tgnh_drude.cpp b/src/DRUDE/fix_tgnh_drude.cpp index fe8cf448f0..700f9669d8 100644 --- a/src/DRUDE/fix_tgnh_drude.cpp +++ b/src/DRUDE/fix_tgnh_drude.cpp @@ -256,9 +256,7 @@ FixTGNHDrude::FixTGNHDrude(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"mtk") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) mtk_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) mtk_flag = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + mtk_flag = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg],"tloop") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); @@ -277,27 +275,19 @@ FixTGNHDrude::FixTGNHDrude(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"scalexy") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalexy = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalexy = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + scalexy = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg],"scalexz") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalexz = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalexz = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + scalexz = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg],"scaleyz") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) scaleyz = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scaleyz = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + scaleyz = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg],"flip") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) flipflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) flipflag = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + flipflag = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg],"fixedpoint") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); @@ -771,7 +761,7 @@ void FixTGNHDrude::setup_mol_mass_dof() { dof_mol, dof_int, dof_drude); } } - if (dof_mol <=0 or dof_int <=0 or dof_drude <=0) + if (dof_mol <=0 || dof_int <=0 || dof_drude <=0) error->all(FLERR, "TGNHC thermostat requires DOFs of molecules, atoms and dipoles larger than 0"); } diff --git a/src/EXTRA-COMPUTE/compute_ackland_atom.cpp b/src/EXTRA-COMPUTE/compute_ackland_atom.cpp index 05fd374a10..dc55167dc5 100644 --- a/src/EXTRA-COMPUTE/compute_ackland_atom.cpp +++ b/src/EXTRA-COMPUTE/compute_ackland_atom.cpp @@ -18,20 +18,22 @@ Updated algorithm by: Brian Barnes, brian.c.barnes11.civ@mail.mil ------------------------------------------------------------------------- */ -#include -#include #include "compute_ackland_atom.h" + #include "atom.h" -#include "update.h" +#include "comm.h" +#include "error.h" +#include "force.h" +#include "memory.h" #include "modify.h" -#include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" -#include "force.h" +#include "neighbor.h" #include "pair.h" -#include "comm.h" -#include "memory.h" -#include "error.h" +#include "update.h" + +#include +#include using namespace LAMMPS_NS; @@ -60,16 +62,10 @@ ComputeAcklandAtom::ComputeAcklandAtom(LAMMPS *lmp, int narg, char **arg) : int iarg = 3; while (narg > iarg) { if (strcmp("legacy",arg[iarg]) == 0) { - ++iarg; - if (iarg >= narg) - error->all(FLERR,"Invalid compute ackland/atom command"); - if (strcmp("yes",arg[iarg]) == 0) - legacy = 1; - else if (strcmp("no",arg[iarg]) == 0) - legacy = 0; - else error->all(FLERR,"Invalid compute ackland/atom command"); + if (iarg+2 > narg) error->all(FLERR,"Invalid compute ackland/atom command"); + legacy = utils::logical(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } - ++iarg; } } diff --git a/src/EXTRA-COMPUTE/compute_entropy_atom.cpp b/src/EXTRA-COMPUTE/compute_entropy_atom.cpp index d0866c946c..ac53bf1e7f 100644 --- a/src/EXTRA-COMPUTE/compute_entropy_atom.cpp +++ b/src/EXTRA-COMPUTE/compute_entropy_atom.cpp @@ -17,21 +17,23 @@ ------------------------------------------------------------------------- */ #include "compute_entropy_atom.h" -#include -#include + #include "atom.h" -#include "update.h" -#include "modify.h" -#include "neighbor.h" -#include "neigh_list.h" -#include "neigh_request.h" -#include "force.h" -#include "pair.h" #include "comm.h" +#include "domain.h" +#include "error.h" +#include "force.h" #include "math_const.h" #include "memory.h" -#include "error.h" -#include "domain.h" +#include "modify.h" +#include "neigh_list.h" +#include "neigh_request.h" +#include "neighbor.h" +#include "pair.h" +#include "update.h" + +#include +#include using namespace LAMMPS_NS; using namespace MathConst; @@ -44,8 +46,7 @@ ComputeEntropyAtom(LAMMPS *lmp, int narg, char **arg) : pair_entropy(nullptr), pair_entropy_avg(nullptr) { if (narg < 5 || narg > 10) - error->all(FLERR,"Illegal compute entropy/atom command; wrong number" - " of arguments"); + error->all(FLERR,"Illegal compute entropy/atom command; wrong number of arguments"); // Arguments are: sigma cutoff avg yes/no cutoff2 local yes/no // sigma is the gaussian width @@ -57,11 +58,9 @@ ComputeEntropyAtom(LAMMPS *lmp, int narg, char **arg) : // the g(r) sigma = utils::numeric(FLERR,arg[3],false,lmp); - if (sigma <= 0.0) error->all(FLERR,"Illegal compute entropy/atom" - " command; sigma must be positive"); + if (sigma <= 0.0) error->all(FLERR,"Illegal compute entropy/atom command; sigma must be positive"); cutoff = utils::numeric(FLERR,arg[4],false,lmp); - if (cutoff <= 0.0) error->all(FLERR,"Illegal compute entropy/atom" - " command; cutoff must be positive"); + if (cutoff <= 0.0) error->all(FLERR,"Illegal compute entropy/atom command; cutoff must be positive"); cutoff2 = 0.; avg_flag = 0; @@ -71,26 +70,17 @@ ComputeEntropyAtom(LAMMPS *lmp, int narg, char **arg) : int iarg = 5; while (iarg < narg) { if (strcmp(arg[iarg],"avg") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute entropy/atom;" - " missing arguments after avg"); - if (strcmp(arg[iarg+1],"yes") == 0) avg_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) avg_flag = 0; - else error->all(FLERR,"Illegal compute entropy/atom;" - " argument after avg should be yes or no"); + if (iarg+3 > narg) error->all(FLERR,"Illegal compute entropy/atom command"); + avg_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); cutoff2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (cutoff2 < 0.0) error->all(FLERR,"Illegal compute entropy/atom" - " command; negative cutoff2"); + if (cutoff2 < 0.0) error->all(FLERR,"Illegal compute entropy/atom command; negative cutoff2"); cutsq2 = cutoff2*cutoff2; iarg += 3; } else if (strcmp(arg[iarg],"local") == 0) { - if (strcmp(arg[iarg+1],"yes") == 0) local_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) local_flag = 0; - else error->all(FLERR,"Illegal compute entropy/atom;" - " argument after local should be yes or no"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute entropy/atom command"); + local_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; - } else error->all(FLERR,"Illegal compute entropy/atom; argument after" - " sigma and cutoff should be avg or local"); + } else error->all(FLERR,"Illegal compute entropy/atom command"); } diff --git a/src/EXTRA-DUMP/dump_dcd.cpp b/src/EXTRA-DUMP/dump_dcd.cpp index 97c9bec646..ec3973448a 100644 --- a/src/EXTRA-DUMP/dump_dcd.cpp +++ b/src/EXTRA-DUMP/dump_dcd.cpp @@ -258,9 +258,7 @@ int DumpDCD::modify_param(int narg, char **arg) { if (strcmp(arg[0],"unwrap") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[1],"yes") == 0) unwrap_flag = 1; - else if (strcmp(arg[1],"no") == 0) unwrap_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + unwrap_flag = utils::logical(FLERR,arg[1],false,lmp); return 2; } return 0; diff --git a/src/EXTRA-DUMP/dump_xtc.cpp b/src/EXTRA-DUMP/dump_xtc.cpp index 7de6d03561..94846671cd 100644 --- a/src/EXTRA-DUMP/dump_xtc.cpp +++ b/src/EXTRA-DUMP/dump_xtc.cpp @@ -24,19 +24,20 @@ ------------------------------------------------------------------------- */ #include "dump_xtc.h" -#include -#include -#include -#include "domain.h" #include "atom.h" -#include "update.h" -#include "group.h" -#include "output.h" -#include "force.h" #include "comm.h" -#include "memory.h" +#include "domain.h" #include "error.h" +#include "force.h" +#include "group.h" +#include "memory.h" +#include "output.h" +#include "update.h" + +#include +#include +#include using namespace LAMMPS_NS; @@ -278,9 +279,7 @@ int DumpXTC::modify_param(int narg, char **arg) { if (strcmp(arg[0],"unwrap") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[1],"yes") == 0) unwrap_flag = 1; - else if (strcmp(arg[1],"no") == 0) unwrap_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + unwrap_flag = utils::logical(FLERR,arg[1],false,lmp); return 2; } else if (strcmp(arg[0],"precision") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); diff --git a/src/EXTRA-DUMP/xdr_compat.h b/src/EXTRA-DUMP/xdr_compat.h index 30aecbcb62..6557a60a53 100644 --- a/src/EXTRA-DUMP/xdr_compat.h +++ b/src/EXTRA-DUMP/xdr_compat.h @@ -59,8 +59,8 @@ extern "C" { typedef int bool_t; -#if defined(__MINGW32__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__) +#if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__) || \ + defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__) typedef char *caddr_t; typedef unsigned int u_int; #endif diff --git a/src/EXTRA-FIX/fix_ave_correlate_long.cpp b/src/EXTRA-FIX/fix_ave_correlate_long.cpp index 6e4e26754f..1746c7f6f5 100644 --- a/src/EXTRA-FIX/fix_ave_correlate_long.cpp +++ b/src/EXTRA-FIX/fix_ave_correlate_long.cpp @@ -36,7 +36,6 @@ #include #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -260,11 +259,11 @@ FixAveCorrelateLong::FixAveCorrelateLong(LAMMPS * lmp, int narg, char **arg): fprintf(fp," %s*%s",arg[5+i],arg[5+j]); fprintf(fp,"\n"); } - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; + delete[] title1; + delete[] title2; // allocate and initialize memory for calculated values and correlators @@ -319,11 +318,11 @@ FixAveCorrelateLong::FixAveCorrelateLong(LAMMPS * lmp, int narg, char **arg): FixAveCorrelateLong::~FixAveCorrelateLong() { - delete [] which; - delete [] argindex; - delete [] value2index; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; + delete[] which; + delete[] argindex; + delete[] value2index; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; memory->destroy(values); memory->destroy(shift); @@ -467,7 +466,7 @@ void FixAveCorrelateLong::end_of_step() evaluate(); if (fp && me == 0) { - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,"# Timestep: " BIGINT_FORMAT "\n", ntimestep); for (unsigned int i=0;idt*nevery); @@ -478,9 +477,9 @@ void FixAveCorrelateLong::end_of_step() } fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } diff --git a/src/EXTRA-FIX/fix_ave_correlate_long.h b/src/EXTRA-FIX/fix_ave_correlate_long.h index b62c6aefcb..a31ae78217 100644 --- a/src/EXTRA-FIX/fix_ave_correlate_long.h +++ b/src/EXTRA-FIX/fix_ave_correlate_long.h @@ -66,7 +66,7 @@ class FixAveCorrelateLong : public Fix { FILE *fp; int type, startstep, overwrite; - long filepos; + bigint filepos; int npair; // number of correlation pairs to calculate double *values; diff --git a/src/EXTRA-FIX/fix_flow_gauss.cpp b/src/EXTRA-FIX/fix_flow_gauss.cpp index 415f1eecc0..2f8de2e21a 100644 --- a/src/EXTRA-FIX/fix_flow_gauss.cpp +++ b/src/EXTRA-FIX/fix_flow_gauss.cpp @@ -91,9 +91,7 @@ FixFlowGauss::FixFlowGauss(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"energy") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal energy keyword"); - if (strcmp(arg[iarg+1],"yes") == 0) workflag = true; - else if (strcmp(arg[iarg+1],"no") != 0) - error->all(FLERR,"Illegal energy keyword"); + workflag = utils::logical(FLERR,arg[iarg+1],false,lmp) == 1; iarg += 2; } else error->all(FLERR,"Illegal fix flow/gauss command"); } diff --git a/src/EXTRA-FIX/fix_gld.cpp b/src/EXTRA-FIX/fix_gld.cpp index 3f807d0f51..41585e4fd0 100644 --- a/src/EXTRA-FIX/fix_gld.cpp +++ b/src/EXTRA-FIX/fix_gld.cpp @@ -19,17 +19,18 @@ #include "fix_gld.h" +#include "atom.h" +#include "comm.h" +#include "error.h" +#include "force.h" +#include "group.h" +#include "memory.h" +#include "random_mars.h" +#include "respa.h" +#include "update.h" + #include #include -#include "atom.h" -#include "force.h" -#include "update.h" -#include "respa.h" -#include "comm.h" -#include "random_mars.h" -#include "memory.h" -#include "error.h" -#include "group.h" #define GLD_UNIFORM_DISTRO @@ -128,26 +129,14 @@ FixGLD::FixGLD(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"zero") == 0) { - if (iarg+2 > narg) { - error->all(FLERR, "Illegal fix gld command"); - } - if (strcmp(arg[iarg+1],"no") == 0) { - zeroflag = 0; - } else if (strcmp(arg[iarg+1],"yes") == 0) { - zeroflag = 1; - } else { - error->all(FLERR,"Illegal fix gld command"); - } + if (iarg+2 > narg) error->all(FLERR, "Illegal fix gld command"); + zeroflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"frozen") == 0) { - if (iarg+2 > narg) { - error->all(FLERR, "Illegal fix gld command"); - } - if (strcmp(arg[iarg+1],"no") == 0) { - freezeflag = 0; - } else if (strcmp(arg[iarg+1],"yes") == 0) { - freezeflag = 1; + if (iarg+2 > narg) error->all(FLERR, "Illegal fix gld command"); + freezeflag = utils::logical(FLERR,arg[iarg+1],false,lmp); + if (freezeflag) { for (int i = 0; i < atom->nlocal; i++) { if (atom->mask[i] & groupbit) { for (int k = 0; k < 3*prony_terms; k=k+3) @@ -158,8 +147,6 @@ FixGLD::FixGLD(LAMMPS *lmp, int narg, char **arg) : } } } - } else { - error->all(FLERR, "Illegal fix gld command"); } iarg += 2; } diff --git a/src/EXTRA-FIX/fix_npt_cauchy.cpp b/src/EXTRA-FIX/fix_npt_cauchy.cpp index 6a7d91dd16..d9a0f850db 100644 --- a/src/EXTRA-FIX/fix_npt_cauchy.cpp +++ b/src/EXTRA-FIX/fix_npt_cauchy.cpp @@ -297,9 +297,7 @@ FixNPTCauchy::FixNPTCauchy(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"mtk") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); - if (strcmp(arg[iarg+1],"yes") == 0) mtk_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) mtk_flag = 0; - else error->all(FLERR,"Illegal fix npt/cauchy command"); + mtk_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"tloop") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); @@ -318,27 +316,19 @@ FixNPTCauchy::FixNPTCauchy(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"scalexy") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalexy = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalexy = 0; - else error->all(FLERR,"Illegal fix npt/cauchy command"); + scalexy = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scalexz") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalexz = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalexz = 0; - else error->all(FLERR,"Illegal fix npt/cauchy command"); + scalexz = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scaleyz") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); - if (strcmp(arg[iarg+1],"yes") == 0) scaleyz = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scaleyz = 0; - else error->all(FLERR,"Illegal fix npt/cauchy command"); + scaleyz = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"flip") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); - if (strcmp(arg[iarg+1],"yes") == 0) flipflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) flipflag = 0; - else error->all(FLERR,"Illegal fix npt/cauchy command"); + flipflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"update") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); @@ -352,10 +342,8 @@ FixNPTCauchy::FixNPTCauchy(LAMMPS *lmp, int narg, char **arg) : alpha = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"continue") == 0) { - if (strcmp(arg[iarg+1],"yes") != 0 && strcmp(arg[iarg+1],"no") != 0) - error->all(FLERR,"Illegal cauchystat continue value. " - "Must be 'yes' or 'no'"); - restartPK = !strcmp(arg[iarg+1],"yes"); + if (iarg+2 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); + restartPK = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"fixedpoint") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal fix npt/cauchy command"); @@ -2454,7 +2442,7 @@ double FixNPTCauchy::memory_usage() void FixNPTCauchy::CauchyStat_init() { if (comm->me == 0) { - std::string mesg = fmt::format("Using fix npt/cauchy with alpha={:f.8}\n",alpha); + std::string mesg = fmt::format("Using fix npt/cauchy with alpha={:.8f}\n",alpha); if (restartPK==1) { mesg += " (this is a continuation run)\n"; } else { @@ -2475,7 +2463,7 @@ void FixNPTCauchy::CauchyStat_init() error->all(FLERR,"Illegal fix npt/cauchy command: Alpha cannot be zero or negative."); if (restart_stored < 0) { - modify->add_fix(std::string(id_store) + "all STORE global 1 6"); + modify->add_fix(std::string(id_store) + " all STORE global 1 6"); restart_stored = modify->find_fix(id_store); } init_store = (FixStore *)modify->fix[restart_stored]; diff --git a/src/EXTRA-FIX/fix_pafi.cpp b/src/EXTRA-FIX/fix_pafi.cpp index 3b51906ae1..fbb6fb2971 100644 --- a/src/EXTRA-FIX/fix_pafi.cpp +++ b/src/EXTRA-FIX/fix_pafi.cpp @@ -103,16 +103,12 @@ FixPAFI::FixPAFI(LAMMPS *lmp, int narg, char **arg) : int iarg = 7; while (iarg < narg) { if (strcmp(arg[iarg],"overdamped") == 0) { - if (strcmp(arg[iarg+1],"no") == 0) od_flag = 0; - else if (strcmp(arg[iarg+1],"0") == 0) od_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) od_flag = 1; - else if (strcmp(arg[iarg+1],"1") == 0) od_flag = 1; + if (iarg+2 > narg) error->all(FLERR,"Illegal fix pafi command"); + od_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"com") == 0) { - if (strcmp(arg[iarg+1],"no") == 0) com_flag = 0; - else if (strcmp(arg[iarg+1],"0") == 0) com_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) com_flag = 1; - else if (strcmp(arg[iarg+1],"1") == 0) com_flag = 1; + if (iarg+2 > narg) error->all(FLERR,"Illegal fix pafi command"); + com_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix pafi command"); } diff --git a/src/EXTRA-FIX/fix_tmd.cpp b/src/EXTRA-FIX/fix_tmd.cpp index a46eb89713..4d85687e4d 100644 --- a/src/EXTRA-FIX/fix_tmd.cpp +++ b/src/EXTRA-FIX/fix_tmd.cpp @@ -123,7 +123,10 @@ nfileevery(0), fp(nullptr), xf(nullptr), xold(nullptr) FixTMD::~FixTMD() { - if (nfileevery && me == 0) fclose(fp); + if (nfileevery && me == 0) { + if (compressed) platform::pclose(fp); + else fclose(fp); + } // unregister callbacks to this fix from Atom class @@ -492,7 +495,7 @@ void FixTMD::readfile(char *file) delete [] buffer; if (me == 0) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } @@ -514,33 +517,21 @@ void FixTMD::readfile(char *file) /* ---------------------------------------------------------------------- proc 0 opens TMD data file - test if gzipped + test if compressed ------------------------------------------------------------------------- */ -void FixTMD::open(char *file) +void FixTMD::open(const std::string &file) { - if (utils::strmatch(file,"\\.gz$")) { + if (platform::has_compress_extension(file)) { compressed = 1; - -#ifdef LAMMPS_GZIP - auto gunzip = fmt::format("gzip -c -d {}",file); - -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file without gzip support"); -#endif + fp = platform::compressed_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file for reading"); } else { compressed = 0; - fp = fopen(file,"r"); + fp = fopen(file.c_str(),"r"); } - if (fp == nullptr) - error->one(FLERR,"Cannot open file {}: {}",file, utils::getsyserror()); + if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror()); } /* ---------------------------------------------------------------------- */ diff --git a/src/EXTRA-FIX/fix_tmd.h b/src/EXTRA-FIX/fix_tmd.h index fd818eb583..b85869930a 100644 --- a/src/EXTRA-FIX/fix_tmd.h +++ b/src/EXTRA-FIX/fix_tmd.h @@ -52,7 +52,7 @@ class FixTMD : public Fix { double **xf, **xold; void readfile(char *); - void open(char *); + void open(const std::string &); }; } // namespace LAMMPS_NS diff --git a/src/EXTRA-MOLECULE/angle_gaussian.cpp b/src/EXTRA-MOLECULE/angle_gaussian.cpp index e4310e0a22..54c2aa1880 100644 --- a/src/EXTRA-MOLECULE/angle_gaussian.cpp +++ b/src/EXTRA-MOLECULE/angle_gaussian.cpp @@ -1,4 +1,3 @@ -// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories @@ -34,9 +33,9 @@ using namespace MathConst; /* ---------------------------------------------------------------------- */ -AngleGaussian::AngleGaussian(LAMMPS *lmp) - : Angle(lmp), nterms(nullptr), angle_temperature(nullptr), - alpha(nullptr), width(nullptr), theta0(nullptr) +AngleGaussian::AngleGaussian(LAMMPS *lmp) : + Angle(lmp), nterms(nullptr), angle_temperature(nullptr), alpha(nullptr), width(nullptr), + theta0(nullptr) { } @@ -49,13 +48,13 @@ AngleGaussian::~AngleGaussian() memory->destroy(nterms); memory->destroy(angle_temperature); for (int i = 1; i <= atom->nangletypes; i++) { - delete [] alpha[i]; - delete [] width[i]; - delete [] theta0[i]; + delete[] alpha[i]; + delete[] width[i]; + delete[] theta0[i]; } - delete [] alpha; - delete [] width; - delete [] theta0; + delete[] alpha; + delete[] width; + delete[] theta0; } } @@ -63,15 +62,15 @@ AngleGaussian::~AngleGaussian() void AngleGaussian::compute(int eflag, int vflag) { - int i1,i2,i3,n,type; - double delx1,dely1,delz1,delx2,dely2,delz2; - double eangle,f1[3],f3[3]; + int i1, i2, i3, n, type; + double delx1, dely1, delz1, delx2, dely2, delz2; + double eangle, f1[3], f3[3]; double dtheta; - double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22; + double rsq1, rsq2, r1, r2, c, s, a, a11, a12, a22; double prefactor, exponent, g_i, sum_g_i, sum_numerator; eangle = 0.0; - ev_init(eflag,vflag); + ev_init(eflag, vflag); double **x = atom->x; double **f = atom->f; @@ -92,7 +91,7 @@ void AngleGaussian::compute(int eflag, int vflag) dely1 = x[i1][1] - x[i2][1]; delz1 = x[i1][2] - x[i2][2]; - rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1; + rsq1 = delx1 * delx1 + dely1 * dely1 + delz1 * delz1; r1 = sqrt(rsq1); // 2nd bond @@ -101,20 +100,20 @@ void AngleGaussian::compute(int eflag, int vflag) dely2 = x[i3][1] - x[i2][1]; delz2 = x[i3][2] - x[i2][2]; - rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2; + rsq2 = delx2 * delx2 + dely2 * dely2 + delz2 * delz2; r2 = sqrt(rsq2); // angle (cos and sin) - c = delx1*delx2 + dely1*dely2 + delz1*delz2; - c /= r1*r2; + c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; + c /= r1 * r2; if (c > 1.0) c = 1.0; if (c < -1.0) c = -1.0; - s = sqrt(1.0 - c*c); + s = sqrt(1.0 - c * c); if (s < SMAL) s = SMAL; - s = 1.0/s; + s = 1.0 / s; // force & energy double theta = acos(c); @@ -123,28 +122,28 @@ void AngleGaussian::compute(int eflag, int vflag) sum_numerator = 0.0; for (int i = 0; i < nterms[type]; i++) { dtheta = theta - theta0[type][i]; - prefactor = (alpha[type][i]/(width[type][i]*sqrt(MY_PI2))); - exponent = -2*dtheta*dtheta/(width[type][i]*width[type][i]); - g_i = prefactor*exp(exponent); + prefactor = (alpha[type][i] / (width[type][i] * sqrt(MY_PI2))); + exponent = -2 * dtheta * dtheta / (width[type][i] * width[type][i]); + g_i = prefactor * exp(exponent); sum_g_i += g_i; - sum_numerator += g_i*dtheta/(width[type][i]*width[type][i]); + sum_numerator += g_i * dtheta / (width[type][i] * width[type][i]); } if (sum_g_i < SMALL) sum_g_i = SMALL; - if (eflag) eangle = -(force->boltz*angle_temperature[type])*log(sum_g_i); + if (eflag) eangle = -(force->boltz * angle_temperature[type]) * log(sum_g_i); // I should check about the sign of this expression - a = -4.0*(force->boltz*angle_temperature[type])*(sum_numerator/sum_g_i)*s; - a11 = a*c / rsq1; - a12 = -a / (r1*r2); - a22 = a*c / rsq2; + a = -4.0 * (force->boltz * angle_temperature[type]) * (sum_numerator / sum_g_i) * s; + a11 = a * c / rsq1; + a12 = -a / (r1 * r2); + a22 = a * c / rsq2; - f1[0] = a11*delx1 + a12*delx2; - f1[1] = a11*dely1 + a12*dely2; - f1[2] = a11*delz1 + a12*delz2; - f3[0] = a22*delx2 + a12*delx1; - f3[1] = a22*dely2 + a12*dely1; - f3[2] = a22*delz2 + a12*delz1; + f1[0] = a11 * delx1 + a12 * delx2; + f1[1] = a11 * dely1 + a12 * dely2; + f1[2] = a11 * delz1 + a12 * delz2; + f3[0] = a22 * delx2 + a12 * delx1; + f3[1] = a22 * dely2 + a12 * dely1; + f3[2] = a22 * delz2 + a12 * delz1; // apply force to each of 3 atoms @@ -166,8 +165,9 @@ void AngleGaussian::compute(int eflag, int vflag) f[i3][2] += f3[2]; } - if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3, - delx1,dely1,delz1,delx2,dely2,delz2); + if (evflag) + ev_tally(i1, i2, i3, nlocal, newton_bond, eangle, f1, f3, delx1, dely1, delz1, delx2, dely2, + delz2); } } @@ -176,20 +176,20 @@ void AngleGaussian::compute(int eflag, int vflag) void AngleGaussian::allocate() { allocated = 1; - int n = atom->nangletypes; + int n = atom->nangletypes + 1; - memory->create(nterms,n+1,"angle:nterms"); - memory->create(angle_temperature,n+1,"angle:angle_temperature"); + memory->create(nterms, n, "angle:nterms"); + memory->create(angle_temperature, n, "angle:angle_temperature"); - alpha = new double *[n+1]; - width = new double *[n+1]; - theta0 = new double *[n+1]; - memset(alpha,0,sizeof(double)*(n+1)); - memset(width,0,sizeof(double)*(n+1)); - memset(theta0,0,sizeof(double)*(n+1)); + alpha = new double *[n]; + width = new double *[n]; + theta0 = new double *[n]; + memset(alpha, 0, sizeof(double *) * n); + memset(width, 0, sizeof(double *) * n); + memset(theta0, 0, sizeof(double *) * n); - memory->create(setflag,n+1,"angle:setflag"); - for (int i = 1; i <= n; i++) setflag[i] = 0; + memory->create(setflag, n, "angle:setflag"); + memset(setflag, 0, sizeof(int) * n); } /* ---------------------------------------------------------------------- @@ -198,15 +198,14 @@ void AngleGaussian::allocate() void AngleGaussian::coeff(int narg, char **arg) { - if (narg < 6) error->all(FLERR,"Incorrect args for angle coefficients"); + if (narg < 6) error->all(FLERR, "Incorrect args for angle coefficients"); - int ilo,ihi; - utils::bounds(FLERR,arg[0],1,atom->nangletypes,ilo,ihi,error); + int ilo, ihi; + utils::bounds(FLERR, arg[0], 1, atom->nangletypes, ilo, ihi, error); - double angle_temperature_one = utils::numeric(FLERR,arg[1],false,lmp); - int n = utils::inumeric(FLERR,arg[2],false,lmp); - if (narg != 3*n + 3) - error->all(FLERR,"Incorrect args for angle coefficients"); + double angle_temperature_one = utils::numeric(FLERR, arg[1], false, lmp); + int n = utils::inumeric(FLERR, arg[2], false, lmp); + if (narg != 3 * n + 3) error->all(FLERR, "Incorrect args for angle coefficients"); if (!allocated) allocate(); @@ -217,21 +216,21 @@ void AngleGaussian::coeff(int narg, char **arg) angle_temperature[i] = angle_temperature_one; nterms[i] = n; delete[] alpha[i]; - alpha[i] = new double [n]; + alpha[i] = new double[n]; delete[] width[i]; - width[i] = new double [n]; + width[i] = new double[n]; delete[] theta0[i]; - theta0[i] = new double [n]; + theta0[i] = new double[n]; for (int j = 0; j < n; j++) { - alpha[i][j] = utils::numeric(FLERR,arg[3+3*j],false,lmp); - width[i][j] = utils::numeric(FLERR,arg[4+3*j],false,lmp); - theta0[i][j] = utils::numeric(FLERR,arg[5+3*j],false,lmp)* MY_PI / 180.0; + alpha[i][j] = utils::numeric(FLERR, arg[3 + 3 * j], false, lmp); + width[i][j] = utils::numeric(FLERR, arg[4 + 3 * j], false, lmp); + theta0[i][j] = utils::numeric(FLERR, arg[5 + 3 * j], false, lmp) * MY_PI / 180.0; setflag[i] = 1; } count++; } - if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients"); + if (count == 0) error->all(FLERR, "Incorrect args for angle coefficients"); } /* ---------------------------------------------------------------------- */ @@ -247,12 +246,12 @@ double AngleGaussian::equilibrium_angle(int i) void AngleGaussian::write_restart(FILE *fp) { - fwrite(&angle_temperature[1],sizeof(double),atom->nangletypes,fp); - fwrite(&nterms[1],sizeof(int),atom->nangletypes,fp); + fwrite(&angle_temperature[1], sizeof(double), atom->nangletypes, fp); + fwrite(&nterms[1], sizeof(int), atom->nangletypes, fp); for (int i = 1; i <= atom->nangletypes; i++) { - fwrite(alpha[i],sizeof(double),nterms[i],fp); - fwrite(width[i],sizeof(double),nterms[i],fp); - fwrite(theta0[i],sizeof(double),nterms[i],fp); + fwrite(alpha[i], sizeof(double), nterms[i], fp); + fwrite(width[i], sizeof(double), nterms[i], fp); + fwrite(theta0[i], sizeof(double), nterms[i], fp); } } @@ -265,31 +264,32 @@ void AngleGaussian::read_restart(FILE *fp) allocate(); if (comm->me == 0) { - utils::sfread(FLERR,&angle_temperature[1],sizeof(double),atom->nangletypes,fp,nullptr,error); - utils::sfread(FLERR,&nterms[1],sizeof(int),atom->nangletypes,fp,nullptr,error); + utils::sfread(FLERR, &angle_temperature[1], sizeof(double), atom->nangletypes, fp, nullptr, + error); + utils::sfread(FLERR, &nterms[1], sizeof(int), atom->nangletypes, fp, nullptr, error); } - MPI_Bcast(&angle_temperature[1],atom->nangletypes,MPI_DOUBLE,0,world); - MPI_Bcast(&nterms[1],atom->nangletypes,MPI_INT,0,world); + MPI_Bcast(&angle_temperature[1], atom->nangletypes, MPI_DOUBLE, 0, world); + MPI_Bcast(&nterms[1], atom->nangletypes, MPI_INT, 0, world); // allocate for (int i = 1; i <= atom->nangletypes; i++) { - alpha[i] = new double [nterms[i]]; - width[i] = new double [nterms[i]]; - theta0[i] = new double [nterms[i]]; + alpha[i] = new double[nterms[i]]; + width[i] = new double[nterms[i]]; + theta0[i] = new double[nterms[i]]; } if (comm->me == 0) { for (int i = 1; i <= atom->nangletypes; i++) { - utils::sfread(FLERR,alpha[i],sizeof(double),nterms[i],fp,nullptr,error); - utils::sfread(FLERR,width[i],sizeof(double),nterms[i],fp,nullptr,error); - utils::sfread(FLERR,theta0[i],sizeof(double),nterms[i],fp,nullptr,error); + utils::sfread(FLERR, alpha[i], sizeof(double), nterms[i], fp, nullptr, error); + utils::sfread(FLERR, width[i], sizeof(double), nterms[i], fp, nullptr, error); + utils::sfread(FLERR, theta0[i], sizeof(double), nterms[i], fp, nullptr, error); } } for (int i = 1; i <= atom->nangletypes; i++) { - MPI_Bcast(alpha[i],nterms[i],MPI_DOUBLE,0,world); - MPI_Bcast(width[i],nterms[i],MPI_DOUBLE,0,world); - MPI_Bcast(theta0[i],nterms[i],MPI_DOUBLE,0,world); + MPI_Bcast(alpha[i], nterms[i], MPI_DOUBLE, 0, world); + MPI_Bcast(width[i], nterms[i], MPI_DOUBLE, 0, world); + MPI_Bcast(theta0[i], nterms[i], MPI_DOUBLE, 0, world); } for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1; @@ -302,13 +302,12 @@ void AngleGaussian::read_restart(FILE *fp) void AngleGaussian::write_data(FILE *fp) { for (int i = 1; i <= atom->nangletypes; i++) { - fprintf(fp,"%d %g %d",i,angle_temperature[i],nterms[i]); + fprintf(fp, "%d %g %d", i, angle_temperature[i], nterms[i]); for (int j = 0; j < nterms[i]; j++) { - fprintf(fp," %g %g %g",alpha[i][j],width[i][j],(theta0[i][j]/MY_PI)*180.0); + fprintf(fp, " %g %g %g", alpha[i][j], width[i][j], (theta0[i][j] / MY_PI) * 180.0); } fprintf(fp, "\n"); } - } /* ---------------------------------------------------------------------- */ @@ -320,30 +319,30 @@ 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); - double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1); + domain->minimum_image(delx1, dely1, delz1); + double r1 = sqrt(delx1 * delx1 + dely1 * dely1 + delz1 * delz1); double delx2 = x[i3][0] - x[i2][0]; double dely2 = x[i3][1] - x[i2][1]; double delz2 = x[i3][2] - x[i2][2]; - domain->minimum_image(delx2,dely2,delz2); - double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2); + domain->minimum_image(delx2, dely2, delz2); + double r2 = sqrt(delx2 * delx2 + dely2 * dely2 + delz2 * delz2); - double c = delx1*delx2 + dely1*dely2 + delz1*delz2; - c /= r1*r2; + double c = delx1 * delx2 + dely1 * dely2 + delz1 * delz2; + c /= r1 * r2; if (c > 1.0) c = 1.0; if (c < -1.0) c = -1.0; - double theta = acos(c) ; + double theta = acos(c); double sum_g_i = 0.0; for (int i = 0; i < nterms[type]; i++) { double dtheta = theta - theta0[type][i]; - double prefactor = (alpha[type][i]/(width[type][i]*sqrt(MY_PI2))); - double exponent = -2*dtheta*dtheta/(width[type][i]*width[type][i]); - double g_i = prefactor*exp(exponent); + double prefactor = (alpha[type][i] / (width[type][i] * sqrt(MY_PI2))); + double exponent = -2 * dtheta * dtheta / (width[type][i] * width[type][i]); + double g_i = prefactor * exp(exponent); sum_g_i += g_i; } if (sum_g_i < SMALL) sum_g_i = SMALL; - return -(force->boltz*angle_temperature[type])*log(sum_g_i); + return -(force->boltz * angle_temperature[type]) * log(sum_g_i); } diff --git a/src/EXTRA-MOLECULE/bond_gaussian.cpp b/src/EXTRA-MOLECULE/bond_gaussian.cpp index ca0bd13df8..c2ab00dfde 100644 --- a/src/EXTRA-MOLECULE/bond_gaussian.cpp +++ b/src/EXTRA-MOLECULE/bond_gaussian.cpp @@ -1,4 +1,3 @@ -// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories @@ -14,16 +13,16 @@ #include "bond_gaussian.h" -#include -#include #include "atom.h" -#include "neighbor.h" #include "comm.h" +#include "error.h" #include "force.h" #include "math_const.h" #include "memory.h" -#include "error.h" +#include "neighbor.h" +#include +#include using namespace LAMMPS_NS; using namespace MathConst; @@ -32,9 +31,9 @@ using namespace MathConst; /* ---------------------------------------------------------------------- */ -BondGaussian::BondGaussian(LAMMPS *lmp) - : Bond(lmp), nterms(nullptr), bond_temperature(nullptr), - alpha(nullptr), width(nullptr), r0(nullptr) +BondGaussian::BondGaussian(LAMMPS *lmp) : + Bond(lmp), nterms(nullptr), bond_temperature(nullptr), alpha(nullptr), width(nullptr), + r0(nullptr) { reinitflag = 1; } @@ -48,13 +47,13 @@ BondGaussian::~BondGaussian() memory->destroy(nterms); memory->destroy(bond_temperature); for (int i = 1; i <= atom->nbondtypes; i++) { - delete [] alpha[i]; - delete [] width[i]; - delete [] r0[i]; + delete[] alpha[i]; + delete[] width[i]; + delete[] r0[i]; } - delete [] alpha; - delete [] width; - delete [] r0; + delete[] alpha; + delete[] width; + delete[] r0; } } @@ -62,13 +61,13 @@ BondGaussian::~BondGaussian() void BondGaussian::compute(int eflag, int vflag) { - int i1,i2,n,type; - double delx,dely,delz,ebond,fbond; - double rsq,r,dr; + int i1, i2, n, type; + double delx, dely, delz, ebond, fbond; + double rsq, r, dr; double prefactor, exponent, g_i, sum_g_i, sum_numerator; ebond = 0.0; - ev_init(eflag,vflag); + ev_init(eflag, vflag); double **x = atom->x; double **f = atom->f; @@ -86,43 +85,45 @@ void BondGaussian::compute(int eflag, int vflag) dely = x[i1][1] - x[i2][1]; delz = x[i1][2] - x[i2][2]; - rsq = delx*delx + dely*dely + delz*delz; + rsq = delx * delx + dely * dely + delz * delz; r = sqrt(rsq); sum_g_i = 0.0; sum_numerator = 0.0; for (int i = 0; i < nterms[type]; i++) { dr = r - r0[type][i]; - prefactor = (alpha[type][i]/(width[type][i]*sqrt(MY_PI2))); - exponent = -2*dr*dr/(width[type][i]*width[type][i]); - g_i = prefactor*exp(exponent); + prefactor = (alpha[type][i] / (width[type][i] * sqrt(MY_PI2))); + exponent = -2 * dr * dr / (width[type][i] * width[type][i]); + g_i = prefactor * exp(exponent); sum_g_i += g_i; - sum_numerator += g_i*dr/(width[type][i]*width[type][i]); + sum_numerator += g_i * dr / (width[type][i] * width[type][i]); } // force & energy if (sum_g_i < SMALL) sum_g_i = SMALL; - if (r > 0.0) fbond = -4.0*(force->boltz*bond_temperature[type])*(sum_numerator/sum_g_i)/r; - else fbond = 0.0; + if (r > 0.0) + fbond = -4.0 * (force->boltz * bond_temperature[type]) * (sum_numerator / sum_g_i) / r; + else + fbond = 0.0; - if (eflag) ebond = -(force->boltz*bond_temperature[type])*log(sum_g_i); + if (eflag) ebond = -(force->boltz * bond_temperature[type]) * log(sum_g_i); // apply force to each of 2 atoms if (newton_bond || i1 < nlocal) { - f[i1][0] += delx*fbond; - f[i1][1] += dely*fbond; - f[i1][2] += delz*fbond; + f[i1][0] += delx * fbond; + f[i1][1] += dely * fbond; + f[i1][2] += delz * fbond; } if (newton_bond || i2 < nlocal) { - f[i2][0] -= delx*fbond; - f[i2][1] -= dely*fbond; - f[i2][2] -= delz*fbond; + f[i2][0] -= delx * fbond; + f[i2][1] -= dely * fbond; + f[i2][2] -= delz * fbond; } - if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz); + if (evflag) ev_tally(i1, i2, nlocal, newton_bond, ebond, fbond, delx, dely, delz); } } @@ -131,20 +132,20 @@ void BondGaussian::compute(int eflag, int vflag) void BondGaussian::allocate() { allocated = 1; - int n = atom->nbondtypes; + int n = atom->nbondtypes + 1; - memory->create(nterms,n+1,"bond:nterms"); - memory->create(bond_temperature,n+1,"bond:bond_temperature"); + memory->create(nterms, n, "bond:nterms"); + memory->create(bond_temperature, n, "bond:bond_temperature"); - alpha = new double *[n+1]; - width = new double *[n+1]; - r0 = new double *[n+1]; - memset(alpha,0,sizeof(double)*(n+1)); - memset(width,0,sizeof(double)*(n+1)); - memset(r0,0,sizeof(double)*(n+1)); + alpha = new double *[n]; + width = new double *[n]; + r0 = new double *[n]; + memset(alpha, 0, sizeof(double *) * n); + memset(width, 0, sizeof(double *) * n); + memset(r0, 0, sizeof(double *) * n); - memory->create(setflag,n+1,"bond:setflag"); - for (int i = 1; i <= n; i++) setflag[i] = 0; + memory->create(setflag, n, "bond:setflag"); + memset(setflag, 0, sizeof(int) * n); } /* ---------------------------------------------------------------------- @@ -153,15 +154,14 @@ void BondGaussian::allocate() void BondGaussian::coeff(int narg, char **arg) { - if (narg < 6) error->all(FLERR,"Incorrect args for bond coefficients"); + if (narg < 6) error->all(FLERR, "Incorrect args for bond coefficients"); - int ilo,ihi; - utils::bounds(FLERR,arg[0],1,atom->nbondtypes,ilo,ihi,error); + int ilo, ihi; + utils::bounds(FLERR, arg[0], 1, atom->nbondtypes, ilo, ihi, error); - double bond_temp_one = utils::numeric(FLERR,arg[1],false,lmp); - int n = utils::inumeric(FLERR,arg[2],false,lmp); - if (narg != 3*n + 3) - error->all(FLERR,"Incorrect args for bond coefficients"); + double bond_temp_one = utils::numeric(FLERR, arg[1], false, lmp); + int n = utils::inumeric(FLERR, arg[2], false, lmp); + if (narg != 3 * n + 3) error->all(FLERR, "Incorrect args for bond coefficients"); if (!allocated) allocate(); @@ -170,21 +170,21 @@ void BondGaussian::coeff(int narg, char **arg) bond_temperature[i] = bond_temp_one; nterms[i] = n; delete[] alpha[i]; - alpha[i] = new double [n]; + alpha[i] = new double[n]; delete[] width[i]; - width[i] = new double [n]; + width[i] = new double[n]; delete[] r0[i]; - r0[i] = new double [n]; + r0[i] = new double[n]; for (int j = 0; j < n; j++) { - alpha[i][j] = utils::numeric(FLERR,arg[3+3*j],false,lmp); - width[i][j] = utils::numeric(FLERR,arg[4+3*j],false,lmp); - r0[i][j] = utils::numeric(FLERR,arg[5+3*j],false,lmp); + alpha[i][j] = utils::numeric(FLERR, arg[3 + 3 * j], false, lmp); + width[i][j] = utils::numeric(FLERR, arg[4 + 3 * j], false, lmp); + r0[i][j] = utils::numeric(FLERR, arg[5 + 3 * j], false, lmp); setflag[i] = 1; } count++; } - if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients"); + if (count == 0) error->all(FLERR, "Incorrect args for bond coefficients"); } /* ---------------------------------------------------------------------- @@ -202,12 +202,12 @@ double BondGaussian::equilibrium_distance(int i) void BondGaussian::write_restart(FILE *fp) { - fwrite(&bond_temperature[1],sizeof(double),atom->nbondtypes,fp); - fwrite(&nterms[1],sizeof(int),atom->nbondtypes,fp); + fwrite(&bond_temperature[1], sizeof(double), atom->nbondtypes, fp); + fwrite(&nterms[1], sizeof(int), atom->nbondtypes, fp); for (int i = 1; i <= atom->nbondtypes; i++) { - fwrite(alpha[i],sizeof(double),nterms[i],fp); - fwrite(width[i],sizeof(double),nterms[i],fp); - fwrite(r0[i],sizeof(double),nterms[i],fp); + fwrite(alpha[i], sizeof(double), nterms[i], fp); + fwrite(width[i], sizeof(double), nterms[i], fp); + fwrite(r0[i], sizeof(double), nterms[i], fp); } } @@ -220,31 +220,32 @@ void BondGaussian::read_restart(FILE *fp) allocate(); if (comm->me == 0) { - utils::sfread(FLERR,&bond_temperature[1],sizeof(double),atom->nbondtypes,fp,nullptr,error); - utils::sfread(FLERR,&nterms[1],sizeof(int),atom->nbondtypes,fp,nullptr,error); + utils::sfread(FLERR, &bond_temperature[1], sizeof(double), atom->nbondtypes, fp, nullptr, + error); + utils::sfread(FLERR, &nterms[1], sizeof(int), atom->nbondtypes, fp, nullptr, error); } - MPI_Bcast(&bond_temperature[1],atom->nbondtypes,MPI_DOUBLE,0,world); - MPI_Bcast(&nterms[1],atom->nbondtypes,MPI_INT,0,world); + MPI_Bcast(&bond_temperature[1], atom->nbondtypes, MPI_DOUBLE, 0, world); + MPI_Bcast(&nterms[1], atom->nbondtypes, MPI_INT, 0, world); // allocate for (int i = 1; i <= atom->nbondtypes; i++) { - alpha[i] = new double [nterms[i]]; - width[i] = new double [nterms[i]]; - r0[i] = new double [nterms[i]]; + alpha[i] = new double[nterms[i]]; + width[i] = new double[nterms[i]]; + r0[i] = new double[nterms[i]]; } if (comm->me == 0) { for (int i = 1; i <= atom->nbondtypes; i++) { - utils::sfread(FLERR,alpha[i],sizeof(double),nterms[i],fp,nullptr,error); - utils::sfread(FLERR,width[i],sizeof(double),nterms[i],fp,nullptr,error); - utils::sfread(FLERR,r0[i],sizeof(double),nterms[i],fp,nullptr,error); + utils::sfread(FLERR, alpha[i], sizeof(double), nterms[i], fp, nullptr, error); + utils::sfread(FLERR, width[i], sizeof(double), nterms[i], fp, nullptr, error); + utils::sfread(FLERR, r0[i], sizeof(double), nterms[i], fp, nullptr, error); } } for (int i = 1; i <= atom->nbondtypes; i++) { - MPI_Bcast(alpha[i],nterms[i],MPI_DOUBLE,0,world); - MPI_Bcast(width[i],nterms[i],MPI_DOUBLE,0,world); - MPI_Bcast(r0[i],nterms[i],MPI_DOUBLE,0,world); + MPI_Bcast(alpha[i], nterms[i], MPI_DOUBLE, 0, world); + MPI_Bcast(width[i], nterms[i], MPI_DOUBLE, 0, world); + MPI_Bcast(r0[i], nterms[i], MPI_DOUBLE, 0, world); } for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1; @@ -257,9 +258,9 @@ void BondGaussian::read_restart(FILE *fp) void BondGaussian::write_data(FILE *fp) { for (int i = 1; i <= atom->nbondtypes; i++) { - fprintf(fp,"%d %g %d",i,bond_temperature[i],nterms[i]); + fprintf(fp, "%d %g %d", i, bond_temperature[i], nterms[i]); for (int j = 0; j < nterms[i]; j++) { - fprintf(fp," %g %g %g",alpha[i][j],width[i][j],r0[i][j]); + fprintf(fp, " %g %g %g", alpha[i][j], width[i][j], r0[i][j]); } fprintf(fp, "\n"); } @@ -267,26 +268,25 @@ void BondGaussian::write_data(FILE *fp) /* ---------------------------------------------------------------------- */ -double BondGaussian::single(int type, double rsq, int /*i*/, int /*j*/, - double &fforce) +double BondGaussian::single(int type, double rsq, int /*i*/, int /*j*/, double &fforce) { double r = sqrt(rsq); fforce = 0; double sum_g_i = 0.0; double sum_numerator = 0.0; - for (int i = 0; i < nterms[type]; i++) { - double dr = r - r0[type][i]; - double prefactor = (alpha[type][i]/(width[type][i]*sqrt(MY_PI2))); - double exponent = -2*dr*dr/(width[type][i]*width[type][i]); - double g_i = prefactor*exp(exponent); - sum_g_i += g_i; - sum_numerator += g_i*dr/(width[type][i]*width[type][i]); - } + for (int i = 0; i < nterms[type]; i++) { + double dr = r - r0[type][i]; + double prefactor = (alpha[type][i] / (width[type][i] * sqrt(MY_PI2))); + double exponent = -2 * dr * dr / (width[type][i] * width[type][i]); + double g_i = prefactor * exp(exponent); + sum_g_i += g_i; + sum_numerator += g_i * dr / (width[type][i] * width[type][i]); + } if (sum_g_i < SMALL) sum_g_i = SMALL; - if (r > 0.0) fforce = -4.0*(force->boltz*bond_temperature[type])*(sum_numerator/sum_g_i)/r; + if (r > 0.0) + fforce = -4.0 * (force->boltz * bond_temperature[type]) * (sum_numerator / sum_g_i) / r; - return -(force->boltz*bond_temperature[type])*log(sum_g_i); + return -(force->boltz * bond_temperature[type]) * log(sum_g_i); } - diff --git a/src/EXTRA-PAIR/pair_coul_exclude.cpp b/src/EXTRA-PAIR/pair_coul_exclude.cpp index 404fc9c784..74890bcf08 100644 --- a/src/EXTRA-PAIR/pair_coul_exclude.cpp +++ b/src/EXTRA-PAIR/pair_coul_exclude.cpp @@ -189,7 +189,7 @@ void PairCoulExclude::init_style() init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ -double PairCoulExclude::init_one(int i, int j) +double PairCoulExclude::init_one(int /*i*/, int /*j*/) { return cut_global; } diff --git a/src/EXTRA-PAIR/pair_e3b.cpp b/src/EXTRA-PAIR/pair_e3b.cpp index a904939e42..7e865ac6f8 100644 --- a/src/EXTRA-PAIR/pair_e3b.cpp +++ b/src/EXTRA-PAIR/pair_e3b.cpp @@ -643,7 +643,7 @@ void PairE3B::checkInputs(const double &bondL) if (k2 == NOT_SET) error->all(FLERR, "K2 keyword missing"); //now test that values are within acceptable ranges - if (k2 < 0.0 or k3 < 0.0) error->all(FLERR, "exponential decay is negative"); + if (k2 < 0.0 || k3 < 0.0) error->all(FLERR, "exponential decay is negative"); if (bondL < 0.0) error->all(FLERR, "OH bond length is negative"); if (rc2 < 0.0 || rc3 < 0.0 || rs < 0.0) error->all(FLERR, "potential cutoff is negative"); if (rs > rc3) error->all(FLERR, "potential switching distance is larger than cutoff"); diff --git a/src/FEP/compute_fep.cpp b/src/FEP/compute_fep.cpp index 683fbe114a..787c8a29e6 100644 --- a/src/FEP/compute_fep.cpp +++ b/src/FEP/compute_fep.cpp @@ -124,18 +124,12 @@ ComputeFEP::ComputeFEP(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"tail") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal optional keyword " - "in compute fep"); - if (strcmp(arg[iarg+1],"no") == 0) tailflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) tailflag = 1; - else error->all(FLERR,"Illegal optional keyword in compute fep"); + if (iarg+2 > narg) error->all(FLERR,"Illegal optional keyword in compute fep"); + tailflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"volume") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal optional keyword " - "in compute fep"); - if (strcmp(arg[iarg+1],"no") == 0) volumeflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) volumeflag = 1; - else error->all(FLERR,"Illegal optional keyword in compute fep"); + if (iarg+2 > narg) error->all(FLERR,"Illegal optional keyword in compute fep"); + volumeflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal optional keyword in compute fep"); diff --git a/src/FEP/fix_adapt_fep.cpp b/src/FEP/fix_adapt_fep.cpp index a6891c8742..d43c053b9a 100644 --- a/src/FEP/fix_adapt_fep.cpp +++ b/src/FEP/fix_adapt_fep.cpp @@ -138,21 +138,15 @@ FixAdaptFEP::FixAdaptFEP(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"reset") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt/fep command"); - if (strcmp(arg[iarg+1],"no") == 0) resetflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) resetflag = 1; - else error->all(FLERR,"Illegal fix adapt/fep command"); + resetflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scale") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt/fep command"); - if (strcmp(arg[iarg+1],"no") == 0) scaleflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) scaleflag = 1; - else error->all(FLERR,"Illegal fix adapt/fep command"); + scaleflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"after") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt/fep command"); - if (strcmp(arg[iarg+1],"no") == 0) afterflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) afterflag = 1; - else error->all(FLERR,"Illegal fix adapt/fep command"); + afterflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix adapt/fep command"); } diff --git a/src/GPU/fix_gpu.cpp b/src/GPU/fix_gpu.cpp index d26493e57b..7180a04873 100644 --- a/src/GPU/fix_gpu.cpp +++ b/src/GPU/fix_gpu.cpp @@ -136,16 +136,17 @@ FixGPU::FixGPU(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"neigh") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package gpu command"); - if (strcmp(arg[iarg+1],"yes") == 0) _gpu_mode = GPU_NEIGH; - else if (strcmp(arg[iarg+1],"no") == 0) _gpu_mode = GPU_FORCE; - else if (strcmp(arg[iarg+1],"hybrid") == 0) _gpu_mode = GPU_HYB_NEIGH; + const std::string modearg = arg[iarg+1]; + if ((modearg == "yes") || (modearg == "on") || (modearg == "true")) + _gpu_mode = GPU_NEIGH; + else if ((modearg == "no") || (modearg == "off") || (modearg == "false")) + _gpu_mode = GPU_FORCE; + else if (modearg == "hybrid") _gpu_mode = GPU_HYB_NEIGH; else error->all(FLERR,"Illegal package gpu command"); iarg += 2; } else if (strcmp(arg[iarg],"newton") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package gpu command"); - if (strcmp(arg[iarg+1],"off") == 0) newtonflag = 0; - else if (strcmp(arg[iarg+1],"on") == 0) newtonflag = 1; - else error->all(FLERR,"Illegal package gpu command"); + newtonflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"binsize") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package gpu command"); @@ -185,9 +186,7 @@ FixGPU::FixGPU(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"pair/only") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package gpu command"); - if (strcmp(arg[iarg+1],"off") == 0) pair_only_flag = 0; - else if (strcmp(arg[iarg+1],"on") == 0) pair_only_flag = 1; - else error->all(FLERR,"Illegal package gpu command"); + pair_only_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"ocl_args") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package gpu command"); diff --git a/src/GPU/gpu_extra.h b/src/GPU/gpu_extra.h index bd55d11021..c2d9931e0a 100644 --- a/src/GPU/gpu_extra.h +++ b/src/GPU/gpu_extra.h @@ -78,7 +78,11 @@ inline void check_flag(int error_flag, LAMMPS_NS::Error *error, MPI_Comm &world) else if (all_success == -13) error->all(FLERR, "Invalid device configuration."); else if (all_success == -15) - error->all(FLERR, "P3M built for FP64 and GPU device is FP32 only."); + error->all(FLERR, "PPPM was compiled for double precision floating point " + "but GPU device supports single precision only."); + else if (all_success == -16) + error->all(FLERR, "GPU library was compiled for double or mixed precision " + "floating point but GPU device supports single precision only."); else error->all(FLERR, "Unknown error in GPU library"); } diff --git a/src/GPU/pair_beck_gpu.cpp b/src/GPU/pair_beck_gpu.cpp index a2a3133a24..e3dfda428f 100644 --- a/src/GPU/pair_beck_gpu.cpp +++ b/src/GPU/pair_beck_gpu.cpp @@ -120,9 +120,9 @@ void PairBeckGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_start < inum) { - cpu_time = MPI_Wtime(); + cpu_time = platform::walltime(); cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } } diff --git a/src/GPU/pair_lj96_cut_gpu.cpp b/src/GPU/pair_lj96_cut_gpu.cpp index f03fbc9d7f..546c31a94e 100644 --- a/src/GPU/pair_lj96_cut_gpu.cpp +++ b/src/GPU/pair_lj96_cut_gpu.cpp @@ -117,9 +117,9 @@ void PairLJ96CutGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); // if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_start(host_start, inum, ilist, numneigh, firstneigh); else cpu_compute<1,0>(host_start, inum, ilist, numneigh, firstneigh); } else cpu_compute<0,0>(host_start, inum, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } } diff --git a/src/GPU/pair_lj_sdk_gpu.cpp b/src/GPU/pair_lj_sdk_gpu.cpp index 9f925d0250..938ee83e4a 100644 --- a/src/GPU/pair_lj_sdk_gpu.cpp +++ b/src/GPU/pair_lj_sdk_gpu.cpp @@ -122,12 +122,12 @@ void PairLJSDKGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_start(host_start, inum, ilist, numneigh, firstneigh); else cpu_compute<1,0>(host_start, inum, ilist, numneigh, firstneigh); } else cpu_compute<0,0>(host_start, inum, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } } diff --git a/src/GPU/pair_lj_sf_dipole_sf_gpu.cpp b/src/GPU/pair_lj_sf_dipole_sf_gpu.cpp index bd40f855dc..0bb0e66d92 100644 --- a/src/GPU/pair_lj_sf_dipole_sf_gpu.cpp +++ b/src/GPU/pair_lj_sf_dipole_sf_gpu.cpp @@ -127,9 +127,9 @@ void PairLJSFDipoleSFGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR, "Insufficient memory on accelerator"); if (host_start < inum) { - cpu_time = MPI_Wtime(); + cpu_time = platform::walltime(); cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } //fprintf("LJ_SMOOTH_GPU"); } diff --git a/src/GPU/pair_mie_cut_gpu.cpp b/src/GPU/pair_mie_cut_gpu.cpp index 568b4dbc18..a059607880 100644 --- a/src/GPU/pair_mie_cut_gpu.cpp +++ b/src/GPU/pair_mie_cut_gpu.cpp @@ -118,9 +118,9 @@ void PairMIECutGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_start < inum) { - cpu_time = MPI_Wtime(); + cpu_time = platform::walltime(); cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } } diff --git a/src/GPU/pair_soft_gpu.cpp b/src/GPU/pair_soft_gpu.cpp index 9b6fc6a39a..654e2e603b 100644 --- a/src/GPU/pair_soft_gpu.cpp +++ b/src/GPU/pair_soft_gpu.cpp @@ -121,9 +121,9 @@ void PairSoftGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_start -#include - -#include -#include -#include "ch5md.h" #include "dump_h5md.h" -#include "domain.h" + #include "atom.h" -#include "update.h" -#include "group.h" -#include "output.h" +#include "domain.h" #include "error.h" #include "force.h" +#include "group.h" #include "memory.h" +#include "output.h" +#include "update.h" #include "version.h" +#include "ch5md.h" + +#include +#include +#include + using namespace LAMMPS_NS; #define MYMIN(a,b) ((a) < (b) ? (a) : (b)) @@ -152,25 +153,14 @@ DumpH5MD::DumpH5MD(LAMMPS *lmp, int narg, char **arg) : Dump(lmp, narg, arg) error->all(FLERR, "Invalid number of arguments in dump h5md"); } box_is_set = true; - if (strcmp(arg[iarg+1], "yes")==0) - do_box=true; - else if (strcmp(arg[iarg+1], "no")==0) - do_box=false; - else - error->all(FLERR, "Illegal dump h5md command"); + do_box = utils::logical(FLERR,arg[iarg+1],false,lmp) == 1; iarg+=2; } else if (strcmp(arg[iarg], "create_group")==0) { if (iarg+1>=narg) { error->all(FLERR, "Invalid number of arguments in dump h5md"); } create_group_is_set = true; - if (strcmp(arg[iarg+1], "yes")==0) - create_group=true; - else if (strcmp(arg[iarg+1], "no")==0) { - create_group=false; - } - else - error->all(FLERR, "Illegal dump h5md command"); + create_group = utils::logical(FLERR,arg[iarg+1],false,lmp) == 1; iarg+=2; } else if (strcmp(arg[iarg], "author")==0) { if (iarg+1>=narg) { @@ -470,9 +460,7 @@ int DumpH5MD::modify_param(int narg, char **arg) { if (strcmp(arg[0],"unwrap") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[1],"yes") == 0) unwrap_flag = 1; - else if (strcmp(arg[1],"no") == 0) unwrap_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + unwrap_flag = utils::logical(FLERR, arg[1], false, lmp); return 2; } return 0; diff --git a/src/INTEL/fix_intel.cpp b/src/INTEL/fix_intel.cpp index d0633d7791..519181be52 100644 --- a/src/INTEL/fix_intel.cpp +++ b/src/INTEL/fix_intel.cpp @@ -118,9 +118,7 @@ FixIntel::FixIntel(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) iarg += 2; } else if (strcmp(arg[iarg], "ghost") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package intel command"); - if (strcmp(arg[iarg+1],"yes") == 0) _offload_ghost = 1; - else if (strcmp(arg[iarg+1],"no") == 0) _offload_ghost = 0; - else error->all(FLERR,"Illegal package intel command"); + _offload_ghost = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg], "tpc") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package intel command"); @@ -135,9 +133,7 @@ FixIntel::FixIntel(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) iarg++; } else if (strcmp(arg[iarg], "lrt") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package intel command"); - if (strcmp(arg[iarg+1],"yes") == 0) _lrt = 1; - else if (strcmp(arg[iarg+1],"no") == 0) _lrt = 0; - else error->all(FLERR,"Illegal package intel command"); + _lrt = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } @@ -915,7 +911,7 @@ template void FixIntel::add_off_results(const ft * _noalias const f_in, const acc_t * _noalias const ev_global) { if (_offload_balance < 0.0) - _balance_other_time = MPI_Wtime() - _balance_other_time; + _balance_other_time = platform::walltime() - _balance_other_time; start_watch(TIME_OFFLOAD_WAIT); #ifdef _LMP_INTEL_OFFLOAD diff --git a/src/INTERLAYER/pair_drip.cpp b/src/INTERLAYER/pair_drip.cpp index e9d32bdb8b..b9a4d1f05b 100644 --- a/src/INTERLAYER/pair_drip.cpp +++ b/src/INTERLAYER/pair_drip.cpp @@ -31,7 +31,6 @@ #include "neigh_request.h" #include "neighbor.h" #include "potential_file_reader.h" -#include "tokenizer.h" #include #include @@ -241,17 +240,17 @@ void PairDRIP::read_file(char *filename) nparams++; } - - MPI_Bcast(&nparams, 1, MPI_INT, 0, world); - MPI_Bcast(&maxparam, 1, MPI_INT, 0, world); - - if (comm->me != 0) { - params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params"); - } - - MPI_Bcast(params, maxparam * sizeof(Param), MPI_BYTE, 0, world); } + MPI_Bcast(&nparams, 1, MPI_INT, 0, world); + MPI_Bcast(&maxparam, 1, MPI_INT, 0, world); + + if (comm->me != 0) { + params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params"); + } + + MPI_Bcast(params, maxparam * sizeof(Param), MPI_BYTE, 0, world); + memory->destroy(elem2param); memory->create(elem2param, nelements, nelements, "pair:elem2param"); for (int i = 0; i < nelements; i++) { diff --git a/src/KIM/kim_init.cpp b/src/KIM/kim_init.cpp index ea3dc46da4..a4003b7510 100644 --- a/src/KIM/kim_init.cpp +++ b/src/KIM/kim_init.cpp @@ -1,4 +1,3 @@ -// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories @@ -85,21 +84,23 @@ void KimInit::command(int narg, char **arg) if ((narg < 2) || (narg > 3)) error->all(FLERR, "Illegal 'kim init' command"); if (domain->box_exist) - error->all(FLERR, "Must use 'kim init' command before " - "simulation box is defined"); + error->all(FLERR, "Must use 'kim init' command before simulation box is defined"); char *model_name = utils::strdup(arg[0]); char *user_units = utils::strdup(arg[1]); if (narg == 3) { auto arg_str = std::string(arg[2]); - if (arg_str == "unit_conversion_mode") unit_conversion_mode = true; + if (arg_str == "unit_conversion_mode") + unit_conversion_mode = true; else { - error->all(FLERR, "Illegal 'kim init' command.\nThe argument " - "followed by unit_style {} is an optional " - "argument and when is used must " - "be unit_conversion_mode", user_units); + error->all(FLERR, + "Illegal 'kim init' command.\n" + "The argument followed by unit_style {} is an optional argument and when " + "is used must be unit_conversion_mode", + user_units); } - } else unit_conversion_mode = false; + } else + unit_conversion_mode = false; char *model_units; KIM_Model *pkim = nullptr; @@ -117,14 +118,9 @@ void KimInit::command(int narg, char **arg) /* ---------------------------------------------------------------------- */ namespace { -void get_kim_unit_names( - char const * const system, - KIM_LengthUnit & lengthUnit, - KIM_EnergyUnit & energyUnit, - KIM_ChargeUnit & chargeUnit, - KIM_TemperatureUnit & temperatureUnit, - KIM_TimeUnit & timeUnit, - Error * error) +void get_kim_unit_names(char const *const system, KIM_LengthUnit &lengthUnit, + KIM_EnergyUnit &energyUnit, KIM_ChargeUnit &chargeUnit, + KIM_TemperatureUnit &temperatureUnit, KIM_TimeUnit &timeUnit, Error *error) { const std::string system_str(system); if (system_str == "real") { @@ -157,20 +153,64 @@ void get_kim_unit_names( chargeUnit = KIM_CHARGE_UNIT_e; temperatureUnit = KIM_TEMPERATURE_UNIT_K; timeUnit = KIM_TIME_UNIT_fs; - } else if ((system_str == "lj") || - (system_str == "micro") || - (system_str == "nano")) { - error->all(FLERR, "LAMMPS unit_style {} not supported " - "by KIM models", system_str); + } else if ((system_str == "lj") || (system_str == "micro") || (system_str == "nano")) { + error->all(FLERR, "LAMMPS unit_style {} not supported by KIM models", system_str); } else { error->all(FLERR, "Unknown unit_style"); } } -} // namespace +} // namespace -void KimInit::determine_model_type_and_units(char * model_name, - char * user_units, - char ** model_units, +void KimInit::print_dirs(struct KIM_Collections *const collections) const +{ + int kim_error = 0; + int dirListExtent = 0; + int dirCounter = 0; + + std::string mesg = "#=== KIM is looking for 'Portable Models' in these directories ===\n"; + std::vector collection_list; + collection_list.push_back(KIM_COLLECTION_currentWorkingDirectory); + collection_list.push_back(KIM_COLLECTION_environmentVariable); + collection_list.push_back(KIM_COLLECTION_user); + collection_list.push_back(KIM_COLLECTION_system); + + for (auto col : collection_list) { + kim_error = KIM_Collections_CacheListOfDirectoryNames( + collections, col, KIM_COLLECTION_ITEM_TYPE_portableModel, &dirListExtent); + if (!kim_error) { + for (int i = 0; i < dirListExtent; ++i) { + char const *name; + kim_error = KIM_Collections_GetDirectoryName(collections, i, &name); + // Don't check for error due to bug in kim-api-2.2.1 and below. +#if ((KIM_VERSION_MAJOR * 1000 + KIM_VERSION_MINOR) * 1000 + KIM_VERSION_PATCH) <= 2002001 + kim_error = 0; +#endif + if (!kim_error) mesg += fmt::format("# {:2}: {}\n", ++dirCounter, name); + } + } + } + + dirCounter = 0; + mesg += "#=== KIM is looking for 'Simulator Models' in these directories ===\n"; + for (auto col : collection_list) { + kim_error = KIM_Collections_CacheListOfDirectoryNames( + collections, col, KIM_COLLECTION_ITEM_TYPE_simulatorModel, &dirListExtent); + if (!kim_error) { + for (int i = 0; i < dirListExtent; ++i) { + char const *name; + kim_error = KIM_Collections_GetDirectoryName(collections, i, &name); + // Don't check for error due to bug in kim-api-2.2.1 and below. +#if ((KIM_VERSION_MAJOR * 1000 + KIM_VERSION_MINOR) * 1000 + KIM_VERSION_PATCH) <= 2002001 + kim_error = 0; +#endif + if (!kim_error) mesg += fmt::format("# {:2}: {}\n", ++dirCounter, name); + } + } + } + input->write_echo(mesg); +} + +void KimInit::determine_model_type_and_units(char *model_name, char *user_units, char **model_units, KIM_Model *&pkim) { KIM_LengthUnit lengthUnit; @@ -179,33 +219,26 @@ void KimInit::determine_model_type_and_units(char * model_name, KIM_TemperatureUnit temperatureUnit; KIM_TimeUnit timeUnit; int units_accepted; - KIM_Collections * collections; + KIM_Collections *collections; KIM_CollectionItemType itemType; int kim_error = KIM_Collections_Create(&collections); - if (kim_error) - error->all(FLERR, "Unable to access KIM Collections to find Model"); + if (kim_error) error->all(FLERR, "Unable to access KIM Collections to find Model"); auto logID = fmt::format("{}_Collections", comm->me); KIM_Collections_SetLogID(collections, logID.c_str()); + print_dirs(collections); + kim_error = KIM_Collections_GetItemType(collections, model_name, &itemType); if (kim_error) error->all(FLERR, "KIM Model name not found"); KIM_Collections_Destroy(&collections); - if (KIM_CollectionItemType_Equal(itemType, - KIM_COLLECTION_ITEM_TYPE_portableModel)) { - get_kim_unit_names(user_units, lengthUnit, energyUnit, - chargeUnit, temperatureUnit, timeUnit, error); - int kim_error = KIM_Model_Create(KIM_NUMBERING_zeroBased, - lengthUnit, - energyUnit, - chargeUnit, - temperatureUnit, - timeUnit, - model_name, - &units_accepted, - &pkim); + if (KIM_CollectionItemType_Equal(itemType, KIM_COLLECTION_ITEM_TYPE_portableModel)) { + get_kim_unit_names(user_units, lengthUnit, energyUnit, chargeUnit, temperatureUnit, timeUnit, + error); + int kim_error = KIM_Model_Create(KIM_NUMBERING_zeroBased, lengthUnit, energyUnit, chargeUnit, + temperatureUnit, timeUnit, model_name, &units_accepted, &pkim); if (kim_error) error->all(FLERR, "Unable to load KIM Simulator Model"); @@ -219,20 +252,12 @@ void KimInit::determine_model_type_and_units(char * model_name, } else if (unit_conversion_mode) { KIM_Model_Destroy(&pkim); int const num_systems = 5; - char const * const systems[num_systems] - = {"metal", "real", "si", "cgs", "electron"}; - for (int i=0; i < num_systems; ++i) { - get_kim_unit_names(systems[i], lengthUnit, energyUnit, - chargeUnit, temperatureUnit, timeUnit, error); - kim_error = KIM_Model_Create(KIM_NUMBERING_zeroBased, - lengthUnit, - energyUnit, - chargeUnit, - temperatureUnit, - timeUnit, - model_name, - &units_accepted, - &pkim); + char const *const systems[num_systems] = {"metal", "real", "si", "cgs", "electron"}; + for (int i = 0; i < num_systems; ++i) { + get_kim_unit_names(systems[i], lengthUnit, energyUnit, chargeUnit, temperatureUnit, + timeUnit, error); + kim_error = KIM_Model_Create(KIM_NUMBERING_zeroBased, lengthUnit, energyUnit, chargeUnit, + temperatureUnit, timeUnit, model_name, &units_accepted, &pkim); if (units_accepted) { logID = fmt::format("{}_Model", comm->me); KIM_Model_SetLogID(pkim, logID.c_str()); @@ -246,12 +271,10 @@ void KimInit::determine_model_type_and_units(char * model_name, KIM_Model_Destroy(&pkim); error->all(FLERR, "KIM Model does not support the requested unit system"); } - } else if (KIM_CollectionItemType_Equal( - itemType, KIM_COLLECTION_ITEM_TYPE_simulatorModel)) { - KIM_SimulatorModel * simulatorModel; + } else if (KIM_CollectionItemType_Equal(itemType, KIM_COLLECTION_ITEM_TYPE_simulatorModel)) { + KIM_SimulatorModel *simulatorModel; kim_error = KIM_SimulatorModel_Create(model_name, &simulatorModel); - if (kim_error) - error->all(FLERR, "Unable to load KIM Simulator Model"); + if (kim_error) error->all(FLERR, "Unable to load KIM Simulator Model"); model_type = SM; logID = fmt::format("{}_SimulatorModel", comm->me); @@ -264,13 +287,11 @@ void KimInit::determine_model_type_and_units(char * model_name, KIM_SimulatorModel_GetNumberOfSimulatorFields(simulatorModel, &sim_fields); KIM_SimulatorModel_CloseTemplateMap(simulatorModel); for (int i = 0; i < sim_fields; ++i) { - KIM_SimulatorModel_GetSimulatorFieldMetadata( - simulatorModel, i, &sim_lines, &sim_field); + KIM_SimulatorModel_GetSimulatorFieldMetadata(simulatorModel, i, &sim_lines, &sim_field); const std::string sim_field_str(sim_field); if (sim_field_str == "units") { - KIM_SimulatorModel_GetSimulatorFieldLine( - simulatorModel, i, 0, &sim_value); + KIM_SimulatorModel_GetSimulatorFieldLine(simulatorModel, i, 0, &sim_value); *model_units = utils::strdup(sim_value); break; } @@ -280,16 +301,15 @@ void KimInit::determine_model_type_and_units(char * model_name, const std::string model_units_str(*model_units); const std::string user_units_str(user_units); if ((!unit_conversion_mode) && (model_units_str != user_units_str)) { - error->all(FLERR, "Incompatible units for KIM Simulator Model" - ", required units = {}", model_units_str); + error->all(FLERR, "Incompatible units for KIM Simulator Model, required units = {}", + model_units_str); } } } /* ---------------------------------------------------------------------- */ -void KimInit::do_init(char *model_name, char *user_units, char *model_units, - KIM_Model *&pkim) +void KimInit::do_init(char *model_name, char *user_units, char *model_units, KIM_Model *&pkim) { // create storage proxy fix. delete existing fix, if needed. @@ -304,8 +324,7 @@ void KimInit::do_init(char *model_name, char *user_units, char *model_units, fix_store->setptr("model_units", (void *) model_units); // Begin output to log file - input->write_echo("#=== BEGIN kim init ===================================" - "=======\n"); + input->write_echo("#=== BEGIN kim init ==========================================\n"); KIM_SimulatorModel *simulatorModel; if (model_type == SM) { @@ -316,18 +335,16 @@ void KimInit::do_init(char *model_name, char *user_units, char *model_units, KIM_SimulatorModel_SetLogID(simulatorModel, logID.c_str()); char const *sim_name, *sim_version; - KIM_SimulatorModel_GetSimulatorNameAndVersion( - simulatorModel, &sim_name, &sim_version); + KIM_SimulatorModel_GetSimulatorNameAndVersion(simulatorModel, &sim_name, &sim_version); const std::string sim_name_str(sim_name); - if (sim_name_str != "LAMMPS") - error->all(FLERR, "Incompatible KIM Simulator Model"); + if (sim_name_str != "LAMMPS") error->all(FLERR, "Incompatible KIM Simulator Model"); if (comm->me == 0) { auto mesg = fmt::format("# Using KIM Simulator Model : {}\n" - "# For Simulator : {} {}\n" - "# Running on : LAMMPS {}\n#\n", model_name, - sim_name_str, sim_version, lmp->version); + "# For Simulator : {} {}\n" + "# Running on : LAMMPS {}\n#\n", + model_name, sim_name_str, sim_version, lmp->version); utils::logmesg(lmp, mesg); } @@ -350,18 +367,16 @@ void KimInit::do_init(char *model_name, char *user_units, char *model_units, // Set the skin and timestep default values as // 2.0 Angstroms and 1.0 femtosecond - const std::string skin_cmd = - (model_units_str == "real") ? "neighbor 2.0 bin # Angstroms": - (model_units_str == "metal") ? "neighbor 2.0 bin # Angstroms": - (model_units_str == "si") ? "neighbor 2e-10 bin # meters": - (model_units_str == "cgs") ? "neighbor 2e-8 bin # centimeters": - "neighbor 3.77945224 bin # Bohr"; - const std::string step_cmd = - (model_units_str == "real") ? "timestep 1.0 # femtoseconds": - (model_units_str == "metal") ? "timestep 1.0e-3 # picoseconds": - (model_units_str == "si") ? "timestep 1e-15 # seconds": - (model_units_str == "cgs") ? "timestep 1e-15 # seconds": - "timestep 1.0 # femtoseconds"; + const std::string skin_cmd = (model_units_str == "real") ? "neighbor 2.0 bin # Angstroms" + : (model_units_str == "metal") ? "neighbor 2.0 bin # Angstroms" + : (model_units_str == "si") ? "neighbor 2e-10 bin # meters" + : (model_units_str == "cgs") ? "neighbor 2e-8 bin # centimeters" + : "neighbor 3.77945224 bin # Bohr"; + const std::string step_cmd = (model_units_str == "real") ? "timestep 1.0 # femtoseconds" + : (model_units_str == "metal") ? "timestep 1.0e-3 # picoseconds" + : (model_units_str == "si") ? "timestep 1e-15 # seconds" + : (model_units_str == "cgs") ? "timestep 1e-15 # seconds" + : "timestep 1.0 # femtoseconds"; input->one(skin_cmd); input->one(step_cmd); @@ -373,14 +388,12 @@ void KimInit::do_init(char *model_name, char *user_units, char *model_units, // init model for (int i = 0; i < sim_fields; ++i) { - KIM_SimulatorModel_GetSimulatorFieldMetadata( - simulatorModel, i, &sim_lines, &sim_field); + KIM_SimulatorModel_GetSimulatorFieldMetadata(simulatorModel, i, &sim_lines, &sim_field); const std::string sim_field_str(sim_field); if (sim_field_str == "model-init") { for (int j = 0; j < sim_lines; ++j) { - KIM_SimulatorModel_GetSimulatorFieldLine( - simulatorModel, i, j, &sim_value); + KIM_SimulatorModel_GetSimulatorFieldLine(simulatorModel, i, j, &sim_value); input->one(sim_value); } break; @@ -404,31 +417,28 @@ void KimInit::do_init(char *model_name, char *user_units, char *model_units, int max_len(0); for (int i = 0; i < numberOfParameters; ++i) { - KIM_Model_GetParameterMetadata(pkim, i, &kim_DataType, - &extent, &str_name, &str_desc); - max_len = MAX(max_len, (int)strlen(str_name)); + KIM_Model_GetParameterMetadata(pkim, i, &kim_DataType, &extent, &str_name, &str_desc); + max_len = MAX(max_len, (int) strlen(str_name)); } max_len = MAX(18, max_len + 1); - mesg += fmt::format(" No. | {:<{}} | data type | extent\n", - "Parameter name", max_len); + mesg += fmt::format(" No. | {:<{}} | data type | extent\n", "Parameter name", max_len); mesg += fmt::format("{:-<{}}\n", "-", max_len + 35); for (int i = 0; i < numberOfParameters; ++i) { - KIM_Model_GetParameterMetadata(pkim, i, &kim_DataType, - &extent, &str_name, &str_desc); + KIM_Model_GetParameterMetadata(pkim, i, &kim_DataType, &extent, &str_name, &str_desc); auto data_type = std::string("\""); data_type += KIM_DataType_ToString(kim_DataType) + std::string("\""); - mesg += fmt::format(" {:<8} | {:<{}} | {:<10} | {}\n", i + 1, str_name, - max_len, data_type, extent); + mesg += fmt::format(" {:<8} | {:<{}} | {:<10} | {}\n", i + 1, str_name, max_len, data_type, + extent); } - } else mesg += "No mutable parameters.\n"; + } else + mesg += "No mutable parameters.\n"; KIM_Model_Destroy(&pkim); input->write_echo(mesg); } // End output to log file - input->write_echo("#=== END kim init =====================================" - "=======\n\n"); + input->write_echo("#=== END kim init ============================================\n\n"); } /* ---------------------------------------------------------------------- */ @@ -446,24 +456,11 @@ void KimInit::do_variables(const std::string &from, const std::string &to) int ier; std::string var_str; int v_unit; - const char *units[] = {"mass", - "distance", - "time", - "energy", - "velocity", - "force", - "torque", - "temperature", - "pressure", - "viscosity", - "charge", - "dipole", - "efield", - "density", - nullptr}; + const char *units[] = {"mass", "distance", "time", "energy", "velocity", + "force", "torque", "temperature", "pressure", "viscosity", + "charge", "dipole", "efield", "density", nullptr}; - input->write_echo(fmt::format("# Conversion factors from {} to {}:\n", - from, to)); + input->write_echo(fmt::format("# Conversion factors from {} to {}:\n", from, to)); auto variable = input->variable; for (int i = 0; units[i] != nullptr; ++i) { @@ -473,24 +470,23 @@ void KimInit::do_variables(const std::string &from, const std::string &to) variable->set(var_str + " internal 1.0"); v_unit = variable->find(var_str.c_str()); } - ier = lammps_unit_conversion(units[i], from, to, - conversion_factor); + ier = lammps_unit_conversion(units[i], from, to, conversion_factor); if (ier != 0) - error->all(FLERR, "Unable to obtain conversion factor: " - "unit = {}; from = {}; to = {}", - units[i], from, to); + error->all(FLERR, + "Unable to obtain conversion factor: " + "unit = {}; from = {}; to = {}", + units[i], from, to); variable->internal_set(v_unit, conversion_factor); - input->write_echo(fmt::format("variable {:<15s} internal {:<15.12e}\n", - var_str, conversion_factor)); + input->write_echo( + fmt::format("variable {:<15s} internal {:<15.12e}\n", var_str, conversion_factor)); } input->write_echo("#\n"); } /* ---------------------------------------------------------------------- */ -void KimInit::write_log_cite(class LAMMPS *lmp, - KimInit::model_type_enum model_type, +void KimInit::write_log_cite(class LAMMPS *lmp, KimInit::model_type_enum model_type, char *model_name) { if (!lmp->citeme) return; @@ -501,7 +497,7 @@ void KimInit::write_log_cite(class LAMMPS *lmp, std::string cite_id; if (kim_id.empty()) { - cite_id = fmt::format("KIM potential: unpublished, \"{}\"\n",model_name_str); + cite_id = fmt::format("KIM potential: unpublished, \"{}\"\n", model_name_str); } else { KIM_Collections *collections; int err = KIM_Collections_Create(&collections); @@ -513,12 +509,10 @@ void KimInit::write_log_cite(class LAMMPS *lmp, int extent; if (model_type == MO) { err = KIM_Collections_CacheListOfItemMetadataFiles( - collections, KIM_COLLECTION_ITEM_TYPE_portableModel, - model_name, &extent); + collections, KIM_COLLECTION_ITEM_TYPE_portableModel, model_name, &extent); } else if (model_type == SM) { err = KIM_Collections_CacheListOfItemMetadataFiles( - collections, KIM_COLLECTION_ITEM_TYPE_simulatorModel, - model_name, &extent); + collections, KIM_COLLECTION_ITEM_TYPE_simulatorModel, model_name, &extent); } else { lmp->error->all(FLERR, "Unknown model type"); } @@ -529,19 +523,18 @@ void KimInit::write_log_cite(class LAMMPS *lmp, } cite_id = fmt::format("OpenKIM potential: https://openkim.org/cite/" - "{}#item-citation\n\n",kim_id); + "{}#item-citation\n\n", + kim_id); for (int i = 0; i < extent; ++i) { char const *fileName; int availableAsString; char const *fileString; - err = KIM_Collections_GetItemMetadataFile( - collections, i, &fileName, nullptr, nullptr, - &availableAsString, &fileString); + err = KIM_Collections_GetItemMetadataFile(collections, i, &fileName, nullptr, nullptr, + &availableAsString, &fileString); if (err) continue; - if (utils::strmatch(fileName, "^kimcite") && availableAsString) - cite_id += fileString; + if (utils::strmatch(fileName, "^kimcite") && availableAsString) cite_id += fileString; } KIM_Collections_Destroy(&collections); } diff --git a/src/KIM/kim_init.h b/src/KIM/kim_init.h index fa042f2723..56922533ab 100644 --- a/src/KIM/kim_init.h +++ b/src/KIM/kim_init.h @@ -62,7 +62,8 @@ #include "pointers.h" // Forward declaration. -typedef struct KIM_Model KIM_Model; +struct KIM_Model; +struct KIM_Collections; namespace LAMMPS_NS { @@ -80,6 +81,8 @@ class KimInit : protected Pointers { void determine_model_type_and_units(char *, char *, char **, KIM_Model *&); void do_init(char *, char *, char *, KIM_Model *&); void do_variables(const std::string &, const std::string &); + + void print_dirs(struct KIM_Collections * const collections) const; }; } // namespace LAMMPS_NS diff --git a/src/KIM/kim_query.cpp b/src/KIM/kim_query.cpp index c1669650cc..3e891468a6 100644 --- a/src/KIM/kim_query.cpp +++ b/src/KIM/kim_query.cpp @@ -377,7 +377,7 @@ char *do_query(const std::string &qfunction, const std::string &mname, } auto user_agent = fmt::format("kim query--LAMMPS/{} ({})", - LAMMPS_VERSION, Info::get_os_info()); + LAMMPS_VERSION, platform::os_info()); curl_easy_setopt(handle, CURLOPT_USERAGENT, user_agent.c_str()); curl_easy_setopt(handle, CURLOPT_URL, url.c_str()); diff --git a/src/KOKKOS/bond_class2_kokkos.cpp b/src/KOKKOS/bond_class2_kokkos.cpp index e538c8e045..b4e87b4119 100644 --- a/src/KOKKOS/bond_class2_kokkos.cpp +++ b/src/KOKKOS/bond_class2_kokkos.cpp @@ -68,14 +68,14 @@ void BondClass2Kokkos::compute(int eflag_in, int vflag_in) //if(k_eatom.extent(0)destroy_kokkos(k_eatom,eatom); memoryKK->create_kokkos(k_eatom,eatom,maxeatom,"improper:eatom"); - d_eatom = k_eatom.template view(); + d_eatom = k_eatom.template view(); //} } if (vflag_atom) { //if(k_vatom.extent(0)destroy_kokkos(k_vatom,vatom); memoryKK->create_kokkos(k_vatom,vatom,maxvatom,"improper:vatom"); - d_vatom = k_vatom.template view(); + d_vatom = k_vatom.template view(); //} } @@ -210,10 +210,10 @@ void BondClass2Kokkos::coeff(int narg, char **arg) BondClass2::coeff(narg, arg); int n = atom->nbondtypes; - Kokkos::DualView k_k2("BondClass2::k2",n+1); - Kokkos::DualView k_k3("BondClass2::k3",n+1); - Kokkos::DualView k_k4("BondClass2::k4",n+1); - Kokkos::DualView k_r0("BondClass2::r0",n+1); + typename AT::tdual_ffloat_1d k_k2("BondClass2::k2",n+1); + typename AT::tdual_ffloat_1d k_k3("BondClass2::k3",n+1); + typename AT::tdual_ffloat_1d k_k4("BondClass2::k4",n+1); + typename AT::tdual_ffloat_1d k_r0("BondClass2::r0",n+1); d_k2 = k_k2.template view(); d_k3 = k_k3.template view(); @@ -247,10 +247,10 @@ void BondClass2Kokkos::read_restart(FILE *fp) BondClass2::read_restart(fp); int n = atom->nbondtypes; - Kokkos::DualView k_k2("BondClass2::k2",n+1); - Kokkos::DualView k_k3("BondClass2::k3",n+1); - Kokkos::DualView k_k4("BondClass2::k4",n+1); - Kokkos::DualView k_r0("BondClass2::r0",n+1); + typename AT::tdual_ffloat_1d k_k2("BondClass2::k2",n+1); + typename AT::tdual_ffloat_1d k_k3("BondClass2::k3",n+1); + typename AT::tdual_ffloat_1d k_k4("BondClass2::k4",n+1); + typename AT::tdual_ffloat_1d k_r0("BondClass2::r0",n+1); d_k2 = k_k2.template view(); d_k3 = k_k3.template view(); diff --git a/src/KOKKOS/bond_class2_kokkos.h b/src/KOKKOS/bond_class2_kokkos.h index 52136030aa..529046845f 100644 --- a/src/KOKKOS/bond_class2_kokkos.h +++ b/src/KOKKOS/bond_class2_kokkos.h @@ -67,10 +67,11 @@ class BondClass2Kokkos : public BondClass2 { typename Kokkos::View::value,Kokkos::MemoryTraits > f; typename AT::t_int_2d bondlist; - Kokkos::DualView k_eatom; - Kokkos::DualView k_vatom; - Kokkos::View::value,Kokkos::MemoryTraits > d_eatom; - Kokkos::View::value,Kokkos::MemoryTraits > d_vatom; + typedef typename KKDevice::value KKDeviceType; + Kokkos::DualView k_eatom; + Kokkos::DualView k_vatom; + Kokkos::View > d_eatom; + Kokkos::View > d_vatom; int nlocal,newton_bond; int eflag,vflag; diff --git a/src/KOKKOS/compute_coord_atom_kokkos.cpp b/src/KOKKOS/compute_coord_atom_kokkos.cpp index b71cd1ec4a..9f0e7fc435 100644 --- a/src/KOKKOS/compute_coord_atom_kokkos.cpp +++ b/src/KOKKOS/compute_coord_atom_kokkos.cpp @@ -59,7 +59,7 @@ ComputeCoordAtomKokkos::ComputeCoordAtomKokkos(LAMMPS *lmp, int narg /* ---------------------------------------------------------------------- */ template -ComputeCoordAtomKokkos::~ComputeCoordAtomKokkos() +ComputeCoordAtomKokkos::~ComputeCoordAtomKokkos() { if (copymode) return; diff --git a/src/KOKKOS/compute_orientorder_atom_kokkos.cpp b/src/KOKKOS/compute_orientorder_atom_kokkos.cpp index 131e9933e8..f7ec879e3c 100644 --- a/src/KOKKOS/compute_orientorder_atom_kokkos.cpp +++ b/src/KOKKOS/compute_orientorder_atom_kokkos.cpp @@ -173,8 +173,6 @@ void ComputeOrientOrderAtomKokkos::compute_peratom() x = atomKK->k_x.view(); mask = atomKK->k_mask.view(); - Kokkos::deep_copy(d_qnm,{0.0,0.0}); - int vector_length_default = 1; int team_size_default = 1; if (!host_flag) @@ -185,6 +183,8 @@ void ComputeOrientOrderAtomKokkos::compute_peratom() if (chunk_size > inum - chunk_offset) chunk_size = inum - chunk_offset; + Kokkos::deep_copy(d_qnm,{0.0,0.0}); + //Neigh { int vector_length = vector_length_default; @@ -286,7 +286,7 @@ void ComputeOrientOrderAtomKokkos::operator() (TagComputeOrientOrder const int i = d_ilist[ii + chunk_offset]; const int ncount = d_ncount(ii); - // if not nnn neighbors, order parameter = 0; + // if not nnn neighbors, order parameter = 0 if ((ncount == 0) || (ncount < nnn)) { for (int jj = 0; jj < ncol; jj++) @@ -316,7 +316,7 @@ void ComputeOrientOrderAtomKokkos::operator() (TagComputeOrientOrder const int ncount = d_ncount(ii); if (jj >= ncount) return; - // if not nnn neighbors, order parameter = 0; + // if not nnn neighbors, order parameter = 0 if ((ncount == 0) || (ncount < nnn)) return; @@ -328,6 +328,12 @@ template KOKKOS_INLINE_FUNCTION void ComputeOrientOrderAtomKokkos::operator() (TagComputeOrientOrderAtomBOOP2,const int& ii) const { const int ncount = d_ncount(ii); + + // if not nnn neighbors, order parameter = 0 + + if ((ncount == 0) || (ncount < nnn)) + return; + calc_boop2(ncount, ii); } diff --git a/src/KOKKOS/fix_rx_kokkos.cpp b/src/KOKKOS/fix_rx_kokkos.cpp index 15b4a39849..caa79c77b1 100644 --- a/src/KOKKOS/fix_rx_kokkos.cpp +++ b/src/KOKKOS/fix_rx_kokkos.cpp @@ -54,7 +54,7 @@ namespace /* anonymous */ { typedef double TimerType; -TimerType getTimeStamp(void) { return MPI_Wtime(); } +TimerType getTimeStamp(void) { return platform::walltime(); } double getElapsedTime( const TimerType &t0, const TimerType &t1) { return t1-t0; } } // end namespace @@ -2075,7 +2075,7 @@ void FixRxKokkos::computeLocalTemperature() // Local list views. (This isn't working!) NeighListKokkos* k_list = static_cast*>(list); - if (not(list->kokkos)) + if (!list->kokkos) error->one(FLERR,"list is not a Kokkos list\n"); //typename ArrayTypes::t_neighbors_2d d_neighbors = k_list->d_neighbors; diff --git a/src/KOKKOS/fix_rx_kokkos.h b/src/KOKKOS/fix_rx_kokkos.h index a782958045..61e4a05946 100644 --- a/src/KOKKOS/fix_rx_kokkos.h +++ b/src/KOKKOS/fix_rx_kokkos.h @@ -196,7 +196,7 @@ class FixRxKokkos : public FixRX { double& h0, VectorType& y, VectorType& rwk, UserDataType& userData) const; //!< ODE Solver diagnostics. - void odeDiagnostics(void); + void odeDiagnostics(); //!< Special counters per-ode. int *diagnosticCounterPerODEnSteps; @@ -231,7 +231,7 @@ class FixRxKokkos : public FixRX { bool update_kinetics_data; - void create_kinetics_data(void); + void create_kinetics_data(); // Need a dual-view and device-view for dpdThetaLocal and sumWeights since they're used in several callbacks. DAT::tdual_efloat_1d k_dpdThetaLocal, k_sumWeights; diff --git a/src/KOKKOS/kokkos.cpp b/src/KOKKOS/kokkos.cpp index aa435d5b0b..63a18ec387 100644 --- a/src/KOKKOS/kokkos.cpp +++ b/src/KOKKOS/kokkos.cpp @@ -23,7 +23,15 @@ #include #include #include -#include + +#if defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include // for _getpid() +#else +#include // for getpid() +#endif #ifdef LMP_KOKKOS_GPU @@ -381,9 +389,7 @@ void KokkosLMP::accelerator(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"newton") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package kokkos command"); - if (strcmp(arg[iarg+1],"off") == 0) newtonflag = 0; - else if (strcmp(arg[iarg+1],"on") == 0) newtonflag = 1; - else error->all(FLERR,"Illegal package kokkos command"); + newtonflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"comm") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package kokkos command"); @@ -459,21 +465,15 @@ void KokkosLMP::accelerator(int narg, char **arg) } else if ((strcmp(arg[iarg],"gpu/aware") == 0) || (strcmp(arg[iarg],"cuda/aware") == 0)) { if (iarg+2 > narg) error->all(FLERR,"Illegal package kokkos command"); - if (strcmp(arg[iarg+1],"off") == 0) gpu_aware_flag = 0; - else if (strcmp(arg[iarg+1],"on") == 0) gpu_aware_flag = 1; - else error->all(FLERR,"Illegal package kokkos command"); + gpu_aware_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"pair/only") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package kokkos command"); - if (strcmp(arg[iarg+1],"off") == 0) pair_only_flag = 0; - else if (strcmp(arg[iarg+1],"on") == 0) pair_only_flag = 1; - else error->all(FLERR,"Illegal package kokkos command"); + pair_only_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"neigh/thread") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package kokkos command"); - if (strcmp(arg[iarg+1],"off") == 0) neigh_thread = 0; - else if (strcmp(arg[iarg+1],"on") == 0) neigh_thread = 1; - else error->all(FLERR,"Illegal package kokkos command"); + neigh_thread = utils::logical(FLERR,arg[iarg+1],false,lmp); neigh_thread_set = 1; iarg += 2; } else error->all(FLERR,"Illegal package kokkos command"); @@ -599,6 +599,10 @@ int KokkosLMP::neigh_count(int m) void KokkosLMP::my_signal_handler(int sig) { if (sig == SIGSEGV) { +#if defined(_WIN32) + kill(_getpid(),SIGABRT); +#else kill(getpid(),SIGABRT); +#endif } } diff --git a/src/KOKKOS/kokkos_type.h b/src/KOKKOS/kokkos_type.h index 05c839db3f..cd829ec3e4 100644 --- a/src/KOKKOS/kokkos_type.h +++ b/src/KOKKOS/kokkos_type.h @@ -25,7 +25,9 @@ #include #include -enum{FULL=1u,HALFTHREAD=2u,HALF=4u}; +constexpr int FULL = 1; +constexpr int HALFTHREAD = 2; +constexpr int HALF = 4; #if defined(KOKKOS_ENABLE_CXX11) #undef ISFINITE diff --git a/src/KOKKOS/modify_kokkos.cpp b/src/KOKKOS/modify_kokkos.cpp index 868de3e11e..5545351f53 100644 --- a/src/KOKKOS/modify_kokkos.cpp +++ b/src/KOKKOS/modify_kokkos.cpp @@ -38,7 +38,20 @@ ModifyKokkos::ModifyKokkos(LAMMPS *lmp) : Modify(lmp) void ModifyKokkos::setup(int vflag) { // compute setup needs to come before fix setup - // b/c NH fixes need use DOF of temperature computes + // b/c NH fixes need DOF of temperature computes + // fix group setup() is special case since populates a dynamic group + // needs to be done before temperature compute setup + + for (int i = 0; i < nfix; i++) { + if (strcmp(fix[i]->style,"GROUP") == 0) { + atomKK->sync(fix[i]->execution_space,fix[i]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[i]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[i]->setup(vflag); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[i]->execution_space,fix[i]->datamask_modify); + } + } for (int i = 0; i < ncompute; i++) compute[i]->setup(); @@ -124,6 +137,37 @@ void ModifyKokkos::setup_pre_neighbor() } } +/* ---------------------------------------------------------------------- + setup post_neighbor call, only for fixes that define post_neighbor + called from Verlet, RESPA +------------------------------------------------------------------------- */ + +void ModifyKokkos::setup_post_neighbor() +{ + if (update->whichflag == 1) + for (int i = 0; i < n_post_neighbor; i++) { + atomKK->sync(fix[list_post_neighbor[i]]->execution_space, + fix[list_post_neighbor[i]]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[list_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_post_neighbor[i]]->setup_post_neighbor(); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[list_post_neighbor[i]]->execution_space, + fix[list_post_neighbor[i]]->datamask_modify); + } + else if (update->whichflag == 2) + for (int i = 0; i < n_min_post_neighbor; i++) { + atomKK->sync(fix[list_min_post_neighbor[i]]->execution_space, + fix[list_min_post_neighbor[i]]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[list_min_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_min_post_neighbor[i]]->setup_post_neighbor(); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[list_min_post_neighbor[i]]->execution_space, + fix[list_min_post_neighbor[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- setup pre_force call, only for fixes that define pre_force called from Verlet, RESPA, Min @@ -258,6 +302,24 @@ void ModifyKokkos::pre_neighbor() } } +/* ---------------------------------------------------------------------- + post_neighbor call, only for relevant fixes +------------------------------------------------------------------------- */ + +void ModifyKokkos::post_neighbor() +{ + for (int i = 0; i < n_post_neighbor; i++) { + atomKK->sync(fix[list_post_neighbor[i]]->execution_space, + fix[list_post_neighbor[i]]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[list_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_post_neighbor[i]]->post_neighbor(); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[list_post_neighbor[i]]->execution_space, + fix[list_post_neighbor[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- pre_force call, only for relevant fixes ------------------------------------------------------------------------- */ @@ -420,6 +482,12 @@ void ModifyKokkos::post_run() atomKK->modified(fix[i]->execution_space, fix[i]->datamask_modify); } + + // must reset this to its default value, since computes may be added + // or removed between runs and with this change we will redirect any + // calls to addstep_compute() to addstep_compute_all() instead. + n_timeflag = -1; + } /* ---------------------------------------------------------------------- @@ -567,6 +635,24 @@ void ModifyKokkos::min_pre_neighbor() } } +/* ---------------------------------------------------------------------- + minimizer post-neighbor call, only for relevant fixes +------------------------------------------------------------------------- */ + +void ModifyKokkos::min_post_neighbor() +{ + for (int i = 0; i < n_min_post_neighbor; i++) { + atomKK->sync(fix[list_min_post_neighbor[i]]->execution_space, + fix[list_min_post_neighbor[i]]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[list_min_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_min_post_neighbor[i]]->min_post_neighbor(); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[list_min_post_neighbor[i]]->execution_space, + fix[list_min_post_neighbor[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- minimizer pre-force call, only for relevant fixes ------------------------------------------------------------------------- */ @@ -646,7 +732,7 @@ double ModifyKokkos::min_energy(double *fextra) } /* ---------------------------------------------------------------------- - store current state of extra dof, only for relevant fixes + store current state of extra minimizer dof, only for relevant fixes ------------------------------------------------------------------------- */ void ModifyKokkos::min_store() @@ -664,7 +750,7 @@ void ModifyKokkos::min_store() } /* ---------------------------------------------------------------------- - mange state of extra dof on a stack, only for relevant fixes + manage state of extra minimizer dof on a stack, only for relevant fixes ------------------------------------------------------------------------- */ void ModifyKokkos::min_clearstore() @@ -710,7 +796,7 @@ void ModifyKokkos::min_popstore() } /* ---------------------------------------------------------------------- - displace extra dof along vector hextra, only for relevant fixes + displace extra minimizer dof along vector hextra, only for relevant fixes ------------------------------------------------------------------------- */ void ModifyKokkos::min_step(double alpha, double *hextra) @@ -755,7 +841,7 @@ double ModifyKokkos::max_alpha(double *hextra) } /* ---------------------------------------------------------------------- - extract extra dof for minimization, only for relevant fixes + extract extra minimizer dof, only for relevant fixes ------------------------------------------------------------------------- */ int ModifyKokkos::min_dof() @@ -775,7 +861,7 @@ int ModifyKokkos::min_dof() } /* ---------------------------------------------------------------------- - reset reference state of fix, only for relevant fixes + reset minimizer reference state of fix, only for relevant fixes ------------------------------------------------------------------------- */ int ModifyKokkos::min_reset_ref() @@ -788,8 +874,8 @@ int ModifyKokkos::min_reset_ref() int prev_auto_sync = lmp->kokkos->auto_sync; if (!fix[list_min_energy[i]]->kokkosable) lmp->kokkos->auto_sync = 1; itmp = fix[list_min_energy[i]]->min_reset_ref(); - lmp->kokkos->auto_sync = prev_auto_sync; if (itmp) itmpall = 1; + lmp->kokkos->auto_sync = prev_auto_sync; atomKK->modified(fix[list_min_energy[i]]->execution_space, fix[list_min_energy[i]]->datamask_modify); } diff --git a/src/KOKKOS/modify_kokkos.h b/src/KOKKOS/modify_kokkos.h index 9b75b7c607..25911743b2 100644 --- a/src/KOKKOS/modify_kokkos.h +++ b/src/KOKKOS/modify_kokkos.h @@ -26,6 +26,7 @@ class ModifyKokkos : public Modify { void setup(int); void setup_pre_exchange(); void setup_pre_neighbor(); + void setup_post_neighbor(); void setup_pre_force(int); void setup_pre_reverse(int, int); void initial_integrate(int); @@ -33,6 +34,7 @@ class ModifyKokkos : public Modify { void pre_decide(); void pre_exchange(); void pre_neighbor(); + void post_neighbor(); void pre_force(int); void pre_reverse(int,int); void post_force(int); @@ -52,6 +54,7 @@ class ModifyKokkos : public Modify { void min_pre_exchange(); void min_pre_neighbor(); + void min_post_neighbor(); void min_pre_force(int); void min_pre_reverse(int,int); void min_post_force(int); diff --git a/src/KOKKOS/pair_eam_alloy_kokkos.cpp b/src/KOKKOS/pair_eam_alloy_kokkos.cpp index a8e65c4a92..9421946c3e 100644 --- a/src/KOKKOS/pair_eam_alloy_kokkos.cpp +++ b/src/KOKKOS/pair_eam_alloy_kokkos.cpp @@ -17,23 +17,23 @@ ------------------------------------------------------------------------- */ #include "pair_eam_alloy_kokkos.h" -#include -#include -#include "kokkos.h" -#include "pair_kokkos.h" + #include "atom_kokkos.h" -#include "force.h" +#include "atom_masks.h" #include "comm.h" -#include "neighbor.h" +#include "error.h" +#include "force.h" +#include "kokkos.h" +#include "memory_kokkos.h" #include "neigh_list_kokkos.h" #include "neigh_request.h" -#include "memory_kokkos.h" -#include "error.h" -#include "atom_masks.h" - -#include "tokenizer.h" +#include "neighbor.h" +#include "pair_kokkos.h" #include "potential_file_reader.h" +#include +#include + using namespace LAMMPS_NS; // Cannot use virtual inheritance on the GPU, so must duplicate code @@ -44,8 +44,8 @@ template PairEAMAlloyKokkos::PairEAMAlloyKokkos(LAMMPS *lmp) : PairEAM(lmp) { respa_enable = 0; + single_enable = 0; one_coeff = 1; - manybody_flag = 1; kokkosable = 1; atomKK = (AtomKokkos *) atom; @@ -261,6 +261,8 @@ void PairEAMAlloyKokkos::compute(int eflag_in, int vflag_in) virial[5] += ev.v[5]; } + if (vflag_fdotr) pair_virial_fdotr_compute(this); + if (eflag_atom) { if (need_dup) Kokkos::Experimental::contribute(d_eatom, dup_eatom); @@ -275,8 +277,6 @@ void PairEAMAlloyKokkos::compute(int eflag_in, int vflag_in) k_vatom.template sync(); } - if (vflag_fdotr) pair_virial_fdotr_compute(this); - copymode = 0; // free duplicated memory @@ -322,6 +322,11 @@ void PairEAMAlloyKokkos::init_style() } +/* ---------------------------------------------------------------------- + convert read-in funcfl potential(s) to standard array format + interpolate all file values to a single grid and cutoff +------------------------------------------------------------------------- */ + template void PairEAMAlloyKokkos::file2array() { @@ -524,7 +529,7 @@ void PairEAMAlloyKokkos::unpack_reverse_comm(int n, int *list, doubl h_rho[j] += buf[m++]; } - k_fp.modify_host(); + k_rho.modify_host(); } /* ---------------------------------------------------------------------- */ @@ -581,8 +586,8 @@ void PairEAMAlloyKokkos::operator()(TagPairEAMAlloyKernelA template KOKKOS_INLINE_FUNCTION void PairEAMAlloyKokkos::operator()(TagPairEAMAlloyKernelB, const int &ii, EV_FLOAT& ev) const { - // fp = derivative of embedding energy at each atom // phi = embedding energy at each atom // if rho > rhomax (e.g. due to close approach of two atoms), @@ -620,7 +624,6 @@ void PairEAMAlloyKokkos::operator()(TagPairEAMAlloyKernelB, c if (eflag_global) ev.evdwl += phi; if (eflag_atom) d_eatom[i] += phi; } - } template diff --git a/src/KOKKOS/pair_eam_fs_kokkos.cpp b/src/KOKKOS/pair_eam_fs_kokkos.cpp index b12de79b37..5fbd14d8b3 100644 --- a/src/KOKKOS/pair_eam_fs_kokkos.cpp +++ b/src/KOKKOS/pair_eam_fs_kokkos.cpp @@ -17,23 +17,23 @@ ------------------------------------------------------------------------- */ #include "pair_eam_fs_kokkos.h" -#include -#include -#include "kokkos.h" -#include "pair_kokkos.h" + #include "atom_kokkos.h" -#include "force.h" +#include "atom_masks.h" #include "comm.h" -#include "neighbor.h" +#include "error.h" +#include "force.h" +#include "kokkos.h" +#include "memory_kokkos.h" #include "neigh_list_kokkos.h" #include "neigh_request.h" -#include "memory_kokkos.h" -#include "error.h" -#include "atom_masks.h" - -#include "tokenizer.h" +#include "neighbor.h" +#include "pair_kokkos.h" #include "potential_file_reader.h" +#include +#include + using namespace LAMMPS_NS; // Cannot use virtual inheritance on the GPU, so must duplicate code @@ -43,9 +43,9 @@ using namespace LAMMPS_NS; template PairEAMFSKokkos::PairEAMFSKokkos(LAMMPS *lmp) : PairEAM(lmp) { - one_coeff = 1; - manybody_flag = 1; respa_enable = 0; + single_enable = 0; + one_coeff = 1; kokkosable = 1; atomKK = (AtomKokkos *) atom; @@ -200,9 +200,9 @@ void PairEAMFSKokkos::compute(int eflag_in, int vflag_in) // communicate derivative of embedding function (on the device) - k_fp.template sync(); - comm->forward_comm_pair(this); k_fp.template modify(); + comm->forward_comm_pair(this); + k_fp.template sync(); // compute kernel C @@ -322,6 +322,11 @@ void PairEAMFSKokkos::init_style() } +/* ---------------------------------------------------------------------- + convert read-in funcfl potential(s) to standard array format + interpolate all file values to a single grid and cutoff +------------------------------------------------------------------------- */ + template void PairEAMFSKokkos::file2array() { @@ -581,8 +586,8 @@ void PairEAMFSKokkos::operator()(TagPairEAMFSKernelA::operator()(TagPairEAMFSKernelB, const i if (eflag_global) ev.evdwl += phi; if (eflag_atom) d_eatom[i] += phi; } - } template diff --git a/src/KOKKOS/pair_eam_kokkos.cpp b/src/KOKKOS/pair_eam_kokkos.cpp index c9d2808075..417efc3f7d 100644 --- a/src/KOKKOS/pair_eam_kokkos.cpp +++ b/src/KOKKOS/pair_eam_kokkos.cpp @@ -17,18 +17,20 @@ ------------------------------------------------------------------------- */ #include "pair_eam_kokkos.h" -#include -#include "kokkos.h" -#include "pair_kokkos.h" + #include "atom_kokkos.h" -#include "force.h" +#include "atom_masks.h" #include "comm.h" -#include "neighbor.h" +#include "error.h" +#include "force.h" +#include "kokkos.h" +#include "memory_kokkos.h" #include "neigh_list_kokkos.h" #include "neigh_request.h" -#include "memory_kokkos.h" -#include "error.h" -#include "atom_masks.h" +#include "neighbor.h" +#include "pair_kokkos.h" + +#include using namespace LAMMPS_NS; diff --git a/src/KOKKOS/pair_exp6_rx_kokkos.cpp b/src/KOKKOS/pair_exp6_rx_kokkos.cpp index 4da3a43243..0988cb4910 100644 --- a/src/KOKKOS/pair_exp6_rx_kokkos.cpp +++ b/src/KOKKOS/pair_exp6_rx_kokkos.cpp @@ -61,7 +61,7 @@ namespace /* anonymous */ { //typedef double TimerType; -//TimerType getTimeStamp(void) { return MPI_Wtime(); } +//TimerType getTimeStamp(void) { return platform::walltime(); } //double getElapsedTime( const TimerType &t0, const TimerType &t1) { return t1-t0; } typedef struct timespec TimerType; diff --git a/src/KOKKOS/pair_exp6_rx_kokkos.h b/src/KOKKOS/pair_exp6_rx_kokkos.h index 4d20c59482..40917d832e 100644 --- a/src/KOKKOS/pair_exp6_rx_kokkos.h +++ b/src/KOKKOS/pair_exp6_rx_kokkos.h @@ -45,7 +45,7 @@ struct PairExp6ParamDataTypeKokkos epsilonOld2, alphaOld2, rmOld2, mixWtSite2old; // Default constructor -- nullify everything. - PairExp6ParamDataTypeKokkos(void) + PairExp6ParamDataTypeKokkos() : n(0) {} }; @@ -63,7 +63,7 @@ struct PairExp6ParamDataTypeKokkosVect nTotalold; // Default constructor -- nullify everything. - PairExp6ParamDataTypeKokkosVect(void) + PairExp6ParamDataTypeKokkosVect() {} }; diff --git a/src/KOKKOS/pppm_kokkos.cpp b/src/KOKKOS/pppm_kokkos.cpp index d71d7d1bad..da18bba001 100644 --- a/src/KOKKOS/pppm_kokkos.cpp +++ b/src/KOKKOS/pppm_kokkos.cpp @@ -2857,7 +2857,7 @@ int PPPMKokkos::timing_1d(int n, double &time1d) copymode = 0; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->timing1d(d_work1,nfft_both,FFT3dKokkos::FORWARD); @@ -2867,7 +2867,7 @@ int PPPMKokkos::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d = time2 - time1; return 4; @@ -2894,7 +2894,7 @@ int PPPMKokkos::timing_3d(int n, double &time3d) copymode = 0; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->compute(d_work1,d_work1,FFT3dKokkos::FORWARD); @@ -2904,7 +2904,7 @@ int PPPMKokkos::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d = time2 - time1; return 4; diff --git a/src/KSPACE/pppm.cpp b/src/KSPACE/pppm.cpp index b6739d43fd..9d3a06f18e 100644 --- a/src/KSPACE/pppm.cpp +++ b/src/KSPACE/pppm.cpp @@ -2981,7 +2981,7 @@ int PPPM::timing_1d(int n, double &time1d) for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->timing1d(work1,nfft_both,FFT3d::FORWARD); @@ -2993,7 +2993,7 @@ int PPPM::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d = time2 - time1; if (differentiation_flag) return 2; @@ -3011,7 +3011,7 @@ int PPPM::timing_3d(int n, double &time3d) for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->compute(work1,work1,FFT3d::FORWARD); @@ -3023,7 +3023,7 @@ int PPPM::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d = time2 - time1; if (differentiation_flag) return 2; diff --git a/src/KSPACE/pppm_dipole.cpp b/src/KSPACE/pppm_dipole.cpp index a39973c6ae..16e06ed13e 100644 --- a/src/KSPACE/pppm_dipole.cpp +++ b/src/KSPACE/pppm_dipole.cpp @@ -2443,7 +2443,7 @@ int PPPMDipole::timing_1d(int n, double &time1d) for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->timing1d(work1,nfft_both,FFT3d::FORWARD); @@ -2461,7 +2461,7 @@ int PPPMDipole::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d = time2 - time1; return 12; @@ -2478,7 +2478,7 @@ int PPPMDipole::timing_3d(int n, double &time3d) for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->compute(work1,work1,FFT3d::FFT3d::FORWARD); @@ -2496,7 +2496,7 @@ int PPPMDipole::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d = time2 - time1; return 12; diff --git a/src/KSPACE/pppm_disp.cpp b/src/KSPACE/pppm_disp.cpp index a523fcce9e..fa14cb23f0 100644 --- a/src/KSPACE/pppm_disp.cpp +++ b/src/KSPACE/pppm_disp.cpp @@ -8183,7 +8183,7 @@ int PPPMDisp::timing_1d(int n, double &time1d) for (int i = 0; i < 2*nfft_both_6; i++) work1_6[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (function[0]) { for (int i = 0; i < n; i++) { @@ -8197,11 +8197,11 @@ int PPPMDisp::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d = time2 - time1; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (function[1] + function[2] + function[3]) { for (int i = 0; i < n; i++) { @@ -8215,7 +8215,7 @@ int PPPMDisp::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d += (time2 - time1)*mixing; if (differentiation_flag) return 2; @@ -8238,7 +8238,7 @@ int PPPMDisp::timing_3d(int n, double &time3d) for (int i = 0; i < 2*nfft_both_6; i++) work1_6[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (function[0]) { for (int i = 0; i < n; i++) { @@ -8252,11 +8252,11 @@ int PPPMDisp::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d = time2 - time1; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (function[1] + function[2] + function[3]) { for (int i = 0; i < n; i++) { @@ -8270,7 +8270,7 @@ int PPPMDisp::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d += (time2 - time1) * mixing; if (differentiation_flag) return 2; diff --git a/src/LATBOLTZ/fix_lb_rigid_pc_sphere.cpp b/src/LATBOLTZ/fix_lb_rigid_pc_sphere.cpp index 9db1c2acec..304d5bbf0f 100644 --- a/src/LATBOLTZ/fix_lb_rigid_pc_sphere.cpp +++ b/src/LATBOLTZ/fix_lb_rigid_pc_sphere.cpp @@ -19,19 +19,19 @@ #include "fix_lb_rigid_pc_sphere.h" -#include - -#include #include "atom.h" -#include "domain.h" -#include "update.h" -#include "modify.h" -#include "group.h" #include "comm.h" -#include "force.h" -#include "memory.h" +#include "domain.h" #include "error.h" #include "fix_lb_fluid.h" +#include "force.h" +#include "group.h" +#include "memory.h" +#include "modify.h" +#include "update.h" + +#include +#include using namespace LAMMPS_NS; using namespace FixConst; @@ -237,15 +237,9 @@ FixLbRigidPCSphere::FixLbRigidPCSphere(LAMMPS *lmp, int narg, char **arg) : utils::bounds(FLERR,arg[iarg+1],1,nbody,mlo,mhi,error); double xflag,yflag,zflag; - if (strcmp(arg[iarg+2],"off") == 0) xflag = 0.0; - else if (strcmp(arg[iarg+2],"on") == 0) xflag = 1.0; - else error->all(FLERR,"Illegal fix lb/rigid/pc/sphere command"); - if (strcmp(arg[iarg+2],"off") == 0) yflag = 0.0; - else if (strcmp(arg[iarg+3],"on") == 0) yflag = 1.0; - else error->all(FLERR,"Illegal fix lb/rigid/pc/sphere command"); - if (strcmp(arg[iarg+4],"off") == 0) zflag = 0.0; - else if (strcmp(arg[iarg+4],"on") == 0) zflag = 1.0; - else error->all(FLERR,"Illegal fix lb/rigid/pc/sphere command"); + xflag = (double) utils::logical(FLERR, arg[iarg+2], false, lmp); + yflag = (double) utils::logical(FLERR, arg[iarg+3], false, lmp); + zflag = (double) utils::logical(FLERR, arg[iarg+4], false, lmp); int count = 0; for (int m = mlo; m <= mhi; m++) { @@ -263,16 +257,9 @@ FixLbRigidPCSphere::FixLbRigidPCSphere(LAMMPS *lmp, int narg, char **arg) : int mlo,mhi; utils::bounds(FLERR,arg[iarg+1],1,nbody,mlo,mhi,error); - double xflag,yflag,zflag; - if (strcmp(arg[iarg+2],"off") == 0) xflag = 0.0; - else if (strcmp(arg[iarg+2],"on") == 0) xflag = 1.0; - else error->all(FLERR,"Illegal fix lb/rigid/pc/sphere command"); - if (strcmp(arg[iarg+3],"off") == 0) yflag = 0.0; - else if (strcmp(arg[iarg+3],"on") == 0) yflag = 1.0; - else error->all(FLERR,"Illegal fix lb/rigid/pc/sphere command"); - if (strcmp(arg[iarg+4],"off") == 0) zflag = 0.0; - else if (strcmp(arg[iarg+4],"on") == 0) zflag = 1.0; - else error->all(FLERR,"Illegal fix lb/rigid/pc/sphere command"); + const double xflag = (double) utils::logical(FLERR,arg[iarg+2],false,lmp); + const double yflag = (double) utils::logical(FLERR,arg[iarg+3],false,lmp); + const double zflag = (double) utils::logical(FLERR,arg[iarg+4],false,lmp); int count = 0; for (int m = mlo; m <= mhi; m++) { diff --git a/src/MAKE/MACHINES/Makefile.aarch64_g++_openmpi_armpl b/src/MAKE/MACHINES/Makefile.aarch64_g++_openmpi_armpl index 4174c9c5e7..2ebd2ac744 100644 --- a/src/MAKE/MACHINES/Makefile.aarch64_g++_openmpi_armpl +++ b/src/MAKE/MACHINES/Makefile.aarch64_g++_openmpi_armpl @@ -8,12 +8,12 @@ SHELL = /bin/sh export OMPI_CXX = g++ CC = mpicxx -CCFLAGS = -O3 -march=native -mcpu=native +CCFLAGS = -O3 -march=native -mcpu=native -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -O +LINKFLAGS = -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/MACHINES/Makefile.aarch64_g++_serial_armpl b/src/MAKE/MACHINES/Makefile.aarch64_g++_serial_armpl index 5cb6fa0cde..054b530bc8 100644 --- a/src/MAKE/MACHINES/Makefile.aarch64_g++_serial_armpl +++ b/src/MAKE/MACHINES/Makefile.aarch64_g++_serial_armpl @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = g++ -CCFLAGS = -O3 -march=native -mcpu=native +CCFLAGS = -O3 -march=native -mcpu=native -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = g++ -LINKFLAGS = -O +LINKFLAGS = -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/MACHINES/Makefile.cygwin b/src/MAKE/MACHINES/Makefile.cygwin index 4c47860a56..3d4a50a8ea 100644 --- a/src/MAKE/MACHINES/Makefile.cygwin +++ b/src/MAKE/MACHINES/Makefile.cygwin @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -CCFLAGS = -O +CCFLAGS = -O2 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -O +LINKFLAGS = -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/MACHINES/Makefile.mac b/src/MAKE/MACHINES/Makefile.mac index 67381fe622..fb749b5759 100644 --- a/src/MAKE/MACHINES/Makefile.mac +++ b/src/MAKE/MACHINES/Makefile.mac @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = c++ -CCFLAGS = -O +CCFLAGS = -O -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = c++ -LINKFLAGS = -O +LINKFLAGS = -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/MACHINES/Makefile.mac_mpi b/src/MAKE/MACHINES/Makefile.mac_mpi index 0b6b4b5ba2..4718c94e51 100644 --- a/src/MAKE/MACHINES/Makefile.mac_mpi +++ b/src/MAKE/MACHINES/Makefile.mac_mpi @@ -8,12 +8,12 @@ SHELL = /bin/sh # unless additional compiler/linker flags or libraries needed for your machine CC = /opt/local/bin/mpicxx-openmpi-mp -CCFLAGS = -O3 +CCFLAGS = -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = /opt/local/bin/mpicxx-openmpi-mp -LINKFLAGS = -O3 +LINKFLAGS = -O3 -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/MACHINES/Makefile.ubuntu b/src/MAKE/MACHINES/Makefile.ubuntu index 6c419ffdfa..f030ce64df 100644 --- a/src/MAKE/MACHINES/Makefile.ubuntu +++ b/src/MAKE/MACHINES/Makefile.ubuntu @@ -11,12 +11,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpic++ -CCFLAGS = -g -O3 # -Wunused +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpic++ -LINKFLAGS = -g -O3 +LINKFLAGS = -g -O3 -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/MACHINES/Makefile.ubuntu_simple b/src/MAKE/MACHINES/Makefile.ubuntu_simple index 98897f964f..e8b58fc804 100644 --- a/src/MAKE/MACHINES/Makefile.ubuntu_simple +++ b/src/MAKE/MACHINES/Makefile.ubuntu_simple @@ -10,12 +10,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpic++ -CCFLAGS = -g -O3 # -Wunused +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpic++ -LINKFLAGS = -g -O3 +LINKFLAGS = -g -O3 -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/Makefile.mpi b/src/MAKE/Makefile.mpi index 9776b0153e..42f48b4e2c 100644 --- a/src/MAKE/Makefile.mpi +++ b/src/MAKE/Makefile.mpi @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -g -O3 +LINKFLAGS = -g -O3 -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/Makefile.serial b/src/MAKE/Makefile.serial index 0f5952f317..b527919147 100644 --- a/src/MAKE/Makefile.serial +++ b/src/MAKE/Makefile.serial @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = g++ -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = g++ -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.g++_mpich b/src/MAKE/OPTIONS/Makefile.g++_mpich index 4ea855cfeb..e0c77437f5 100644 --- a/src/MAKE/OPTIONS/Makefile.g++_mpich +++ b/src/MAKE/OPTIONS/Makefile.g++_mpich @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -cxx=g++ -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -cxx=g++ -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.g++_mpich_link b/src/MAKE/OPTIONS/Makefile.g++_mpich_link index 7b92a3e77a..4f2855a9cc 100644 --- a/src/MAKE/OPTIONS/Makefile.g++_mpich_link +++ b/src/MAKE/OPTIONS/Makefile.g++_mpich_link @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = g++ -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = g++ -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.g++_openmpi_link b/src/MAKE/OPTIONS/Makefile.g++_openmpi_link index 6fc71fe2a5..0c9997dbb0 100644 --- a/src/MAKE/OPTIONS/Makefile.g++_openmpi_link +++ b/src/MAKE/OPTIONS/Makefile.g++_openmpi_link @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = g++ -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = g++ -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.g++_serial b/src/MAKE/OPTIONS/Makefile.g++_serial index 4f6f0afe22..d6b9bf3221 100644 --- a/src/MAKE/OPTIONS/Makefile.g++_serial +++ b/src/MAKE/OPTIONS/Makefile.g++_serial @@ -6,13 +6,13 @@ SHELL = /bin/sh # compiler/linker settings # specify flags and libraries needed for your compiler -CC = g++ -std=c++11 -CCFLAGS = -g -O3 +CC = g++ +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M -LINK = g++ -std=c++11 -LINKFLAGS = -g -O +LINK = g++ +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.gpu b/src/MAKE/OPTIONS/Makefile.gpu index 26c98c120d..9ad5cf477c 100644 --- a/src/MAKE/OPTIONS/Makefile.gpu +++ b/src/MAKE/OPTIONS/Makefile.gpu @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.icc_mpich b/src/MAKE/OPTIONS/Makefile.icc_mpich index cf76506da5..c630c42c26 100644 --- a/src/MAKE/OPTIONS/Makefile.icc_mpich +++ b/src/MAKE/OPTIONS/Makefile.icc_mpich @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -cxx=icc -CCFLAGS = -g -O3 -restrict +CCFLAGS = -g -O3 -restrict -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -cxx=icc -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.icc_mpich_link b/src/MAKE/OPTIONS/Makefile.icc_mpich_link index 3994968430..8b89d2509a 100644 --- a/src/MAKE/OPTIONS/Makefile.icc_mpich_link +++ b/src/MAKE/OPTIONS/Makefile.icc_mpich_link @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = icc -CCFLAGS = -g -O3 -restrict +CCFLAGS = -g -O3 -restrict -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = icc -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.icc_openmpi b/src/MAKE/OPTIONS/Makefile.icc_openmpi index 72e3d44093..0a2c9598a6 100644 --- a/src/MAKE/OPTIONS/Makefile.icc_openmpi +++ b/src/MAKE/OPTIONS/Makefile.icc_openmpi @@ -8,12 +8,12 @@ SHELL = /bin/sh export OMPI_CXX = icc CC = mpicxx -CCFLAGS = -g -O3 -restrict +CCFLAGS = -g -O3 -restrict -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.icc_openmpi_link b/src/MAKE/OPTIONS/Makefile.icc_openmpi_link index e44486aeb5..825d4cdff0 100644 --- a/src/MAKE/OPTIONS/Makefile.icc_openmpi_link +++ b/src/MAKE/OPTIONS/Makefile.icc_openmpi_link @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = icc -CCFLAGS = -g -O3 -restrict +CCFLAGS = -g -O3 -restrict -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = icc -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.icc_serial b/src/MAKE/OPTIONS/Makefile.icc_serial index a81c73c718..2d2da54c68 100644 --- a/src/MAKE/OPTIONS/Makefile.icc_serial +++ b/src/MAKE/OPTIONS/Makefile.icc_serial @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = icc -CCFLAGS = -g -O3 -restrict +CCFLAGS = -g -O3 -restrict -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = icc -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.jpeg b/src/MAKE/OPTIONS/Makefile.jpeg index e8f1f3e96a..268e7b94e8 100644 --- a/src/MAKE/OPTIONS/Makefile.jpeg +++ b/src/MAKE/OPTIONS/Makefile.jpeg @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.omp b/src/MAKE/OPTIONS/Makefile.omp index 0f49cdb15c..573c2d826b 100644 --- a/src/MAKE/OPTIONS/Makefile.omp +++ b/src/MAKE/OPTIONS/Makefile.omp @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -CCFLAGS = -g -O3 -restrict -fopenmp +CCFLAGS = -g -O3 -restrict -fopenmp -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -g -O -fopenmp +LINKFLAGS = -g -O -fopenmp -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.opt b/src/MAKE/OPTIONS/Makefile.opt index 8919e6e1d9..2cb5540fd4 100644 --- a/src/MAKE/OPTIONS/Makefile.opt +++ b/src/MAKE/OPTIONS/Makefile.opt @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -CCFLAGS = -g -O3 -restrict +CCFLAGS = -g -O3 -restrict -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MAKE/OPTIONS/Makefile.png b/src/MAKE/OPTIONS/Makefile.png index 9fd7b9b79c..40ebe43d32 100644 --- a/src/MAKE/OPTIONS/Makefile.png +++ b/src/MAKE/OPTIONS/Makefile.png @@ -7,12 +7,12 @@ SHELL = /bin/sh # specify flags and libraries needed for your compiler CC = mpicxx -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -std=c++11 SHFLAGS = -fPIC DEPFLAGS = -M LINK = mpicxx -LINKFLAGS = -g -O +LINKFLAGS = -g -O -std=c++11 LIB = SIZE = size diff --git a/src/MANYBODY/pair_atm.cpp b/src/MANYBODY/pair_atm.cpp index 81adef5871..f7eda909e6 100644 --- a/src/MANYBODY/pair_atm.cpp +++ b/src/MANYBODY/pair_atm.cpp @@ -128,9 +128,9 @@ void PairATM::compute(int eflag, int vflag) rij[0] = x[j][0] - xi; if (rij[0] < 0.0) continue; rij[1] = x[j][1] - yi; - if (rij[0] == 0.0 and rij[1] < 0.0) continue; + if (rij[0] == 0.0 && rij[1] < 0.0) continue; rij[2] = x[j][2] - zi; - if (rij[0] == 0.0 and rij[1] == 0.0 and rij[2] < 0.0) continue; + if (rij[0] == 0.0 && rij[1] == 0.0 && rij[2] < 0.0) continue; rij2 = rij[0]*rij[0] + rij[1]*rij[1] + rij[2]*rij[2]; if (rij2 > cutoff_squared) continue; @@ -141,9 +141,9 @@ void PairATM::compute(int eflag, int vflag) rik[0] = x[k][0] - xi; if (rik[0] < 0.0) continue; rik[1] = x[k][1] - yi; - if (rik[0] == 0.0 and rik[1] < 0.0) continue; + if (rik[0] == 0.0 && rik[1] < 0.0) continue; rik[2] = x[k][2] - zi; - if (rik[0] == 0.0 and rik[1] == 0.0 and rik[2] < 0.0) continue; + if (rik[0] == 0.0 && rik[1] == 0.0 && rik[2] < 0.0) continue; rik2 = rik[0]*rik[0] + rik[1]*rik[1] + rik[2]*rik[2]; if (rik2 > cutoff_squared) continue; diff --git a/src/MANYBODY/pair_polymorphic.cpp b/src/MANYBODY/pair_polymorphic.cpp index f12d369e0d..ce476e1204 100644 --- a/src/MANYBODY/pair_polymorphic.cpp +++ b/src/MANYBODY/pair_polymorphic.cpp @@ -593,7 +593,7 @@ void PairPolymorphic::read_file(char *file) if ((ng == 0) || (nr == 0) || (nx == 0)) error->one(FLERR,"Error reading potential file header"); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { error->one(FLERR,"Potential file incompatible with this pair style version"); } diff --git a/src/MC/fix_atom_swap.cpp b/src/MC/fix_atom_swap.cpp index 84c060a557..76200dc614 100644 --- a/src/MC/fix_atom_swap.cpp +++ b/src/MC/fix_atom_swap.cpp @@ -160,15 +160,11 @@ void FixAtomSwap::options(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"ke") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix atom/swap command"); - if (strcmp(arg[iarg+1],"no") == 0) conserve_ke_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) conserve_ke_flag = 1; - else error->all(FLERR,"Illegal fix atom/swap command"); + conserve_ke_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"semi-grand") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix atom/swap command"); - if (strcmp(arg[iarg+1],"no") == 0) semi_grand_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) semi_grand_flag = 1; - else error->all(FLERR,"Illegal fix atom/swap command"); + semi_grand_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"types") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal fix atom/swap command"); diff --git a/src/MC/fix_charge_regulation.cpp b/src/MC/fix_charge_regulation.cpp index 2497b3d976..078e7eb9db 100644 --- a/src/MC/fix_charge_regulation.cpp +++ b/src/MC/fix_charge_regulation.cpp @@ -1180,8 +1180,8 @@ void FixChargeRegulation::setThermoTemperaturePointer() { int ifix = -1; ifix = modify->find_fix(idftemp); if (ifix == -1) { - error->all(FLERR, - "fix charge/regulation regulation could not find a temperature fix id provided by tempfixid\n"); + error->all(FLERR, "fix charge/regulation regulation could not find " + "a temperature fix id provided by tempfixid\n"); } Fix *temperature_fix = modify->fix[ifix]; int dim; @@ -1198,8 +1198,7 @@ void FixChargeRegulation::assign_tags() { for (int i = 0; i < atom->nlocal; i++) maxtag = MAX(maxtag, tag[i]); maxtag_all = maxtag; MPI_Allreduce(&maxtag, &maxtag_all, 1, MPI_LMP_TAGINT, MPI_MAX, world); - if (maxtag_all >= MAXTAGINT) - error->all(FLERR, "New atom IDs exceed maximum allowed ID"); + if (maxtag_all >= MAXTAGINT) error->all(FLERR, "New atom IDs exceed maximum allowed ID"); tagint notag = 0; tagint notag_all; @@ -1267,23 +1266,19 @@ void FixChargeRegulation::options(int narg, char **arg) { while (iarg < narg) { if (strcmp(arg[iarg], "lunit_nm") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); llength_unit_in_nm = utils::numeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "acid_type") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); acid_type = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "base_type") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); base_type = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "pH") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); if (strstr(arg[iarg + 1],"v_") == arg[iarg + 1]) { pHstr = utils::strdup(&arg[iarg + 1][2]); } else { @@ -1292,45 +1287,37 @@ void FixChargeRegulation::options(int narg, char **arg) { } iarg += 2; } else if (strcmp(arg[iarg], "pIp") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); pI_plus = utils::numeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "pIm") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); pI_minus = utils::numeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "pKa") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); pKa = utils::numeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "pKb") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); pKb = utils::numeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "temp") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); reservoir_temperature = utils::numeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "pKs") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); pKs = utils::numeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "tempfixid") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); idftemp = utils::strdup(arg[iarg+1]); setThermoTemperaturePointer(); iarg += 2; } else if (strcmp(arg[iarg], "rxd") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); reaction_distance = utils::numeric(FLERR, arg[iarg + 1], false, lmp); if ((reaction_distance > domain->prd_half[0]) || (reaction_distance > domain->prd_half[1]) || @@ -1342,61 +1329,44 @@ void FixChargeRegulation::options(int narg, char **arg) { } iarg += 2; } else if (strcmp(arg[iarg], "nevery") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); nevery = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "nmc") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); nmc = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "pmcmoves") == 0) { - if (iarg + 4 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 4 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); pmcmoves[0] = utils::numeric(FLERR, arg[iarg + 1], false, lmp); pmcmoves[1] = utils::numeric(FLERR, arg[iarg + 2], false, lmp); pmcmoves[2] = utils::numeric(FLERR, arg[iarg + 3], false, lmp); iarg += 4; } else if (strcmp(arg[iarg], "seed") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); seed = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg], "tag") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); - if (strcmp(arg[iarg + 1], "yes") == 0) { - add_tags_flag = true; - } else if (strcmp(arg[iarg + 1], "no") == 0) { - add_tags_flag = false; - } else error->all(FLERR, "Illegal fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); + add_tags_flag = utils::logical(FLERR,arg[iarg+1],false,lmp) == 1; iarg += 2; } else if (strcmp(arg[iarg], "onlysalt") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); - if (strcmp(arg[iarg + 1], "yes") == 0) { - only_salt_flag = true; + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); + only_salt_flag = utils::logical(FLERR,arg[iarg+1],false,lmp) == 1; + iarg += 2; + if (only_salt_flag) { // need to specify salt charge - if (iarg + 4 > narg) - error->all(FLERR, "Illegal fix charge/regulation command"); - salt_charge[0] = utils::inumeric(FLERR, arg[iarg + 2], false, lmp); - salt_charge[1] = utils::inumeric(FLERR, arg[iarg + 3], false, lmp); - iarg += 4; - } else if (strcmp(arg[iarg + 1], "no") == 0) { - only_salt_flag = false; + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix charge/regulation command"); + salt_charge[0] = utils::inumeric(FLERR, arg[iarg], false, lmp); + salt_charge[1] = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); iarg += 2; - } else error->all(FLERR, "Illegal fix charge/regulation command"); - + } } else if (strcmp(arg[iarg], "group") == 0) { - if (iarg + 2 > narg) - error->all(FLERR, "Illegal fix fix charge/regulation command"); + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix fix charge/regulation command"); if (ngroups >= ngroupsmax) { ngroupsmax = ngroups + 1; groupstrings = (char **) - memory->srealloc(groupstrings, - ngroupsmax * sizeof(char *), - "fix_charge_regulation:groupstrings"); + memory->srealloc(groupstrings, ngroupsmax * sizeof(char *), "fix_charge_regulation:groupstrings"); } groupstrings[ngroups] = utils::strdup(arg[iarg+1]); ngroups++; diff --git a/src/MDI/fix_mdi_engine.cpp b/src/MDI/fix_mdi_engine.cpp index 8024623e43..b08209080a 100644 --- a/src/MDI/fix_mdi_engine.cpp +++ b/src/MDI/fix_mdi_engine.cpp @@ -388,7 +388,7 @@ char *FixMDIEngine::engine_mode(const char *node) // respond to commands from the driver - while (not exit_flag and not local_exit_flag) { + while (!exit_flag && !local_exit_flag) { // read the next command from the driver // all procs call this, but only proc 0 receives the command diff --git a/src/MISC/fix_imd.cpp b/src/MISC/fix_imd.cpp index abba37cf3f..1e2160ef07 100644 --- a/src/MISC/fix_imd.cpp +++ b/src/MISC/fix_imd.cpp @@ -458,28 +458,20 @@ FixIMD::FixIMD(LAMMPS *lmp, int narg, char **arg) : imd_trate = 1; /* parse optional arguments */ - int argsdone = 4; - while (argsdone+1 < narg) { - if (0 == strcmp(arg[argsdone], "unwrap")) { - if (0 == strcmp(arg[argsdone+1], "on")) { - unwrap_flag = 1; - } else { - unwrap_flag = 0; - } - } else if (0 == strcmp(arg[argsdone], "nowait")) { - if (0 == strcmp(arg[argsdone+1], "on")) { - nowait_flag = 1; - } else { - nowait_flag = 0; - } - } else if (0 == strcmp(arg[argsdone], "fscale")) { - imd_fscale = utils::numeric(FLERR,arg[argsdone+1],false,lmp); - } else if (0 == strcmp(arg[argsdone], "trate")) { - imd_trate = utils::inumeric(FLERR,arg[argsdone+1],false,lmp); + int iarg = 4; + while (iarg+1 < narg) { + if (0 == strcmp(arg[iarg], "unwrap")) { + unwrap_flag = utils::logical(FLERR, arg[iarg+1], false, lmp); + } else if (0 == strcmp(arg[iarg], "nowait")) { + nowait_flag = utils::logical(FLERR, arg[iarg+1], false, lmp); + } else if (0 == strcmp(arg[iarg], "fscale")) { + imd_fscale = utils::numeric(FLERR,arg[iarg+1],false,lmp); + } else if (0 == strcmp(arg[iarg], "trate")) { + imd_trate = utils::inumeric(FLERR,arg[iarg+1],false,lmp); } else { error->all(FLERR,"Unknown fix imd parameter"); } - ++argsdone; ++argsdone; + ++iarg; ++iarg; } /* sanity check on parameters */ diff --git a/src/MISC/fix_ipi.cpp b/src/MISC/fix_ipi.cpp index b56c5eebcb..b82339713e 100644 --- a/src/MISC/fix_ipi.cpp +++ b/src/MISC/fix_ipi.cpp @@ -200,22 +200,10 @@ FixIPI::FixIPI(LAMMPS *lmp, int narg, char **arg) : hasdata = bsize = 0; // creates a temperature compute for all atoms - char** newarg = new char*[3]; - newarg[0] = (char *) "IPI_TEMP"; - newarg[1] = (char *) "all"; - newarg[2] = (char *) "temp"; - modify->add_compute(3,newarg); - delete [] newarg; + modify->add_compute("IPI_TEMP all temp"); // creates a pressure compute to extract the virial - newarg = new char*[5]; - newarg[0] = (char *) "IPI_PRESS"; - newarg[1] = (char *) "all"; - newarg[2] = (char *) "pressure"; - newarg[3] = (char *) "IPI_TEMP"; - newarg[4] = (char *) "virial"; - modify->add_compute(5,newarg); - delete [] newarg; + modify->add_compute("IPI_PRESS all pressure IPI_TEMP virial"); // create instance of Irregular class irregular = new Irregular(lmp); diff --git a/src/MISC/fix_pair_tracker.cpp b/src/MISC/fix_pair_tracker.cpp index 95151375c4..3616855869 100644 --- a/src/MISC/fix_pair_tracker.cpp +++ b/src/MISC/fix_pair_tracker.cpp @@ -79,15 +79,14 @@ FixPairTracker::FixPairTracker(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg], "type/include") == 0) { if (iarg + 1 >= narg) error->all(FLERR, "Invalid keyword in fix pair/tracker command"); int ntypes = atom->ntypes; - - int i, j, itype, jtype, in, jn, infield, jnfield; + int i, j, itype, jtype; int inlo, inhi, jnlo, jnhi; - char *istr, *jstr; + if (!type_filter) { memory->create(type_filter, ntypes + 1, ntypes + 1, "fix/pair/tracker:type_filter"); for (i = 0; i <= ntypes; i++) { - for (j = 0; j <= ntypes; j++) { type_filter[i][j] = 0; } + for (j = 0; j <= ntypes; j++) type_filter[i][j] = 0; } } diff --git a/src/MISC/pair_srp.cpp b/src/MISC/pair_srp.cpp index 456d45c0ae..77a8eb4c2d 100644 --- a/src/MISC/pair_srp.cpp +++ b/src/MISC/pair_srp.cpp @@ -378,12 +378,8 @@ void PairSRP::settings(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"exclude") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair srp command"); - if (strcmp(arg[iarg+1],"yes") == 0) - exclude = 1; - if (strcmp(arg[iarg+1],"no") == 0) { - if (min) error->all(FLERR,"Illegal exclude option in pair srp command"); - exclude = 0; - } + exclude = utils::logical(FLERR, arg[iarg+1], false, lmp); + if (min && !exclude) error->all(FLERR,"Illegal exclude option in pair srp command"); iarg += 2; } else if (strcmp(arg[iarg],"bptype") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair srp command"); diff --git a/src/ML-HDNNP/pair_hdnnp.cpp b/src/ML-HDNNP/pair_hdnnp.cpp index c27f93c132..8411a0c3cf 100644 --- a/src/ML-HDNNP/pair_hdnnp.cpp +++ b/src/ML-HDNNP/pair_hdnnp.cpp @@ -148,12 +148,7 @@ void PairHDNNP::settings(int narg, char **arg) // show extrapolation warnings } else if (strcmp(arg[iarg], "showew") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal pair_style command"); - if (strcmp(arg[iarg + 1], "yes") == 0) - showew = true; - else if (strcmp(arg[iarg + 1], "no") == 0) - showew = false; - else - error->all(FLERR, "Illegal pair_style command"); + showew = utils::logical(FLERR, arg[iarg + 1], false, lmp) == 1; iarg += 2; // show extrapolation warning summary } else if (strcmp(arg[iarg], "showewsum") == 0) { @@ -168,12 +163,7 @@ void PairHDNNP::settings(int narg, char **arg) // reset extrapolation warning counter } else if (strcmp(arg[iarg], "resetew") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal pair_style command"); - if (strcmp(arg[iarg + 1], "yes") == 0) - resetew = true; - else if (strcmp(arg[iarg + 1], "no") == 0) - resetew = false; - else - error->all(FLERR, "Illegal pair_style command"); + resetew = utils::logical(FLERR, arg[iarg + 1], false, lmp) == 1; iarg += 2; // length unit conversion factor } else if (strcmp(arg[iarg], "cflength") == 0) { diff --git a/src/ML-IAP/mliap_model_python.cpp b/src/ML-IAP/mliap_model_python.cpp index 3d91107449..b89d17f289 100644 --- a/src/ML-IAP/mliap_model_python.cpp +++ b/src/ML-IAP/mliap_model_python.cpp @@ -132,7 +132,7 @@ void MLIAPModelPython::connect_param_counts() void MLIAPModelPython::compute_gradients(MLIAPData *data) { - if (not model_loaded) { error->all(FLERR, "Model not loaded."); } + if (!model_loaded) { error->all(FLERR, "Model not loaded."); } PyGILState_STATE gstate = PyGILState_Ensure(); MLIAPPY_compute_gradients(this, data); diff --git a/src/ML-SNAP/pair_snap.cpp b/src/ML-SNAP/pair_snap.cpp index d7cd953615..d6da639734 100644 --- a/src/ML-SNAP/pair_snap.cpp +++ b/src/ML-SNAP/pair_snap.cpp @@ -500,8 +500,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) nelemtmp = words.next_int(); ncoeffall = words.next_int(); } catch (TokenizerException &e) { - error->all(FLERR,"Incorrect format in SNAP coefficient " - "file: {}", e.what()); + error->all(FLERR,"Incorrect format in SNAP coefficient file: {}", e.what()); } // clean out old arrays and set up element lists @@ -538,7 +537,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) std::vector words; try { words = Tokenizer(utils::trim_comment(line),"\"' \t\n\r\f").as_vector(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { // ignore } if (words.size() != 3) @@ -599,8 +598,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) coeffelem[jelem][icoeff] = coeff.next_double(); } catch (TokenizerException &e) { - error->all(FLERR,"Incorrect format in SNAP coefficient " - "file: {}", e.what()); + error->all(FLERR,"Incorrect format in SNAP coefficient file: {}", e.what()); } } } @@ -609,8 +607,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) for (int jelem = 0; jelem < nelements; jelem++) { if (elementflags[jelem] == 0) - error->all(FLERR,"Element {} not found in SNAP coefficient " - "file", elements[jelem]); + error->all(FLERR,"Element {} not found in SNAP coefficient file", elements[jelem]); } delete[] elementflags; @@ -660,7 +657,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) std::vector words; try { words = Tokenizer(utils::trim_comment(line),"\"' \t\n\r\f").as_vector(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { // ignore } diff --git a/src/MOLECULE/angle_table.cpp b/src/MOLECULE/angle_table.cpp index 4299e375f1..a5ba07b779 100644 --- a/src/MOLECULE/angle_table.cpp +++ b/src/MOLECULE/angle_table.cpp @@ -412,7 +412,7 @@ void AngleTable::read_table(Table *tb, char *file, char *keyword) tb->afile[i] = values.next_double(); tb->efile[i] = values.next_double(); tb->ffile[i] = values.next_double(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { ++cerror; } } diff --git a/src/MOLECULE/bond_table.cpp b/src/MOLECULE/bond_table.cpp index 5637dfa699..db1314c76f 100644 --- a/src/MOLECULE/bond_table.cpp +++ b/src/MOLECULE/bond_table.cpp @@ -340,7 +340,7 @@ void BondTable::read_table(Table *tb, char *file, char *keyword) tb->rfile[i] = values.next_double(); tb->efile[i] = values.next_double(); tb->ffile[i] = values.next_double(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { ++cerror; } diff --git a/src/MOLFILE/dump_molfile.cpp b/src/MOLFILE/dump_molfile.cpp index c1c4120405..35e87f94af 100644 --- a/src/MOLFILE/dump_molfile.cpp +++ b/src/MOLFILE/dump_molfile.cpp @@ -26,8 +26,8 @@ #include "memory.h" #include "update.h" -#include #include +#include #include "molfile_interface.h" @@ -131,9 +131,9 @@ DumpMolfile::~DumpMolfile() if (typenames) { for (int i = 1; i <= ntypes; i++) - delete [] typenames[i]; + delete[] typenames[i]; - delete [] typenames; + delete[] typenames; typenames = nullptr; } } @@ -152,8 +152,7 @@ void DumpMolfile::init_style() typenames = new char*[ntypes+1]; for (int itype = 1; itype <= ntypes; itype++) { /* a 32-bit int can be maximally 10 digits plus sign */ - typenames[itype] = new char[12]; - sprintf(typenames[itype],"%d",itype); + typenames[itype] = utils::strdup(std::to_string(itype)); } } @@ -207,6 +206,7 @@ void DumpMolfile::write() } } ntotal = 0; + reorderflag = 0; // if file per timestep, open new file @@ -421,9 +421,7 @@ int DumpMolfile::modify_param(int narg, char **arg) { if (strcmp(arg[0],"unwrap") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[1],"yes") == 0) unwrap_flag = 1; - else if (strcmp(arg[1],"no") == 0) unwrap_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + unwrap_flag = utils::logical(FLERR,arg[1],false,lmp); return 2; } else if (strcmp(arg[0],"element") == 0) { @@ -432,9 +430,9 @@ int DumpMolfile::modify_param(int narg, char **arg) if (typenames) { for (int i = 1; i <= ntypes; i++) - delete [] typenames[i]; + delete[] typenames[i]; - delete [] typenames; + delete[] typenames; typenames = nullptr; } diff --git a/src/MOLFILE/molfile_interface.cpp b/src/MOLFILE/molfile_interface.cpp index 8e1174d8f4..808bc16ab4 100644 --- a/src/MOLFILE/molfile_interface.cpp +++ b/src/MOLFILE/molfile_interface.cpp @@ -17,20 +17,16 @@ ------------------------------------------------------------------------- */ #include "molfile_interface.h" + +#include "platform.h" +#include "tokenizer.h" +#include "utils.h" + #include "molfile_plugin.h" #include #include #include -#include -#include // for strcasecmp() - -#if defined(_WIN32) -#include -#else -#include -#include -#endif #if vmdplugin_ABIVERSION < 16 #error "unsupported VMD molfile plugin ABI version" @@ -199,172 +195,17 @@ extern "C" { return 0; } - // directory traversal helper functions - -#if defined(_WIN32) - - // Win32 directory traversal handle - typedef struct { - HANDLE h; - WIN32_FIND_DATA fd; - char *name; - char *searchname; - int dlen; - } dirhandle_t; - - // open a directory handle - static dirhandle_t *my_opendir(const char *dirname) - { - dirhandle_t *d; - int len; - - if (dirname == nullptr) - return nullptr; - d = new dirhandle_t; - - len = 2 + strlen(dirname); - d->name = new char[len]; - strcpy(d->name, dirname); - strcat(d->name, "\\"); - d->dlen = len; - - len += 1; - d->searchname = new char[len]; - strcpy(d->searchname, dirname); - strcat(d->searchname, "\\*"); - - d->h = FindFirstFile(d->searchname, &(d->fd)); - if (d->h == ((HANDLE)(-1))) { - delete[] d->searchname; - delete[] d->name; - delete d; - return nullptr; - } - return d; - } - - // get next file name from directory handle - static char *my_readdir(dirhandle_t *d) - { - if (FindNextFile(d->h, &(d->fd))) { - return d->fd.cFileName; - } - return nullptr; - } - - // close directory handle - static void my_closedir(dirhandle_t *d) - { - if (d->h != nullptr) { - FindClose(d->h); - } - delete[] d->searchname; - delete[] d->name; - delete d; - } - - // open a shared object file - static void *my_dlopen(const char *fname) { - return (void *)LoadLibrary(fname); - } - - // resolve a symbol in shared object - static void *my_dlsym(void *h, const char *sym) { - return (void *)GetProcAddress((HINSTANCE)h, sym); - } - - // close a shared object - static int my_dlclose(void *h) { - /* FreeLibrary returns nonzero on success */ - return !FreeLibrary((HINSTANCE)h); - } - -#else - - // Unix directory traversal handle - typedef struct { - DIR *d; - char *name; - int dlen; - } dirhandle_t; - - // open a directory handle - static dirhandle_t *my_opendir(const char *dirname) - { - dirhandle_t *d; - int len; - - if (dirname == nullptr) return nullptr; - - d = new dirhandle_t; - len = 2 + strlen(dirname); - d->name = new char[len]; - strcpy(d->name,dirname); - strcat(d->name,"/"); - d->dlen = len; - - d->d = opendir(d->name); - if (d->d == nullptr) { - delete[] d->name; - delete d; - return nullptr; - } - return d; - } - - // get next file name from directory handle - static char *my_readdir(dirhandle_t *d) - { - struct dirent *p; - - if ((p = readdir(d->d)) != nullptr) { - return p->d_name; - } - - return nullptr; - } - - // close directory handle - static void my_closedir(dirhandle_t *d) - { - if (d->d != nullptr) { - closedir(d->d); - } - delete[] d->name; - delete d; - return; - } - - // open a shared object file - static void *my_dlopen(const char *fname) { - return dlopen(fname, RTLD_NOW); - } - - // resolve a symbol in shared object - static void *my_dlsym(void *h, const char *sym) { - return dlsym(h, sym); - } - - // close a shared object - static int my_dlclose(void *h) { - return dlclose(h); - } - -#endif - } // end of extern "C" region using namespace LAMMPS_NS; // constructor. MolfileInterface::MolfileInterface(const char *type, const int mode) - : _plugin(0), _dso(0), _ptr(0), _info(0), _natoms(0), - _mode(mode), _caps(M_NONE) + : _plugin(nullptr), _dso(nullptr), _ptr(nullptr), _info(nullptr), _natoms(0), + _mode(mode), _caps(M_NONE), _props(0) { - _name = new char[5]; - strcpy(_name,"none"); - _type = new char[1+strlen(type)]; - strcpy(_type,type); + _name = utils::strdup("none"); + _type = utils::strdup(type); } // destructor. @@ -384,62 +225,21 @@ MolfileInterface::~MolfileInterface() // register the best matching plugin in a given directory int MolfileInterface::find_plugin(const char *pluginpath) { - dirhandle_t *dir; - char *filename, *ext, *next, *path, *plugindir; int retval = E_NONE; -#if defined(_WIN32) -#define MY_PATHSEP ';' -#else -#define MY_PATHSEP ':' -#endif if (pluginpath == nullptr) return E_DIR; - plugindir = path = strdup(pluginpath); - while (plugindir) { - // check if this a single directory or path. - next = strchr(plugindir,MY_PATHSEP); - if (next) { - *next = '\0'; - ++next; + // search for suitable file names in provided path and try to inspect them + // only look at .so files, since this is what VMD uses on all platforms + + for (const auto &dir : Tokenizer(pluginpath,":").as_vector()) { + for (const auto &filename : platform::list_directory(dir)) { + if (utils::strmatch(filename,"\\.so$")) { + int rv = load_plugin(platform::path_join(dir,filename).c_str()); + if (rv > retval) retval = rv; + } } - - dir = my_opendir(plugindir); - if (!dir) - retval = (retval > E_DIR) ? retval : E_DIR; - - // search for suitable file names and try to inspect them - while (dir) { - char *fullname; - int len; - - filename = my_readdir(dir); - if (filename == nullptr) break; - - // only look at .so files - ext = strrchr(filename, '.'); - if (ext == nullptr) continue; - if (strcasecmp(ext,".so") != 0) continue; - - // construct full pathname of potential DSO - len = dir->dlen; - len += strlen(filename); - fullname = new char[len]; - strcpy(fullname,dir->name); - strcat(fullname,filename); - - // try to register plugin at file name. - int rv = load_plugin(fullname); - if (rv > retval) retval = rv; - - delete[] fullname; - } - if (dir) - my_closedir(dir); - - plugindir = next; } - free(path); return retval; } @@ -447,25 +247,25 @@ int MolfileInterface::find_plugin(const char *pluginpath) int MolfileInterface::load_plugin(const char *filename) { void *dso; - int len, retval = E_NONE; + int retval = E_NONE; // access shared object - dso = my_dlopen(filename); + dso = platform::dlopen(filename); if (dso == nullptr) return E_FILE; // check for required plugin symbols - void *ifunc = my_dlsym(dso,"vmdplugin_init"); - void *rfunc = my_dlsym(dso,"vmdplugin_register"); - void *ffunc = my_dlsym(dso,"vmdplugin_fini"); + void *ifunc = platform::dlsym(dso,"vmdplugin_init"); + void *rfunc = platform::dlsym(dso,"vmdplugin_register"); + void *ffunc = platform::dlsym(dso,"vmdplugin_fini"); if (ifunc == nullptr || rfunc == nullptr || ffunc == nullptr) { - my_dlclose(dso); + platform::dlclose(dso); return E_SYMBOL; } // initialize plugin. skip plugin if it fails. if (((initfunc)(ifunc))()) { - my_dlclose(dso); + platform::dlclose(dso); return E_SYMBOL; } @@ -528,12 +328,8 @@ int MolfileInterface::load_plugin(const char *filename) forget_plugin(); delete[] _name; - len = 16; - len += strlen(plugin->prettyname); - len += strlen(plugin->author); - _name = new char[len]; - sprintf(_name,"%s v%d.%d by %s",plugin->prettyname, - plugin->majorv, plugin->minorv, plugin->author); + _name = utils::strdup(fmt::format("{} v{}.{} by {}", plugin->prettyname, + plugin->majorv, plugin->minorv, plugin->author)); // determine plugin capabilities _caps = M_NONE; @@ -569,7 +365,7 @@ int MolfileInterface::load_plugin(const char *filename) } // better luck next time. clean up and return. - my_dlclose(dso); + platform::dlclose(dso); return retval; } @@ -583,10 +379,10 @@ void MolfileInterface::forget_plugin() _plugin = nullptr; if (_dso) { - void *ffunc = my_dlsym(_dso,"vmdplugin_fini"); + void *ffunc = platform::dlsym(_dso,"vmdplugin_fini"); if (ffunc) ((finifunc)ffunc)(); - my_dlclose(_dso); + platform::dlclose(_dso); } _dso = nullptr; diff --git a/src/MOLFILE/reader_molfile.cpp b/src/MOLFILE/reader_molfile.cpp index e04b615018..5f75ae50f5 100644 --- a/src/MOLFILE/reader_molfile.cpp +++ b/src/MOLFILE/reader_molfile.cpp @@ -85,13 +85,7 @@ void ReaderMolfile::settings(int narg, char **arg) if (mf->find_plugin(path)!= MFI::E_MATCH) error->one(FLERR,"No suitable molfile plugin found"); - if (screen) - fprintf(screen,"Dump reader uses molfile plugin: %s\n", - mf->get_plugin_name()); - - if (logfile) - fprintf(logfile,"Dump reader uses molfile plugin: %s\n", - mf->get_plugin_name()); + utils::logmesg(lmp,"Dump reader uses molfile plugin: {}\n", mf->get_plugin_name()); } } @@ -100,30 +94,22 @@ void ReaderMolfile::settings(int narg, char **arg) only called by proc 0 ------------------------------------------------------------------------- */ -void ReaderMolfile::open_file(const char *file) +void ReaderMolfile::open_file(const std::string &file) { int rv; - char str[1024]; // close open file, if needed. if (mf->is_open()) mf->close(); - rv = mf->open(file,&natoms); + rv = mf->open(file.c_str(),&natoms); - if (rv != MFI::E_NONE) { - snprintf(str,1024,"Cannot open file %s",file); - error->one(FLERR,str); - } + if (rv != MFI::E_NONE) error->one(FLERR,"Cannot open file {}", file); - if (natoms < 1) { - snprintf(str,1024,"No atoms in file %s",file); - error->one(FLERR,str); - } + if (natoms < 1) error->one(FLERR,"No atoms in file {}", file); memory->create(types,natoms,"reader:types"); memory->create(coords,3*natoms,"reader:coords"); - if (mf->has_vels()) - memory->create(vels,3*natoms,"reader:vels"); + if (mf->has_vels()) memory->create(vels,3*natoms,"reader:vels"); // initialize system properties, if available if (mf->has_props()) { diff --git a/src/MOLFILE/reader_molfile.h b/src/MOLFILE/reader_molfile.h index 1f7fead9c0..4330eaf4eb 100644 --- a/src/MOLFILE/reader_molfile.h +++ b/src/MOLFILE/reader_molfile.h @@ -39,7 +39,7 @@ class ReaderMolfile : public Reader { int &, int &, int &); virtual void read_atoms(int, int, double **); - virtual void open_file(const char *); + virtual void open_file(const std::string &); virtual void close_file(); private: diff --git a/src/MPIIO/dump_xyz_mpiio.cpp b/src/MPIIO/dump_xyz_mpiio.cpp index 24fd130e3d..f322a0da58 100644 --- a/src/MPIIO/dump_xyz_mpiio.cpp +++ b/src/MPIIO/dump_xyz_mpiio.cpp @@ -16,17 +16,18 @@ Contributing author: Paul Coffman (IBM) ------------------------------------------------------------------------- */ -#include "omp_compat.h" #include "dump_xyz_mpiio.h" -#include -#include -#include "domain.h" -#include "update.h" #include "compute.h" -#include "memory.h" +#include "domain.h" #include "error.h" +#include "memory.h" +#include "update.h" +#include +#include + +#include "omp_compat.h" #if defined(_OPENMP) #include #endif diff --git a/src/MSCG/fix_mscg.cpp b/src/MSCG/fix_mscg.cpp index 0d420cace8..1aa644b976 100644 --- a/src/MSCG/fix_mscg.cpp +++ b/src/MSCG/fix_mscg.cpp @@ -18,9 +18,6 @@ #include "fix_mscg.h" -#include - -#include "mscg.h" #include "atom.h" #include "comm.h" #include "domain.h" @@ -35,6 +32,10 @@ #include "update.h" #include "variable.h" +#include + +#include "mscg.h" + using namespace LAMMPS_NS; using namespace FixConst; @@ -49,8 +50,7 @@ FixMSCG::FixMSCG(LAMMPS *lmp, int narg, char **arg) : me = comm->me; nprocs = comm->nprocs; - if (nprocs > 1) error->all(FLERR,"Fix mscg does not yet support " - "parallel use via MPI"); + if (nprocs > 1) error->all(FLERR,"Fix mscg does not yet support parallel use via MPI"); if (sizeof(tagint) != sizeof(smallint)) error->all(FLERR,"Fix mscg must be used with 32-bit atom IDs"); @@ -77,11 +77,7 @@ FixMSCG::FixMSCG(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"range") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix mscg command"); - if (strcmp(arg[iarg+1],"on") == 0) - range_flag = 1; - else if (strcmp(arg[iarg+1],"off") == 0) - range_flag = 0; - else error->all(FLERR,"Illegal fix mscg command"); + range_flag = utils::logical(FLERR, arg[iarg+1], false, lmp); iarg += 2; } else if (strcmp(arg[iarg],"name") == 0) { if (iarg+ntypes+1 > narg) @@ -89,23 +85,23 @@ FixMSCG::FixMSCG(LAMMPS *lmp, int narg, char **arg) : name_flag = 1; for (int i = 0; i < ntypes; i++) { iarg += 1; - std::string str = arg[iarg]; - type_names[i] = strcat(strdup(str.c_str()),"\0"); + delete[] type_names[i]; + type_names[i] = utils::strdup(arg[iarg]); } iarg += 1; } else if (strcmp(arg[iarg],"max") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal fix mscg command"); - max_partners_bond = atoi(arg[iarg+1]); - max_partners_angle = atoi(arg[iarg+2]); - max_partners_dihedral = atoi(arg[iarg+3]); + max_partners_bond = utils::inumeric(FLERR,arg[iarg+1],false, lmp); + max_partners_angle = utils::inumeric(FLERR,arg[iarg+2],false, lmp); + max_partners_dihedral = utils::inumeric(FLERR,arg[iarg+3],false, lmp); iarg += 4; } else error->all(FLERR,"Illegal fix mscg command"); } if (name_flag == 0) { for (int i = 0; i < natoms; i++) { - std::string str = std::to_string(i+1); - type_names[i] = strcat(strdup(str.c_str()),"\0"); + delete[] type_names[i]; + type_names[i] = utils::strdup(std::to_string(i+1)); } } } @@ -114,6 +110,9 @@ FixMSCG::FixMSCG(LAMMPS *lmp, int narg, char **arg) : FixMSCG::~FixMSCG() { + int natoms = atom->natoms; + for (int i = 0; i < natoms; i++) delete[] type_names[i]; + delete[] type_names; memory->destroy(f); } @@ -141,14 +140,14 @@ void FixMSCG::post_constructor() tagint *tag = atom->tag; int *type = atom->type; int *num_bond = atom->num_bond; - int **bond_atom = atom->bond_atom; + tagint **bond_atom = atom->bond_atom; int *num_angle = atom->num_angle; - int **angle_atom1 = atom->angle_atom1; - int **angle_atom3 = atom->angle_atom3; + tagint **angle_atom1 = atom->angle_atom1; + tagint **angle_atom3 = atom->angle_atom3; int *num_dihedral = atom->num_dihedral; - int **dihedral_atom1 = atom->dihedral_atom1; - int **dihedral_atom3 = atom->dihedral_atom3; - int **dihedral_atom4 = atom->dihedral_atom4; + tagint **dihedral_atom1 = atom->dihedral_atom1; + tagint **dihedral_atom3 = atom->dihedral_atom3; + tagint **dihedral_atom4 = atom->dihedral_atom4; double *prd_half = domain->prd_half; int i,ii,j,jj,jnum,k,l; @@ -321,8 +320,7 @@ void FixMSCG::post_run() if (nframes != n_frames) error->warning(FLERR,"Fix mscg n_frames is inconsistent with control.in"); if (nframes % block_size != 0) - error->warning(FLERR,"Fix mscg n_frames is not divisible by " - "block_size in control.in"); + error->warning(FLERR,"Fix mscg n_frames is not divisible by block_size in control.in"); if (range_flag) rangefinder_solve_and_output(mscg_struct); diff --git a/src/Makefile b/src/Makefile index 4e6fb5cea9..7f02c1e84b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -260,12 +260,11 @@ uppercase_internal=$(if $1,$$(subst $(firstword $1),$(call uppercase_internal,$( uppercase=$(eval uppercase_RESULT:=$(call uppercase_internal,$(uppercase_TABLE),$1))$(uppercase_RESULT) PACKAGEUC = $(call uppercase,$(PACKAGE)) -PACKUSERUC = $(call uppercase,$(PACKUSER)) +PACKAGESORTED = $(sort $(PACKAGEUC)) YESDIR = $(call uppercase,$(@:yes-%=%)) NODIR = $(call uppercase,$(@:no-%=%)) LIBDIR = $(@:lib-%=%) -LIBUSERDIR = $(@:lib-%=%) # List of all targets @@ -332,7 +331,7 @@ lmpinstalledpkgs.h: $(SRC) $(INC) @echo '#ifndef LMP_INSTALLED_PKGS_H' > ${TMPNAME}.lmpinstalled @echo '#define LMP_INSTALLED_PKGS_H' >> ${TMPNAME}.lmpinstalled @echo 'const char * LAMMPS_NS::LAMMPS::installed_packages[] = {' >> ${TMPNAME}.lmpinstalled - @for p in $(PACKAGEUC) $(PACKUSERUC); do info=$$($(SHELL) Package.sh $$p installed); \ + @for p in $(PACKAGEUC); do info=$$($(SHELL) Package.sh $$p installed); \ [ -n "$$info" ] && echo "\"$$info\"" | sed -e 's/".*package \(.*\)"/"\1",/' >> ${TMPNAME}.lmpinstalled || :; done @echo ' NULL };' >> ${TMPNAME}.lmpinstalled @echo '#endif' >> ${TMPNAME}.lmpinstalled @@ -469,7 +468,7 @@ tar: @cd ..; tar cvzf src/$(ROOT)_src.tar.gz \ src/Make* src/Package.sh src/Depend.sh src/Install.sh src/Fetch.sh \ src/MAKE src/DEPEND src/*.cpp src/*.h src/STUBS \ - $(patsubst %,src/%,$(PACKAGEUC)) $(patsubst %,src/%,$(PACKUSERUC)) \ + $(patsubst %,src/%,$(PACKAGEUC)) \ --exclude=*/.svn @cd STUBS; $(MAKE) @echo "Created $(ROOT)_src.tar.gz" @@ -502,9 +501,7 @@ format-tests: # Package management package: - @echo 'Standard packages:' $(PACKAGE) - @echo '' - @echo 'User-contributed packages:' $(PACKUSER) + @echo 'Available packages:' $(PACKAGE) @echo '' @echo 'Packages that need system libraries:' $(PACKSYS) @echo '' @@ -615,9 +612,6 @@ lib-%: @if [ -e ../lib/$(LIBDIR)/Install.py ]; then \ echo "Installing lib $(@:lib-%=%)"; \ ( cd ../lib/$(LIBDIR); $(PYTHON) Install.py $(args) ); \ - elif [ -e ../lib/$(LIBUSERDIR)/Install.py ]; then \ - echo "Installing lib $(@:lib-%=%)"; \ - ( cd ../lib/$(LIBUSERDIR); $(PYTHON) Install.py $(args) ); \ else \ echo "Install script for lib $(@:lib-%=%) does not exist"; \ fi; touch main.cpp @@ -630,28 +624,21 @@ lib-%: # purge = delete obsolete and auto-generated package files package-status ps: - @for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p status; done - @echo '' - @for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p status; done + @for p in $(PACKAGESORTED); do $(SHELL) Package.sh $$p status; done package-installed pi: - @for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p installed; done - @for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p installed; done + @for p in $(PACKAGESORTED); do $(SHELL) Package.sh $$p installed; done package-update pu: purge + @echo 'Updating installed packages:' @for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p update; done - @echo '' - @for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p update; done package-overwrite: purge - @for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p overwrite; done - @echo '' - @for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p overwrite; done + @echo 'Overwriting installed packages:' + @for p in $(PACKAGESORTED); do $(SHELL) Package.sh $$p overwrite; done package-diff pd: - @for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p diff; done - @echo '' - @for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p diff; done + @for p in $(PACKAGESORTED); do $(SHELL) Package.sh $$p diff; done purge: Purge.list @echo 'Purging obsolete and auto-generated source files' diff --git a/src/NETCDF/dump_netcdf.cpp b/src/NETCDF/dump_netcdf.cpp index cd7783a0aa..5f30c941ca 100644 --- a/src/NETCDF/dump_netcdf.cpp +++ b/src/NETCDF/dump_netcdf.cpp @@ -274,7 +274,7 @@ void DumpNetCDF::openfile() if (append_flag && !multifile) { // Fixme! Perform checks if dimensions and variables conform with // data structure standard. - if (not utils::file_is_readable(filecurrent)) + if (!platform::file_is_readable(filecurrent)) error->all(FLERR, "cannot append to non-existent file {}",filecurrent); if (singlefile_opened) return; @@ -871,19 +871,13 @@ int DumpNetCDF::modify_param(int narg, char **arg) int iarg = 0; if (strcmp(arg[iarg],"double") == 0) { iarg++; - if (iarg >= narg) - error->all(FLERR,"expected 'yes' or 'no' after 'double' keyword."); - if (strcmp(arg[iarg],"yes") == 0) { - double_precision = true; - } else if (strcmp(arg[iarg],"no") == 0) { - double_precision = false; - } else error->all(FLERR,"expected 'yes' or 'no' after 'double' keyword."); + if (iarg >= narg) error->all(FLERR,"expected 'yes' or 'no' after 'double' keyword."); + double_precision = utils::logical(FLERR,arg[iarg],false,lmp) == 1; iarg++; return 2; } else if (strcmp(arg[iarg],"at") == 0) { iarg++; - if (iarg >= narg) - error->all(FLERR,"expected additional arg after 'at' keyword."); + if (iarg >= narg) error->all(FLERR,"expected additional arg after 'at' keyword."); framei = utils::inumeric(FLERR,arg[iarg],false,lmp); if (framei == 0) error->all(FLERR,"frame 0 not allowed for 'at' keyword."); else if (framei < 0) framei--; @@ -891,13 +885,8 @@ int DumpNetCDF::modify_param(int narg, char **arg) return 2; } else if (strcmp(arg[iarg],"thermo") == 0) { iarg++; - if (iarg >= narg) - error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword."); - if (strcmp(arg[iarg],"yes") == 0) { - thermo = true; - } else if (strcmp(arg[iarg],"no") == 0) { - thermo = false; - } else error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword."); + if (iarg >= narg) error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword."); + thermo = utils::logical(FLERR,arg[iarg],false,lmp) == 1; iarg++; return 2; } else return 0; diff --git a/src/NETCDF/dump_netcdf_mpiio.cpp b/src/NETCDF/dump_netcdf_mpiio.cpp index 4179b362c8..0a76203f96 100644 --- a/src/NETCDF/dump_netcdf_mpiio.cpp +++ b/src/NETCDF/dump_netcdf_mpiio.cpp @@ -272,7 +272,7 @@ void DumpNetCDFMPIIO::openfile() if (append_flag && !multifile) { // Fixme! Perform checks if dimensions and variables conform with // data structure standard. - if (not utils::file_is_readable(filecurrent)) + if (!platform::file_is_readable(filecurrent)) error->all(FLERR, "cannot append to non-existent file {}", filecurrent); MPI_Offset index[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS]; @@ -866,19 +866,13 @@ int DumpNetCDFMPIIO::modify_param(int narg, char **arg) int iarg = 0; if (strcmp(arg[iarg],"double") == 0) { iarg++; - if (iarg >= narg) - error->all(FLERR,"expected 'yes' or 'no' after 'double' keyword."); - if (strcmp(arg[iarg],"yes") == 0) { - double_precision = true; - } else if (strcmp(arg[iarg],"no") == 0) { - double_precision = false; - } else error->all(FLERR,"expected 'yes' or 'no' after 'double' keyword."); + if (iarg >= narg) error->all(FLERR,"expected 'yes' or 'no' after 'double' keyword."); + double_precision = utils::logical(FLERR,arg[iarg],false,lmp) == 1; iarg++; return 2; } else if (strcmp(arg[iarg],"at") == 0) { iarg++; - if (iarg >= narg) - error->all(FLERR,"expected additional arg after 'at' keyword."); + if (iarg >= narg) error->all(FLERR,"expected additional arg after 'at' keyword."); framei = utils::inumeric(FLERR,arg[iarg],false,lmp); if (framei == 0) error->all(FLERR,"frame 0 not allowed for 'at' keyword."); else if (framei < 0) framei--; @@ -886,13 +880,8 @@ int DumpNetCDFMPIIO::modify_param(int narg, char **arg) return 2; } else if (strcmp(arg[iarg],"thermo") == 0) { iarg++; - if (iarg >= narg) - error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword."); - if (strcmp(arg[iarg],"yes") == 0) { - thermo = true; - } else if (strcmp(arg[iarg],"no") == 0) { - thermo = false; - } else error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword."); + if (iarg >= narg) error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword."); + thermo = utils::logical(FLERR,arg[iarg],false,lmp) == 1; iarg++; return 2; } else return 0; diff --git a/src/OPENMP/fix_omp.cpp b/src/OPENMP/fix_omp.cpp index 2b7e7eeaf9..ec5b1d5be0 100644 --- a/src/OPENMP/fix_omp.cpp +++ b/src/OPENMP/fix_omp.cpp @@ -99,9 +99,7 @@ FixOMP::FixOMP(LAMMPS *lmp, int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"neigh") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package omp command"); - if (strcmp(arg[iarg+1],"yes") == 0) _neighbor = true; - else if (strcmp(arg[iarg+1],"no") == 0) _neighbor = false; - else error->all(FLERR,"Illegal package omp command"); + _neighbor = utils::logical(FLERR,arg[iarg+1],false,lmp) != 0; iarg += 2; } else error->all(FLERR,"Illegal package omp command"); } diff --git a/src/OPENMP/npair_half_size_multi_newton_omp.cpp b/src/OPENMP/npair_half_size_multi_newton_omp.cpp index cdc68e1b42..bcf87d385c 100644 --- a/src/OPENMP/npair_half_size_multi_newton_omp.cpp +++ b/src/OPENMP/npair_half_size_multi_newton_omp.cpp @@ -108,7 +108,7 @@ void NPairHalfSizeMultiNewtonOmp::build(NeighList *list) // if j is ghost, only store if j coords are "above and to the right" of i for (j = js; j >= 0; j = bins[j]) { - if(icollection != jcollection and j < i) continue; + if(icollection != jcollection && j < i) continue; if (j >= nlocal) { if (x[j][2] < ztmp) continue; diff --git a/src/ORIENT/fix_orient_eco.cpp b/src/ORIENT/fix_orient_eco.cpp index 6ec4e278ec..55486adc37 100644 --- a/src/ORIENT/fix_orient_eco.cpp +++ b/src/ORIENT/fix_orient_eco.cpp @@ -550,7 +550,7 @@ int FixOrientECO::get_norm() { squared_distance = delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]; // check if atom is within cutoff region - if ((squared_distance != 0.0) and (squared_distance < squared_cutoff)) { + if ((squared_distance != 0.0) && (squared_distance < squared_cutoff)) { ++neigh; squared_distance *= inv_squared_cutoff; diff --git a/src/PHONON/dynamical_matrix.cpp b/src/PHONON/dynamical_matrix.cpp index 810111998e..e236e24a15 100644 --- a/src/PHONON/dynamical_matrix.cpp +++ b/src/PHONON/dynamical_matrix.cpp @@ -55,9 +55,12 @@ DynamicalMatrix::DynamicalMatrix(LAMMPS *lmp) : Command(lmp), fp(nullptr) DynamicalMatrix::~DynamicalMatrix() { - if (fp && me == 0) fclose(fp); + if (fp && me == 0) { + if (compressed) platform::pclose(fp); + else fclose(fp); memory->destroy(groupmap); fp = nullptr; + } } /* ---------------------------------------------------------------------- @@ -181,64 +184,55 @@ void DynamicalMatrix::command(int narg, char **arg) void DynamicalMatrix::options(int narg, char **arg) { - if (narg < 0) error->all(FLERR,"Illegal dynamical_matrix command"); - int iarg = 0; - const char* filename = "dynmat.dyn"; - while (iarg < narg) { - if (strcmp(arg[iarg],"binary") == 0) { - if (iarg + 2 > narg) error->all(FLERR, "Illegal dynamical_matrix command"); - if (strcmp(arg[iarg+1],"gzip") == 0) { - compressed = 1; - } - else if (strcmp(arg[iarg+1],"yes") == 0) { - binaryflag = 1; - } - iarg += 2; - } - else if (strcmp(arg[iarg],"file") == 0) { - if (iarg+2 > narg) error->all(FLERR, "Illegal dynamical_matrix command"); - filename = arg[iarg + 1]; - file_flag = 1; - iarg += 2; - } else error->all(FLERR,"Illegal dynamical_matrix command"); - } - if (file_flag == 1) { - openfile(filename); - } + if (narg < 0) error->all(FLERR,"Illegal dynamical_matrix command"); + int iarg = 0; + const char* filename = "dynmat.dyn"; + + while (iarg < narg) { + if (strcmp(arg[iarg],"binary") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal dynamical_matrix command"); + if (strcmp(arg[iarg+1],"gzip") == 0) { + compressed = 1; + } else { + binaryflag = utils::logical(FLERR,arg[iarg+1],false,lmp); + } + iarg += 2; + } else if (strcmp(arg[iarg],"file") == 0) { + if (iarg+2 > narg) error->all(FLERR, "Illegal dynamical_matrix command"); + filename = arg[iarg + 1]; + file_flag = 1; + iarg += 2; + } else error->all(FLERR,"Illegal dynamical_matrix command"); + } + if (file_flag == 1) { + openfile(filename); + } } /* ---------------------------------------------------------------------- generic opening of a file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ -void DynamicalMatrix::openfile(const char* filename) +void DynamicalMatrix::openfile(const char *filename) { // if file already opened, return - //if (me!=0) return; if (file_opened) return; + fp = nullptr; - if (compressed) { -#ifdef LAMMPS_GZIP - char gzip[128]; - sprintf(gzip,"gzip -6 > %s",filename); -#ifdef _WIN32 - fp = _popen(gzip,"wb"); -#else - fp = popen(gzip,"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif - } else if (binaryflag) { + if (me == 0) { + if (compressed) { + fp = platform::compressed_write(std::string(filename)+".gz"); + if (!fp) error->one(FLERR,"Cannot open compressed file"); + } else if (binaryflag) { fp = fopen(filename,"wb"); - } else { + } else { fp = fopen(filename,"w"); + } + if (!fp) error->one(FLERR,"Cannot open dynmat file: {}", utils::getsyserror()); } - if (fp == nullptr) error->one(FLERR,"Cannot open dump file"); - file_opened = 1; } diff --git a/src/PHONON/third_order.cpp b/src/PHONON/third_order.cpp index e9add72267..3206882a4a 100644 --- a/src/PHONON/third_order.cpp +++ b/src/PHONON/third_order.cpp @@ -55,7 +55,10 @@ ThirdOrder::ThirdOrder(LAMMPS *lmp) : Command(lmp), fp(nullptr) ThirdOrder::~ThirdOrder() { - if (fp && me == 0) fclose(fp); + if (fp && me == 0) { + if (compressed) platform::pclose(fp); + else fclose(fp); + } fp = nullptr; memory->destroy(groupmap); } @@ -185,29 +188,29 @@ void ThirdOrder::options(int narg, char **arg) const char *filename = "third_order.dat"; while (iarg < narg) { - if (strcmp(arg[iarg],"file") == 0) { + if (strcmp(arg[iarg],"binary") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal third_order command"); + if (strcmp(arg[iarg+1],"gzip") == 0) { + compressed = 1; + } else { + binaryflag = utils::logical(FLERR,arg[iarg+1],false,lmp); + } + iarg += 2; + } else if (strcmp(arg[iarg],"file") == 0) { if (iarg+2 > narg) error->all(FLERR, "Illegal third_order command"); filename = arg[iarg + 1]; file_flag = 1; iarg += 2; - } else if (strcmp(arg[iarg],"binary") == 0) { - if (iarg + 2 > narg) error->all(FLERR, "Illegal third_order command"); - if (strcmp(arg[iarg+1],"gzip") == 0) { - compressed = 1; - } else if (strcmp(arg[iarg+1],"yes") == 0) { - binaryflag = 1; - } - iarg += 2; } else error->all(FLERR,"Illegal third_order command"); } - if (file_flag == 1 and me == 0) { + if (file_flag == 1 && me == 0) { openfile(filename); } } /* ---------------------------------------------------------------------- generic opening of a file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -215,27 +218,19 @@ void ThirdOrder::openfile(const char* filename) { // if file already opened, return if (file_opened) return; + fp = nullptr; - if (compressed) { -#ifdef LAMMPS_GZIP - char gzip[128]; - sprintf(gzip,"gzip -6 > %s",filename); -#ifdef _WIN32 - fp = _popen(gzip,"wb"); -#else - fp = popen(gzip,"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif - } else if (binaryflag) { - fp = fopen(filename,"wb"); - } else { - fp = fopen(filename,"w"); + if (me == 0) { + if (compressed) { + fp = platform::compressed_write(std::string(filename)+".gz"); + if (!fp) error->one(FLERR,"Cannot open compressed file"); + } else if (binaryflag) { + fp = fopen(filename,"wb"); + } else { + fp = fopen(filename,"w"); + } + if (!fp) error->one(FLERR,"Cannot open third_order file: {}", utils::getsyserror()); } - - if (fp == nullptr) error->one(FLERR,"Cannot open dump file"); - file_opened = 1; } diff --git a/src/PLUGIN/plugin.cpp b/src/PLUGIN/plugin.cpp index 270c9958f5..443fecc99f 100644 --- a/src/PLUGIN/plugin.cpp +++ b/src/PLUGIN/plugin.cpp @@ -25,12 +25,6 @@ #include #include -#ifdef _WIN32 -#include -#else -#include -#endif - namespace LAMMPS_NS { // list of plugin information data for loaded styles @@ -87,31 +81,28 @@ namespace LAMMPS_NS { #if defined(LMP_PLUGIN) int me = lmp->comm->me; -#if defined(WIN32) - lmp->error->all(FLERR,"Loading of plugins on Windows is not supported\n"); -#else // open DSO file from given path; load symbols globally - dlerror(); - void *dso = dlopen(file,RTLD_NOW|RTLD_GLOBAL); + platform::dlerror(); + void *dso = platform::dlopen(file); if (dso == nullptr) { if (me == 0) - utils::logmesg(lmp,"Open of file {} failed: {}\n",file,dlerror()); + utils::logmesg(lmp,"Open of file {} failed: {}\n",file,platform::dlerror()); return; } // look up lammpsplugin_init() function in DSO // function must have C bindings so there is no name mangling - dlerror(); - void *initfunc = dlsym(dso,"lammpsplugin_init"); + platform::dlerror(); + void *initfunc = platform::dlsym(dso,"lammpsplugin_init"); if (initfunc == nullptr) { - dlclose(dso); + platform::dlclose(dso); if (me == 0) utils::logmesg(lmp,"Plugin symbol lookup failure in file {}: {}\n", - file,dlerror()); + file,platform::dlerror()); return; } @@ -121,7 +112,6 @@ namespace LAMMPS_NS (*(lammpsplugin_initfunc)(initfunc))((void *)lmp, dso, (void *)&plugin_register); -#endif #endif } @@ -410,9 +400,7 @@ namespace LAMMPS_NS -- dso_refcounter[handle]; if (dso_refcounter[handle] == 0) { -#ifndef WIN32 - dlclose(handle); -#endif + platform::dlclose(handle); } #endif } diff --git a/src/PLUMED/fix_plumed.cpp b/src/PLUMED/fix_plumed.cpp index b38e745b7a..137cd580a8 100644 --- a/src/PLUMED/fix_plumed.cpp +++ b/src/PLUMED/fix_plumed.cpp @@ -41,7 +41,7 @@ #if defined(__PLUMED_DEFAULT_KERNEL) #define PLUMED_QUOTE_DIRECT(name) #name #define PLUMED_QUOTE(macro) PLUMED_QUOTE_DIRECT(macro) -static char plumed_default_kernel[] = "PLUMED_KERNEL=" PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL); +static const char plumed_default_kernel[] = "PLUMED_KERNEL=" PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL); #endif /* -------------------------------------------------------------------- */ @@ -68,7 +68,7 @@ FixPlumed::FixPlumed(LAMMPS *lmp, int narg, char **arg) : #if defined(__PLUMED_DEFAULT_KERNEL) if (getenv("PLUMED_KERNEL") == nullptr) - putenv(plumed_default_kernel); + platform::putenv(plumed_default_kernel); #endif p=new PLMD::Plumed; @@ -215,31 +215,13 @@ FixPlumed::FixPlumed(LAMMPS *lmp, int narg, char **arg) : // Define compute to calculate potential energy - id_pe = new char[8]; - strcpy(id_pe,"plmd_pe"); - char **newarg = new char*[3]; - newarg[0] = id_pe; - newarg[1] = (char *) "all"; - newarg[2] = (char *) "pe"; - modify->add_compute(3,newarg); - delete [] newarg; - int ipe = modify->find_compute(id_pe); - c_pe = modify->compute[ipe]; + id_pe = utils::strdup("plmd_pe"); + c_pe = modify->add_compute(std::string(id_pe) + " all pe"); // Define compute to calculate pressure tensor - id_press = new char[11]; - strcpy(id_press,"plmd_press"); - newarg = new char*[5]; - newarg[0] = id_press; - newarg[1] = (char *) "all"; - newarg[2] = (char *) "pressure"; - newarg[3] = (char *) "NULL"; - newarg[4] = (char *) "virial"; - modify->add_compute(5,newarg); - delete [] newarg; - int ipress = modify->find_compute(id_press); - c_press = modify->compute[ipress]; + id_press = utils::strdup("plmd_press"); + c_press = modify->add_compute(std::string(id_press) + " all pressure NULL virial"); for (int i = 0; i < modify->nfix; i++) { const char * const check_style = modify->fix[i]->style; diff --git a/src/Package.sh b/src/Package.sh index f776a02e48..aa217fb555 100755 --- a/src/Package.sh +++ b/src/Package.sh @@ -45,9 +45,8 @@ elif (test $2 = "installed") then # perform a re-install, but only if the package is already installed elif (test $2 = "update") then - echo "Updating src files from $1 package files" if (test $installed = 1) then - echo " updating package $1" + echo "Updating src files from $1 package files" if (test -e Install.sh) then /bin/sh Install.sh 2 else @@ -55,16 +54,14 @@ elif (test $2 = "update") then fi cd .. /bin/sh Depend.sh $1 - else - echo " $1 package is not installed" fi # overwrite, only if installed # overwrite package file with src file, if the two are different elif (test $2 = "overwrite") then - echo "Overwriting $1 package files with src files" if (test $installed = 1) then + echo "Overwriting $1 package files with src files" for file in *.cpp *.h; do if (test ! -e ../$file) then continue diff --git a/src/QEQ/fix_qeq.cpp b/src/QEQ/fix_qeq.cpp index a0d012bb5b..e2cae80dd4 100644 --- a/src/QEQ/fix_qeq.cpp +++ b/src/QEQ/fix_qeq.cpp @@ -767,7 +767,7 @@ void FixQEq::read_file(char *file) for (int n=nlo; n <= nhi; ++n) zcore[n] = val; for (int n=nlo; n <= nhi; ++n) setflag[n] = 1; } - } catch (EOFException &e) { + } catch (EOFException &) { ; // catch and ignore to exit loop } catch (std::exception &e) { error->one(FLERR,e.what()); diff --git a/src/QEQ/fix_qeq_dynamic.cpp b/src/QEQ/fix_qeq_dynamic.cpp index b8fc08dc14..06cfe0d0bd 100644 --- a/src/QEQ/fix_qeq_dynamic.cpp +++ b/src/QEQ/fix_qeq_dynamic.cpp @@ -56,9 +56,7 @@ FixQEqDynamic::FixQEqDynamic(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"warn") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix qeq/dynamic command"); - if (strcmp(arg[iarg+1],"no") == 0) maxwarn = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) maxwarn = 1; - else error->all(FLERR,"Illegal fix qeq/dynamic command"); + maxwarn = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix qeq/dynamic command"); } diff --git a/src/QEQ/fix_qeq_fire.cpp b/src/QEQ/fix_qeq_fire.cpp index eb206effc6..77a5ae36a1 100644 --- a/src/QEQ/fix_qeq_fire.cpp +++ b/src/QEQ/fix_qeq_fire.cpp @@ -66,9 +66,7 @@ FixQEqFire::FixQEqFire(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"warn") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix qeq/fire command"); - if (strcmp(arg[iarg+1],"no") == 0) maxwarn = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) maxwarn = 1; - else error->all(FLERR,"Illegal fix qeq/fire command"); + maxwarn = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix qeq/fire command"); } diff --git a/src/QEQ/fix_qeq_point.cpp b/src/QEQ/fix_qeq_point.cpp index e836c0dad8..3ad76b74d9 100644 --- a/src/QEQ/fix_qeq_point.cpp +++ b/src/QEQ/fix_qeq_point.cpp @@ -42,9 +42,7 @@ FixQEqPoint::FixQEqPoint(LAMMPS *lmp, int narg, char **arg) : FixQEq(lmp, narg, arg) { if (narg == 10) { if (strcmp(arg[8],"warn") == 0) { - if (strcmp(arg[9],"no") == 0) maxwarn = 0; - else if (strcmp(arg[9],"yes") == 0) maxwarn = 1; - else error->all(FLERR,"Illegal fix qeq/point command"); + maxwarn = utils::logical(FLERR,arg[9],false,lmp); } else error->all(FLERR,"Illegal fix qeq/point command"); } else if (narg > 8) error->all(FLERR,"Illegal fix qeq/point command"); } diff --git a/src/QEQ/fix_qeq_shielded.cpp b/src/QEQ/fix_qeq_shielded.cpp index 4cc254a361..8c1b95996b 100644 --- a/src/QEQ/fix_qeq_shielded.cpp +++ b/src/QEQ/fix_qeq_shielded.cpp @@ -43,9 +43,7 @@ FixQEqShielded::FixQEqShielded(LAMMPS *lmp, int narg, char **arg) : FixQEq(lmp, narg, arg) { if (narg == 10) { if (strcmp(arg[8],"warn") == 0) { - if (strcmp(arg[9],"no") == 0) maxwarn = 0; - else if (strcmp(arg[9],"yes") == 0) maxwarn = 1; - else error->all(FLERR,"Illegal fix qeq/shielded command"); + maxwarn = utils::logical(FLERR,arg[9],false,lmp); } else error->all(FLERR,"Illegal fix qeq/shielded command"); } else if (narg > 8) error->all(FLERR,"Illegal fix qeq/shielded command"); if (reax_flag) extract_reax(); diff --git a/src/QEQ/fix_qeq_slater.cpp b/src/QEQ/fix_qeq_slater.cpp index 4b4814d982..d491b301d5 100644 --- a/src/QEQ/fix_qeq_slater.cpp +++ b/src/QEQ/fix_qeq_slater.cpp @@ -55,9 +55,7 @@ FixQEqSlater::FixQEqSlater(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"warn") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix qeq/slater command"); - if (strcmp(arg[iarg+1],"no") == 0) maxwarn = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) maxwarn = 1; - else error->all(FLERR,"Illegal fix qeq/slater command"); + maxwarn = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix qeq/slater command"); } diff --git a/src/REACTION/fix_bond_react.cpp b/src/REACTION/fix_bond_react.cpp index 7b891d42fe..69c9c87ddf 100644 --- a/src/REACTION/fix_bond_react.cpp +++ b/src/REACTION/fix_bond_react.cpp @@ -179,24 +179,20 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) : int num_common_keywords = 2; for (int m = 0; m < num_common_keywords; m++) { if (strcmp(arg[iarg],"stabilization") == 0) { - if (strcmp(arg[iarg+1],"no") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix bond/react command: " - "'stabilization' keyword has too few arguments"); - iarg += 2; - } - if (strcmp(arg[iarg+1],"yes") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal fix bond/react command: " + "'stabilization' keyword has too few arguments"); + stabilization_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); + if (stabilization_flag) { if (iarg+4 > narg) error->all(FLERR,"Illegal fix bond/react command:" "'stabilization' keyword has too few arguments"); exclude_group = utils::strdup(arg[iarg+2]); - stabilization_flag = 1; nve_limit_xmax = arg[iarg+3]; iarg += 4; - } + } else iarg += 2; } else if (strcmp(arg[iarg],"reset_mol_ids") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix bond/react command: " "'reset_mol_ids' keyword has too few arguments"); - if (strcmp(arg[iarg+1],"yes") == 0) reset_mol_ids_flag = 1; // default - if (strcmp(arg[iarg+1],"no") == 0) reset_mol_ids_flag = 0; + reset_mol_ids_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"react") == 0) { break; @@ -914,7 +910,8 @@ void FixBondReact::post_integrate() int j; for (rxnID = 0; rxnID < nreacts; rxnID++) { - if (max_rxn[rxnID] <= reaction_count_total[rxnID]) continue; + if ((update->ntimestep % nevery[rxnID]) || + (max_rxn[rxnID] <= reaction_count_total[rxnID])) continue; for (int ii = 0; ii < nall; ii++) { partner[ii] = 0; finalpartner[ii] = 0; diff --git a/src/REAXFF/fix_reaxff_bonds.cpp b/src/REAXFF/fix_reaxff_bonds.cpp index f13056c5b6..740a32a0a6 100644 --- a/src/REAXFF/fix_reaxff_bonds.cpp +++ b/src/REAXFF/fix_reaxff_bonds.cpp @@ -45,30 +45,21 @@ FixReaxFFBonds::FixReaxFFBonds(LAMMPS *lmp, int narg, char **arg) : MPI_Comm_size(world,&nprocs); ntypes = atom->ntypes; nmax = atom->nmax; + compressed = 0; nevery = utils::inumeric(FLERR,arg[3],false,lmp); - if (nevery <= 0) - error->all(FLERR,"Illegal fix reaxff/bonds command"); + if (nevery <= 0) error->all(FLERR,"Illegal fix reaxff/bonds command"); if (me == 0) { - char *suffix = strrchr(arg[4],'.'); - if (suffix && strcmp(suffix,".gz") == 0) { -#ifdef LAMMPS_GZIP - auto gzip = fmt::format("gzip -6 > {}",arg[4]); -#ifdef _WIN32 - fp = _popen(gzip.c_str(),"wb"); -#else - fp = popen(gzip.c_str(),"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif + if (platform::has_compress_extension(arg[4])) { + compressed = 1; + fp = platform::compressed_write(arg[4]); + if (!fp) error->one(FLERR,"Cannot open compressed file"); } else fp = fopen(arg[4],"w"); - if (!fp) - error->one(FLERR,fmt::format("Cannot open fix reaxff/bonds file {}: " - "{}",arg[4],utils::getsyserror())); + if (!fp) error->one(FLERR,fmt::format("Cannot open fix reaxff/bonds file {}: " + "{}",arg[4],utils::getsyserror())); } if (atom->tag_consecutive() == 0) diff --git a/src/REAXFF/fix_reaxff_bonds.h b/src/REAXFF/fix_reaxff_bonds.h index 4c2fd535ea..4c40017e43 100644 --- a/src/REAXFF/fix_reaxff_bonds.h +++ b/src/REAXFF/fix_reaxff_bonds.h @@ -36,7 +36,7 @@ class FixReaxFFBonds : public Fix { void end_of_step(); protected: - int me, nprocs, nmax, ntypes, maxsize; + int me, nprocs, nmax, ntypes, maxsize, compressed; int *numneigh; tagint **neighid; double **abo; diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index 4fc08975a8..7bf6f34aa7 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -56,6 +56,7 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : size_peratom_cols = 0; peratom_freq = 1; + compressed = 0; nvalid = -1; MPI_Comm_rank(world,&me); @@ -106,23 +107,14 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : strcpy(tmparg[2],arg[5]); if (me == 0) { - char *suffix = strrchr(arg[6],'.'); - if (suffix && strcmp(suffix,".gz") == 0) { -#ifdef LAMMPS_GZIP - auto gzip = fmt::format("gzip -6 > {}",arg[6]); -#ifdef _WIN32 - fp = _popen(gzip.c_str(),"wb"); -#else - fp = popen(gzip.c_str(),"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif + if (platform::has_compress_extension(arg[6])) { + fp = platform::compressed_write(arg[6]); + compressed = 1; + if (!fp) error->one(FLERR,"Cannot open compressed file"); } else fp = fopen(arg[6],"w"); - if (!fp) - error->one(FLERR,fmt::format("Cannot open fix reaxff/species file {}: " - "{}",arg[6],utils::getsyserror())); + if (!fp) error->one(FLERR,fmt::format("Cannot open fix reaxff/species file {}: " + "{}",arg[6],utils::getsyserror())); } x0 = nullptr; @@ -256,8 +248,11 @@ FixReaxFFSpecies::~FixReaxFFSpecies() if (filepos) delete [] filepos; - if (me == 0) fclose(fp); - if (me == 0 && posflag && multipos_opened) fclose(pos); + if (me == 0) { + if (compressed) platform::pclose(fp); + else fclose(fp); + if (posflag && multipos_opened) fclose(pos); + } modify->delete_compute("SPECATOM"); modify->delete_fix("SPECBOND"); @@ -683,8 +678,7 @@ void FixReaxFFSpecies::OpenPos() char *ptr = strchr(filepos,'*'); *ptr = '\0'; if (padflag == 0) - sprintf(filecurrent,"%s" BIGINT_FORMAT "%s", - filepos,ntimestep,ptr+1); + sprintf(filecurrent,"%s" BIGINT_FORMAT "%s",filepos,ntimestep,ptr+1); else { char bif[8],pad[16]; strcpy(bif,BIGINT_FORMAT); diff --git a/src/REAXFF/fix_reaxff_species.h b/src/REAXFF/fix_reaxff_species.h index bcfcf2b6dd..91326273b6 100644 --- a/src/REAXFF/fix_reaxff_species.h +++ b/src/REAXFF/fix_reaxff_species.h @@ -45,7 +45,7 @@ class FixReaxFFSpecies : public Fix { protected: int me, nprocs, nmax, nlocal, ntypes, ntotal; - int nrepeat, nfreq, posfreq; + int nrepeat, nfreq, posfreq, compressed; int Nmoltype, vector_nmole, vector_nspec; int *Name, *MolName, *NMol, *nd, *MolType, *molmap; double *clusterID; diff --git a/src/REAXFF/pair_reaxff.cpp b/src/REAXFF/pair_reaxff.cpp index 758ee70ab7..000209a606 100644 --- a/src/REAXFF/pair_reaxff.cpp +++ b/src/REAXFF/pair_reaxff.cpp @@ -39,7 +39,6 @@ #include #include -#include // for strcasecmp() #include "reaxff_api.h" @@ -227,21 +226,18 @@ void PairReaxFF::settings(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"checkqeq") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reaxff command"); + qeqflag = utils::logical(FLERR,arg[iarg+1],false,lmp); if (strcmp(arg[iarg+1],"yes") == 0) qeqflag = 1; else if (strcmp(arg[iarg+1],"no") == 0) qeqflag = 0; else error->all(FLERR,"Illegal pair_style reaxff command"); iarg += 2; } else if (strcmp(arg[iarg],"enobonds") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reaxff command"); - if (strcmp(arg[iarg+1],"yes") == 0) api->control->enobondsflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) api->control->enobondsflag = 0; - else error->all(FLERR,"Illegal pair_style reaxff command"); + api->control->enobondsflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"lgvdw") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reaxff command"); - if (strcmp(arg[iarg+1],"yes") == 0) api->control->lgflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) api->control->lgflag = 0; - else error->all(FLERR,"Illegal pair_style reaxff command"); + api->control->lgflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"safezone") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reaxff command"); @@ -302,7 +298,7 @@ void PairReaxFF::coeff(int nargs, char **args) // pair_coeff element map for (int i = 3; i < nargs; i++) for (int j = 0; j < nreax_types; j++) - if (strcasecmp(args[i],api->system->reax_param.sbp[j].name) == 0) { + if (utils::lowercase(args[i]) == utils::lowercase(api->system->reax_param.sbp[j].name)) { map[i-2] = j; itmp ++; } diff --git a/src/REAXFF/reaxff_ffield.cpp b/src/REAXFF/reaxff_ffield.cpp index 6297f4cf94..f3f9bf6a00 100644 --- a/src/REAXFF/reaxff_ffield.cpp +++ b/src/REAXFF/reaxff_ffield.cpp @@ -32,7 +32,6 @@ #include "text_file_reader.h" #include "utils.h" -#include #include #include #include @@ -40,6 +39,7 @@ using LAMMPS_NS::utils::open_potential; using LAMMPS_NS::utils::getsyserror; +using LAMMPS_NS::utils::uppercase; namespace ReaxFF { @@ -161,11 +161,10 @@ namespace ReaxFF { if (values.count() < 9) THROW_ERROR("Invalid force field file format"); - auto element = values.next_string(); - int len = MIN(element.size(),3); // truncate stored element symbol if necessary - for (j = 0; j < len; ++j) - sbp[i].name[j] = toupper(element[j]); - sbp[i].name[len] = '\0'; + // copy element symbol in uppercase and truncate stored element symbol if necessary + auto element = uppercase(values.next_string()); + strncpy(sbp[i].name,element.c_str(),4); + sbp[i].name[3] = '\0'; sbp[i].r_s = values.next_double(); sbp[i].valency = values.next_double(); diff --git a/src/REPLICA/fix_hyper_local.cpp b/src/REPLICA/fix_hyper_local.cpp index 4a477fad8d..ba91644c53 100644 --- a/src/REPLICA/fix_hyper_local.cpp +++ b/src/REPLICA/fix_hyper_local.cpp @@ -447,7 +447,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) int *ilist,*jlist,*numneigh,**firstneigh; //double time1,time2,time3,time4,time5,time6,time7,time8; - //time1 = MPI_Wtime(); + //time1 = platform::walltime(); nostrainyet = 0; @@ -520,7 +520,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) maxhalfstrain[iold] = halfstrain; } - //time2 = MPI_Wtime(); + //time2 = platform::walltime(); // reverse comm acquires maxstrain of all current owned atoms // needed b/c only saw half the bonds of each atom @@ -531,7 +531,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) comm->reverse_comm_fix(this); comm->forward_comm_fix(this); - //time3 = MPI_Wtime(); + //time3 = platform::walltime(); // ------------------------------------------------------------- // stage 2: @@ -636,7 +636,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) maxstrain_domain[i] = emax; } - //time4 = MPI_Wtime(); + //time4 = platform::walltime(); // reverse comm to acquire maxstrain_domain from ghost atoms // needed b/c neigh list may refer to old owned atoms that are now ghost @@ -646,7 +646,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) comm->reverse_comm_fix(this); comm->forward_comm_fix(this); - //time5 = MPI_Wtime(); + //time5 = platform::walltime(); // ------------------------------------------------------------- // stage 3: @@ -672,7 +672,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) bias[nbias++] = maxhalf[iold]; } - //time6 = MPI_Wtime(); + //time6 = platform::walltime(); // ------------------------------------------------------------- // stage 4: @@ -724,7 +724,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) // myboost += exp(beta * biascoeff[m]*vbias); } - //time7 = MPI_Wtime(); + //time7 = platform::walltime(); // ------------------------------------------------------------- // stage 5: @@ -887,7 +887,7 @@ void FixHyperLocal::build_bond_list(int natom) int *ilist,*jlist,*numneigh,**firstneigh; double time1,time2; - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (natom) { nevent++; @@ -1185,7 +1185,7 @@ void FixHyperLocal::build_bond_list(int natom) // DEBUG //if (me == 0) printf("TOTAL BOND COUNT = %ld\n",allbonds); - time2 = MPI_Wtime(); + time2 = platform::walltime(); if (firstflag) nnewbond = 0; else { diff --git a/src/REPLICA/neb.cpp b/src/REPLICA/neb.cpp index 9e6e32772d..8cfc4b5c24 100644 --- a/src/REPLICA/neb.cpp +++ b/src/REPLICA/neb.cpp @@ -94,7 +94,10 @@ NEB::~NEB() MPI_Comm_free(&roots); memory->destroy(all); delete[] rdist; - if (fp) fclose(fp); + if (fp) { + if (compressed) platform::pclose(fp); + else fclose(fp); + } } /* ---------------------------------------------------------------------- @@ -525,12 +528,12 @@ void NEB::readfile(char *file, int flag) if (flag == 0) { if (me_universe == 0) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } } else { if (me == 0 && ireplica) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } } @@ -539,28 +542,17 @@ void NEB::readfile(char *file, int flag) /* ---------------------------------------------------------------------- universe proc 0 opens NEB data file - test if gzipped + test if compressed ------------------------------------------------------------------------- */ void NEB::open(char *file) { compressed = 0; - char *suffix = file + strlen(file) - 3; - if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1; - if (!compressed) fp = fopen(file,"r"); - else { -#ifdef LAMMPS_GZIP - auto gunzip = std::string("gzip -c -d ") + file; -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif - } + if (platform::has_compress_extension(file)) { + compressed = 1; + fp = platform::compressed_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file"); + } else fp = fopen(file,"r"); if (fp == nullptr) error->one(FLERR,"Cannot open file {}: {}",file,utils::getsyserror()); diff --git a/src/REPLICA/tad.cpp b/src/REPLICA/tad.cpp index 9b6ecf0b0c..881ec1604c 100644 --- a/src/REPLICA/tad.cpp +++ b/src/REPLICA/tad.cpp @@ -710,7 +710,7 @@ void TAD::perform_neb(int ievent) // time_neb += timer->get_wall(Timer::TOTAL); MPI_Barrier(world); - double time_tmp = MPI_Wtime(); + double time_tmp = platform::walltime(); double dt_hold = update->dt; update->dt = dt_neb; @@ -718,7 +718,7 @@ void TAD::perform_neb(int ievent) update->dt = dt_hold; MPI_Barrier(world); - time_neb += MPI_Wtime() - time_tmp; + time_neb += platform::walltime() - time_tmp; if (universe->me == 0) { universe->ulogfile = ulogfile_lammps; diff --git a/src/RIGID/fix_rigid.cpp b/src/RIGID/fix_rigid.cpp index 6f3486945c..db9767d01e 100644 --- a/src/RIGID/fix_rigid.cpp +++ b/src/RIGID/fix_rigid.cpp @@ -535,9 +535,7 @@ FixRigid::FixRigid(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg],"reinit") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix rigid command"); - if (strcmp("yes",arg[iarg+1]) == 0) reinitflag = 1; - else if (strcmp("no",arg[iarg+1]) == 0) reinitflag = 0; - else error->all(FLERR,"Illegal fix rigid command"); + reinitflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"gravity") == 0) { diff --git a/src/RIGID/fix_rigid_small.cpp b/src/RIGID/fix_rigid_small.cpp index 40bfc3ce2d..7a30c8b1c9 100644 --- a/src/RIGID/fix_rigid_small.cpp +++ b/src/RIGID/fix_rigid_small.cpp @@ -227,17 +227,13 @@ FixRigidSmall::FixRigidSmall(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg],"reinit") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix rigid/small command"); - if (strcmp("yes",arg[iarg+1]) == 0) reinitflag = 1; - else if (strcmp("no",arg[iarg+1]) == 0) reinitflag = 0; - else error->all(FLERR,"Illegal fix rigid/small command"); + reinitflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"mol") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix rigid/small command"); int imol = atom->find_molecule(arg[iarg+1]); - if (imol == -1) - error->all(FLERR,"Molecule template ID for " - "fix rigid/small does not exist"); + if (imol == -1) error->all(FLERR,"Molecule template ID for fix rigid/small does not exist"); onemols = &atom->molecules[imol]; nmol = onemols[0]->nset; restart_file = 1; @@ -395,14 +391,14 @@ FixRigidSmall::FixRigidSmall(LAMMPS *lmp, int narg, char **arg) : // sets bodytag for owned atoms // body attributes are computed later by setup_bodies() - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); create_bodies(bodyID); if (customflag) delete [] bodyID; if (comm->me == 0) utils::logmesg(lmp," create bodies CPU = {:.3f} seconds\n", - MPI_Wtime()-time1); + platform::walltime()-time1); // set nlocal_body and allocate bodies I own diff --git a/src/RIGID/fix_shake.cpp b/src/RIGID/fix_shake.cpp index f1c1d30fc5..9e45ec13d8 100644 --- a/src/RIGID/fix_shake.cpp +++ b/src/RIGID/fix_shake.cpp @@ -222,13 +222,13 @@ FixShake::FixShake(LAMMPS *lmp, int narg, char **arg) : // identify all SHAKE clusters - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); find_clusters(); if (comm->me == 0) utils::logmesg(lmp," find clusters CPU = {:.3f} seconds\n", - MPI_Wtime()-time1); + platform::walltime()-time1); // initialize list of SHAKE clusters to constrain diff --git a/src/SHOCK/fix_msst.cpp b/src/SHOCK/fix_msst.cpp index e8430b6ab1..ae1d0f4cd5 100644 --- a/src/SHOCK/fix_msst.cpp +++ b/src/SHOCK/fix_msst.cpp @@ -129,9 +129,7 @@ FixMSST::FixMSST(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"dftb") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix msst command"); - if (strcmp(arg[iarg+1],"yes") == 0) dftb = 1; - else if (strcmp(arg[iarg+1],"yes") == 0) dftb = 0; - else error->all(FLERR,"Illegal fix msst command"); + dftb = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"beta") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix msst command"); @@ -152,8 +150,7 @@ FixMSST::FixMSST(LAMMPS *lmp, int narg, char **arg) : mesg += fmt::format(" Cell mass-like parameter qmass " "(units of mass^2/length^4) = {:.8g}\n", qmass); mesg += fmt::format(" Shock velocity = {:.8g}\n", velocity); - mesg += fmt::format(" Artificial viscosity " - "(units of mass/length/time) = {:.8g}\n", mu); + mesg += fmt::format(" Artificial viscosity (units of mass/length/time) = {:.8g}\n", mu); if (p0_set) mesg += fmt::format(" Initial pressure specified to be {:.8g}\n", p0); diff --git a/src/SMTBQ/pair_smtbq.cpp b/src/SMTBQ/pair_smtbq.cpp index 4b7a1f2ac5..8922173433 100644 --- a/src/SMTBQ/pair_smtbq.cpp +++ b/src/SMTBQ/pair_smtbq.cpp @@ -2426,7 +2426,7 @@ void PairSMTBQ::Charge() ilist = list->ilist; - if (me == 0) t_init = MPI_Wtime(); + if (me == 0) t_init = platform::walltime(); if (step == 0) cluster = 0; // --------------------------- @@ -2729,7 +2729,7 @@ void PairSMTBQ::Charge() printf (" convergence : %f - %f\n",enegchk[gp],enegmax[gp]); } - t_end = MPI_Wtime(); + t_end = platform::walltime(); dt = t_end - t_init; printf (" temps dans charges : %f seconde. \n",dt); printf (" ======================================================== \n"); diff --git a/src/SPIN/fix_nve_spin.cpp b/src/SPIN/fix_nve_spin.cpp index c64609cfe3..970af9c4fb 100644 --- a/src/SPIN/fix_nve_spin.cpp +++ b/src/SPIN/fix_nve_spin.cpp @@ -71,7 +71,7 @@ FixNVESpin::FixNVESpin(LAMMPS *lmp, int narg, char **arg) : { if (lmp->citeme) lmp->citeme->add(cite_fix_nve_spin); - if (narg < 4) error->all(FLERR,"Illegal fix/NVE/spin command"); + if (narg < 4) error->all(FLERR,"Illegal fix/nve/spin command"); time_integrate = 1; sector_flag = NONE; @@ -86,7 +86,7 @@ FixNVESpin::FixNVESpin(LAMMPS *lmp, int narg, char **arg) : // checking if map array or hash is defined if (atom->map_style == Atom::MAP_NONE) - error->all(FLERR,"Fix NVE/spin requires an atom map, see atom_modify"); + error->all(FLERR,"Fix nve/spin requires an atom map, see atom_modify"); // defining sector_flag @@ -95,7 +95,7 @@ FixNVESpin::FixNVESpin(LAMMPS *lmp, int narg, char **arg) : sector_flag = 0; } else if (nprocs_tmp >= 1) { sector_flag = 1; - } else error->all(FLERR,"Illegal fix/NVE/spin command"); + } else error->all(FLERR,"Illegal fix/nve/spin command"); // defining lattice_flag @@ -105,25 +105,26 @@ FixNVESpin::FixNVESpin(LAMMPS *lmp, int narg, char **arg) : int iarg = 3; while (iarg < narg) { if (strcmp(arg[iarg],"lattice") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix/NVE/spin command"); - if (strcmp(arg[iarg+1],"no") == 0) lattice_flag = 0; - else if (strcmp(arg[iarg+1],"frozen") == 0) lattice_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) lattice_flag = 1; - else if (strcmp(arg[iarg+1],"moving") == 0) lattice_flag = 1; - else error->all(FLERR,"Illegal fix/NVE/spin command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal fix/nve/spin command"); + const std::string latarg = arg[iarg+1]; + if ((latarg == "no") || (latarg == "off") || (latarg == "false") || (latarg == "frozen")) + lattice_flag = 0; + else if ((latarg == "yes") || (latarg == "on") || (latarg == "true") || (latarg == "moving")) + lattice_flag = 1; + else error->all(FLERR,"Illegal fix/nve/spin command"); iarg += 2; - } else error->all(FLERR,"Illegal fix/NVE/spin command"); + } else error->all(FLERR,"Illegal fix/nve/spin command"); } // check if the atom/spin style is defined if (!atom->sp_flag) - error->all(FLERR,"Fix NVE/spin requires atom/spin style"); + error->all(FLERR,"Fix nve/spin requires atom/spin style"); // check if sector_flag is correctly defined if (sector_flag == 0 && nprocs_tmp > 1) - error->all(FLERR,"Illegal fix/NVE/spin command"); + error->all(FLERR,"Illegal fix/nve/spin command"); // initialize the magnetic interaction flags @@ -307,7 +308,7 @@ void FixNVESpin::init() // setting the sector variables/lists nsectors = 0; - memory->create(rsec,3,"NVE/spin:rsec"); + memory->create(rsec,3,"nve/spin:rsec"); // perform the sectoring operation @@ -316,10 +317,10 @@ void FixNVESpin::init() // init. size of stacking lists (sectoring) nlocal_max = atom->nlocal; - memory->grow(stack_head,nsectors,"NVE/spin:stack_head"); - memory->grow(stack_foot,nsectors,"NVE/spin:stack_foot"); - memory->grow(backward_stacks,nlocal_max,"NVE/spin:backward_stacks"); - memory->grow(forward_stacks,nlocal_max,"NVE/spin:forward_stacks"); + memory->grow(stack_head,nsectors,"nve/spin:stack_head"); + memory->grow(stack_foot,nsectors,"nve/spin:stack_foot"); + memory->grow(backward_stacks,nlocal_max,"nve/spin:backward_stacks"); + memory->grow(forward_stacks,nlocal_max,"nve/spin:forward_stacks"); } /* ---------------------------------------------------------------------- */ @@ -391,7 +392,7 @@ void FixNVESpin::initial_integrate(int /*vflag*/) AdvanceSingleSpin(i); } } - } else error->all(FLERR,"Illegal fix NVE/spin command"); + } else error->all(FLERR,"Illegal fix nve/spin command"); // update x for all particles @@ -444,7 +445,7 @@ void FixNVESpin::initial_integrate(int /*vflag*/) AdvanceSingleSpin(i); } } - } else error->all(FLERR,"Illegal fix NVE/spin command"); + } else error->all(FLERR,"Illegal fix nve/spin command"); } @@ -468,8 +469,8 @@ void FixNVESpin::pre_neighbor() if (nlocal_max < nlocal) { // grow linked lists if necessary nlocal_max = nlocal; - memory->grow(backward_stacks,nlocal_max,"NVE/spin:backward_stacks"); - memory->grow(forward_stacks,nlocal_max,"NVE/spin:forward_stacks"); + memory->grow(backward_stacks,nlocal_max,"nve/spin:backward_stacks"); + memory->grow(forward_stacks,nlocal_max,"nve/spin:forward_stacks"); } for (int j = 0; j < nsectors; j++) { diff --git a/src/SPIN/neb_spin.cpp b/src/SPIN/neb_spin.cpp index fe24235a98..1c987f8e7e 100644 --- a/src/SPIN/neb_spin.cpp +++ b/src/SPIN/neb_spin.cpp @@ -79,7 +79,10 @@ NEBSpin::~NEBSpin() MPI_Comm_free(&roots); memory->destroy(all); delete[] rdist; - if (fp) fclose(fp); + if (fp) { + if (compressed) platform::pclose(fp); + else fclose(fp); + } } /* ---------------------------------------------------------------------- @@ -552,12 +555,12 @@ void NEBSpin::readfile(char *file, int flag) if (flag == 0) { if (me_universe == 0) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } } else { if (me == 0 && ireplica) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } } @@ -684,28 +687,16 @@ int NEBSpin::initial_rotation(double *spi, double *sploc, double fraction) /* ---------------------------------------------------------------------- universe proc 0 opens NEBSpin data file - test if gzipped + test if compressed ------------------------------------------------------------------------- */ void NEBSpin::open(char *file) { compressed = 0; - char *suffix = file + strlen(file) - 3; - if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1; - if (!compressed) fp = fopen(file,"r"); - else { -#ifdef LAMMPS_GZIP - auto gunzip = std::string("gzip -c -d ") + file; -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif - } + if (platform::has_compress_extension(file)) { + fp = platform::compressed_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file"); + } else fp = fopen(file,"r"); if (fp == nullptr) error->one(FLERR,"Cannot open file {}: {}",file,utils::getsyserror()); diff --git a/src/SPIN/pair_spin_exchange.cpp b/src/SPIN/pair_spin_exchange.cpp index 23553a9d94..329ad5e100 100644 --- a/src/SPIN/pair_spin_exchange.cpp +++ b/src/SPIN/pair_spin_exchange.cpp @@ -105,7 +105,6 @@ void PairSpinExchange::coeff(int narg, char **arg) // get exchange arguments from input command - int iarg = 7; const double rc = utils::numeric(FLERR,arg[3],false,lmp); const double j1 = utils::numeric(FLERR,arg[4],false,lmp); const double j2 = utils::numeric(FLERR,arg[5],false,lmp); @@ -113,13 +112,10 @@ void PairSpinExchange::coeff(int narg, char **arg) // read energy offset flag if specified + int iarg = 7; while (iarg < narg) { - if (strcmp(arg[7],"offset") == 0) { - if (strcmp(arg[8],"yes") == 0) { - e_offset = 1; - } else if (strcmp(arg[8],"no") == 0) { - e_offset = 0; - } else error->all(FLERR,"Incorrect args for pair coefficients"); + if (strcmp(arg[iarg],"offset") == 0) { + e_offset = utils::logical(FLERR, arg[iarg+1], false, lmp); iarg += 2; } else error->all(FLERR,"Incorrect args for pair coefficients"); } diff --git a/src/SPIN/pair_spin_exchange_biquadratic.cpp b/src/SPIN/pair_spin_exchange_biquadratic.cpp index 8bff5e1b1d..fb727e1939 100644 --- a/src/SPIN/pair_spin_exchange_biquadratic.cpp +++ b/src/SPIN/pair_spin_exchange_biquadratic.cpp @@ -121,12 +121,8 @@ void PairSpinExchangeBiquadratic::coeff(int narg, char **arg) // read energy offset flag if specified while (iarg < narg) { - if (strcmp(arg[10],"offset") == 0) { - if (strcmp(arg[11],"yes") == 0) { - e_offset = 1; - } else if (strcmp(arg[11],"no") == 0) { - e_offset = 0; - } else error->all(FLERR,"Incorrect args for pair coefficients"); + if (strcmp(arg[iarg],"offset") == 0) { + e_offset = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Incorrect args for pair coefficients"); } diff --git a/src/SRD/fix_srd.cpp b/src/SRD/fix_srd.cpp index 22fade7bf3..f1e17eaa24 100644 --- a/src/SRD/fix_srd.cpp +++ b/src/SRD/fix_srd.cpp @@ -142,12 +142,7 @@ FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg], "overlap") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix srd command"); - if (strcmp(arg[iarg + 1], "yes") == 0) - overlap = 1; - else if (strcmp(arg[iarg + 1], "no") == 0) - overlap = 0; - else - error->all(FLERR, "Illegal fix srd command"); + overlap = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg], "inside") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix srd command"); @@ -162,12 +157,7 @@ FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg], "exact") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix srd command"); - if (strcmp(arg[iarg + 1], "yes") == 0) - exactflag = 1; - else if (strcmp(arg[iarg + 1], "no") == 0) - exactflag = 0; - else - error->all(FLERR, "Illegal fix srd command"); + exactflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg], "radius") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix srd command"); @@ -206,12 +196,7 @@ FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : iarg += 3; } else if (strcmp(arg[iarg], "tstat") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix srd command"); - if (strcmp(arg[iarg + 1], "no") == 0) - tstat = 0; - else if (strcmp(arg[iarg + 1], "yes") == 0) - tstat = 1; - else - error->all(FLERR, "Illegal fix srd command"); + tstat = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg], "rescale") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix srd command"); diff --git a/src/STUBS/mpi.cpp b/src/STUBS/mpi.cpp index e5cd50629e..3f4cc5964f 100644 --- a/src/STUBS/mpi.cpp +++ b/src/STUBS/mpi.cpp @@ -21,7 +21,13 @@ #include #include #include + +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +#else #include +#endif /* data structure for double/int */ @@ -167,7 +173,7 @@ int MPI_Finalize() double MPI_Wtime() { -#if defined(_MSC_VER) +#if defined(_WIN32) double t; t = GetTickCount(); diff --git a/src/VORONOI/compute_voronoi_atom.cpp b/src/VORONOI/compute_voronoi_atom.cpp index 5808b8d17c..2be02e3d2a 100644 --- a/src/VORONOI/compute_voronoi_atom.cpp +++ b/src/VORONOI/compute_voronoi_atom.cpp @@ -109,15 +109,11 @@ ComputeVoronoi::ComputeVoronoi(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg], "neighbors") == 0) { if (iarg + 2 > narg) error->all(FLERR,"Illegal compute voronoi/atom command"); - if (strcmp(arg[iarg+1],"yes") == 0) faces_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) faces_flag = 0; - else error->all(FLERR,"Illegal compute voronoi/atom command"); + faces_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg], "peratom") == 0) { if (iarg + 2 > narg) error->all(FLERR,"Illegal compute voronoi/atom command"); - if (strcmp(arg[iarg+1],"yes") == 0) peratom_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) peratom_flag = 0; - else error->all(FLERR,"Illegal compute voronoi/atom command"); + peratom_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal compute voronoi/atom command"); diff --git a/src/VTK/dump_vtk.cpp b/src/VTK/dump_vtk.cpp index f323ce820f..a7aabe3f51 100644 --- a/src/VTK/dump_vtk.cpp +++ b/src/VTK/dump_vtk.cpp @@ -2070,9 +2070,7 @@ int DumpVTK::modify_param(int narg, char **arg) if (strcmp(arg[0],"binary") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command [binary]"); - if (strcmp(arg[1],"yes") == 0) binary = 1; - else if (strcmp(arg[1],"no") == 0) binary = 0; - else error->all(FLERR,"Illegal dump_modify command [binary]"); + binary = utils::logical(FLERR,arg[1],false,lmp); return 2; } diff --git a/src/atom.cpp b/src/atom.cpp index 43d2578828..9fe115f5aa 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -822,17 +822,13 @@ void Atom::modify_params(int narg, char **arg) if (strcmp(arg[iarg],"id") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command"); if (domain->box_exist) - error->all(FLERR, - "Atom_modify id command after simulation box is defined"); - if (strcmp(arg[iarg+1],"yes") == 0) tag_enable = 1; - else if (strcmp(arg[iarg+1],"no") == 0) tag_enable = 0; - else error->all(FLERR,"Illegal atom_modify command"); + error->all(FLERR,"Atom_modify id command after simulation box is defined"); + tag_enable = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"map") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command"); if (domain->box_exist) - error->all(FLERR, - "Atom_modify map command after simulation box is defined"); + error->all(FLERR,"Atom_modify map command after simulation box is defined"); if (strcmp(arg[iarg+1],"array") == 0) map_user = 1; else if (strcmp(arg[iarg+1],"hash") == 0) map_user = 2; else if (strcmp(arg[iarg+1],"yes") == 0) map_user = 3; diff --git a/src/balance.cpp b/src/balance.cpp index 06a3463db5..bd3ba007ef 100644 --- a/src/balance.cpp +++ b/src/balance.cpp @@ -259,7 +259,7 @@ void Balance::command(int narg, char **arg) // must reset atom map after exchange() since it clears it MPI_Barrier(world); - double start_time = MPI_Wtime(); + double start_time = platform::walltime(); lmp->init(); @@ -386,7 +386,7 @@ void Balance::command(int narg, char **arg) if (me == 0) { std::string mesg = fmt::format(" rebalancing time: {:.3f} seconds\n", - MPI_Wtime()-start_time); + platform::walltime()-start_time); mesg += fmt::format(" iteration count = {}\n",niter); for (int i = 0; i < nimbalance; ++i) mesg += imbalances[i]->info(); mesg += fmt::format(" initial/final maximal load/proc = {:.8} {:.8}\n" diff --git a/src/bond.cpp b/src/bond.cpp index e636ae9bf8..fb313f0170 100644 --- a/src/bond.cpp +++ b/src/bond.cpp @@ -270,7 +270,7 @@ void Bond::write_file(int narg, char **arg) // write out a line with "DATE:" and "UNITS:" tags // - if the file already exists, print a message about appending // while printing the date and check that units are consistent. - if (utils::file_is_readable(table_file)) { + if (platform::file_is_readable(table_file)) { std::string units = utils::get_potential_units(table_file,"table"); if (!units.empty() && (units != update->unit_style)) { error->one(FLERR,"Trying to append to a table file with UNITS: {} while units are {}", diff --git a/src/comm.cpp b/src/comm.cpp index f79c48ace1..afe074cb5c 100644 --- a/src/comm.cpp +++ b/src/comm.cpp @@ -395,9 +395,7 @@ void Comm::modify_params(int narg, char **arg) iarg += 1; } else if (strcmp(arg[iarg],"vel") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal comm_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) ghost_velocity = 1; - else if (strcmp(arg[iarg+1],"no") == 0) ghost_velocity = 0; - else error->all(FLERR,"Illegal comm_modify command"); + ghost_velocity = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal comm_modify command"); } diff --git a/src/compute.cpp b/src/compute.cpp index 76a953484b..ba1d53e7c3 100644 --- a/src/compute.cpp +++ b/src/compute.cpp @@ -128,9 +128,7 @@ void Compute::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"dynamic") == 0 || strcmp(arg[iarg],"dynamic/dof") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute_modify command"); - if (strcmp(arg[iarg+1],"no") == 0) dynamic_user = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) dynamic_user = 1; - else error->all(FLERR,"Illegal compute_modify command"); + dynamic_user = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal compute_modify command"); } diff --git a/src/compute_angle_local.cpp b/src/compute_angle_local.cpp index 7401d8b214..2bceb91dd5 100644 --- a/src/compute_angle_local.cpp +++ b/src/compute_angle_local.cpp @@ -194,7 +194,7 @@ void ComputeAngleLocal::compute_local() int ComputeAngleLocal::compute_angles(int flag) { - int i,m,n,na,atom1,atom2,atom3,imol,iatom,atype,ivar; + int i,m,na,atom1,atom2,atom3,imol,iatom,atype,ivar; tagint tagprev; double delx1,dely1,delz1,delx2,dely2,delz2; double rsq1,rsq2,r1,r2,c,theta; diff --git a/src/compute_centro_atom.cpp b/src/compute_centro_atom.cpp index 5816bee17a..90f535613b 100644 --- a/src/compute_centro_atom.cpp +++ b/src/compute_centro_atom.cpp @@ -17,19 +17,21 @@ ------------------------------------------------------------------------- */ #include "compute_centro_atom.h" -#include + #include "atom.h" -#include "update.h" -#include "modify.h" -#include "neighbor.h" -#include "neigh_list.h" -#include "neigh_request.h" -#include "force.h" -#include "pair.h" #include "comm.h" +#include "error.h" +#include "force.h" #include "math_extra.h" #include "memory.h" -#include "error.h" +#include "modify.h" +#include "neigh_list.h" +#include "neigh_request.h" +#include "neighbor.h" +#include "pair.h" +#include "update.h" + +#include using namespace LAMMPS_NS; @@ -55,11 +57,8 @@ ComputeCentroAtom::ComputeCentroAtom(LAMMPS *lmp, int narg, char **arg) : int iarg = 4; while (iarg < narg) { if (strcmp(arg[iarg],"axes") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute centro/atom command3"); - if (strcmp(arg[iarg+1],"yes") == 0) axes_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) axes_flag = 0; - else error->all(FLERR,"Illegal compute centro/atom command2"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute centro/atom command3"); + axes_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal compute centro/atom command1"); } diff --git a/src/compute_chunk_atom.cpp b/src/compute_chunk_atom.cpp index 5d789f722a..fc4f17e53a 100644 --- a/src/compute_chunk_atom.cpp +++ b/src/compute_chunk_atom.cpp @@ -220,9 +220,7 @@ ComputeChunkAtom::ComputeChunkAtom(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"compress") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute chunk/atom command"); - else if (strcmp(arg[iarg+1],"no") == 0) compress = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) compress = 1; - else error->all(FLERR,"Illegal compute chunk/atom command"); + compress = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"discard") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute chunk/atom command"); @@ -255,9 +253,7 @@ ComputeChunkAtom::ComputeChunkAtom(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"pbc") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute chunk/atom command"); - if (strcmp(arg[iarg+1],"no") == 0) pbcflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) pbcflag = 1; - else error->all(FLERR,"Illegal compute chunk/atom command"); + pbcflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal compute chunk/atom command"); } diff --git a/src/compute_fragment_atom.cpp b/src/compute_fragment_atom.cpp index b0a72080df..9ed57fef60 100644 --- a/src/compute_fragment_atom.cpp +++ b/src/compute_fragment_atom.cpp @@ -54,9 +54,7 @@ ComputeFragmentAtom::ComputeFragmentAtom(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"single") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute fragment/atom command"); - if (strcmp(arg[iarg+1],"yes") == 0) singleflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) singleflag = 0; - else error->all(FLERR,"Illegal compute fragment/atom command"); + singleflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal compute fragment/atom command"); } diff --git a/src/compute_group_group.cpp b/src/compute_group_group.cpp index 161126b53a..db26a75880 100644 --- a/src/compute_group_group.cpp +++ b/src/compute_group_group.cpp @@ -19,21 +19,22 @@ #include "compute_group_group.h" -#include -#include #include "atom.h" -#include "update.h" -#include "force.h" -#include "pair.h" -#include "neighbor.h" -#include "neigh_request.h" -#include "neigh_list.h" -#include "group.h" -#include "kspace.h" -#include "error.h" #include "comm.h" #include "domain.h" +#include "error.h" +#include "force.h" +#include "group.h" +#include "kspace.h" #include "math_const.h" +#include "neigh_list.h" +#include "neigh_request.h" +#include "neighbor.h" +#include "pair.h" +#include "update.h" + +#include +#include using namespace LAMMPS_NS; using namespace MathConst; @@ -69,29 +70,19 @@ ComputeGroupGroup::ComputeGroupGroup(LAMMPS *lmp, int narg, char **arg) : int iarg = 4; while (iarg < narg) { if (strcmp(arg[iarg],"pair") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute group/group command"); - if (strcmp(arg[iarg+1],"yes") == 0) pairflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) pairflag = 0; - else error->all(FLERR,"Illegal compute group/group command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute group/group command"); + pairflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"kspace") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute group/group command"); - if (strcmp(arg[iarg+1],"yes") == 0) kspaceflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) kspaceflag = 0; - else error->all(FLERR,"Illegal compute group/group command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute group/group command"); + kspaceflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"boundary") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute group/group command"); - if (strcmp(arg[iarg+1],"yes") == 0) boundaryflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) boundaryflag = 0; - else error->all(FLERR,"Illegal compute group/group command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute group/group command"); + boundaryflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"molecule") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute group/group command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute group/group command"); if (strcmp(arg[iarg+1],"off") == 0) molflag = OFF; else if (strcmp(arg[iarg+1],"inter") == 0) molflag = INTER; else if (strcmp(arg[iarg+1],"intra") == 0) molflag = INTRA; diff --git a/src/compute_msd.cpp b/src/compute_msd.cpp index 209eec2810..7eee23a466 100644 --- a/src/compute_msd.cpp +++ b/src/compute_msd.cpp @@ -49,15 +49,11 @@ ComputeMSD::ComputeMSD(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"com") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute msd command"); - if (strcmp(arg[iarg+1],"no") == 0) comflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) comflag = 1; - else error->all(FLERR,"Illegal compute msd command"); + comflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"average") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute msd command"); - if (strcmp(arg[iarg+1],"no") == 0) avflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) avflag = 1; - else error->all(FLERR,"Illegal compute msd command"); + avflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal compute msd command"); } diff --git a/src/compute_orientorder_atom.cpp b/src/compute_orientorder_atom.cpp index b77e68062f..d4291251b6 100644 --- a/src/compute_orientorder_atom.cpp +++ b/src/compute_orientorder_atom.cpp @@ -83,53 +83,41 @@ ComputeOrientOrderAtom::ComputeOrientOrderAtom(LAMMPS *lmp, int narg, char **arg int iarg = 3; while (iarg < narg) { if (strcmp(arg[iarg],"nnn") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute orientorder/atom command"); if (strcmp(arg[iarg+1],"NULL") == 0) { nnn = 0; } else { nnn = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (nnn <= 0) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (nnn <= 0) error->all(FLERR,"Illegal compute orientorder/atom command"); } iarg += 2; } else if (strcmp(arg[iarg],"degrees") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute orientorder/atom command"); nqlist = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (nqlist <= 0) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (nqlist <= 0) error->all(FLERR,"Illegal compute orientorder/atom command"); memory->destroy(qlist); memory->create(qlist,nqlist,"orientorder/atom:qlist"); iarg += 2; - if (iarg+nqlist > narg) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (iarg+nqlist > narg) error->all(FLERR,"Illegal compute orientorder/atom command"); qmax = 0; for (int il = 0; il < nqlist; il++) { qlist[il] = utils::numeric(FLERR,arg[iarg+il],false,lmp); - if (qlist[il] < 0) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (qlist[il] < 0) error->all(FLERR,"Illegal compute orientorder/atom command"); if (qlist[il] > qmax) qmax = qlist[il]; } iarg += nqlist; } else if (strcmp(arg[iarg],"wl") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal compute orientorder/atom command"); - if (strcmp(arg[iarg+1],"yes") == 0) wlflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) wlflag = 0; - else error->all(FLERR,"Illegal compute orientorder/atom command"); + wlflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"wl/hat") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute orientorder/atom command"); - if (strcmp(arg[iarg+1],"yes") == 0) wlhatflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) wlhatflag = 0; - else error->all(FLERR,"Illegal compute orientorder/atom command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute orientorder/atom command"); + wlhatflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"components") == 0) { qlcompflag = 1; - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute orientorder/atom command"); qlcomp = utils::numeric(FLERR,arg[iarg+1],false,lmp); iqlcomp = -1; for (int il = 0; il < nqlist; il++) @@ -137,23 +125,18 @@ ComputeOrientOrderAtom::ComputeOrientOrderAtom(LAMMPS *lmp, int narg, char **arg iqlcomp = il; break; } - if (iqlcomp == -1) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (iqlcomp == -1) error->all(FLERR,"Illegal compute orientorder/atom command"); iarg += 2; } else if (strcmp(arg[iarg],"cutoff") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute orientorder/atom command"); double cutoff = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (cutoff <= 0.0) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (cutoff <= 0.0) error->all(FLERR,"Illegal compute orientorder/atom command"); cutsq = cutoff*cutoff; iarg += 2; } else if (strcmp(arg[iarg],"chunksize") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute orientorder/atom command"); chunksize = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (chunksize <= 0) - error->all(FLERR,"Illegal compute orientorder/atom command"); + if (chunksize <= 0) error->all(FLERR,"Illegal compute orientorder/atom command"); iarg += 2; } else error->all(FLERR,"Illegal compute orientorder/atom command"); } diff --git a/src/compute_temp_chunk.cpp b/src/compute_temp_chunk.cpp index 60014c7e21..8798835071 100644 --- a/src/compute_temp_chunk.cpp +++ b/src/compute_temp_chunk.cpp @@ -14,15 +14,16 @@ #include "compute_temp_chunk.h" -#include #include "atom.h" -#include "update.h" -#include "force.h" -#include "modify.h" #include "compute_chunk_atom.h" #include "domain.h" -#include "memory.h" #include "error.h" +#include "force.h" +#include "memory.h" +#include "modify.h" +#include "update.h" + +#include using namespace LAMMPS_NS; @@ -76,26 +77,20 @@ ComputeTempChunk::ComputeTempChunk(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"com") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute temp/chunk command"); - if (strcmp(arg[iarg+1],"yes") == 0) comflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) comflag = 0; - else error->all(FLERR,"Illegal compute temp/chunk command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/chunk command"); + comflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"bias") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute temp/chunk command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/chunk command"); biasflag = 1; id_bias = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"adof") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute temp/chunk command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/chunk command"); adof = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"cdof") == 0) { - if (iarg+2 > narg) - error->all(FLERR,"Illegal compute temp/chunk command"); + if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/chunk command"); cdof = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal compute temp/chunk command"); diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index cdcdc42a45..e82be7d331 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -151,9 +151,7 @@ void CreateAtoms::command(int narg, char **arg) iarg += 3; } else if (strcmp(arg[iarg],"remap") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal create_atoms command"); - if (strcmp(arg[iarg+1],"yes") == 0) remapflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) remapflag = 0; - else error->all(FLERR,"Illegal create_atoms command"); + remapflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"mol") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal create_atoms command"); @@ -380,7 +378,7 @@ void CreateAtoms::command(int narg, char **arg) // Record wall time for atom creation MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); // clear ghost count and any ghost bonus data internal to AtomVec // same logic as beginning of Comm::exchange() @@ -593,7 +591,7 @@ void CreateAtoms::command(int narg, char **arg) if (scaleflag) domain->print_box(" using lattice units in "); else domain->print_box(" using box units in "); utils::logmesg(lmp," create_atoms CPU = {:.3f} seconds\n", - MPI_Wtime() - time1); + platform::walltime() - time1); } } diff --git a/src/create_bonds.cpp b/src/create_bonds.cpp index 99cfdfa958..ab3bba7041 100644 --- a/src/create_bonds.cpp +++ b/src/create_bonds.cpp @@ -125,9 +125,7 @@ void CreateBonds::command(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"special") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal create_bonds command"); - if (strcmp(arg[iarg+1],"yes") == 0) specialflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) specialflag = 0; - else error->all(FLERR,"Illegal create_bonds command"); + specialflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal create_bonds command"); } diff --git a/src/delete_atoms.cpp b/src/delete_atoms.cpp index a9c25200d1..55b05e3d98 100644 --- a/src/delete_atoms.cpp +++ b/src/delete_atoms.cpp @@ -738,30 +738,21 @@ void DeleteAtoms::options(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"compress") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal delete_atoms command"); - if (strcmp(arg[iarg+1],"yes") == 0) compress_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) compress_flag = 0; - else error->all(FLERR,"Illegal delete_atoms command"); + compress_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"bond") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal delete_atoms command"); if (atom->molecular == Atom::ATOMIC) - error->all(FLERR,"Cannot delete_atoms bond yes for " - "non-molecular systems"); + error->all(FLERR,"Cannot delete_atoms bond yes for non-molecular systems"); if (atom->molecular == Atom::TEMPLATE) - error->all(FLERR,"Cannot use delete_atoms bond yes with " - "atom_style template"); - if (strcmp(arg[iarg+1],"yes") == 0) bond_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) bond_flag = 0; - else error->all(FLERR,"Illegal delete_atoms command"); + error->all(FLERR,"Cannot use delete_atoms bond yes with atom_style template"); + bond_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"mol") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal delete_atoms command"); if (atom->molecule_flag == 0) - error->all(FLERR,"Delete_atoms mol yes requires " - "atom attribute molecule"); - if (strcmp(arg[iarg+1],"yes") == 0) mol_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) mol_flag = 0; - else error->all(FLERR,"Illegal delete_atoms command"); + error->all(FLERR,"Delete_atoms mol yes requires atom attribute molecule"); + mol_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal delete_atoms command"); } diff --git a/src/dump.cpp b/src/dump.cpp index b42797833b..d00c42086d 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -108,9 +108,8 @@ Dump::Dump(LAMMPS *lmp, int /*narg*/, char **arg) : Pointers(lmp) // if contains '%', write one file per proc and replace % with proc-ID // if contains '*', write one file per timestep and replace * with timestep // check file suffixes - // if ends in .bin = binary file - // else if ends in .gz = gzipped text file - // else if ends in .zst = Zstd compressed text file + // if ends in .bin -> binary file + // else if ends in .gz or other known extensions -> compressed text file // else ASCII text file fp = nullptr; @@ -144,8 +143,7 @@ Dump::Dump(LAMMPS *lmp, int /*narg*/, char **arg) : Pointers(lmp) if (strchr(filename,'*')) multifile = 1; if (utils::strmatch(filename, "\\.bin$")) binary = 1; - if (utils::strmatch(filename, "\\.gz$") - || utils::strmatch(filename, "\\.zst$")) compressed = 1; + if (platform::has_compress_extension(filename)) compressed = 1; } /* ---------------------------------------------------------------------- */ @@ -198,7 +196,7 @@ Dump::~Dump() if (multifile == 0 && fp != nullptr) { if (compressed) { - if (filewriter) pclose(fp); + if (filewriter) platform::pclose(fp); } else { if (filewriter) fclose(fp); } @@ -520,7 +518,7 @@ void Dump::write() if (multifile) { if (compressed) { - if (filewriter && fp != nullptr) pclose(fp); + if (filewriter && fp != nullptr) platform::pclose(fp); } else { if (filewriter && fp != nullptr) fclose(fp); } @@ -530,7 +528,7 @@ void Dump::write() /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -580,16 +578,7 @@ void Dump::openfile() if (filewriter) { if (compressed) { -#ifdef LAMMPS_GZIP - auto gzip = fmt::format("gzip -6 > {}",filecurrent); -#ifdef _WIN32 - fp = _popen(gzip.c_str(),"wb"); -#else - fp = popen(gzip.c_str(),"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif + fp = platform::compressed_write(filecurrent); } else if (binary) { fp = fopen(filecurrent,"wb"); } else if (append_flag) { @@ -912,16 +901,12 @@ void Dump::modify_params(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"append") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) append_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) append_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + append_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"buffer") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) buffer_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) buffer_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + buffer_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); if (buffer_flag && buffer_allow == 0) error->all(FLERR,"Dump_modify buffer yes not allowed for this style"); iarg += 2; @@ -935,9 +920,7 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"header") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) write_header_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) write_header_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + header_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"every") == 0) { @@ -960,8 +943,7 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"fileper") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (!multiproc) - error->all(FLERR,"Cannot use dump_modify fileper " - "without % in dump file name"); + error->all(FLERR,"Cannot use dump_modify fileper without % in dump file name"); int nper = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (nper <= 0) error->all(FLERR,"Illegal dump_modify command"); @@ -986,16 +968,12 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"first") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) first_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) first_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + first_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"flush") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) flush_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) flush_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + flush_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"format") == 0) { @@ -1032,8 +1010,7 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"maxfiles") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (!multifile) - error->all(FLERR,"Cannot use dump_modify maxfiles " - "without * in dump file name"); + error->all(FLERR,"Cannot use dump_modify maxfiles without * in dump file name"); // wipe out existing storage if (maxfiles > 0) { for (int idx=0; idx < numfiles; ++idx) @@ -1053,8 +1030,7 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"nfile") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (!multiproc) - error->all(FLERR,"Cannot use dump_modify nfile " - "without % in dump file name"); + error->all(FLERR,"Cannot use dump_modify nfile without % in dump file name"); int nfile = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (nfile <= 0) error->all(FLERR,"Illegal dump_modify command"); nfile = MIN(nfile,nprocs); @@ -1090,9 +1066,7 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"pbc") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) pbcflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) pbcflag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + pbcflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"sort") == 0) { @@ -1117,16 +1091,12 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"time") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) time_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) time_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + time_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"units") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) unit_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) unit_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + unit_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else { diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp index 79aaa1ffcd..0dbd3b3278 100644 --- a/src/dump_atom.cpp +++ b/src/dump_atom.cpp @@ -13,13 +13,15 @@ ------------------------------------------------------------------------- */ #include "dump_atom.h" -#include -#include "domain.h" + #include "atom.h" -#include "memory.h" +#include "domain.h" #include "error.h" +#include "memory.h" #include "update.h" +#include + using namespace LAMMPS_NS; #define ONELINE 256 @@ -114,15 +116,11 @@ int DumpAtom::modify_param(int narg, char **arg) { if (strcmp(arg[0],"scale") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[1],"yes") == 0) scale_flag = 1; - else if (strcmp(arg[1],"no") == 0) scale_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + scale_flag = utils::logical(FLERR,arg[1],false,lmp); return 2; } else if (strcmp(arg[0],"image") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[1],"yes") == 0) image_flag = 1; - else if (strcmp(arg[1],"no") == 0) image_flag = 0; - else error->all(FLERR,"Illegal dump_modify command"); + image_flag = utils::logical(FLERR,arg[1],false,lmp); return 2; } return 0; @@ -562,7 +560,8 @@ void DumpAtom::write_binary(int n, double *mybuf) void DumpAtom::write_string(int n, double *mybuf) { - fwrite(mybuf,sizeof(char),n,fp); + if (mybuf) + fwrite(mybuf,sizeof(char),n,fp); } /* ---------------------------------------------------------------------- */ diff --git a/src/dump_cfg.cpp b/src/dump_cfg.cpp index 28f5a35a4b..8e87f4104e 100644 --- a/src/dump_cfg.cpp +++ b/src/dump_cfg.cpp @@ -233,7 +233,8 @@ void DumpCFG::write_data(int n, double *mybuf) void DumpCFG::write_string(int n, double *mybuf) { - fwrite(mybuf,sizeof(char),n,fp); + if (mybuf) + fwrite(mybuf,sizeof(char),n,fp); } /* ---------------------------------------------------------------------- */ diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp index 16c67927bf..b2acdbfc51 100644 --- a/src/dump_custom.cpp +++ b/src/dump_custom.cpp @@ -1234,7 +1234,8 @@ void DumpCustom::write_binary(int n, double *mybuf) void DumpCustom::write_string(int n, double *mybuf) { - fwrite(mybuf,sizeof(char),n,fp); + if (mybuf) + fwrite(mybuf,sizeof(char),n,fp); } /* ---------------------------------------------------------------------- */ diff --git a/src/dump_image.cpp b/src/dump_image.cpp index f6ca49851d..c073d152f8 100644 --- a/src/dump_image.cpp +++ b/src/dump_image.cpp @@ -47,7 +47,7 @@ using namespace MathConst; enum{NUMERIC,ATOM,TYPE,ELEMENT,ATTRIBUTE}; enum{SPHERE,LINE,TRI}; // also in some Body and Fix child classes enum{STATIC,DYNAMIC}; -enum{NO,YES}; +enum{NO=0,YES=1}; /* ---------------------------------------------------------------------- */ @@ -146,9 +146,7 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"atom") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command"); - if (strcmp(arg[iarg+1],"yes") == 0) atomflag = YES; - else if (strcmp(arg[iarg+1],"no") == 0) atomflag = NO; - else error->all(FLERR,"Illegal dump image command"); + atomflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"adiam") == 0) { @@ -290,18 +288,14 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg],"box") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command"); - if (strcmp(arg[iarg+1],"yes") == 0) boxflag = YES; - else if (strcmp(arg[iarg+1],"no") == 0) boxflag = NO; - else error->all(FLERR,"Illegal dump image command"); + boxflag = utils::logical(FLERR,arg[iarg+1],false,lmp); boxdiam = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (boxdiam < 0.0) error->all(FLERR,"Illegal dump image command"); iarg += 3; } else if (strcmp(arg[iarg],"axes") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command"); - if (strcmp(arg[iarg+1],"yes") == 0) axesflag = YES; - else if (strcmp(arg[iarg+1],"no") == 0) axesflag = NO; - else error->all(FLERR,"Illegal dump image command"); + axesflag = utils::logical(FLERR,arg[iarg+1],false,lmp); axeslen = utils::numeric(FLERR,arg[iarg+2],false,lmp); axesdiam = utils::numeric(FLERR,arg[iarg+3],false,lmp); if (axeslen < 0.0 || axesdiam < 0.0) @@ -310,9 +304,7 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg],"subbox") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command"); - if (strcmp(arg[iarg+1],"yes") == 0) subboxflag = YES; - else if (strcmp(arg[iarg+1],"no") == 0) subboxflag = NO; - else error->all(FLERR,"Illegal dump image command"); + subboxflag = utils::logical(FLERR,arg[iarg+1],false,lmp); subboxdiam = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (subboxdiam < 0.0) error->all(FLERR,"Illegal dump image command"); iarg += 3; @@ -327,9 +319,7 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg],"ssao") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command"); - if (strcmp(arg[iarg+1],"yes") == 0) image->ssao = YES; - else if (strcmp(arg[iarg+1],"no") == 0) image->ssao = NO; - else error->all(FLERR,"Illegal dump image command"); + image->ssao = utils::logical(FLERR,arg[iarg+1],false,lmp); int seed = utils::inumeric(FLERR,arg[iarg+2],false,lmp); if (seed <= 0) error->all(FLERR,"Illegal dump image command"); image->seed = seed; diff --git a/src/dump_local.cpp b/src/dump_local.cpp index f9a970d2b2..96d8944e2f 100644 --- a/src/dump_local.cpp +++ b/src/dump_local.cpp @@ -399,7 +399,8 @@ void DumpLocal::write_data(int n, double *mybuf) void DumpLocal::write_string(int n, double *mybuf) { - fwrite(mybuf,sizeof(char),n,fp); + if (mybuf) + fwrite(mybuf,sizeof(char),n,fp); } /* ---------------------------------------------------------------------- */ diff --git a/src/dump_movie.cpp b/src/dump_movie.cpp index fb834b5fb0..52c0522289 100644 --- a/src/dump_movie.cpp +++ b/src/dump_movie.cpp @@ -41,28 +41,29 @@ DumpMovie::DumpMovie(LAMMPS *lmp, int narg, char **arg) : /* ---------------------------------------------------------------------- */ +DumpMovie::~DumpMovie() +{ + if (fp) platform::pclose(fp); + fp = nullptr; +} + +/* ---------------------------------------------------------------------- */ + void DumpMovie::openfile() { - char moviecmd[1024]; - if ((comm->me == 0) && (fp == nullptr)) { #ifdef LAMMPS_FFMPEG - sprintf(moviecmd,"ffmpeg -v error -y -r %.2f -f image2pipe -c:v ppm -i - " - "-r 24.0 -b:v %dk %s ", framerate, bitrate, filename); + auto moviecmd = fmt::format("ffmpeg -v error -y -r {:.2f} -f image2pipe -c:v ppm -i - " + "-r 24.0 -b:v {}k {}", framerate, bitrate, filename); + fp = platform::popen(moviecmd,"w"); #else + fp = nullptr; error->one(FLERR,"Support for writing movies not included"); #endif -#if defined(_WIN32) - fp = _popen(moviecmd,"wb"); -#else - fp = popen(moviecmd,"w"); -#endif - if (fp == nullptr) - error->one(FLERR,"Failed to open FFmpeg pipeline to " - "file {}",filename); + error->one(FLERR,"Failed to open FFmpeg pipeline to file {}",filename); } } /* ---------------------------------------------------------------------- */ @@ -100,4 +101,3 @@ int DumpMovie::modify_param(int narg, char **arg) return 0; } - diff --git a/src/dump_movie.h b/src/dump_movie.h index 1c41cb09b5..770193e039 100644 --- a/src/dump_movie.h +++ b/src/dump_movie.h @@ -27,6 +27,7 @@ namespace LAMMPS_NS { class DumpMovie : public DumpImage { public: DumpMovie(LAMMPS *, int, char **); + virtual ~DumpMovie(); virtual void openfile(); virtual void init_style(); diff --git a/src/dump_xyz.cpp b/src/dump_xyz.cpp index ebbd432f5d..e009937959 100644 --- a/src/dump_xyz.cpp +++ b/src/dump_xyz.cpp @@ -13,12 +13,14 @@ ------------------------------------------------------------------------- */ #include "dump_xyz.h" -#include + #include "atom.h" #include "error.h" #include "memory.h" #include "update.h" +#include + using namespace LAMMPS_NS; #define ONELINE 128 @@ -194,7 +196,8 @@ void DumpXYZ::write_data(int n, double *mybuf) void DumpXYZ::write_string(int n, double *mybuf) { - fwrite(mybuf,sizeof(char),n,fp); + if (mybuf) + fwrite(mybuf,sizeof(char),n,fp); } /* ---------------------------------------------------------------------- */ diff --git a/src/error.cpp b/src/error.cpp index 9811a1d3eb..5338f41cca 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -58,7 +58,8 @@ void Error::universe_all(const std::string &file, int line, const std::string &s std::string mesg = "ERROR: " + str; try { mesg += fmt::format(" ({}:{})\n",truncpath(file),line); - } catch (fmt::format_error &e) { + } catch (fmt::format_error &) { + ; // do nothing } if (universe->me == 0) { if (universe->uscreen) fputs(mesg.c_str(),universe->uscreen); @@ -147,9 +148,9 @@ void Error::all(const std::string &file, int line, const std::string &str) std::string mesg = "ERROR: " + str; if (input && input->line) lastcmd = input->line; try { - mesg += fmt::format(" ({}:{})\nLast command: {}\n", - truncpath(file),line,lastcmd); - } catch (fmt::format_error &e) { + mesg += fmt::format(" ({}:{})\nLast command: {}\n", truncpath(file),line,lastcmd); + } catch (fmt::format_error &) { + ; // do nothing } utils::logmesg(lmp,mesg); } diff --git a/src/exceptions.h b/src/exceptions.h index d05e14eeb7..1df6c5d1a3 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -35,8 +35,8 @@ class LAMMPSAbortException : public LAMMPSException { public: MPI_Comm universe; - LAMMPSAbortException(const std::string &msg, MPI_Comm universe) : - LAMMPSException(msg), universe(universe) + LAMMPSAbortException(const std::string &msg, MPI_Comm _universe) : + LAMMPSException(msg), universe(_universe) { } }; diff --git a/src/fix.cpp b/src/fix.cpp index 8f5b60535c..996cd9b7d5 100644 --- a/src/fix.cpp +++ b/src/fix.cpp @@ -137,27 +137,19 @@ void Fix::modify_params(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"dynamic/dof") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix_modify command"); - if (strcmp(arg[iarg+1],"no") == 0) dynamic = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) dynamic = 1; - else error->all(FLERR,"Illegal fix_modify command"); + dynamic = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"energy") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix_modify command"); - if (strcmp(arg[iarg+1],"no") == 0) thermo_energy = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) { - if (energy_global_flag == 0 && energy_peratom_flag == 0) + thermo_energy = utils::logical(FLERR,arg[iarg+1],false,lmp); + if (thermo_energy && !energy_global_flag && !energy_peratom_flag) error->all(FLERR,"Illegal fix_modify command"); - thermo_energy = 1; - } else error->all(FLERR,"Illegal fix_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"virial") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix_modify command"); - if (strcmp(arg[iarg+1],"no") == 0) thermo_virial = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) { - if (virial_global_flag == 0 && virial_peratom_flag == 0) - error->all(FLERR,"Illegal fix_modify command"); - thermo_virial = 1; - } else error->all(FLERR,"Illegal fix_modify command"); + thermo_virial = utils::logical(FLERR,arg[iarg+1],false,lmp); + if (thermo_virial && !virial_global_flag && !virial_peratom_flag) + error->all(FLERR,"Illegal fix_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"respa") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix_modify command"); diff --git a/src/fix_adapt.cpp b/src/fix_adapt.cpp index 358cf8045f..766dc9cd74 100644 --- a/src/fix_adapt.cpp +++ b/src/fix_adapt.cpp @@ -158,21 +158,15 @@ nadapt(0), id_fix_diam(nullptr), id_fix_chg(nullptr), adapt(nullptr) while (iarg < narg) { if (strcmp(arg[iarg],"reset") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt command"); - if (strcmp(arg[iarg+1],"no") == 0) resetflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) resetflag = 1; - else error->all(FLERR,"Illegal fix adapt command"); + resetflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scale") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt command"); - if (strcmp(arg[iarg+1],"no") == 0) scaleflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) scaleflag = 1; - else error->all(FLERR,"Illegal fix adapt command"); + scaleflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"mass") == 0) { if (iarg+2 > narg)error->all(FLERR,"Illegal fix adapt command"); - if (strcmp(arg[iarg+1],"no") == 0) massflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) massflag = 1; - else error->all(FLERR,"Illegal fix adapt command"); + massflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix adapt command"); } diff --git a/src/fix_ave_chunk.cpp b/src/fix_ave_chunk.cpp index 1328a27376..36c9eaf6fc 100644 --- a/src/fix_ave_chunk.cpp +++ b/src/fix_ave_chunk.cpp @@ -29,7 +29,6 @@ #include "variable.h" #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -216,23 +215,23 @@ FixAveChunk::FixAveChunk(LAMMPS *lmp, int narg, char **arg) : iarg += 1; } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/chunk command"); - delete [] format_user; + delete[] format_user; format_user = utils::strdup(arg[iarg+1]); format = format_user; iarg += 2; } else if (strcmp(arg[iarg],"title1") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/chunk command"); - delete [] title1; + delete[] title1; title1 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title2") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/chunk command"); - delete [] title2; + delete[] title2; title2 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title3") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/chunk command"); - delete [] title3; + delete[] title3; title3 = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal fix ave/chunk command"); @@ -348,18 +347,18 @@ FixAveChunk::FixAveChunk(LAMMPS *lmp, int narg, char **arg) : if (ferror(fp)) error->one(FLERR,"Error writing file header"); - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; - delete [] title3; + delete[] title1; + delete[] title2; + delete[] title3; // 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 < nargnew; i++) delete [] earg[i]; + for (int i = 0; i < nargnew; i++) delete[] earg[i]; memory->sfree(earg); } @@ -407,11 +406,11 @@ FixAveChunk::FixAveChunk(LAMMPS *lmp, int narg, char **arg) : FixAveChunk::~FixAveChunk() { - delete [] which; - delete [] argindex; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; - delete [] value2index; + delete[] which; + delete[] argindex; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; + delete[] value2index; if (fp && comm->me == 0) fclose(fp); @@ -438,7 +437,7 @@ FixAveChunk::~FixAveChunk() } } - delete [] idchunk; + delete[] idchunk; which = nullptr; argindex = nullptr; ids = nullptr; @@ -941,7 +940,7 @@ void FixAveChunk::end_of_step() if (fp && comm->me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); double count = 0.0; for (m = 0; m < nchunk; m++) count += count_total[m]; fprintf(fp,BIGINT_FORMAT " %d %g\n",ntimestep,nchunk,count); @@ -1027,9 +1026,9 @@ void FixAveChunk::end_of_step() fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } } diff --git a/src/fix_ave_chunk.h b/src/fix_ave_chunk.h index e7beed341f..69fdea0f06 100644 --- a/src/fix_ave_chunk.h +++ b/src/fix_ave_chunk.h @@ -61,7 +61,7 @@ class FixAveChunk : public Fix { class ComputeChunkAtom *cchunk; int lockforever; - long filepos; + bigint filepos; int maxvar; double *varatom; diff --git a/src/fix_ave_correlate.cpp b/src/fix_ave_correlate.cpp index 92b5ea3693..df6e33288e 100644 --- a/src/fix_ave_correlate.cpp +++ b/src/fix_ave_correlate.cpp @@ -30,7 +30,6 @@ #include "variable.h" #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -139,17 +138,17 @@ FixAveCorrelate::FixAveCorrelate(LAMMPS * lmp, int narg, char **arg): iarg += 1; } else if (strcmp(arg[iarg],"title1") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command"); - delete [] title1; + delete[] title1; title1 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title2") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command"); - delete [] title2; + delete[] title2; title2 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title3") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command"); - delete [] title3; + delete[] title3; title3 = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal fix ave/correlate command"); @@ -256,18 +255,18 @@ FixAveCorrelate::FixAveCorrelate(LAMMPS * lmp, int narg, char **arg): if (ferror(fp)) error->one(FLERR,"Error writing file header"); - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; - delete [] title3; + delete[] title1; + delete[] title2; + delete[] title3; // 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 < nargnew; i++) delete [] earg[i]; + for (int i = 0; i < nargnew; i++) delete[] earg[i]; memory->sfree(earg); } @@ -312,11 +311,11 @@ FixAveCorrelate::FixAveCorrelate(LAMMPS * lmp, int narg, char **arg): FixAveCorrelate::~FixAveCorrelate() { - delete [] which; - delete [] argindex; - delete [] value2index; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; + delete[] which; + delete[] argindex; + delete[] value2index; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; memory->destroy(values); memory->destroy(count); @@ -489,7 +488,7 @@ void FixAveCorrelate::end_of_step() if (fp && me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nrepeat); for (i = 0; i < nrepeat; i++) { fprintf(fp,"%d %d %d",i+1,i*nevery,count[i]); @@ -507,9 +506,9 @@ void FixAveCorrelate::end_of_step() fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } diff --git a/src/fix_ave_correlate.h b/src/fix_ave_correlate.h index d551ba7b92..6dde75c0d3 100644 --- a/src/fix_ave_correlate.h +++ b/src/fix_ave_correlate.h @@ -44,7 +44,7 @@ class FixAveCorrelate : public Fix { int type, ave, startstep, overwrite; double prefactor; - long filepos; + bigint filepos; int firstindex; // index in values ring of earliest time sample int lastindex; // index in values ring of latest time sample diff --git a/src/fix_ave_histo.cpp b/src/fix_ave_histo.cpp index 92b03035b3..8c55337074 100644 --- a/src/fix_ave_histo.cpp +++ b/src/fix_ave_histo.cpp @@ -25,7 +25,6 @@ #include "variable.h" #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -168,7 +167,7 @@ FixAveHisto::FixAveHisto(LAMMPS *lmp, int narg, char **arg) : // if wildcard expansion occurred, free earg memory from expand_args() if (expand) { - for (int i = 0; i < nvalues; i++) delete [] earg[i]; + for (int i = 0; i < nvalues; i++) delete[] earg[i]; memory->sfree(earg); } @@ -434,12 +433,12 @@ FixAveHisto::FixAveHisto(LAMMPS *lmp, int narg, char **arg) : if (ferror(fp)) error->one(FLERR,"Error writing file header"); - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; - delete [] title3; + delete[] title1; + delete[] title2; + delete[] title3; // allocate and initialize memory for averaging @@ -502,18 +501,18 @@ FixAveHisto::FixAveHisto(LAMMPS *lmp, int narg, char **arg) : FixAveHisto::~FixAveHisto() { - delete [] which; - delete [] argindex; - delete [] value2index; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; + delete[] which; + delete[] argindex; + delete[] value2index; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; if (fp && me == 0) fclose(fp); - delete [] bin; - delete [] bin_total; - delete [] bin_all; - delete [] coord; + delete[] bin; + delete[] bin_total; + delete[] bin_all; + delete[] coord; memory->destroy(stats_list); memory->destroy(bin_list); memory->destroy(vector); @@ -817,7 +816,7 @@ void FixAveHisto::end_of_step() if (fp && me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT " %d %g %g %g %g\n",ntimestep,nbins, stats_total[0],stats_total[1],stats_total[2],stats_total[3]); if (stats_total[0] != 0.0) @@ -833,9 +832,9 @@ void FixAveHisto::end_of_step() fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}",utils::getsyserror()); } } } @@ -993,17 +992,17 @@ void FixAveHisto::options(int iarg, int narg, char **arg) iarg += 1; } else if (strcmp(arg[iarg],"title1") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command"); - delete [] title1; + delete[] title1; title1 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title2") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command"); - delete [] title2; + delete[] title2; title2 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title3") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command"); - delete [] title3; + delete[] title3; title3 = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal fix ave/histo command"); diff --git a/src/fix_ave_histo.h b/src/fix_ave_histo.h index 0158d04377..ef64ad74ff 100644 --- a/src/fix_ave_histo.h +++ b/src/fix_ave_histo.h @@ -44,7 +44,7 @@ class FixAveHisto : public Fix { FILE *fp; double lo, hi, binsize, bininv; int kind, beyond, overwrite; - long filepos; + bigint filepos; double stats[4], stats_total[4], stats_all[4]; double **stats_list; diff --git a/src/fix_ave_histo_weight.cpp b/src/fix_ave_histo_weight.cpp index 63321bf53e..7866490840 100644 --- a/src/fix_ave_histo_weight.cpp +++ b/src/fix_ave_histo_weight.cpp @@ -28,8 +28,6 @@ #include "update.h" #include "variable.h" -#include - using namespace LAMMPS_NS; using namespace FixConst; @@ -472,7 +470,7 @@ void FixAveHistoWeight::end_of_step() if (fp && me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT " %d %g %g %g %g\n",ntimestep,nbins, stats_total[0],stats_total[1],stats_total[2],stats_total[3]); if (stats_total[0] != 0.0) @@ -488,9 +486,9 @@ void FixAveHistoWeight::end_of_step() fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } } diff --git a/src/fix_ave_time.cpp b/src/fix_ave_time.cpp index da9cd89e5e..a3da6e6a3d 100644 --- a/src/fix_ave_time.cpp +++ b/src/fix_ave_time.cpp @@ -28,7 +28,6 @@ #include "variable.h" #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -274,18 +273,18 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) : if (ferror(fp)) error->one(FLERR,"Error writing file header"); - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; - delete [] title3; + delete[] title1; + delete[] title2; + delete[] title3; // 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]; + for (int i = 0; i < nvalues; i++) delete[] earg[i]; memory->sfree(earg); } @@ -446,24 +445,24 @@ FixAveTime::~FixAveTime() } } - delete [] format_user; + delete[] format_user; - delete [] which; - delete [] argindex; - delete [] value2index; - delete [] offcol; - delete [] varlen; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; + delete[] which; + delete[] argindex; + delete[] value2index; + delete[] offcol; + delete[] varlen; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; - delete [] extlist; + delete[] extlist; if (fp && me == 0) fclose(fp); memory->destroy(column); - delete [] vector; - delete [] vector_total; + delete[] vector; + delete[] vector_total; memory->destroy(array); memory->destroy(array_total); memory->destroy(array_list); @@ -673,7 +672,7 @@ void FixAveTime::invoke_scalar(bigint ntimestep) if (fp && me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT,ntimestep); for (i = 0; i < nvalues; i++) fprintf(fp,format,vector_total[i]/norm); fprintf(fp,"\n"); @@ -683,9 +682,9 @@ void FixAveTime::invoke_scalar(bigint ntimestep) fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } } @@ -885,7 +884,7 @@ void FixAveTime::invoke_vector(bigint ntimestep) // output result to file if (fp && me == 0) { - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nrows); for (i = 0; i < nrows; i++) { fprintf(fp,"%d",i+1); @@ -894,9 +893,9 @@ void FixAveTime::invoke_vector(bigint ntimestep) } fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } } @@ -1066,23 +1065,23 @@ void FixAveTime::options(int iarg, int narg, char **arg) iarg += 1; } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command"); - delete [] format_user; + delete[] format_user; format_user = utils::strdup(arg[iarg+1]); format = format_user; iarg += 2; } else if (strcmp(arg[iarg],"title1") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command"); - delete [] title1; + delete[] title1; title1 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title2") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command"); - delete [] title2; + delete[] title2; title2 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title3") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command"); - delete [] title3; + delete[] title3; title3 = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal fix ave/time command"); diff --git a/src/fix_ave_time.h b/src/fix_ave_time.h index 391a06f495..3a26dd6d70 100644 --- a/src/fix_ave_time.h +++ b/src/fix_ave_time.h @@ -54,7 +54,7 @@ class FixAveTime : public Fix { int *offlist; char *format, *format_user; char *title1, *title2, *title3; - long filepos; + bigint filepos; int norm, iwindow, window_limit; double *vector; diff --git a/src/fix_box_relax.cpp b/src/fix_box_relax.cpp index e80a4db593..7988657339 100644 --- a/src/fix_box_relax.cpp +++ b/src/fix_box_relax.cpp @@ -196,21 +196,15 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"scalexy") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalexy = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalexy = 0; - else error->all(FLERR,"Illegal fix box/relax command"); + scalexy = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scalexz") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalexz = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalexz = 0; - else error->all(FLERR,"Illegal fix box/relax command"); + scalexz = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scaleyz") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); - if (strcmp(arg[iarg+1],"yes") == 0) scaleyz = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scaleyz = 0; - else error->all(FLERR,"Illegal fix box/relax command"); + scaleyz = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"fixedpoint") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal fix box/relax command"); diff --git a/src/fix_deform.cpp b/src/fix_deform.cpp index 4d923ae7ff..71429ac0f8 100644 --- a/src/fix_deform.cpp +++ b/src/fix_deform.cpp @@ -1008,9 +1008,7 @@ void FixDeform::options(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"flip") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix deform command"); - if (strcmp(arg[iarg+1],"yes") == 0) flipflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) flipflag = 0; - else error->all(FLERR,"Illegal fix deform command"); + flipflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix deform command"); } diff --git a/src/fix_dt_reset.cpp b/src/fix_dt_reset.cpp index 409729c242..c80c976504 100644 --- a/src/fix_dt_reset.cpp +++ b/src/fix_dt_reset.cpp @@ -171,7 +171,7 @@ void FixDtReset::end_of_step() if (vsq > 0.0) dtv = xmax / sqrt(vsq); if (fsq > 0.0) dtf = sqrt(2.0 * xmax / (ftm2v * sqrt(fsq) * massinv)); dt = MIN(dtv, dtf); - if (emax > 0.0 && vsq > 0.0 && fsq > 0.0) { + if ((emax > 0.0) && (fsq * vsq > 0.0)) { dte = emax / sqrt(fsq * vsq) / sqrt(ftm2v * mvv2e); dt = MIN(dt, dte); } diff --git a/src/fix_evaporate.cpp b/src/fix_evaporate.cpp index ceb9f52818..531dcf9ffd 100644 --- a/src/fix_evaporate.cpp +++ b/src/fix_evaporate.cpp @@ -14,19 +14,20 @@ #include "fix_evaporate.h" -#include #include "atom.h" #include "atom_vec.h" -#include "molecule.h" -#include "update.h" -#include "domain.h" -#include "region.h" #include "comm.h" +#include "domain.h" +#include "error.h" #include "force.h" #include "group.h" -#include "random_park.h" #include "memory.h" -#include "error.h" +#include "molecule.h" +#include "random_park.h" +#include "region.h" +#include "update.h" + +#include using namespace LAMMPS_NS; using namespace FixConst; @@ -69,9 +70,7 @@ FixEvaporate::FixEvaporate(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"molecule") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix evaporate command"); - if (strcmp(arg[iarg+1],"no") == 0) molflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) molflag = 1; - else error->all(FLERR,"Illegal fix evaporate command"); + molflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix evaporate command"); } diff --git a/src/fix_halt.cpp b/src/fix_halt.cpp index 3e207baae7..263386e2b0 100644 --- a/src/fix_halt.cpp +++ b/src/fix_halt.cpp @@ -34,7 +34,7 @@ using namespace FixConst; enum{BONDMAX,TLIMIT,DISKFREE,VARIABLE}; enum{LT,LE,GT,GE,EQ,NEQ,XOR}; enum{HARD,SOFT,CONTINUE}; -enum{NOMSG,YESMSG}; +enum{NOMSG=0,YESMSG=1}; /* ---------------------------------------------------------------------- */ @@ -102,9 +102,7 @@ FixHalt::FixHalt(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"message") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix halt command"); - if (strcmp(arg[iarg+1],"no") == 0) msgflag = NOMSG; - else if (strcmp(arg[iarg+1],"yes") == 0) msgflag = YESMSG; - else error->all(FLERR,"Illegal fix halt command"); + msgflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"path") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix halt command"); diff --git a/src/fix_langevin.cpp b/src/fix_langevin.cpp index ef1cb4eeaf..6e770689dc 100644 --- a/src/fix_langevin.cpp +++ b/src/fix_langevin.cpp @@ -128,9 +128,7 @@ FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"omega") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix langevin command"); - if (strcmp(arg[iarg+1],"no") == 0) oflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) oflag = 1; - else error->all(FLERR,"Illegal fix langevin command"); + oflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scale") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal fix langevin command"); @@ -142,15 +140,11 @@ FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) : iarg += 3; } else if (strcmp(arg[iarg],"tally") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix langevin command"); - if (strcmp(arg[iarg+1],"no") == 0) tallyflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) tallyflag = 1; - else error->all(FLERR,"Illegal fix langevin command"); + tallyflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"zero") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix langevin command"); - if (strcmp(arg[iarg+1],"no") == 0) zeroflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) zeroflag = 1; - else error->all(FLERR,"Illegal fix langevin command"); + zeroflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix langevin command"); } diff --git a/src/fix_nh.cpp b/src/fix_nh.cpp index c906000ec5..91be322d82 100644 --- a/src/fix_nh.cpp +++ b/src/fix_nh.cpp @@ -17,23 +17,25 @@ ------------------------------------------------------------------------- */ #include "fix_nh.h" -#include -#include + #include "atom.h" +#include "comm.h" +#include "compute.h" +#include "domain.h" +#include "error.h" +#include "fix_deform.h" #include "force.h" #include "group.h" -#include "comm.h" -#include "neighbor.h" #include "irregular.h" -#include "modify.h" -#include "fix_deform.h" -#include "compute.h" #include "kspace.h" -#include "update.h" -#include "respa.h" -#include "domain.h" #include "memory.h" -#include "error.h" +#include "modify.h" +#include "neighbor.h" +#include "respa.h" +#include "update.h" + +#include +#include using namespace LAMMPS_NS; using namespace FixConst; @@ -297,9 +299,7 @@ FixNH::FixNH(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"mtk") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) mtk_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) mtk_flag = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + mtk_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"tloop") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); @@ -318,27 +318,19 @@ FixNH::FixNH(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"scalexy") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalexy = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalexy = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + scalexy = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scalexz") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalexz = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalexz = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + scalexz = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scaleyz") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) scaleyz = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scaleyz = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + scaleyz = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"flip") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); - if (strcmp(arg[iarg+1],"yes") == 0) flipflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) flipflag = 0; - else error->all(FLERR,"Illegal fix nvt/npt/nph command"); + flipflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"update") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command"); diff --git a/src/fix_print.cpp b/src/fix_print.cpp index fa1eba4842..df5b5f77ff 100644 --- a/src/fix_print.cpp +++ b/src/fix_print.cpp @@ -64,14 +64,12 @@ FixPrint::FixPrint(LAMMPS *lmp, int narg, char **arg) : else fp = fopen(arg[iarg+1],"a"); if (fp == nullptr) error->one(FLERR,"Cannot open fix print file {}: {}", - arg[iarg+1], utils::getsyserror()); + arg[iarg+1], utils::getsyserror()); } iarg += 2; } else if (strcmp(arg[iarg],"screen") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix print command"); - if (strcmp(arg[iarg+1],"yes") == 0) screenflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) screenflag = 0; - else error->all(FLERR,"Illegal fix print command"); + screenflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"title") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix print command"); diff --git a/src/fix_property_atom.cpp b/src/fix_property_atom.cpp index 8fcb0f2af0..f90d83af4b 100644 --- a/src/fix_property_atom.cpp +++ b/src/fix_property_atom.cpp @@ -151,9 +151,7 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"ghost") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix property/atom command"); - if (strcmp(arg[iarg+1],"no") == 0) border = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) border = 1; - else error->all(FLERR,"Illegal fix property/atom command"); + border = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix property/atom command"); } diff --git a/src/fix_store_state.cpp b/src/fix_store_state.cpp index e4d1634a07..cd29e785ec 100644 --- a/src/fix_store_state.cpp +++ b/src/fix_store_state.cpp @@ -231,9 +231,7 @@ FixStoreState::FixStoreState(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"com") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix store/state command"); - if (strcmp(arg[iarg+1],"no") == 0) comflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) comflag = 1; - else error->all(FLERR,"Illegal fix store/state command"); + comflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix store/state command"); } @@ -246,16 +244,13 @@ FixStoreState::FixStoreState(LAMMPS *lmp, int narg, char **arg) : if (icompute < 0) error->all(FLERR,"Compute ID for fix store/state does not exist"); if (modify->compute[icompute]->peratom_flag == 0) - error->all(FLERR,"Fix store/state compute " - "does not calculate per-atom values"); + error->all(FLERR,"Fix store/state compute does not calculate per-atom values"); if (argindex[i] == 0 && modify->compute[icompute]->size_peratom_cols != 0) - error->all(FLERR,"Fix store/state compute does not " - "calculate a per-atom vector"); + error->all(FLERR,"Fix store/state compute does not calculate a per-atom vector"); if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0) error->all(FLERR, - "Fix store/state compute does not " - "calculate a per-atom array"); + "Fix store/state compute does not calculate a per-atom array"); if (argindex[i] && argindex[i] > modify->compute[icompute]->size_peratom_cols) error->all(FLERR, diff --git a/src/fix_wall.cpp b/src/fix_wall.cpp index bec669ff10..0c3623857e 100644 --- a/src/fix_wall.cpp +++ b/src/fix_wall.cpp @@ -128,15 +128,11 @@ FixWall::FixWall(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"fld") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix wall command"); - if (strcmp(arg[iarg+1],"no") == 0) fldflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) fldflag = 1; - else error->all(FLERR,"Illegal fix wall command"); + fldflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"pbc") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix wall command"); - if (strcmp(arg[iarg+1],"yes") == 0) pbcflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) pbcflag = 0; - else error->all(FLERR,"Illegal fix wall command"); + pbcflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal fix wall command"); } diff --git a/src/force.cpp b/src/force.cpp index 62d9738206..6b7e9033ca 100644 --- a/src/force.cpp +++ b/src/force.cpp @@ -811,15 +811,11 @@ void Force::set_special(int narg, char **arg) iarg += 4; } else if (strcmp(arg[iarg],"angle") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal special_bonds command"); - if (strcmp(arg[iarg+1],"no") == 0) special_angle = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) special_angle = 1; - else error->all(FLERR,"Illegal special_bonds command"); + special_angle = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"dihedral") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal special_bonds command"); - if (strcmp(arg[iarg+1],"no") == 0) special_dihedral = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) special_dihedral = 1; - else error->all(FLERR,"Illegal special_bonds command"); + special_dihedral = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal special_bonds command"); } diff --git a/src/info.cpp b/src/info.cpp index 137bf44b1a..3d24f9b56a 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -282,7 +282,7 @@ void Info::command(int narg, char **arg) fmt::print(out,"Git info: {} / {} / {}\n", lmp->git_branch, lmp->git_descriptor,lmp->git_commit); - fmt::print(out,"\nOS information: {}\n\n",get_os_info()); + fmt::print(out,"\nOS information: {}\n\n",platform::os_info()); fmt::print(out,"sizeof(smallint): {}-bit\n" "sizeof(imageint): {}-bit\n" @@ -292,7 +292,7 @@ void Info::command(int narg, char **arg) sizeof(tagint)*8, sizeof(bigint)*8); fmt::print(out,"\nCompiler: {} with {}\nC++ standard: {}\n", - get_compiler_info(),get_openmp_info(),get_cxx_info()); + platform::compiler_info(),platform::openmp_standard(),platform::cxx_standard()); fputs("\nActive compile time flags:\n\n",out); if (has_gzip_support()) fputs("-DLAMMPS_GZIP\n",out); @@ -353,7 +353,7 @@ void Info::command(int narg, char **arg) if (flags & COMM) { int major,minor; - std::string version = get_mpi_info(major,minor); + std::string version = platform::mpi_info(major,minor); fmt::print(out,"\nCommunication information:\n" "MPI library level: MPI v{}.{}\n" @@ -635,24 +635,8 @@ void Info::command(int narg, char **arg) } if (flags & TIME) { - double wallclock = MPI_Wtime() - lmp->initclock; - double cpuclock = 0.0; - -#if defined(_WIN32) - // from MSD docs. - FILETIME ct,et,kt,ut; - union { FILETIME ft; uint64_t ui; } cpu; - if (GetProcessTimes(GetCurrentProcess(),&ct,&et,&kt,&ut)) { - cpu.ft = ut; - cpuclock = cpu.ui * 0.0000001; - } -#else /* POSIX */ - struct rusage ru; - if (getrusage(RUSAGE_SELF, &ru) == 0) { - cpuclock = (double) ru.ru_utime.tv_sec; - cpuclock += (double) ru.ru_utime.tv_usec * 0.000001; - } -#endif /* ! _WIN32 */ + double wallclock = platform::walltime() - lmp->initclock; + double cpuclock = platform::cputime(); int cpuh,cpum,cpus,wallh,wallm,walls; cpus = fmod(cpuclock,60.0); @@ -1266,200 +1250,6 @@ bool Info::has_accelerator_feature(const std::string &package, return false; } -/* ---------------------------------------------------------------------- */ -#define _INFOBUF_SIZE 256 - -std::string Info::get_os_info() -{ - std::string buf; - -#if defined(_WIN32) - DWORD fullversion,majorv,minorv,buildv=0; - - fullversion = GetVersion(); - majorv = (DWORD) (LOBYTE(LOWORD(fullversion))); - minorv = (DWORD) (HIBYTE(LOWORD(fullversion))); - if (fullversion < 0x80000000) - buildv = (DWORD) (HIWORD(fullversion)); - - buf = fmt::format("Windows {}.{} ({}) on ",majorv,minorv,buildv); - - SYSTEM_INFO si; - GetSystemInfo(&si); - - switch (si.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_AMD64: - buf += "x86_64"; - break; - case PROCESSOR_ARCHITECTURE_ARM: - buf += "arm"; - break; - case PROCESSOR_ARCHITECTURE_IA64: - buf += "ia64"; - break; - case PROCESSOR_ARCHITECTURE_INTEL: - buf += "i386"; - break; - default: - buf += "(unknown)"; - } -#else - struct utsname ut; - uname(&ut); - - // try to get OS distribution name, if available - std::string distro = ut.sysname; - if (utils::file_is_readable("/etc/os-release")) { - try { - TextFileReader reader("/etc/os-release",""); - while (1) { - auto words = reader.next_values(0,"="); - if ((words.count() > 1) && (words.next_string() == "PRETTY_NAME")) { - distro += " " + utils::trim(words.next_string()); - break; - } - } - } catch (std::exception &e) { - ; // EOF but keyword not found - } - } - - buf = fmt::format("{} {} on {}", distro, ut.release, ut.machine); -#endif - return buf; -} - -std::string Info::get_compiler_info() -{ - std::string buf; -#if defined(__INTEL_LLVM_COMPILER) - constexpr double version = static_cast(__INTEL_LLVM_COMPILER)*0.01; - buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__); -#elif defined(__ibmxl__) - buf = fmt::format("IBM XL C/C++ (Clang) {}.{}.{}", - __ibmxl_version__, __ibmxl_release__, __ibmxl_modification__); -#elif defined(__clang__) - buf = fmt::format("Clang C++ {}", __VERSION__); -#elif defined(__PGI) - buf = fmt::format("PGI C++ {}.{}",__PGIC__, __PGIC_MINOR__); -#elif defined(__INTEL_COMPILER) - double version = static_cast(__INTEL_COMPILER)*0.01; - buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version, - __INTEL_COMPILER_UPDATE, __VERSION__); -#elif defined(__MINGW64__) - buf = fmt::format("MinGW-w64 64bit {}.{} / GNU C++ {}", __MINGW64_VERSION_MAJOR, - __MINGW64_VERSION_MINOR, __VERSION__); -#elif defined(__MINGW32__) - buf = fmt::format("MinGW-w64 32bit {}.{} / GNU C++ {}", __MINGW32_MAJOR_VERSION, - __MINGW32_MINOR_VERSION, __VERSION__); -#elif defined(__GNUC__) - buf = fmt::format("GNU C++ {}", __VERSION__); -#elif defined(_MSC_VER) && (_MSC_VER > 1920) && (_MSC_VER < 2000) - constexpr int major = _MSC_VER / 100; - constexpr int minor = _MSC_VER - major *100; - buf = fmt::format("Microsoft Visual Studio 20{}, C/C++ {}.{}", major, major-5, minor); -#else - buf = "(Unknown)"; -#endif - return buf; -} - -std::string Info::get_openmp_info() -{ - -#if !defined(_OPENMP) - return "OpenMP not enabled"; -#else - -// Supported OpenMP version corresponds to the release date of the -// specifications as posted at https://www.openmp.org/specifications/ - -#if _OPENMP > 202011 - return "OpenMP newer than version 5.1"; -#elif _OPENMP == 202011 - return "OpenMP 5.1"; -#elif _OPENMP == 201811 - return "OpenMP 5.0"; -#elif _OPENMP == 201611 - return "OpenMP 5.0 preview 1"; -#elif _OPENMP == 201511 - return "OpenMP 4.5"; -#elif _OPENMP == 201307 - return "OpenMP 4.0"; -#elif _OPENMP == 201107 - return "OpenMP 3.1"; -#elif _OPENMP == 200805 - return "OpenMP 3.0"; -#elif _OPENMP == 200505 - return "OpenMP 2.5"; -#elif _OPENMP == 200203 - return "OpenMP 2.0"; -#else - return "unknown OpenMP version"; -#endif - -#endif -} - -std::string Info::get_mpi_vendor() { - #if defined(MPI_STUBS) - return "MPI STUBS"; - #elif defined(OPEN_MPI) - return "Open MPI"; - #elif defined(MPICH_NAME) - return "MPICH"; - #elif defined(I_MPI_VERSION) - return "Intel MPI"; - #elif defined(PLATFORM_MPI) - return "Platform MPI"; - #elif defined(HP_MPI) - return "HP MPI"; - #elif defined(MSMPI_VER) - return "Microsoft MPI"; - #else - return "Unknown MPI implementation"; - #endif -} - -std::string Info::get_mpi_info(int &major, int &minor) -{ - int len; -#if (defined(MPI_VERSION) && (MPI_VERSION > 2)) || defined(MPI_STUBS) - static char version[MPI_MAX_LIBRARY_VERSION_STRING]; - MPI_Get_library_version(version,&len); -#else - static char version[32]; - strcpy(version,get_mpi_vendor().c_str()); - len = strlen(version); -#endif - - MPI_Get_version(&major,&minor); - if (len > 80) { - char *ptr = strchr(version+80,'\n'); - if (ptr) *ptr = '\0'; - } - return std::string(version); -} - -std::string Info::get_cxx_info() -{ -#if __cplusplus > 202002L - return "newer than C++20"; -#elif __cplusplus == 202002L - return "C++20"; -#elif __cplusplus == 201703L - return "C++17"; -#elif __cplusplus == 201402L - return "C++14"; -#elif __cplusplus == 201103L - return "C++11"; -#elif __cplusplus == 199711L - return "C++98"; -#else - return "unknown"; -#endif -} - std::string Info::get_accelerator_info(const std::string &package) { std::string mesg(""); diff --git a/src/info.h b/src/info.h index d000b3c443..0e7bfb68f3 100644 --- a/src/info.h +++ b/src/info.h @@ -48,13 +48,6 @@ class Info : public Command { const std::string &); static bool has_gpu_device(); static std::string get_gpu_device_info(); - - static std::string get_os_info(); - static std::string get_compiler_info(); - static std::string get_openmp_info(); - static std::string get_mpi_vendor(); - static std::string get_mpi_info(int &, int &); - static std::string get_cxx_info(); static std::string get_accelerator_info(const std::string &pkg = ""); void get_memory_info(double *); diff --git a/src/input.cpp b/src/input.cpp index f67438d635..21c092f356 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -49,11 +49,6 @@ #include #include #include -#include - -#ifdef _WIN32 -#include -#endif using namespace LAMMPS_NS; @@ -1068,19 +1063,14 @@ void Input::partition() { if (narg < 3) error->all(FLERR,"Illegal partition command"); - int yesflag = 0; - if (strcmp(arg[0],"yes") == 0) yesflag = 1; - else if (strcmp(arg[0],"no") == 0) yesflag = 0; - else error->all(FLERR,"Illegal partition command"); - int ilo,ihi; + int yesflag = utils::logical(FLERR,arg[0],false,lmp); utils::bounds(FLERR,arg[1],1,universe->nworlds,ilo,ihi,error); // new command starts at the 3rd argument, // which must not be another partition command - if (strcmp(arg[2],"partition") == 0) - error->all(FLERR,"Illegal partition command"); + if (strcmp(arg[2],"partition") == 0) error->all(FLERR,"Illegal partition command"); char *cmd = strstr(line,arg[2]); @@ -1123,21 +1113,16 @@ void Input::print() if (strcmp(arg[iarg],"file") == 0) fp = fopen(arg[iarg+1],"w"); else fp = fopen(arg[iarg+1],"a"); if (fp == nullptr) - error->one(FLERR,"Cannot open print file {}: {}", - arg[iarg+1], utils::getsyserror()); + error->one(FLERR,"Cannot open print file {}: {}", arg[iarg+1], utils::getsyserror()); } iarg += 2; } else if (strcmp(arg[iarg],"screen") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal print command"); - if (strcmp(arg[iarg+1],"yes") == 0) screenflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) screenflag = 0; - else error->all(FLERR,"Illegal print command"); + screenflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"universe") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal print command"); - if (strcmp(arg[iarg+1],"yes") == 0) universeflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) universeflag = 0; - else error->all(FLERR,"Illegal print command"); + universeflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal print command"); } @@ -1174,15 +1159,6 @@ void Input::quit() /* ---------------------------------------------------------------------- */ -char *shell_failed_message(const char* cmd, int errnum) -{ - std::string errmsg = fmt::format("Shell command '{}' failed with error '{}'", - cmd, strerror(errnum)); - char *msg = new char[errmsg.size()+1]; - strcpy(msg, errmsg.c_str()); - return msg; -} - void Input::shell() { int rv,err; @@ -1191,89 +1167,59 @@ void Input::shell() if (strcmp(arg[0],"cd") == 0) { if (narg != 2) error->all(FLERR,"Illegal shell cd command"); - rv = (chdir(arg[1]) < 0) ? errno : 0; + rv = (platform::chdir(arg[1]) < 0) ? errno : 0; MPI_Reduce(&rv,&err,1,MPI_INT,MPI_MAX,0,world); + errno = err; if (me == 0 && err != 0) { - char *message = shell_failed_message("cd",err); - error->warning(FLERR,message); - delete[] message; + error->warning(FLERR, "Shell command 'cd {}' failed with error '{}'", arg[1], utils::getsyserror()); } - } else if (strcmp(arg[0],"mkdir") == 0) { if (narg < 2) error->all(FLERR,"Illegal shell mkdir command"); - if (me == 0) + if (me == 0) { for (int i = 1; i < narg; i++) { -#if defined(_WIN32) - rv = _mkdir(arg[i]); -#else - rv = mkdir(arg[i], S_IRWXU | S_IRGRP | S_IXGRP); -#endif - if (rv < 0) { - char *message = shell_failed_message("mkdir",errno); - error->warning(FLERR,message); - delete[] message; - } + if (platform::mkdir(arg[i]) < 0) + error->warning(FLERR, "Shell command 'mkdir {}' failed with error '{}'", + arg[i],utils::getsyserror()); } - + } } else if (strcmp(arg[0],"mv") == 0) { if (narg != 3) error->all(FLERR,"Illegal shell mv command"); - rv = (rename(arg[1],arg[2]) < 0) ? errno : 0; - MPI_Reduce(&rv,&err,1,MPI_INT,MPI_MAX,0,world); - if (me == 0 && err != 0) { - char *message = shell_failed_message("mv",err); - error->warning(FLERR,message); - delete[] message; + if (me == 0) { + if (rename(arg[1],arg[2]) < 0) { + error->warning(FLERR, "Shell command 'mv {} {}' failed with error '{}'", + arg[1],arg[2],utils::getsyserror()); + } } - } else if (strcmp(arg[0],"rm") == 0) { if (narg < 2) error->all(FLERR,"Illegal shell rm command"); - if (me == 0) + if (me == 0) { for (int i = 1; i < narg; i++) { - if (unlink(arg[i]) < 0) { - char *message = shell_failed_message("rm",errno); - error->warning(FLERR,message); - delete[] message; - } + if (platform::unlink(arg[i]) < 0) + error->warning(FLERR, "Shell command 'rm {}' failed with error '{}'", + arg[i], utils::getsyserror()); } - + } } else if (strcmp(arg[0],"rmdir") == 0) { if (narg < 2) error->all(FLERR,"Illegal shell rmdir command"); - if (me == 0) + if (me == 0) { for (int i = 1; i < narg; i++) { - if (rmdir(arg[i]) < 0) { - char *message = shell_failed_message("rmdir",errno); - error->warning(FLERR,message); - delete[] message; - } + if (platform::rmdir(arg[i]) < 0) + error->warning(FLERR, "Shell command 'rmdir {}' failed with error '{}'", + arg[i], utils::getsyserror()); } - + } } else if (strcmp(arg[0],"putenv") == 0) { if (narg < 2) error->all(FLERR,"Illegal shell putenv command"); for (int i = 1; i < narg; i++) { rv = 0; -#ifdef _WIN32 - if (arg[i]) rv = _putenv(utils::strdup(arg[i])); -#else - if (arg[i]) { - std::string vardef(arg[i]); - auto found = vardef.find_first_of('='); - if (found == std::string::npos) { - rv = setenv(vardef.c_str(),"",1); - } else { - rv = setenv(vardef.substr(0,found).c_str(), - vardef.substr(found+1).c_str(),1); - } - } -#endif + if (arg[i]) rv = platform::putenv(arg[i]); rv = (rv < 0) ? errno : 0; MPI_Reduce(&rv,&err,1,MPI_INT,MPI_MAX,0,world); - if (me == 0 && err != 0) { - char *message = shell_failed_message("putenv",err); - error->warning(FLERR,message); - delete[] message; - } + errno = err; + if (me == 0 && err != 0) + error->warning(FLERR, "Shell command 'putenv {}' failed with error '{}'", + arg[i], utils::getsyserror()); } - // use work string to concat args back into one string separated by spaces // invoke string in shell via system() @@ -1632,16 +1578,10 @@ void Input::newton() int newton_pair=1,newton_bond=1; if (narg == 1) { - if (strcmp(arg[0],"off") == 0) newton_pair = newton_bond = 0; - else if (strcmp(arg[0],"on") == 0) newton_pair = newton_bond = 1; - else error->all(FLERR,"Illegal newton command"); + newton_pair = newton_bond = utils::logical(FLERR,arg[0],false,lmp); } else if (narg == 2) { - if (strcmp(arg[0],"off") == 0) newton_pair = 0; - else if (strcmp(arg[0],"on") == 0) newton_pair= 1; - else error->all(FLERR,"Illegal newton command"); - if (strcmp(arg[1],"off") == 0) newton_bond = 0; - else if (strcmp(arg[1],"on") == 0) newton_bond = 1; - else error->all(FLERR,"Illegal newton command"); + newton_pair = utils::logical(FLERR,arg[0],false,lmp); + newton_bond = utils::logical(FLERR,arg[1],false,lmp); } else error->all(FLERR,"Illegal newton command"); force->newton_pair = newton_pair; @@ -1838,11 +1778,13 @@ void Input::suffix() { if (narg < 1) error->all(FLERR,"Illegal suffix command"); - if (strcmp(arg[0],"off") == 0) lmp->suffix_enable = 0; - else if (strcmp(arg[0],"on") == 0) { - if (!lmp->suffix) - error->all(FLERR,"May only enable suffixes after defining one"); + const std::string firstarg = arg[0]; + + if ((firstarg == "off") || (firstarg == "no") || (firstarg == "false")) { + lmp->suffix_enable = 0; + } else if ((firstarg == "on") || (firstarg == "yes") || (firstarg == "true")) { lmp->suffix_enable = 1; + if (!lmp->suffix) error->all(FLERR,"May only enable suffixes after defining one"); } else { lmp->suffix_enable = 1; @@ -1850,7 +1792,7 @@ void Input::suffix() delete[] lmp->suffix2; lmp->suffix = lmp->suffix2 = nullptr; - if (strcmp(arg[0],"hybrid") == 0) { + if (firstarg == "hybrid") { if (narg != 3) error->all(FLERR,"Illegal suffix command"); lmp->suffix = utils::strdup(arg[1]); lmp->suffix2 = utils::strdup(arg[2]); diff --git a/src/kspace.cpp b/src/kspace.cpp index a18a9ca702..fb995fca8a 100644 --- a/src/kspace.cpp +++ b/src/kspace.cpp @@ -480,8 +480,7 @@ void KSpace::modify_params(int narg, char **arg) if (nx_pppm_6 == 0 && ny_pppm_6 == 0 && nz_pppm_6 == 0) gridflag_6 = 0; else if (nx_pppm_6 <= 0 || ny_pppm_6 <= 0 || nz_pppm_6 == 0) - error->all(FLERR,"Kspace_modify mesh/disp parameters must be all " - "zero or all positive"); + error->all(FLERR,"Kspace_modify mesh/disp parameters must be all zero or all positive"); else gridflag_6 = 1; iarg += 4; } else if (strcmp(arg[iarg],"order") == 0) { @@ -499,9 +498,7 @@ void KSpace::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"overlap") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) overlap_allowed = 1; - else if (strcmp(arg[iarg+1],"no") == 0) overlap_allowed = 0; - else error->all(FLERR,"Illegal kspace_modify command"); + overlap_allowed = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"force") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); @@ -535,21 +532,15 @@ void KSpace::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"compute") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) compute_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) compute_flag = 0; - else error->all(FLERR,"Illegal kspace_modify command"); + compute_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"fftbench") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) fftbench = 1; - else if (strcmp(arg[iarg+1],"no") == 0) fftbench = 0; - else error->all(FLERR,"Illegal kspace_modify command"); + fftbench = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"collective") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) collective_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) collective_flag = 0; - else error->all(FLERR,"Illegal kspace_modify command"); + collective_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"diff") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); @@ -559,9 +550,7 @@ void KSpace::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"cutoff/adjust") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) adjust_cutoff_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) adjust_cutoff_flag = 0; - else error->all(FLERR,"Illegal kspace_modify command"); + adjust_cutoff_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"kmax/ewald") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal kspace_modify command"); @@ -598,15 +587,11 @@ void KSpace::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"pressure/scalar") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) scalar_pressure_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scalar_pressure_flag = 0; - else error->all(FLERR,"Illegal kspace_modify command"); + scalar_pressure_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"disp/auto") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) auto_disp_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) auto_disp_flag = 0; - else error->all(FLERR,"Illegal kspace_modify command"); + auto_disp_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else { int n = modify_param(narg-iarg,&arg[iarg]); diff --git a/src/lammps.cpp b/src/lammps.cpp index 89c59bec3d..f4dd4e5708 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -56,12 +56,6 @@ #include #include -#if defined(_WIN32) -#include -#else -#include // for isatty() -#endif - #include "lmpinstalledpkgs.h" #include "lmpgitversion.h" @@ -135,20 +129,21 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : logfile = nullptr; infile = nullptr; - initclock = MPI_Wtime(); + initclock = platform::walltime(); init_pkg_lists(); #if defined(LMP_PYTHON) && defined(_WIN32) - // if the LAMMPSHOME environment variable is set, it should point + // If the LAMMPSHOME environment variable is set, it should point // to the location of the LAMMPS installation tree where we bundle // the matching Python installation for use with the PYTHON package. - // this is currently only used on Windows with the windows installer packages + // This is currently only used on Windows with the Windows installer packages const char *lmpenv = getenv("LAMMPSHOME"); if (lmpenv) { - _putenv(utils::strdup(fmt::format("PYTHONHOME={}",lmpenv))); + platform::putenv(fmt::format("PYTHONHOME={}",lmpenv)); } #endif + // check if -mpicolor is first arg // if so, then 2 apps were launched with one mpirun command // this means passed communicator (e.g. MPI_COMM_WORLD) is bigger than LAMMPS @@ -266,8 +261,11 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : strcmp(arg[iarg],"-k") == 0) { if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument"); - if (strcmp(arg[iarg+1],"on") == 0) kokkosflag = 1; - else if (strcmp(arg[iarg+1],"off") == 0) kokkosflag = 0; + const std::string kokkosarg = arg[iarg+1]; + if ((kokkosarg == "on") || (kokkosarg == "yes") || (kokkosarg == "true")) + kokkosflag = 1; + else if ((kokkosarg == "off") || (kokkosarg == "no") || (kokkosarg == "false")) + kokkosflag = 0; else error->universe_all(FLERR,"Invalid command-line argument"); iarg += 2; // delimit any extra args for the Kokkos instantiation @@ -659,7 +657,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : int n = plast[i] - pfirst[i]; packargs[i] = new char*[n+1]; for (int j=0; j < n; ++j) - packargs[i][j] = strdup(arg[pfirst[i]+j]); + packargs[i][j] = utils::strdup(arg[pfirst[i]+j]); packargs[i][n] = nullptr; } memory->destroy(pfirst); @@ -713,7 +711,7 @@ LAMMPS::~LAMMPS() if (num_package) { for (int i = 0; i < num_package; i++) { for (char **ptr = packargs[i]; *ptr != nullptr; ++ptr) - free(*ptr); + delete[] *ptr; delete[] packargs[i]; } delete[] packargs; @@ -721,7 +719,7 @@ LAMMPS::~LAMMPS() num_package = 0; packargs = nullptr; - double totalclock = MPI_Wtime() - initclock; + double totalclock = platform::walltime() - initclock; if ((me == 0) && (screen || logfile)) { int seconds = fmod(totalclock,60.0); totalclock = (totalclock - seconds) / 60.0; @@ -1115,11 +1113,7 @@ void _noopt LAMMPS::help() // user. scrollback buffers are often not large enough. this is most // beneficial to windows users, who are not used to command line. -#if defined(_WIN32) - int use_pager = _isatty(fileno(fp)); -#else - int use_pager = isatty(fileno(fp)); -#endif + int use_pager = platform::is_console(fp); // cannot use this with OpenMPI since its console is non-functional @@ -1130,11 +1124,7 @@ void _noopt LAMMPS::help() if (use_pager) { pager = getenv("PAGER"); if (pager == nullptr) pager = "more"; -#if defined(_WIN32) - fp = _popen(pager,"w"); -#else - fp = popen(pager,"w"); -#endif + fp = platform::popen(pager,"w"); // reset to original state, if pipe command failed if (fp == nullptr) { @@ -1296,7 +1286,7 @@ void _noopt LAMMPS::help() // close pipe to pager, if active - if (pager != nullptr) pclose(fp); + if (pager != nullptr) platform::pclose(fp); } /* ---------------------------------------------------------------------- @@ -1337,14 +1327,14 @@ void LAMMPS::print_config(FILE *fp) const char *pkg; int ncword, ncline = 0; - fmt::print(fp,"OS: {}\n\n",Info::get_os_info()); + fmt::print(fp,"OS: {}\n\n",platform::os_info()); fmt::print(fp,"Compiler: {} with {}\nC++ standard: {}\n", - Info::get_compiler_info(),Info::get_openmp_info(), - Info::get_cxx_info()); + platform::compiler_info(),platform::openmp_standard(), + platform::cxx_standard()); int major,minor; - std::string infobuf = Info::get_mpi_info(major,minor); + std::string infobuf = platform::mpi_info(major,minor); fmt::print(fp,"MPI v{}.{}: {}\n\n",major,minor,infobuf); fmt::print(fp,"Accelerator configuration:\n\n{}\n", diff --git a/src/lammpsplugin.h b/src/lammpsplugin.h index 93bf418893..5df0172763 100644 --- a/src/lammpsplugin.h +++ b/src/lammpsplugin.h @@ -15,8 +15,9 @@ #define LMP_LAMMPSPLUGIN_H // C style API and data structure required for dynamic loading - +#ifdef __cplusplus extern "C" { +#endif typedef void *(lammpsplugin_factory1) (void *); typedef void *(lammpsplugin_factory2) (void *, int, char **); @@ -41,6 +42,9 @@ typedef void (*lammpsplugin_initfunc)(void *, void *, void *); // to load a plugin; uses C bindings void lammpsplugin_init(void *, void *, void *); + +#ifdef __cplusplus } +#endif #endif diff --git a/src/library.cpp b/src/library.cpp index 13f480ed03..ed208413e6 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -4394,9 +4394,9 @@ void lammps_get_os_info(char *buffer, int buf_size) { if (buf_size <=0) return; buffer[0] = buffer[buf_size-1] = '\0'; - std::string txt = Info::get_os_info() + "\n"; - txt += Info::get_compiler_info(); - txt += " with " + Info::get_openmp_info() + "\n"; + std::string txt = platform::os_info() + "\n"; + txt += platform::compiler_info(); + txt += " with " + platform::openmp_standard() + "\n"; strncpy(buffer, txt.c_str(), buf_size-1); } @@ -4420,15 +4420,16 @@ int lammps_config_has_mpi_support() /* ---------------------------------------------------------------------- */ -/** Check if the LAMMPS library supports compressed files via a pipe to gzip +/** Check if the LAMMPS library supports reading or writing compressed + * files via a pipe to gzip or similar compression programs \verbatim embed:rst Several LAMMPS commands (e.g. :doc:`read_data`, :doc:`write_data`, :doc:`dump styles atom, custom, and xyz `) support reading and writing compressed files via creating a pipe to the ``gzip`` program. This function checks whether this feature was :ref:`enabled at compile -time `. It does **not** check whether the ``gzip`` itself is -installed and usable. +time `. It does **not** check whether``gzip`` or any other +supported compression programs themselves are installed and usable. \endverbatim * * \return 1 if yes, otherwise 0 diff --git a/src/main.cpp b/src/main.cpp index 568da132e2..095e1752da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -79,7 +79,7 @@ int main(int argc, char **argv) KokkosLMP::finalize(); Python::finalize(); MPI_Abort(ae.universe, 1); - } catch (LAMMPSException &e) { + } catch (LAMMPSException &) { KokkosLMP::finalize(); Python::finalize(); MPI_Barrier(lammps_comm); diff --git a/src/min.cpp b/src/min.cpp index ab8b1a5235..4780cf31eb 100644 --- a/src/min.cpp +++ b/src/min.cpp @@ -705,15 +705,11 @@ void Min::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"halfstepback") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal min_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) halfstepback_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) halfstepback_flag = 0; - else error->all(FLERR,"Illegal min_modify command"); + halfstepback_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"initialdelay") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal min_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) delaystep_start_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) delaystep_start_flag = 0; - else error->all(FLERR,"Illegal min_modify command"); + delaystep_start_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"vdfmax") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal min_modify command"); diff --git a/src/neighbor.cpp b/src/neighbor.cpp index d58823063c..74bb3bf762 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -915,11 +915,14 @@ int Neighbor::init_pair() requests[i]->index_bin = -1; flag = lists[i]->bin_method; if (flag == 0) continue; - for (j = 0; j < nbin; j++) - if (neigh_bin[j]->istyle == flag) break; - if (j < nbin && !requests[i]->unique) { - requests[i]->index_bin = j; - continue; + if (!requests[i]->unique) { + for (j = 0; j < nbin; j++) + if (neigh_bin[j]->istyle == flag && + neigh_bin[j]->cutoff_custom == 0.0) break; + if (j < nbin) { + requests[i]->index_bin = j; + continue; + } } BinCreator &bin_creator = binclass[flag-1]; @@ -936,11 +939,14 @@ int Neighbor::init_pair() requests[i]->index_stencil = -1; flag = lists[i]->stencil_method; if (flag == 0) continue; - for (j = 0; j < nstencil; j++) - if (neigh_stencil[j]->istyle == flag) break; - if (j < nstencil && !requests[i]->unique) { - requests[i]->index_stencil = j; - continue; + if (!requests[i]->unique) { + for (j = 0; j < nstencil; j++) + if (neigh_stencil[j]->istyle == flag && + neigh_stencil[j]->cutoff_custom == 0.0) break; + if (j < nstencil) { + requests[i]->index_stencil = j; + continue; + } } StencilCreator &stencil_creator = stencilclass[flag-1]; @@ -2404,15 +2410,11 @@ void Neighbor::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"check") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) dist_check = 1; - else if (strcmp(arg[iarg+1],"no") == 0) dist_check = 0; - else error->all(FLERR,"Illegal neigh_modify command"); + dist_check = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"once") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) build_once = 1; - else if (strcmp(arg[iarg+1],"no") == 0) build_once = 0; - else error->all(FLERR,"Illegal neigh_modify command"); + build_once = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"page") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); @@ -2432,9 +2434,7 @@ void Neighbor::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"cluster") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) cluster_check = 1; - else if (strcmp(arg[iarg+1],"no") == 0) cluster_check = 0; - else error->all(FLERR,"Illegal neigh_modify command"); + cluster_check = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"include") == 0) { @@ -2521,6 +2521,7 @@ void Neighbor::modify_params(int narg, char **arg) int i; // Invalidate old user cutoffs + comm->ncollections_cutoff = 0; interval_collection_flag = 1; custom_collection_flag = 1; @@ -2552,9 +2553,10 @@ void Neighbor::modify_params(int narg, char **arg) error->all(FLERR,"Invalid collection/type command"); int ntypes = atom->ntypes; - int n, nlo, nhi, i, j, k; + int nlo, nhi, i, k; // Invalidate old user cutoffs + comm->ncollections_cutoff = 0; interval_collection_flag = 0; custom_collection_flag = 1; @@ -2562,10 +2564,12 @@ void Neighbor::modify_params(int narg, char **arg) memory->create(type2collection,ntypes+1,"neigh:type2collection"); // Erase previous mapping + for (i = 1; i <= ntypes; i++) type2collection[i] = -1; // For each custom range, define mapping for types in interval + for (i = 0; i < ncollections; i++){ std::vector words = Tokenizer(arg[iarg+2+i], ",").as_vector(); for (const auto &word : words) { @@ -2579,6 +2583,7 @@ void Neighbor::modify_params(int narg, char **arg) } // Check for undefined atom type + for (i = 1; i <= ntypes; i++){ if (type2collection[i] == -1) { error->all(FLERR,"Type missing in collection/type commnd"); diff --git a/src/pair.cpp b/src/pair.cpp index 38a21481cd..1039875718 100644 --- a/src/pair.cpp +++ b/src/pair.cpp @@ -167,9 +167,7 @@ void Pair::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"shift") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) offset_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) offset_flag = 0; - else error->all(FLERR,"Illegal pair_modify command"); + offset_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"table") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command"); @@ -193,15 +191,11 @@ void Pair::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"tail") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) tail_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) tail_flag = 0; - else error->all(FLERR,"Illegal pair_modify command"); + tail_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"compute") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command"); - if (strcmp(arg[iarg+1],"yes") == 0) compute_flag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) compute_flag = 0; - else error->all(FLERR,"Illegal pair_modify command"); + compute_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"nofdotr") == 0) { no_virial_fdotr_compute = 1; @@ -1805,7 +1799,7 @@ void Pair::write_file(int narg, char **arg) // write out a line with "DATE:" and "UNITS:" tags // - if the file already exists, print a message about appending // while printing the date and check that units are consistent. - if (utils::file_is_readable(table_file)) { + if (platform::file_is_readable(table_file)) { std::string units = utils::get_potential_units(table_file,"table"); if (!units.empty() && (units != update->unit_style)) { error->one(FLERR,"Trying to append to a table file " diff --git a/src/pair_hybrid.cpp b/src/pair_hybrid.cpp index 67e0a70249..b5daa111da 100644 --- a/src/pair_hybrid.cpp +++ b/src/pair_hybrid.cpp @@ -512,13 +512,16 @@ void PairHybrid::coeff(int narg, char **arg) // then unset setflag/map assigned to that style before setting it below // in case pair coeff for this sub-style is being called for 2nd time - if (!none && styles[m]->one_coeff) + if (!none && styles[m]->one_coeff) { + if ((strcmp(arg[0],"*") != 0) || (strcmp(arg[1],"*") != 0)) + error->all(FLERR,"Incorrect args for pair coefficients"); for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) if (nmap[i][j] && map[i][j][0] == m) { setflag[i][j] = 0; nmap[i][j] = 0; } + } // set setflag and which type pairs map to which sub-style // if sub-style is none: set hybrid setflag, wipe out map @@ -918,8 +921,7 @@ void PairHybrid::modify_params(int narg, char **arg) again: if (iarg < narg && strcmp(arg[iarg],"special") == 0) { - if (narg < iarg+5) - error->all(FLERR,"Illegal pair_modify special command"); + if (narg < iarg+5) error->all(FLERR,"Illegal pair_modify special command"); modify_special(m,narg-iarg,&arg[iarg+1]); iarg += 5; goto again; @@ -929,13 +931,8 @@ again: // set flag to register TALLY computes accordingly if (iarg < narg && strcmp(arg[iarg],"compute/tally") == 0) { - if (narg < iarg+2) - error->all(FLERR,"Illegal pair_modify compute/tally command"); - if (strcmp(arg[iarg+1],"yes") == 0) { - compute_tally[m] = 1; - } else if (strcmp(arg[iarg+1],"no") == 0) { - compute_tally[m] = 0; - } else error->all(FLERR,"Illegal pair_modify compute/tally command"); + if (narg < iarg+2) error->all(FLERR,"Illegal pair_modify compute/tally command"); + compute_tally[m] = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; goto again; } diff --git a/src/pair_hybrid_overlay.cpp b/src/pair_hybrid_overlay.cpp index db12750f40..e93473e3c9 100644 --- a/src/pair_hybrid_overlay.cpp +++ b/src/pair_hybrid_overlay.cpp @@ -70,6 +70,12 @@ void PairHybridOverlay::coeff(int narg, char **arg) arg[2+multflag] = arg[1]; arg[1+multflag] = arg[0]; + // ensure that one_coeff flag is honored + + if (!none && styles[m]->one_coeff) + if ((strcmp(arg[0],"*") != 0) || (strcmp(arg[1],"*") != 0)) + error->all(FLERR,"Incorrect args for pair coefficients"); + // invoke sub-style coeff() starting with 1st remaining arg if (!none) styles[m]->coeff(narg-1-multflag,arg+1+multflag); diff --git a/src/pair_hybrid_scaled.cpp b/src/pair_hybrid_scaled.cpp index 90e30dd9b2..5bf593d147 100644 --- a/src/pair_hybrid_scaled.cpp +++ b/src/pair_hybrid_scaled.cpp @@ -474,6 +474,12 @@ void PairHybridScaled::coeff(int narg, char **arg) arg[2 + multflag] = arg[1]; arg[1 + multflag] = arg[0]; + // ensure that one_coeff flag is honored + + if (!none && styles[m]->one_coeff) + if ((strcmp(arg[0],"*") != 0) || (strcmp(arg[1],"*") != 0)) + error->all(FLERR,"Incorrect args for pair coefficients"); + // invoke sub-style coeff() starting with 1st remaining arg if (!none) styles[m]->coeff(narg - 1 - multflag, &arg[1 + multflag]); diff --git a/src/pair_table.cpp b/src/pair_table.cpp index 60272b5276..7b77a847f1 100644 --- a/src/pair_table.cpp +++ b/src/pair_table.cpp @@ -407,7 +407,7 @@ void PairTable::read_table(Table *tb, char *file, char *keyword) rfile = values.next_double(); tb->efile[i] = conversion_factor * values.next_double(); tb->ffile[i] = conversion_factor * values.next_double(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { ++cerror; } diff --git a/src/platform.cpp b/src/platform.cpp new file mode 100644 index 0000000000..b057c6415b --- /dev/null +++ b/src/platform.cpp @@ -0,0 +1,974 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + 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. +------------------------------------------------------------------------- */ +/** \file platform.cpp + * This file provides abstractions for a variety of platform specific + * functionality in a namespace "platform". This is a companion to + * the "utils" namespace with convenience and utility functions. */ + +#include "platform.h" +#include "text_file_reader.h" +#include "utils.h" + +#if HAVE_MPI +#include +#endif + +//////////////////////////////////////////////////////////////////////// +// include system headers and tweak system settings +#if defined(_WIN32) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#if defined(_WIN32_WINNT) +#undef _WIN32_WINNT +#endif + +// target Windows version is windows 7 and later +#define _WIN32_WINNT _WIN32_WINNT_WIN7 +#define PSAPI_VERSION 2 + +#include +#include // for _get_osfhandle() +#include +#include + +#else // not Windows /////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if defined(__APPLE__) +#include +#include +#endif +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +/* ------------------------------------------------------------------ */ + +/// Struct for listing on-the-fly compression/decompression commands +struct compress_info { + /// identifier for the different compression algorithms + enum styles { NONE, GZIP, BZIP2, ZSTD, XZ, LZMA, LZ4 }; + const std::string extension; ///< filename extension for the current algorithm + const std::string command; ///< command to perform compression or decompression + const std::string compressflags; ///< flags to append to compress from stdin to stdout + const std::string uncompressflags; ///< flags to decompress file to stdout + const int style; ///< compression style flag +}; + +// clang-format off +static const std::vector compress_styles = { + {"", "", "", "", compress_info::NONE}, + {"gz", "gzip", " > ", " -cdf ", compress_info::GZIP}, + {"bz2", "bzip2", " > ", " -cdf ", compress_info::BZIP2}, + {"zst", "zstd", " -q > ", " -cdf ", compress_info::ZSTD}, + {"xz", "xz", " > ", " -cdf ", compress_info::XZ}, + {"lzma", "xz", " --format=lzma > ", " --format=lzma -cdf ", compress_info::LZMA}, + {"lz4", "lz4", " > ", " -cdf ", compress_info::LZ4}, +}; +// clang-format on + +/* ------------------------------------------------------------------ */ + +static const compress_info &find_compress_type(const std::string &file) +{ + std::size_t dot = file.find_last_of('.'); + if (dot != std::string::npos) { + const std::string ext = file.substr(dot + 1); + for (const auto &i : compress_styles) { + if (i.extension == ext) return i; + } + } + return compress_styles[0]; +} + +/* ------------------------------------------------------------------ */ + +// set reference time stamp during executable/library init. +// should provide better resolution than using epoch, if the system clock supports it. +static auto initial_time = std::chrono::steady_clock::now(); + +using namespace LAMMPS_NS; + +// get CPU time + +// clang-format off +// clang compilers are optimizing this function too aggressively returning always 0 +#if defined(__clang__) +[[clang::optnone]] +#elif defined(_MSC_VER) +#pragma optimize("",off) +#endif +double platform::cputime() +// clang-format on +{ + double rv = 0.0; + +#ifdef _WIN32 + + // from MSD docs. + FILETIME ct, et, kt, ut; + union { + FILETIME ft; + uint64_t ui; + } cpu; + if (GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) { + cpu.ft = ut; + rv = cpu.ui * 0.0000001; + } + +#else /* ! _WIN32 */ + + struct rusage ru; + if (getrusage(RUSAGE_SELF, &ru) == 0) { + rv = (double) ru.ru_utime.tv_sec; + rv += (double) ru.ru_utime.tv_usec * 0.000001; + } + +#endif + + return rv; +} +#if defined(_MSC_VER) +#pragma optimize("", on) +#endif + +/* ---------------------------------------------------------------------- + get wall time +------------------------------------------------------------------------ */ +double platform::walltime() +{ + return std::chrono::duration(std::chrono::steady_clock::now() - initial_time).count(); +} + +/* ---------------------------------------------------------------------- + sleep with microsecond resolution +------------------------------------------------------------------------ */ +void platform::usleep(int usec) +{ + return std::this_thread::sleep_for(std::chrono::microseconds(usec)); +} + +/* ---------------------------------------------------------------------- + get Operating system and version info +------------------------------------------------------------------------- */ + +std::string platform::os_info() +{ + std::string buf; + +#if defined(_WIN32) + + // Get Windows Edition name from registry + char value[1024]; + DWORD value_length = 1024; + const char *subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; + const char *entry = "ProductName"; + RegGetValue(HKEY_LOCAL_MACHINE, subkey, entry, RRF_RT_REG_SZ, nullptr, &value, + (LPDWORD) &value_length); + // enforce zero termination + value[1023] = '\0'; + buf = value; + + DWORD fullversion, majorv, minorv, buildv = 0; + fullversion = GetVersion(); + majorv = (DWORD) (LOBYTE(LOWORD(fullversion))); + minorv = (DWORD) (HIBYTE(LOWORD(fullversion))); + if (fullversion < 0x80000000) buildv = (DWORD) (HIWORD(fullversion)); + + buf += ", Windows ABI " + std::to_string(majorv) + "." + std::to_string(minorv) + " (" + + std::to_string(buildv) + ") on "; + + SYSTEM_INFO si; + GetSystemInfo(&si); + + switch (si.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_AMD64: + buf += "x86_64"; + break; + case PROCESSOR_ARCHITECTURE_ARM: + buf += "arm"; + break; + case PROCESSOR_ARCHITECTURE_IA64: + buf += "ia64"; + break; + case PROCESSOR_ARCHITECTURE_INTEL: + buf += "i386"; + break; + default: + buf += "(unknown)"; + } +#else + struct utsname ut; + uname(&ut); + + // try to get OS distribution name, if available + buf = ut.sysname; + + if (platform::file_is_readable("/etc/os-release")) { + try { + TextFileReader reader("/etc/os-release",""); + while (1) { + auto words = reader.next_values(0,"="); + if ((words.count() > 1) && (words.next_string() == "PRETTY_NAME")) { + buf += " " + utils::trim(words.next_string()); + break; + } + } + } catch (std::exception &e) { + ; // EOF but keyword not found + } + } + + buf += std::string(" ") + ut.release + " " + ut.machine; +#endif + return buf; +} + +/* ---------------------------------------------------------------------- + identify C++ standard version +------------------------------------------------------------------------- */ + +std::string platform::cxx_standard() +{ +#if __cplusplus > 202002L + return "newer than C++20"; +#elif __cplusplus == 202002L + return "C++20"; +#elif __cplusplus == 201703L + return "C++17"; +#elif __cplusplus == 201402L + return "C++14"; +#elif __cplusplus == 201103L + return "C++11"; +#elif __cplusplus == 199711L + return "C++98"; +#else + return "unknown"; +#endif +} + +/* ---------------------------------------------------------------------- + identify compiler and its version +------------------------------------------------------------------------- */ + +std::string platform::compiler_info() +{ + std::string buf = "(Unknown)"; +#if defined(__INTEL_LLVM_COMPILER) + double version = static_cast(__INTEL_LLVM_COMPILER) * 0.01; + buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__); +#elif defined(__ibmxl__) + buf = fmt::format("IBM XL C/C++ (Clang) {}.{}.{}", __ibmxl_version__, __ibmxl_release__, + __ibmxl_modification__); +#elif defined(__clang__) + buf = fmt::format("Clang C++ {}", __VERSION__); +#elif defined(__PGI) + buf = fmt::format("PGI C++ {}.{}", __PGIC__, __PGIC_MINOR__); +#elif defined(__INTEL_COMPILER) +#if !defined(__VERSION__) +#define __VERSION__ __INTEL_COMPILER_BUILD_DATE +#endif + double version = static_cast(__INTEL_COMPILER) * 0.01; + buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version, __INTEL_COMPILER_UPDATE, + __VERSION__); +#elif defined(__MINGW64__) + buf = fmt::format("MinGW-w64 64bit {}.{} / GNU C++ {}", __MINGW64_VERSION_MAJOR, + __MINGW64_VERSION_MINOR, __VERSION__); +#elif defined(__MINGW32__) + buf = fmt::format("MinGW-w64 32bit {}.{} / GNU C++ {}", __MINGW32_MAJOR_VERSION, + __MINGW32_MINOR_VERSION, __VERSION__); +#elif defined(__GNUC__) + buf = fmt::format("GNU C++ {}", __VERSION__); +#elif defined(_MSC_VER) && (_MSC_VER > 1920) && (_MSC_VER < 2000) + constexpr int major = _MSC_VER / 100; + constexpr int minor = _MSC_VER - major * 100; + buf = "Microsoft Visual Studio 20" + std::to_string(major) + ", C/C++ " + + std::to_string(major - 5) + "." + std::to_string(minor); +#else + buf = "(Unknown)"; +#endif + return buf; +} + +/* ---------------------------------------------------------------------- + detect OpenMP standard +------------------------------------------------------------------------- */ + +std::string platform::openmp_standard() +{ + +#if !defined(_OPENMP) + return "OpenMP not enabled"; +#else + + // Supported OpenMP version corresponds to the release date of the + // specifications as posted at https://www.openmp.org/specifications/ + +#if _OPENMP > 202011 + return "OpenMP newer than version 5.1"; +#elif _OPENMP == 202011 + return "OpenMP 5.1"; +#elif _OPENMP == 201811 + return "OpenMP 5.0"; +#elif _OPENMP == 201611 + return "OpenMP 5.0 preview 1"; +#elif _OPENMP == 201511 + return "OpenMP 4.5"; +#elif _OPENMP == 201307 + return "OpenMP 4.0"; +#elif _OPENMP == 201107 + return "OpenMP 3.1"; +#elif _OPENMP == 200805 + return "OpenMP 3.0"; +#elif _OPENMP == 200505 + return "OpenMP 2.5"; +#elif _OPENMP == 200203 + return "OpenMP 2.0"; +#else + return "unknown OpenMP version"; +#endif + +#endif +} + +/* ---------------------------------------------------------------------- + identify MPI vendor from defines in the mpi.h file. +------------------------------------------------------------------------- */ + +std::string platform::mpi_vendor() +{ +#if defined(MPI_STUBS) + return "MPI STUBS"; +#elif defined(OPEN_MPI) + return "Open MPI"; +#elif defined(MPICH_NAME) + return "MPICH"; +#elif defined(I_MPI_VERSION) + return "Intel MPI"; +#elif defined(PLATFORM_MPI) + return "Platform MPI"; +#elif defined(HP_MPI) + return "HP MPI"; +#elif defined(MSMPI_VER) + // Get Microsoft MPI version from registry + char value[1024]; + DWORD value_length = 1024; + const char *subkey = "SOFTWARE\\Microsoft\\MPI"; + const char *entry = "Version"; + auto rv = RegGetValueA(HKEY_LOCAL_MACHINE, subkey, entry, RRF_RT_REG_SZ, nullptr, &value, + (LPDWORD) &value_length); + std::string buf = "Microsoft MPI"; + if (rv == ERROR_SUCCESS) buf += std::string(" v") + value; + return buf; +#else + return "Unknown MPI implementation"; +#endif +} + +/* ---------------------------------------------------------------------- + detect MPI version info +------------------------------------------------------------------------- */ + +std::string platform::mpi_info(int &major, int &minor) +{ + int len = 0; +#if (defined(MPI_VERSION) && (MPI_VERSION > 2)) || defined(MPI_STUBS) + static char version[MPI_MAX_LIBRARY_VERSION_STRING]; + MPI_Get_library_version(version, &len); + if (len > 80) { + char *ptr = strchr(version + 80, '\n'); + if (ptr) *ptr = '\0'; + } +#else + constexpr int MAX_VERSION_STRING = 32; + static char version[MAX_VERSION_STRING]; + strncpy(version, mpi_vendor().c_str(), MAX_VERSION_STRING); +#endif + +#if defined(MPI_VERSION) + MPI_Get_version(&major, &minor); +#else + major = 1; + minor = 0; +#endif + return std::string(version); +} + +/* ---------------------------------------------------------------------- + set environment variable +------------------------------------------------------------------------- */ + +int platform::putenv(const std::string &vardef) +{ + if (vardef.size() == 0) return -1; + + auto found = vardef.find_first_of('='); +#ifdef _WIN32 + // must assign a value to variable with _putenv() + if (found == std::string::npos) + return _putenv(utils::strdup(vardef + "=1")); + else + return _putenv(utils::strdup(vardef)); +#else + if (found == std::string::npos) + return setenv(vardef.c_str(), "", 1); + else + return setenv(vardef.substr(0, found).c_str(), vardef.substr(found + 1).c_str(), 1); +#endif + return -1; +} + +/* ---------------------------------------------------------------------- + split a "path" environment variable into a list +------------------------------------------------------------------------- */ + +std::vector platform::list_pathenv(const std::string &var) +{ + std::vector dirs; + const char *ptr = getenv(var.c_str()); + if (ptr == nullptr) return dirs; + + std::string pathvar = ptr; + std::size_t first = 0, next; + while (true) { + next = pathvar.find_first_of(pathvarsep, first); + if (next == std::string::npos) { + dirs.push_back(pathvar.substr(first)); + break; + } else { + dirs.push_back(pathvar.substr(first, next - first)); + first = next + 1; + } + } + return dirs; +} + +/* ---------------------------------------------------------------------- + find the full path name of an executable +------------------------------------------------------------------------- */ + +std::string platform::find_exe_path(const std::string &cmd) +{ + if (cmd.size() == 0) return ""; + auto pathdirs = list_pathenv("PATH"); +#ifdef _WIN32 + // windows always looks in "." and does it first + pathdirs.insert(pathdirs.begin(), "."); +#else + struct stat info; +#endif + for (const auto &dir : pathdirs) { + std::string exe = path_join(dir, cmd); +#ifdef _WIN32 + const char *extensions[] = {".exe", ".com", ".bat", nullptr}; + for (auto ext = extensions; *ext != nullptr; ++ext) { + auto exe_path = exe + *ext; + if (file_is_readable(exe_path)) return exe_path; + } +#else + memset(&info, 0, sizeof(info)); + if (stat(exe.c_str(), &info) != 0) continue; + if ((info.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) != 0) return exe; +#endif + } + return ""; +} + +/* ---------------------------------------------------------------------- + wrapper functions for loading shared objects and libraries +------------------------------------------------------------------------- */ + +#ifdef _WIN32 + +// open a shared object file +void *platform::dlopen(const std::string &fname) +{ + return (void *) LoadLibrary(fname.c_str()); +} + +// return dynamic linker error string + +std::string platform::dlerror() +{ + return ""; +} + +// close a shared object +int platform::dlclose(void *handle) +{ + /* FreeLibrary returns nonzero on success unlike dlclose() */ + return (FreeLibrary((HINSTANCE) handle) == 0); +} + +// resolve a symbol in shared object +void *platform::dlsym(void *handle, const std::string &symbol) +{ + return (void *) GetProcAddress((HINSTANCE) handle, symbol.c_str()); +} + +#else + +// open a shared object file +void *platform::dlopen(const std::string &fname) +{ + return ::dlopen(fname.c_str(), RTLD_NOW | RTLD_GLOBAL); +} + +// return dynamic linker error string + +std::string platform::dlerror() +{ + const char *errmesg = ::dlerror(); + if (errmesg) return std::string(errmesg); + else return ""; +} + +// close a shared object +int platform::dlclose(void *handle) +{ + return ::dlclose(handle); +} + +// resolve a symbol in shared object +void *platform::dlsym(void *handle, const std::string &symbol) +{ + return ::dlsym(handle, symbol.c_str()); +} +#endif + +/* ---------------------------------------------------------------------- */ + +/** On Linux the folder /proc/self/fd holds symbolic links to the actual + * pathnames associated with each open file descriptor of the current process. + * On MacOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. + * On Windows we use ``GetFinalPathNameByHandleA()`` which is available with + * Windows Vista and later. If the buffer is too small (< 16 bytes) a null pointer is returned. + * + * This function is used to provide a filename with error messages in functions + * where the filename is not passed as an argument, but the FILE * pointer. */ + +const char *platform::guesspath(FILE *fp, char *buf, int len) +{ + // no point in guessing a path with a short buffer or NULL pointer as buffer + if ((buf == nullptr) || (len < 16)) return nullptr; + + // zero buffer and reserve last character in buffer for terminating '\0' + memset(buf, 0, len); + len--; + +#if defined(__linux__) + + int fd = fileno(fp); + // get pathname from /proc or copy (unknown) + if (readlink((std::string("/proc/self/fd/") + std::to_string(fd)).c_str(), buf, len) <= 0) + strncpy(buf, "(unknown)", len); + +#elif defined(__APPLE__) + + int fd = fileno(fp); + char filepath[PATH_MAX]; + if (fcntl(fd, F_GETPATH, filepath) != -1) + strncpy(buf, filepath, len); + else + strncpy(buf, "(unknown)", len); + +#elif defined(_WIN32) + + char filepath[MAX_PATH]; + HANDLE h = (HANDLE) _get_osfhandle(_fileno(fp)); + if (GetFinalPathNameByHandleA(h, filepath, MAX_PATH, FILE_NAME_NORMALIZED) > 0) + strncpy(buf, filepath, len); + else + strncpy(buf, "(unknown)", len); + +#else // unsupported OS + + strncpy(buf, "(unknown)", len); + +#endif + + return buf; +} + +/* ---------------------------------------------------------------------- + detect terminal, e.g. for using a pager automatically +------------------------------------------------------------------------- */ + +bool platform::is_console(FILE *fp) +{ + if (!fp) return false; +#if defined(_WIN32) + return (_isatty(_fileno(fp)) == 1); +#else + return (isatty(fileno(fp)) == 1); +#endif +} + +/* ---------------------------------------------------------------------- + Get string with path to the current directory + PATH_MAX may not be a compile time constant, so we must allocate and delete a buffer. +------------------------------------------------------------------------- */ + +std::string platform::current_directory() +{ + std::string cwd = ""; + +#if defined(_WIN32) + char *buf = new char[MAX_PATH]; + if (_getcwd(buf, MAX_PATH)) { cwd = buf; } + delete[] buf; +#else + char *buf = new char[PATH_MAX]; + if (::getcwd(buf, PATH_MAX)) { cwd = buf; } + delete[] buf; +#endif + return cwd; +} + +/* ---------------------------------------------------------------------- + check if a path is a directory +------------------------------------------------------------------------- */ + +bool platform::path_is_directory(const std::string &path) +{ +#if defined(_WIN32) + struct _stat info; + memset(&info, 0, sizeof(info)); + if (_stat(path.c_str(), &info) != 0) return false; +#else + struct stat info; + memset(&info, 0, sizeof(info)); + if (stat(path.c_str(), &info) != 0) return false; +#endif + return ((info.st_mode & S_IFDIR) != 0); +} + +/* ---------------------------------------------------------------------- + get directory listing in string vector +------------------------------------------------------------------------- */ + +std::vector platform::list_directory(const std::string &dir) +{ + std::vector files; + if (!path_is_directory(dir)) return files; + +#if defined(_WIN32) + HANDLE handle; + WIN32_FIND_DATA fd; + std::string searchname = dir + filepathsep[0] + "*"; + handle = FindFirstFile(searchname.c_str(), &fd); + if (handle == ((HANDLE) -1)) return files; + while (FindNextFile(handle, &fd)) { + std::string entry(fd.cFileName); + if ((entry == "..") || (entry == ".")) continue; + files.push_back(entry); + } + FindClose(handle); +#else + std::string dirname = dir + filepathsep[0]; + DIR *handle = opendir(dirname.c_str()); + if (handle == nullptr) return files; + struct dirent *fd; + while ((fd = readdir(handle)) != nullptr) { + std::string entry(fd->d_name); + if ((entry == "..") || (entry == ".")) continue; + files.push_back(entry); + } + closedir(handle); +#endif + return files; +} + +/* ---------------------------------------------------------------------- + Change current directory +------------------------------------------------------------------------- */ + +int platform::chdir(const std::string &path) +{ +#if defined(_WIN32) + return ::_chdir(path.c_str()); +#else + return ::chdir(path.c_str()); +#endif +} + +/* ---------------------------------------------------------------------- + Create a directory +------------------------------------------------------------------------- */ + +int platform::mkdir(const std::string &path) +{ +#if defined(_WIN32) + return ::_mkdir(path.c_str()); +#else + return ::mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP); +#endif +} + +/* ---------------------------------------------------------------------- + Delete a directory and its contents recursively +------------------------------------------------------------------------- */ + +int platform::rmdir(const std::string &path) +{ + // recurse through directory tree deleting files and directories + auto entries = list_directory(path); + for (const auto &entry : entries) { + const auto newpath = path_join(path, entry); + if (path_is_directory(newpath)) + rmdir(newpath); + else + unlink(newpath); + } +#if defined(_WIN32) + return ::_rmdir(path.c_str()); +#else + return ::rmdir(path.c_str()); +#endif +} + +/* ---------------------------------------------------------------------- + Delete a file +------------------------------------------------------------------------- */ + +int platform::unlink(const std::string &path) +{ +#if defined(_WIN32) + return ::_unlink(path.c_str()); +#else + return ::unlink(path.c_str()); +#endif +} + +/* ---------------------------------------------------------------------- + Get current file stream position +------------------------------------------------------------------------- */ + +bigint platform::ftell(FILE *fp) +{ +#if defined(_WIN32) + return (bigint)::_ftelli64(fp); +#else + return (bigint)::ftell(fp); +#endif +} + +/* ---------------------------------------------------------------------- + Set current file stream position +------------------------------------------------------------------------- */ + +int platform::fseek(FILE *fp, bigint pos) +{ +#if defined(_WIN32) + if (pos == platform::END_OF_FILE) + return ::_fseeki64(fp, 0, SEEK_END); + else + return ::_fseeki64(fp, (__int64) pos, SEEK_SET); +#else + if (pos == platform::END_OF_FILE) + return ::fseek(fp, 0, SEEK_END); + else + return ::fseek(fp, (long) pos, SEEK_SET); +#endif +} + +/* ---------------------------------------------------------------------- + Truncate opened file to given length +------------------------------------------------------------------------- */ + +int platform::ftruncate(FILE *fp, bigint length) +{ +#if defined(_WIN32) + HANDLE h = (HANDLE) _get_osfhandle(_fileno(fp)); + LARGE_INTEGER li_start, li_length; + li_start.QuadPart = (int64_t) 0; + li_length.QuadPart = (int64_t) length; + if (SetFilePointerEx(h, li_start, NULL, FILE_CURRENT) && + SetFilePointerEx(h, li_length, NULL, FILE_BEGIN) && SetEndOfFile(h)) { + return 0; + } else { + return 1; + } +#else + platform::fseek(fp, length); + return ::ftruncate(fileno(fp), (off_t) length); +#endif +} + +/* ---------------------------------------------------------------------- + open pipe +------------------------------------------------------------------------- */ + +FILE *platform::popen(const std::string &cmd, const std::string &mode) +{ + FILE *fp = nullptr; +#if defined(_WIN32) + if (mode == "r") + fp = ::_popen(cmd.c_str(), "rb"); + else if (mode == "w") + fp = ::_popen(cmd.c_str(), "wb"); +#else + if (mode == "r") + fp = ::popen(cmd.c_str(), "r"); + else if (mode == "w") + fp = ::popen(cmd.c_str(), "w"); +#endif + return fp; +} + +/* ---------------------------------------------------------------------- + close pipe +------------------------------------------------------------------------- */ + +int platform::pclose(FILE *fp) +{ +#if defined(_WIN32) + return ::_pclose(fp); +#else + return ::pclose(fp); +#endif +} + +/* ---------------------------------------------------------------------- + strip off leading part of path, return just the filename +------------------------------------------------------------------------- */ + +std::string platform::path_basename(const std::string &path) +{ + size_t start = path.find_last_of(platform::filepathsep); + + if (start == std::string::npos) { + start = 0; + } else { + start += 1; + } + + return path.substr(start); +} + +/* ---------------------------------------------------------------------- + Return only the leading part of a path, return just the directory +------------------------------------------------------------------------- */ + +std::string platform::path_dirname(const std::string &path) +{ + size_t start = path.find_last_of(platform::filepathsep); + + if (start == std::string::npos) return "."; + + return path.substr(0, start); +} + +/* ---------------------------------------------------------------------- + join two paths. + if one of the two is an empty string just return the other unmodified + if the first string ends in the separator or the second begins with one, trim them +------------------------------------------------------------------------- */ + +std::string platform::path_join(const std::string &a, const std::string &b) +{ + if (a.empty()) return b; + if (b.empty()) return a; + + // remove trailing separator(s) in first part + std::string joined = a; + while (joined.find_last_of(platform::filepathsep) == joined.size() - 1) { + for (const auto &s : platform::filepathsep) + if (joined.back() == s) joined.pop_back(); + } + + // skip over leading separator(s) in second part + std::size_t skip = 0; + while (b.find_first_of(platform::filepathsep, skip) == skip) ++skip; + + // combine and return + joined += platform::filepathsep[0] + b.substr(skip); + return joined; +} + +/* ---------------------------------------------------------------------- + try to open file for reading to prove if it exists and is accessible +------------------------------------------------------------------------- */ + +bool platform::file_is_readable(const std::string &path) +{ + FILE *fp = fopen(path.c_str(), "r"); + if (fp) { + fclose(fp); + return true; + } + return false; +} + +/* ---------------------------------------------------------------------- + check if filename has a known compression extension +------------------------------------------------------------------------- */ + +bool platform::has_compress_extension(const std::string &file) +{ + return find_compress_type(file).style != compress_info::NONE; +} + +/* ---------------------------------------------------------------------- + open pipe to read a compressed file +------------------------------------------------------------------------- */ + +FILE *platform::compressed_read(const std::string &file) +{ + FILE *fp = nullptr; + +#if defined(LAMMPS_GZIP) + auto compress = find_compress_type(file); + if (compress.style == compress_info::NONE) return nullptr; + + if (find_exe_path(compress.command).size()) + // put quotes around file name so that they may contain blanks + fp = popen((compress.command + compress.uncompressflags + "\"" + file + "\""), "r"); +#endif + return fp; +} + +/* ---------------------------------------------------------------------- + open pipe to write a compressed file +------------------------------------------------------------------------- */ + +FILE *platform::compressed_write(const std::string &file) +{ + FILE *fp = nullptr; + +#if defined(LAMMPS_GZIP) + auto compress = find_compress_type(file); + if (compress.style == compress_info::NONE) return nullptr; + + if (find_exe_path(compress.command).size()) + // put quotes around file name so that they may contain blanks + fp = popen((compress.command + compress.compressflags + "\"" + file + "\""), "w"); +#endif + return fp; +} + +/* ---------------------------------------------------------------------- */ diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 0000000000..de8ecce016 --- /dev/null +++ b/src/platform.h @@ -0,0 +1,383 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + 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_PLATFORM_H +#define LMP_PLATFORM_H + +/*! \file platform.h */ + +#include "lmptype.h" + +#include +#include + +namespace LAMMPS_NS { +namespace platform { + + /*! Return the consumed CPU time for the current process in seconds + * + * This is a wrapper around the POSIX function getrusage() and its Windows equivalent. + * It is to be used in a similar fashion than MPI_Wtime(). Its resolution may + * be rather low so it can only be trusted when observing processes consuming at + * seconds or more of CPU time. + * + * \return used CPU time in seconds */ + + double cputime(); + + /*! Return the wall clock state for the current process in seconds + * + * This this clock is counting continuous time is initialized during + * Load of the executable/library. Its absolute value must be considered + * arbitrary and thus elapsed wall times are measured in taking differences. + * It is therefore to be used in a similar fashion as MPI_Wtime() but + * has a different offset, usually leading to better resolution. + * + * \return wall clock time in seconds */ + + double walltime(); + + /*! Suspend execution for a microsecond interval + * + * This emulates the usleep(3) BSD function call also mentioned in POSIX.1-2001. + * This is not a precise delay; it may be longer, but not shorter. + * + * \param usec length of delay in microseconds */ + + void usleep(int usec); + + /*! Return string with the operating system version and architecture info + * + * \return string with info about the OS and the platform is is running on */ + + std::string os_info(); + + /*! Return string with C++ standard version used to compile LAMMPS. + * + * This function uses predefined compiler macros to identify + * the C++ standard version used to compile LAMMPS with. + * + * \return string with the C++ standard version or "unknown" */ + + std::string cxx_standard(); + + /*! Return string with compiler version info + * + * This function uses predefined compiler macros to identify + * Compilers and their version and configuration info. + * + * \return string with the compiler information text */ + + std::string compiler_info(); + + /*! Return string with OpenMP standard version info + * + * This function uses predefined compiler macros to identify + * OpenMP support and the supported version of the standard. + * + * \return string with the openmp information text */ + + std::string openmp_standard(); + + /*! Return string with MPI vendor info + * + * This function uses predefined macros to identify + * the vendor of the MPI library used. + * + * \return string with the MPI vendor information text */ + + std::string mpi_vendor(); + + /*! Return string with MPI version info + * + * This function uses predefined macros and MPI function + * calls to identify the version of the MPI library used. + * + * \param major major version of the MPI standard (set on exit) + * \param minor minor version of the MPI standard (set on exit) + * \return string with the MPI version information text */ + + std::string mpi_info(int &major, int &minor); + + /*! Add variable to the environment + * + * \param vardef variable name or variable definition (NAME=value) + * \return -1 if failure otherwise 0 */ + + int putenv(const std::string &vardef); + + /*! Get list of entries in a path environment variable + * + * This provides a list of strings of the entries in an environment + * variable that is containing a "path" like "PATH" or "LD_LIBRARY_PATH". + * + * \param var name of the environment variable + * \return vector with strings of all entries in that path variable */ + + std::vector list_pathenv(const std::string &var); + + /*! Open a shared object file or library + * + * \param fname name or path of the shared object + * \return handle to the shared object or null */ + + void *dlopen(const std::string &fname); + + /*! Obtain error diagnostic info after dynamic linking function calls + * + * Return a human-readable string describing the most recent error that + * occurred when using one of the functions for dynamic loading objects + * the last call to this function. The string is empty, if there was no error. + * + * \return string with error message or empty */ + + std::string dlerror(); + + /*! Close a shared object + * + * This releases the object corresponding to the provided handle. + * Resolved symbols associated with this handle may not be used + * after this call + * + * \param handle handle to an opened shared object + * \return 0 if successful, non-zero of not */ + + int dlclose(void *handle); + + /*! Resolve a symbol in shared object + * + * \param handle handle to an opened shared object + * \param symbol name of the symbol to extract + * \return pointer to the resolved symbol or null */ + + void *dlsym(void *handle, const std::string &symbol); + + /*! Platform specific file path component separator + * + * This is a string with the character that separates directories and filename in paths on + * a platform. If multiple are characters are provided, the first is the preferred one. */ + +#if !defined(_WIN32) + constexpr char filepathsep[] = "/"; +#else + constexpr char filepathsep[] = "\\/"; +#endif + + /*! Platform specific path environment variable component separator + * + * This is the character that separates entries in "PATH"-style environment variables. */ + +#if !defined(_WIN32) + constexpr char pathvarsep = ':'; +#else + constexpr char pathvarsep = ';'; +#endif + + /*! Try to detect pathname from FILE pointer + * + * Currently only supported on Linux, MacOS, and Windows. Otherwise will report "(unknown)". + * + * \param fp FILE pointer struct from STDIO library for which we want to detect the name + * \param buf storage buffer for pathname. output will be truncated if not large enough + * \param len size of storage buffer. output will be truncated to this length - 1 + * \return pointer to the storage buffer with path or a NULL pointer if buf is invalid + * or the buffer size is too small */ + + const char *guesspath(FILE *fp, char *buf, int len); + + /*! Check if a file pointer may be connected to a console + * + * \param fp file pointer + * \return true if the file pointer is flagged as a TTY */ + + bool is_console(FILE *fp); + + /*! Get string with path to the current directory + * + * \return path to the current directory or empty string */ + + std::string current_directory(); + + /*! Check if a path is a directory + * + * \param path directory path + * \return true if the directory exists */ + + bool path_is_directory(const std::string &path); + + /*! Get list of entries in a directory + * + * This provides a list of strings of the entries in the directory + * without the leading path name while also skipping over ".." and ".". + * + * \param dir path to directory + * \return vector with strings of all directory entries */ + + std::vector list_directory(const std::string &dir); + + /*! Find pathname of an executable in the standard search path + * + * This function will traverse the list of directories in the PATH + * environment variable and look for the executable *cmd*. If the + * file exists and is executable the full path is returned as string, + * otherwise and empty string is returned. + * + * On Windows the *cmd* string must not include and extension as + * this function will automatically append the extensions ".exe", + * ".com" and ".bat" and look for those paths. On Windows also the + * current directory is checked (and first), while otherwise not unless + * "." exists in the PATH environment variable. + * + * Because of the nature of the check, this will not detect shell functions + * built-in command or aliases. + * + * \param cmd name of command + * \return vector with strings of all directory entries */ + + std::string find_exe_path(const std::string &cmd); + + /*! Change current directory + * + * \param path new current working directory path + * \return -1 if unsuccessful, otherwise >= 0 */ + + int chdir(const std::string &path); + + /*! Create a directory + * + * \param path directory path + * \return -1 if unsuccessful, otherwise >= 0 */ + + int mkdir(const std::string &path); + + /*! Delete a directory + * + * \param path directory path + * \return -1 if unsuccessful, otherwise >= 0 */ + + int rmdir(const std::string &path); + + /*! Delete a directory and its contents + * + * Unlike the the ``rmdir()`` or ``_rmdir()`` function of the + * C library, this function will check for the contents of the + * folder and recurse into any sub-folders, if necessary and + * delete all contained folders and their contents before + * deleting the folder *path*. + * + * \param path path to file to be deleted + * \return 0 on success, -1 on error */ + + int unlink(const std::string &path); + + /*! Get current file position + * + * \param fp FILE pointer of the given file + * \return current FILE pointer position cast to a bigint */ + + bigint ftell(FILE *fp); + + /*! constant to seek to the end of the file */ + constexpr bigint END_OF_FILE = -1; + + /*! Set absolute file position + * + * If the absolute position is END_OF_FILE, then position at the end of the file. + * + * \param fp FILE pointer of the given file + * \param pos new position of the FILE pointer + * \return 0 if successful, otherwise -1 */ + + int fseek(FILE *fp, bigint pos); + + /*! Truncate file to a given length and re-position file pointer + * + * \param fp FILE pointer of the given file + * \param length length to which the file is being truncated to + * \return 0 if successful, otherwise -1 */ + + int ftruncate(FILE *fp, bigint length); + + /*! Open a pipe to a command for reading or writing + * + * \param cmd command for the pipe + * \param mode "r" for reading from *cmd* or "w" for writing to *cmd* + * \return file pointer to the pipe if successful or null */ + + FILE *popen(const std::string &cmd, const std::string &mode); + + /*! Close a previously opened pipe + * + * \param fp FILE pointer for the pipe + * \return exit status of the pipe command or -1 in case of errors */ + + int pclose(FILE *fp); + + /*! Strip off leading part of path, return just the filename + * + * \param path file path + * \return file name */ + + std::string path_basename(const std::string &path); + + /*! Return the directory part of a path. Return "." if empty + * + * \param path file path + * \return directory name */ + + std::string path_dirname(const std::string &path); + + /*! Join two pathname segments + * + * This uses the forward slash '/' character unless LAMMPS is compiled + * for Windows where it uses the backward slash '\\' + * + * \param a first path + * \param b second path + * \return combined path */ + + std::string path_join(const std::string &a, const std::string &b); + + /*! Check if file exists and is readable + * + * \param path file path + * \return true if file exists and is readable */ + + bool file_is_readable(const std::string &path); + + /*! Check if a file name ends in a known extension for a compressed file format + * + * Currently supported file extensions are: .gz, .bz2, .zst, .xz, .lzma, lz4 + * + * \param file name of the file to check + * \return true if the file has a known extension, otherwise false */ + + bool has_compress_extension(const std::string &file); + + /*! Open pipe to compressed text file for reading + * + * \param file name of the file to open + * \return FILE pointer to pipe using for reading the compressed file. */ + + FILE *compressed_read(const std::string &file); + + /*! Open pipe to compressed text file for writing + * + * \param file name of the file to open + * \return FILE pointer to pipe using for reading the compressed file. */ + + FILE *compressed_write(const std::string &file); + +} // namespace platform +} // namespace LAMMPS_NS +#endif diff --git a/src/pointers.h b/src/pointers.h index 4ae50715c1..55033aae3e 100644 --- a/src/pointers.h +++ b/src/pointers.h @@ -30,6 +30,7 @@ #include "lammps.h" // IWYU pragma: export #include "utils.h" // IWYU pragma: export #include "fmt/format.h" // IWYU pragma: export +#include "platform.h" // IWYU pragma: export namespace LAMMPS_NS { diff --git a/src/read_data.cpp b/src/read_data.cpp index c33c65f676..c17ab97229 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -114,7 +114,7 @@ void ReadData::command(int narg, char **arg) if (narg < 1) error->all(FLERR,"Illegal read_data command"); MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); // optional args @@ -308,7 +308,7 @@ void ReadData::command(int narg, char **arg) // check if data file is available and readable - if (!utils::file_is_readable(arg[0])) + if (!platform::file_is_readable(arg[0])) error->all(FLERR,fmt::format("Cannot open file {}: {}", arg[0], utils::getsyserror())); @@ -741,7 +741,7 @@ void ReadData::command(int narg, char **arg) // close file if (me == 0) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); fp = nullptr; } @@ -914,7 +914,7 @@ void ReadData::command(int narg, char **arg) MPI_Barrier(world); if (comm->me == 0) - utils::logmesg(lmp," read_data CPU = {:.3f} seconds\n",MPI_Wtime()-time1); + utils::logmesg(lmp," read_data CPU = {:.3f} seconds\n",platform::walltime()-time1); } /* ---------------------------------------------------------------------- @@ -1321,7 +1321,7 @@ void ReadData::bonds(int firstpass) int *count = nullptr; if (firstpass) { memory->create(count,nlocal,"read_data:count"); - memset(count,0,nlocal*sizeof(int)); + if (count) memset(count,0,nlocal*sizeof(int)); } // read and process bonds @@ -1395,7 +1395,7 @@ void ReadData::angles(int firstpass) int *count = nullptr; if (firstpass) { memory->create(count,nlocal,"read_data:count"); - memset(count,0,nlocal*sizeof(int)); + if (count) memset(count,0,nlocal*sizeof(int)); } // read and process angles @@ -1469,7 +1469,7 @@ void ReadData::dihedrals(int firstpass) int *count = nullptr; if (firstpass) { memory->create(count,nlocal,"read_data:count"); - memset(count,0,nlocal*sizeof(int)); + if (count) memset(count,0,nlocal*sizeof(int)); } // read and process dihedrals @@ -1543,7 +1543,7 @@ void ReadData::impropers(int firstpass) int *count = nullptr; if (firstpass) { memory->create(count,nlocal,"read_data:count"); - memset(count,0,nlocal*sizeof(int)); + if (count) memset(count,0,nlocal*sizeof(int)); } // read and process impropers @@ -1951,34 +1951,20 @@ int ReadData::reallocate(int **pcount, int cmax, int amax) /* ---------------------------------------------------------------------- proc 0 opens data file - test if gzipped + test if compressed ------------------------------------------------------------------------- */ -void ReadData::open(char *file) +void ReadData::open(const std::string &file) { - if (utils::strmatch(file,"\\.gz$")) { + if (platform::has_compress_extension(file)) { compressed = 1; - -#ifdef LAMMPS_GZIP - auto gunzip = fmt::format("gzip -c -d {}",file); - -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file without gzip support"); -#endif + fp = platform::compressed_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file {}", file); } else { compressed = 0; - fp = fopen(file,"r"); + fp = fopen(file.c_str(),"r"); + if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror()); } - - if (fp == nullptr) - error->one(FLERR,"Cannot open file {}: {}", - file, utils::getsyserror()); } /* ---------------------------------------------------------------------- diff --git a/src/read_data.h b/src/read_data.h index 482c45e6e6..3374f48be0 100644 --- a/src/read_data.h +++ b/src/read_data.h @@ -78,7 +78,7 @@ class ReadData : public Command { // methods - void open(char *); + void open(const std::string &); void scan(int &, int &, int &, int &); int reallocate(int **, int, int); void header(int); diff --git a/src/read_dump.cpp b/src/read_dump.cpp index 4a7a483cb0..c09bd38c87 100644 --- a/src/read_dump.cpp +++ b/src/read_dump.cpp @@ -1217,32 +1217,26 @@ int ReadDump::fields_and_keywords(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"box") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); - if (strcmp(arg[iarg+1],"yes") == 0) boxflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) boxflag = 0; - else error->all(FLERR,"Illegal read_dump command"); + boxflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"replace") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); - if (strcmp(arg[iarg+1],"yes") == 0) replaceflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) replaceflag = 0; - else error->all(FLERR,"Illegal read_dump command"); + replaceflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"purge") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); - if (strcmp(arg[iarg+1],"yes") == 0) purgeflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) purgeflag = 0; - else error->all(FLERR,"Illegal read_dump command"); + purgeflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"trim") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); - if (strcmp(arg[iarg+1],"yes") == 0) trimflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) trimflag = 0; - else error->all(FLERR,"Illegal read_dump command"); + trimflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"add") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); if (strcmp(arg[iarg+1],"yes") == 0) addflag = YESADD; else if (strcmp(arg[iarg+1],"no") == 0) addflag = NOADD; + else if (strcmp(arg[iarg+1],"true") == 0) addflag = YESADD; + else if (strcmp(arg[iarg+1],"false") == 0) addflag = NOADD; else if (strcmp(arg[iarg+1],"keep") == 0) addflag = KEEPADD; else error->all(FLERR,"Illegal read_dump command"); iarg += 2; @@ -1257,15 +1251,11 @@ int ReadDump::fields_and_keywords(int narg, char **arg) iarg += 3; } else if (strcmp(arg[iarg],"scaled") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); - if (strcmp(arg[iarg+1],"yes") == 0) scaleflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) scaleflag = 0; - else error->all(FLERR,"Illegal read_dump command"); + scaleflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"wrapped") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); - if (strcmp(arg[iarg+1],"yes") == 0) wrapflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) wrapflag = 0; - else error->all(FLERR,"Illegal read_dump command"); + wrapflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal read_dump command"); diff --git a/src/read_restart.cpp b/src/read_restart.cpp index bbd3bd3359..0eab44baaa 100644 --- a/src/read_restart.cpp +++ b/src/read_restart.cpp @@ -35,7 +35,6 @@ #include "update.h" #include -#include #include "lmprestart.h" @@ -55,7 +54,7 @@ void ReadRestart::command(int narg, char **arg) error->all(FLERR,"Cannot read_restart after simulation box is defined"); MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); MPI_Comm_rank(world,&me); MPI_Comm_size(world,&nprocs); @@ -117,6 +116,7 @@ void ReadRestart::command(int narg, char **arg) magic_string(); endian(); format_revision(); + check_eof_magic(); // read header info which creates simulation box @@ -522,7 +522,7 @@ void ReadRestart::command(int narg, char **arg) MPI_Barrier(world); if (comm->me == 0) - utils::logmesg(lmp," read_restart CPU = {:.3f} seconds\n",MPI_Wtime()-time1); + utils::logmesg(lmp," read_restart CPU = {:.3f} seconds\n",platform::walltime()-time1); delete mpiio; } @@ -540,8 +540,8 @@ std::string ReadRestart::file_search(const std::string &inpfile) { // separate inpfile into dir + filename - auto dirname = utils::path_dirname(inpfile); - auto filename = utils::path_basename(inpfile); + auto dirname = platform::path_dirname(inpfile); + auto filename = platform::path_basename(inpfile); // if filename contains "%" replace "%" with "base" @@ -557,24 +557,20 @@ std::string ReadRestart::file_search(const std::string &inpfile) if (loc != std::string::npos) { // convert pattern to equivalent regexp pattern.replace(loc,1,"\\d+"); - struct dirent *ep; - DIR *dp = opendir(dirname.c_str()); - if (dp == nullptr) - error->one(FLERR,"Cannot open directory {} to search for restart file: {}", - dirname, utils::getsyserror()); - while ((ep = readdir(dp))) { - std::string candidate(ep->d_name); + if (!platform::path_is_directory(dirname)) + error->one(FLERR,"Cannot open directory {} to search for restart file: {}",dirname); + + for (const auto &candidate : platform::list_directory(dirname)) { if (utils::strmatch(candidate,pattern)) { bigint num = ATOBIGINT(utils::strfind(candidate.substr(loc),"\\d+").c_str()); if (num > maxnum) maxnum = num; } } - closedir(dp); if (maxnum < 0) error->one(FLERR,"Found no restart file matching pattern"); filename.replace(filename.find('*'),1,std::to_string(maxnum)); } - return utils::path_join(dirname,filename); + return platform::path_join(dirname,filename); } /* ---------------------------------------------------------------------- @@ -1084,11 +1080,11 @@ void ReadRestart::file_layout() flag = read_int(); } - // if MPI-IO file, broadcast the end of the header offste + // if MPI-IO file, broadcast the end of the header offset // this allows all ranks to compute offset to their data if (mpiioflag) { - if (me == 0) headerOffset = ftell(fp); + if (me == 0) headerOffset = platform::ftell(fp); MPI_Bcast(&headerOffset,1,MPI_LMP_BIGINT,0,world); } } @@ -1152,10 +1148,12 @@ void ReadRestart::check_eof_magic() // read magic string at end of file and restore file pointer if (me == 0) { - long curpos = ftell(fp); - fseek(fp,(long)-n,SEEK_END); + bigint curpos = platform::ftell(fp); + platform::fseek(fp,platform::END_OF_FILE); + bigint offset = platform::ftell(fp) - n; + platform::fseek(fp,offset); utils::sfread(FLERR,str,sizeof(char),n,fp,nullptr,error); - fseek(fp,curpos,SEEK_SET); + platform::fseek(fp,curpos); } MPI_Bcast(str,n,MPI_CHAR,0,world); diff --git a/src/reader.cpp b/src/reader.cpp index 71036e7444..f2652d868d 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -32,33 +32,20 @@ Reader::Reader(LAMMPS *lmp) : Pointers(lmp) generic version for ASCII files that may be compressed ------------------------------------------------------------------------- */ -void Reader::open_file(const char *file) +void Reader::open_file(const std::string &file) { if (fp != nullptr) close_file(); - if (utils::strmatch(file,"\\.gz$")) { + if (platform::has_compress_extension(file)) { compressed = 1; - -#ifdef LAMMPS_GZIP - auto gunzip = fmt::format("gzip -c -d {}",file); - -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file without gzip support"); -#endif + fp = platform::compressed_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file for reading"); } else { compressed = 0; - fp = fopen(file,"r"); + fp = fopen(file.c_str(),"r"); } - if (fp == nullptr) - error->one(FLERR,"Cannot open file {}: {}", - file, utils::getsyserror()); + if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror()); } /* ---------------------------------------------------------------------- @@ -69,7 +56,7 @@ void Reader::open_file(const char *file) void Reader::close_file() { if (fp == nullptr) return; - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); fp = nullptr; } diff --git a/src/reader.h b/src/reader.h index 2d71750f98..18977790cd 100644 --- a/src/reader.h +++ b/src/reader.h @@ -33,7 +33,7 @@ class Reader : protected Pointers { int &, int &, int &) = 0; virtual void read_atoms(int, int, double **) = 0; - virtual void open_file(const char *); + virtual void open_file(const std::string &); virtual void close_file(); protected: diff --git a/src/replicate.cpp b/src/replicate.cpp index 2c2b512026..80edd7bcbc 100644 --- a/src/replicate.cpp +++ b/src/replicate.cpp @@ -79,7 +79,7 @@ void Replicate::command(int narg, char **arg) // record wall time for atom replication MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); // maxtag = largest atom tag across all existing atoms @@ -799,5 +799,5 @@ void Replicate::command(int narg, char **arg) MPI_Barrier(world); if (me == 0) - utils::logmesg(lmp," replicate CPU = {:.3f} seconds\n",MPI_Wtime()-time1); + utils::logmesg(lmp," replicate CPU = {:.3f} seconds\n",platform::walltime()-time1); } diff --git a/src/rerun.cpp b/src/rerun.cpp index f9bb507a11..ce21fbc2b8 100644 --- a/src/rerun.cpp +++ b/src/rerun.cpp @@ -106,11 +106,7 @@ void Rerun::command(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"post") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal rerun command"); - if (strcmp(arg[iarg+1],"yes") == 0) { - postflag = 1; - } else if (strcmp(arg[iarg+1],"no") == 0) { - postflag = 0; - } else error->all(FLERR,"Illegal rerun command"); + postflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"dump") == 0) { break; diff --git a/src/reset_atom_ids.cpp b/src/reset_atom_ids.cpp index 3aea800b6f..822490ffc8 100644 --- a/src/reset_atom_ids.cpp +++ b/src/reset_atom_ids.cpp @@ -69,9 +69,7 @@ void ResetIDs::command(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"sort") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal reset_atom_ids command"); - if (strcmp(arg[iarg+1],"yes") == 0) sortflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) sortflag = 0; - else error->all(FLERR,"Illegal reset_atom_ids command"); + sortflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else error->all(FLERR,"Illegal reset_atom_ids command"); } diff --git a/src/reset_mol_ids.cpp b/src/reset_mol_ids.cpp index 3ddef738d2..4c973f543f 100644 --- a/src/reset_mol_ids.cpp +++ b/src/reset_mol_ids.cpp @@ -77,15 +77,11 @@ void ResetMolIDs::command(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"compress") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal reset_mol_ids command"); - if (strcmp(arg[iarg+1],"yes") == 0) compressflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) compressflag = 0; - else error->all(FLERR,"Illegal reset_mol_ids command"); + compressflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"single") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal reset_mol_ids command"); - if (strcmp(arg[iarg+1],"yes") == 0) singleflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) singleflag = 0; - else error->all(FLERR,"Illegal reset_mol_ids command"); + singleflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"offset") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal reset_mol_ids command"); @@ -100,7 +96,7 @@ void ResetMolIDs::command(int narg, char **arg) // record wall time for resetting molecule IDs MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); // initialize system since comm->borders() will be invoked @@ -136,7 +132,7 @@ void ResetMolIDs::command(int narg, char **arg) else utils::logmesg(lmp," number of new molecule IDs = {}\n",nchunk); utils::logmesg(lmp," reset_mol_ids CPU = {:.3f} seconds\n", - MPI_Wtime()-time1); + platform::walltime()-time1); } } diff --git a/src/run.cpp b/src/run.cpp index 2d8b4816a4..a026580c83 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -77,15 +77,11 @@ void Run::command(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"pre") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run command"); - if (strcmp(arg[iarg+1],"no") == 0) preflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) preflag = 1; - else error->all(FLERR,"Illegal run command"); + preflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"post") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run command"); - if (strcmp(arg[iarg+1],"no") == 0) postflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) postflag = 1; - else error->all(FLERR,"Illegal run command"); + postflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; // all remaining args are commands diff --git a/src/special.cpp b/src/special.cpp index dcc0d0c0ad..9f480da78f 100644 --- a/src/special.cpp +++ b/src/special.cpp @@ -56,7 +56,7 @@ Special::~Special() void Special::build() { MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); if (me == 0) { const double * const special_lj = force->special_lj; @@ -1303,5 +1303,5 @@ void Special::timer_output(double time1) { if (comm->me == 0) utils::logmesg(lmp," special bonds CPU = {:.3f} seconds\n", - MPI_Wtime()-time1); + platform::walltime()-time1); } diff --git a/src/thermo.cpp b/src/thermo.cpp index eaf208c2eb..434012870b 100644 --- a/src/thermo.cpp +++ b/src/thermo.cpp @@ -556,16 +556,12 @@ void Thermo::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"norm") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command"); normuserflag = 1; - if (strcmp(arg[iarg+1],"no") == 0) normuser = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) normuser = 1; - else error->all(FLERR,"Illegal thermo_modify command"); + normuser = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"flush") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command"); - if (strcmp(arg[iarg+1],"no") == 0) flushflag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) flushflag = 1; - else error->all(FLERR,"Illegal thermo_modify command"); + flushflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"line") == 0) { diff --git a/src/timer.cpp b/src/timer.cpp index b01a7aa9d6..0cbf687137 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -20,50 +20,8 @@ #include -#ifdef _WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#else -#include -#include -#endif - using namespace LAMMPS_NS; - -// Return the CPU time for the current process in seconds very -// much in the same way as MPI_Wtime() returns the wall time. - -static double CPU_Time() -{ - double rv = 0.0; - -#ifdef _WIN32 - - // from MSD docs. - FILETIME ct,et,kt,ut; - union { FILETIME ft; uint64_t ui; } cpu; - if (GetProcessTimes(GetCurrentProcess(),&ct,&et,&kt,&ut)) { - cpu.ft = ut; - rv = cpu.ui * 0.0000001; - } - -#else /* ! _WIN32 */ - - struct rusage ru; - if (getrusage(RUSAGE_SELF, &ru) == 0) { - rv = (double) ru.ru_utime.tv_sec; - rv += (double) ru.ru_utime.tv_usec * 0.000001; - } - -#endif /* ! _WIN32 */ - - return rv; -} - /* ---------------------------------------------------------------------- */ Timer::Timer(LAMMPS *lmp) : Pointers(lmp) @@ -93,8 +51,8 @@ void Timer::_stamp(enum ttype which) { double current_cpu=0.0, current_wall=0.0; - if (_level > NORMAL) current_cpu = CPU_Time(); - current_wall = MPI_Wtime(); + if (_level > NORMAL) current_cpu = platform::cputime(); + current_wall = platform::walltime(); if ((which > TOTAL) && (which < NUM_TIMER)) { const double delta_cpu = current_cpu - previous_cpu; @@ -117,8 +75,8 @@ void Timer::_stamp(enum ttype which) if (_sync) { MPI_Barrier(world); - if (_level > NORMAL) current_cpu = CPU_Time(); - current_wall = MPI_Wtime(); + if (_level > NORMAL) current_cpu = platform::cputime(); + current_wall = platform::walltime(); cpu_array[SYNC] += current_cpu - previous_cpu; wall_array[SYNC] += current_wall - previous_wall; @@ -137,8 +95,8 @@ void Timer::barrier_start() if (_level < LOOP) return; - current_cpu = CPU_Time(); - current_wall = MPI_Wtime(); + current_cpu = platform::cputime(); + current_wall = platform::walltime(); cpu_array[TOTAL] = current_cpu; wall_array[TOTAL] = current_wall; @@ -156,8 +114,8 @@ void Timer::barrier_stop() if (_level < LOOP) return; - current_cpu = CPU_Time(); - current_wall = MPI_Wtime(); + current_cpu = platform::cputime(); + current_wall = platform::walltime(); cpu_array[TOTAL] = current_cpu - cpu_array[TOTAL]; wall_array[TOTAL] = current_wall - wall_array[TOTAL]; @@ -167,7 +125,7 @@ void Timer::barrier_stop() double Timer::cpu(enum ttype which) { - double current_cpu = CPU_Time(); + double current_cpu = platform::cputime(); return (current_cpu - cpu_array[which]); } @@ -176,7 +134,7 @@ double Timer::cpu(enum ttype which) double Timer::elapsed(enum ttype which) { if (_level == OFF) return 0.0; - double current_wall = MPI_Wtime(); + double current_wall = platform::walltime(); return (current_wall - wall_array[which]); } @@ -207,7 +165,7 @@ void Timer::print_timeout(FILE *fp) // format timeout setting if (_timeout > 0) { // time since init_timeout() - const double d = MPI_Wtime() - timeout_start; + const double d = platform::walltime() - timeout_start; // remaining timeout in seconds int s = _timeout - d; // remaining 1/100ths of seconds @@ -226,7 +184,7 @@ void Timer::print_timeout(FILE *fp) bool Timer::_check_timeout() { - double walltime = MPI_Wtime() - timeout_start; + double walltime = platform::walltime() - timeout_start; // broadcast time to insure all ranks act the same. MPI_Bcast(&walltime,1,MPI_DOUBLE,0,world); @@ -244,7 +202,7 @@ bool Timer::_check_timeout() /* ---------------------------------------------------------------------- */ double Timer::get_timeout_remain() { - return (_timeout < 0.0) ? 0.0 : _timeout + timeout_start - MPI_Wtime(); + return (_timeout < 0.0) ? 0.0 : _timeout + timeout_start - platform::walltime(); } /* ---------------------------------------------------------------------- @@ -285,7 +243,7 @@ void Timer::modify_params(int narg, char **arg) ++iarg; } - timeout_start = MPI_Wtime(); + timeout_start = platform::walltime(); if (comm->me == 0) { // format timeout setting diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 538cd716ad..71b4ad610e 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -46,11 +46,11 @@ TokenizerException::TokenizerException(const std::string &msg, const std::string \endverbatim * - * \param str string to be processed - * \param separators string with separator characters (default: " \t\r\n\f") */ + * \param str string to be processed + * \param _separators string with separator characters (default: " \t\r\n\f") */ -Tokenizer::Tokenizer(const std::string &str, const std::string &separators) : - text(str), separators(separators), start(0), ntokens(std::string::npos) +Tokenizer::Tokenizer(const std::string &str, const std::string &_separators) : + text(str), separators(_separators), start(0), ntokens(std::string::npos) { // replace known UTF-8 characters with ASCII equivalents if (utils::has_utf8(text)) text = utils::utf8_subst(text); diff --git a/src/utils.cpp b/src/utils.cpp index b2a1e801f7..035b68d660 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -25,30 +25,12 @@ #include "tokenizer.h" #include "update.h" +#include #include #include #include #include -#if defined(__linux__) -#include // for readlink -#endif - -#if defined(__APPLE__) -#include // for fcntl -#include -#endif - -#if defined(_WIN32) -// target Windows version is Windows 7 and later -#if defined(_WIN32_WINNT) -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT _WIN32_WINNT_WIN7 -#include -#include -#endif - /*! \file utils.cpp */ /* @@ -164,44 +146,6 @@ std::string utils::getsyserror() return std::string(strerror(errno)); } -/** On Linux the folder /proc/self/fd holds symbolic links to the actual - * pathnames associated with each open file descriptor of the current process. - * On MacOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. - * On Windows we use ``GetFinalPathNameByHandleA()`` which is available with - * Windows Vista and later. - * - * This function is used to provide a filename with error messages in functions - * where the filename is not passed as an argument, but the FILE * pointer. - */ -const char *utils::guesspath(char *buf, int len, FILE *fp) -{ - memset(buf, 0, len); - -#if defined(__linux__) - int fd = fileno(fp); - // get pathname from /proc or copy (unknown) - if (readlink(fmt::format("/proc/self/fd/{}", fd).c_str(), buf, len - 1) <= 0) - strncpy(buf, "(unknown)", len - 1); -#elif defined(__APPLE__) - int fd = fileno(fp); - char filepath[PATH_MAX]; - if (fcntl(fd, F_GETPATH, filepath) != -1) - strncpy(buf, filepath, len - 1); - else - strncpy(buf, "(unknown)", len - 1); -#elif defined(_WIN32) - char filepath[MAX_PATH]; - HANDLE h = (HANDLE) _get_osfhandle(_fileno(fp)); - if (GetFinalPathNameByHandleA(h, filepath, PATH_MAX, FILE_NAME_NORMALIZED) > 0) - strncpy(buf, filepath, len - 1); - else - strncpy(buf, "(unknown)", len - 1); -#else - strncpy(buf, "(unknown)", len - 1); -#endif - return buf; -} - // read line into buffer. if line is too long keep reading until EOL or EOF // but return only the first part with a newline at the end. @@ -255,7 +199,7 @@ void utils::sfgets(const char *srcname, int srcline, char *s, int size, FILE *fp std::string errmsg; // try to figure out the file name from the file pointer - if (!filename) filename = guesspath(buf, MAXPATHLENBUF, fp); + if (!filename) filename = platform::guesspath(fp, buf, MAXPATHLENBUF); if (feof(fp)) { errmsg = "Unexpected end of file while reading file '"; @@ -284,7 +228,7 @@ void utils::sfread(const char *srcname, int srcline, void *s, size_t size, size_ std::string errmsg; // try to figure out the file name from the file pointer - if (!filename) filename = guesspath(buf, MAXPATHLENBUF, fp); + if (!filename) filename = platform::guesspath(fp, buf, MAXPATHLENBUF); if (feof(fp)) { errmsg = "Unexpected end of file while reading file '"; @@ -347,6 +291,47 @@ std::string utils::check_packages_for_style(const std::string &style, const std: return errmsg; } +/* ---------------------------------------------------------------------- + read a boolean value from a string + transform to lower case before checking + generate an error if is not a legitimate boolean + called by various commands to check validity of their arguments +------------------------------------------------------------------------- */ + +int utils::logical(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +{ + int n = 0; + + if (str) n = strlen(str); + if (n == 0) { + const char msg[] = "Expected boolean parameter instead of NULL or empty string " + "in input script or data file"; + if (do_abort) + lmp->error->one(file, line, msg); + else + lmp->error->all(file, line, msg); + } + + // convert to ascii + std::string buf(str); + if (has_utf8(buf)) buf = utf8_subst(buf); + + int rv = 0; + if ((buf == "yes") || (buf == "on") || (buf == "true") || (buf == "1")) { + rv = 1; + } else if ((buf == "no") || (buf == "off") || (buf == "false") || (buf == "0")) { + rv = 0; + } else { + std::string msg("Expected boolean parameter instead of '"); + msg += buf + "' in input script or data file"; + if (do_abort) + lmp->error->one(file, line, msg); + else + lmp->error->all(file, line, msg); + } + return rv; +} + /* ---------------------------------------------------------------------- read a floating point value from a string generate an error if not a legitimate floating point value @@ -709,6 +694,28 @@ char *utils::strdup(const std::string &text) return tmp; } +/* ---------------------------------------------------------------------- + Return string converted to lowercase +------------------------------------------------------------------------- */ + +std::string utils::lowercase(const std::string &text) +{ + std::string converted(text); + for (auto &c : converted) c = ::tolower(c); + return converted; +} + +/* ---------------------------------------------------------------------- + Return string converted to uppercase +------------------------------------------------------------------------- */ + +std::string utils::uppercase(const std::string &text) +{ + std::string converted(text); + for (auto &c : converted) c = ::toupper(c); + return converted; +} + /* ---------------------------------------------------------------------- Return string without leading or trailing whitespace ------------------------------------------------------------------------- */ @@ -878,7 +885,7 @@ size_t utils::count_words(const std::string &text, const std::string &separators size_t utils::trim_and_count_words(const std::string &text, const std::string &separators) { - return utils::count_words(utils::trim_comment(text), separators); + return utils::count_words(trim_comment(text), separators); } /* ---------------------------------------------------------------------- @@ -1023,71 +1030,6 @@ bool utils::is_id(const std::string &str) return true; } -/* ---------------------------------------------------------------------- - strip off leading part of path, return just the filename -------------------------------------------------------------------------- */ - -std::string utils::path_basename(const std::string &path) -{ -#if defined(_WIN32) - size_t start = path.find_last_of("/\\"); -#else - size_t start = path.find_last_of('/'); -#endif - - if (start == std::string::npos) { - start = 0; - } else { - start += 1; - } - - return path.substr(start); -} - -/* ---------------------------------------------------------------------- - Return only the leading part of a path, return just the directory -------------------------------------------------------------------------- */ - -std::string utils::path_dirname(const std::string &path) -{ -#if defined(_WIN32) - size_t start = path.find_last_of("/\\"); -#else - size_t start = path.find_last_of('/'); -#endif - - if (start == std::string::npos) return "."; - - return path.substr(0, start); -} - -/* ---------------------------------------------------------------------- - join two paths -------------------------------------------------------------------------- */ - -std::string utils::path_join(const std::string &a, const std::string &b) -{ -#if defined(_WIN32) - return fmt::format("{}\\{}", a, b); -#else - return fmt::format("{}/{}", a, b); -#endif -} - -/* ---------------------------------------------------------------------- - try to open file for reading -------------------------------------------------------------------------- */ - -bool utils::file_is_readable(const std::string &path) -{ - FILE *fp = fopen(path.c_str(), "r"); - if (fp) { - fclose(fp); - return true; - } - return false; -} - /* ---------------------------------------------------------------------- try to find potential file as specified by name search current directory and the LAMMPS_POTENTIALS directory if @@ -1096,28 +1038,13 @@ bool utils::file_is_readable(const std::string &path) std::string utils::get_potential_file_path(const std::string &path) { - std::string filepath = path; - std::string filename = utils::path_basename(path); - - if (utils::file_is_readable(filepath)) { - return filepath; + if (platform::file_is_readable(path)) { + return path; } else { - // try the environment variable directory - const char *var = getenv("LAMMPS_POTENTIALS"); - - if (var != nullptr) { -#if defined(_WIN32) - Tokenizer dirs(var, ";"); -#else - Tokenizer dirs(var, ":"); -#endif - while (dirs.has_next()) { - auto pot = utils::path_basename(filepath); - auto dir = dirs.next(); - filepath = utils::path_join(dir, pot); - - if (utils::file_is_readable(filepath)) { return filepath; } - } + for (const auto &dir : platform::list_pathenv("LAMMPS_POTENTIALS")) { + auto pot = platform::path_basename(path); + auto filepath = platform::path_join(dir, pot); + if (platform::file_is_readable(filepath)) return filepath; } } return ""; @@ -1267,7 +1194,7 @@ double utils::timespec2seconds(const std::string ×pec) if (!values.has_next()) break; vals[i] = values.next_int(); } - } catch (TokenizerException &e) { + } catch (TokenizerException &) { return -1.0; } diff --git a/src/utils.h b/src/utils.h index 37d52f2614..1feee26f27 100644 --- a/src/utils.h +++ b/src/utils.h @@ -158,6 +158,19 @@ namespace utils { std::string check_packages_for_style(const std::string &style, const std::string &name, LAMMPS *lmp); + /*! Convert a string to a boolean while checking whether it is a valid boolean term. + * Valid terms are 'yes', 'no', 'true', 'false', 'on', 'off', and '1', '0'. Only + * lower case is accepted. + * + * \param file name of source file for error message + * \param line line number in source file for error message + * \param str string to be converted to logical + * \param do_abort determines whether to call Error::one() or Error::all() + * \param lmp pointer to top-level LAMMPS class instance + * \return 1 if string resolves to "true", otherwise 0 */ + + int logical(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp); + /*! Convert a string to a floating point number while checking * if it is a valid floating point or integer number * @@ -269,6 +282,20 @@ namespace utils { char *strdup(const std::string &text); + /*! Convert string to lowercase + * + * \param line string that should be converted + * \return new string with all lowercase characters */ + + std::string lowercase(const std::string &line); + + /*! Convert string to uppercase + * + * \param line string that should be converted + * \return new string with all uppercase characters */ + + std::string uppercase(const std::string &line); + /*! Trim leading and trailing whitespace. Like TRIM() in Fortran. * * \param line string that should be trimmed @@ -404,49 +431,6 @@ namespace utils { bool is_id(const std::string &str); - /*! Try to detect pathname from FILE pointer. - * - * Currently supported on Linux, MacOS, and Windows, otherwise will report "(unknown)". - * - * \param buf storage buffer for pathname. output will be truncated if not large enough - * \param len size of storage buffer. output will be truncated to this length - 1 - * \param fp FILE pointer struct from STDIO library for which we want to detect the name - * \return pointer to the storage buffer, i.e. buf */ - - const char *guesspath(char *buf, int len, FILE *fp); - - /*! Strip off leading part of path, return just the filename - * - * \param path file path - * \return file name */ - - std::string path_basename(const std::string &path); - - /*! Return the directory part of a path. Return "." if empty - * - * \param path file path - * \return directory name */ - - std::string path_dirname(const std::string &path); - - /*! Join two pathname segments - * - * This uses the forward slash '/' character unless LAMMPS is compiled - * for Windows where it used the equivalent backward slash '\\'. - * - * \param a first path - * \param b second path - * \return combined path */ - - std::string path_join(const std::string &a, const std::string &b); - - /*! Check if file exists and is readable - * - * \param path file path - * \return true if file exists and is readable */ - - bool file_is_readable(const std::string &path); - /*! Determine full path of potential file. If file is not found in current directory, * search directories listed in LAMMPS_POTENTIALS environment variable * diff --git a/src/variable.cpp b/src/variable.cpp index 1981d000c3..22f792b5ec 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -39,7 +39,6 @@ #include #include #include -#include #include using namespace LAMMPS_NS; @@ -692,11 +691,11 @@ int Variable::next(int narg, char **arg) int seed = 12345 + universe->me + which[find(arg[0])]; if (!random) random = new RanMars(lmp,seed); int delay = (int) (1000000*random->uniform()); - usleep(delay); + platform::usleep(delay); while (1) { if (!rename("tmp.lammps.variable","tmp.lammps.variable.lock")) break; delay = (int) (1000000*random->uniform()); - usleep(delay); + platform::usleep(delay); } // if the file cannot be found, we may have a race with some @@ -719,7 +718,7 @@ int Variable::next(int narg, char **arg) break; } delay = (int) (1000000*random->uniform()); - usleep(delay); + platform::usleep(delay); } delete random; random = nullptr; diff --git a/src/velocity.cpp b/src/velocity.cpp index a42c820d8c..4a449d00e7 100644 --- a/src/velocity.cpp +++ b/src/velocity.cpp @@ -35,6 +35,7 @@ using namespace LAMMPS_NS; enum{CREATE,SET,SCALE,RAMP,ZERO}; enum{ALL,LOCAL,GEOM}; +enum{UNIFORM,GAUSSIAN}; enum{NONE,CONSTANT,EQUAL,ATOM}; #define WARMUP 100 @@ -83,7 +84,7 @@ void Velocity::command(int narg, char **arg) // set defaults temperature = nullptr; - dist_flag = 0; + dist_flag = UNIFORM; sum_flag = 0; momentum_flag = 1; rotation_flag = 0; @@ -148,11 +149,12 @@ void Velocity::init_external(const char *extgroup) groupbit = group->bitmask[igroup]; temperature = nullptr; - dist_flag = 0; + dist_flag = UNIFORM; sum_flag = 0; momentum_flag = 1; rotation_flag = 0; loop_flag = ALL; + rfix = -1; scale_flag = 1; bias_flag = 0; } @@ -274,11 +276,11 @@ void Velocity::create(double t_desired, int seed) int natoms = static_cast (atom->natoms); for (i = 1; i <= natoms; i++) { - if (dist_flag == 0) { + if (dist_flag == UNIFORM) { vx = random->uniform() - 0.5; vy = random->uniform() - 0.5; vz = random->uniform() - 0.5; - } else { + } else { // GAUSSIAN vx = random->gaussian(); vy = random->gaussian(); vz = random->gaussian(); @@ -309,11 +311,11 @@ void Velocity::create(double t_desired, int seed) for (i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { - if (dist_flag == 0) { + if (dist_flag == UNIFORM) { vx = random->uniform() - 0.5; vy = random->uniform() - 0.5; vz = random->uniform() - 0.5; - } else { + } else { // GAUSSIAN vx = random->gaussian(); vy = random->gaussian(); vz = random->gaussian(); @@ -334,11 +336,11 @@ void Velocity::create(double t_desired, int seed) for (i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { random->reset(seed,x[i]); - if (dist_flag == 0) { + if (dist_flag == UNIFORM) { vx = random->uniform() - 0.5; vy = random->uniform() - 0.5; vz = random->uniform() - 0.5; - } else { + } else { // GAUSSIAN vx = random->gaussian(); vy = random->gaussian(); vz = random->gaussian(); @@ -823,27 +825,21 @@ void Velocity::options(int narg, char **arg) while (iarg < narg) { if (strcmp(arg[iarg],"dist") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command"); - if (strcmp(arg[iarg+1],"uniform") == 0) dist_flag = 0; - else if (strcmp(arg[iarg+1],"gaussian") == 0) dist_flag = 1; + if (strcmp(arg[iarg+1],"uniform") == 0) dist_flag = UNIFORM; + else if (strcmp(arg[iarg+1],"gaussian") == 0) dist_flag = GAUSSIAN; else error->all(FLERR,"Illegal velocity command"); iarg += 2; } else if (strcmp(arg[iarg],"sum") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command"); - if (strcmp(arg[iarg+1],"no") == 0) sum_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) sum_flag = 1; - else error->all(FLERR,"Illegal velocity command"); + sum_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"mom") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command"); - if (strcmp(arg[iarg+1],"no") == 0) momentum_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) momentum_flag = 1; - else error->all(FLERR,"Illegal velocity command"); + momentum_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"rot") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command"); - if (strcmp(arg[iarg+1],"no") == 0) rotation_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) rotation_flag = 1; - else error->all(FLERR,"Illegal velocity command"); + rotation_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"temp") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command"); @@ -855,9 +851,7 @@ void Velocity::options(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"bias") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command"); - if (strcmp(arg[iarg+1],"no") == 0) bias_flag = 0; - else if (strcmp(arg[iarg+1],"yes") == 0) bias_flag = 1; - else error->all(FLERR,"Illegal velocity command"); + bias_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"loop") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command"); diff --git a/src/version.h b/src/version.h index 6b4ecca26b..c1b2b627a8 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define LAMMPS_VERSION "20 Sep 2021" +#define LAMMPS_VERSION "29 Sep 2021" diff --git a/src/write_coeff.cpp b/src/write_coeff.cpp index e030148901..6f53a97e8f 100644 --- a/src/write_coeff.cpp +++ b/src/write_coeff.cpp @@ -26,7 +26,6 @@ #include #include -#include using namespace LAMMPS_NS; @@ -170,8 +169,8 @@ void WriteCoeff::command(int narg, char **arg) } fclose(one); fclose(two); - unlink(file); + platform::unlink(file); } - delete [] file; + delete[] file; } diff --git a/src/write_restart.cpp b/src/write_restart.cpp index 7f73d868ff..4333fa5416 100644 --- a/src/write_restart.cpp +++ b/src/write_restart.cpp @@ -595,7 +595,7 @@ void WriteRestart::file_layout(int send_size) // this allows all ranks to compute offset to their data if (mpiioflag) { - if (me == 0) headerOffset = ftell(fp); + if (me == 0) headerOffset = platform::ftell(fp); MPI_Bcast(&headerOffset,1,MPI_LMP_BIGINT,0,world); } } diff --git a/tools/lammps-shell/lammps-shell.cpp b/tools/lammps-shell/lammps-shell.cpp index 2ee62df920..936b539d43 100644 --- a/tools/lammps-shell/lammps-shell.cpp +++ b/tools/lammps-shell/lammps-shell.cpp @@ -1,11 +1,12 @@ // LAMMPS Shell. An improved interactive LAMMPS session with // command line editing, history, TAB expansion and shell escapes -// Copyright (c) 2020 Axel Kohlmeyer +// Copyright (c) 2020, 2021 Axel Kohlmeyer // This software is distributed under the GNU General Public License. #include "library.h" +#include "platform.h" #include "utils.h" #include @@ -14,21 +15,12 @@ #include #include -#if !defined(_WIN32) -#include -#else +#if defined(_WIN32) #if !defined(WIN32_LEAN_AND_MEAN) #define WIN32_LEAN_AND_MEAN #endif -#include -#include #include -#define chdir(x) _chdir(x) -#define getcwd(buf, len) _getcwd(buf, len) -#define isatty(x) _isatty(x) -#endif - -#if !defined(_WIN32) +#else #include #endif @@ -41,10 +33,10 @@ using namespace LAMMPS_NS; -char *omp_threads = nullptr; -const int buflen = 512; -char buf[buflen]; void *lmp = nullptr; +char *omp_threads = nullptr; +constexpr int BUFLEN = 512; +char buf[BUFLEN]; enum { ATOM_STYLE, @@ -213,7 +205,7 @@ template char *style_generator(const char *text, int state) } while (idx < num) { - lammps_style_name(lmp, lmp_style[STYLE], idx, buf, buflen); + lammps_style_name(lmp, lmp_style[STYLE], idx, buf, BUFLEN); ++idx; if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf); } @@ -230,7 +222,7 @@ template char *id_generator(const char *text, int state) } while (idx < num) { - lammps_id_name(lmp, lmp_id[ID], idx, buf, buflen); + lammps_id_name(lmp, lmp_id[ID], idx, buf, BUFLEN); ++idx; if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf); } @@ -388,8 +380,8 @@ static char *plugin_name_generator(const char *text, int state) nmax = lammps_plugin_count(); while (idx < nmax) { - char style[buflen], name[buflen]; - lammps_plugin_name(idx, style, name, buflen); + char style[BUFLEN], name[BUFLEN]; + lammps_plugin_name(idx, style, name, BUFLEN); ++idx; if (words[2] == style) { if (strncmp(name, words[3].c_str(), len) == 0) @@ -474,7 +466,7 @@ char *group_generator(const char *text, int state) } while (idx < num) { - lammps_id_name(lmp, "group", idx, buf, buflen); + lammps_id_name(lmp, "group", idx, buf, BUFLEN); ++idx; if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf); } @@ -576,7 +568,7 @@ static void init_commands() // store optional commands from command styles ncmds = lammps_style_count(lmp, "command"); for (int i = 0; i < ncmds; ++i) { - if (lammps_style_name(lmp, "command", i, buf, buflen)) commands.push_back(buf); + if (lammps_style_name(lmp, "command", i, buf, BUFLEN)) commands.push_back(buf); } // store LAMMPS shell specific command names @@ -598,7 +590,7 @@ static void init_commands() // otherwise any tabs in redirected input will cause havoc. const char *test_mode = getenv("LAMMPS_SHELL_TESTING"); if (test_mode) std::cout << "*TESTING* using LAMMPS Shell in test mode *TESTING*\n"; - if (isatty(fileno(stdin)) || test_mode) { + if (platform::is_console(stdin) || test_mode) { rl_attempted_completion_function = cmd_completion; } else { rl_bind_key('\t', rl_insert); @@ -607,10 +599,11 @@ static void init_commands() // read saved history, but not in test mode. if (!test_mode) read_history(".lammps_history"); -#if !defined(_WIN32) - signal(SIGINT, ctrl_c_handler); -#else + // intercept CTRL-C +#if defined(_WIN32) SetConsoleCtrlHandler(ctrl_c_handler, TRUE); +#else + signal(SIGINT, ctrl_c_handler); #endif } @@ -684,7 +677,7 @@ static int shell_cmd(const std::string &cmd) free(text); return 0; } else if ((words[0] == "pwd") || ((words[0] == "cd") && (words.size() == 1))) { - if (getcwd(buf, buflen)) std::cout << buf << "\n"; + std::cout << platform::current_directory() << "\n"; free(text); return 0; } else if (words[0] == "cd") { @@ -740,28 +733,19 @@ int main(int argc, char **argv) #if defined(_WIN32) // Special hack for Windows: if the current working directory is // the "system folder" (because that is where cmd.exe lives) - // switch to the user's documents directory. Avoid buffer overflow - // and skip this step if the path is too long for our buffer. - if (getcwd(buf, buflen)) { - if ((strstr(buf, "System32") || strstr(buf, "system32"))) { - char *drive = getenv("HOMEDRIVE"); - char *path = getenv("HOMEPATH"); - buf[0] = '\0'; - int len = strlen("\\Documents"); - if (drive) len += strlen(drive); - if (path) len += strlen(path); - if (len < buflen) { - if (drive) strcat(buf, drive); - if (path) strcat(buf, path); - strcat(buf, "\\Documents"); - chdir(buf); - } - } + // switch to the user's documents directory. + + auto curdir = platform::current_directory(); + if (utils::strmatch(curdir,"[Ss]ystem32")) { + std::string docdir = getenv("HOMEDRIVE"); + docdir += getenv("HOMEPATH"); + docdir += "\\Documents"; + platform::chdir(docdir); } #endif - lammps_get_os_info(buf, buflen); - std::cout << "LAMMPS Shell version 1.1 OS: " << buf; + lammps_get_os_info(buf, BUFLEN); + std::cout << "LAMMPS Shell version 1.2 OS: " << buf; if (!lammps_config_has_exceptions()) std::cout << "WARNING: LAMMPS was compiled without exceptions\n" @@ -776,7 +760,7 @@ int main(int argc, char **argv) // to use the maximum number of threads available since this is // not intended to be run with MPI. omp_threads = dupstring(std::string("OMP_NUM_THREADS=" + std::to_string(nthreads))); - putenv(omp_threads); + platform::putenv(omp_threads); // handle the special case where the first argument is not a flag but a file // this happens for example when using file type associations on Windows. @@ -785,8 +769,8 @@ int main(int argc, char **argv) std::string input_file; if ((argc > 1) && (argv[1][0] != '-')) { --argc; - input_file = utils::path_basename(argv[1]); - chdir(utils::path_dirname(input_file).c_str()); + input_file = platform::path_basename(argv[1]); + platform::chdir(platform::path_dirname(input_file)); for (int i = 1; i < argc; ++i) argv[i] = argv[i + 1]; } diff --git a/tools/msi2lmp/src/SearchAndFill.c b/tools/msi2lmp/src/SearchAndFill.c index 1a85ee111f..ff05ff13d0 100644 --- a/tools/msi2lmp/src/SearchAndFill.c +++ b/tools/msi2lmp/src/SearchAndFill.c @@ -13,6 +13,10 @@ #include #include +#if defined(_WIN32) +#define strdup(x) _strdup(x) +#endif + static int blank_line(char *line) { while (*line != '\0') { diff --git a/tools/singularity/README.md b/tools/singularity/README.md index 3f7b69d409..bd13d75ad7 100644 --- a/tools/singularity/README.md +++ b/tools/singularity/README.md @@ -10,12 +10,6 @@ workstation, e.g. when bugs are reported that can only be reproduced on a specific OS or with specific (mostly older) versions of tools, compilers, or libraries. -Ready-to-use container images built from some these definition files are -occasionally uploaded to the container library at sylabs.io. They -can be found here: https://cloud.sylabs.io/library/lammps/default/lammps_development# -and will be signed with a GPG key that has the fingerprint: -EEA103764C6C633EDC8AC428D9B44E93BF0C375A - Here is a workflow for testing a compilation of LAMMPS with a locally built CentOS 7.x singularity container. @@ -30,34 +24,3 @@ cmake -C ../cmake/presets/most.cmake ../cmake make ``` -And here is the equivalent workflow for testing a compilation of LAMMPS -using a pre-built Ubuntu 18.04LTS singularity container. - -``` -cd some/work/directory -git clone --depth 500 git://github.com/lammps/lammps.git lammps -mkdir build-ubuntu18 -cd build-ubuntu18 -singularity pull library://lammps/default/lammps_development:ubuntu18.04 -singularity exec lammps_development_ubuntu18.04.sif bash --login -cmake -C ../cmake/presets/most.cmake ../cmake -make -``` - -| Currently available: | Description | -| ------------------------------ | ---------------------------------------------- | -| centos7.def | CentOS 7.x with EPEL enabled, no LaTeX | -| centos8.def | CentOS 8.x with EPEL enabled | -| fedora34_mingw.def | Fedora 34 with MinGW cross-compiler toolchain | -| ubuntu16.04.def | Ubuntu 16.04LTS with MPI == OpenMPI, no LaTeX | -| ubuntu18.04.def | Ubuntu 18.04LTS with MPI == OpenMPI | -| ubuntu18.04_amd_rocm.def | Ubuntu 18.04LTS with AMD ROCm toolkit | -| ubuntu18.04_gpu.def | Ubuntu 18.04LTS with -"- plus Nvidia CUDA 11.0 | -| ubuntu18.04_nvidia.def | Ubuntu 18.04LTS with Nvidia CUDA 11.0 toolkit | -| ubuntu18.04_intel_opencl.def | Ubuntu 18.04LTS with Intel OpenCL runtime | -| ubuntu20.04.def | Ubuntu 20.04LTS with MPI == OpenMPI | -| ubuntu20.04_amd_rocm.def | Ubuntu 20.04LTS with AMD ROCm toolkit | -| ubuntu20.04_gpu.def | Ubuntu 20.04LTS with -"- plus Nvidia CUDA 11.0 | -| ubuntu20.04_nvidia.def | Ubuntu 20.04LTS with Nvidia CUDA 11.0 toolkit | -| ubuntu20.04_intel_opencl.def | Ubuntu 20.04LTS with Intel OpenCL runtime | -| ------------------------------ | ---------------------------------------------- | diff --git a/tools/singularity/centos7.def b/tools/singularity/centos7.def index f64db0649b..8a3235b58f 100644 --- a/tools/singularity/centos7.def +++ b/tools/singularity/centos7.def @@ -36,7 +36,7 @@ From: centos:7 # manually install Plumed mkdir plumed cd plumed - version=2.6.1 + version=2.7.2 curl -L -o plumed.tar.gz https://github.com/plumed/plumed2/releases/download/v${version}/plumed-src-${version}.tgz tar -xzf plumed.tar.gz cd plumed-${version} diff --git a/tools/singularity/centos8.def b/tools/singularity/centos8.def index c48d2718eb..e35f97f453 100644 --- a/tools/singularity/centos8.def +++ b/tools/singularity/centos8.def @@ -3,7 +3,7 @@ From: centos:8 %post dnf -y install epel-release dnf-utils - dnf config-manager --set-enabled PowerTools + dnf config-manager --set-enabled powertools dnf -y update dnf -y install vim-enhanced git file make cmake patch which file ninja-build \ ccache gcc-c++ gcc-gfortran clang libomp-devel gdb valgrind libubsan libasan libtsan \ @@ -42,7 +42,7 @@ From: centos:8 # manually install Plumed mkdir plumed cd plumed - version=2.6.1 + version=2.7.2 curl -L -o plumed.tar.gz https://github.com/plumed/plumed2/releases/download/v${version}/plumed-src-${version}.tgz tar -xzf plumed.tar.gz cd plumed-${version} diff --git a/tools/singularity/fedora34_mingw.def b/tools/singularity/fedora34_mingw.def index 2f8118778f..40e6f72861 100644 --- a/tools/singularity/fedora34_mingw.def +++ b/tools/singularity/fedora34_mingw.def @@ -30,6 +30,7 @@ From: fedora:34 mingw32-readline mingw64-readline \ mingw32-termcap mingw64-termcap \ mingw32-zlib mingw64-zlib \ + mingw32-zstd mingw64-zstd \ enchant python3-virtualenv doxygen latexmk \ texlive-latex-fonts texlive-pslatex texlive-collection-latexrecommended \ texlive-latex texlive-latexconfig doxygen-latex texlive-collection-latex \ diff --git a/tools/singularity/rocky8.def b/tools/singularity/rocky8.def new file mode 100644 index 0000000000..0827b1d548 --- /dev/null +++ b/tools/singularity/rocky8.def @@ -0,0 +1,110 @@ +BootStrap: docker +From: rockylinux/rockylinux:8 + +%post + dnf -y install epel-release dnf-utils + dnf config-manager --set-enabled powertools + dnf -y update + dnf -y install vim-enhanced git file make cmake patch which file ninja-build \ + ccache gcc-c++ gcc-gfortran clang libomp-devel gdb valgrind libubsan libasan libtsan \ + eigen3-devel openblas-devel libpng-devel libjpeg-devel platform-python-devel \ + openmpi-devel mpich-devel fftw-devel voro++-devel gsl-devel hdf5-devel \ + netcdf-devel netcdf-cxx-devel netcdf-mpich-devel netcdf-openmpi-devel \ + enchant python3-virtualenv doxygen diffutils latexmk readline-devel \ + texlive-latex-fonts texlive-pslatex texlive-collection-latexrecommended \ + texlive-latex texlive-latexconfig doxygen-latex texlive-collection-latex \ + texlive-latex-bin texlive-lualatex-math texlive-fncychap texlive-tabulary \ + texlive-framed texlive-wrapfig texlive-upquote texlive-capt-of \ + texlive-needspace texlive-titlesec texlive-anysize texlive-dvipng \ + blas-devel lapack-devel libyaml-devel openkim-models kim-api-devel \ + zstd libzstd-devel + dnf clean all + + # we need to reset any module variables + # inherited from the host. + unset __LMOD_REF_COUNT__LMFILES_ + unset __LMOD_REF_COUNT_PATH + unset __LMOD_REF_COUNT_LD_LIBRARY_PATH + unset __LMOD_REF_COUNT_MANPATH + unset __LMOD_REF_COUNT_MODULEPATH + unset __LMOD_REF_COUNT_LOADEDMODULES + unset _LMFILES_ + unset MODULEPATH + unset MODULESHOME + unset MODULEPATH_ROOT + unset LOADEDMODULES + unset LMOD_SYSTEM_DEFAULT_MODULES + + # load MPI by default + . /etc/profile + module load mpi + + # manually install Plumed + mkdir plumed + cd plumed + version=2.7.2 + curl -L -o plumed.tar.gz https://github.com/plumed/plumed2/releases/download/v${version}/plumed-src-${version}.tgz + tar -xzf plumed.tar.gz + cd plumed-${version} + ./configure --disable-doc --prefix=/usr + make + make install + # fix up installation for CentOS and Fedora + mv -v /usr/lib64/pkgconfig/plumed* /usr/share/pkgconfig/ + cd ../../ + rm -rvf plumed + + # create missing readline pkgconfig file + cat > /usr/lib64/pkgconfig/readline.pc <$CUSTOM_PROMPT_ENV <> /etc/ld.so.conf.d/nvidia.conf - echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf + libcublas-${CUDA_PKG_VERSION} \ + libcublas-dev-${CUDA_PKG_VERSION} # add missing symlink - ln -s /usr/local/cuda-11.0 /usr/local/cuda - ln -s /usr/local/cuda-11.0/lib64/stubs/libcuda.so /usr/local/cuda-11.0/lib64/stubs/libcuda.so.1 + ln -s /usr/local/cuda-${CUDA_PKG_VERSION}/lib64/stubs/libcuda.so /usr/local/cuda-${CUDA_PKG_VERSION}/lib64/stubs/libcuda.so.1 ########################################################################### # NVIDIA OpenCL @@ -134,7 +130,7 @@ From: ubuntu:18.04 ########################################################################### export PATH=$PATH:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin/x86_64 - git clone -b rocm-3.7.x https://github.com/ROCmSoftwarePlatform/hipCUB.git + git clone -b release/rocm-rel-4.3 https://github.com/ROCmSoftwarePlatform/hipCUB.git mkdir hipCUB/build cd hipCUB/build CXX=hipcc cmake -D BUILD_TEST=off .. @@ -169,7 +165,7 @@ From: ubuntu:18.04 # Plumed ########################################################################### - export PLUMED_PKG_VERSION=2.6.1 + export PLUMED_PKG_VERSION=2.7.2 mkdir plumed cd plumed diff --git a/tools/singularity/ubuntu18.04_intel_opencl.def b/tools/singularity/ubuntu18.04_intel_opencl.def index 01f0d78d0a..95c744c67d 100644 --- a/tools/singularity/ubuntu18.04_intel_opencl.def +++ b/tools/singularity/ubuntu18.04_intel_opencl.def @@ -106,7 +106,7 @@ From: ubuntu:18.04 # Plumed ########################################################################### - export PLUMED_PKG_VERSION=2.6.1 + export PLUMED_PKG_VERSION=2.7.2 mkdir plumed cd plumed diff --git a/tools/singularity/ubuntu18.04_nvidia.def b/tools/singularity/ubuntu18.04_nvidia.def index 2b6fcf8c45..359e1d1c4d 100644 --- a/tools/singularity/ubuntu18.04_nvidia.def +++ b/tools/singularity/ubuntu18.04_nvidia.def @@ -1,5 +1,5 @@ BootStrap: docker -From: nvidia/cuda:11.0-devel-ubuntu18.04 +From: nvidia/cuda:11.4.1-devel-ubuntu18.04 %post export DEBIAN_FRONTEND=noninteractive @@ -105,7 +105,7 @@ From: nvidia/cuda:11.0-devel-ubuntu18.04 # Plumed ########################################################################### - export PLUMED_PKG_VERSION=2.6.1 + export PLUMED_PKG_VERSION=2.7.2 mkdir plumed cd plumed diff --git a/tools/singularity/ubuntu20.04.def b/tools/singularity/ubuntu20.04.def index 7f081ab2e3..f85d3ca614 100644 --- a/tools/singularity/ubuntu20.04.def +++ b/tools/singularity/ubuntu20.04.def @@ -100,7 +100,7 @@ From: ubuntu:20.04 # Plumed ########################################################################### - export PLUMED_PKG_VERSION=2.6.1 + export PLUMED_PKG_VERSION=2.7.2 mkdir plumed cd plumed diff --git a/tools/singularity/ubuntu20.04_amd_rocm.def b/tools/singularity/ubuntu20.04_amd_rocm.def index 9db8265629..2b4176f183 100644 --- a/tools/singularity/ubuntu20.04_amd_rocm.def +++ b/tools/singularity/ubuntu20.04_amd_rocm.def @@ -3,7 +3,7 @@ From: ubuntu:20.04 %environment export PATH=/usr/lib/ccache:${PATH}:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin/x86_64 - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/rocm/lib:/opt/rocm-4.2.0/llvm/lib + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/rocm/lib:/opt/rocm-4.3.0/llvm/lib %post export DEBIAN_FRONTEND=noninteractive apt-get update @@ -91,7 +91,7 @@ From: ubuntu:20.04 ########################################################################### export PATH=$PATH:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin/x86_64 - git clone -b rocm-4.1.x https://github.com/ROCmSoftwarePlatform/hipCUB.git + git clone -b release/rocm-rel-4.3 https://github.com/ROCmSoftwarePlatform/hipCUB.git mkdir hipCUB/build cd hipCUB/build CXX=hipcc cmake -D BUILD_TEST=off .. @@ -126,7 +126,7 @@ From: ubuntu:20.04 # Plumed ########################################################################### - export PLUMED_PKG_VERSION=2.6.1 + export PLUMED_PKG_VERSION=2.7.2 mkdir plumed cd plumed diff --git a/tools/singularity/ubuntu20.04_gpu.def b/tools/singularity/ubuntu20.04_gpu.def index 44f975d2c8..3ea759078b 100644 --- a/tools/singularity/ubuntu20.04_gpu.def +++ b/tools/singularity/ubuntu20.04_gpu.def @@ -2,11 +2,11 @@ BootStrap: docker From: ubuntu:20.04 %environment - export PATH=/usr/lib/ccache:/usr/local/cuda-11.0/bin:${PATH}:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin/x86_64 - export CUDADIR=/usr/local/cuda-11.0 - export CUDA_PATH=/usr/local/cuda-11.0 - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-11.0/lib64:/opt/rocm/lib:/opt/rocm-4.2.0/llvm/lib - export LIBRARY_PATH=/usr/local/cuda-11.0/lib64/stubs + export PATH=/usr/lib/ccache:/usr/local/cuda-11.4/bin:${PATH}:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin/x86_64 + export CUDADIR=/usr/local/cuda-11.4 + export CUDA_PATH=/usr/local/cuda-11.4 + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-11.4/lib64:/opt/rocm/lib:/opt/rocm-4.3.0/llvm/lib + export LIBRARY_PATH=/usr/local/cuda-11.4/lib64/stubs %post export DEBIAN_FRONTEND=noninteractive apt-get update @@ -101,23 +101,19 @@ From: ubuntu:20.04 add-apt-repository "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/ /" apt-get update - export CUDA_PKG_VERSION=11.0 + export CUDA_PKG_VERSION=11.4 apt-get install -y --no-install-recommends \ - cuda-libraries-$CUDA_PKG_VERSION \ - cuda-command-line-tools-$CUDA_PKG_VERSION \ - cuda-libraries-dev-$CUDA_PKG_VERSION \ - cuda-minimal-build-$CUDA_PKG_VERSION \ + cuda-libraries-${CUDA_PKG_VERSION} \ + cuda-command-line-tools-${CUDA_PKG_VERSION} \ + cuda-libraries-dev-${CUDA_PKG_VERSION} \ + cuda-minimal-build-${CUDA_PKG_VERSION} \ cuda-compat-$CUDA_PKG_VERSION \ - libcublas-11-0 \ - libcublas-dev-11-0 - - echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf - echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf + libcublas-${CUDA_PKG_VERSION} \ + libcublas-dev-${CUDA_PKG_VERSION} # add missing symlink - ln -s /usr/local/cuda-11.0 /usr/local/cuda - ln -s /usr/local/cuda-11.0/lib64/stubs/libcuda.so /usr/local/cuda-11.0/lib64/stubs/libcuda.so.1 + ln -s /usr/local/cuda-${CUDA_PKG_VERSION}/lib64/stubs/libcuda.so /usr/local/cuda-${CUDA_PKG_VERSION}/lib64/stubs/libcuda.so.1 ########################################################################### # NVIDIA OpenCL @@ -131,7 +127,7 @@ From: ubuntu:20.04 ########################################################################### export PATH=$PATH:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin/x86_64 - git clone -b rocm-4.2.x https://github.com/ROCmSoftwarePlatform/hipCUB.git + git clone -b release/rocm-rel-4.3 https://github.com/ROCmSoftwarePlatform/hipCUB.git mkdir hipCUB/build cd hipCUB/build CXX=hipcc cmake -D BUILD_TEST=off .. @@ -166,7 +162,7 @@ From: ubuntu:20.04 # Plumed ########################################################################### - export PLUMED_PKG_VERSION=2.6.1 + export PLUMED_PKG_VERSION=2.7.2 mkdir plumed cd plumed diff --git a/tools/singularity/ubuntu20.04_intel_opencl.def b/tools/singularity/ubuntu20.04_intel_opencl.def index 82ca53a851..7c83ecb5b1 100644 --- a/tools/singularity/ubuntu20.04_intel_opencl.def +++ b/tools/singularity/ubuntu20.04_intel_opencl.def @@ -99,7 +99,7 @@ From: ubuntu:20.04 # Plumed ########################################################################### - export PLUMED_PKG_VERSION=2.6.1 + export PLUMED_PKG_VERSION=2.7.2 mkdir plumed cd plumed diff --git a/tools/singularity/ubuntu20.04_nvidia.def b/tools/singularity/ubuntu20.04_nvidia.def index 7bbc3ab0b5..ddcbd34db9 100644 --- a/tools/singularity/ubuntu20.04_nvidia.def +++ b/tools/singularity/ubuntu20.04_nvidia.def @@ -1,5 +1,5 @@ BootStrap: docker -From: nvidia/cuda:11.0-devel-ubuntu20.04 +From: nvidia/cuda:11.4.1-devel-ubuntu20.04 %post export DEBIAN_FRONTEND=noninteractive @@ -102,7 +102,7 @@ From: nvidia/cuda:11.0-devel-ubuntu20.04 # Plumed ########################################################################### - export PLUMED_PKG_VERSION=2.6.1 + export PLUMED_PKG_VERSION=2.7.2 mkdir plumed cd plumed diff --git a/tools/swig/CMakeLists.txt b/tools/swig/CMakeLists.txt index 204b351ed6..966837dc2f 100644 --- a/tools/swig/CMakeLists.txt +++ b/tools/swig/CMakeLists.txt @@ -90,7 +90,15 @@ if(BUILD_SWIG_TCL) # build loadable Tcl module set_property(SOURCE lammps.i PROPERTY SWIG_MODULE_NAME tcllammps) swig_add_library(tcllammps TYPE MODULE LANGUAGE tcl SOURCES lammps.i) - find_package(TCL REQUIRED) + find_package(TCL) + if(NOT TCL_FOUND) + message(FATAL_ERROR "Tcl development headers and libraries are required") + endif() + find_package(TclStub) + if(TCL_STUB_LIBRARY) + target_compile_definitions(tcllammps PRIVATE USE_TCL_STUBS) + target_link_libraries(tcllammps PRIVATE ${TCL_STUB_LIBRARY}) + endif() target_include_directories(tcllammps PRIVATE ${TCL_INCLUDE_PATH}) swig_link_libraries(tcllammps PRIVATE lammps ${TCL_LIBRARY}) # build extended Tcl shell binary diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 14da15c6e5..23a841b0a7 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -41,7 +41,7 @@ add_test(NAME RunLammps COMMAND $ -log none -echo none -in in.empty WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) set_tests_properties(RunLammps PROPERTIES - ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1" + ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1;HWLOC_HIDE_ERRORS=1" PASS_REGULAR_EXPRESSION "^LAMMPS \\([0-9]+ [A-Za-z]+ 2[0-9][0-9][0-9]\\)") # check if the compiled executable will print the help message @@ -49,7 +49,7 @@ add_test(NAME HelpMessage COMMAND $ -h WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) set_tests_properties(HelpMessage PROPERTIES - ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1" + ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1;HWLOC_HIDE_ERRORS=1" PASS_REGULAR_EXPRESSION ".*Large-scale Atomic/Molecular Massively Parallel Simulator -.*Usage example:.*") # check if the compiled executable will error out on an invalid command line flag @@ -57,7 +57,7 @@ add_test(NAME InvalidFlag COMMAND $ -xxx WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) set_tests_properties(InvalidFlag PROPERTIES - ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1" + ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1;HWLOC_HIDE_ERRORS=1" PASS_REGULAR_EXPRESSION "ERROR: Invalid command-line argument.*") # convenience function for adding tests requiring to be run in parallel with MPI diff --git a/unittest/commands/test_groups.cpp b/unittest/commands/test_groups.cpp index e238e630d5..0c8a7cd83c 100644 --- a/unittest/commands/test_groups.cpp +++ b/unittest/commands/test_groups.cpp @@ -316,7 +316,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_kim_commands.cpp b/unittest/commands/test_kim_commands.cpp index a70176cc92..183d333ab4 100644 --- a/unittest/commands/test_kim_commands.cpp +++ b/unittest/commands/test_kim_commands.cpp @@ -684,7 +684,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_lattice_region.cpp b/unittest/commands/test_lattice_region.cpp index 5fbabcf173..47b69a15e0 100644 --- a/unittest/commands/test_lattice_region.cpp +++ b/unittest/commands/test_lattice_region.cpp @@ -20,7 +20,6 @@ #include "lammps.h" #include "lattice.h" #include "region.h" -#include "utils.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -631,7 +630,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_reset_ids.cpp b/unittest/commands/test_reset_ids.cpp index bc9d39dc37..c67f90b341 100644 --- a/unittest/commands/test_reset_ids.cpp +++ b/unittest/commands/test_reset_ids.cpp @@ -637,10 +637,10 @@ TEST_F(ResetIDsTest, DeathTests) TEST_FAILURE(".*ERROR: Illegal reset_mol_ids command.*", command("reset_mol_ids all compress");); - TEST_FAILURE(".*ERROR: Illegal reset_mol_ids command.*", + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of 'xxx'.*", command("reset_mol_ids all compress xxx");); TEST_FAILURE(".*ERROR: Illegal reset_mol_ids command.*", command("reset_mol_ids all single");); - TEST_FAILURE(".*ERROR: Illegal reset_mol_ids command.*", + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of 'xxx'.*", command("reset_mol_ids all single xxx");); } @@ -686,7 +686,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_simple_commands.cpp b/unittest/commands/test_simple_commands.cpp index 8b57c26af1..0ad47f4e96 100644 --- a/unittest/commands/test_simple_commands.cpp +++ b/unittest/commands/test_simple_commands.cpp @@ -20,7 +20,6 @@ #include "input.h" #include "output.h" #include "update.h" -#include "utils.h" #include "variable.h" #include "../testing/core.h" @@ -160,7 +159,8 @@ TEST_F(SimpleCommandsTest, Partition) BEGIN_HIDE_OUTPUT(); command("echo none"); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal partition command .*", command("partition xxx 1 echo none");); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of 'xxx'.*", + command("partition xxx 1 echo none");); TEST_FAILURE(".*ERROR: Numeric index 2 is out of bounds.*", command("partition yes 2 echo none");); @@ -216,7 +216,7 @@ TEST_F(SimpleCommandsTest, Quit) TEST_FAILURE(".*ERROR: Expected integer .*", command("quit xxx");); // the following tests must be skipped with OpenMPI due to using threads - if (Info::get_mpi_vendor() == "Open MPI") GTEST_SKIP(); + if (platform::mpi_vendor() == "Open MPI") GTEST_SKIP(); ASSERT_EXIT(command("quit"), ExitedWithCode(0), ""); ASSERT_EXIT(command("quit 9"), ExitedWithCode(9), ""); } @@ -248,6 +248,8 @@ TEST_F(SimpleCommandsTest, Suffix) ASSERT_EQ(lmp->suffix2, nullptr); TEST_FAILURE(".*ERROR: May only enable suffixes after defining one.*", command("suffix on");); + TEST_FAILURE(".*ERROR: May only enable suffixes after defining one.*", command("suffix yes");); + TEST_FAILURE(".*ERROR: May only enable suffixes after defining one.*", command("suffix true");); BEGIN_HIDE_OUTPUT(); command("suffix one"); @@ -271,6 +273,26 @@ TEST_F(SimpleCommandsTest, Suffix) END_HIDE_OUTPUT(); ASSERT_EQ(lmp->suffix_enable, 0); + BEGIN_HIDE_OUTPUT(); + command("suffix yes"); + END_HIDE_OUTPUT(); + ASSERT_EQ(lmp->suffix_enable, 1); + + BEGIN_HIDE_OUTPUT(); + command("suffix no"); + END_HIDE_OUTPUT(); + ASSERT_EQ(lmp->suffix_enable, 0); + + BEGIN_HIDE_OUTPUT(); + command("suffix true"); + END_HIDE_OUTPUT(); + ASSERT_EQ(lmp->suffix_enable, 1); + + BEGIN_HIDE_OUTPUT(); + command("suffix false"); + END_HIDE_OUTPUT(); + ASSERT_EQ(lmp->suffix_enable, 0); + BEGIN_HIDE_OUTPUT(); command("suffix on"); END_HIDE_OUTPUT(); @@ -505,7 +527,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_variables.cpp b/unittest/commands/test_variables.cpp index 9d8932d0f0..4f603df5ac 100644 --- a/unittest/commands/test_variables.cpp +++ b/unittest/commands/test_variables.cpp @@ -517,7 +517,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/cplusplus/test_error_class.cpp b/unittest/cplusplus/test_error_class.cpp index 489b085b1b..f4f0d3b28b 100644 --- a/unittest/cplusplus/test_error_class.cpp +++ b/unittest/cplusplus/test_error_class.cpp @@ -128,7 +128,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/cplusplus/test_lammps_class.cpp b/unittest/cplusplus/test_lammps_class.cpp index d25b232fa7..fa7f6b30a9 100644 --- a/unittest/cplusplus/test_lammps_class.cpp +++ b/unittest/cplusplus/test_lammps_class.cpp @@ -325,7 +325,7 @@ TEST_F(LAMMPS_kokkos, InitMembers) TEST(LAMMPS_init, OpenMP) { if (!LAMMPS::is_installed_pkg("OPENMP")) GTEST_SKIP(); - if (Info::get_openmp_info() == "OpenMP not enabled") GTEST_SKIP(); + if (platform::openmp_standard() == "OpenMP not enabled") GTEST_SKIP(); FILE *fp = fopen("in.lammps_empty", "w"); fputs("\n", fp); diff --git a/unittest/formats/CMakeLists.txt b/unittest/formats/CMakeLists.txt index ae5919ba2a..6be712edd6 100644 --- a/unittest/formats/CMakeLists.txt +++ b/unittest/formats/CMakeLists.txt @@ -7,6 +7,10 @@ add_executable(test_image_flags test_image_flags.cpp) target_link_libraries(test_image_flags PRIVATE lammps gmock) add_test(NAME ImageFlags COMMAND test_image_flags WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +add_executable(test_input_convert test_input_convert.cpp) +target_link_libraries(test_input_convert PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) +add_test(NAME InputConvert COMMAND test_input_convert WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + add_executable(test_molecule_file test_molecule_file.cpp) target_link_libraries(test_molecule_file PRIVATE lammps gmock) add_test(NAME MoleculeFile COMMAND test_molecule_file WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/unittest/formats/test_dump_atom.cpp b/unittest/formats/test_dump_atom.cpp index b11dd4e800..8a3dab44a4 100644 --- a/unittest/formats/test_dump_atom.cpp +++ b/unittest/formats/test_dump_atom.cpp @@ -120,7 +120,7 @@ TEST_F(DumpAtomTest, format_line_run0) TEST_F(DumpAtomTest, no_scale_run0) { auto dump_file = "dump_no_scale_run0.melt"; - generate_dump(dump_file, "scale no", 0); + generate_dump(dump_file, "scale off", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -135,7 +135,7 @@ TEST_F(DumpAtomTest, no_scale_run0) TEST_F(DumpAtomTest, no_buffer_no_scale_run0) { auto dump_file = "dump_no_buffer_no_scale_run0.melt"; - generate_dump(dump_file, "buffer no scale no", 0); + generate_dump(dump_file, "buffer false scale false", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -150,7 +150,7 @@ TEST_F(DumpAtomTest, no_buffer_no_scale_run0) TEST_F(DumpAtomTest, no_buffer_with_scale_run0) { auto dump_file = "dump_no_buffer_with_scale_run0.melt"; - generate_dump(dump_file, "buffer no scale yes", 0); + generate_dump(dump_file, "buffer 0 scale 1", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -165,7 +165,7 @@ TEST_F(DumpAtomTest, no_buffer_with_scale_run0) TEST_F(DumpAtomTest, with_image_run0) { auto dump_file = "dump_with_image_run0.melt"; - generate_dump(dump_file, "scale no image yes", 0); + generate_dump(dump_file, "scale no image on", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -178,7 +178,7 @@ TEST_F(DumpAtomTest, with_image_run0) TEST_F(DumpAtomTest, with_units_run0) { auto dump_file = "dump_with_units_run0.melt"; - generate_dump(dump_file, "scale no units yes", 0); + generate_dump(dump_file, "scale false units 1", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -193,7 +193,7 @@ TEST_F(DumpAtomTest, with_units_run0) TEST_F(DumpAtomTest, with_time_run0) { auto dump_file = "dump_with_time_run0.melt"; - generate_dump(dump_file, "scale no time yes", 0); + generate_dump(dump_file, "scale off time true", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -207,7 +207,7 @@ TEST_F(DumpAtomTest, with_time_run0) TEST_F(DumpAtomTest, with_units_run1) { auto dump_file = "dump_with_units_run1.melt"; - generate_dump(dump_file, "scale no units yes", 1); + generate_dump(dump_file, "scale 0 units on", 1); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -222,7 +222,7 @@ TEST_F(DumpAtomTest, with_units_run1) TEST_F(DumpAtomTest, no_buffer_with_scale_and_image_run0) { auto dump_file = "dump_no_buffer_with_scale_and_image_run0.melt"; - generate_dump(dump_file, "buffer no scale yes image yes", 0); + generate_dump(dump_file, "buffer 0 scale 1 image true", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -253,7 +253,7 @@ TEST_F(DumpAtomTest, triclinic_with_units_run0) { auto dump_file = "dump_triclinic_with_units_run0.melt"; enable_triclinic(); - generate_dump(dump_file, "units yes", 0); + generate_dump(dump_file, "units on", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -271,7 +271,7 @@ TEST_F(DumpAtomTest, triclinic_with_time_run0) { auto dump_file = "dump_triclinic_with_time_run0.melt"; enable_triclinic(); - generate_dump(dump_file, "time yes", 0); + generate_dump(dump_file, "time on", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); @@ -548,7 +548,8 @@ TEST_F(DumpAtomTest, dump_modify_scale_invalid) command("dump id all atom 1 dump.txt"); END_HIDE_OUTPUT(); - TEST_FAILURE(".*Illegal dump_modify command.*", command("dump_modify id scale true");); + TEST_FAILURE(".*Expected boolean parameter instead of 'xxx'.*", + command("dump_modify id scale xxx");); } TEST_F(DumpAtomTest, dump_modify_image_invalid) @@ -557,7 +558,8 @@ TEST_F(DumpAtomTest, dump_modify_image_invalid) command("dump id all atom 1 dump.txt"); END_HIDE_OUTPUT(); - TEST_FAILURE(".*Illegal dump_modify command.*", command("dump_modify id image true");); + TEST_FAILURE(".*Expected boolean parameter instead of 'xxx'.*", + command("dump_modify id image xxx");); } TEST_F(DumpAtomTest, dump_modify_invalid) diff --git a/unittest/formats/test_file_operations.cpp b/unittest/formats/test_file_operations.cpp index 08baed2e54..bb26dff391 100644 --- a/unittest/formats/test_file_operations.cpp +++ b/unittest/formats/test_file_operations.cpp @@ -491,7 +491,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_input_convert.cpp b/unittest/formats/test_input_convert.cpp new file mode 100644 index 0000000000..0ff6878b13 --- /dev/null +++ b/unittest/formats/test_input_convert.cpp @@ -0,0 +1,179 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + 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 "../testing/core.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "library.h" +#include "utils.h" + +// whether to print verbose output (i.e. not capturing LAMMPS screen output). +bool verbose = false; + +using LAMMPS_NS::utils::split_words; + +namespace LAMMPS_NS { +using ::testing::Eq; + +class InputConvertTest : public LAMMPSTest { +protected: + void SetUp() override + { + testbinary = "InputConvertTest"; + LAMMPSTest::SetUp(); + ASSERT_NE(lmp, nullptr); + } + + void TearDown() override { LAMMPSTest::TearDown(); } +}; + +TEST_F(InputConvertTest, logical) +{ + EXPECT_EQ(utils::logical(FLERR, "yes", false, lmp), 1); + EXPECT_EQ(utils::logical(FLERR, "true", false, lmp), 1); + EXPECT_EQ(utils::logical(FLERR, "on", false, lmp), 1); + EXPECT_EQ(utils::logical(FLERR, "1", false, lmp), 1); + EXPECT_EQ(utils::logical(FLERR, "no", false, lmp), 0); + EXPECT_EQ(utils::logical(FLERR, "false", false, lmp), 0); + EXPECT_EQ(utils::logical(FLERR, "off", false, lmp), 0); + EXPECT_EQ(utils::logical(FLERR, "0", false, lmp), 0); + + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "YES", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "Yes", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "On", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "ON", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "TRUE", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "True", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "NO", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "No", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "Off", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "OFF", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "FALSE", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "False", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "yay", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "xxx", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "none", false, lmp);); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", + utils::logical(FLERR, "5", false, lmp);); +} + +TEST_F(InputConvertTest, numeric) +{ + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "0", false, lmp), 0); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "0.1", false, lmp), 0.1); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "-.232", false, lmp), -0.232); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, ".2e5", false, lmp), 20000.0); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "2.5e-10", false, lmp), 2.5e-10); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "+0.3", false, lmp), 0.3); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "10000000000", false, lmp), 1e10); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "2.56E+3", false, lmp), 2560); + + TEST_FAILURE(".*ERROR: Expected floating point.*", utils::numeric(FLERR, "yay", false, lmp);); + TEST_FAILURE(".*ERROR: Expected floating point.*", utils::numeric(FLERR, "", false, lmp);); + TEST_FAILURE(".*ERROR: Expected floating point.*", utils::numeric(FLERR, nullptr, false, lmp);); + TEST_FAILURE(".*ERROR: Expected floating point.*", + utils::numeric(FLERR, "2.56D+3", false, lmp);); +} + +TEST_F(InputConvertTest, inumeric) +{ + EXPECT_EQ(utils::inumeric(FLERR, "0", false, lmp), 0); + EXPECT_EQ(utils::inumeric(FLERR, "-1", false, lmp), -1); + EXPECT_EQ(utils::inumeric(FLERR, "10000", false, lmp), 10000); + EXPECT_EQ(utils::inumeric(FLERR, "-532410", false, lmp), -532410); + EXPECT_EQ(utils::inumeric(FLERR, "-0", false, lmp), 0); + EXPECT_EQ(utils::inumeric(FLERR, "0100", false, lmp), 100); + + TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "yay", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "0.1", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "1.1", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "1e5", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "0x05", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, nullptr, false, lmp);); +} + +TEST_F(InputConvertTest, bnumeric) +{ + EXPECT_EQ(utils::bnumeric(FLERR, "0", false, lmp), 0); + EXPECT_EQ(utils::bnumeric(FLERR, "-1", false, lmp), -1); + EXPECT_EQ(utils::bnumeric(FLERR, "10000", false, lmp), 10000); + EXPECT_EQ(utils::bnumeric(FLERR, "-532410", false, lmp), -532410); + EXPECT_EQ(utils::bnumeric(FLERR, "-0", false, lmp), 0); + EXPECT_EQ(utils::bnumeric(FLERR, "0100", false, lmp), 100); + + TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "yay", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "0.1", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "1.1", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "1e5", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "0x05", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, nullptr, false, lmp);); +} + +TEST_F(InputConvertTest, tnumeric) +{ + EXPECT_EQ(utils::tnumeric(FLERR, "0", false, lmp), 0); + EXPECT_EQ(utils::tnumeric(FLERR, "-1", false, lmp), -1); + EXPECT_EQ(utils::tnumeric(FLERR, "10000", false, lmp), 10000); + EXPECT_EQ(utils::tnumeric(FLERR, "-532410", false, lmp), -532410); + EXPECT_EQ(utils::tnumeric(FLERR, "-0", false, lmp), 0); + EXPECT_EQ(utils::tnumeric(FLERR, "0100", false, lmp), 100); + + TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "yay", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "0.1", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "1.1", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "1e5", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "0x05", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "", false, lmp);); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, nullptr, false, lmp);); +} + +} // namespace LAMMPS_NS + +int main(int argc, char **argv) +{ + lammps_mpi_init(); + ::testing::InitGoogleMock(&argc, argv); + + // handle arguments passed via environment variable + if (const char *var = getenv("TEST_ARGS")) { + auto env = split_words(var); + for (auto arg : env) { + if (arg == "-v") { + verbose = true; + } + } + } + if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = true; + + int rv = RUN_ALL_TESTS(); + lammps_mpi_finalize(); + return rv; +} diff --git a/unittest/formats/test_molecule_file.cpp b/unittest/formats/test_molecule_file.cpp index 5a3e3ca750..2cca7a6832 100644 --- a/unittest/formats/test_molecule_file.cpp +++ b/unittest/formats/test_molecule_file.cpp @@ -17,7 +17,6 @@ #include "input.h" #include "lammps.h" #include "molecule.h" -#include "utils.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -257,7 +256,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_potential_file_reader.cpp b/unittest/formats/test_potential_file_reader.cpp index 5f7148b7e4..7cd61d25a4 100644 --- a/unittest/formats/test_potential_file_reader.cpp +++ b/unittest/formats/test_potential_file_reader.cpp @@ -326,7 +326,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_text_file_reader.cpp b/unittest/formats/test_text_file_reader.cpp index 4e1f608d25..f0f695ae54 100644 --- a/unittest/formats/test_text_file_reader.cpp +++ b/unittest/formats/test_text_file_reader.cpp @@ -160,7 +160,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/python/python-capabilities.py b/unittest/python/python-capabilities.py index 8f72c39670..4c14cac37d 100644 --- a/unittest/python/python-capabilities.py +++ b/unittest/python/python-capabilities.py @@ -166,9 +166,9 @@ class PythonCapabilities(unittest.TestCase): self.assertIn('single',settings['GPU']['precision']) if self.cmake_cache['PKG_KOKKOS']: - if self.cmake_cache['Kokkos_ENABLE_OPENMP']: + if 'Kokkos_ENABLE_OPENMP' in self.cmake_cache and self.cmake_cache['Kokkos_ENABLE_OPENMP']: self.assertIn('openmp',settings['KOKKOS']['api']) - if self.cmake_cache['Kokkos_ENABLE_SERIAL']: + if 'Kokkos_ENABLE_SERIAL' in self.cmake_cache and self.cmake_cache['Kokkos_ENABLE_SERIAL']: self.assertIn('serial',settings['KOKKOS']['api']) self.assertIn('double',settings['KOKKOS']['precision']) diff --git a/unittest/testing/core.h b/unittest/testing/core.h index 6867d88587..c922e96cc0 100644 --- a/unittest/testing/core.h +++ b/unittest/testing/core.h @@ -17,6 +17,7 @@ #include "info.h" #include "input.h" #include "lammps.h" +#include "platform.h" #include "variable.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -36,7 +37,7 @@ using ::testing::MatchesRegex; auto mesg = ::testing::internal::GetCapturedStdout(); \ ASSERT_THAT(mesg, MatchesRegex(errmsg)); \ } else { \ - if (Info::get_mpi_vendor() != "Open MPI") { \ + if (platform::mpi_vendor() != "Open MPI") { \ ::testing::internal::CaptureStdout(); \ ASSERT_DEATH({__VA_ARGS__}, ""); \ auto mesg = ::testing::internal::GetCapturedStdout(); \ diff --git a/unittest/utils/CMakeLists.txt b/unittest/utils/CMakeLists.txt index 431b0b2ee1..047f0cee57 100644 --- a/unittest/utils/CMakeLists.txt +++ b/unittest/utils/CMakeLists.txt @@ -13,7 +13,25 @@ add_test(ArgUtils test_argutils) add_executable(test_utils test_utils.cpp) target_link_libraries(test_utils PRIVATE lammps gmock_main) add_test(Utils test_utils) -set_tests_properties(Utils PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + +add_executable(test_platform test_platform.cpp) +target_link_libraries(test_platform PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) +add_test(Platform test_platform) + +set_tests_properties(Utils Platform PROPERTIES + ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + +if(BUILD_SHARED_LIBS) + enable_language(C) + add_library(testsharedobj MODULE testshared.c) + set_target_properties(testsharedobj PROPERTIES PREFIX "" WINDOWS_EXPORT_ALL_SYMBOLS TRUE) + add_library(testsharedlib SHARED testshared.c) + set_target_properties(testsharedlib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) + add_dependencies(test_platform testsharedobj testsharedlib) + target_compile_definitions(test_platform PRIVATE TEST_SHARED_LOAD=1 + TEST_SHARED_LIB=$ + TEST_SHARED_OBJ=$) +endif() add_executable(test_fmtlib test_fmtlib.cpp) target_link_libraries(test_fmtlib PRIVATE lammps gmock_main) diff --git a/unittest/utils/test_platform.cpp b/unittest/utils/test_platform.cpp new file mode 100644 index 0000000000..0f39534c31 --- /dev/null +++ b/unittest/utils/test_platform.cpp @@ -0,0 +1,402 @@ + +#include "platform.h" +#include "utils.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include + +using namespace LAMMPS_NS; +using testing::EndsWith; +using testing::Eq; +using testing::IsEmpty; +using testing::StartsWith; +using testing::StrEq; + +TEST(Platform, clock) +{ + const double wt_start = platform::walltime(); + const double ct_start = platform::cputime(); + + // spend some time computing pi + constexpr double known_pi = 3.141592653589793238462643; + constexpr int n = 10000000; + constexpr double h = 1.0 / (double)n; + double my_pi = 0.0, x; + for (int i = 0; i < n; ++i) { + x = h * ((double)i + 0.5); + my_pi += 4.0 / (1.0 + x * x); + } + my_pi *= h; + const double wt_used = platform::walltime() - wt_start; + const double ct_used = platform::cputime() - ct_start; + + ASSERT_NEAR(my_pi, known_pi, 1e-12); + ASSERT_GT(wt_used, 1e-4); + ASSERT_GT(ct_used, 1e-4); +} + +TEST(Platform, putenv) +{ + const char *var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(var, nullptr); + int rv = platform::putenv("UNITTEST_VAR1"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + // we cannot set environment variables without a value on windows with _putenv() +#if defined(_WIN32) + ASSERT_THAT(var, StrEq("1")); +#else + ASSERT_THAT(var, StrEq("")); +#endif + + rv = platform::putenv("UNITTEST_VAR1=one"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + ASSERT_THAT(var, StrEq("one")); + + rv = platform::putenv("UNITTEST_VAR1=one=two"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + ASSERT_THAT(var, StrEq("one=two")); + + ASSERT_EQ(platform::putenv(""), -1); +} + +TEST(Platform, list_pathenv) +{ + auto dirs = platform::list_pathenv("PATH"); + ASSERT_GT(dirs.size(), 1); +} + +TEST(Platform, find_cmd_path) +{ +#if defined(_WIN32) + ASSERT_THAT(platform::find_exe_path("notepad"), EndsWith("\\notepad.exe")); + ASSERT_THAT(platform::find_exe_path("cmd"), EndsWith("\\cmd.exe")); + ASSERT_THAT(platform::find_exe_path("some_bogus_command"), IsEmpty()); +#else + ASSERT_THAT(platform::find_exe_path("ls"), EndsWith("bin/ls")); + ASSERT_THAT(platform::find_exe_path("sh"), EndsWith("bin/sh")); + ASSERT_THAT(platform::find_exe_path("some_bogus_command"), IsEmpty()); +#endif +} + +#if defined(TEST_SHARED_LOAD) +#define stringify(s) mkstring(s) +#define mkstring(s) #s +TEST(Platform, sharedload) +{ + const std::vector objs = {stringify(TEST_SHARED_OBJ), stringify(TEST_SHARED_LIB)}; + const int *intvar; + const double *doublevar; + void *handle; + int (*intfunc)(int); + double (*doublefunc)(double, int); + + for (const auto &obj : objs) { + handle = platform::dlopen(obj.c_str()); + EXPECT_NE(handle, nullptr); + intvar = (int *)platform::dlsym(handle, "some_int_val"); + EXPECT_NE(intvar, nullptr); + EXPECT_EQ(*intvar, 12345); + doublevar = (double *)platform::dlsym(handle, "some_double_val"); + EXPECT_NE(doublevar, nullptr); + EXPECT_DOUBLE_EQ(*doublevar, 6.78e-9); + intfunc = (int (*)(int))platform::dlsym(handle, "some_int_function"); + EXPECT_NE(intfunc, nullptr); + EXPECT_EQ((*intfunc)(12), 144); + doublefunc = (double (*)(double, int))platform::dlsym(handle, "some_double_function"); + EXPECT_NE(doublefunc, nullptr); + EXPECT_DOUBLE_EQ((*doublefunc)(0.5, 6), 3.0); + EXPECT_EQ(platform::dlsym(handle, "some_nonexisting_symbol"), nullptr); + EXPECT_EQ(platform::dlclose(handle), 0); + } +} +#undef stringify +#undef mkstring +#endif + +TEST(Platform, guesspath) +{ + char buf[256]; + FILE *fp = fopen("test_guesspath.txt", "w"); +#if defined(__linux__) || defined(__APPLE__) || defined(_WIN32) + const char *path = platform::guesspath(fp, buf, sizeof(buf)); + ASSERT_THAT(path, EndsWith("test_guesspath.txt")); +#else + const char *path = platform::guesspath(fp, buf, sizeof(buf)); + ASSERT_THAT(path, EndsWith("(unknown)")); +#endif + fclose(fp); + platform::unlink("test_guesspath.txt"); +} + +TEST(Platform, unlink) +{ + const char test[] = "12345678901234567890"; + platform::unlink("unlink.dat"); + ASSERT_EQ(platform::unlink("dummy.dat"), -1); + FILE *fp = fopen("unlink.dat", "w"); + fwrite(test, sizeof(test), 1, fp); + fclose(fp); + ASSERT_EQ(platform::unlink("unlink.dat"), 0); + ASSERT_EQ(platform::unlink("unlink.dat"), -1); + fp = fopen("unlink.dat", "r"); + ASSERT_EQ(fp, nullptr); + + platform::mkdir("unlink.dir"); + ASSERT_EQ(platform::unlink("unlink.dir"), -1); + platform::rmdir("unlink.dir"); +} + +TEST(Platform, fseek_ftell) +{ + const char test[] = "12345678901234567890"; + platform::unlink("seek_tell.dat"); + FILE *fp = fopen("seek_tell.dat", "w"); + fwrite(test, sizeof(test), 1, fp); + fflush(fp); + ASSERT_EQ(platform::ftell(fp), sizeof(test)); + fclose(fp); + fp = fopen("seek_tell.dat", "r+"); + ASSERT_EQ(fgetc(fp), '1'); + ASSERT_EQ(fgetc(fp), '2'); + ASSERT_EQ(platform::ftell(fp), 2); + ASSERT_EQ(platform::fseek(fp, 15), 0); + ASSERT_EQ(fgetc(fp), '6'); + fflush(fp); + ASSERT_EQ(platform::fseek(fp, platform::END_OF_FILE), 0); + ASSERT_EQ(platform::ftell(fp), 21); + ASSERT_EQ(platform::fseek(fp, 20), 0); + ASSERT_EQ(fgetc(fp), 0); + ASSERT_EQ(platform::ftell(fp), 21); + fclose(fp); + platform::unlink("seek_tell.dat"); +} + +TEST(Platform, ftruncate) +{ + platform::unlink("truncate.dat"); + FILE *fp = fopen("truncate.dat", "w"); + fputs("header one\n", fp); + fputs("header two\n", fp); + fflush(fp); + bigint filepos = platform::ftell(fp); + fputs("line one\n", fp); + fputs("line two\n", fp); + fputs("line three\n", fp); + fflush(fp); + ASSERT_EQ(platform::ftruncate(fp, filepos), 0); + fputs("line four\n", fp); + ASSERT_GT(platform::ftell(fp), filepos); + fputs("line five\n", fp); + fflush(fp); + fclose(fp); + + // check file + fp = fopen("truncate.dat", "r"); + char buf[128]; + char *ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("header one")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("header two")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("line four")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("line five")); + ptr = fgets(buf, 127, fp); + ASSERT_EQ(ptr, nullptr); + fclose(fp); + platform::unlink("truncate.dat"); +} + +TEST(Platform, path_basename) +{ +#if defined(_WIN32) + ASSERT_THAT(platform::path_basename("c:\\parent\\folder\\filename"), Eq("filename")); + ASSERT_THAT(platform::path_basename("folder\\"), Eq("")); + ASSERT_THAT(platform::path_basename("c:/parent/folder/filename"), Eq("filename")); +#else + ASSERT_THAT(platform::path_basename("/parent/folder/filename"), Eq("filename")); + ASSERT_THAT(platform::path_basename("/parent/folder/"), Eq("")); +#endif +} + +TEST(Platform, path_dirname) +{ +#if defined(_WIN32) + ASSERT_THAT(platform::path_dirname("c:/parent/folder/filename"), Eq("c:/parent/folder")); + ASSERT_THAT(platform::path_dirname("c:\\parent\\folder\\filename"), Eq("c:\\parent\\folder")); + ASSERT_THAT(platform::path_dirname("c:filename"), Eq(".")); +#else + ASSERT_THAT(platform::path_dirname("/parent/folder/filename"), Eq("/parent/folder")); +#endif + ASSERT_THAT(platform::path_dirname("filename"), Eq(".")); +} + +TEST(Platform, path_join) +{ +#if defined(_WIN32) + ASSERT_THAT(platform::path_join("c:\\folder", "filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", "/filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\\\", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "\\\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder/\\", "/\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\/", "\\/filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", ""), Eq("c:\\folder")); + ASSERT_THAT(platform::path_join("", "\\/filename"), Eq("\\/filename")); +#else + ASSERT_THAT(platform::path_join("/parent/folder", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder", "/filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "/filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder//", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder", "//filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder///", "/filename"), + Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "///filename"), + Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", ""), Eq("/parent/folder/")); + ASSERT_THAT(platform::path_join("", "\\/filename"), Eq("\\/filename")); +#endif +} + +TEST(Platform, is_console) +{ + platform::unlink("file_is_no_console.txt"); + FILE *fp = fopen("file_is_no_console.txt", "w"); + fputs("some text\n", fp); + EXPECT_FALSE(platform::is_console(fp)); + fclose(fp); + platform::unlink("file_is_no_console.txt"); +} + +TEST(Platform, path_and_directory) +{ + platform::unlink("path_is_directory"); + platform::rmdir("path_is_directory"); + platform::unlink("path_is_file"); + platform::mkdir("path_is_directory"); + FILE *fp = fopen("path_is_file", "w"); + fputs("some text\n", fp); + fclose(fp); + + ASSERT_TRUE(platform::path_is_directory("path_is_directory")); + ASSERT_FALSE(platform::path_is_directory("path_is_file")); + ASSERT_FALSE(platform::path_is_directory("path_does_not_exist")); + platform::unlink("path_is_file"); + +#if defined(_WIN32) + fp = fopen("path_is_directory\\path_is_file", "w"); +#else + fp = fopen("path_is_directory/path_is_file", "w"); +#endif + fputs("some text\n", fp); + fclose(fp); +#if defined(_WIN32) + platform::mkdir("path_is_directory\\path_is_directory"); + fp = fopen("path_is_directory\\path_is_other_file", "w"); +#else + platform::mkdir("path_is_directory/path_is_directory"); + fp = fopen("path_is_directory/path_is_other_file", "w"); +#endif + fputs("some text\n", fp); + fclose(fp); + auto dirs = platform::list_directory("path_is_directory"); + ASSERT_EQ(dirs.size(), 3); + platform::rmdir("path_is_directory"); + ASSERT_FALSE(platform::path_is_directory("path_is_directory")); +} + +TEST(Platform, get_change_directory) +{ + platform::unlink("working_directory"); + platform::rmdir("working_directory"); + + auto cwd = platform::current_directory(); + ASSERT_GT(cwd.size(), 0); + + platform::mkdir("working_directory"); + ASSERT_EQ(platform::chdir("working_directory"), 0); + ASSERT_THAT(platform::current_directory(), EndsWith("working_directory")); + + ASSERT_EQ(platform::chdir(".."), 0); + ASSERT_THAT(platform::current_directory(), StrEq(cwd)); + platform::rmdir("working_directory"); +} + +TEST(Platform, file_is_readable) +{ + platform::unlink("file_is_readable.txt"); + FILE *fp = fopen("file_is_readable.txt", "w"); + fputs("some text\n", fp); + fclose(fp); + + ASSERT_TRUE(platform::file_is_readable("file_is_readable.txt")); + ASSERT_FALSE(platform::file_is_readable("file_does_not_exist.txt")); + platform::unlink("file_is_readable.txt"); + + // windows does not have permission flags +#if !defined(_WIN32) + platform::unlink("file_is_not_readable.txt"); + fp = fopen("file_is_not_readable.txt", "w"); + fputs("some text\n", fp); + fclose(fp); + chmod("file_is_not_readable.txt", 0); + ASSERT_FALSE(platform::file_is_readable("file_is_not_readable.txt")); + platform::unlink("file_is_not_readable.txt"); +#endif +} + +TEST(Platform, has_compress_extension) +{ + ASSERT_FALSE(platform::has_compress_extension("dummy")); + ASSERT_FALSE(platform::has_compress_extension("dum.my")); + ASSERT_TRUE(platform::has_compress_extension("dummy.gz")); + ASSERT_TRUE(platform::has_compress_extension("dummy.bz2")); + ASSERT_TRUE(platform::has_compress_extension("dummy.zst")); + ASSERT_TRUE(platform::has_compress_extension("dummy.xz")); + ASSERT_TRUE(platform::has_compress_extension("dummy.lzma")); + ASSERT_TRUE(platform::has_compress_extension("dummy.lz4")); +} + +TEST(Platform, compress_read_write) +{ + const std::vector test_files = {"zip_test.zip", "zip_test.gz", "zip_test.bz2", + "zip_test.zst", "zip_test.xz", "zip_test.lzma", + "zip_test.lz4", "zip_test.unk", "zip test.gz"}; + for (const auto &file : test_files) { + platform::unlink(file); + FILE *fp = platform::compressed_write(file); + if (!fp) { + platform::unlink(file); + continue; + } + + clearerr(fp); + fputs("line one\n", fp); + fputs("line two\n", fp); + ASSERT_EQ(ferror(fp), 0); + fflush(fp); + platform::pclose(fp); + + fp = platform::compressed_read(file); + ASSERT_NE(fp, nullptr); + char buf[128]; + char *ptr = fgets(buf, 128, fp); + EXPECT_THAT(ptr, StartsWith("line one")); + ptr = fgets(buf, 128, fp); + EXPECT_THAT(ptr, StartsWith("line two")); + ASSERT_EQ(ferror(fp), 0); + platform::pclose(fp); + platform::unlink(file); + } +} diff --git a/unittest/utils/test_utils.cpp b/unittest/utils/test_utils.cpp index e0bc4984cc..72a90a95a0 100644 --- a/unittest/utils/test_utils.cpp +++ b/unittest/utils/test_utils.cpp @@ -13,14 +13,12 @@ #include "lmptype.h" #include "pointers.h" -#include "utils.h" #include "tokenizer.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include -#include #include #include @@ -66,6 +64,14 @@ TEST(Utils, trim) ASSERT_THAT(trimmed, StrEq("")); } +TEST(Utils, casemod) +{ + ASSERT_THAT(utils::lowercase("Gba35%*zAKgRvr"), StrEq("gba35%*zakgrvr")); + ASSERT_THAT(utils::lowercase("A BC DEFG"), StrEq("a bc defg")); + ASSERT_THAT(utils::uppercase("Gba35%*zAKgRvr"), StrEq("GBA35%*ZAKGRVR")); + ASSERT_THAT(utils::uppercase("a bc defg"), StrEq("A BC DEFG")); +} + TEST(Utils, trim_comment) { auto trimmed = utils::trim_comment("some text # comment"); @@ -721,54 +727,6 @@ TEST(Utils, boundsbig_case3) ASSERT_EQ(nhi, -1); } -TEST(Utils, guesspath) -{ - char buf[256]; - FILE *fp = fopen("test_guesspath.txt", "w"); -#if defined(__linux__) || defined(__APPLE__) || defined(_WIN32) - const char *path = utils::guesspath(buf, sizeof(buf), fp); - ASSERT_THAT(path, EndsWith("test_guesspath.txt")); -#else - const char *path = utils::guesspath(buf, sizeof(buf), fp); - ASSERT_THAT(path, EndsWith("(unknown)")); -#endif - fclose(fp); -} - -TEST(Utils, path_join) -{ -#if defined(_WIN32) - ASSERT_THAT(utils::path_join("c:\\parent\\folder", "filename"), - Eq("c:\\parent\\folder\\filename")); -#else - ASSERT_THAT(utils::path_join("/parent/folder", "filename"), Eq("/parent/folder/filename")); -#endif -} - -TEST(Utils, path_basename) -{ -#if defined(_WIN32) - ASSERT_THAT(utils::path_basename("c:\\parent\\folder\\filename"), Eq("filename")); - ASSERT_THAT(utils::path_basename("folder\\"), Eq("")); - ASSERT_THAT(utils::path_basename("c:/parent/folder/filename"), Eq("filename")); -#else - ASSERT_THAT(utils::path_basename("/parent/folder/filename"), Eq("filename")); - ASSERT_THAT(utils::path_basename("/parent/folder/"), Eq("")); -#endif -} - -TEST(Utils, path_dirname) -{ -#if defined(_WIN32) - ASSERT_THAT(utils::path_dirname("c:/parent/folder/filename"), Eq("c:/parent/folder")); - ASSERT_THAT(utils::path_dirname("c:\\parent\\folder\\filename"), Eq("c:\\parent\\folder")); - ASSERT_THAT(utils::path_dirname("c:filename"), Eq(".")); -#else - ASSERT_THAT(utils::path_dirname("/parent/folder/filename"), Eq("/parent/folder")); -#endif - ASSERT_THAT(utils::path_dirname("filename"), Eq(".")); -} - TEST(Utils, getsyserror) { #if defined(__linux__) @@ -792,16 +750,16 @@ TEST(Utils, potential_file) fputs("# CONTRIBUTOR: Pippo\n", fp); fclose(fp); - ASSERT_TRUE(utils::file_is_readable("ctest1.txt")); - ASSERT_TRUE(utils::file_is_readable("ctest2.txt")); - ASSERT_FALSE(utils::file_is_readable("no_such_file.txt")); + ASSERT_TRUE(platform::file_is_readable("ctest1.txt")); + ASSERT_TRUE(platform::file_is_readable("ctest2.txt")); + ASSERT_FALSE(platform::file_is_readable("no_such_file.txt")); ASSERT_THAT(utils::get_potential_file_path("ctest1.txt"), Eq("ctest1.txt")); ASSERT_THAT(utils::get_potential_file_path("no_such_file.txt"), Eq("")); const char *folder = getenv("LAMMPS_POTENTIALS"); if (folder != nullptr) { - std::string path = utils::path_join(folder, "Cu_u3.eam"); + std::string path = platform::path_join(folder, "Cu_u3.eam"); EXPECT_THAT(utils::get_potential_file_path("Cu_u3.eam"), Eq(path)); EXPECT_THAT(utils::get_potential_units(path, "EAM"), Eq("metal")); } diff --git a/unittest/utils/testshared.c b/unittest/utils/testshared.c new file mode 100644 index 0000000000..869be91c2a --- /dev/null +++ b/unittest/utils/testshared.c @@ -0,0 +1,20 @@ +/* file for testing loading of shared objects and libraries */ + +int some_int_val = 12345; +double some_double_val = 6.78e-9; + +int some_int_function(int arg) +{ + return arg*arg; +} + +double some_double_function(double arg1, int arg2) +{ + double sum = 0; + for (int i = 0; i < arg2; ++i) + sum += arg1; + return sum; +} + + +