diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 921295f6e6..62b80d6044 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,7 +2,7 @@ -**Related Issues** +**Related Issue(s)** diff --git a/.github/PULL_REQUEST_TEMPLATE/bug_fix.md b/.github/PULL_REQUEST_TEMPLATE/bug_fix.md index a5a0b8c489..d359c23a84 100644 --- a/.github/PULL_REQUEST_TEMPLATE/bug_fix.md +++ b/.github/PULL_REQUEST_TEMPLATE/bug_fix.md @@ -9,34 +9,37 @@ assignees: '' **Summary** - + **Related Issue(s)** - + **Author(s)** - + **Licensing** -By submitting this pull request I implicitly accept, that my submission is subject to the same licensing terms as the files that are modified. +By submitting this pull request, I agree, that my contribution will be included in LAMMPS and redistributed under either the GNU General Public License version 2 (GPL v2) or the GNU Lesser General Public License version 2.1 (LGPL v2.1). **Backward Compatibility** - + **Detailed Description** -## Post Submission Checklist +**Post Submission Checklist** - -- [ ] The code in this pull request is complete + + +- [ ] The feature or features in this pull request is complete +- [ ] Licensing information is complete +- [ ] Corresponding author information is complete - [ ] The source code follows the LAMMPS formatting guidelines +- [ ] The feature has been verified to work with the conventional build system +- [ ] The feature has been verified to work with the CMake based build system +- [ ] Suitable tests have been added to the unittest tree. -## Further Information, Files, and Links - - diff --git a/.github/PULL_REQUEST_TEMPLATE/maintenance_refactoring.md b/.github/PULL_REQUEST_TEMPLATE/maintenance_refactoring.md index b7bf40a1e8..ef5add65d8 100644 --- a/.github/PULL_REQUEST_TEMPLATE/maintenance_refactoring.md +++ b/.github/PULL_REQUEST_TEMPLATE/maintenance_refactoring.md @@ -13,23 +13,31 @@ assignees: '' **Related Issue(s)** - **Author(s)** - + **Licensing** -By submitting this pull request I implicitly accept, that my submission is subject to the same licensing terms as the files that are modified. +By submitting this pull request, I agree, that my contribution will be included in LAMMPS and redistributed under either the GNU General Public License version 2 (GPL v2) or the GNU Lesser General Public License version 2.1 (LGPL v2.1). + +**Backward Compatibility** + + **Detailed Description** - + -## Post Submission Checklist +**Post Submission Checklist** - [ ] The pull request is complete - [ ] The source code follows the LAMMPS formatting guidelines +- [ ] The feature has been verified to work with the conventional build system +- [ ] The feature has been verified to work with the CMake based build system +- [ ] Suitable tests have been added to the unittest tree. + diff --git a/.github/PULL_REQUEST_TEMPLATE/new_feature.md b/.github/PULL_REQUEST_TEMPLATE/new_feature.md index 563a9be4aa..aaeeb94660 100644 --- a/.github/PULL_REQUEST_TEMPLATE/new_feature.md +++ b/.github/PULL_REQUEST_TEMPLATE/new_feature.md @@ -11,32 +11,29 @@ assignees: '' -**Related Issues** +**Related Issue(s)** - + **Author(s)** - + **Licensing** - - -My contribution may be licensed as GPL v2 (default LAMMPS license): -My contribution may be licensed as LGPL (for use as a library with proprietary software): +By submitting this pull request, I agree, that my contribution will be included in LAMMPS and redistributed under either the GNU General Public License version 2 (GPL v2) or the GNU Lesser General Public License version 2.1 (LGPL v2.1). **Backward Compatibility** - + **Implementation Notes** - + -## Post Submission Checklist +**Post Submission Checklist** - + - [ ] The feature or features in this pull request is complete - [ ] Licensing information is complete @@ -46,10 +43,11 @@ My contribution may be licensed as LGPL (for use as a library with proprietary s - [ ] The added/updated documentation is integrated and tested with the documentation build system - [ ] The feature has been verified to work with the conventional build system - [ ] The feature has been verified to work with the CMake based build system +- [ ] Suitable tests have been added to the unittest tree. - [ ] A package specific README file has been included or updated - [ ] One or more example input decks are included -## Further Information, Files, and Links +**Further Information, Files, and Links** diff --git a/.github/PULL_REQUEST_TEMPLATE/update_enhancement.md b/.github/PULL_REQUEST_TEMPLATE/update_enhancement.md index 9edfb587c0..467d8db6b7 100644 --- a/.github/PULL_REQUEST_TEMPLATE/update_enhancement.md +++ b/.github/PULL_REQUEST_TEMPLATE/update_enhancement.md @@ -11,17 +11,21 @@ assignees: '' +**Related Issue(s)** + + + **Author(s)** **Licensing** -By submitting this pull request I implicitly accept, that my submission is subject to the same licensing terms as the original package or feature(s) that are updated or amended by this pull request. +By submitting this pull request, I agree, that my contribution will be included in LAMMPS and redistributed under either the GNU General Public License version 2 (GPL v2) or the GNU Lesser General Public License version 2.1 (LGPL v2.1). **Backward Compatibility** - + **Implementation Notes** @@ -29,11 +33,19 @@ By submitting this pull request I implicitly accept, that my submission is subje **Post Submission Checklist** - + + - [ ] The feature or features in this pull request is complete -- [ ] Suitable updates to the existing docs are included -- [ ] One or more example input decks are included +- [ ] Licensing information is complete +- [ ] Corresponding author information is complete - [ ] The source code follows the LAMMPS formatting guidelines +- [ ] Suitable updates to the existing docs are included +- [ ] The updated documentation is integrated and tested with the documentation build system +- [ ] The feature has been verified to work with the conventional build system +- [ ] The feature has been verified to work with the CMake based build system +- [ ] Suitable tests have been updated or added to the unittest tree. +- [ ] A package specific README file has been updated +- [ ] One or more example input decks are included **Further Information, Files, and Links** diff --git a/README b/README index 680986bf61..7b30b891ed 100644 --- a/README +++ b/README @@ -22,28 +22,32 @@ more information about the code and its uses. The LAMMPS distribution includes the following files and directories: -README this file -LICENSE the GNU General Public License (GPL) -bench benchmark problems -cmake CMake build system -doc documentation -examples simple test problems -lib libraries LAMMPS can be linked with -potentials interatomic potential files -python Python wrapper on LAMMPS as a library -src source files -tools pre- and post-processing tools +README this file +LICENSE the GNU General Public License (GPL) +bench benchmark problems +cmake CMake build files +doc documentation +examples simple test problems +fortran Fortran wrapper for LAMMPS +lib additional provided or external libraries +potentials interatomic potential files +python Python wrappers for LAMMPS +src source files +tools pre- and post-processing tools Point your browser at any of these files to get started: -http://lammps.sandia.gov/doc/Manual.html the LAMMPS manual -http://lammps.sandia.gov/doc/Intro.html hi-level introduction -http://lammps.sandia.gov/doc/Build.html how to build LAMMPS -http://lammps.sandia.gov/doc/Run_head.html how to run LAMMPS -http://lammps.sandia.gov/doc/Developer.pdf LAMMPS developer guide +https://lammps.sandia.gov/doc/Manual.html LAMMPS user manual +https://lammps.sandia.gov/doc/Intro.html hi-level introduction +https://lammps.sandia.gov/doc/Build.html how to build LAMMPS +https://lammps.sandia.gov/doc/Run_head.html how to run LAMMPS +https://lammps.sandia.gov/doc/Commands_all.html Table of available commands +https://lammps.sandia.gov/doc/pg_library.html LAMMPS programmer guide +https://lammps.sandia.gov/doc/Modify.html how to modify and extend LAMMPS +https://lammps.sandia.gov/doc/pg_developer.html LAMMPS developer guide You can also create these doc pages locally: % cd doc % make html # creates HTML pages in doc/html -% make pdf # creates Manual.pdf and Developer.pdf +% make pdf # creates Manual.pdf diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 9e0d748140..d9887925ec 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -157,11 +157,11 @@ else() file(GLOB MPI_SOURCES ${LAMMPS_SOURCE_DIR}/STUBS/mpi.c) add_library(mpi_stubs STATIC ${MPI_SOURCES}) set_target_properties(mpi_stubs PROPERTIES OUTPUT_NAME lammps_mpi_stubs${LAMMPS_MACHINE}) - target_include_directories(mpi_stubs PUBLIC $ $) - install(FILES ${LAMMPS_SOURCE_DIR}/STUBS/mpi.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lammps/mpi) + target_include_directories(mpi_stubs PUBLIC $) if(BUILD_SHARED_LIBS) target_link_libraries(lammps PRIVATE mpi_stubs) - target_include_directories(lammps INTERFACE $ $) + target_include_directories(lammps INTERFACE $) + target_compile_definitions(lammps INTERFACE $) else() target_link_libraries(lammps PUBLIC mpi_stubs) endif() @@ -574,7 +574,7 @@ if (${_index} GREATER -1) endif() set(LAMMPS_CXX_HEADERS angle.h atom.h bond.h citeme.h comm.h compute.h dihedral.h domain.h error.h fix.h force.h group.h improper.h input.h info.h kspace.h lammps.h lattice.h library.h lmppython.h lmptype.h memory.h modify.h neighbor.h neigh_list.h output.h - pair.h pointers.h region.h timer.h universe.h update.h variable.h) + pair.h pointers.h region.h timer.h universe.h update.h utils.h variable.h) if(LAMMPS_EXCEPTIONS) list(APPEND LAMMPS_CXX_HEADERS exceptions.h) endif() diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index 3b323e37ff..054e08fc1a 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -3,11 +3,16 @@ # # Requires latest gcovr (for GCC 8.1 support):# # pip install git+https://github.com/gcovr/gcovr.git +# +# For Python coverage the coverage package needs to be installed ############################################################################### if(ENABLE_COVERAGE) find_program(GCOVR_BINARY gcovr) find_package_handle_standard_args(GCOVR DEFAULT_MSG GCOVR_BINARY) + find_program(COVERAGE_BINARY coverage) + find_package_handle_standard_args(COVERAGE DEFAULT_MSG COVERAGE_BINARY) + if(GCOVR_FOUND) get_filename_component(ABSOLUTE_LAMMPS_SOURCE_DIR ${LAMMPS_SOURCE_DIR} ABSOLUTE) @@ -46,4 +51,30 @@ if(ENABLE_COVERAGE) ) add_dependencies(reset_coverage clean_coverage_html) endif() + + if(COVERAGE_FOUND) + set(PYTHON_COVERAGE_HTML_DIR ${CMAKE_BINARY_DIR}/python_coverage_html) + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/unittest/python/.coverage + COMMAND ${COVERAGE_BINARY} combine + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python + COMMENT "Combine Python coverage files..." + ) + + add_custom_target( + gen_python_coverage_html + COMMAND ${COVERAGE_BINARY} html -d ${PYTHON_COVERAGE_HTML_DIR} + DEPENDS ${CMAKE_BINARY_DIR}/unittest/python/.coverage + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python + COMMENT "Generating HTML Python coverage report..." + ) + + add_custom_target( + gen_python_coverage_xml + COMMAND ${COVERAGE_BINARY} xml -o ${CMAKE_BINARY_DIR}/python_coverage.xml + DEPENDS ${CMAKE_BINARY_DIR}/unittest/python/.coverage + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python + COMMENT "Generating XML Python coverage report..." + ) + endif() endif() diff --git a/cmake/Modules/GenerateBinaryHeader.cmake b/cmake/Modules/GenerateBinaryHeader.cmake index 512f69e09d..498a4f68f5 100644 --- a/cmake/Modules/GenerateBinaryHeader.cmake +++ b/cmake/Modules/GenerateBinaryHeader.cmake @@ -1,3 +1,3 @@ # utility script to call GenerateBinaryHeader function include(${SOURCE_DIR}/Modules/LAMMPSUtils.cmake) -GenerateBinaryHeader(${VARNAME} ${HEADER_FILE} ${SOURCE_FILES}) +GenerateBinaryHeader(${VARNAME} ${HEADER_FILE} ${SOURCE_FILE}) diff --git a/cmake/Modules/LAMMPSUtils.cmake b/cmake/Modules/LAMMPSUtils.cmake index a87c0f567c..339ba867bd 100644 --- a/cmake/Modules/LAMMPSUtils.cmake +++ b/cmake/Modules/LAMMPSUtils.cmake @@ -71,19 +71,15 @@ macro(pkg_depends PKG1 PKG2) endmacro() # CMake-only replacement for bin2c and xxd -function(GenerateBinaryHeader varname outfile files) +function(GenerateBinaryHeader varname outfile infile) message("Creating ${outfile}...") file(WRITE ${outfile} "// CMake generated file\n") - math(EXPR ARG_END "${ARGC}-1") - foreach(IDX RANGE 2 ${ARG_END}) - list(GET ARGV ${IDX} filename) - file(READ ${filename} content HEX) - string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," content "${content}") - string(REGEX REPLACE ",$" "" content "${content}") - file(APPEND ${outfile} "const unsigned char ${varname}[] = { ${content} };\n") - file(APPEND ${outfile} "const unsigned int ${varname}_size = sizeof(${varname});\n") - endforeach() + file(READ ${infile} content HEX) + string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," content "${content}") + string(REGEX REPLACE ",$" "" content "${content}") + file(APPEND ${outfile} "const unsigned char ${varname}[] = { ${content} };\n") + file(APPEND ${outfile} "const unsigned int ${varname}_size = sizeof(${varname});\n") endfunction(GenerateBinaryHeader) # fetch missing potential files diff --git a/cmake/Modules/Packages/GPU.cmake b/cmake/Modules/Packages/GPU.cmake index ac2c975da3..cad6e2bf9a 100644 --- a/cmake/Modules/Packages/GPU.cmake +++ b/cmake/Modules/Packages/GPU.cmake @@ -309,7 +309,7 @@ elseif(GPU_API STREQUAL "HIP") endif() add_custom_command(OUTPUT ${CUBIN_H_FILE} - COMMAND ${CMAKE_COMMAND} -D SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -D VARNAME=${CU_NAME} -D HEADER_FILE=${CUBIN_H_FILE} -D SOURCE_FILES=${CUBIN_FILE} -P ${CMAKE_CURRENT_SOURCE_DIR}/Modules/GenerateBinaryHeader.cmake + COMMAND ${CMAKE_COMMAND} -D SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -D VARNAME=${CU_NAME} -D HEADER_FILE=${CUBIN_H_FILE} -D SOURCE_FILE=${CUBIN_FILE} -P ${CMAKE_CURRENT_SOURCE_DIR}/Modules/GenerateBinaryHeader.cmake DEPENDS ${CUBIN_FILE} COMMENT "Generating ${CU_NAME}_cubin.h") diff --git a/cmake/Modules/Packages/USER-COLVARS.cmake b/cmake/Modules/Packages/USER-COLVARS.cmake index 92595a9c8a..3488aa62b1 100644 --- a/cmake/Modules/Packages/USER-COLVARS.cmake +++ b/cmake/Modules/Packages/USER-COLVARS.cmake @@ -2,6 +2,8 @@ set(COLVARS_SOURCE_DIR ${LAMMPS_LIB_SOURCE_DIR}/colvars) file(GLOB COLVARS_SOURCES ${COLVARS_SOURCE_DIR}/[^.]*.cpp) +option(COLVARS_DEBUG "Debugging messages for Colvars (quite verbose)" OFF) + # Build Lepton by default option(COLVARS_LEPTON "Build and link the Lepton library" ON) @@ -16,11 +18,18 @@ if(COLVARS_LEPTON) endif() add_library(colvars STATIC ${COLVARS_SOURCES}) -target_compile_definitions(colvars PRIVATE -DLAMMPS_${LAMMPS_SIZES}) +target_compile_definitions(colvars PRIVATE -DCOLVARS_LAMMPS) set_target_properties(colvars PROPERTIES OUTPUT_NAME lammps_colvars${LAMMPS_MACHINE}) target_include_directories(colvars PUBLIC ${LAMMPS_LIB_SOURCE_DIR}/colvars) +# The line below is needed to locate math_eigen_impl.h +target_include_directories(colvars PRIVATE ${LAMMPS_SOURCE_DIR}) target_link_libraries(lammps PRIVATE colvars) +if(COLVARS_DEBUG) + # Need to export the macro publicly to also affect the proxy + target_compile_definitions(colvars PUBLIC -DCOLVARS_DEBUG) +endif() + if(COLVARS_LEPTON) target_link_libraries(lammps PRIVATE lepton) target_compile_definitions(colvars PRIVATE -DLEPTON) diff --git a/doc/Makefile b/doc/Makefile index 61875cbaae..2b9849d9e8 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,6 +1,12 @@ # Makefile for LAMMPS documentation SHELL = /bin/bash +HAS_BASH = YES +ifeq (,$(wildcard $(SHELL))) +OSHELL := $(SHELL) +override SHELL = /bin/sh +HAS_BASH = NO +endif BUILDDIR = ${CURDIR} RSTDIR = $(BUILDDIR)/src VENV = $(BUILDDIR)/docenv @@ -37,8 +43,10 @@ HAS_VIRTUALENV = YES endif ifeq ($(shell which pdflatex >/dev/null 2>&1; echo $$?), 0) +ifeq ($(shell which latexmk >/dev/null 2>&1; echo $$?), 0) HAS_PDFLATEX = YES endif +endif #SPHINXEXTRA = -j $(shell $(PYTHON) -c 'import multiprocessing;print(multiprocessing.cpu_count())') $(shell test -f $(BUILDDIR)/doxygen/xml/run.stamp && printf -- "-E") @@ -55,6 +63,7 @@ DOXYFILES = $(shell sed -n -e 's/\#.*$$//' -e '/^ *INPUT \+=/,/^[A-Z_]\+ \+ # ------------------------------------------ help: + @if [ "$(HAS_BASH)" == "NO" ] ; then echo "bash was not found at $(OSHELL)! Please use: $(MAKE) SHELL=/path/to/bash" 1>&2; exit 1; fi @echo "Please use \`make ' where is one of" @echo " html create HTML doc pages in html dir" @echo " pdf create Manual.pdf in this dir" @@ -72,7 +81,7 @@ help: # ------------------------------------------ clean-all: clean - rm -rf $(BUILDDIR)/docenv $(MATHJAX) $(BUILDDIR)/LAMMPS.mobi $(BUILDDIR)/LAMMPS.epub $(BUILDDIR)/Manual.pdf + rm -rf $(BUILDDIR)/docenv $(MATHJAX) $(POLYFILL) $(BUILDDIR)/LAMMPS.mobi $(BUILDDIR)/LAMMPS.epub $(BUILDDIR)/Manual.pdf clean: clean-spelling rm -rf $(BUILDDIR)/html $(BUILDDIR)/epub $(BUILDDIR)/latex $(BUILDDIR)/doctrees $(BUILDDIR)/doxygen/xml $(BUILDDIR)/doxygen-warn.log $(BUILDDIR)/doxygen/Doxyfile $(SPHINXCONFIG)/conf.py @@ -87,6 +96,7 @@ $(SPHINXCONFIG)/conf.py: $(SPHINXCONFIG)/conf.py.in -e 's,@LAMMPS_DOC_DIR@,$(BUILDDIR),g' $< > $@ html: xmlgen $(SPHINXCONFIG)/conf.py $(ANCHORCHECK) $(MATHJAX) $(POLYFILL) + @if [ "$(HAS_BASH)" == "NO" ] ; then echo "bash was not found at $(OSHELL)! Please use: $(MAKE) SHELL=/path/to/bash" 1>&2; exit 1; fi @$(MAKE) $(MFLAGS) -C graphviz all @(\ . $(VENV)/bin/activate ; env PYTHONWARNINGS= \ @@ -110,6 +120,7 @@ html: xmlgen $(SPHINXCONFIG)/conf.py $(ANCHORCHECK) $(MATHJAX) $(POLYFILL) @echo "Build finished. The HTML pages are in doc/html." spelling: xmlgen $(VENV) $(SPHINXCONFIG)/false_positives.txt + @if [ "$(HAS_BASH)" == "NO" ] ; then echo "bash was not found at $(OSHELL)! Please use: $(MAKE) SHELL=/path/to/bash" 1>&2; exit 1; fi @(\ . $(VENV)/bin/activate ; env PYTHONWARNINGS= \ cp $(SPHINXCONFIG)/false_positives.txt $(RSTDIR)/ ; env PYTHONWARNINGS= \ @@ -120,6 +131,7 @@ spelling: xmlgen $(VENV) $(SPHINXCONFIG)/false_positives.txt @echo "Spell check finished." epub: xmlgen $(VENV) $(SPHINXCONFIG)/conf.py $(ANCHORCHECK) + @if [ "$(HAS_BASH)" == "NO" ] ; then echo "bash was not found at $(OSHELL)! Please use: $(MAKE) SHELL=/path/to/bash" 1>&2; exit 1; fi @$(MAKE) $(MFLAGS) -C graphviz all @mkdir -p epub/JPG @rm -f LAMMPS.epub @@ -140,8 +152,9 @@ mobi: epub @echo "Conversion finished. The MOBI manual file is created." pdf: xmlgen $(VENV) $(SPHINXCONFIG)/conf.py $(ANCHORCHECK) + @if [ "$(HAS_BASH)" == "NO" ] ; then echo "bash was not found at $(OSHELL)! Please use: $(MAKE) SHELL=/path/to/bash" 1>&2; exit 1; fi @$(MAKE) $(MFLAGS) -C graphviz all - @if [ "$(HAS_PDFLATEX)" == "NO" ] ; then echo "PDFLaTeX was not found! Please check README.md for further instructions" 1>&2; exit 1; fi + @if [ "$(HAS_PDFLATEX)" == "NO" ] ; then echo "PDFLaTeX or latexmk were not found! Please check README for further instructions" 1>&2; exit 1; fi @(\ . $(VENV)/bin/activate ; env PYTHONWARNINGS= \ sphinx-build $(SPHINXEXTRA) -b latex -c $(SPHINXCONFIG) -d $(BUILDDIR)/doctrees $(RSTDIR) latex ;\ @@ -155,15 +168,13 @@ pdf: xmlgen $(VENV) $(SPHINXCONFIG)/conf.py $(ANCHORCHECK) deactivate ;\ ) @cd latex && \ - sed 's/latexmk -pdf -dvi- -ps-/pdflatex/g' Makefile > temp && \ - mv temp Makefile && \ sed 's/\\begin{equation}//g' LAMMPS.tex > tmp.tex && \ mv tmp.tex LAMMPS.tex && \ sed 's/\\end{equation}//g' LAMMPS.tex > tmp.tex && \ mv tmp.tex LAMMPS.tex && \ - make && \ - make && \ - make && \ + sed 's/\\contentsname}{.*}}/\\contentsname}{LAMMPS Documentation}}/g' LAMMPS.tex > tmp.tex && \ + mv tmp.tex LAMMPS.tex && \ + $(MAKE) $(MFLAGS) && \ mv LAMMPS.pdf ../Manual.pdf && \ cd ../; @rm -rf latex/_sources @@ -211,6 +222,7 @@ doxygen/xml/index.xml : $(VENV) doxygen/Doxyfile $(DOXYFILES) # ------------------------------------------ $(VENV): + @if [ "$(HAS_BASH)" == "NO" ] ; then echo "bash was not found at $(OSHELL)! Please use: $(MAKE) SHELL=/path/to/bash" 1>&2; exit 1; fi @if [ "$(HAS_PYTHON3)" == "NO" ] ; then echo "python3 was not found! Please see README for further instructions" 1>&2; exit 1; fi @if [ "$(HAS_DOXYGEN)" == "NO" ] ; then echo "doxygen was not found! Please see README for further instructions" 1>&2; exit 1; fi @if [ "$(HAS_VIRTUALENV)" == "NO" ] ; then echo "virtualenv was not found! Please see README for further instructions" 1>&2; exit 1; fi @@ -225,8 +237,12 @@ $(VENV): $(MATHJAX): @git clone --depth 1 https://github.com/mathjax/MathJax.git $@ +# fall back to using wget and/or unencrypted download, if curl fails $(POLYFILL): $(MATHJAX) - @curl -s -o $@ "https://polyfill.io/v3/polyfill.min.js?features=es6" + @curl -s -o $@ "https://polyfill.io/v3/polyfill.min.js?features=es6" > /dev/null 2>&1 || \ + curl -s -o $@ "http://polyfill.io/v3/polyfill.min.js?features=es6" > /dev/null 2>&1 || \ + wget -O $@ "https://polyfill.io/v3/polyfill.min.js?features=es6" > /dev/null 2>&1 || \ + wget -O $@ "http://polyfill.io/v3/polyfill.min.js?features=es6" > /dev/null 2>&1 $(TXT2RST) $(ANCHORCHECK): $(VENV) @( \ diff --git a/doc/README b/doc/README index f0c74f7771..8af4021a60 100644 --- a/doc/README +++ b/doc/README @@ -9,12 +9,10 @@ src content files for LAMMPS documentation html HTML version of the LAMMPS manual (see html/Manual.html) utils utilities and settings for building the documentation Manual.pdf PDF version of entire manual -Developer.pdf PDF with info about how LAMMPS is structured LAMMPS.epub Manual in ePUB format LAMMPS.mobi Manual in MOBI (Kindle) format lammps.1 man page for the lammps command msi2lmp.1 man page for the msi2lmp command -mathjax code and fonts for rendering math in html doctree temporary data docenv python virtual environment for generating the manual doxygen Doxygen configuration and output @@ -32,9 +30,9 @@ folder and the PDF manual should be included. If you downloaded LAMMPS from GitHub then you either need to download them or build them. (a) You can "fetch" the current HTML and PDF files from the LAMMPS web -site. Just type "make fetch". This should create a html_www dir and -Manual_www.pdf/Developer_www.pdf files. These files will always -represent the latest published patch/development version of LAMMPS. +site. Just type "make fetch". This should create a html_www directory +and Manual_www.pdf file. These will always represent the latest published +patch/development version of LAMMPS. (b) You can build the HTML and PDF files yourself, by typing "make html" or by "make pdf", respectively. This requires various tools and files. @@ -68,6 +66,9 @@ installed. This includes: - tabulary - upquote - wrapfig +Also the latexmk script is required to run PDFLaTeX and related tools. +the required number of times to have self-consistent output and include +updated bibliography and indices. Building the EPUB format requires LaTeX installation with the same packages as for the PDF format plus the 'dvipng' command to convert the embedded math diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in index f0bf127ee1..f8a5bc6cdb 100644 --- a/doc/doxygen/Doxyfile.in +++ b/doc/doxygen/Doxyfile.in @@ -416,6 +416,7 @@ INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \ @LAMMPS_SOURCE_DIR@/library.h \ @LAMMPS_SOURCE_DIR@/lammps.cpp \ @LAMMPS_SOURCE_DIR@/lammps.h \ + @LAMMPS_SOURCE_DIR@/pointers.h \ @LAMMPS_SOURCE_DIR@/lmptype.h \ @LAMMPS_SOURCE_DIR@/atom.cpp \ @LAMMPS_SOURCE_DIR@/atom.h \ @@ -431,6 +432,7 @@ INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \ @LAMMPS_SOURCE_DIR@/my_page.h \ @LAMMPS_SOURCE_DIR@/my_pool_chunk.cpp \ @LAMMPS_SOURCE_DIR@/my_pool_chunk.h \ + @LAMMPS_SOURCE_DIR@/math_eigen.h \ # 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/graphviz/Makefile b/doc/graphviz/Makefile index fb6411379d..a8c424c540 100644 --- a/doc/graphviz/Makefile +++ b/doc/graphviz/Makefile @@ -1,6 +1,5 @@ # Makefile for generating images with graphviz # -SHELL = /bin/bash BUILDDIR = ${CURDIR}/.. IMGDIR = $(BUILDDIR)/src/JPG IMGSRC = $(wildcard *.dot) diff --git a/doc/lammps.1 b/doc/lammps.1 index c123bf8a63..71795325e8 100644 --- a/doc/lammps.1 +++ b/doc/lammps.1 @@ -1,4 +1,4 @@ -.TH LAMMPS "24 August 2020" "2020-08-24" +.TH LAMMPS "18 September 2020" "2020-09-18" .SH NAME .B LAMMPS \- Molecular Dynamics Simulator. diff --git a/doc/src/Build_basics.rst b/doc/src/Build_basics.rst index 3b20209e5c..d364382591 100644 --- a/doc/src/Build_basics.rst +++ b/doc/src/Build_basics.rst @@ -159,11 +159,11 @@ others (e.g. GCC version 9 and beyond, Clang version 10 and later) may implement strict OpenMP 4.0 and later semantics, which are incompatible with the OpenMP 3.1 semantics used in LAMMPS for maximal compatibility with compiler versions in use. If compilation with OpenMP enabled fails -because of your compiler requiring strict OpenMP 4.0 semantic, you can +because of your compiler requiring strict OpenMP 4.0 semantics, you can change the behavior by adding ``-D LAMMPS_OMP_COMPAT=4`` to the ``LMP_INC`` variable in your makefile, or add it to the command line -while configuring with CMake. CMake will detect the suitable setting for -the GNU, Clang, and Intel compilers. +while configuring with CMake. LAMMPS will autodetect a suitable setting +for most GNU, Clang, and Intel compilers. ---------- diff --git a/doc/src/Build_settings.rst b/doc/src/Build_settings.rst index 600bd084ec..9618d7e5a4 100644 --- a/doc/src/Build_settings.rst +++ b/doc/src/Build_settings.rst @@ -487,3 +487,41 @@ e.g. to Python. Of course, the calling code has to be set up to cleanly recover from an exception since not all parallel ranks may throw an exception and thus other MPI ranks may get stuck waiting for messages from the ones with errors. + +---------- + +.. _trap_fpe: + +Trigger selected floating-point exceptions +------------------------------------------ + +Many kinds of CPUs have the capability to detect when a calculation +results in an invalid math operation like a division by zero or calling +the square root with a negative argument. The default behavior on +most operating systems is to continue and have values for ``NaN`` (= not +a number) or ``Inf`` (= infinity). This allows software to detect and +recover from such conditions. This behavior can be changed, however, +often through use of compiler flags. On Linux systems (or more general +on systems using the GNU C library), these so-called floating-point traps +can also be selectively enabled through library calls. LAMMPS supports +that by setting the ``-DLAMMPS_TRAP_FPE`` pre-processor define. As it is +done in the ``main()`` function, this applies only to the standalone +executable, not the library. + +.. tabs:: + + .. tab:: CMake build + + .. code-block:: bash + + -D CMAKE_TUNE_FLAGS=-DLAMMPS_TRAP_FPE + + .. tab:: Traditional make + + .. code-block:: make + + LMP_INC = -DLAMMPS_TRAP_FPE + +After compilation with this flag set, the LAMMPS executable will stop +and produce a core dump when a division by zero, overflow, illegal math +function argument or other invalid floating point operation is encountered. diff --git a/doc/src/Errors_messages.rst b/doc/src/Errors_messages.rst index 6bf2e1092c..b1b9f38311 100644 --- a/doc/src/Errors_messages.rst +++ b/doc/src/Errors_messages.rst @@ -5708,6 +5708,9 @@ Doc page with :doc:`WARNING messages ` *Molecule file has dihedrals but no ndihedrals setting* Self-explanatory. +*Molecule file has fragments but no nfragments setting* + Self-explanatory. + *Molecule file has impropers but no nimpropers setting* Self-explanatory. @@ -5717,6 +5720,9 @@ Doc page with :doc:`WARNING messages ` *Molecule file has no Body Integers section* Self-explanatory. +*Molecule file has no Fragments section* + Self-explanatory. + *Molecule file has special flags but no bonds* Self-explanatory. diff --git a/doc/src/Install.rst b/doc/src/Install.rst index 03a1551686..29e19767b2 100644 --- a/doc/src/Install.rst +++ b/doc/src/Install.rst @@ -23,7 +23,7 @@ need the source code. These are the files and sub-directories in the LAMMPS distribution: +------------+-------------------------------------------+ -| README | text file | +| README | Short description of the LAMMPS package | +------------+-------------------------------------------+ | LICENSE | GNU General Public License (GPL) | +------------+-------------------------------------------+ @@ -35,16 +35,20 @@ These are the files and sub-directories in the LAMMPS distribution: +------------+-------------------------------------------+ | examples | simple test problems | +------------+-------------------------------------------+ +| fortran | Fortran wrapper for LAMMPS | ++------------+-------------------------------------------+ | lib | additional provided or external libraries | +------------+-------------------------------------------+ | potentials | interatomic potential files | +------------+-------------------------------------------+ -| python | Python wrapper on LAMMPS | +| python | Python wrappers for LAMMPS | +------------+-------------------------------------------+ | src | source files | +------------+-------------------------------------------+ | tools | pre- and post-processing tools | +------------+-------------------------------------------+ +| unittest | sources and inputs for testing LAMMPS | ++------------+-------------------------------------------+ You will have all of these if you download source. You will only have some of them if you download executables, as explained on the pages diff --git a/doc/src/Intro.rst b/doc/src/Intro.rst index 6d388aa87e..53111f71c3 100644 --- a/doc/src/Intro.rst +++ b/doc/src/Intro.rst @@ -12,4 +12,5 @@ These pages provide a brief introduction to LAMMPS. Intro_nonfeatures Intro_opensource Intro_authors + Intro_citing Intro_website diff --git a/doc/src/Intro_citing.rst b/doc/src/Intro_citing.rst new file mode 100644 index 0000000000..aa27080a75 --- /dev/null +++ b/doc/src/Intro_citing.rst @@ -0,0 +1,52 @@ +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: + + `S. Plimpton, Fast Parallel Algorithms for Short-Range Molecular Dynamics, J Comp Phys, 117, 1-19 (1995). `_ + +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. + + +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: 1) the canonical DOI for **all** versions of LAMMPS, +which will always point to the latest stable release version is: + + `DOI: 10.5281/zenodo.3726416 `_ + +In addition there are DOIs for individual stable releases starting with +the `3 March 2020 version, DOI:10.5281/zenodo.3726417 `_ + + +Home page +^^^^^^^^^ + +The LAMMPS website at `https://lammps.sandia.gov/ `_ is the canonical +location for information about LAMMPS and more detailed lists of publications +using LAMMPS and contributing features. + +Citing contributions +^^^^^^^^^^^^^^^^^^^^ + +LAMMPS has many features and uses previously published methods and +algorithms or novel features. It also includes potential parameter +filed for specific models. You can look up relevant publications either +in the LAMMPS output to the screen, the ``log.cite`` file (which is +populated with references to relevant papers through embedding them into +the source code) and in the documentation of the :doc:`corresponding commands +` or in the :doc:`Howto tutorials `. diff --git a/doc/src/Manual.rst b/doc/src/Manual.rst index 7c715239df..ddc2b2daa8 100644 --- a/doc/src/Manual.rst +++ b/doc/src/Manual.rst @@ -1,13 +1,8 @@ -LAMMPS Documentation -#################### +LAMMPS version |version| Documentation +###################################### -|version| version -***************** - -:doc:`What is a LAMMPS version? ` - -LAMMPS stands for Large-scale Atomic/Molecular Massively Parallel -Simulator. +LAMMPS stands for **L**\ arge-scale **A**\ tomic/**M**\ olecular +**M**\ assively **P**\ arallel **S**\ imulator. LAMMPS is a classical molecular dynamics simulation code with a focus on materials modeling. It was designed to run efficiently on parallel @@ -28,16 +23,22 @@ The content for this manual is part of the LAMMPS distribution. You can build a local copy of the Manual as HTML pages or a PDF file, by following the steps on the :doc:`Manual build ` doc page. The manual is organized in two parts: -1) A :ref:`User documentation ` for how to install -and use LAMMPS and 2) a :ref:`Programmer documentation ` -for how to write programs using the LAMMPS library or how to modify LAMMPS. +1) the :ref:`User documentation ` for how to install +and use LAMMPS and 2) the :ref:`Programmer documentation ` +for how to write programs using the LAMMPS library from different +programming languages and how to modify and extend LAMMPS. + +.. only:: html + + Once you are familiar with LAMMPS, you may want to bookmark :doc:`this page ` since it gives quick access to a doc page for + every LAMMPS command. + +.. _lws: https://lammps.sandia.gov ---------- -Once you are familiar with LAMMPS, you may want to bookmark :doc:`this page ` since it gives quick access to a doc page for -every LAMMPS command. - -.. _lws: https://lammps.sandia.gov +User Documentation +****************** .. _user_documentation: .. toctree:: @@ -61,6 +62,9 @@ every LAMMPS command. Errors Manual_build +Programmer Documentation +************************ + .. _programmer_documentation: .. toctree:: :maxdepth: 2 @@ -89,7 +93,9 @@ every LAMMPS command. fix_modify_atc_commands Indices and tables -================== +****************** -* :ref:`genindex` -* :ref:`search` +.. only:: html + + * :ref:`genindex` + * :ref:`search` diff --git a/doc/src/Manual_build.rst b/doc/src/Manual_build.rst index a8e3f1a1c6..d1aebe9b09 100644 --- a/doc/src/Manual_build.rst +++ b/doc/src/Manual_build.rst @@ -18,7 +18,6 @@ files. Here is a list with descriptions: LAMMPS.mobi # Manual in MOBI e-book format docenv # virtualenv folder for processing the manual sources doctrees # temporary data from processing the manual - mathjax # code and fonts for rendering math in html doxygen # doxygen configuration and output .gitignore # list of files and folders to be ignored by git doxygen-warn.log # logfile with warnings from running doxygen @@ -34,11 +33,10 @@ of two ways: a. You can "fetch" the current HTML and PDF files from the LAMMPS web site. Just type ``make fetch``. This should download a html_www - directory and a Manual_www.pdf file. Note that if - new LAMMPS features have been added more recently than the date of - your LAMMPS version, the fetched documentation will include those - changes (but your source code will not, unless you update your local - repository). + directory and a Manual_www.pdf file. Note that if new LAMMPS features + have been added more recently than the date of your LAMMPS version, the + fetched documentation will include those changes (but your source code + will not, unless you update your local repository). b. You can build the HTML or PDF files yourself, by typing ``make html`` or ``make pdf``. This requires various tools and files. Some of them @@ -133,7 +131,8 @@ Installing prerequisites for PDF build In addition to the tools needed for building the HTML format manual, a working LaTeX installation with support for PDFLaTeX and a selection -of LaTeX styles/packages are required. +of LaTeX styles/packages are required. To run the PDFLaTeX translation +the ``latexmk`` script needs to be installed as well. Installing prerequisites for e-book reader builds ================================================= diff --git a/doc/src/PDF/colvars-refman-lammps.pdf b/doc/src/PDF/colvars-refman-lammps.pdf index c9a67d6a1d..8fcc37c26e 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/fix_bond_react.rst b/doc/src/fix_bond_react.rst index 8d54ce755b..159e39d075 100644 --- a/doc/src/fix_bond_react.rst +++ b/doc/src/fix_bond_react.rst @@ -41,7 +41,7 @@ Syntax * template-ID(post-reacted) = ID of a molecule template containing post-reaction topology * map_file = name of file specifying corresponding atom-IDs in the pre- and post-reacted templates * zero or more individual keyword/value pairs may be appended to each react argument -* individual_keyword = *prob* or *max_rxn* or *stabilize_steps* or *update_edges* +* individual_keyword = *prob* or *max_rxn* or *stabilize_steps* or *custom_charges* .. parsed-literal:: @@ -52,10 +52,9 @@ Syntax N = maximum number of reactions allowed to occur *stabilize_steps* value = timesteps timesteps = number of timesteps to apply the internally-created :doc:`nve/limit ` fix to reacting atoms - *update_edges* value = *none* or *charges* or *custom* - *none* = do not update topology near the edges of reaction templates - *charges* = update atomic charges of all atoms in reaction templates - *custom* = force the update of user-specified atomic charges + *custom_charges* value = *no* or *fragmentID* + no = update all atomic charges (default) + fragmentID = ID of molecule fragment whose charges are updated Examples """""""" @@ -271,14 +270,14 @@ A discussion of correctly handling this is also provided on the The map file is a text document with the following format: A map file has a header and a body. The header of map file the -contains one mandatory keyword and five optional keywords. The +contains one mandatory keyword and four optional keywords. The mandatory keyword is 'equivalences': .. parsed-literal:: N *equivalences* = # of atoms N in the reaction molecule templates -The optional keywords are 'edgeIDs', 'deleteIDs', 'customIDs' and +The optional keywords are 'edgeIDs', 'deleteIDs', 'chiralIDs' and 'constraints': .. parsed-literal:: @@ -286,10 +285,9 @@ The optional keywords are 'edgeIDs', 'deleteIDs', 'customIDs' and N *edgeIDs* = # of edge atoms N in the pre-reacted molecule template N *deleteIDs* = # of atoms N that are specified for deletion N *chiralIDs* = # of specified chiral centers N - N *customIDs* = # of atoms N that are specified for a custom update N *constraints* = # of specified reaction constraints N -The body of the map file contains two mandatory sections and five +The body of the map file contains two mandatory sections and four optional sections. The first mandatory section begins with the keyword 'BondingIDs' and lists the atom IDs of the bonding atom pair in the pre-reacted molecule template. The second mandatory section begins @@ -303,16 +301,11 @@ molecule template. The second optional section begins with the keyword 'DeleteIDs' and lists the atom IDs of pre-reaction template atoms to delete. The third optional section begins with the keyword 'ChiralIDs' lists the atom IDs of chiral atoms whose handedness should be -enforced. The fourth optional section begins with the keyword 'Custom -Edges' and allows for forcing the update of a specific atom's atomic -charge. The first column is the ID of an atom near the edge of the -pre-reacted molecule template, and the value of the second column is -either 'none' or 'charges.' Further details are provided in the -discussion of the 'update_edges' keyword. The fifth optional section -begins with the keyword 'Constraints' and lists additional criteria -that must be satisfied in order for the reaction to occur. Currently, -there are five types of constraints available, as discussed below: -'distance', 'angle', 'dihedral', 'arrhenius', and 'rmsd'. +enforced. The fourth optional section begins with the keyword +'Constraints' and lists additional criteria that must be satisfied in +order for the reaction to occur. Currently, there are five types of +constraints available, as discussed below: 'distance', 'angle', +'dihedral', 'arrhenius', and 'rmsd'. A sample map file is given below: @@ -488,17 +481,12 @@ individually tuned for each fix reaction step. Note that in some situations, decreasing rather than increasing this parameter will result in an increase in stability. -The *update_edges* keyword can increase the number of atoms whose -atomic charges are updated, when the pre-reaction template contains -edge atoms. When the value is set to 'charges,' all atoms' atomic -charges are updated to those specified by the post-reaction template, -including atoms near the edge of reaction templates. When the value is -set to 'custom,' an additional section must be included in the map -file that specifies whether or not to update charges, on a per-atom -basis. The format of this section is detailed above. Listing a -pre-reaction atom ID with a value of 'charges' will force the update -of the atom's charge, even if it is near a template edge. Atoms not -near a template edge are unaffected by this setting. +The *custom_charges* keyword can be used to specify which atoms' +atomic charges are updated. When the value is set to 'no,' all atomic +charges are updated to those specified by the post-reaction template +(default). Otherwise, the value should be the name of a molecule +fragment defined in the pre-reaction molecule template. In this case, +only the atomic charges of atoms in the molecule fragment are updated. A few other considerations: @@ -584,7 +572,7 @@ Default """"""" The option defaults are stabilization = no, prob = 1.0, stabilize_steps = 60, -reset_mol_ids = yes, update_edges = none +reset_mol_ids = yes, custom_charges = no ---------- diff --git a/doc/src/pg_cplusplus.rst b/doc/src/pg_cplusplus.rst index 2a7028b0f8..e51f7fc7d2 100644 --- a/doc/src/pg_cplusplus.rst +++ b/doc/src/pg_cplusplus.rst @@ -26,7 +26,6 @@ the ``delete`` operator. Here is a simple example: .. code-block:: c++ #include "lammps.h" - #include "universe.h" #include #include @@ -44,7 +43,7 @@ the ``delete`` operator. Here is a simple example: // create LAMMPS instance lmp = new LAMMPS_NS::LAMMPS(lmpargc, (char **)lmpargv, MPI_COMM_WORLD); // output numerical version string - std::cout << "LAMMPS version: " << lmp->universe->num_ver << std::endl; + std::cout << "LAMMPS version ID: " << lmp->num_ver << std::endl; // delete LAMMPS instance delete lmp; @@ -53,8 +52,8 @@ the ``delete`` operator. Here is a simple example: return 0; } -Please note that this requires to include the ``lammps.h`` header for accessing -the members of the LAMMPS class and then the ``universe.h`` header for accessing the ``num_ver`` member of the :cpp:class:`Universe` class. +This minimal example only requires to include the ``lammps.h`` header +file since it only accesses a non-pointer member of the LAMMPS class. Executing LAMMPS commands diff --git a/doc/src/pg_dev_utils.rst b/doc/src/pg_dev_utils.rst index e34f8c806e..4e005fc134 100644 --- a/doc/src/pg_dev_utils.rst +++ b/doc/src/pg_dev_utils.rst @@ -10,7 +10,7 @@ strings into specific types of numbers with checking for validity. This reduces redundant implementations and encourages consistent behavior. I/O with status check -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ These are wrappers around the corresponding C library calls like ``fgets()`` or ``fread()``. They will check if there were errors @@ -26,6 +26,8 @@ indicating the name of the problematic file, if possible. .. doxygenfunction:: sfread :project: progguide +---------- + String to number conversions with validity check ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,8 +44,9 @@ 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()`` and avoids a "hanging" calculation when run in parallel. -Please also see :cpp:func:`is_integer` and :cpp:func:`is_double` for -testing strings for compliance without conversion. +Please also see :cpp:func:`is_integer() ` +and :cpp:func:`is_double() ` for testing +strings for compliance without conversion. ---------- @@ -169,6 +172,27 @@ Customized standard functions --------------------------- +Communication buffer coding with *ubuf* +========================================= + +LAMMPS uses communication buffers where it collects data from various +class instances and then exchanges the data with neighboring sub-domains. +For simplicity those buffers are defined as ``double`` buffers and +used for doubles and integer numbers. This presents a unique problem +when 64-bit integers are used. While the storage needed for a ``double`` +is also 64-bit, it cannot be used by a simple assignment. To get around +that limitation, LAMMPS uses the :cpp:union:`ubuf ` +union. It is used in the various "pack" and "unpack" functions in the +LAMMPS classes to store and retrieve integers that may be 64-bit from +the communication buffers. + +--------------------------- + +.. doxygenunion:: LAMMPS_NS::ubuf + :project: progguide + +--------------------------- + Tokenizer classes ================= @@ -281,6 +305,8 @@ This code example should produce the following output: :project: progguide :members: what +---------- + File reader classes ==================== @@ -333,6 +359,8 @@ convert numbers, so that LAMMPS will be aborted. A file that would be parsed by the reader code fragment looks like this: +.. parsed-literal:: + # DATE: 2015-02-19 UNITS: metal CONTRIBUTOR: Ray Shan CITATION: Streitz and Mintmire, Phys Rev B, 50, 11996-12003 (1994) # # X (eV) J (eV) gamma (1/\AA) zeta (1/\AA) Z (e) @@ -351,7 +379,6 @@ A file that would be parsed by the reader code fragment looks like this: :project: progguide :members: - ---------- Memory pool classes @@ -415,3 +442,43 @@ its size is registered later with :cpp:func:`vgot() .. doxygenclass:: LAMMPS_NS::MyPoolChunk :project: progguide :members: + +---------- + +Eigensolver functions +===================== + +The ``MathEigen`` sub-namespace of the ``LAMMPS_NS`` namespace contains +functions and classes for eigensolvers. Currently only the +:cpp:func:`jacobi3 function ` is used in various +places in LAMMPS. That function is built on top of a group of more +generic eigensolvers that are maintained in the ``math_eigen_impl.h`` +header file. This header contains the implementation of three template +classes: + +#. "Jacobi" calculates all of the eigenvalues and eigenvectors + of a dense, symmetric, real matrix. + +#. The "PEigenDense" class only calculates the principal eigenvalue + (ie. the largest or smallest eigenvalue), and its corresponding + eigenvector. However it is much more efficient than "Jacobi" when + applied to large matrices (larger than 13x13). PEigenDense also can + understand complex-valued Hermitian matrices. + +#. The "LambdaLanczos" class is a generalization of "PEigenDense" which can be + applied to arbitrary sparse matrices. + +The "math_eigen_impl.h" code is an amalgamation of `jacobi_pd +`_ by Andrew Jewett at Scripps +Research (under CC0-1.0 license) and `Lambda Lanczos +`_ by Yuya Kurebayashi at +Tohoku University (under MIT license) + +---------- + +.. doxygenfunction:: MathEigen::jacobi3(double const *const *mat, double *eval, double **evec) + :project: progguide + +.. doxygenfunction:: MathEigen::jacobi3(double const mat[3][3], double *eval, double evec[3][3]) + :project: progguide + diff --git a/doc/src/pg_lammps.rst b/doc/src/pg_lammps.rst index efa282e33a..dd6798d9a1 100644 --- a/doc/src/pg_lammps.rst +++ b/doc/src/pg_lammps.rst @@ -14,9 +14,20 @@ C-library interface, or the :py:class:`lammps.lammps` class constructor of the Python module, or the :f:func:`lammps` constructor of the Fortran module. +In order to avoid clashes of function names, all of the core code in +LAMMPS is placed into the ``LAMMPS_NS`` namespace. Functions or variables +outside of that namespace must be "static", i.e. visible only to the +scope of the file/object they are defined in. Code in packages or the +libraries in the ``lib`` folder may not adhere to this as some of them +are adapted from legacy code or consist of external libraries with their +own requirements and policies. + -------------------- .. doxygenclass:: LAMMPS_NS::LAMMPS :project: progguide :members: +.. doxygenclass:: LAMMPS_NS::Pointers + :project: progguide + diff --git a/doc/src/pg_lib_objects.rst b/doc/src/pg_lib_objects.rst index 5da858db0c..301511b848 100644 --- a/doc/src/pg_lib_objects.rst +++ b/doc/src/pg_lib_objects.rst @@ -26,6 +26,8 @@ computes, fixes, or variables in LAMMPS. ----------------------- +.. doxygenenum:: _LMP_DATATYPE_CONST + .. doxygenenum:: _LMP_STYLE_CONST .. doxygenenum:: _LMP_TYPE_CONST diff --git a/doc/src/pg_lib_properties.rst b/doc/src/pg_lib_properties.rst index 256ed1cf82..bf36dcb8b1 100644 --- a/doc/src/pg_lib_properties.rst +++ b/doc/src/pg_lib_properties.rst @@ -84,11 +84,22 @@ event as atoms are migrating between sub-domains. ----------------------- +.. doxygenfunction:: lammps_extract_global_datatype + :project: progguide + +----------------------- + .. doxygenfunction:: lammps_extract_global :project: progguide ----------------------- +.. doxygenfunction:: lammps_extract_atom_datatype + :project: progguide + + +----------------------- + .. doxygenfunction:: lammps_extract_atom :project: progguide diff --git a/doc/src/pg_python.rst b/doc/src/pg_python.rst index 80e83d4638..37cfb2c6db 100644 --- a/doc/src/pg_python.rst +++ b/doc/src/pg_python.rst @@ -28,16 +28,58 @@ There are multiple Python interface classes in the :py:mod:`lammps` module: ---------- +Setting up a Python virtual environment +*************************************** + +LAMMPS and its Python module can be installed together into a Python virtual +environment. This lets you isolate your customized Python environment from +your user or system installation. The following is a minimal working example: + +.. code-block:: bash + + # create and change into build directory + mkdir build + cd build + + # create virtual environment + virtualenv myenv + + # Add venv lib folder to LD_LIBRARY_PATH when activating it + echo 'export LD_LIBRARY_PATH=$VIRTUAL_ENV/lib:$LD_LIBRARY_PATH' >> myenv/bin/activate + + # Add LAMMPS_POTENTIALS path when activating venv + echo 'export LAMMPS_POTENTIALS=$VIRTUAL_ENV/share/lammps/potentials' >> myenv/bin/activate + + # activate environment + source myenv/bin/activate + + # configure LAMMPS compilation + # compiles as shared library with PYTHON package and C++ exceptions + # and installs into myvenv + (myenv)$ cmake -C ../cmake/presets/minimal.cmake \ + -D BUILD_SHARED_LIBS=on \ + -D PKG_PYTHON=on \ + -D LAMMPS_EXCEPTIONS=on \ + -D CMAKE_INSTALL_PREFIX=$VIRTUAL_ENV \ + ../cmake + + # compile LAMMPS + (myenv)$ cmake --build . --parallel + + # install LAMMPS into myvenv + (myenv)$ cmake --install . + Creating or deleting a LAMMPS object ************************************ With the Python interface the creation of a :cpp:class:`LAMMPS -` instance is included in the constructor for the -:py:func:`lammps ` class. Internally it will call either -:cpp:func:`lammps_open` or :cpp:func:`lammps_open_no_mpi` from the C +` instance is included in the constructors for the +:py:meth:`lammps `, :py:meth:`PyLammps `, +and :py:meth:`PyLammps ` classes. +Internally it will call either :cpp:func:`lammps_open` or :cpp:func:`lammps_open_no_mpi` from the C library API to create the class instance. -All arguments are optional. The *name* argument is to allow loading a +All arguments are optional. The *name* argument allows loading a LAMMPS shared library that is named ``liblammps_machine.so`` instead of the default name of ``liblammps.so``. In most cases the latter will be installed or used. The *ptr* argument is for use of the @@ -48,22 +90,99 @@ to the Python class and used instead of creating a new instance. The *comm* argument may be used in combination with the `mpi4py `_ module to pass an MPI communicator to LAMMPS and thus it is possible to run the Python module like the library interface on a subset of the -MPI ranks after splitting the communicator. Here is a simple example: +MPI ranks after splitting the communicator. -.. code-block:: python - from lammps import lammps +Here are simple examples using all three Python interfaces: - # NOTE: argv[0] is set by the Python module - args = ["-log", "none"] - # create LAMMPS instance - lmp = lammps(cmdargs=args) - # get and print numerical version code - print("LAMMPS Version: ", lmp.version()) - # explicitly close and delete LAMMPS instance (optional) - lmp.close() +.. tabs:: -Same as with the :ref:`C library API ` this will use the + .. tab:: lammps API + + .. code-block:: python + + from lammps import lammps + + # NOTE: argv[0] is set by the lammps class constructor + args = ["-log", "none"] + # create LAMMPS instance + lmp = lammps(cmdargs=args) + # get and print numerical version code + print("LAMMPS Version: ", lmp.version()) + # explicitly close and delete LAMMPS instance (optional) + lmp.close() + + .. tab:: PyLammps API + + The :py:class:`PyLammps` class is a wrapper around the + :py:class:`lammps` class and all of its lower level functions. + By default, it will create a new instance of :py:class:`lammps` passing + along all arguments to the constructor of :py:class:`lammps`. + + .. code-block:: python + + from lammps import PyLammps + + # NOTE: argv[0] is set by the lammps class constructor + args = ["-log", "none"] + # create LAMMPS instance + L = PyLammps(cmdargs=args) + # get and print numerical version code + print("LAMMPS Version: ", L.version()) + # explicitly close and delete LAMMPS instance (optional) + L.close() + + :py:class:`PyLammps` objects can also be created on top of an existing :py:class:`lammps` object: + + .. code-block:: Python + + from lammps import lammps, PyLammps + ... + # create LAMMPS instance + lmp = lammps(cmdargs=args) + # create PyLammps instance using previously created LAMMPS instance + L = PyLammps(ptr=lmp) + + This is useful if you have to create the :py:class:`lammps ` + instance is a specific way, but want to take advantage of the + :py:class:`PyLammps ` interface. + + .. tab:: IPyLammps API + + The :py:class:`IPyLammps` class is an extension of the + :py:class:`PyLammps` class. It has the same construction behavior. By + default, it will create a new instance of :py:class:`lammps` passing + along all arguments to the constructor of :py:class:`lammps`. + + .. code-block:: python + + from lammps import IPyLammps + + # NOTE: argv[0] is set by the lammps class constructor + args = ["-log", "none"] + # create LAMMPS instance + L = IPyLammps(cmdargs=args) + # get and print numerical version code + print("LAMMPS Version: ", L.version()) + # explicitly close and delete LAMMPS instance (optional) + L.close() + + You can also initialize IPyLammps on top of an existing :py:class:`lammps` or :py:class:`PyLammps` object: + + .. code-block:: Python + + from lammps import lammps, IPyLammps + ... + # create LAMMPS instance + lmp = lammps(cmdargs=args) + # create PyLammps instance using previously created LAMMPS instance + L = PyLammps(ptr=lmp) + + This is useful if you have to create the :py:class:`lammps ` + instance is a specific way, but want to take advantage of the + :py:class:`IPyLammps ` interface. + +In all of the above cases, same as with the :ref:`C library API `, this will use the ``MPI_COMM_WORLD`` communicator for the MPI library that LAMMPS was compiled with. The :py:func:`lmp.close() ` call is optional since the LAMMPS class instance will also be deleted @@ -73,39 +192,109 @@ destructor. Executing LAMMPS commands ************************* -Once an instance of the :py:class:`lammps ` class is -created, there are multiple ways to "feed" it commands. In a way that is -not very different from running a LAMMPS input script, except that -Python has many more facilities for structured programming than the -LAMMPS input script syntax. Furthermore it is possible to "compute" -what the next LAMMPS command should be. Same as in the equivalent `C -library functions `, commands can be read from a file, a -single string, a list of strings and a block of commands in a single -multi-line string. They are processed under the same boundary conditions -as the C library counterparts. The example below demonstrates the use -of :py:func:`lammps.file`, :py:func:`lammps.command`, -:py:func:`lammps.commands_list`, and :py:func:`lammps.commands_string`: +Once an instance of the :py:class:`lammps`, :py:class:`PyLammps`, or +:py:class:`IPyLammps` class is created, there are multiple ways to "feed" it +commands. In a way that is not very different from running a LAMMPS input +script, except that Python has many more facilities for structured +programming than the LAMMPS input script syntax. Furthermore it is possible +to "compute" what the next LAMMPS command should be. -.. code-block:: python +.. tabs:: - from lammps import lammps + .. tab:: lammps API - lmp = lammps() - # read commands from file 'in.melt' - lmp.file('in.melt') - # issue a single command - lmp.command('variable zpos index 1.0') - # create 10 groups with 10 atoms each - cmds = ["group g{} id {}:{}".format(i,10*i+1,10*(i+1)) for i in range(10)] - lmp.commands_list(cmds) - # run commands from a multi-line string - block = """ - clear - region box block 0 2 0 2 0 2 - create_box 1 box - create_atoms 1 single 1.0 1.0 ${zpos} - """ - lmp.commands_string(block) + Same as in the equivalent + :doc:`C library functions `, commands can be read from a file, a + single string, a list of strings and a block of commands in a single + multi-line string. They are processed under the same boundary conditions + as the C library counterparts. The example below demonstrates the use + of :py:func:`lammps.file`, :py:func:`lammps.command`, + :py:func:`lammps.commands_list`, and :py:func:`lammps.commands_string`: + + .. code-block:: python + + from lammps import lammps + lmp = lammps() + # read commands from file 'in.melt' + lmp.file('in.melt') + # issue a single command + lmp.command('variable zpos index 1.0') + # create 10 groups with 10 atoms each + cmds = ["group g{} id {}:{}".format(i,10*i+1,10*(i+1)) for i in range(10)] + lmp.commands_list(cmds) + # run commands from a multi-line string + block = """ + clear + region box block 0 2 0 2 0 2 + create_box 1 box + create_atoms 1 single 1.0 1.0 ${zpos} + """ + lmp.commands_string(block) + + .. tab:: PyLammps/IPyLammps API + + Unlike the lammps API, the PyLammps/IPyLammps APIs allow running LAMMPS + commands by calling equivalent member functions. + + For instance, the following LAMMPS command + + .. code-block:: LAMMPS + + region box block 0 10 0 5 -0.5 0.5 + + can be executed using the following Python code if *L* is a :py:class:`lammps` instance: + + .. code-block:: Python + + L.command("region box block 0 10 0 5 -0.5 0.5") + + With the PyLammps interface, any LAMMPS command can be split up into arbitrary parts. + These parts are then passed to a member function with the name of the command. + For the ``region`` command that means the :code:`region` method can be called. + The arguments of the command can be passed as one string, or + individually. + + .. code-block:: Python + + L.region("box block", 0, 10, 0, 5, -0.5, 0.5) + + In this example all parameters except the first are Python floating-point literals. The + PyLammps interface takes the entire parameter list and transparently + merges it to a single command string. + + The benefit of this approach is avoiding redundant command calls and easier + parameterization. In the original interface parameterization this needed to be done + manually by creating formatted strings. + + .. code-block:: Python + + L.command("region box block %f %f %f %f %f %f" % (xlo, xhi, ylo, yhi, zlo, zhi)) + + In contrast, methods of PyLammps accept parameters directly and will convert + them automatically to a final command string. + + .. code-block:: Python + + L.region("box block", xlo, xhi, ylo, yhi, zlo, zhi) + + Using these facilities, the example shown for the lammps API can be rewritten as follows: + + .. code-block:: python + + from lammps import PyLammps + L = PyLammps() + # read commands from file 'in.melt' + L.file('in.melt') + # issue a single command + L.variable('zpos', 'index', 1.0) + # create 10 groups with 10 atoms each + for i in range(10): + L.group(f"g{i}", "id", f"{10*i+1}:{10*(i+1)}") + + L.clear() + L.region("box block", 0, 2, 0, 2, 0, 2) + L.create_box(1, "box") + L.create_atoms(1, "single", 1.0, 1.0, "${zpos}") ---------- @@ -130,14 +319,34 @@ functions. Below is a detailed documentation of the API. The ``PyLammps`` class API ************************** +The :py:class:`PyLammps ` class is a wrapper that creates a +simpler, more "Pythonic" interface to common LAMMPS functionality. LAMMPS +data structures are exposed through objects and properties. This makes Python +scripts shorter and more concise. See the :doc:`PyLammps Tutorial +` for an introduction on how to use this interface. + .. autoclass:: lammps.PyLammps :members: +.. autoclass:: lammps.AtomList + :members: + +.. autoclass:: lammps.Atom + :members: + +.. autoclass:: lammps.Atom2D + :members: + ---------- The ``IPyLammps`` class API *************************** +The :py:class:`IPyLammps ` class is an extension of +:py:class:`PyLammps `, adding additional functions to +quickly display visualizations such as images and videos inside of IPython. +See the :doc:`PyLammps Tutorial ` for examples. + .. autoclass:: lammps.IPyLammps :members: @@ -150,14 +359,24 @@ The :py:mod:`lammps` module additionally contains several constants and the :py:class:`NeighList ` class: .. _py_data_constants: -.. py:data:: LAMMPS_INT, LAMMPS_DOUBLE, LAMMPS_BIGINT, LAMMPS_TAGINT, LAMMPS_STRING + +Data Types +---------- + +.. py:data:: LAMMPS_INT, LAMMPS_INT_2D, LAMMPS_DOUBLE, LAMMPS_DOUBLE_2D, LAMMPS_INT64, LAMMPS_INT64_2D, LAMMPS_STRING :type: int Constants in the :py:mod:`lammps` module to indicate how to cast data when the C library function returns a void pointer. - Used in :py:func:`lammps.extract_global`. + Used in :py:func:`lammps.extract_global` and :py:func:`lammps.extract_atom`. + See :cpp:enum:`_LMP_DATATYPE_CONST` for the equivalent constants in the + C library interface. .. _py_style_constants: + +Style Constants +--------------- + .. py:data:: LMP_STYLE_GLOBAL, LMP_STYLE_ATOM, LMP_STYLE_LOCAL :type: int @@ -167,6 +386,10 @@ and the :py:class:`NeighList ` class: :py:func:`lammps.extract_compute` and :py:func:`lammps.extract_fix`. .. _py_type_constants: + +Type Constants +-------------- + .. py:data:: LMP_TYPE_SCALAR, LMP_TYLE_VECTOR, LMP_TYPE_ARRAY, LMP_SIZE_VECTOR, LMP_SIZE_ROWS, LMP_SIZE_COLS :type: int @@ -176,13 +399,36 @@ and the :py:class:`NeighList ` class: :py:func:`lammps.extract_compute` and :py:func:`lammps.extract_fix`. .. _py_var_constants: + +Variable Style Constants +------------------------ + .. py:data:: LMP_VAR_EQUAL, LMP_VAR_ATOM :type: int Constants in the :py:mod:`lammps` module to select what style of variable to query when calling :py:func:`lammps.extract_variable`. +Classes representing internal objects +------------------------------------- + .. autoclass:: lammps.NeighList :members: :no-undoc-members: + +LAMMPS error handling in Python +******************************* + +Compiling the shared library with :ref:`C++ exception support ` provides a better error +handling experience. Without exceptions the LAMMPS code will terminate the +current Python process with an error message. C++ exceptions allow capturing +them on the C++ side and rethrowing them on the Python side. This way +LAMMPS errors can be handled through the Python exception handling mechanism. + +.. warning:: + + Capturing a LAMMPS exception in Python can still mean that the + current LAMMPS process is in an illegal state and must be terminated. It is + advised to save your data and terminate the Python instance as quickly as + possible. diff --git a/doc/utils/sphinx-config/_static/css/lammps.css b/doc/utils/sphinx-config/_static/css/lammps.css index 2efb1246b3..a4f7d68693 100644 --- a/doc/utils/sphinx-config/_static/css/lammps.css +++ b/doc/utils/sphinx-config/_static/css/lammps.css @@ -18,3 +18,41 @@ .versionmodified { font-weight: bold; } + +hr { + margin: 12px 0; +} + +.rst-content { + margin-bottom: 12px !important; +} + +#user-documentation.section h2 { + display: none; +} + +#programmer-documentation.section h2 { + display: none; +} + +.ui.tabular.menu .item { + padding-right: 1em; + padding-left: 1em; + padding-top: 0.1em; + padding-bottom: 0.1em; + border-radius: 6px; +} + +.btn { + padding: 4px; + font-size: 80%; + border-radius: 4px; +} + +.rst-breadcrumbs-buttons { + margin: 0; +} + +p { + margin-bottom: 12px; +} diff --git a/doc/utils/sphinx-config/_themes/lammps_theme/static/css/lammps.css b/doc/utils/sphinx-config/_themes/lammps_theme/static/css/lammps.css deleted file mode 100644 index b9816c3f8c..0000000000 --- a/doc/utils/sphinx-config/_themes/lammps_theme/static/css/lammps.css +++ /dev/null @@ -1,9 +0,0 @@ -.lammps_version { - text-align: center; - display: block; - margin-bottom: 0.809em; -} - -.versionmodified { - font-weight: bold; -} diff --git a/doc/utils/sphinx-config/_themes/lammps_theme/theme.conf b/doc/utils/sphinx-config/_themes/lammps_theme/theme.conf index 699f1bd5f3..37dc1185b7 100644 --- a/doc/utils/sphinx-config/_themes/lammps_theme/theme.conf +++ b/doc/utils/sphinx-config/_themes/lammps_theme/theme.conf @@ -13,6 +13,6 @@ includehidden = True titles_only = logo_only = display_version = True -prev_next_buttons_location = bottom -style_external_links = False +prev_next_buttons_location = both +style_external_links = True style_nav_header_background = diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 1eec67ebf9..669bb8fd64 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -110,7 +110,9 @@ api Apoorva Appl Apu +arallel arccos +arge Archlinux arcsin arg @@ -128,6 +130,7 @@ aspherical asphericity Asq assignee +assively Asta Astart Astop @@ -325,6 +328,7 @@ Buyl Bybee bz cadetblue +calc calibre caltech Caltech @@ -397,6 +401,7 @@ ChiralIDs chiralIDs chirality Cho +ChooseOffset chris Christoph Chu @@ -469,6 +474,7 @@ config configfile configurational conformational +ConstMatrix Contrib cooperativity coord @@ -639,7 +645,10 @@ dhex dia diag diagonalization +diagonalize diagonalized +diagonalizers +diagonalizing Diallo diel differentiable @@ -778,8 +787,15 @@ Eggebrecht ehex eHEX Ei -Eigen -Eigensolve +eigen +eigensolve +eigensolver +eigensolvers +eigendecomposition +eigenvalue +eigenvalues +eigenvector +eigenvectors eij Eij Eijnden @@ -893,6 +909,11 @@ eV evalue Evanseck evdwl +evector +evec +evecs +eval +evals Everaers Evgeny evirials @@ -1069,6 +1090,7 @@ Germann Germano gerolf Gerolf +Gershgorin gettimeofday gewald Gezelter @@ -1184,6 +1206,7 @@ Henkelman Henkes henrich Henrich +Hermitian Herrmann Hertizian hertzian @@ -1257,6 +1280,7 @@ icosahedral idealgas IDR idx +ie ielement ieni ifdefs @@ -1279,8 +1303,10 @@ Imageint Imagemagick imd Impey +impl impropers Impropers +imulator includelink incompressible incrementing @@ -1348,6 +1374,8 @@ isothermal isotropically isovolume Isralewitz +iter +iters iteratively Ith Itsets @@ -1525,6 +1553,7 @@ Kub Kubo Kumagai Kumar +Kurebayashi Kuronen Kusters Kutta @@ -1535,12 +1564,14 @@ Ladd lagrangian lambdai lamda +LambdaLanczos lammps Lammps LAMMPS lammpsplot Lampis Lamoureux +Lanczos Lande Landron langevin @@ -1848,6 +1879,7 @@ Microscale midnightblue mie Mie +Mij Mikami Militzer Minary @@ -1946,6 +1978,7 @@ Muccioli mui Mukherjee Mulders +mult multi multibody Multibody @@ -1990,6 +2023,7 @@ Nakano nall namespace namespaces +namedtuple nan NaN Nandor @@ -2226,6 +2260,7 @@ Okamoto O'Keefe OKeefe oldlace +olecular Oleinik Olfason olivedrab @@ -2332,6 +2367,7 @@ peachpuff Pearlman Pedersen peID +PEigenDense Peng peptide peratom @@ -2560,6 +2596,8 @@ rdf RDideal rdx reacter +realTypeMap +real_t README realtime reamin @@ -2744,6 +2782,7 @@ Schuring Schwen screenshot screenshots +Scripps Scripta sdk sdpd @@ -3072,10 +3111,12 @@ Tmin tmp tN Tobias +Tohoku tokenizer tokyo tol Toennies +tomic toolchain topologies Toporov @@ -3136,6 +3177,8 @@ tu Tuckerman tue tunable +tuple +tuples Turkand Tutein tweakable @@ -3430,6 +3473,7 @@ Yuh yukawa Yukawa Yusof +Yuya yx yy yz diff --git a/examples/COUPLE/.gitignore b/examples/COUPLE/.gitignore index 6ffb58df7d..a3927e0c93 100644 --- a/examples/COUPLE/.gitignore +++ b/examples/COUPLE/.gitignore @@ -2,3 +2,7 @@ *.d *.a *~ +liblammps.mod +simpleC +simpleCC +simpleF diff --git a/examples/COUPLE/simple/README b/examples/COUPLE/simple/README index 8a97137bf7..bcd0d635b8 100644 --- a/examples/COUPLE/simple/README +++ b/examples/COUPLE/simple/README @@ -8,16 +8,14 @@ code to perform a coupled calculation. simple.cpp is the C++ driver simple.c is the C driver simple.f90 is the Fortran driver -libfwrapper.c is the Fortran-to-C wrapper The 3 codes do the same thing, so you can compare them to see how to -drive LAMMPS from each language. See lammps/python/example/simple.py -to do something similar from Python. The Fortran driver requires an -additional wrapper library that interfaces the C interface of the -LAMMPS library to Fortran and also translates the MPI communicator -from Fortran to C. +drive LAMMPS from each language. See python/example/simple.py +to do something similar from Python. The Fortran driver requires a +Fortran module that uses the Fortran 03 ISO_C_BINDING module to +interface the LAMMPS C library functions to Fortran. -First build LAMMPS as a library (see examples/COUPLE/README), e.g. +First build LAMMPS as a library (see examples/COUPLE/README), e.g. make mode=shlib mpi @@ -26,27 +24,23 @@ these, which include paths to the LAMMPS library interface, and linking with FFTW (only needed if you built LAMMPS as a library with its PPPM solver). -This builds the C++ driver with the LAMMPS library using the mpiCC +This builds the C++ driver with the LAMMPS library using the mpicxx (C++) compiler: -mpiCC -I/home/sjplimp/lammps/src -c simple.cpp -mpiCC -L/home/sjplimp/lammps/src simple.o -llammps -lfftw -o simpleCC +mpicxx -I/home/sjplimp/lammps/src -c simple.cpp +mpicxx -L/home/sjplimp/lammps/src simple.o -llammps -o simpleCC This builds the C driver with the LAMMPS library using the mpicc (C) compiler: mpicc -I/home/sjplimp/lammps/src -c simple.c -mpicc -L/home/sjplimp/lammps/src simple.o -llammps -lfftw -o simpleC +mpicc -L/home/sjplimp/lammps/src simple.o -llammps -o simpleC -This builds the Fortran wrapper and driver with the LAMMPS library -using the mpicc (C) and mpifort (Fortran) compilers, using the wrapper -in the fortran directory: +This builds the Fortran module and driver with the LAMMPS library +using the mpifort (Fortran) compilers, using the Fortran module from +the fortran directory: -cp ../fortran/libfwrapper.c . -mpicc -I/home/sjplimp/lammps/src -c libfwrapper.c -mpifort -c simple.f90 -mpifort -L/home/sjplimp/lammps/src simple.o libfwrapper.o \ - -llammps -lfftw -o simpleF +mpifort -L/home/sjplimp/lammps/src ../../../fortran/lammps.f90 simple.f90 -llammps -o simpleF You then run simpleCC, simpleC, or simpleF on a parallel machine on some number of processors Q with 2 arguments: @@ -69,10 +63,9 @@ The C driver is calling C-style routines in the src/library.cpp file of LAMMPS. You could add any functions you wish to this file to manipulate LAMMPS data however you wish. -The Fortran driver is using the same C-style routines, but requires an -additional wrapper to make them Fortran callable. Only a subset of the -library functions are currently wrapped, but it should be clear how to -extend the wrapper if desired. +The Fortran driver is using the Fortran 03 module which uses a derived +type with type bound subroutines. Only a small subset of the C library +functions are currently accessible through the Fortran module. The C++ driver does the same thing, except that it instantiates LAMMPS as an object first. Some of the functions in src/library.cpp can be diff --git a/examples/COUPLE/simple/simple.c b/examples/COUPLE/simple/simple.c index f4623470b7..a5ce281b1d 100644 --- a/examples/COUPLE/simple/simple.c +++ b/examples/COUPLE/simple/simple.c @@ -19,11 +19,11 @@ in.lammps = LAMMPS input script See README for compilation instructions */ -#include "stdio.h" -#include "stdlib.h" -#include "string.h" -#include "mpi.h" -#include "lammps/library.h" /* this is a LAMMPS include file */ +#include +#include +#include +#include +#include "library.h" /* this is a LAMMPS include file */ int main(int narg, char **arg) { @@ -72,7 +72,7 @@ int main(int narg, char **arg) all LAMMPS procs call lammps_command() on the line */ void *lmp = NULL; - if (lammps == 1) lammps_open(0,NULL,comm_lammps,&lmp); + if (lammps == 1) lmp = lammps_open(0,NULL,comm_lammps,NULL); int n; char line[1024]; @@ -124,10 +124,10 @@ int main(int narg, char **arg) /* use commands_string() and commands_list() to invoke more commands */ - char *strtwo = "run 10\nrun 20"; + const char *strtwo = "run 10\nrun 20"; if (lammps == 1) lammps_commands_string(lmp,strtwo); - char *cmds[2]; + const char *cmds[2]; cmds[0] = "run 10"; cmds[1] = "run 20"; if (lammps == 1) lammps_commands_list(lmp,2,cmds); diff --git a/examples/COUPLE/simple/simple.cpp b/examples/COUPLE/simple/simple.cpp index a76ed8a6e9..8660dfa656 100644 --- a/examples/COUPLE/simple/simple.cpp +++ b/examples/COUPLE/simple/simple.cpp @@ -25,10 +25,10 @@ #include // these are LAMMPS include files -#include -#include -#include -#include +#include "lammps.h" +#include "input.h" +#include "atom.h" +#include "library.h" using namespace LAMMPS_NS; @@ -135,10 +135,10 @@ int main(int narg, char **arg) // use commands_string() and commands_list() to invoke more commands - char *strtwo = (char *) "run 10\nrun 20"; + const char *strtwo = (char *) "run 10\nrun 20"; if (lammps == 1) lammps_commands_string(lmp,strtwo); - char *cmds[2]; + const char *cmds[2]; cmds[0] = (char *) "run 10"; cmds[1] = (char *) "run 20"; if (lammps == 1) lammps_commands_list(lmp,2,cmds); diff --git a/examples/COUPLE/simple/simple.f90 b/examples/COUPLE/simple/simple.f90 index 0ac3e4fd5c..aacbbfcb79 100644 --- a/examples/COUPLE/simple/simple.f90 +++ b/examples/COUPLE/simple/simple.f90 @@ -18,13 +18,14 @@ ! See README for compilation instructions PROGRAM f_driver + USE mpi + USE liblammps IMPLICIT NONE - INCLUDE 'mpif.h' INTEGER, PARAMETER :: fp=20 INTEGER :: n, narg, ierr, me, nprocs, natoms - INTEGER :: lammps, nprocs_lammps, comm_lammps - INTEGER (kind=8) :: ptr + INTEGER :: color, nprocs_lammps, comm_lammps + TYPE(LAMMPS) :: lmp REAL (kind=8), ALLOCATABLE :: x(:) REAL (kind=8), PARAMETER :: epsilon=0.1 @@ -58,14 +59,14 @@ PROGRAM f_driver END IF END IF - lammps = 0 + color = 0 IF (me < nprocs_lammps) THEN - lammps = 1 + color = 1 ELSE - lammps = MPI_UNDEFINED + color = MPI_UNDEFINED END IF - CALL mpi_comm_split(MPI_COMM_WORLD,lammps,0,comm_lammps,ierr) + CALL mpi_comm_split(MPI_COMM_WORLD,color,0,comm_lammps,ierr) ! open LAMMPS input script on rank zero @@ -81,7 +82,7 @@ PROGRAM f_driver ! (could just send it to proc 0 of comm_lammps and let it Bcast) ! all LAMMPS procs call lammps_command() on the line */ - IF (lammps == 1) CALL lammps_open(comm_lammps,ptr) + IF (color == 1) lmp=lammps(comm=comm_lammps) n = 0 DO @@ -99,7 +100,7 @@ PROGRAM f_driver CALL mpi_bcast(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr) IF (n == 0) EXIT CALL mpi_bcast(line,n,MPI_CHARACTER,0,MPI_COMM_WORLD,ierr) - IF (lammps == 1) CALL lammps_command(ptr,line,n) + IF (color == 1) CALL lmp%command(line(1:n)) END DO CLOSE(UNIT=fp) @@ -109,27 +110,27 @@ PROGRAM f_driver ! put coords back into LAMMPS ! run a single step with changed coords */ - IF (lammps == 1) THEN - CALL lammps_command(ptr,'run 10',6) + IF (color == 1) THEN + CALL lmp%command('run 10') - CALL lammps_get_natoms(ptr,natoms) + natoms = NINT(lmp%get_natoms()) ALLOCATE(x(3*natoms)) ! these calls are commented out, b/c libfwrapper.c ! needs to be updated to use gather_atoms and scatter_atoms - !CALL lammps_gather_atoms(ptr,'x',1,3,x); + !CALL lammps_gather_atoms(ptr,'x',1,3,x) !x(1) = x(1) + epsilon - !CALL lammps_scatter_atoms(ptr,'x',1,3,x); + !CALL lammps_scatter_atoms(ptr,'x',1,3,x) DEALLOCATE(x) - CALL lammps_command(ptr,'run 1',5); + CALL lmp%command('run 1') END IF ! free LAMMPS object - IF (lammps == 1) CALL lammps_close(ptr); + IF (color == 1) CALL lmp%close() ! close down MPI diff --git a/examples/USER/colvars/out.colvars.state b/examples/USER/colvars/out.colvars.state index e5c6e98ef5..e1c98c5096 100644 --- a/examples/USER/colvars/out.colvars.state +++ b/examples/USER/colvars/out.colvars.state @@ -1,7 +1,7 @@ configuration { step 200 dt 2.000000e+00 - version 2018-11-16 + version 2020-07-07 } colvar { diff --git a/examples/USER/colvars/out.colvars.state.old b/examples/USER/colvars/out.colvars.state.old index ea33a8b1b1..458485ca83 100644 --- a/examples/USER/colvars/out.colvars.state.old +++ b/examples/USER/colvars/out.colvars.state.old @@ -1,7 +1,7 @@ configuration { step 100 dt 2.000000e+00 - version 2018-11-16 + version 2020-07-07 } colvar { diff --git a/examples/USER/colvars/out2.colvars.state b/examples/USER/colvars/out2.colvars.state index e923862831..95bb3dafbb 100644 --- a/examples/USER/colvars/out2.colvars.state +++ b/examples/USER/colvars/out2.colvars.state @@ -1,7 +1,7 @@ configuration { step 300 dt 2.000000e+00 - version 2018-11-16 + version 2020-07-07 } colvar { diff --git a/examples/USER/colvars/peptide2.colvars.state b/examples/USER/colvars/peptide2.colvars.state index 5272bb7c4a..6e23e3a6c5 100644 --- a/examples/USER/colvars/peptide2.colvars.state +++ b/examples/USER/colvars/peptide2.colvars.state @@ -1,7 +1,7 @@ configuration { step 100 dt 2.000000e+00 - version 2018-11-16 + version 2020-07-07 } colvar { diff --git a/examples/python/in.fix_python_invoke b/examples/python/in.fix_python_invoke index f77cc15c90..ac435762c5 100644 --- a/examples/python/in.fix_python_invoke +++ b/examples/python/in.fix_python_invoke @@ -23,12 +23,12 @@ from lammps import lammps def end_of_step_callback(lmp): L = lammps(ptr=lmp) - t = L.extract_global("ntimestep", 0) + t = L.extract_global("ntimestep") print("### END OF STEP ###", t) def post_force_callback(lmp, v): L = lammps(ptr=lmp) - t = L.extract_global("ntimestep", 0) + t = L.extract_global("ntimestep") print("### POST_FORCE ###", t) """ diff --git a/examples/python/in.fix_python_invoke_neighlist b/examples/python/in.fix_python_invoke_neighlist index 50f1d52c33..e5445227b1 100644 --- a/examples/python/in.fix_python_invoke_neighlist +++ b/examples/python/in.fix_python_invoke_neighlist @@ -35,14 +35,13 @@ def post_force_callback(lmp, v): #mylist = L.get_neighlist(0) mylist = L.find_pair_neighlist("lj/cut", request=0) print(pid_prefix, mylist) - nlocal = L.extract_global("nlocal", 0) - nghost = L.extract_global("nghost", 0) - ntypes = L.extract_global("ntypes", 0) - mass = L.numpy.extract_atom_darray("mass", ntypes+1) - atype = L.numpy.extract_atom_iarray("type", nlocal+nghost) - x = L.numpy.extract_atom_darray("x", nlocal+nghost, dim=3) - v = L.numpy.extract_atom_darray("v", nlocal+nghost, dim=3) - f = L.numpy.extract_atom_darray("f", nlocal+nghost, dim=3) + nlocal = L.extract_global("nlocal") + nghost = L.extract_global("nghost") + mass = L.numpy.extract_atom("mass") + atype = L.numpy.extract_atom("type", nelem=nlocal+nghost) + x = L.numpy.extract_atom("x", nelem=nlocal+nghost, dim=3) + v = L.numpy.extract_atom("v", nelem=nlocal+nghost, dim=3) + f = L.numpy.extract_atom("f", nelem=nlocal+nghost, dim=3) for iatom, numneigh, neighs in mylist: print(pid_prefix, "- {}".format(iatom), x[iatom], v[iatom], f[iatom], " : ", numneigh, "Neighbors") diff --git a/examples/python/py_nve.py b/examples/python/py_nve.py index 79331528b1..9ff7c0978b 100644 --- a/examples/python/py_nve.py +++ b/examples/python/py_nve.py @@ -1,12 +1,12 @@ from __future__ import print_function -import lammps +from lammps import lammps, LAMMPS_INT, LAMMPS_DOUBLE import ctypes import traceback import numpy as np class LAMMPSFix(object): def __init__(self, ptr, group_name="all"): - self.lmp = lammps.lammps(ptr=ptr) + self.lmp = lammps(ptr=ptr) self.group_name = group_name class LAMMPSFixMove(LAMMPSFix): @@ -39,19 +39,18 @@ class NVE(LAMMPSFixMove): assert(self.group_name == "all") def init(self): - dt = self.lmp.extract_global("dt", 1) - ftm2v = self.lmp.extract_global("ftm2v", 1) - self.ntypes = self.lmp.extract_global("ntypes", 0) + dt = self.lmp.extract_global("dt") + ftm2v = self.lmp.extract_global("ftm2v") + self.ntypes = self.lmp.extract_global("ntypes") self.dtv = dt self.dtf = 0.5 * dt * ftm2v def initial_integrate(self, vflag): - nlocal = self.lmp.extract_global("nlocal", 0) - mass = self.lmp.numpy.extract_atom_darray("mass", self.ntypes+1) - atype = self.lmp.numpy.extract_atom_iarray("type", nlocal) - x = self.lmp.numpy.extract_atom_darray("x", nlocal, dim=3) - v = self.lmp.numpy.extract_atom_darray("v", nlocal, dim=3) - f = self.lmp.numpy.extract_atom_darray("f", nlocal, dim=3) + mass = self.lmp.numpy.extract_atom("mass") + atype = self.lmp.numpy.extract_atom("type") + x = self.lmp.numpy.extract_atom("x") + v = self.lmp.numpy.extract_atom("v") + f = self.lmp.numpy.extract_atom("f") for i in range(x.shape[0]): dtfm = self.dtf / mass[int(atype[i])] @@ -59,11 +58,10 @@ class NVE(LAMMPSFixMove): x[i,:] += self.dtv * v[i,:] def final_integrate(self): - nlocal = self.lmp.extract_global("nlocal", 0) - mass = self.lmp.numpy.extract_atom_darray("mass", self.ntypes+1) - atype = self.lmp.numpy.extract_atom_iarray("type", nlocal) - v = self.lmp.numpy.extract_atom_darray("v", nlocal, dim=3) - f = self.lmp.numpy.extract_atom_darray("f", nlocal, dim=3) + mass = self.lmp.numpy.extract_atom("mass") + atype = self.lmp.numpy.extract_atom("type") + v = self.lmp.numpy.extract_atom("v") + f = self.lmp.numpy.extract_atom("f") for i in range(v.shape[0]): dtfm = self.dtf / mass[int(atype[i])] @@ -77,19 +75,19 @@ class NVE_Opt(LAMMPSFixMove): assert(self.group_name == "all") def init(self): - dt = self.lmp.extract_global("dt", 1) - ftm2v = self.lmp.extract_global("ftm2v", 1) - self.ntypes = self.lmp.extract_global("ntypes", 0) + dt = self.lmp.extract_global("dt") + ftm2v = self.lmp.extract_global("ftm2v") + self.ntypes = self.lmp.extract_global("ntypes") self.dtv = dt self.dtf = 0.5 * dt * ftm2v - self.mass = self.lmp.numpy.extract_atom_darray("mass", self.ntypes+1) + self.mass = self.lmp.numpy.extract_atom("mass") def initial_integrate(self, vflag): - nlocal = self.lmp.extract_global("nlocal", 0) - atype = self.lmp.numpy.extract_atom_iarray("type", nlocal) - x = self.lmp.numpy.extract_atom_darray("x", nlocal, dim=3) - v = self.lmp.numpy.extract_atom_darray("v", nlocal, dim=3) - f = self.lmp.numpy.extract_atom_darray("f", nlocal, dim=3) + nlocal = self.lmp.extract_global("nlocal") + atype = self.lmp.numpy.extract_atom("type") + x = self.lmp.numpy.extract_atom("x") + v = self.lmp.numpy.extract_atom("v") + f = self.lmp.numpy.extract_atom("f") dtf = self.dtf dtv = self.dtv mass = self.mass @@ -102,13 +100,12 @@ class NVE_Opt(LAMMPSFixMove): x[:,d] += dtv * v[:,d] def final_integrate(self): - nlocal = self.lmp.extract_global("nlocal", 0) - mass = self.lmp.numpy.extract_atom_darray("mass", self.ntypes+1) - atype = self.lmp.numpy.extract_atom_iarray("type", nlocal) - v = self.lmp.numpy.extract_atom_darray("v", nlocal, dim=3) - f = self.lmp.numpy.extract_atom_darray("f", nlocal, dim=3) + nlocal = self.lmp.extract_global("nlocal") + mass = self.lmp.numpy.extract_atom("mass") + atype = self.lmp.numpy.extract_atom("type") + v = self.lmp.numpy.extract_atom("v") + f = self.lmp.numpy.extract_atom("f") dtf = self.dtf - dtv = self.dtv mass = self.mass dtfm = dtf / np.take(mass, atype) diff --git a/lib/colvars/Makefile.common b/lib/colvars/Makefile.common index 2f2e2beffb..ce501dc5f3 100644 --- a/lib/colvars/Makefile.common +++ b/lib/colvars/Makefile.common @@ -15,7 +15,7 @@ else COLVARS_DEBUG_INCFLAGS = -DCOLVARS_DEBUG endif -COLVARS_INCFLAGS = $(COLVARS_DEBUG_INCFLAGS) $(COLVARS_PYTHON_INCFLAGS) +COLVARS_INCFLAGS = -DCOLVARS_LAMMPS $(COLVARS_DEBUG_INCFLAGS) $(COLVARS_PYTHON_INCFLAGS) -I../../src .SUFFIXES: @@ -38,6 +38,7 @@ COLVARS_SRCS = \ colvarcomp_gpath.cpp \ colvarcomp_protein.cpp \ colvarcomp_rotations.cpp \ + colvarcomp_volmaps.cpp \ colvar.cpp \ colvardeps.cpp \ colvargrid.cpp \ @@ -46,7 +47,12 @@ COLVARS_SRCS = \ colvarparse.cpp \ colvarproxy.cpp \ colvarproxy_replicas.cpp \ + colvarproxy_tcl.cpp \ + colvarproxy_volmaps.cpp \ colvarscript.cpp \ + colvarscript_commands.cpp \ + colvarscript_commands_bias.cpp \ + colvarscript_commands_colvar.cpp \ colvartypes.cpp \ colvarvalue.cpp @@ -61,7 +67,7 @@ ifeq ($(COLVARS_LEPTON),no) LEPTON_INCFLAGS = COLVARS_OBJS = $(COLVARS_SRCS:.cpp=.o) else -LEPTON_INCFLAGS = -Ilepton/include -DLEPTON -DLEPTON_USE_STATIC_LIBRARIES +LEPTON_INCFLAGS = -Ilepton/include -DLEPTON COLVARS_OBJS = $(COLVARS_SRCS:.cpp=.o) $(LEPTON_SRCS:.cpp=.o) endif @@ -77,25 +83,9 @@ Makefile.deps: $(COLVARS_SRCS) @echo > $@ @for src in $^ ; do \ obj=`basename $$src .cpp`.o ; \ - $(CXX) -MM $(COLVARS_INCFLAGS) $(LEPTON_INCFLAGS) \ + $(CXX) $(CXXFLAGS) -MM $(COLVARS_INCFLAGS) $(LEPTON_INCFLAGS) \ -MT '$$(COLVARS_OBJ_DIR)'$$obj $$src >> $@ ; \ done include Makefile.deps - -# Exceptions to pattern rule above for Lepton objects - -lepton/src/CompiledExpression.o: lepton/src/CompiledExpression.cpp - $(CXX) $(CXXFLAGS) -Ilepton/include -DLEPTON_BUILDING_STATIC_LIBRARY -c -o $@ $< -lepton/src/ExpressionProgram.o: lepton/src/ExpressionProgram.cpp - $(CXX) $(CXXFLAGS) -Ilepton/include -DLEPTON_BUILDING_STATIC_LIBRARY -c -o $@ $< -lepton/src/ExpressionTreeNode.o: lepton/src/ExpressionTreeNode.cpp - $(CXX) $(CXXFLAGS) -Ilepton/include -DLEPTON_BUILDING_STATIC_LIBRARY -c -o $@ $< -lepton/src/Operation.o: lepton/src/Operation.cpp - $(CXX) $(CXXFLAGS) -Ilepton/include -DLEPTON_BUILDING_STATIC_LIBRARY -c -o $@ $< -lepton/src/ParsedExpression.o: lepton/src/ParsedExpression.cpp - $(CXX) $(CXXFLAGS) -Ilepton/include -DLEPTON_BUILDING_STATIC_LIBRARY -c -o $@ $< -lepton/src/Parser.o: lepton/src/Parser.cpp - $(CXX) $(CXXFLAGS) -Ilepton/include -DLEPTON_BUILDING_STATIC_LIBRARY -c -o $@ $< - include Makefile.lepton.deps # Hand-generated diff --git a/lib/colvars/Makefile.deps b/lib/colvars/Makefile.deps index 2c0dabea6a..78e8768edd 100644 --- a/lib/colvars/Makefile.deps +++ b/lib/colvars/Makefile.deps @@ -1,83 +1,270 @@ $(COLVARS_OBJ_DIR)colvaratoms.o: colvaratoms.cpp colvarmodule.h \ colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \ - colvarparse.h colvarparams.h colvaratoms.h colvardeps.h + colvarproxy_tcl.h colvarproxy_volmaps.h colvarparse.h colvarparams.h \ + colvaratoms.h colvardeps.h $(COLVARS_OBJ_DIR)colvarbias_abf.o: colvarbias_abf.cpp colvarmodule.h \ - colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h colvar.h \ - colvarparse.h colvarparams.h colvardeps.h colvarbias_abf.h colvarbias.h \ - colvargrid.h colvar_UIestimator.h + colvars_version.h colvar.h colvarvalue.h colvartypes.h colvarparse.h \ + colvarparams.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarbias_abf.h colvarproxy.h colvarproxy_tcl.h colvarproxy_volmaps.h \ + colvarbias.h colvargrid.h colvar_UIestimator.h $(COLVARS_OBJ_DIR)colvarbias_alb.o: colvarbias_alb.cpp colvarmodule.h \ colvars_version.h colvarbias.h colvar.h colvarvalue.h colvartypes.h \ - colvarparse.h colvarparams.h colvardeps.h colvarbias_alb.h + colvarparse.h colvarparams.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarbias_alb.h $(COLVARS_OBJ_DIR)colvarbias.o: colvarbias.cpp colvarmodule.h \ - colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h colvarbias.h \ - colvar.h colvarparse.h colvarparams.h colvardeps.h colvargrid.h + colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \ + colvarproxy_tcl.h colvarproxy_volmaps.h colvarbias.h colvar.h \ + colvarparse.h colvarparams.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvargrid.h $(COLVARS_OBJ_DIR)colvarbias_histogram.o: colvarbias_histogram.cpp \ colvarmodule.h colvars_version.h colvarproxy.h colvartypes.h \ - colvarvalue.h colvar.h colvarparse.h colvarparams.h colvardeps.h \ + colvarvalue.h colvarproxy_tcl.h colvarproxy_volmaps.h colvar.h \ + colvarparse.h colvarparams.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ colvarbias_histogram.h colvarbias.h colvargrid.h $(COLVARS_OBJ_DIR)colvarbias_meta.o: colvarbias_meta.cpp colvarmodule.h \ - colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h colvar.h \ - colvarparse.h colvarparams.h colvardeps.h colvarbias_meta.h colvarbias.h \ - colvargrid.h + colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \ + colvarproxy_tcl.h colvarproxy_volmaps.h colvar.h colvarparse.h \ + colvarparams.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarbias_meta.h colvarbias.h colvargrid.h $(COLVARS_OBJ_DIR)colvarbias_restraint.o: colvarbias_restraint.cpp \ colvarmodule.h colvars_version.h colvarproxy.h colvartypes.h \ - colvarvalue.h colvarbias_restraint.h colvarbias.h colvar.h colvarparse.h \ - colvarparams.h colvardeps.h + colvarvalue.h colvarproxy_tcl.h colvarproxy_volmaps.h \ + colvarbias_restraint.h colvarbias.h colvar.h colvarparse.h \ + colvarparams.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h $(COLVARS_OBJ_DIR)colvarcomp_angles.o: colvarcomp_angles.cpp \ colvarmodule.h colvars_version.h colvar.h colvarvalue.h colvartypes.h \ - colvarparse.h colvarparams.h colvardeps.h colvarcomp.h colvaratoms.h \ - colvarproxy.h colvar_arithmeticpath.h colvar_geometricpath.h + colvarparse.h colvarparams.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvarcomp_apath.o: colvarcomp_apath.cpp colvarmodule.h \ colvars_version.h colvarvalue.h colvartypes.h colvarparse.h \ - colvarparams.h colvar.h colvardeps.h colvarcomp.h colvaratoms.h \ - colvarproxy.h colvar_arithmeticpath.h colvar_geometricpath.h + colvarparams.h colvar.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvarcomp_coordnums.o: colvarcomp_coordnums.cpp \ colvarmodule.h colvars_version.h colvarparse.h colvarvalue.h \ - colvartypes.h colvarparams.h colvaratoms.h colvarproxy.h colvardeps.h \ - colvar.h colvarcomp.h colvar_arithmeticpath.h colvar_geometricpath.h + colvartypes.h colvarparams.h colvaratoms.h colvarproxy.h \ + colvarproxy_tcl.h colvarproxy_volmaps.h colvardeps.h colvar.h \ + lepton/include/Lepton.h lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvar_arithmeticpath.h colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvarcomp.o: colvarcomp.cpp colvarmodule.h \ colvars_version.h colvarvalue.h colvartypes.h colvar.h colvarparse.h \ - colvarparams.h colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h \ - colvar_arithmeticpath.h colvar_geometricpath.h + colvarparams.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvarcomp_distances.o: colvarcomp_distances.cpp \ colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \ - colvarparse.h colvarparams.h colvar.h colvardeps.h colvarcomp.h \ - colvaratoms.h colvarproxy.h colvar_arithmeticpath.h \ - colvar_geometricpath.h + colvarparse.h colvarparams.h colvar.h colvardeps.h \ + lepton/include/Lepton.h lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvarcomp_gpath.o: colvarcomp_gpath.cpp colvarmodule.h \ colvars_version.h colvarvalue.h colvartypes.h colvarparse.h \ - colvarparams.h colvar.h colvardeps.h colvarcomp.h colvaratoms.h \ - colvarproxy.h colvar_arithmeticpath.h colvar_geometricpath.h + colvarparams.h colvar.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvarcomp_protein.o: colvarcomp_protein.cpp \ colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \ - colvarparse.h colvarparams.h colvar.h colvardeps.h colvarcomp.h \ - colvaratoms.h colvarproxy.h colvar_arithmeticpath.h \ - colvar_geometricpath.h + colvarparse.h colvarparams.h colvar.h colvardeps.h \ + lepton/include/Lepton.h lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvarcomp_rotations.o: colvarcomp_rotations.cpp \ colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \ - colvarparse.h colvarparams.h colvar.h colvardeps.h colvarcomp.h \ - colvaratoms.h colvarproxy.h colvar_arithmeticpath.h \ - colvar_geometricpath.h + colvarparse.h colvarparams.h colvar.h colvardeps.h \ + lepton/include/Lepton.h lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h +$(COLVARS_OBJ_DIR)colvarcomp_volmaps.o: colvarcomp_volmaps.cpp \ + colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \ + colvarparse.h colvarparams.h colvar.h colvardeps.h \ + lepton/include/Lepton.h lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvar.o: colvar.cpp colvarmodule.h colvars_version.h \ colvarvalue.h colvartypes.h colvarparse.h colvarparams.h colvar.h \ - colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h \ - colvar_arithmeticpath.h colvar_geometricpath.h colvarscript.h \ - colvarbias.h + colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h \ + colvarscript.h colvarbias.h colvarscript_commands.h \ + colvarscript_commands_colvar.h colvarscript_commands_bias.h $(COLVARS_OBJ_DIR)colvardeps.o: colvardeps.cpp colvarmodule.h \ - colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h colvardeps.h \ - colvarparse.h colvarparams.h + colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \ + colvarproxy_tcl.h colvarproxy_volmaps.h colvardeps.h colvarparse.h \ + colvarparams.h $(COLVARS_OBJ_DIR)colvargrid.o: colvargrid.cpp colvarmodule.h \ colvars_version.h colvarvalue.h colvartypes.h colvarparse.h \ - colvarparams.h colvar.h colvardeps.h colvarcomp.h colvaratoms.h \ - colvarproxy.h colvar_arithmeticpath.h colvar_geometricpath.h \ + colvarparams.h colvar.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h \ colvargrid.h $(COLVARS_OBJ_DIR)colvarmodule.o: colvarmodule.cpp colvarmodule.h \ colvars_version.h colvarparse.h colvarvalue.h colvartypes.h \ - colvarparams.h colvarproxy.h colvar.h colvardeps.h colvarbias.h \ - colvarbias_abf.h colvargrid.h colvar_UIestimator.h colvarbias_alb.h \ - colvarbias_histogram.h colvarbias_meta.h colvarbias_restraint.h \ - colvarscript.h colvaratoms.h colvarcomp.h colvar_arithmeticpath.h \ + colvarparams.h colvarproxy.h colvarproxy_tcl.h colvarproxy_volmaps.h \ + colvar.h colvardeps.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarbias.h colvarbias_abf.h colvargrid.h colvar_UIestimator.h \ + colvarbias_alb.h colvarbias_histogram.h colvarbias_meta.h \ + colvarbias_restraint.h colvarscript.h colvarscript_commands.h \ + colvarscript_commands_colvar.h colvarscript_commands_bias.h \ + colvaratoms.h colvarcomp.h colvar_arithmeticpath.h \ colvar_geometricpath.h $(COLVARS_OBJ_DIR)colvarparams.o: colvarparams.cpp colvarmodule.h \ colvars_version.h colvarvalue.h colvartypes.h colvarparams.h @@ -86,17 +273,92 @@ $(COLVARS_OBJ_DIR)colvarparse.o: colvarparse.cpp colvarmodule.h \ colvarparams.h $(COLVARS_OBJ_DIR)colvarproxy.o: colvarproxy.cpp colvarmodule.h \ colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \ - colvarscript.h colvarbias.h colvar.h colvarparse.h colvarparams.h \ - colvardeps.h colvaratoms.h + colvarproxy_tcl.h colvarproxy_volmaps.h colvarscript.h colvarbias.h \ + colvar.h colvarparse.h colvarparams.h colvardeps.h \ + lepton/include/Lepton.h lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarscript_commands.h colvarscript_commands_colvar.h \ + colvarscript_commands_bias.h colvaratoms.h $(COLVARS_OBJ_DIR)colvarproxy_replicas.o: colvarproxy_replicas.cpp \ colvarmodule.h colvars_version.h colvarproxy.h colvartypes.h \ - colvarvalue.h -$(COLVARS_OBJ_DIR)colvarscript.o: colvarscript.cpp colvarscript.h \ - colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \ - colvarbias.h colvar.h colvarparse.h colvarparams.h colvardeps.h \ - colvarproxy.h + colvarvalue.h colvarproxy_tcl.h colvarproxy_volmaps.h +$(COLVARS_OBJ_DIR)colvarproxy_tcl.o: colvarproxy_tcl.cpp colvarmodule.h \ + colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \ + colvarproxy_tcl.h colvarproxy_volmaps.h colvaratoms.h colvarparse.h \ + colvarparams.h colvardeps.h +$(COLVARS_OBJ_DIR)colvarproxy_volmaps.o: colvarproxy_volmaps.cpp \ + colvarmodule.h colvars_version.h colvarproxy_volmaps.h +$(COLVARS_OBJ_DIR)colvarscript.o: colvarscript.cpp colvarproxy.h \ + colvarmodule.h colvars_version.h colvartypes.h colvarvalue.h \ + colvarproxy_tcl.h colvarproxy_volmaps.h colvardeps.h colvarparse.h \ + colvarparams.h colvarscript.h colvarbias.h colvar.h \ + lepton/include/Lepton.h lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarscript_commands.h colvarscript_commands_colvar.h \ + colvarscript_commands_bias.h +$(COLVARS_OBJ_DIR)colvarscript_commands.o: colvarscript_commands.cpp \ + colvarproxy.h colvarmodule.h colvars_version.h colvartypes.h \ + colvarvalue.h colvarproxy_tcl.h colvarproxy_volmaps.h colvardeps.h \ + colvarparse.h colvarparams.h colvarscript.h colvarbias.h colvar.h \ + lepton/include/Lepton.h lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarscript_commands.h colvarscript_commands_colvar.h \ + colvarscript_commands_bias.h +$(COLVARS_OBJ_DIR)colvarscript_commands_bias.o: \ + colvarscript_commands_bias.cpp colvarproxy.h colvarmodule.h \ + colvars_version.h colvartypes.h colvarvalue.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvardeps.h colvarparse.h colvarparams.h \ + colvarscript.h colvarbias.h colvar.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarscript_commands.h colvarscript_commands_colvar.h \ + colvarscript_commands_bias.h +$(COLVARS_OBJ_DIR)colvarscript_commands_colvar.o: \ + colvarscript_commands_colvar.cpp colvarproxy.h colvarmodule.h \ + colvars_version.h colvartypes.h colvarvalue.h colvarproxy_tcl.h \ + colvarproxy_volmaps.h colvardeps.h colvarparse.h colvarparams.h \ + colvarscript.h colvarbias.h colvar.h lepton/include/Lepton.h \ + lepton/include/lepton/CompiledExpression.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/windowsIncludes.h \ + lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/ExpressionProgram.h \ + lepton/include/lepton/ExpressionTreeNode.h \ + lepton/include/lepton/Operation.h lepton/include/lepton/CustomFunction.h \ + lepton/include/lepton/Exception.h \ + lepton/include/lepton/ParsedExpression.h lepton/include/lepton/Parser.h \ + colvarscript_commands.h colvarscript_commands_colvar.h \ + colvarscript_commands_bias.h $(COLVARS_OBJ_DIR)colvartypes.o: colvartypes.cpp colvarmodule.h \ colvars_version.h colvartypes.h colvarparse.h colvarvalue.h \ - colvarparams.h + colvarparams.h ../../src/math_eigen.h $(COLVARS_OBJ_DIR)colvarvalue.o: colvarvalue.cpp colvarmodule.h \ colvars_version.h colvarvalue.h colvartypes.h diff --git a/lib/colvars/colvar.cpp b/lib/colvars/colvar.cpp index 1002dc35d8..ed6fec1ac5 100644 --- a/lib/colvars/colvar.cpp +++ b/lib/colvars/colvar.cpp @@ -18,7 +18,9 @@ #include "colvarcomp.h" #include "colvarscript.h" - +#if (__cplusplus >= 201103L) +std::map> colvar::global_cvc_map = std::map>(); +#endif colvar::colvar() { @@ -541,7 +543,7 @@ int colvar::init_grid_parameters(std::string const &conf) cvm::log("Reading legacy options lowerWall and lowerWallConstant: " "consider using a harmonicWalls restraint (caution: force constant would then be scaled by width^2).\n"); if (!get_keyval(conf, "lowerWall", lower_wall)) { - error_code != cvm::error("Error: the value of lowerWall must be set " + error_code |= cvm::error("Error: the value of lowerWall must be set " "explicitly.\n", INPUT_ERROR); } lw_conf = std::string("\n\ @@ -554,7 +556,7 @@ int colvar::init_grid_parameters(std::string const &conf) cvm::log("Reading legacy options upperWall and upperWallConstant: " "consider using a harmonicWalls restraint (caution: force constant would then be scaled by width^2).\n"); if (!get_keyval(conf, "upperWall", upper_wall)) { - error_code != cvm::error("Error: the value of upperWall must be set " + error_code |= cvm::error("Error: the value of upperWall must be set " "explicitly.\n", INPUT_ERROR); } uw_conf = std::string("\n\ @@ -616,7 +618,7 @@ harmonicWalls {\n\ "are enabled).\n", INPUT_ERROR); } - return COLVARS_OK; + return error_code; } @@ -681,6 +683,9 @@ int colvar::init_extended_Lagrangian(std::string const &conf) // Adjust Langevin sigma for slow time step if time_step_factor != 1 ext_sigma = cvm::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / (cvm::dt() * cvm::real(time_step_factor))); } + + get_keyval_feature(this, conf, "reflectingLowerBoundary", f_cv_reflecting_lower_boundary, false); + get_keyval_feature(this, conf, "reflectingUpperBoundary", f_cv_reflecting_upper_boundary, false); } return COLVARS_OK; @@ -721,15 +726,15 @@ int colvar::init_output_flags(std::string const &conf) return COLVARS_OK; } - - - // read the configuration and set up corresponding instances, for // each type of component implemented template int colvar::init_components_type(std::string const &conf, char const * /* def_desc */, char const *def_config_key) { +#if (__cplusplus >= 201103L) + global_cvc_map[def_config_key] = [](const std::string& cvc_conf){return new def_class_name(cvc_conf);}; +#endif size_t def_count = 0; std::string def_conf = ""; size_t pos = 0; @@ -863,6 +868,8 @@ int colvar::init_components(std::string const &conf) error_code |= init_components_type(conf, "arithmetic path collective variables (s) for other CVs", "aspathCV"); error_code |= init_components_type(conf, "arithmetic path collective variables (s) for other CVs", "azpathCV"); + error_code |= init_components_type(conf, "total value of atomic map", "mapTotal"); + if (!cvcs.size() || (error_code != COLVARS_OK)) { cvm::error("Error: no valid components were provided " "for this collective variable.\n", @@ -1040,85 +1047,93 @@ int colvar::init_dependencies() { init_feature(f_cv_gradient, "gradient", f_type_dynamic); require_feature_children(f_cv_gradient, f_cvc_gradient); - init_feature(f_cv_collect_gradient, "collect gradient", f_type_dynamic); + init_feature(f_cv_collect_gradient, "collect_gradient", f_type_dynamic); require_feature_self(f_cv_collect_gradient, f_cv_gradient); require_feature_self(f_cv_collect_gradient, f_cv_scalar); // The following exlusion could be lifted by implementing the feature exclude_feature_self(f_cv_collect_gradient, f_cv_scripted); require_feature_children(f_cv_collect_gradient, f_cvc_explicit_gradient); - init_feature(f_cv_fdiff_velocity, "velocity from finite differences", f_type_dynamic); + init_feature(f_cv_fdiff_velocity, "velocity_from_finite_differences", f_type_dynamic); // System force: either trivial (spring force); through extended Lagrangian, or calculated explicitly - init_feature(f_cv_total_force, "total force", f_type_dynamic); + init_feature(f_cv_total_force, "total_force", f_type_dynamic); require_feature_alt(f_cv_total_force, f_cv_extended_Lagrangian, f_cv_total_force_calc); // Deps for explicit total force calculation - init_feature(f_cv_total_force_calc, "total force calculation", f_type_dynamic); + init_feature(f_cv_total_force_calc, "total_force_calculation", f_type_dynamic); require_feature_self(f_cv_total_force_calc, f_cv_scalar); require_feature_self(f_cv_total_force_calc, f_cv_linear); require_feature_children(f_cv_total_force_calc, f_cvc_inv_gradient); require_feature_self(f_cv_total_force_calc, f_cv_Jacobian); - init_feature(f_cv_Jacobian, "Jacobian derivative", f_type_dynamic); + init_feature(f_cv_Jacobian, "Jacobian_derivative", f_type_dynamic); require_feature_self(f_cv_Jacobian, f_cv_scalar); require_feature_self(f_cv_Jacobian, f_cv_linear); require_feature_children(f_cv_Jacobian, f_cvc_Jacobian); - init_feature(f_cv_hide_Jacobian, "hide Jacobian force", f_type_user); + init_feature(f_cv_hide_Jacobian, "hide_Jacobian_force", f_type_user); require_feature_self(f_cv_hide_Jacobian, f_cv_Jacobian); // can only hide if calculated - init_feature(f_cv_extended_Lagrangian, "extended Lagrangian", f_type_user); + init_feature(f_cv_extended_Lagrangian, "extended_Lagrangian", f_type_user); require_feature_self(f_cv_extended_Lagrangian, f_cv_scalar); require_feature_self(f_cv_extended_Lagrangian, f_cv_gradient); - init_feature(f_cv_Langevin, "Langevin dynamics", f_type_user); + init_feature(f_cv_Langevin, "Langevin_dynamics", f_type_user); require_feature_self(f_cv_Langevin, f_cv_extended_Lagrangian); - init_feature(f_cv_single_cvc, "single component", f_type_static); + init_feature(f_cv_single_cvc, "single_component", f_type_static); init_feature(f_cv_linear, "linear", f_type_static); init_feature(f_cv_scalar, "scalar", f_type_static); - init_feature(f_cv_output_energy, "output energy", f_type_user); + init_feature(f_cv_output_energy, "output_energy", f_type_user); - init_feature(f_cv_output_value, "output value", f_type_user); + init_feature(f_cv_output_value, "output_value", f_type_user); - init_feature(f_cv_output_velocity, "output velocity", f_type_user); + init_feature(f_cv_output_velocity, "output_velocity", f_type_user); require_feature_self(f_cv_output_velocity, f_cv_fdiff_velocity); - init_feature(f_cv_output_applied_force, "output applied force", f_type_user); + init_feature(f_cv_output_applied_force, "output_applied_force", f_type_user); - init_feature(f_cv_output_total_force, "output total force", f_type_user); + init_feature(f_cv_output_total_force, "output_total_force", f_type_user); require_feature_self(f_cv_output_total_force, f_cv_total_force); - init_feature(f_cv_subtract_applied_force, "subtract applied force from total force", f_type_user); + init_feature(f_cv_subtract_applied_force, "subtract_applied_force_from_total_force", f_type_user); require_feature_self(f_cv_subtract_applied_force, f_cv_total_force); - init_feature(f_cv_lower_boundary, "lower boundary", f_type_user); + init_feature(f_cv_lower_boundary, "lower_boundary", f_type_user); require_feature_self(f_cv_lower_boundary, f_cv_scalar); - init_feature(f_cv_upper_boundary, "upper boundary", f_type_user); + init_feature(f_cv_upper_boundary, "upper_boundary", f_type_user); require_feature_self(f_cv_upper_boundary, f_cv_scalar); - init_feature(f_cv_hard_lower_boundary, "hard lower boundary", f_type_user); + init_feature(f_cv_hard_lower_boundary, "hard_lower_boundary", f_type_user); require_feature_self(f_cv_hard_lower_boundary, f_cv_lower_boundary); - init_feature(f_cv_hard_upper_boundary, "hard upper boundary", f_type_user); + init_feature(f_cv_hard_upper_boundary, "hard_upper_boundary", f_type_user); require_feature_self(f_cv_hard_upper_boundary, f_cv_upper_boundary); + init_feature(f_cv_reflecting_lower_boundary, "reflecting_lower_boundary", f_type_user); + require_feature_self(f_cv_reflecting_lower_boundary, f_cv_lower_boundary); + require_feature_self(f_cv_reflecting_lower_boundary, f_cv_extended_Lagrangian); + + init_feature(f_cv_reflecting_upper_boundary, "reflecting_upper_boundary", f_type_user); + require_feature_self(f_cv_reflecting_upper_boundary, f_cv_upper_boundary); + require_feature_self(f_cv_reflecting_upper_boundary, f_cv_extended_Lagrangian); + init_feature(f_cv_grid, "grid", f_type_dynamic); require_feature_self(f_cv_grid, f_cv_lower_boundary); require_feature_self(f_cv_grid, f_cv_upper_boundary); - init_feature(f_cv_runave, "running average", f_type_user); + init_feature(f_cv_runave, "running_average", f_type_user); - init_feature(f_cv_corrfunc, "correlation function", f_type_user); + init_feature(f_cv_corrfunc, "correlation_function", f_type_user); init_feature(f_cv_scripted, "scripted", f_type_user); - init_feature(f_cv_custom_function, "custom function", f_type_user); + init_feature(f_cv_custom_function, "custom_function", f_type_user); exclude_feature_self(f_cv_custom_function, f_cv_scripted); init_feature(f_cv_periodic, "periodic", f_type_static); @@ -1129,7 +1144,7 @@ int colvar::init_dependencies() { // because total forces are obtained from the previous time step, // we cannot (currently) have colvar values and total forces for the same timestep - init_feature(f_cv_multiple_ts, "multiple timestep colvar", f_type_static); + init_feature(f_cv_multiple_ts, "multiple_timestep", f_type_static); exclude_feature_self(f_cv_multiple_ts, f_cv_total_force_calc); // check that everything is initialized @@ -1199,8 +1214,17 @@ colvar::~colvar() (*ci)->remove_all_children(); delete *ci; } + cvcs.clear(); - // remove reference to this colvar from the CVM + while (biases.size() > 0) { + size_t const i = biases.size()-1; + cvm::log("Warning: before deleting colvar " + name + + ", deleting related bias " + biases[i]->name); + delete biases[i]; + } + biases.clear(); + + // remove reference to this colvar from the module colvarmodule *cv = cvm::main(); for (std::vector::iterator cvi = cv->variables()->begin(); cvi != cv->variables()->end(); @@ -1211,6 +1235,8 @@ colvar::~colvar() } } + cv->config_changed(); + #ifdef LEPTON for (std::vector::iterator cei = value_evaluators.begin(); cei != value_evaluators.end(); @@ -1599,6 +1625,15 @@ int colvar::calc_colvar_properties() // just calculated from the cvcs if ((cvm::step_relative() == 0 && !after_restart) || x_ext.type() == colvarvalue::type_notset) { x_ext = x; + if (is_enabled(f_cv_reflecting_lower_boundary) && x_ext < lower_boundary) { + cvm::log("Warning: initializing extended coordinate to reflective lower boundary, as colvar value is below."); + x_ext = lower_boundary; + } + if (is_enabled(f_cv_reflecting_upper_boundary) && x_ext > upper_boundary) { + cvm::log("Warning: initializing extended coordinate to reflective upper boundary, as colvar value is above."); + x_ext = upper_boundary; + } + v_ext.reset(); // (already 0; added for clarity) } @@ -1672,10 +1707,10 @@ cvm::real colvar::update_forces_energy() cvm::log("Updating extended-Lagrangian degree of freedom.\n"); } - if (prev_timestep > -1) { + if (prev_timestep > -1L) { // Keep track of slow timestep to integrate MTS colvars // the colvar checks the interval after waking up twice - int n_timesteps = cvm::step_relative() - prev_timestep; + cvm::step_number n_timesteps = cvm::step_relative() - prev_timestep; if (n_timesteps != 0 && n_timesteps != time_step_factor) { cvm::error("Error: extended-Lagrangian " + description + " has timeStepFactor " + cvm::to_str(time_step_factor) + ", but was activated after " + cvm::to_str(n_timesteps) + @@ -1737,6 +1772,14 @@ cvm::real colvar::update_forces_energy() } v_ext += (0.5 * dt) * f_ext / ext_mass; x_ext += dt * v_ext; + + cvm::real delta = 0; // Length of overshoot past either reflecting boundary + if ((is_enabled(f_cv_reflecting_lower_boundary) && (delta = x_ext - lower_boundary) < 0) || + (is_enabled(f_cv_reflecting_upper_boundary) && (delta = x_ext - upper_boundary) > 0)) { + x_ext -= 2.0 * delta; + v_ext *= -1.0; + } + x_ext.apply_constraints(); this->wrap(x_ext); } else { @@ -2082,7 +2125,7 @@ void colvar::wrap(colvarvalue &x_unwrapped) const std::istream & colvar::read_state(std::istream &is) { - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); std::string conf; if ( !(is >> colvarparse::read_block("colvar", &conf)) ) { @@ -2163,7 +2206,7 @@ std::istream & colvar::read_state(std::istream &is) std::istream & colvar::read_traj(std::istream &is) { - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); if (is_enabled(f_cv_output_value)) { diff --git a/lib/colvars/colvar.h b/lib/colvars/colvar.h index e6fafbdec3..5cf0077a39 100644 --- a/lib/colvars/colvar.h +++ b/lib/colvars/colvar.h @@ -12,6 +12,11 @@ #include +#if (__cplusplus >= 201103L) +#include +#include +#endif + #include "colvarmodule.h" #include "colvarvalue.h" #include "colvarparse.h" @@ -114,6 +119,7 @@ public: /// List of biases that depend on this colvar std::vector biases; + protected: @@ -602,6 +608,17 @@ public: class cartesian; class orientation; + // components that do not handle any atoms directly + class map_total; + + /// getter of the global cvc map +#if (__cplusplus >= 201103L) + /// A global mapping of cvc names to the cvc constructors + static const std::map>& get_global_cvc_map() { + return global_cvc_map; + } +#endif + protected: /// \brief Array of \link colvar::cvc \endlink objects @@ -636,6 +653,11 @@ protected: double dev_null; #endif +#if (__cplusplus >= 201103L) + /// A global mapping of cvc names to the cvc constructors + static std::map> global_cvc_map; +#endif + public: /// \brief Sorted array of (zero-based) IDs for all atoms involved diff --git a/lib/colvars/colvar_UIestimator.h b/lib/colvars/colvar_UIestimator.h index cb4c7ed57d..1ec378f90c 100644 --- a/lib/colvars/colvar_UIestimator.h +++ b/lib/colvars/colvar_UIestimator.h @@ -116,7 +116,7 @@ namespace UIestimator { int i; for (i = 0; i < dimension; i++) { - temp[i] = round((round(y[i] / width[i] + EPSILON) - round(x[i] / width[i] + EPSILON)) + (y_size - 1) / 2 + EPSILON); + temp[i] = int(round((round(y[i] / width[i] + EPSILON) - round(x[i] / width[i] + EPSILON)) + (y_size - 1) / 2 + EPSILON)); } int index = 0; @@ -305,12 +305,6 @@ namespace UIestimator { int i; - if (step % output_freq == 0) { - calc_pmf(); - write_files(); - //write_interal_data(); - } - for (i = 0; i < dimension; i++) { // for dihedral RC, it is possible that x = 179 and y = -179, should correct it // may have problem, need to fix @@ -381,6 +375,7 @@ namespace UIestimator { bool written; bool written_1D; + public: // calculate gradients from the internal variables void calc_pmf() { int norm; diff --git a/lib/colvars/colvaratoms.cpp b/lib/colvars/colvaratoms.cpp index 180fc69a85..1a4280a202 100644 --- a/lib/colvars/colvaratoms.cpp +++ b/lib/colvars/colvaratoms.cpp @@ -240,19 +240,19 @@ int cvm::atom_group::init_dependencies() { } init_feature(f_ag_active, "active", f_type_dynamic); - init_feature(f_ag_center, "translational fit", f_type_static); - init_feature(f_ag_rotate, "rotational fit", f_type_static); - init_feature(f_ag_fitting_group, "fitting group", f_type_static); - init_feature(f_ag_explicit_gradient, "explicit atom gradient", f_type_dynamic); - init_feature(f_ag_fit_gradients, "fit gradients", f_type_user); + init_feature(f_ag_center, "translational_fit", f_type_static); + init_feature(f_ag_rotate, "rotational_fit", f_type_static); + init_feature(f_ag_fitting_group, "fitting_group", f_type_static); + init_feature(f_ag_explicit_gradient, "explicit_atom_gradient", f_type_dynamic); + init_feature(f_ag_fit_gradients, "fit_gradients", f_type_user); require_feature_self(f_ag_fit_gradients, f_ag_explicit_gradient); - init_feature(f_ag_atom_forces, "atomic forces", f_type_dynamic); + init_feature(f_ag_atom_forces, "atomic_forces", f_type_dynamic); // parallel calculation implies that we have at least a scalable center of mass, // but f_ag_scalable is kept as a separate feature to deal with future dependencies - init_feature(f_ag_scalable, "scalable group calculation", f_type_static); - init_feature(f_ag_scalable_com, "scalable group center of mass calculation", f_type_static); + init_feature(f_ag_scalable, "scalable_group", f_type_static); + init_feature(f_ag_scalable_com, "scalable_group_center_of_mass", f_type_static); require_feature_self(f_ag_scalable, f_ag_scalable_com); // check that everything is initialized diff --git a/lib/colvars/colvarbias.cpp b/lib/colvars/colvarbias.cpp index 09bcca01b5..65e9dedc36 100644 --- a/lib/colvars/colvarbias.cpp +++ b/lib/colvars/colvarbias.cpp @@ -7,6 +7,9 @@ // If you wish to distribute your changes, please submit them to the // Colvars repository at GitHub. +#include +#include + #include "colvarmodule.h" #include "colvarproxy.h" #include "colvarvalue.h" @@ -23,8 +26,12 @@ colvarbias::colvarbias(char const *key) init_dependencies(); rank = 1; + time_step_factor = 1; + has_data = false; b_output_energy = false; + output_freq = cvm::restart_out_freq; + reset(); state_file_step = 0L; matching_state = false; @@ -93,12 +100,18 @@ int colvarbias::init(std::string const &conf) output_prefix = cvm::output_prefix(); + get_keyval_feature(this, conf, "stepZeroData", f_cvb_step_zero_data, is_enabled(f_cvb_step_zero_data)); + + // Write energy to traj file? get_keyval(conf, "outputEnergy", b_output_energy, b_output_energy); - // Disabled by default in base class; default value can be overridden by derived class constructor - get_keyval_feature(this, conf, "bypassExtendedLagrangian", f_cvb_bypass_ext_lagrangian, is_enabled(f_cvb_bypass_ext_lagrangian), parse_silent); + // How often to write full output files? + get_keyval(conf, "outputFreq", output_freq, output_freq); - get_keyval(conf, "timeStepFactor", time_step_factor, 1); + // Disabled by default in base class; default value can be overridden by derived class constructor + get_keyval_feature(this, conf, "bypassExtendedLagrangian", f_cvb_bypass_ext_lagrangian, is_enabled(f_cvb_bypass_ext_lagrangian), parse_echo); + + get_keyval(conf, "timeStepFactor", time_step_factor, time_step_factor); if (time_step_factor < 1) { cvm::error("Error: timeStepFactor must be 1 or greater.\n"); return COLVARS_ERROR; @@ -125,37 +138,40 @@ int colvarbias::init_dependencies() { init_feature(f_cvb_awake, "awake", f_type_static); require_feature_self(f_cvb_awake, f_cvb_active); - init_feature(f_cvb_apply_force, "apply force", f_type_user); + init_feature(f_cvb_step_zero_data, "step_zero_data", f_type_user); + + init_feature(f_cvb_apply_force, "apply_force", f_type_user); require_feature_children(f_cvb_apply_force, f_cv_gradient); - init_feature(f_cvb_bypass_ext_lagrangian, "bypass extended-Lagrangian coordinates", f_type_user); + init_feature(f_cvb_bypass_ext_lagrangian, "bypass_extended_Lagrangian_coordinates", f_type_user); + // The exclusion below prevents the inconsistency where biasing forces are applied onto // the actual colvar, while total forces are measured on the extended coordinate exclude_feature_self(f_cvb_bypass_ext_lagrangian, f_cvb_get_total_force); - init_feature(f_cvb_get_total_force, "obtain total force", f_type_dynamic); + init_feature(f_cvb_get_total_force, "obtain_total_force", f_type_dynamic); require_feature_children(f_cvb_get_total_force, f_cv_total_force); - init_feature(f_cvb_output_acc_work, "output accumulated work", f_type_user); + init_feature(f_cvb_output_acc_work, "output_accumulated_work", f_type_user); require_feature_self(f_cvb_output_acc_work, f_cvb_apply_force); - init_feature(f_cvb_history_dependent, "history-dependent", f_type_static); + init_feature(f_cvb_history_dependent, "history_dependent", f_type_static); - init_feature(f_cvb_time_dependent, "time-dependent", f_type_static); + init_feature(f_cvb_time_dependent, "time_dependent", f_type_static); - init_feature(f_cvb_scalar_variables, "require scalar variables", f_type_static); + init_feature(f_cvb_scalar_variables, "require_scalar_variables", f_type_static); require_feature_children(f_cvb_scalar_variables, f_cv_scalar); - init_feature(f_cvb_calc_pmf, "calculate a PMF", f_type_static); + init_feature(f_cvb_calc_pmf, "calculate_a_PMF", f_type_static); - init_feature(f_cvb_calc_ti_samples, "calculate TI samples", f_type_dynamic); + init_feature(f_cvb_calc_ti_samples, "calculate_TI_samples", f_type_dynamic); require_feature_self(f_cvb_calc_ti_samples, f_cvb_get_total_force); require_feature_children(f_cvb_calc_ti_samples, f_cv_grid); - init_feature(f_cvb_write_ti_samples, "write TI samples ", f_type_user); + init_feature(f_cvb_write_ti_samples, "write_TI_samples_", f_type_user); require_feature_self(f_cvb_write_ti_samples, f_cvb_calc_ti_samples); - init_feature(f_cvb_write_ti_pmf, "write TI PMF", f_type_user); + init_feature(f_cvb_write_ti_pmf, "write_TI_PMF", f_type_user); require_feature_self(f_cvb_write_ti_pmf, f_cvb_calc_ti_samples); // check that everything is initialized @@ -237,6 +253,8 @@ int colvarbias::clear() } } + cv->config_changed(); + return COLVARS_OK; } @@ -302,6 +320,17 @@ int colvarbias::update() } +bool colvarbias::can_accumulate_data() +{ + colvarproxy *proxy = cvm::main()->proxy; + if (((cvm::step_relative() > 0) && !proxy->simulation_continuing()) || + is_enabled(f_cvb_step_zero_data)) { + return true; + } + return false; +} + + int colvarbias::calc_energy(std::vector const *) { bias_energy = 0.0; @@ -451,7 +480,7 @@ std::ostream & colvarbias::write_state(std::ostream &os) std::istream & colvarbias::read_state(std::istream &is) { - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); std::string key, brace, conf; if ( !(is >> key) || !(key == state_keyword || key == bias_type) || @@ -501,12 +530,80 @@ std::istream & colvarbias::read_state(std::istream &is) } +int colvarbias::write_state_prefix(std::string const &prefix) +{ + std::string const filename = + cvm::state_file_prefix(prefix.c_str())+".colvars.state"; + std::ostream *os = cvm::proxy->output_stream(filename.c_str()); + int error_code = COLVARS_OK; + if (os != NULL) { + os->setf(std::ios::scientific, std::ios::floatfield); + error_code = write_state(*os).good() ? COLVARS_OK : FILE_ERROR; + } else { + error_code = FILE_ERROR; + } + cvm::proxy->close_output_stream(filename.c_str()); + return error_code; +} + + +int colvarbias::write_state_string(std::string &output) +{ + std::ostringstream os; + if (!write_state(os)) { + return cvm::error("Error: in writing state of bias \""+name+ + "\" to buffer.\n", FILE_ERROR); + } + output = os.str(); + return COLVARS_OK; +} + + +int colvarbias::read_state_prefix(std::string const &prefix) +{ + std::string filename((prefix+std::string(".colvars.state")).c_str()); + std::ifstream is(filename.c_str()); + if (!is.good()) { + // try without the suffix + is.clear(); + filename = prefix; + is.open(filename.c_str()); + } + return read_state(is).good() ? COLVARS_OK : + cvm::error("Error: in reading state for \""+name+"\" from input file \""+ + std::string(filename)+"\".\n", FILE_ERROR); +} + + +int colvarbias::read_state_string(char const *buffer) +{ + if (buffer != NULL) { + size_t const buffer_size = strlen(buffer); + if (cvm::debug()) { + cvm::log("colvarbias::read_state_string() with argument:\n"); + cvm::log(buffer); + } + + if (buffer_size > 0) { + std::istringstream is; + is.rdbuf()->pubsetbuf(const_cast(buffer), buffer_size); + return read_state(is).good() ? COLVARS_OK : + cvm::error("Error: in reading state for \""+name+"\" from buffer.\n", + FILE_ERROR); + } + return COLVARS_OK; + } + return cvm::error("Error: NULL pointer for colvarbias::read_state_string()", + BUG_ERROR); +} + + std::istream & colvarbias::read_state_data_key(std::istream &is, char const *key) { - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); std::string key_in; if ( !(is >> key_in) || - !(key_in == to_lower_cppstr(std::string(key))) ) { + !(to_lower_cppstr(key_in) == to_lower_cppstr(std::string(key))) ) { cvm::error("Error: in reading restart configuration for "+ bias_type+" bias \""+this->name+"\" at position "+ cvm::to_str(static_cast(is.tellg()))+ @@ -546,7 +643,12 @@ std::ostream & colvarbias::write_traj(std::ostream &os) colvarbias_ti::colvarbias_ti(char const *key) : colvarbias(key) { + colvarproxy *proxy = cvm::main()->proxy; provide(f_cvb_calc_ti_samples); + if (!proxy->total_forces_same_step()) { + // Samples at step zero can not be collected + feature_states[f_cvb_step_zero_data].available = false; + } ti_avg_forces = NULL; ti_count = NULL; } @@ -683,7 +785,9 @@ int colvarbias_ti::update_system_forces(std::vector const (*subtract_forces)[i] : previous_colvar_forces[i]); } } - ti_avg_forces->acc_value(ti_bin, ti_system_forces); + if (cvm::step_relative() > 0 || is_enabled(f_cvb_step_zero_data)) { + ti_avg_forces->acc_value(ti_bin, ti_system_forces); + } } } diff --git a/lib/colvars/colvarbias.h b/lib/colvars/colvarbias.h index 5179c42853..a2788eea72 100644 --- a/lib/colvars/colvarbias.h +++ b/lib/colvars/colvarbias.h @@ -57,6 +57,10 @@ public: /// Some implementations may use calc_energy() and calc_forces() virtual int update(); + /// Returns true if the current step represent a valid increment, whose data + /// can be recorded (as opposed to e.g. a continuation step from a restart) + virtual bool can_accumulate_data(); + /// Compute the energy of the bias /// Uses the vector of colvar values provided if not NULL, and the values /// currently cached in the bias instance otherwise @@ -144,14 +148,28 @@ public: } /// Read a keyword from the state data (typically a header) + /// \param Input stream + /// \param Keyword labeling the header block std::istream & read_state_data_key(std::istream &is, char const *key); - /// Write the bias configuration to a restart file or other stream + /// Write the bias configuration to a state file or other stream std::ostream & write_state(std::ostream &os); /// Read the bias configuration from a restart file or other stream std::istream & read_state(std::istream &is); + /// Write the bias state to a file with the given prefix + int write_state_prefix(std::string const &prefix); + + /// Write the bias state to a string + int write_state_string(std::string &output); + + /// Read the bias state from a file with this name or prefix + int read_state_prefix(std::string const &prefix); + + /// Read the bias state from this string buffer + int read_state_string(char const *buffer); + /// Write a label to the trajectory file (comment line) virtual std::ostream & write_traj_label(std::ostream &os); @@ -164,6 +182,9 @@ public: return COLVARS_OK; } + /// Frequency for writing output files + size_t output_freq; + /// Write any output files that this bias may have (e.g. PMF files) virtual int write_output_files() { diff --git a/lib/colvars/colvarbias_abf.cpp b/lib/colvars/colvarbias_abf.cpp index 5382a828f7..a84ec358dd 100644 --- a/lib/colvars/colvarbias_abf.cpp +++ b/lib/colvars/colvarbias_abf.cpp @@ -8,7 +8,6 @@ // Colvars repository at GitHub. #include "colvarmodule.h" -#include "colvarproxy.h" #include "colvar.h" #include "colvarbias_abf.h" @@ -29,8 +28,14 @@ colvarbias_abf::colvarbias_abf(char const *key) last_gradients(NULL), last_samples(NULL) { + colvarproxy *proxy = cvm::main()->proxy; + if (!proxy->total_forces_same_step()) { + // Samples at step zero can not be collected + feature_states[f_cvb_step_zero_data].available = false; + } } + int colvarbias_abf::init(std::string const &conf) { colvarbias::init(conf); @@ -71,8 +76,19 @@ int colvarbias_abf::init(std::string const &conf) // full_samples - min_samples >= 1 is guaranteed get_keyval(conf, "inputPrefix", input_prefix, std::vector()); - get_keyval(conf, "outputFreq", output_freq, cvm::restart_out_freq); + get_keyval(conf, "historyFreq", history_freq, 0); + if (history_freq != 0) { + if (output_freq == 0) { + cvm::error("Error: historyFreq must be a multiple of outputFreq.\n", + INPUT_ERROR); + } else { + if ((history_freq % output_freq) != 0) { + cvm::error("Error: historyFreq must be a multiple of outputFreq.\n", + INPUT_ERROR); + } + } + } b_history_files = (history_freq > 0); // shared ABF @@ -146,6 +162,7 @@ int colvarbias_abf::init(std::string const &conf) for (i = 0; i < num_variables(); i++) { if (max_force[i] < 0.0) { cvm::error("Error: maxForce should be non-negative."); + return COLVARS_ERROR; } } cap_force = true; @@ -184,25 +201,24 @@ int colvarbias_abf::init(std::string const &conf) czar_gradients = new colvar_grid_gradient(colvars); } - // For now, we integrate on-the-fly iff the grid is < 3D - if ( num_variables() <= 3 ) { + get_keyval(conf, "integrate", b_integrate, num_variables() <= 3); // Integrate for output if d<=3 + if (b_integrate) { + // For now, we integrate on-the-fly iff the grid is < 3D + if ( num_variables() > 3 ) { + cvm::error("Error: cannot integrate free energy in dimension > 3.\n"); + return COLVARS_ERROR; + } pmf = new integrate_potential(colvars, gradients); if ( b_CZAR_estimator ) { czar_pmf = new integrate_potential(colvars, czar_gradients); } - get_keyval(conf, "integrate", b_integrate, true); // Integrate for output - if ( num_variables() > 1 ) { - // Projected ABF - get_keyval(conf, "pABFintegrateFreq", pabf_freq, 0); - // Parameters for integrating initial (and final) gradient data - get_keyval(conf, "integrateInitMaxIterations", integrate_initial_iterations, 1e4); - get_keyval(conf, "integrateInitTol", integrate_initial_tol, 1e-6); - // for updating the integrated PMF on the fly - get_keyval(conf, "integrateMaxIterations", integrate_iterations, 100); - get_keyval(conf, "integrateTol", integrate_tol, 1e-4); - } - } else { - b_integrate = false; + // Parameters for integrating initial (and final) gradient data + get_keyval(conf, "integrateMaxIterations", integrate_iterations, 1e4, colvarparse::parse_silent); + get_keyval(conf, "integrateTol", integrate_tol, 1e-6, colvarparse::parse_silent); + // Projected ABF, updating the integrated PMF on the fly + get_keyval(conf, "pABFintegrateFreq", pabf_freq, 0, colvarparse::parse_silent); + get_keyval(conf, "pABFintegrateMaxIterations", pabf_integrate_iterations, 100, colvarparse::parse_silent); + get_keyval(conf, "pABFintegrateTol", pabf_integrate_tol, 1e-4, colvarparse::parse_silent); } // For shared ABF, we store a second set of grids. @@ -330,7 +346,7 @@ int colvarbias_abf::update() force_bin = bin; } - if (cvm::step_relative() > 0 || cvm::proxy->total_forces_same_step()) { + if (cvm::step_relative() > 0 || is_enabled(f_cvb_step_zero_data)) { if (update_bias) { // if (b_adiabatic_reweighting) { @@ -346,10 +362,10 @@ int colvarbias_abf::update() // and subtract previous ABF force if necessary update_system_force(i); } - gradients->acc_force(force_bin, system_force); - if ( b_integrate ) { - pmf->update_div_neighbors(force_bin); - } + gradients->acc_force(force_bin, system_force); + if ( b_integrate ) { + pmf->update_div_neighbors(force_bin); + } } } @@ -370,10 +386,10 @@ int colvarbias_abf::update() if ( b_integrate ) { if ( pabf_freq && cvm::step_relative() % pabf_freq == 0 ) { cvm::real err; - int iter = pmf->integrate(integrate_iterations, integrate_tol, err); - if ( iter == integrate_iterations ) { - cvm::log("Warning: PMF integration did not converge to " + cvm::to_str(integrate_tol) - + " in " + cvm::to_str(integrate_iterations) + int iter = pmf->integrate(pabf_integrate_iterations, pabf_integrate_tol, err); + if ( iter == pabf_integrate_iterations ) { + cvm::log("Warning: PMF integration did not converge to " + cvm::to_str(pabf_integrate_tol) + + " in " + cvm::to_str(pabf_integrate_iterations) + " steps. Residual error: " + cvm::to_str(err)); } pmf->set_zero_minimum(); // TODO: do this only when necessary @@ -448,17 +464,6 @@ int colvarbias_abf::update() output_prefix = cvm::output_prefix() + "." + this->name; } - if (output_freq && (cvm::step_absolute() % output_freq) == 0) { - if (cvm::debug()) cvm::log("ABF bias trying to write gradients and samples to disk"); - write_gradients_samples(output_prefix); - } - - if (b_history_files && (cvm::step_absolute() % history_freq) == 0) { - // file already exists iff cvm::step_relative() > 0 - // otherwise, backup and replace - write_gradients_samples(output_prefix + ".hist", (cvm::step_relative() > 0)); - } - if (shared_on && shared_last_step >= 0 && cvm::step_absolute() % shared_freq == 0) { // Share gradients and samples for shared ABF. replica_share(); @@ -487,10 +492,10 @@ int colvarbias_abf::update() eabf_UI.update(cvm::step_absolute(), x, y); } - /// Add the bias energy for 1D ABF - bias_energy = calc_energy(NULL); + /// Compute the bias energy + int error_code = calc_energy(NULL); - return COLVARS_OK; + return error_code; } @@ -570,83 +575,71 @@ int colvarbias_abf::replica_share() { last_samples->copy_grid(*samples); shared_last_step = cvm::step_absolute(); + if (b_integrate) { + // Update divergence to account for newly shared gradients + pmf->set_div(); + } return COLVARS_OK; } - -void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool append) -{ - std::string samples_out_name = prefix + ".count"; - std::string gradients_out_name = prefix + ".grad"; - std::ios::openmode mode = (append ? std::ios::app : std::ios::out); - - std::ostream *samples_os = - cvm::proxy->output_stream(samples_out_name, mode); - if (!samples_os) return; - samples->write_multicol(*samples_os); - cvm::proxy->close_output_stream(samples_out_name); - - // In dimension higher than 2, dx is easier to handle and visualize - if (num_variables() > 2) { - std::string samples_dx_out_name = prefix + ".count.dx"; - std::ostream *samples_dx_os = cvm::proxy->output_stream(samples_dx_out_name, mode); - if (!samples_os) return; - samples->write_opendx(*samples_dx_os); - *samples_dx_os << std::endl; - cvm::proxy->close_output_stream(samples_dx_out_name); +template int colvarbias_abf::write_grid_to_file(T const *grid, + std::string const &filename, + bool close) { + std::ostream *os = cvm::proxy->output_stream(filename); + if (!os) { + return cvm::error("Error opening file " + filename + " for writing.\n", COLVARS_ERROR | FILE_ERROR); + } + grid->write_multicol(*os); + if (close) { + cvm::proxy->close_output_stream(filename); + } else { + // Insert empty line between frames in history files + *os << std::endl; + cvm::proxy->flush_output_stream(os); } - std::ostream *gradients_os = - cvm::proxy->output_stream(gradients_out_name, mode); - if (!gradients_os) return; - gradients->write_multicol(*gradients_os); - cvm::proxy->close_output_stream(gradients_out_name); + // In dimension higher than 2, dx is easier to handle and visualize + // but we cannot write multiple frames in a dx file now + // (could be implemented as multiple dx files) + if (num_variables() > 2 && close) { + std::string dx = filename + ".dx"; + std::ostream *dx_os = cvm::proxy->output_stream(dx); + if (!dx_os) { + return cvm::error("Error opening file " + dx + " for writing.\n", COLVARS_ERROR | FILE_ERROR); + } + grid->write_opendx(*dx_os); + // if (close) { + cvm::proxy->close_output_stream(dx); + // } + // else { + // // TODO, decide convention for multiple datasets in dx file + // *dx_os << std::endl; + // dx_os->flush(); + // } + } + return COLVARS_OK; +} + + +void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool close) +{ + write_grid_to_file(samples, prefix + ".count", close); + write_grid_to_file(gradients, prefix + ".grad", close); if (b_integrate) { // Do numerical integration (to high precision) and output a PMF cvm::real err; - pmf->integrate(integrate_initial_iterations, integrate_initial_tol, err); + pmf->integrate(integrate_iterations, integrate_tol, err); pmf->set_zero_minimum(); - - std::string pmf_out_name = prefix + ".pmf"; - std::ostream *pmf_os = cvm::proxy->output_stream(pmf_out_name, mode); - if (!pmf_os) return; - pmf->write_multicol(*pmf_os); - - // In dimension higher than 2, dx is easier to handle and visualize - if (num_variables() > 2) { - std::string pmf_dx_out_name = prefix + ".pmf.dx"; - std::ostream *pmf_dx_os = cvm::proxy->output_stream(pmf_dx_out_name, mode); - if (!pmf_dx_os) return; - pmf->write_opendx(*pmf_dx_os); - *pmf_dx_os << std::endl; - cvm::proxy->close_output_stream(pmf_dx_out_name); - } - - *pmf_os << std::endl; - cvm::proxy->close_output_stream(pmf_out_name); + write_grid_to_file(pmf, prefix + ".pmf", close); } if (b_CZAR_estimator) { // Write eABF CZAR-related quantities - - std::string z_samples_out_name = prefix + ".zcount"; - - std::ostream *z_samples_os = - cvm::proxy->output_stream(z_samples_out_name, mode); - if (!z_samples_os) return; - z_samples->write_multicol(*z_samples_os); - cvm::proxy->close_output_stream(z_samples_out_name); - + write_grid_to_file(z_samples, prefix + ".zcount", close); if (b_czar_window_file) { - std::string z_gradients_out_name = prefix + ".zgrad"; - - std::ostream *z_gradients_os = - cvm::proxy->output_stream(z_gradients_out_name, mode); - if (!z_gradients_os) return; - z_gradients->write_multicol(*z_gradients_os); - cvm::proxy->close_output_stream(z_gradients_out_name); + write_grid_to_file(z_gradients, prefix + ".zgrad", close); } // Calculate CZAR estimator of gradients @@ -657,39 +650,15 @@ void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool app - cvm::temperature() * cvm::boltzmann() * z_samples->log_gradient_finite_diff(ix, n), n); } } - - std::string czar_gradients_out_name = prefix + ".czar.grad"; - - std::ostream *czar_gradients_os = - cvm::proxy->output_stream(czar_gradients_out_name, mode); - if (!czar_gradients_os) return; - czar_gradients->write_multicol(*czar_gradients_os); - cvm::proxy->close_output_stream(czar_gradients_out_name); + write_grid_to_file(czar_gradients, prefix + ".czar.grad", close); if (b_integrate) { // Do numerical integration (to high precision) and output a PMF cvm::real err; czar_pmf->set_div(); - czar_pmf->integrate(integrate_initial_iterations, integrate_initial_tol, err); + czar_pmf->integrate(integrate_iterations, integrate_tol, err); czar_pmf->set_zero_minimum(); - - std::string czar_pmf_out_name = prefix + ".czar.pmf"; - std::ostream *czar_pmf_os = cvm::proxy->output_stream(czar_pmf_out_name, mode); - if (!czar_pmf_os) return; - czar_pmf->write_multicol(*czar_pmf_os); - - // In dimension higher than 2, dx is easier to handle and visualize - if (num_variables() > 2) { - std::string czar_pmf_dx_out_name = prefix + ".czar.pmf.dx"; - std::ostream *czar_pmf_dx_os = cvm::proxy->output_stream(czar_pmf_dx_out_name, mode); - if (!czar_pmf_dx_os) return; - czar_pmf->write_opendx(*czar_pmf_dx_os); - *czar_pmf_dx_os << std::endl; - cvm::proxy->close_output_stream(czar_pmf_dx_out_name); - } - - *czar_pmf_os << std::endl; - cvm::proxy->close_output_stream(czar_pmf_out_name); + write_grid_to_file(czar_pmf, prefix + ".czar.pmf", close); } } return; @@ -836,25 +805,56 @@ std::istream & colvarbias_abf::read_state_data(std::istream& is) return is; } + int colvarbias_abf::write_output_files() { + if (cvm::debug()) { + cvm::log("ABF bias trying to write gradients and samples to disk"); + } + + if (shared_on && cvm::main()->proxy->replica_index() > 0) { + // No need to report the same data as replica 0, let it do the I/O job + return COLVARS_OK; + } + write_gradients_samples(output_prefix); + if (b_history_files) { + if ((cvm::step_absolute() % history_freq) == 0) { + write_gradients_samples(output_prefix + ".hist", false); + } + } + + if (b_UI_estimator) { + eabf_UI.calc_pmf(); + eabf_UI.write_files(); + } + return COLVARS_OK; } + int colvarbias_abf::calc_energy(std::vector const *values) { - if (values) { - return cvm::error("colvarbias_abf::calc_energy() with an argument " - "is currently not implemented.\n", - COLVARS_NOT_IMPLEMENTED); - } + bias_energy = 0.0; // default value, overridden if a value can be calculated - if (num_variables() != 1) return 0.0; + if (num_variables() > 1 || values != NULL) { + // Use simple estimate: neglect effect of fullSamples, + // return value at center of bin + if (pmf != NULL) { + std::vector const curr_bin = values ? + pmf->get_colvars_index(*values) : + pmf->get_colvars_index(); + + if (pmf->index_ok(curr_bin)) { + bias_energy = pmf->value(curr_bin); + } + } + return COLVARS_OK; + } // Get the home bin. int home0 = gradients->current_bin_scalar(0); - if (home0 < 0) return 0.0; + if (home0 < 0) return COLVARS_OK; int gradient_len = (int)(gradients->number_of_points(0)); int home = (home0 < gradient_len) ? home0 : (gradient_len-1); @@ -886,5 +886,6 @@ int colvarbias_abf::calc_energy(std::vector const *values) sum += fact*gradients->value(ix)/count*gradients->widths[0]*frac; // The applied potential is the negative integral of force samples. - return -sum; + bias_energy = -sum; + return COLVARS_OK; } diff --git a/lib/colvars/colvarbias_abf.h b/lib/colvars/colvarbias_abf.h index 1939b61a8b..15c81e9466 100644 --- a/lib/colvars/colvarbias_abf.h +++ b/lib/colvars/colvarbias_abf.h @@ -15,6 +15,7 @@ #include #include +#include "colvarproxy.h" #include "colvarbias.h" #include "colvargrid.h" #include "colvar_UIestimator.h" @@ -56,8 +57,6 @@ private: size_t full_samples; /// Number of samples per bin before applying a scaled-down biasing force size_t min_samples; - /// frequency for updating output files - int output_freq; /// Write combined files with a history of all output data? bool b_history_files; /// Write CZAR output file for stratified eABF (.zgrad) @@ -74,13 +73,13 @@ private: /// Frequency for updating pABF PMF (if zero, pABF is not used) int pabf_freq; /// Max number of CG iterations for integrating PMF at startup and for file output - int integrate_initial_iterations; - /// Tolerance for integrating PMF at startup and for file output - cvm::real integrate_initial_tol; - /// Max number of CG iterations for integrating PMF at on-the-fly pABF updates int integrate_iterations; - /// Tolerance for integrating PMF at on-the-fly pABF updates + /// Tolerance for integrating PMF at startup and for file output cvm::real integrate_tol; + /// Max number of CG iterations for integrating PMF at on-the-fly pABF updates + int pabf_integrate_iterations; + /// Tolerance for integrating PMF at on-the-fly pABF updates + cvm::real pabf_integrate_tol; /// Cap the biasing force to be applied? (option maxForce) bool cap_force; @@ -151,11 +150,16 @@ private: virtual int bin_count(int bin_index); /// Write human-readable FE gradients and sample count, and DX file in dim > 2 - void write_gradients_samples(const std::string &prefix, bool append = false); + void write_gradients_samples(const std::string &prefix, bool close = true); /// Read human-readable FE gradients and sample count (if not using restart) void read_gradients_samples(); + /// Template used in write_gradient_samples() + template int write_grid_to_file(T const *grid, + std::string const &name, + bool close); + virtual std::istream& read_state_data(std::istream&); virtual std::ostream& write_state_data(std::ostream&); virtual int write_output_files(); diff --git a/lib/colvars/colvarbias_histogram.cpp b/lib/colvars/colvarbias_histogram.cpp index 92985b0f61..3efe0b0acc 100644 --- a/lib/colvars/colvarbias_histogram.cpp +++ b/lib/colvars/colvarbias_histogram.cpp @@ -30,9 +30,10 @@ int colvarbias_histogram::init(std::string const &conf) size_t i; - get_keyval(conf, "outputFile", out_name, std::string("")); - get_keyval(conf, "outputFileDX", out_name_dx, std::string("")); - get_keyval(conf, "outputFreq", output_freq, cvm::restart_out_freq); + get_keyval(conf, "outputFile", out_name, ""); + // Write DX file by default only in dimension >= 3 + std::string default_name_dx = this->num_variables() > 2 ? "" : "none"; + get_keyval(conf, "outputFileDX", out_name_dx, default_name_dx); /// with VMD, this may not be an error // if ( output_freq == 0 ) { @@ -146,8 +147,10 @@ int colvarbias_histogram::update() bin[i] = grid->current_bin_scalar(i); } - if (grid->index_ok(bin)) { - grid->acc_value(bin, 1.0); + if (can_accumulate_data()) { + if (grid->index_ok(bin)) { + grid->acc_value(bin, 1.0); + } } } else { // update indices for vector/array values @@ -163,10 +166,6 @@ int colvarbias_histogram::update() } } - if (output_freq && (cvm::step_absolute() % output_freq) == 0) { - write_output_files(); - } - error_code |= cvm::get_error(); return error_code; } @@ -179,7 +178,7 @@ int colvarbias_histogram::write_output_files() return COLVARS_OK; } - if (out_name.size()) { + if (out_name.size() && out_name != "none") { cvm::log("Writing the histogram file \""+out_name+"\".\n"); cvm::backup_file(out_name.c_str()); std::ostream *grid_os = cvm::proxy->output_stream(out_name); @@ -191,7 +190,7 @@ int colvarbias_histogram::write_output_files() cvm::proxy->close_output_stream(out_name); } - if (out_name_dx.size()) { + if (out_name_dx.size() && out_name_dx != "none") { cvm::log("Writing the histogram file \""+out_name_dx+"\".\n"); cvm::backup_file(out_name_dx.c_str()); std::ostream *grid_os = cvm::proxy->output_stream(out_name_dx); diff --git a/lib/colvars/colvarbias_meta.cpp b/lib/colvars/colvarbias_meta.cpp index 05f293d872..d448b1f2e4 100644 --- a/lib/colvars/colvarbias_meta.cpp +++ b/lib/colvars/colvarbias_meta.cpp @@ -566,8 +566,8 @@ int colvarbias_meta::update_grid_params() int colvarbias_meta::update_bias() { // add a new hill if the required time interval has passed - if ((cvm::step_absolute() % new_hill_freq) == 0 && - is_enabled(f_cvb_history_dependent)) { + if (((cvm::step_absolute() % new_hill_freq) == 0) && + can_accumulate_data() && is_enabled(f_cvb_history_dependent)) { if (cvm::debug()) { cvm::log("Metadynamics bias \""+this->name+"\""+ @@ -883,7 +883,7 @@ void colvarbias_meta::project_hills(colvarbias_meta::hill_iter h_first, // TODO: improve it by looping over a small subgrid instead of the whole grid - std::vector colvar_values(num_variables()); + std::vector new_colvar_values(num_variables()); std::vector colvar_forces_scalar(num_variables()); std::vector he_ix = he->new_index(); @@ -902,17 +902,17 @@ void colvarbias_meta::project_hills(colvarbias_meta::hill_iter h_first, count++) { size_t i; for (i = 0; i < num_variables(); i++) { - colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); + new_colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); } // loop over the hills and increment the energy grid locally hills_energy_here = 0.0; - calc_hills(h_first, h_last, hills_energy_here, &colvar_values); + calc_hills(h_first, h_last, hills_energy_here, &new_colvar_values); he->acc_value(he_ix, hills_energy_here); for (i = 0; i < num_variables(); i++) { hills_forces_here[i].reset(); - calc_hills_force(i, h_first, h_last, hills_forces_here, &colvar_values); + calc_hills_force(i, h_first, h_last, hills_forces_here, &new_colvar_values); colvar_forces_scalar[i] = hills_forces_here[i].real_value; } hg->acc_force(hg_ix, &(colvar_forces_scalar.front())); @@ -935,16 +935,18 @@ void colvarbias_meta::project_hills(colvarbias_meta::hill_iter h_first, } else { + // TODO delete this (never used) + // simpler version, with just the energy for ( ; (he->index_ok(he_ix)); ) { for (size_t i = 0; i < num_variables(); i++) { - colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); + new_colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); } hills_energy_here = 0.0; - calc_hills(h_first, h_last, hills_energy_here, &colvar_values); + calc_hills(h_first, h_last, hills_energy_here, &new_colvar_values); he->acc_value(he_ix, hills_energy_here); he->incr(he_ix); @@ -1240,7 +1242,7 @@ void colvarbias_meta::read_replica_files() // test whether this is the end of the file is.seekg(0, std::ios::end); - if (is.tellg() > (replicas[ir])->replica_hills_file_pos+1) { + if (is.tellg() > (replicas[ir])->replica_hills_file_pos + ((std::streampos) 1)) { (replicas[ir])->update_status++; } else { (replicas[ir])->update_status = 0; @@ -1324,7 +1326,7 @@ std::istream & colvarbias_meta::read_state_data(std::istream& is) hills_energy_gradients = new colvar_grid_gradient(colvars); } - size_t const hills_energy_pos = is.tellg(); + std::streampos const hills_energy_pos = is.tellg(); std::string key; if (!(is >> key)) { if (hills_energy_backup != NULL) { @@ -1363,7 +1365,7 @@ std::istream & colvarbias_meta::read_state_data(std::istream& is) } } - size_t const hills_energy_gradients_pos = is.tellg(); + std::streampos const hills_energy_gradients_pos = is.tellg(); if (!(is >> key)) { if (hills_energy_backup != NULL) { delete hills_energy; @@ -1511,7 +1513,7 @@ std::istream & colvarbias_meta::read_hill(std::istream &is) { if (!is) return is; // do nothing if failbit is set - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); size_t i = 0; std::string data; @@ -1958,11 +1960,12 @@ colvarbias_meta::hill::hill(cvm::step_number it_in, colvarbias_meta::hill::hill(colvarbias_meta::hill const &h) - : sW(1.0), + : it(h.it), + hill_value(0.0), + sW(1.0), W(h.W), centers(h.centers), sigmas(h.sigmas), - it(h.it), replica(h.replica) {} diff --git a/lib/colvars/colvarbias_meta.h b/lib/colvars/colvarbias_meta.h index 9f9fc63fc7..2f34abcc77 100644 --- a/lib/colvars/colvarbias_meta.h +++ b/lib/colvars/colvarbias_meta.h @@ -257,7 +257,7 @@ protected: std::string replica_hills_file; /// Position within replica_hills_file (when reading it) - int replica_hills_file_pos; + std::streampos replica_hills_file_pos; }; diff --git a/lib/colvars/colvarcomp.cpp b/lib/colvars/colvarcomp.cpp index 05d1195d58..a1542d05bf 100644 --- a/lib/colvars/colvarcomp.cpp +++ b/lib/colvars/colvarcomp.cpp @@ -169,7 +169,7 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf, group->check_keywords(group_conf, group_key); if (cvm::get_error()) { cvm::error("Error parsing definition for atom group \""+ - std::string(group_key)+"\"\n.", INPUT_ERROR); + std::string(group_key)+"\".", INPUT_ERROR); } cvm::decrease_depth(); @@ -200,40 +200,40 @@ int colvar::cvc::init_dependencies() { init_feature(f_cvc_periodic, "periodic", f_type_static); - init_feature(f_cvc_width, "defined width", f_type_static); + init_feature(f_cvc_width, "defined_width", f_type_static); - init_feature(f_cvc_lower_boundary, "defined lower boundary", f_type_static); + init_feature(f_cvc_lower_boundary, "defined_lower_boundary", f_type_static); - init_feature(f_cvc_upper_boundary, "defined upper boundary", f_type_static); + init_feature(f_cvc_upper_boundary, "defined_upper_boundary", f_type_static); init_feature(f_cvc_gradient, "gradient", f_type_dynamic); - init_feature(f_cvc_explicit_gradient, "explicit gradient", f_type_static); + init_feature(f_cvc_explicit_gradient, "explicit_gradient", f_type_static); require_feature_children(f_cvc_explicit_gradient, f_ag_explicit_gradient); - init_feature(f_cvc_inv_gradient, "inverse gradient", f_type_dynamic); + init_feature(f_cvc_inv_gradient, "inverse_gradient", f_type_dynamic); require_feature_self(f_cvc_inv_gradient, f_cvc_gradient); - init_feature(f_cvc_debug_gradient, "debug gradient", f_type_user); + init_feature(f_cvc_debug_gradient, "debug_gradient", f_type_user); require_feature_self(f_cvc_debug_gradient, f_cvc_gradient); require_feature_self(f_cvc_debug_gradient, f_cvc_explicit_gradient); - init_feature(f_cvc_Jacobian, "Jacobian derivative", f_type_dynamic); + init_feature(f_cvc_Jacobian, "Jacobian_derivative", f_type_dynamic); require_feature_self(f_cvc_Jacobian, f_cvc_inv_gradient); // Compute total force on first site only to avoid unwanted // coupling to other colvars (see e.g. Ciccotti et al., 2005) - init_feature(f_cvc_one_site_total_force, "compute total force from one group", f_type_user); + init_feature(f_cvc_one_site_total_force, "total_force_from_one_group", f_type_user); require_feature_self(f_cvc_one_site_total_force, f_cvc_com_based); - init_feature(f_cvc_com_based, "depends on group centers of mass", f_type_static); + init_feature(f_cvc_com_based, "function_of_centers_of_mass", f_type_static); - init_feature(f_cvc_pbc_minimum_image, "use minimum-image distances with PBCs", f_type_user); + init_feature(f_cvc_pbc_minimum_image, "use_minimum-image_with_PBCs", f_type_user); - init_feature(f_cvc_scalable, "scalable calculation", f_type_static); + init_feature(f_cvc_scalable, "scalable_calculation", f_type_static); require_feature_self(f_cvc_scalable, f_cvc_scalable_com); - init_feature(f_cvc_scalable_com, "scalable calculation of centers of mass", f_type_static); + init_feature(f_cvc_scalable_com, "scalable_calculation_of_centers_of_mass", f_type_static); require_feature_self(f_cvc_scalable_com, f_cvc_com_based); @@ -626,6 +626,7 @@ void colvar::cvc::wrap(colvarvalue & /* x_unwrapped */) const } + // Static members std::vector colvar::cvc::cvc_features; diff --git a/lib/colvars/colvarcomp.h b/lib/colvars/colvarcomp.h index e405f4c9b1..57df68ab6e 100644 --- a/lib/colvars/colvarcomp.h +++ b/lib/colvars/colvarcomp.h @@ -1358,8 +1358,14 @@ protected: cvm::atom_group *atoms; /// Reference coordinates (for RMSD calculation only) + /// Includes sets with symmetry permutations (n_permutations * n_atoms) std::vector ref_pos; + /// Number of permutations of symmetry-related atoms + size_t n_permutations; + + /// Index of the permutation yielding the smallest RMSD (0 for identity) + size_t best_perm_index; public: /// Constructor @@ -1487,8 +1493,6 @@ class colvar::linearCombination : public colvar::cvc { protected: - /// Map from string to the types of colvar components - std::map> string_cv_map; /// Sub-colvar components std::vector cv; /// If all sub-cvs use explicit gradients then we also use it @@ -1508,8 +1512,6 @@ class colvar::CVBasedPath : public colvar::cvc { protected: - /// Map from string to the types of colvar components - std::map> string_cv_map; /// Sub-colvar components std::vector cv; /// Reference colvar values from path @@ -1661,6 +1663,33 @@ public: #endif // C++11 checking + +// \brief Colvar component: total value of a scalar map +// (usually implemented as a grid by the simulation engine) +class colvar::map_total + : public colvar::cvc +{ +public: + + map_total(); + map_total(std::string const &conf); + virtual ~map_total() {} + virtual int init(std::string const &conf); + virtual void calc_value(); + virtual void calc_gradients(); + virtual void apply_force(colvarvalue const &force); + +protected: + + /// Identifier of the map object (as used by the simulation engine) + std::string map_name; + + /// Index of the map objet in the proxy arrays + int volmap_index; +}; + + + // metrics functions for cvc implementations // simple definitions of the distance functions; these are useful only @@ -1691,6 +1720,6 @@ public: { \ return this->dist2_lgrad(x2, x1); \ } \ - \ + #endif diff --git a/lib/colvars/colvarcomp_distances.cpp b/lib/colvars/colvarcomp_distances.cpp index c3c1ee55d5..1b1b295ff1 100644 --- a/lib/colvars/colvarcomp_distances.cpp +++ b/lib/colvars/colvarcomp_distances.cpp @@ -7,6 +7,8 @@ // If you wish to distribute your changes, please submit them to the // Colvars repository at GitHub. +#include + #include "colvarmodule.h" #include "colvarvalue.h" #include "colvarparse.h" @@ -1045,6 +1047,44 @@ colvar::rmsd::rmsd(std::string const &conf) // this is only required for ABF, but we do both groups here for better caching atoms->rot.request_group2_gradients(atoms->size()); } + + std::string perm_conf; + size_t pos = 0; // current position in config string + n_permutations = 1; + + while (key_lookup(conf, "atomPermutation", &perm_conf, &pos)) { + std::vector perm; + if (perm_conf.size()) { + std::istringstream is(perm_conf); + size_t index; + while (is >> index) { + std::vector const &ids = atoms->ids(); + size_t const ia = std::find(ids.begin(), ids.end(), index-1) - ids.begin(); + if (ia == atoms->size()) { + cvm::error("Error: atom id " + cvm::to_str(index) + + " is not a member of group \"atoms\"."); + return; + } + if (std::find(perm.begin(), perm.end(), ia) != perm.end()) { + cvm::error("Error: atom id " + cvm::to_str(index) + + " is mentioned more than once in atomPermutation list."); + return; + } + perm.push_back(ia); + } + if (perm.size() != atoms->size()) { + cvm::error("Error: symmetry permutation in input contains " + cvm::to_str(perm.size()) + + " indices, but group \"atoms\" contains " + cvm::to_str(atoms->size()) + " atoms."); + return; + } + cvm::log("atomPermutation = " + cvm::to_str(perm)); + n_permutations++; + // Record a copy of reference positions in new order + for (size_t ia = 0; ia < atoms->size(); ia++) { + ref_pos.push_back(ref_pos[perm[ia]]); + } + } + } } @@ -1056,6 +1096,20 @@ void colvar::rmsd::calc_value() for (size_t ia = 0; ia < atoms->size(); ia++) { x.real_value += ((*atoms)[ia].pos - ref_pos[ia]).norm2(); } + best_perm_index = 0; + + // Compute sum of squares for each symmetry permutation of atoms, keep the smallest + size_t ref_pos_index = atoms->size(); + for (size_t ip = 1; ip < n_permutations; ip++) { + cvm::real value = 0.0; + for (size_t ia = 0; ia < atoms->size(); ia++) { + value += ((*atoms)[ia].pos - ref_pos[ref_pos_index++]).norm2(); + } + if (value < x.real_value) { + x.real_value = value; + best_perm_index = ip; + } + } x.real_value /= cvm::real(atoms->size()); // MSD x.real_value = cvm::sqrt(x.real_value); } @@ -1067,8 +1121,10 @@ void colvar::rmsd::calc_gradients() 0.5 / (x.real_value * cvm::real(atoms->size())) : 0.0; + // Use the appropriate symmetry permutation of reference positions to calculate gradients + size_t const start = atoms->size() * best_perm_index; for (size_t ia = 0; ia < atoms->size(); ia++) { - (*atoms)[ia].grad = (drmsddx2 * 2.0 * ((*atoms)[ia].pos - ref_pos[ia])); + (*atoms)[ia].grad = (drmsddx2 * 2.0 * ((*atoms)[ia].pos - ref_pos[start + ia])); } } diff --git a/lib/colvars/colvarcomp_gpath.cpp b/lib/colvars/colvarcomp_gpath.cpp index d563403628..8849f9dbe4 100644 --- a/lib/colvars/colvarcomp_gpath.cpp +++ b/lib/colvars/colvarcomp_gpath.cpp @@ -19,10 +19,6 @@ #include "colvar.h" #include "colvarcomp.h" -namespace GeometricPathCV { -void init_string_cv_map(std::map>& string_cv_map); -} - bool compareColvarComponent(colvar::cvc *i, colvar::cvc *j) { return i->name < j->name; @@ -406,9 +402,8 @@ void colvar::gzpath::apply_force(colvarvalue const &force) { } colvar::linearCombination::linearCombination(std::string const &conf): cvc(conf) { - GeometricPathCV::init_string_cv_map(string_cv_map); // Lookup all available sub-cvcs - for (auto it_cv_map = string_cv_map.begin(); it_cv_map != string_cv_map.end(); ++it_cv_map) { + for (auto it_cv_map = colvar::get_global_cvc_map().begin(); it_cv_map != colvar::get_global_cvc_map().end(); ++it_cv_map) { if (key_lookup(conf, it_cv_map->first.c_str())) { std::vector sub_cvc_confs; get_key_string_multi_value(conf, it_cv_map->first.c_str(), sub_cvc_confs); @@ -506,9 +501,8 @@ void colvar::linearCombination::apply_force(colvarvalue const &force) { } colvar::CVBasedPath::CVBasedPath(std::string const &conf): cvc(conf) { - GeometricPathCV::init_string_cv_map(string_cv_map); // Lookup all available sub-cvcs - for (auto it_cv_map = string_cv_map.begin(); it_cv_map != string_cv_map.end(); ++it_cv_map) { + for (auto it_cv_map = colvar::get_global_cvc_map().begin(); it_cv_map != colvar::get_global_cvc_map().end(); ++it_cv_map) { if (key_lookup(conf, it_cv_map->first.c_str())) { std::vector sub_cvc_confs; get_key_string_multi_value(conf, it_cv_map->first.c_str(), sub_cvc_confs); @@ -909,33 +903,4 @@ void colvar::gzpathCV::apply_force(colvarvalue const &force) { } } -void GeometricPathCV::init_string_cv_map(std::map>& string_cv_map) { - string_cv_map["distance"] = [](const std::string& conf){return new colvar::distance(conf);}; - string_cv_map["dihedral"] = [](const std::string& conf){return new colvar::dihedral(conf);}; - string_cv_map["angle"] = [](const std::string& conf){return new colvar::angle(conf);}; - string_cv_map["rmsd"] = [](const std::string& conf){return new colvar::rmsd(conf);}; - string_cv_map["gyration"] = [](const std::string& conf){return new colvar::gyration(conf);}; - string_cv_map["inertia"] = [](const std::string& conf){return new colvar::inertia(conf);}; - string_cv_map["inertiaZ"] = [](const std::string& conf){return new colvar::inertia_z(conf);}; - string_cv_map["tilt"] = [](const std::string& conf){return new colvar::tilt(conf);}; - string_cv_map["distanceZ"] = [](const std::string& conf){return new colvar::distance_z(conf);}; - string_cv_map["distanceXY"] = [](const std::string& conf){return new colvar::distance_xy(conf);}; - string_cv_map["polarTheta"] = [](const std::string& conf){return new colvar::polar_theta(conf);}; - string_cv_map["polarPhi"] = [](const std::string& conf){return new colvar::polar_phi(conf);}; - string_cv_map["distanceVec"] = [](const std::string& conf){return new colvar::distance_vec(conf);}; - string_cv_map["orientationAngle"] = [](const std::string& conf){return new colvar::orientation_angle(conf);}; - string_cv_map["distancePairs"] = [](const std::string& conf){return new colvar::distance_pairs(conf);}; - string_cv_map["dipoleMagnitude"] = [](const std::string& conf){return new colvar::dipole_magnitude(conf);}; - string_cv_map["coordNum"] = [](const std::string& conf){return new colvar::coordnum(conf);}; - string_cv_map["selfCoordNum"] = [](const std::string& conf){return new colvar::selfcoordnum(conf);}; - string_cv_map["dipoleAngle"] = [](const std::string& conf){return new colvar::dipole_angle(conf);}; - string_cv_map["orientation"] = [](const std::string& conf){return new colvar::orientation(conf);}; - string_cv_map["orientationProj"] = [](const std::string& conf){return new colvar::orientation_proj(conf);}; - string_cv_map["eigenvector"] = [](const std::string& conf){return new colvar::eigenvector(conf);}; - string_cv_map["cartesian"] = [](const std::string& conf){return new colvar::cartesian(conf);}; - string_cv_map["alpha"] = [](const std::string& conf){return new colvar::alpha_angles(conf);}; - string_cv_map["dihedralPC"] = [](const std::string& conf){return new colvar::dihedPC(conf);}; - string_cv_map["linearCombination"] = [](const std::string& conf){return new colvar::linearCombination(conf);}; -} - #endif diff --git a/lib/colvars/colvarcomp_volmaps.cpp b/lib/colvars/colvarcomp_volmaps.cpp new file mode 100644 index 0000000000..8ea2b76de4 --- /dev/null +++ b/lib/colvars/colvarcomp_volmaps.cpp @@ -0,0 +1,60 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + +#include "colvarmodule.h" +#include "colvarvalue.h" +#include "colvarparse.h" +#include "colvar.h" +#include "colvarcomp.h" + + + +colvar::map_total::map_total() + : cvc(), volmap_index(-1) +{ + function_type = "map_total"; + x.type(colvarvalue::type_scalar); +} + + +colvar::map_total::map_total(std::string const &conf) + : cvc(), volmap_index(-1) +{ + function_type = "map_total"; + x.type(colvarvalue::type_scalar); + map_total::init(conf); +} + + +int colvar::map_total::init(std::string const &conf) +{ + int error_code = cvc::init(conf); + get_keyval(conf, "mapName", map_name, map_name); + volmap_index = (cvm::proxy)->init_volmap(map_name); + error_code |= volmap_index > 0 ? COLVARS_OK : INPUT_ERROR; + return error_code; +} + + +void colvar::map_total::calc_value() +{ + x.real_value = (cvm::proxy)->get_volmap_value(volmap_index); +} + + +void colvar::map_total::calc_gradients() +{ + // Atomic coordinates are not available here +} + + +void colvar::map_total::apply_force(colvarvalue const &force) +{ + (cvm::proxy)->apply_volmap_force(volmap_index, force.real_value); +} diff --git a/lib/colvars/colvardeps.cpp b/lib/colvars/colvardeps.cpp index f83458b51c..94c5cfbda7 100644 --- a/lib/colvars/colvardeps.cpp +++ b/lib/colvars/colvardeps.cpp @@ -115,7 +115,9 @@ bool colvardeps::get_keyval_feature(colvarparse *cvp, } bool value; bool const found = cvp->get_keyval(conf, key, value, def_value, parse_mode); - if (value) enable(feature_id); + // If the default value is on, this function should be able to disable the feature! + set_enabled(feature_id, value); + return found; } diff --git a/lib/colvars/colvardeps.h b/lib/colvars/colvardeps.h index 63669536fe..f4f543f336 100644 --- a/lib/colvars/colvardeps.h +++ b/lib/colvars/colvardeps.h @@ -227,6 +227,8 @@ public: f_cvb_active, /// \brief Bias is awake (active on its own accord) this timestep f_cvb_awake, + /// Accumulates data starting from step 0 of a simulation run + f_cvb_step_zero_data, /// \brief will apply forces f_cvb_apply_force, /// \brief force this bias to act on actual value for extended-Lagrangian coordinates @@ -302,6 +304,10 @@ public: f_cv_hard_lower_boundary, /// \brief The upper boundary is not defined from user's choice f_cv_hard_upper_boundary, + /// \brief Reflecting lower boundary condition + f_cv_reflecting_lower_boundary, + /// \brief Reflecting upper boundary condition + f_cv_reflecting_upper_boundary, /// \brief Provide a discretization of the values of the colvar to /// be used by the biases or in analysis (needs lower and upper /// boundary) diff --git a/lib/colvars/colvargrid.h b/lib/colvars/colvargrid.h index 314a92b8c6..427e5b0825 100644 --- a/lib/colvars/colvargrid.h +++ b/lib/colvars/colvargrid.h @@ -239,19 +239,21 @@ public: } /// \brief Constructor from a vector of colvars + /// \param add_extra_bin requests that non-periodic dimensions are extended + /// by 1 bin to accommodate the integral (PMF) of another gridded quantity (gradient) colvar_grid(std::vector const &colvars, T const &t = T(), size_t mult_i = 1, - bool margin = false) + bool add_extra_bin = false) : has_data(false) { - this->init_from_colvars(colvars, t, mult_i, margin); + this->init_from_colvars(colvars, t, mult_i, add_extra_bin); } int init_from_colvars(std::vector const &colvars, T const &t = T(), size_t mult_i = 1, - bool margin = false) + bool add_extra_bin = false) { if (cvm::debug()) { cvm::log("Reading grid configuration from collective variables.\n"); @@ -299,7 +301,7 @@ public: use_actual_value[i-1] = true; } - if (margin) { + if (add_extra_bin) { if (periodic[i]) { // Shift the grid by half the bin width (values at edges instead of center of bins) lower_boundaries.push_back(cv[i]->lower_boundary.real_value - 0.5 * widths[i]); @@ -699,7 +701,7 @@ public: } if (scale_factor != 1.0) for (size_t i = 0; i < data.size(); i++) { - data[i] += scale_factor * other_grid.data[i]; + data[i] += static_cast(scale_factor * other_grid.data[i]); } else // skip multiplication if possible @@ -712,7 +714,7 @@ public: /// \brief Return the value suitable for output purposes (so that it /// may be rescaled or manipulated without changing it permanently) virtual inline T value_output(std::vector const &ix, - size_t const &imult = 0) + size_t const &imult = 0) const { return value(ix, imult); } @@ -820,6 +822,8 @@ public: std::vector old_nx = nx; std::vector old_lb = lower_boundaries; + std::vector old_ub = upper_boundaries; + std::vector old_w = widths; { size_t nd_in = 0; @@ -858,12 +862,15 @@ public: if (! periodic.size()) periodic.assign(nd, false); if (! widths.size()) widths.assign(nd, 1.0); + cvm::real eps = 1.e-10; + bool new_params = false; if (old_nx.size()) { for (size_t i = 0; i < nd; i++) { - if ( (old_nx[i] != nx[i]) || - (cvm::sqrt(cv[i]->dist2(old_lb[i], - lower_boundaries[i])) > 1.0E-10) ) { + if (old_nx[i] != nx[i] || + cvm::sqrt(cv[i]->dist2(old_lb[i], lower_boundaries[i])) > eps || + cvm::sqrt(cv[i]->dist2(old_ub[i], upper_boundaries[i])) > eps || + cvm::fabs(old_w[i] - widths[i]) > eps) { new_params = true; } } @@ -928,7 +935,7 @@ public: /// \brief Read grid entry in restart file std::istream & read_restart(std::istream &is) { - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); std::string key, conf; if ((is >> key) && (key == std::string("grid_parameters"))) { is.seekg(start_pos, std::ios::beg); @@ -955,7 +962,7 @@ public: /// represented in memory /// \param buf_size Number of values per line std::ostream & write_raw(std::ostream &os, - size_t const buf_size = 3) + size_t const buf_size = 3) const { std::streamsize const w = os.width(); std::streamsize const p = os.precision(); @@ -981,7 +988,7 @@ public: /// \brief Read data written by colvar_grid::write_raw() std::istream & read_raw(std::istream &is) { - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); for (std::vector ix = new_index(); index_ok(ix); incr(ix)) { for (size_t imult = 0; imult < mult; imult++) { @@ -1004,7 +1011,7 @@ public: /// \brief Write the grid in a format which is both human readable /// and suitable for visualization e.g. with gnuplot - void write_multicol(std::ostream &os) + void write_multicol(std::ostream &os) const { std::streamsize const w = os.width(); std::streamsize const p = os.precision(); @@ -1145,7 +1152,7 @@ public: /// \brief Write the grid data without labels, as they are /// represented in memory - std::ostream & write_opendx(std::ostream &os) + std::ostream & write_opendx(std::ostream &os) const { // write the header os << "object 1 class gridpositions counts"; @@ -1208,7 +1215,7 @@ public: /// Constructor from a vector of colvars colvar_grid_count(std::vector &colvars, size_t const &def_count = 0, - bool margin = false); + bool add_extra_bin = false); /// Increment the counter at given position inline void incr_count(std::vector const &ix) @@ -1360,7 +1367,7 @@ public: /// Constructor from a vector of colvars colvar_grid_scalar(std::vector &colvars, - bool margin = 0); + bool add_extra_bin = false); /// Accumulate the value inline void acc_value(std::vector const &ix, @@ -1419,9 +1426,9 @@ public: // 100 101 110 111 000 001 010 011 grad[0] = 0.25 * ((p[4] + p[5] + p[6] + p[7]) - (p[0] + p[1] + p[2] + p[3])) / widths[0]; // 010 011 110 111 000 001 100 101 - grad[1] = 0.25 * ((p[2] + p[3] + p[6] + p[7]) - (p[0] + p[1] + p[4] + p[5])) / widths[0]; + grad[1] = 0.25 * ((p[2] + p[3] + p[6] + p[7]) - (p[0] + p[1] + p[4] + p[5])) / widths[1]; // 001 011 101 111 000 010 100 110 - grad[2] = 0.25 * ((p[1] + p[3] + p[5] + p[7]) - (p[0] + p[2] + p[4] + p[6])) / widths[0]; + grad[2] = 0.25 * ((p[1] + p[3] + p[5] + p[7]) - (p[0] + p[2] + p[4] + p[6])) / widths[2]; } else { cvm::error("Finite differences available in dimension 2 and 3 only."); } @@ -1430,7 +1437,7 @@ public: /// \brief Return the value of the function at ix divided by its /// number of samples (if the count grid is defined) virtual cvm::real value_output(std::vector const &ix, - size_t const &imult = 0) + size_t const &imult = 0) const { if (imult > 0) { cvm::error("Error: trying to access a component " @@ -1574,7 +1581,7 @@ public: /// \brief Return the value of the function at ix divided by its /// number of samples (if the count grid is defined) virtual inline cvm::real value_output(std::vector const &ix, - size_t const &imult = 0) + size_t const &imult = 0) const { if (samples) return (samples->value(ix) > 0) ? diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp index 1d5f75bbca..95d42560fc 100644 --- a/lib/colvars/colvarmodule.cpp +++ b/lib/colvars/colvarmodule.cpp @@ -50,7 +50,7 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in) cvm::log("Initializing the collective variables module, version "+ cvm::to_str(COLVARS_VERSION)+".\n"); cvm::log("Please cite Fiorin et al, Mol Phys 2013:\n " - "https://doi.org/10.1080/00268976.2013.813594\n" + "https://dx.doi.org/10.1080/00268976.2013.813594\n" "in any publication based on this calculation.\n"); if (proxy->smp_enabled() == COLVARS_OK) { @@ -80,7 +80,7 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in) colvarmodule::rotation::crossing_threshold = 1.0e-02; cv_traj_freq = 100; - restart_out_freq = proxy->restart_frequency(); + restart_out_freq = proxy->default_restart_frequency(); // by default overwrite the existing trajectory file cv_traj_append = false; @@ -91,7 +91,7 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in) colvarmodule * colvarmodule::main() { - return proxy->colvars; + return proxy ? proxy->colvars : NULL; } @@ -245,9 +245,6 @@ int colvarmodule::parse_config(std::string &conf) // Update any necessary proxy data proxy->setup(); - // configuration might have changed, better redo the labels - cv_traj_write_labels = true; - return get_error(); } @@ -265,6 +262,12 @@ int colvarmodule::append_new_config(std::string const &new_conf) } +void colvarmodule::config_changed() +{ + cv_traj_write_labels = true; +} + + int colvarmodule::parse_global_params(std::string const &conf) { // TODO document and then echo this keyword @@ -332,8 +335,13 @@ int colvarmodule::parse_global_params(std::string const &conf) scripting_after_biases, scripting_after_biases); if (use_scripted_forces && !proxy->force_script_defined) { - return cvm::error("User script for scripted colvar forces not found.", - INPUT_ERROR); + if (proxy->simulation_running()) { + return cvm::error("User script for scripted colvar forces not found.", + INPUT_ERROR); + } else { + // Not necessary if we are not applying biases in a real simulation (eg. VMD) + cvm::log("Warning: User script for scripted colvar forces not found."); + } } return cvm::get_error(); @@ -369,6 +377,11 @@ int colvarmodule::parse_colvars(std::string const &conf) colvar_conf = ""; } + if (pos > 0) { + // One or more new variables were added + config_changed(); + } + if (!colvars.size()) { cvm::log("Warning: no collective variables defined.\n"); } @@ -419,6 +432,10 @@ int colvarmodule::parse_biases_type(std::string const &conf, } bias_conf = ""; } + if (conf_saved_pos > 0) { + // One or more new biases were added + config_changed(); + } return COLVARS_OK; } @@ -656,6 +673,7 @@ std::string colvarmodule::read_colvar(std::string const &name) return ss.str(); } + cvm::real colvarmodule::energy_difference(std::string const &bias_name, std::string const &conf) { @@ -672,75 +690,6 @@ cvm::real colvarmodule::energy_difference(std::string const &bias_name, return energy_diff; } -int colvarmodule::bias_current_bin(std::string const &bias_name) -{ - cvm::increase_depth(); - int ret; - colvarbias *b = bias_by_name(bias_name); - - if (b != NULL) { - ret = b->current_bin(); - } else { - cvm::error("Error: bias not found.\n"); - ret = COLVARS_ERROR; - } - - cvm::decrease_depth(); - return ret; -} - -int colvarmodule::bias_bin_num(std::string const &bias_name) -{ - cvm::increase_depth(); - int ret; - colvarbias *b = bias_by_name(bias_name); - - if (b != NULL) { - ret = b->bin_num(); - } else { - cvm::error("Error: bias not found.\n"); - ret = COLVARS_ERROR; - } - - cvm::decrease_depth(); - return ret; -} - -int colvarmodule::bias_bin_count(std::string const &bias_name, size_t bin_index) -{ - cvm::increase_depth(); - int ret; - colvarbias *b = bias_by_name(bias_name); - - if (b != NULL) { - ret = b->bin_count(bin_index); - } else { - cvm::error("Error: bias not found.\n"); - ret = COLVARS_ERROR; - } - - cvm::decrease_depth(); - return ret; -} - -int colvarmodule::bias_share(std::string const &bias_name) -{ - cvm::increase_depth(); - int ret; - colvarbias *b = bias_by_name(bias_name); - - if (b != NULL) { - b->replica_share(); - ret = COLVARS_OK; - } else { - cvm::error("Error: bias not found.\n"); - ret = COLVARS_ERROR; - } - - cvm::decrease_depth(); - return ret; -} - int colvarmodule::calc() { @@ -753,11 +702,6 @@ int colvarmodule::calc() } error_code |= calc_colvars(); - // set biasing forces to zero before biases are calculated and summed over - for (std::vector::iterator cvi = colvars.begin(); - cvi != colvars.end(); cvi++) { - (*cvi)->reset_bias_force(); - } error_code |= calc_biases(); error_code |= update_colvar_forces(); @@ -768,18 +712,46 @@ int colvarmodule::calc() error_code |= write_traj_files(); } - // write restart files, if needed + // write restart files and similar data if (restart_out_freq && (cvm::step_relative() > 0) && ((cvm::step_absolute() % restart_out_freq) == 0) ) { + if (restart_out_name.size()) { // Write restart file, if different from main output error_code |= write_restart_file(restart_out_name); } else { error_code |= write_restart_file(output_prefix()+".colvars.state"); } - write_output_files(); + + cvm::increase_depth(); + for (std::vector::iterator cvi = colvars.begin(); + cvi != colvars.end(); + cvi++) { + // TODO remove this when corrFunc becomes a bias + error_code |= (*cvi)->write_output_files(); + } + for (std::vector::iterator bi = biases.begin(); + bi != biases.end(); + bi++) { + error_code |= (*bi)->write_state_to_replicas(); + } + cvm::decrease_depth(); } + // Write output files for biases, at the specified frequency for each + cvm::increase_depth(); + for (std::vector::iterator bi = biases.begin(); + bi != biases.end(); + bi++) { + if ((*bi)->output_freq > 0) { + if ((cvm::step_relative() > 0) && + ((cvm::step_absolute() % (*bi)->output_freq) == 0) ) { + error_code |= (*bi)->write_output_files(); + } + } + } + cvm::decrease_depth(); + error_code |= end_of_step(); return error_code; @@ -885,6 +857,12 @@ int colvarmodule::calc_biases() if (cvm::debug() && num_biases()) cvm::log("Updating collective variable biases.\n"); + // set biasing forces to zero before biases are calculated and summed over + for (std::vector::iterator cvi = colvars.begin(); + cvi != colvars.end(); cvi++) { + (*cvi)->reset_bias_force(); + } + std::vector::iterator bi; int error_code = COLVARS_OK; @@ -1031,12 +1009,32 @@ int colvarmodule::write_restart_file(std::string const &out_name) return cvm::error("Error: in writing restart file.\n", FILE_ERROR); } proxy->close_output_stream(out_name); + if (cv_traj_os != NULL) { + // Take the opportunity to flush colvars.traj + proxy->flush_output_stream(cv_traj_os); + } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } +int colvarmodule::write_restart_string(std::string &output) +{ + cvm::log("Saving state to output buffer.\n"); + std::ostringstream os; + if (!write_restart(os)) { + return cvm::error("Error: in writing restart to buffer.\n", FILE_ERROR); + } + output = os.str(); + return COLVARS_OK; +} + + int colvarmodule::write_traj_files() { + if (cvm::debug()) { + cvm::log("colvarmodule::write_traj_files()\n"); + } + if (cv_traj_os == NULL) { if (open_traj_file(cv_traj_name) != COLVARS_OK) { return cvm::get_error(); @@ -1057,14 +1055,11 @@ int colvarmodule::write_traj_files() write_traj(*cv_traj_os); } - if (restart_out_freq && (cv_traj_os != NULL)) { - // flush the trajectory file if we are at the restart frequency - if ( (cvm::step_relative() > 0) && - ((cvm::step_absolute() % restart_out_freq) == 0) ) { - cvm::log("Synchronizing (emptying the buffer of) trajectory file \""+ - cv_traj_name+"\".\n"); - proxy->flush_output_stream(cv_traj_os); - } + if (restart_out_freq && (cv_traj_os != NULL) && + ((cvm::step_absolute() % restart_out_freq) == 0)) { + cvm::log("Synchronizing (emptying the buffer of) trajectory file \""+ + cv_traj_name+"\".\n"); + proxy->flush_output_stream(cv_traj_os); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); @@ -1182,52 +1177,63 @@ int colvarmodule::reset() reset_index_groups(); + proxy->flush_output_streams(); proxy->reset(); - if (cv_traj_os != NULL) { - // Do not close traj file here, as we might not be done with it yet. - proxy->flush_output_stream(cv_traj_os); - } - return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::setup_input() { - std::string restart_in_name(""); - - // read the restart configuration, if available if (proxy->input_prefix().size()) { - // read the restart file - restart_in_name = proxy->input_prefix(); + // Read a state file + std::string restart_in_name(proxy->input_prefix()+ + std::string(".colvars.state")); std::ifstream input_is(restart_in_name.c_str()); if (!input_is.good()) { - // try by adding the suffix + // Try without the suffix input_is.clear(); - restart_in_name = restart_in_name+std::string(".colvars.state"); + restart_in_name = proxy->input_prefix(); input_is.open(restart_in_name.c_str()); } + // Now that the file has been opened, clear this for the next round + proxy->input_prefix().clear(); + if (!input_is.good()) { - cvm::error("Error: in opening input file \""+ - std::string(restart_in_name)+"\".\n", - FILE_ERROR); - return COLVARS_ERROR; + return cvm::error("Error: in opening input state file \""+ + std::string(restart_in_name)+"\".\n", + FILE_ERROR); } else { cvm::log(cvm::line_marker); - cvm::log("Restarting from file \""+restart_in_name+"\".\n"); + cvm::log("Loading state from file \""+restart_in_name+"\".\n"); read_restart(input_is); - if (cvm::get_error() != COLVARS_OK) { - return COLVARS_ERROR; - } else { - proxy->input_prefix().clear(); - } cvm::log(cvm::line_marker); + return cvm::get_error(); } } - return cvm::get_error(); + if (proxy->input_buffer() != NULL) { + // Read a string buffer + char const *buffer = proxy->input_buffer(); + size_t const buffer_size = strlen(proxy->input_buffer()); + // Clear proxy pointer for the next round + proxy->input_buffer() = NULL; + if (buffer_size > 0) { + std::istringstream input_is; + // Replace the buffer of input_is; work around the lack of const in + // pubsetbuf's prototype (which also needs to support output streams) + input_is.rdbuf()->pubsetbuf(const_cast(buffer), buffer_size); + cvm::log(cvm::line_marker); + cvm::log("Loading state from input buffer.\n"); + read_restart(input_is); + cvm::log(cvm::line_marker); + return cvm::get_error(); + } + } + + return COLVARS_OK; } @@ -1277,6 +1283,20 @@ int colvarmodule::setup_output() } +std::string colvarmodule::state_file_prefix(char const *filename) +{ + std::string const filename_str(filename); + std::string const prefix = + filename_str.substr(0, filename_str.find(".colvars.state")); + if (prefix.size() == 0) { + cvm::error("Error: invalid filename/prefix value \""+filename_str+"\".", + INPUT_ERROR); + } + return prefix; +} + + + std::istream & colvarmodule::read_restart(std::istream &is) { bool warn_total_forces = false; @@ -1340,7 +1360,7 @@ std::istream & colvarmodule::read_restart(std::istream &is) std::istream & colvarmodule::read_objects_state(std::istream &is) { - size_t pos = 0; + std::streampos pos = 0; std::string word; while (is.good()) { @@ -1365,7 +1385,7 @@ std::istream & colvarmodule::read_objects_state(std::istream &is) "collective variable \""+(*cvi)->name+"\".\n", INPUT_ERROR); } - if (static_cast(is.tellg()) > pos) break; // found it + if (is.tellg() > pos) break; // found it } cvm::decrease_depth(); @@ -1386,13 +1406,13 @@ std::istream & colvarmodule::read_objects_state(std::istream &is) (*bi)->name+"\".\n", INPUT_ERROR); } - if (static_cast(is.tellg()) > pos) break; // found it + if (is.tellg() > pos) break; // found it } cvm::decrease_depth(); } } - if (static_cast(is.tellg()) == pos) { + if (is.tellg() == pos) { // This block has not been read by any object: discard it and move on // to the next one is >> colvarparse::read_block(word, NULL); @@ -1438,34 +1458,21 @@ int colvarmodule::backup_file(char const *filename) int colvarmodule::write_output_files() { int error_code = COLVARS_OK; - - cvm::increase_depth(); - for (std::vector::iterator cvi = colvars.begin(); - cvi != colvars.end(); - cvi++) { - error_code |= (*cvi)->write_output_files(); - } - cvm::decrease_depth(); - cvm::increase_depth(); for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { - error_code |= (*bi)->write_output_files(); + // 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) { + error_code |= (*bi)->write_output_files(); + } error_code |= (*bi)->write_state_to_replicas(); } cvm::decrease_depth(); - - if (cv_traj_os != NULL) { - // do not close, there may be another run command - proxy->flush_output_stream(cv_traj_os); - } - return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } - int colvarmodule::read_traj(char const *traj_filename, long traj_read_begin, long traj_read_end) @@ -1581,12 +1588,10 @@ int colvarmodule::open_traj_file(std::string const &file_name) // (re)open trajectory file if (cv_traj_append) { - cvm::log("Appending to colvar trajectory file \""+file_name+ - "\".\n"); + cvm::log("Appending to trajectory file \""+file_name+"\".\n"); cv_traj_os = (cvm::proxy)->output_stream(file_name, std::ios::app); } else { - cvm::log("Writing to colvar trajectory file \""+file_name+ - "\".\n"); + cvm::log("Opening trajectory file \""+file_name+"\".\n"); proxy->backup_file(file_name.c_str()); cv_traj_os = (cvm::proxy)->output_stream(file_name); } @@ -1603,6 +1608,7 @@ int colvarmodule::open_traj_file(std::string const &file_name) int colvarmodule::close_traj_file() { if (cv_traj_os != NULL) { + cvm::log("Closing trajectory file \""+cv_traj_name+"\".\n"); proxy->close_output_stream(cv_traj_name); cv_traj_os = NULL; } @@ -1668,7 +1674,7 @@ std::ostream & colvarmodule::write_traj(std::ostream &os) } -void cvm::log(std::string const &message, int min_log_level) +void colvarmodule::log(std::string const &message, int min_log_level) { if (cvm::log_level() < min_log_level) return; // allow logging when the module is not fully initialized @@ -1681,13 +1687,13 @@ void cvm::log(std::string const &message, int min_log_level) } -void cvm::increase_depth() +void colvarmodule::increase_depth() { (depth())++; } -void cvm::decrease_depth() +void colvarmodule::decrease_depth() { if (depth() > 0) { (depth())--; @@ -1695,7 +1701,7 @@ void cvm::decrease_depth() } -size_t & cvm::depth() +size_t & colvarmodule::depth() { // NOTE: do not call log() or error() here, to avoid recursion colvarmodule *cv = cvm::main(); @@ -1726,16 +1732,19 @@ void colvarmodule::set_error_bits(int code) proxy->smp_unlock(); } + bool colvarmodule::get_error_bit(int code) { return bool(errorCode & code); } + void colvarmodule::clear_error() { proxy->smp_lock(); errorCode = COLVARS_OK; proxy->smp_unlock(); + proxy->clear_error_msgs(); } @@ -1749,9 +1758,7 @@ int colvarmodule::error(std::string const &message, int code) int colvarmodule::fatal_error(std::string const &message) { - set_error_bits(FATAL_ERROR); - proxy->fatal_error(message); - return get_error(); + return error(message, FATAL_ERROR); } @@ -1793,7 +1800,7 @@ int cvm::read_index_file(char const *filename) std::vector *new_index_group = new std::vector(); int atom_number = 1; - size_t pos = is.tellg(); + std::streampos pos = is.tellg(); while ( (is >> atom_number) && (atom_number > 0) ) { new_index_group->push_back(atom_number); pos = is.tellg(); diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h index 9346e8e1d6..1cad4195d6 100644 --- a/lib/colvars/colvarmodule.h +++ b/lib/colvars/colvarmodule.h @@ -221,7 +221,6 @@ public: static void clear_error(); - /// Current step number static step_number it; /// Starting step number for this run @@ -371,6 +370,9 @@ public: /// anything that triggers another call int append_new_config(std::string const &conf); + /// Signals to the module object that the configuration has changed + void config_changed(); + private: /// Configuration string read so far by the module (includes comments) @@ -441,6 +443,9 @@ public: /// Write the output restart file std::ostream & write_restart(std::ostream &os); + /// Strips .colvars.state from filename and checks that it is not empty + static std::string state_file_prefix(char const *filename); + /// Open a trajectory file if requested (and leave it open) int open_traj_file(std::string const &file_name); /// Close it (note: currently unused) @@ -459,6 +464,9 @@ public: /// Backup a file before writing it static int backup_file(char const *filename); + /// Write the state into a string + int write_restart_string(std::string &output); + /// Look up a bias by name; returns NULL if not found static colvarbias * bias_by_name(std::string const &name); @@ -479,15 +487,6 @@ public: /// currently works for harmonic (force constant and/or centers) real energy_difference(std::string const &bias_name, std::string const &conf); - /// Give the total number of bins for a given bias. - int bias_bin_num(std::string const &bias_name); - /// Calculate the bin index for a given bias. - int bias_current_bin(std::string const &bias_name); - //// Give the count at a given bin index. - int bias_bin_count(std::string const &bias_name, size_t bin_index); - //// Share among replicas. - int bias_share(std::string const &bias_name); - /// Main worker function int calc(); diff --git a/lib/colvars/colvarparse.cpp b/lib/colvars/colvarparse.cpp index a09d6be9ef..cbe19c1914 100644 --- a/lib/colvars/colvarparse.cpp +++ b/lib/colvars/colvarparse.cpp @@ -853,7 +853,7 @@ colvarparse::read_block::~read_block() std::istream & operator>> (std::istream &is, colvarparse::read_block const &rb) { - size_t start_pos = is.tellg(); + std::streampos start_pos = is.tellg(); std::string read_key, next; if ( !(is >> read_key) || !(read_key == rb.key) || diff --git a/lib/colvars/colvarproxy.cpp b/lib/colvars/colvarproxy.cpp index 63ae07a57c..24f833f857 100644 --- a/lib/colvars/colvarproxy.cpp +++ b/lib/colvars/colvarproxy.cpp @@ -20,11 +20,6 @@ #include #endif -#if defined(NAMD_TCL) || defined(VMDTCL) -#define COLVARS_TCL -#include -#endif - #include "colvarmodule.h" #include "colvarproxy.h" #include "colvarscript.h" @@ -33,8 +28,9 @@ colvarproxy_system::colvarproxy_system() - : angstrom_value(0.) { + angstrom_value = 0.0; + total_force_requested = false; reset_pbc_lattice(); } @@ -67,7 +63,7 @@ bool colvarproxy_system::total_forces_same_step() const inline int round_to_integer(cvm::real x) { - return cvm::floor(x+0.5); + return int(cvm::floor(x+0.5)); } @@ -135,6 +131,14 @@ cvm::rvector colvarproxy_system::position_distance(cvm::atom_pos const &pos1, } +int colvarproxy_system::get_molid(int &) +{ + cvm::error("Error: only VMD allows the use of multiple \"molecules\", " + "i.e. multiple molecular systems.", COLVARS_NOT_IMPLEMENTED); + return -1; +} + + colvarproxy_atoms::colvarproxy_atoms() { @@ -505,144 +509,12 @@ int colvarproxy_script::run_colvar_gradient_callback(std::string const & /* name -colvarproxy_tcl::colvarproxy_tcl() +colvarproxy_io::colvarproxy_io() { - tcl_interp_ = NULL; + input_buffer_ = NULL; } -colvarproxy_tcl::~colvarproxy_tcl() -{ -} - - -void colvarproxy_tcl::init_tcl_pointers() -{ - cvm::error("Error: Tcl support is currently unavailable " - "outside NAMD or VMD.\n", COLVARS_NOT_IMPLEMENTED); -} - - -char const *colvarproxy_tcl::tcl_obj_to_str(unsigned char *obj) -{ -#if defined(COLVARS_TCL) - return Tcl_GetString(reinterpret_cast(obj)); -#else - return NULL; -#endif -} - - -int colvarproxy_tcl::tcl_run_force_callback() -{ -#if defined(COLVARS_TCL) - Tcl_Interp *const tcl_interp = reinterpret_cast(tcl_interp_); - std::string cmd = std::string("calc_colvar_forces ") - + cvm::to_str(cvm::step_absolute()); - int err = Tcl_Eval(tcl_interp, cmd.c_str()); - if (err != TCL_OK) { - cvm::log(std::string("Error while executing calc_colvar_forces:\n")); - cvm::error(Tcl_GetStringResult(tcl_interp)); - return COLVARS_ERROR; - } - return cvm::get_error(); -#else - return COLVARS_NOT_IMPLEMENTED; -#endif -} - - -int colvarproxy_tcl::tcl_run_colvar_callback( - std::string const & name, - std::vector const & cvc_values, - colvarvalue & value) -{ -#if defined(COLVARS_TCL) - - Tcl_Interp *const tcl_interp = reinterpret_cast(tcl_interp_); - size_t i; - std::string cmd = std::string("calc_") + name; - for (i = 0; i < cvc_values.size(); i++) { - cmd += std::string(" {") + (*(cvc_values[i])).to_simple_string() + - std::string("}"); - } - int err = Tcl_Eval(tcl_interp, cmd.c_str()); - const char *result = Tcl_GetStringResult(tcl_interp); - if (err != TCL_OK) { - return cvm::error(std::string("Error while executing ") - + cmd + std::string(":\n") + - std::string(Tcl_GetStringResult(tcl_interp)), COLVARS_ERROR); - } - std::istringstream is(result); - if (value.from_simple_string(is.str()) != COLVARS_OK) { - cvm::log("Error parsing colvar value from script:"); - cvm::error(result); - return COLVARS_ERROR; - } - return cvm::get_error(); - -#else - - return COLVARS_NOT_IMPLEMENTED; - -#endif -} - - -int colvarproxy_tcl::tcl_run_colvar_gradient_callback( - std::string const & name, - std::vector const & cvc_values, - std::vector > & gradient) -{ -#if defined(COLVARS_TCL) - - Tcl_Interp *const tcl_interp = reinterpret_cast(tcl_interp_); - size_t i; - std::string cmd = std::string("calc_") + name + "_gradient"; - for (i = 0; i < cvc_values.size(); i++) { - cmd += std::string(" {") + (*(cvc_values[i])).to_simple_string() + - std::string("}"); - } - int err = Tcl_Eval(tcl_interp, cmd.c_str()); - if (err != TCL_OK) { - return cvm::error(std::string("Error while executing ") - + cmd + std::string(":\n") + - std::string(Tcl_GetStringResult(tcl_interp)), COLVARS_ERROR); - } - Tcl_Obj **list; - int n; - Tcl_ListObjGetElements(tcl_interp, Tcl_GetObjResult(tcl_interp), - &n, &list); - if (n != int(gradient.size())) { - cvm::error("Error parsing list of gradient values from script: found " - + cvm::to_str(n) + " values instead of " + - cvm::to_str(gradient.size())); - return COLVARS_ERROR; - } - for (i = 0; i < gradient.size(); i++) { - std::istringstream is(Tcl_GetString(list[i])); - if (gradient[i].from_simple_string(is.str()) != COLVARS_OK) { - cvm::log("Gradient matrix size: " + cvm::to_str(gradient[i].size())); - cvm::log("Gradient string: " + cvm::to_str(Tcl_GetString(list[i]))); - cvm::error("Error parsing gradient value from script", COLVARS_ERROR); - return COLVARS_ERROR; - } - } - - return cvm::get_error(); - -#else - - return COLVARS_NOT_IMPLEMENTED; - -#endif -} - - - -colvarproxy_io::colvarproxy_io() {} - - colvarproxy_io::~colvarproxy_io() {} @@ -658,78 +530,6 @@ int colvarproxy_io::set_frame(long int) } -std::ostream * colvarproxy_io::output_stream(std::string const &output_name, - std::ios_base::openmode mode) -{ - if (cvm::debug()) { - cvm::log("Using colvarproxy::output_stream()\n"); - } - - std::ostream *os = get_output_stream(output_name); - if (os != NULL) return os; - - if (!(mode & (std::ios_base::app | std::ios_base::ate))) { - backup_file(output_name); - } - std::ofstream *osf = new std::ofstream(output_name.c_str(), mode); - if (!osf->is_open()) { - cvm::error("Error: cannot write to file/channel \""+output_name+"\".\n", - FILE_ERROR); - return NULL; - } - output_stream_names.push_back(output_name); - output_files.push_back(osf); - return osf; -} - - -std::ostream *colvarproxy_io::get_output_stream(std::string const &output_name) -{ - std::list::iterator osi = output_files.begin(); - std::list::iterator osni = output_stream_names.begin(); - for ( ; osi != output_files.end(); osi++, osni++) { - if (*osni == output_name) { - return *osi; - } - } - return NULL; -} - - - -int colvarproxy_io::flush_output_stream(std::ostream *os) -{ - std::list::iterator osi = output_files.begin(); - std::list::iterator osni = output_stream_names.begin(); - for ( ; osi != output_files.end(); osi++, osni++) { - if (*osi == os) { - ((std::ofstream *) (*osi))->flush(); - return COLVARS_OK; - } - } - return cvm::error("Error: trying to flush an output file/channel " - "that wasn't open.\n", BUG_ERROR); -} - - -int colvarproxy_io::close_output_stream(std::string const &output_name) -{ - std::list::iterator osi = output_files.begin(); - std::list::iterator osni = output_stream_names.begin(); - for ( ; osi != output_files.end(); osi++, osni++) { - if (*osni == output_name) { - ((std::ofstream *) (*osi))->close(); - delete *osi; - output_files.erase(osi); - output_stream_names.erase(osni); - return COLVARS_OK; - } - } - return cvm::error("Error: trying to close an output file/channel " - "that wasn't open.\n", BUG_ERROR); -} - - int colvarproxy_io::backup_file(char const * /* filename */) { // TODO implement this using rename_file() @@ -796,11 +596,33 @@ colvarproxy::colvarproxy() { colvars = NULL; b_simulation_running = true; + b_simulation_continuing = false; b_delete_requested = false; } -colvarproxy::~colvarproxy() {} +colvarproxy::~colvarproxy() +{ + close_files(); +} + + +int colvarproxy::close_files() +{ + if (smp_enabled() == COLVARS_OK && smp_thread_id() > 0) { + // Nothing to do on non-master threads + return COLVARS_OK; + } + std::list::iterator osni = output_stream_names.begin(); + std::list::iterator osi = output_files.begin(); + for ( ; osi != output_files.end(); osi++, osni++) { + ((std::ofstream *) (*osi))->close(); + delete *osi; + } + output_files.clear(); + output_stream_names.clear(); + return COLVARS_OK; +} int colvarproxy::reset() @@ -838,9 +660,37 @@ int colvarproxy::update_output() } -size_t colvarproxy::restart_frequency() +int colvarproxy::post_run() { - return 0; + int error_code = COLVARS_OK; + if (colvars->output_prefix().size()) { + error_code |= colvars->write_restart_file(cvm::output_prefix()+".colvars.state"); + error_code |= colvars->write_output_files(); + } + error_code |= flush_output_streams(); + return error_code; +} + + +void colvarproxy::add_error_msg(std::string const &message) +{ + std::istringstream is(message); + std::string line; + while (std::getline(is, line)) { + error_output += line+"\n"; + } +} + + +void colvarproxy::clear_error_msgs() +{ + error_output.clear(); +} + + +std::string const & colvarproxy::get_error_msgs() +{ + return error_output; } @@ -852,3 +702,105 @@ int colvarproxy::get_version_from_string(char const *version_string) is >> newint; return newint; } + + +void colvarproxy::smp_stream_error() +{ + cvm::error("Error: trying to access an output stream from a " + "multi-threaded region (bug). For a quick workaround, use " + "\"smp off\" in the Colvars config.\n", BUG_ERROR); +} + + +std::ostream * colvarproxy::output_stream(std::string const &output_name, + std::ios_base::openmode mode) +{ + if (cvm::debug()) { + cvm::log("Using colvarproxy::output_stream()\n"); + } + + std::ostream *os = get_output_stream(output_name); + if (os != NULL) return os; + + if (!(mode & (std::ios_base::app | std::ios_base::ate))) { + backup_file(output_name); + } + std::ofstream *osf = new std::ofstream(output_name.c_str(), mode); + if (!osf->is_open()) { + cvm::error("Error: cannot write to file/channel \""+output_name+"\".\n", + FILE_ERROR); + return NULL; + } + output_stream_names.push_back(output_name); + output_files.push_back(osf); + return osf; +} + + +std::ostream *colvarproxy::get_output_stream(std::string const &output_name) +{ + if (smp_enabled() == COLVARS_OK) { + if (smp_thread_id() > 0) smp_stream_error(); + } + std::list::iterator osi = output_files.begin(); + std::list::iterator osni = output_stream_names.begin(); + for ( ; osi != output_files.end(); osi++, osni++) { + if (*osni == output_name) { + return *osi; + } + } + return NULL; +} + + + +int colvarproxy::flush_output_stream(std::ostream *os) +{ + if (smp_enabled() == COLVARS_OK) { + if (smp_thread_id() > 0) smp_stream_error(); + } + std::list::iterator osi = output_files.begin(); + std::list::iterator osni = output_stream_names.begin(); + for ( ; osi != output_files.end(); osi++, osni++) { + if (*osi == os) { + ((std::ofstream *) (*osi))->flush(); + return COLVARS_OK; + } + } + return cvm::error("Error: trying to flush an output file/channel " + "that wasn't open.\n", BUG_ERROR); +} + + +int colvarproxy::flush_output_streams() +{ + if (smp_enabled() == COLVARS_OK && smp_thread_id() > 0) + return COLVARS_OK; + + std::list::iterator osi = output_files.begin(); + for ( ; osi != output_files.end(); osi++) { + ((std::ofstream *) (*osi))->flush(); + } + return COLVARS_OK; +} + + +int colvarproxy::close_output_stream(std::string const &output_name) +{ + if (smp_enabled() == COLVARS_OK) { + if (smp_thread_id() > 0) smp_stream_error(); + } + std::list::iterator osi = output_files.begin(); + std::list::iterator osni = output_stream_names.begin(); + for ( ; osi != output_files.end(); osi++, osni++) { + if (*osni == output_name) { + ((std::ofstream *) (*osi))->close(); + delete *osi; + output_files.erase(osi); + output_stream_names.erase(osni); + return COLVARS_OK; + } + } + return cvm::error("Error: trying to close an output file/channel " + "that wasn't open.\n", BUG_ERROR); +} diff --git a/lib/colvars/colvarproxy.h b/lib/colvars/colvarproxy.h index ba91afb40e..7a60292092 100644 --- a/lib/colvars/colvarproxy.h +++ b/lib/colvars/colvarproxy.h @@ -16,7 +16,8 @@ #include "colvarmodule.h" #include "colvartypes.h" #include "colvarvalue.h" - +#include "colvarproxy_tcl.h" +#include "colvarproxy_volmaps.h" /// \file colvarproxy.h /// \brief Colvars proxy classes @@ -29,7 +30,7 @@ /// /// To interface to a new MD engine, the simplest solution is to derive a new /// class from \link colvarproxy \endlink. Currently implemented are: \link -/// colvarproxy_lammps \endlink, \link colvarproxy_namd \endlink, \link +/// colvarproxy_lammps, \endlink, \link colvarproxy_namd, \endlink, \link /// colvarproxy_vmd \endlink. @@ -121,8 +122,15 @@ public: /// Are total forces from the current step available? virtual bool total_forces_same_step() const; + /// Get the molecule ID when called in VMD; raise error otherwise + /// \param molid Set this argument equal to the current VMD molid + virtual int get_molid(int &molid); + protected: + /// Whether the total forces have been requested + bool total_force_requested; + /// \brief Type of boundary conditions /// /// Orthogonal and triclinic cells are made available to objects. @@ -542,46 +550,6 @@ public: }; -/// Methods for using Tcl within Colvars -class colvarproxy_tcl { - -public: - - /// Constructor - colvarproxy_tcl(); - - /// Destructor - virtual ~colvarproxy_tcl(); - - /// Is Tcl available? (trigger initialization if needed) - int tcl_available(); - - /// Tcl implementation of script_obj_to_str() - char const *tcl_obj_to_str(unsigned char *obj); - - /// Run a user-defined colvar forces script - int tcl_run_force_callback(); - - int tcl_run_colvar_callback( - std::string const &name, - std::vector const &cvcs, - colvarvalue &value); - - int tcl_run_colvar_gradient_callback( - std::string const &name, - std::vector const &cvcs, - std::vector > &gradient); - -protected: - - /// Pointer to Tcl interpreter object - void *tcl_interp_; - - /// Set Tcl pointers - virtual void init_tcl_pointers(); -}; - - /// Methods for data input/output class colvarproxy_io { @@ -601,21 +569,6 @@ public: // Returns error code virtual int set_frame(long int); - /// \brief Returns a reference to the given output channel; - /// if this is not open already, then open it - virtual std::ostream *output_stream(std::string const &output_name, - std::ios_base::openmode mode = - std::ios_base::out); - - /// Returns a reference to output_name if it exists, NULL otherwise - virtual std::ostream *get_output_stream(std::string const &output_name); - - /// \brief Flushes the given output channel - virtual int flush_output_stream(std::ostream *os); - - /// \brief Closes the given output channel - virtual int close_output_stream(std::string const &output_name); - /// \brief Rename the given file, before overwriting it virtual int backup_file(char const *filename); @@ -644,30 +597,49 @@ public: return rename_file(filename.c_str(), newfilename.c_str()); } - /// \brief Prefix of the input state file + /// Prefix of the input state file to be read next inline std::string & input_prefix() { return input_prefix_str; } - /// \brief Prefix to be used for output restart files - inline std::string & restart_output_prefix() - { - return restart_output_prefix_str; - } - - /// \brief Prefix to be used for output files (final system - /// configuration) + /// Default prefix to be used for all output files (final configuration) inline std::string & output_prefix() { return output_prefix_str; } + /// Prefix of the restart (checkpoint) file to be written next + inline std::string & restart_output_prefix() + { + return restart_output_prefix_str; + } + + /// Default restart frequency (as set by the simulation engine) + inline int default_restart_frequency() const + { + return restart_frequency_engine; + } + + /// Buffer from which the input state information may be read + inline char const * & input_buffer() + { + return input_buffer_; + } + protected: - /// \brief Prefix to be used for input files (restarts, not - /// configuration) - std::string input_prefix_str, output_prefix_str, restart_output_prefix_str; + /// Prefix of the input state file to be read next + std::string input_prefix_str; + + /// Default prefix to be used for all output files (final configuration) + std::string output_prefix_str; + + /// Prefix of the restart (checkpoint) file to be written next + std::string restart_output_prefix_str; + + /// How often the simulation engine will write its own restart + int restart_frequency_engine; /// \brief Currently opened output files: by default, these are ofstream objects. /// Allows redefinition to implement different output mechanisms @@ -675,6 +647,8 @@ protected: /// \brief Identifiers for output_stream objects: by default, these are the names of the files std::list output_stream_names; + /// Buffer from which the input state information may be read + char const *input_buffer_; }; @@ -687,6 +661,7 @@ class colvarproxy : public colvarproxy_system, public colvarproxy_atoms, public colvarproxy_atom_groups, + public colvarproxy_volmaps, public colvarproxy_smp, public colvarproxy_replicas, public colvarproxy_script, @@ -717,6 +692,9 @@ public: /// \brief Reset proxy state, e.g. requested atoms virtual int reset(); + /// Close any open files to prevent data loss + int close_files(); + /// (Re)initialize required member data after construction virtual int setup(); @@ -731,14 +709,17 @@ public: /// Print a message to the main log virtual void log(std::string const &message) = 0; - /// Print a message to the main log and let the rest of the program handle the error + /// Print a message to the main log and/or let the host code know about it virtual void error(std::string const &message) = 0; - /// Print a message to the main log and exit with error code - virtual void fatal_error(std::string const &message) = 0; + /// Record error message (used by VMD to collect them after a script call) + void add_error_msg(std::string const &message); - /// \brief Restarts will be written each time this number of steps has passed - virtual size_t restart_frequency(); + /// Retrieve accumulated error messages + std::string const & get_error_msgs(); + + /// As the name says + void clear_error_msgs(); /// Whether a simulation is running (warn against irrecovarable errors) inline bool simulation_running() const @@ -746,6 +727,17 @@ public: return b_simulation_running; } + /// Is the current step a repetition of a step just executed? + /// This is set to true when the step 0 of a new "run" command is being + /// executed, regardless of whether a state file has been loaded. + inline bool simulation_continuing() const + { + return b_simulation_continuing; + } + + /// Called at the end of a simulation segment (i.e. "run" command) + int post_run(); + /// Convert a version string "YYYY-MM-DD" into an integer int get_version_from_string(char const *version_string); @@ -755,17 +747,46 @@ public: return version_int; } + /// \brief Returns a reference to the given output channel; + /// if this is not open already, then open it + virtual std::ostream *output_stream(std::string const &output_name, + std::ios_base::openmode mode = + std::ios_base::out); + + /// Returns a reference to output_name if it exists, NULL otherwise + virtual std::ostream *get_output_stream(std::string const &output_name); + + /// \brief Flushes the given output channel + virtual int flush_output_stream(std::ostream *os); + + /// \brief Flushes all output channels + virtual int flush_output_streams(); + + /// \brief Closes the given output channel + virtual int close_output_stream(std::string const &output_name); + protected: + /// Collected error messages + std::string error_output; + /// Whether a simulation is running (warn against irrecovarable errors) bool b_simulation_running; + /// Is the current step a repetition of a step just executed? + /// This is set to true when the step 0 of a new "run" command is being + /// executed, regardless of whether a state file has been loaded. + bool b_simulation_continuing; + /// Whether the entire module should be deallocated by the host engine bool b_delete_requested; /// Integer representing the version string (allows comparisons) int version_int; + /// Raise when the output stream functions are used on threads other than 0 + void smp_stream_error(); + }; diff --git a/lib/colvars/colvarproxy_tcl.cpp b/lib/colvars/colvarproxy_tcl.cpp new file mode 100644 index 0000000000..a799bead7d --- /dev/null +++ b/lib/colvars/colvarproxy_tcl.cpp @@ -0,0 +1,160 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + +#include + +#if defined(NAMD_TCL) || defined(VMDTCL) +#define COLVARS_TCL +#include +#endif + +#include "colvarmodule.h" +#include "colvarproxy.h" +#include "colvarproxy_tcl.h" +#include "colvaratoms.h" + + + +colvarproxy_tcl::colvarproxy_tcl() +{ + tcl_interp_ = NULL; +} + + +colvarproxy_tcl::~colvarproxy_tcl() +{ +} + + +void colvarproxy_tcl::init_tcl_pointers() +{ + cvm::error("Error: Tcl support is not available in this build.\n", + COLVARS_NOT_IMPLEMENTED); +} + + +char const *colvarproxy_tcl::tcl_get_str(void *obj) +{ +#if defined(COLVARS_TCL) + return Tcl_GetString(reinterpret_cast(obj)); +#else + return NULL; +#endif +} + + +int colvarproxy_tcl::tcl_run_force_callback() +{ +#if defined(COLVARS_TCL) + Tcl_Interp *const tcl_interp = + reinterpret_cast(get_tcl_interp()); + std::string cmd = std::string("calc_colvar_forces ") + + cvm::to_str(cvm::step_absolute()); + int err = Tcl_Eval(tcl_interp, cmd.c_str()); + if (err != TCL_OK) { + cvm::log(std::string("Error while executing calc_colvar_forces:\n")); + cvm::error(Tcl_GetStringResult(tcl_interp)); + return COLVARS_ERROR; + } + return cvm::get_error(); +#else + return COLVARS_NOT_IMPLEMENTED; +#endif +} + + +int colvarproxy_tcl::tcl_run_colvar_callback( + std::string const &name, + std::vector const &cvc_values, + colvarvalue &value) +{ +#if defined(COLVARS_TCL) + + Tcl_Interp *const tcl_interp = + reinterpret_cast(get_tcl_interp()); + size_t i; + std::string cmd = std::string("calc_") + name; + for (i = 0; i < cvc_values.size(); i++) { + cmd += std::string(" {") + (*(cvc_values[i])).to_simple_string() + + std::string("}"); + } + int err = Tcl_Eval(tcl_interp, cmd.c_str()); + const char *result = Tcl_GetStringResult(tcl_interp); + if (err != TCL_OK) { + return cvm::error(std::string("Error while executing ") + + cmd + std::string(":\n") + + std::string(Tcl_GetStringResult(tcl_interp)), + COLVARS_ERROR); + } + std::istringstream is(result); + if (value.from_simple_string(is.str()) != COLVARS_OK) { + cvm::log("Error parsing colvar value from script:"); + cvm::error(result); + return COLVARS_ERROR; + } + return cvm::get_error(); + +#else + + return COLVARS_NOT_IMPLEMENTED; + +#endif +} + + +int colvarproxy_tcl::tcl_run_colvar_gradient_callback( + std::string const &name, + std::vector const &cvc_values, + std::vector > &gradient) +{ +#if defined(COLVARS_TCL) + + Tcl_Interp *const tcl_interp = + reinterpret_cast(get_tcl_interp()); + size_t i; + std::string cmd = std::string("calc_") + name + "_gradient"; + for (i = 0; i < cvc_values.size(); i++) { + cmd += std::string(" {") + (*(cvc_values[i])).to_simple_string() + + std::string("}"); + } + int err = Tcl_Eval(tcl_interp, cmd.c_str()); + if (err != TCL_OK) { + return cvm::error(std::string("Error while executing ") + + cmd + std::string(":\n") + + std::string(Tcl_GetStringResult(tcl_interp)), + COLVARS_ERROR); + } + Tcl_Obj **list; + int n; + Tcl_ListObjGetElements(tcl_interp, Tcl_GetObjResult(tcl_interp), + &n, &list); + if (n != int(gradient.size())) { + cvm::error("Error parsing list of gradient values from script: found " + + cvm::to_str(n) + " values instead of " + + cvm::to_str(gradient.size())); + return COLVARS_ERROR; + } + for (i = 0; i < gradient.size(); i++) { + std::istringstream is(Tcl_GetString(list[i])); + if (gradient[i].from_simple_string(is.str()) != COLVARS_OK) { + cvm::log("Gradient matrix size: " + cvm::to_str(gradient[i].size())); + cvm::log("Gradient string: " + cvm::to_str(Tcl_GetString(list[i]))); + cvm::error("Error parsing gradient value from script", COLVARS_ERROR); + return COLVARS_ERROR; + } + } + + return cvm::get_error(); + +#else + + return COLVARS_NOT_IMPLEMENTED; + +#endif +} diff --git a/lib/colvars/colvarproxy_tcl.h b/lib/colvars/colvarproxy_tcl.h new file mode 100644 index 0000000000..371b3c0224 --- /dev/null +++ b/lib/colvars/colvarproxy_tcl.h @@ -0,0 +1,64 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + +#ifndef COLVARPROXY_TCL_H +#define COLVARPROXY_TCL_H + +#include + + +/// Methods for using Tcl within Colvars +class colvarproxy_tcl { + +public: + + /// Constructor + colvarproxy_tcl(); + + /// Destructor + virtual ~colvarproxy_tcl(); + + /// Is Tcl available? (trigger initialization if needed) + int tcl_available(); + + /// Tcl implementation of script_obj_to_str() + char const *tcl_get_str(void *obj); + + /// Tcl implementation of run_force_callback() + int tcl_run_force_callback(); + + /// Tcl implementation of run_colvar_callback() + int tcl_run_colvar_callback( + std::string const &name, + std::vector const &cvcs, + colvarvalue &value); + + /// Tcl implementation of run_colvar_gradient_callback() + int tcl_run_colvar_gradient_callback( + std::string const &name, + std::vector const &cvcs, + std::vector > &gradient); + + /// Get a pointer to the Tcl interpreter + inline void *get_tcl_interp() + { + return tcl_interp_; + } + +protected: + + /// Pointer to Tcl interpreter object + void *tcl_interp_; + + /// Set Tcl pointers + virtual void init_tcl_pointers(); +}; + + +#endif diff --git a/lib/colvars/colvarproxy_volmaps.cpp b/lib/colvars/colvarproxy_volmaps.cpp new file mode 100644 index 0000000000..fc665eec99 --- /dev/null +++ b/lib/colvars/colvarproxy_volmaps.cpp @@ -0,0 +1,81 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + +#include "colvarmodule.h" +#include "colvarproxy_volmaps.h" + + +colvarproxy_volmaps::colvarproxy_volmaps() {} + + +colvarproxy_volmaps::~colvarproxy_volmaps() {} + + +int colvarproxy_volmaps::volmaps_available() +{ + return COLVARS_NOT_IMPLEMENTED; +} + + +int colvarproxy_volmaps::reset() +{ + for (size_t i = 0; i < volmaps_ids.size(); i++) { + clear_volmap(i); + } + volmaps_ids.clear(); + volmaps_ncopies.clear(); + volmaps_values.clear(); + volmaps_new_colvar_forces.clear(); + return COLVARS_OK; +} + + +int colvarproxy_volmaps::add_volmap_slot(int volmap_id) +{ + volmaps_ids.push_back(volmap_id); + volmaps_ncopies.push_back(1); + volmaps_values.push_back(0.0); + volmaps_new_colvar_forces.push_back(0.0); + return (volmaps_ids.size() - 1); +} + + +int colvarproxy_volmaps::init_volmap(int volmap_id) +{ + return cvm::error("Error: access to volumetric maps is unavailable " + "in this build.\n", + COLVARS_NOT_IMPLEMENTED); +} + + +int colvarproxy_volmaps::init_volmap(const char *volmap_name) +{ + return cvm::error("Error: access to volumetric maps is unavailable " + "in this build.\n", + COLVARS_NOT_IMPLEMENTED); +} + + +int colvarproxy_volmaps::init_volmap(const std::string &volmap_name) +{ + return init_volmap(volmap_name.c_str()); +} + + +void colvarproxy_volmaps::clear_volmap(int index) +{ + if (((size_t) index) >= volmaps_ids.size()) { + cvm::error("Error: trying to unrequest a volumetric map that was not " + "previously requested.\n", INPUT_ERROR); + } + + if (volmaps_ncopies[index] > 0) { + volmaps_ncopies[index] -= 1; + } +} diff --git a/lib/colvars/colvarproxy_volmaps.h b/lib/colvars/colvarproxy_volmaps.h new file mode 100644 index 0000000000..67cbb2cd2d --- /dev/null +++ b/lib/colvars/colvarproxy_volmaps.h @@ -0,0 +1,76 @@ +// -*- c++ -*- + +#ifndef COLVARPROXY_VOLMAPS_H +#define COLVARPROXY_VOLMAPS_H + + +/// \brief Container of grid-based objects +class colvarproxy_volmaps { + +public: + + /// Contructor + colvarproxy_volmaps(); + + /// Destructor + virtual ~colvarproxy_volmaps(); + + /// Clear volumetric map data + int reset(); + + /// \brief Whether this implementation has capability to use volumetric maps + virtual int volmaps_available(); + + /// Create a slot for a volumetric map not requested yet + int add_volmap_slot(int volmap_id); + + /// Request and prepare this volumetric map for use by Colvars + virtual int init_volmap(int volmap_id); + + /// Request and prepare this volumetric map for use by Colvars + virtual int init_volmap(char const *volmap_name); + + /// Request and prepare this volumetric map for use by Colvars + int init_volmap(std::string const &volmap_name); + + /// \brief Used by the CVC destructors + virtual void clear_volmap(int index); + + /// Get the numeric ID of the given volumetric map (for the MD program) + inline int get_volmap_id(int index) const + { + return volmaps_ids[index]; + } + + /// Read the current value of the volumetric map + inline cvm::real get_volmap_value(int index) const + { + return volmaps_values[index]; + } + + /// Request that this force is applied to the given volumetric map + inline void apply_volmap_force(int index, cvm::real const &new_force) + { + volmaps_new_colvar_forces[index] += new_force; + } + + +protected: + + /// \brief Array of numeric IDs of volumetric maps + std::vector volmaps_ids; + + /// \brief Keep track of how many times each vol map is used by a + /// separate colvar object + std::vector volmaps_ncopies; + + /// \brief Current values of the vol maps + std::vector volmaps_values; + + /// \brief Forces applied from colvars, to be communicated to the MD + /// integrator + std::vector volmaps_new_colvar_forces; +}; + + +#endif diff --git a/lib/colvars/colvars_version.h b/lib/colvars/colvars_version.h index cc8744d62b..33e05d72d1 100644 --- a/lib/colvars/colvars_version.h +++ b/lib/colvars/colvars_version.h @@ -1,3 +1,3 @@ #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2020-02-25" +#define COLVARS_VERSION "2020-09-17" #endif diff --git a/lib/colvars/colvarscript.cpp b/lib/colvars/colvarscript.cpp index 10b276c89e..ebd52b10ad 100644 --- a/lib/colvars/colvarscript.cpp +++ b/lib/colvars/colvarscript.cpp @@ -9,58 +9,239 @@ #include #include +#include -#define COLVARSCRIPT_CPP -#include "colvarscript.h" -#undef COLVARSCRIPT_CPP +#if defined(NAMD_TCL) || defined(VMDTCL) +#define COLVARS_TCL +#include +#endif #include "colvarproxy.h" #include "colvardeps.h" +#include "colvarscript.h" +#include "colvarscript_commands.h" + colvarscript::colvarscript(colvarproxy *p) - : proxy(p), + : proxy_(p), colvars(p->colvars), proxy_error(0) { - comm_help.resize(colvarscript::cv_n_commands); - comm_fns.resize(colvarscript::cv_n_commands); -#define COLVARSCRIPT_INIT_FN -#include "colvarscript.h" -#undef COLVARSCRIPT_INIT_FN + cmd_names = NULL; + init_commands(); +#ifdef COLVARS_TCL + // TODO put this in backend functions so we don't have to delete + Tcl_Interp *interp = reinterpret_cast(proxy_->get_tcl_interp()); + Tcl_DeleteCommand(interp, "cv"); + Tcl_CreateObjCommand(interp, "cv", tcl_run_colvarscript_command, + (ClientData) this, (Tcl_CmdDeleteProc *) NULL); + cvm::log("Redefining the Tcl \"cv\" command to the new script interface."); +#endif } -extern "C" { - - // Generic hooks; NAMD and VMD have Tcl-specific versions in the respective proxies - - int run_colvarscript_command(int objc, unsigned char *const objv[]) - { - colvarproxy *cvp = cvm::proxy; - if (!cvp) { - return -1; - } - if (!cvp->script) { - cvm::error("Called run_colvarscript_command without a script object initialized.\n"); - return -1; - } - return cvp->script->run(objc, objv); - } - - const char * get_colvarscript_result() - { - colvarproxy *cvp = cvm::proxy; - if (!cvp->script) { - cvm::error("Called run_colvarscript_command without a script object initialized.\n"); - return ""; - } - return cvp->script->result.c_str(); +colvarscript::~colvarscript() +{ + if (cmd_names) { + delete [] cmd_names; + cmd_names = NULL; } } -/// Run method based on given arguments +int colvarscript::init_commands() +{ + if (cvm::debug()) { + cvm::log("Called colvarcript::init_commands()\n"); + } + + cmd_help.resize(colvarscript::cv_n_commands); + cmd_n_args_min.resize(colvarscript::cv_n_commands); + cmd_n_args_max.resize(colvarscript::cv_n_commands); + cmd_arghelp.resize(colvarscript::cv_n_commands); + cmd_fns.resize(colvarscript::cv_n_commands); + + if (cmd_names) { + delete [] cmd_names; + cmd_names = NULL; + } + cmd_names = new char const * [colvarscript::cv_n_commands]; + +#undef COLVARSCRIPT_COMMANDS_H // disable include guard +#if defined(CVSCRIPT) +#undef CVSCRIPT // disable default macro +#endif +#define CVSCRIPT_COMM_INIT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGHELP) { \ + init_command(COMM,#COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGHELP,&(CVSCRIPT_COMM_FNAME(COMM))); \ + } +#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + CVSCRIPT_COMM_INIT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS) + +#include "colvarscript_commands.h" + +#undef CVSCRIPT_COMM_INIT +#undef CVSCRIPT + + return COLVARS_OK; +} + + +int colvarscript::init_command(colvarscript::command const &comm, + char const *name, char const *help, + int n_args_min, int n_args_max, + char const *arghelp, + int (*fn)(void *, int, unsigned char * const *)) +{ + cmd_str_map[std::string(name)] = comm; + cmd_names[comm] = name; + cmd_help[comm] = help; + cmd_n_args_min[comm] = n_args_min; + cmd_n_args_max[comm] = n_args_max; + std::string const arghelp_str(arghelp); + std::istringstream is(arghelp_str); + std::string line; + for (int iarg = 0; iarg < n_args_max; iarg++) { + if (! std::getline(is, line)) { + return cvm::error("Error: could not initialize help string for scripting " + "command \""+std::string(name)+"\".\n", BUG_ERROR); + } + cmd_arghelp[comm].push_back(line); + } + cmd_fns[comm] = fn; + if (cvm::debug()) { + cvm::log("Defined command \""+std::string(name)+"\", with help string:\n"); + cvm::log(get_command_help(name)); + } + return COLVARS_OK; +} + + +std::string colvarscript::get_cmd_prefix(colvarscript::Object_type t) +{ + switch (t) { + case use_module: + return std::string("cv_"); break; + case use_colvar: + return std::string("colvar_"); break; + case use_bias: + return std::string("bias_"); break; + default: + cvm::error("Error: undefined colvarscript object type.", BUG_ERROR); + return std::string(""); + } +} + + +std::string colvarscript::get_command_help(char const *cmd) +{ + if (cmd_str_map.count(cmd) > 0) { + colvarscript::command const c = cmd_str_map[std::string(cmd)]; + std::string new_result(cmd_help[c]+"\n"); + if (cmd_n_args_max[c] == 0) return new_result; + new_result += "\nParameters\n"; + new_result += "----------\n\n"; + size_t i; + for (i = 0; i < cmd_n_args_min[c]; i++) { + new_result += cmd_arghelp[c][i]+"\n"; + } + for (i = cmd_n_args_min[c]; i < cmd_n_args_max[c]; i++) { + new_result += cmd_arghelp[c][i]+" (optional)\n"; + } + return new_result; + } + + cvm::error("Error: command "+std::string(cmd)+ + " is not implemented.\n", INPUT_ERROR); + return std::string(""); +} + + +std::string colvarscript::get_command_cmdline_syntax(colvarscript::Object_type t, + colvarscript::command cmd) +{ + std::string const prefix = get_cmd_prefix(t); + std::string const cmdstr(cmd_names[cmd]); + + // Get the sub-command as used in the command line + std::string const cmdline_cmd(cmdstr, prefix.size()); + std::string cmdline_args; + + size_t i; + for (i = 0; i < cmd_n_args_min[cmd]; i++) { + std::string const &arghelp = cmd_arghelp[cmd][i]; + size_t space = arghelp.find(" : "); + cmdline_args += " <"+cmd_arghelp[cmd][i].substr(0, space)+">"; + } + for (i = cmd_n_args_min[cmd]; i < cmd_n_args_max[cmd]; i++) { + std::string const &arghelp = cmd_arghelp[cmd][i]; + size_t space = arghelp.find(" : "); + cmdline_args += " ["+cmd_arghelp[cmd][i].substr(0, space)+"]"; + } + + switch (t) { + case use_module: + return std::string("cv "+cmdline_cmd+cmdline_args); break; + case use_colvar: + return std::string("cv colvar name "+cmdline_cmd+cmdline_args); break; + case use_bias: + return std::string("cv bias name "+cmdline_cmd+cmdline_args); break; + default: + // Already handled, but silence the warning + return std::string(""); + } + + return std::string(""); +} + + +std::string colvarscript::get_cmdline_help_summary(colvarscript::Object_type t) +{ + std::string output; + output += "List of commands:\n\n"; + + for (size_t i = 0; i < cmd_help.size(); i++) { + std::string const prefix = get_cmd_prefix(t); + command const c = cmd_str_map[std::string(cmd_names[i])]; + if (std::string(cmd_names[i], prefix.size()) == prefix) { + output += get_command_cmdline_syntax(t, c)+std::string("\n"); + } + } + if (t == use_module) { + output += "\nFor detailed help on each command use:\n" + " cv help \n"; + output += "\nTo list all commands acting on collective variables use:\n" + " cv help colvar\n"; + output += "\nTo list all commands acting on biases use:\n" + " cv help bias\n"; + } + if (t == use_colvar) { + output += "\nFor detailed help on each command use:\n" + " cv colvar name help (\"name\" does not need to exist)\n"; + } + if (t == use_bias) { + output += "\nFor detailed help on each command use:\n" + " cv bias name help (\"name\" does not need to exist)\n"; + } + return output; +} + + +std::string colvarscript::get_command_cmdline_help(colvarscript::Object_type t, + std::string const &cmd) +{ + std::string const cmdkey(get_cmd_prefix(t)+cmd); + if (cmd_str_map.count(cmdkey) > 0) { + command const c = cmd_str_map[cmdkey]; + return get_command_cmdline_syntax(t, c)+"\n\n"+ + get_command_help(cmd_names[c]); + } + cvm::error("Error: could not find scripting command \""+cmd+"\".", + INPUT_ERROR); + return std::string(""); +} + + int colvarscript::run(int objc, unsigned char *const objv[]) { result.clear(); @@ -73,497 +254,114 @@ int colvarscript::run(int objc, unsigned char *const objv[]) } if (objc < 2) { - set_str_result("No commands given: use \"cv help\" " + set_result_str("No commands given: use \"cv help\" " "for a list of commands."); return COLVARSCRIPT_ERROR; } + // Main command; usually "cv" + std::string const main_cmd(std::string(obj_to_str(objv[0]))); + + // Name of the (sub)command std::string const cmd(obj_to_str(objv[1])); + // Build a safe-to-print command line to print in case of error + std::string cmdline(main_cmd+std::string(" ")+cmd); + + // Pointer to the function implementing it + int (*cmd_fn)(void *, int, unsigned char * const *) = NULL; + + // Pointer to object handling the command (the functions are C) + void *obj_for_cmd = NULL; + + if (cmd == "colvar") { + + if (objc < 4) { + add_error_msg("Missing parameters: use \""+main_cmd+ + " help colvar\" for a summary"); + return COLVARSCRIPT_ERROR; + } + std::string const name(obj_to_str(objv[2])); + std::string const subcmd(obj_to_str(objv[3])); + obj_for_cmd = reinterpret_cast(cvm::colvar_by_name(name)); + if (obj_for_cmd == NULL) { + if (subcmd != std::string("help")) { + // Unless asking for help, a valid colvar name must be given + add_error_msg("Colvar not found: " + name); + return COLVARSCRIPT_ERROR; + } + } + cmd_fn = get_cmd_fn(get_cmd_prefix(use_colvar)+subcmd); + cmdline += std::string(" name ")+subcmd; + if (objc > 4) { + cmdline += " ..."; + } + + } else if (cmd == "bias") { + + if (objc < 4) { + add_error_msg("Missing parameters: use \""+main_cmd+ + " help bias\" for a summary"); + return COLVARSCRIPT_ERROR; + } + std::string const name(obj_to_str(objv[2])); + std::string const subcmd(obj_to_str(objv[3])); + obj_for_cmd = reinterpret_cast(cvm::bias_by_name(name)); + if (obj_for_cmd == NULL) { + if ((subcmd == "") || (subcmd != std::string("help"))) { + // Unless asking for help, a valid bias name must be given + add_error_msg("Bias not found: " + name); + return COLVARSCRIPT_ERROR; + } + } + cmd_fn = get_cmd_fn(get_cmd_prefix(use_bias)+subcmd); + cmdline += std::string(" name ")+subcmd; + if (objc > 4) { + cmdline += " ..."; + } + + } else { + + cmd_fn = get_cmd_fn(get_cmd_prefix(use_module)+cmd); + obj_for_cmd = reinterpret_cast(this); + + if (objc > 2) { + cmdline += " ..."; + } + } + int error_code = COLVARS_OK; - // If command is found in map, execute it - std::string const cmd_key("cv_"+cmd); - if (comm_str_map.count(cmd_key) > 0) { - error_code |= (*(comm_fns[comm_str_map[cmd_key]]))( - reinterpret_cast(this), objc, objv); - return error_code; + // If command was found in map, execute it + if (cmd_fn) { + error_code = (*cmd_fn)(obj_for_cmd, objc, objv); + } else { + add_error_msg("Syntax error: "+cmdline+"\n" + " Run \"cv help\" or \"cv help \" " + "to get the correct syntax.\n"); + error_code = COLVARSCRIPT_ERROR; } - if (cmd == "colvar") { - if (objc < 3) { - result = "Missing parameters\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - std::string const name(obj_to_str(objv[2])); - colvar *cv = cvm::colvar_by_name(name); - if (cv == NULL) { - result = "Colvar not found: " + name; - return COLVARSCRIPT_ERROR; - } - return proc_colvar(cv, objc-1, &(objv[1])); - } - - if (cmd == "bias") { - if (objc < 3) { - result = "Missing parameters\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - std::string const name(obj_to_str(objv[2])); - colvarbias *b = cvm::bias_by_name(name); - if (b == NULL) { - result = "Bias not found: " + name; - return COLVARSCRIPT_ERROR; - } - return proc_bias(b, objc-1, &(objv[1])); - } - - if (cmd == "version") { - result = COLVARS_VERSION; - return COLVARS_OK; - } - - if (cmd == "reset") { - /// Delete every child object - colvars->reset(); - return COLVARS_OK; - } - - if (cmd == "delete") { - // Note: the delete bit may be ignored by some backends - // it is mostly useful in VMD - return proxy->request_deletion(); - } - - if (cmd == "update") { - error_code |= proxy->update_input(); - if (error_code) { - result += "Error updating the Colvars module.\n"; - return error_code; - } - error_code |= colvars->calc(); - error_code |= proxy->update_output(); - if (error_code) { - result += "Error updating the Colvars module.\n"; - } - return error_code; - } - - if (cmd == "list") { - if (objc == 2) { - for (std::vector::iterator cvi = colvars->colvars.begin(); - cvi != colvars->colvars.end(); - ++cvi) { - result += (cvi == colvars->colvars.begin() ? "" : " ") + (*cvi)->name; - } - return COLVARS_OK; - } else if (objc == 3 && !strcmp(obj_to_str(objv[2]), "biases")) { - for (std::vector::iterator bi = colvars->biases.begin(); - bi != colvars->biases.end(); - ++bi) { - result += (bi == colvars->biases.begin() ? "" : " ") + (*bi)->name; - } - return COLVARS_OK; - } else { - result = "Wrong arguments to command \"list\"\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - } - - /// Parse config from file - if (cmd == "configfile") { - if (objc < 3) { - result = "Missing arguments\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - if (colvars->read_config_file(obj_to_str(objv[2])) == COLVARS_OK) { - return COLVARS_OK; - } else { - result = "Error parsing configuration file"; - return COLVARSCRIPT_ERROR; - } - } - - /// Parse config from string - if (cmd == "config") { - return exec_command(cv_config, NULL, objc, objv); - } - - /// Load an input state file - if (cmd == "load") { - if (objc < 3) { - result = "Missing arguments\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - proxy->input_prefix() = obj_to_str(objv[2]); - if (colvars->setup_input() == COLVARS_OK) { - return COLVARS_OK; - } else { - result = "Error loading state file"; - return COLVARSCRIPT_ERROR; - } - } - - /// Save to an output state file - if (cmd == "save") { - if (objc < 3) { - result = "Missing arguments"; - return COLVARSCRIPT_ERROR; - } - proxy->output_prefix() = obj_to_str(objv[2]); - int error = 0; - error |= colvars->setup_output(); - error |= colvars->write_restart_file(colvars->output_prefix()+ - ".colvars.state"); - error |= colvars->write_output_files(); - return error ? COLVARSCRIPT_ERROR : COLVARS_OK; - } - - /// Print the values that would go on colvars.traj - if (cmd == "printframelabels") { - std::ostringstream os; - colvars->write_traj_label(os); - result = os.str(); - return COLVARS_OK; - } - if (cmd == "printframe") { - std::ostringstream os; - colvars->write_traj(os); - result = os.str(); - return COLVARS_OK; - } - - if (cmd == "frame") { - if (objc == 2) { - long int f; - int error = proxy->get_frame(f); - if (error == COLVARS_OK) { - result = cvm::to_str(f); - return COLVARS_OK; - } else { - result = "Frame number is not available"; - return COLVARSCRIPT_ERROR; - } - } else if (objc == 3) { - // Failure of this function does not trigger an error, but - // returns nonzero, to let scripts detect available frames - int error = proxy->set_frame(strtol(obj_to_str(objv[2]), NULL, 10)); - result = cvm::to_str(error == COLVARS_OK ? 0 : -1); - return COLVARS_OK; - } else { - result = "Wrong arguments to command \"frame\"\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - } - - if (cmd == "addenergy") { - if (objc == 3) { - colvars->total_bias_energy += strtod(obj_to_str(objv[2]), NULL); - return COLVARS_OK; - } else { - result = "Wrong arguments to command \"addenergy\"\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - } - - if (cmd == "help") { - return exec_command(cv_help, NULL, objc, objv); - } - - result = "Syntax error\n" + help_string(); - return COLVARSCRIPT_ERROR; -} - - -int colvarscript::proc_colvar(colvar *cv, int objc, unsigned char *const objv[]) { - - if (objc < 3) { - result = "Missing arguments"; - return COLVARSCRIPT_ERROR; - } - std::string const subcmd(obj_to_str(objv[2])); - - if (subcmd == "value") { - result = (cv->value()).to_simple_string(); - return COLVARS_OK; - } - - if (subcmd == "run_ave") { - result = (cv->run_ave()).to_simple_string(); - return COLVARS_OK; - } - - if (subcmd == "width") { - result = cvm::to_str(cv->width, 0, cvm::cv_prec); - return COLVARS_OK; - } - - if (subcmd == "type") { - result = cv->value().type_desc(cv->value().value_type); - return COLVARS_OK; - } - - if (subcmd == "update") { - cv->calc(); - cv->update_forces_energy(); - result = (cv->value()).to_simple_string(); - return COLVARS_OK; - } - - if (subcmd == "delete") { - while (cv->biases.size() > 0) { - size_t i = cv->biases.size()-1; - cvm::log("Warning: before deleting colvar " + cv->name - + ", deleting parent bias " + cv->biases[i]->name); - delete cv->biases[i]; - } - // colvar destructor is tasked with the cleanup - delete cv; - // TODO this could be done by the destructors - if (colvars->cv_traj_os != NULL) { - colvars->write_traj_label(*(colvars->cv_traj_os)); - } - return COLVARS_OK; - } - - if (subcmd == "getconfig") { - result = cv->get_config(); - return COLVARS_OK; - } - - if (subcmd == "getatomgroups") { - std::vector > lists = cv->get_atom_lists(); - std::vector >::iterator li = lists.begin(); - - for ( ; li != lists.end(); ++li) { - result += "{"; - std::vector::iterator lj = (*li).begin(); - for ( ; lj != (*li).end(); ++lj) { - result += cvm::to_str(*lj); - result += " "; - } - result += "} "; - } - return COLVARS_OK; - } - - if (subcmd == "getatomids") { - std::vector::iterator li = cv->atom_ids.begin(); - - for ( ; li != cv->atom_ids.end(); ++li) { - result += cvm::to_str(*li); - result += " "; - } - return COLVARS_OK; - } - - if (subcmd == "getgradients") { - std::vector::iterator li = cv->atomic_gradients.begin(); - - for ( ; li != cv->atomic_gradients.end(); ++li) { - result += "{"; - int j; - for (j = 0; j < 3; ++j) { - result += cvm::to_str((*li)[j]); - result += " "; - } - result += "} "; - } - return COLVARS_OK; - } - - if (subcmd == "getappliedforce") { - result = (cv->applied_force()).to_simple_string(); - return COLVARS_OK; - } - - if (subcmd == "getsystemforce") { - // TODO warning here - result = (cv->total_force()).to_simple_string(); - return COLVARS_OK; - } - - if (subcmd == "gettotalforce") { - result = (cv->total_force()).to_simple_string(); - return COLVARS_OK; - } - - if (subcmd == "addforce") { - if (objc < 4) { - result = "addforce: missing parameter: force value\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - std::string const f_str(obj_to_str(objv[3])); - std::istringstream is(f_str); - is.width(cvm::cv_width); - is.precision(cvm::cv_prec); - colvarvalue force(cv->value()); - force.is_derivative(); - if (force.from_simple_string(is.str()) != COLVARS_OK) { - result = "addforce : error parsing force value"; - return COLVARSCRIPT_ERROR; - } - cv->add_bias_force(force); - result = force.to_simple_string(); - return COLVARS_OK; - } - - if (subcmd == "cvcflags") { - if (objc < 4) { - result = "cvcflags: missing parameter: vector of flags"; - return COLVARSCRIPT_ERROR; - } - std::string const flags_str(obj_to_str(objv[3])); - std::istringstream is(flags_str); - std::vector flags; - - int flag; - while (is >> flag) { - flags.push_back(flag != 0); - } - - int res = cv->set_cvc_flags(flags); - if (res != COLVARS_OK) { - result = "Error setting CVC flags"; - return COLVARSCRIPT_ERROR; - } - result = "0"; - return COLVARS_OK; - } - - if (subcmd == "modifycvcs") { - if (objc < 4) { - result = "cvcflags: missing parameter: vector of strings"; - return COLVARSCRIPT_ERROR; - } - std::vector const confs(proxy->script_obj_to_str_vector(objv[3])); - cvm::increase_depth(); - int res = cv->update_cvc_config(confs); - cvm::decrease_depth(); - if (res != COLVARS_OK) { - result = "Error setting CVC flags"; - return COLVARSCRIPT_ERROR; - } - result = "0"; - return COLVARS_OK; - } - - if ((subcmd == "get") || (subcmd == "set") || (subcmd == "state")) { - return proc_features(cv, objc, objv); - } - - result = "Syntax error\n" + help_string(); - return COLVARSCRIPT_ERROR; -} - - -int colvarscript::proc_bias(colvarbias *b, int objc, unsigned char *const objv[]) { - - if (objc < 3) { - result = "Missing arguments"; - return COLVARSCRIPT_ERROR; - } - std::string const subcmd(obj_to_str(objv[2])); - - if (subcmd == "energy") { - result = cvm::to_str(b->get_energy()); - return COLVARS_OK; - } - - if (subcmd == "update") { - b->update(); - result = cvm::to_str(b->get_energy()); - return COLVARS_OK; - } - - if (subcmd == "getconfig") { - result = b->get_config(); - return COLVARS_OK; - } - - // Subcommands for MW ABF - if (subcmd == "bin") { - int r = b->current_bin(); - result = cvm::to_str(r); - return COLVARS_OK; - } - - if (subcmd == "binnum") { - int r = b->bin_num(); - if (r < 0) { - result = "Error: calling bin_num() for bias " + b->name; - return COLVARSCRIPT_ERROR; - } - result = cvm::to_str(r); - return COLVARS_OK; - } - - if (subcmd == "share") { - int r = b->replica_share(); - if (r < 0) { - result = "Error: calling replica_share() for bias " + b->name; - return COLVARSCRIPT_ERROR; - } - result = cvm::to_str(r); - return COLVARS_OK; - } - // End commands for MW ABF - - if (subcmd == "delete") { - // the bias destructor takes care of the cleanup at cvm level - delete b; - // TODO this could be done by the destructors - if (colvars->cv_traj_os != NULL) { - colvars->write_traj_label(*(colvars->cv_traj_os)); - } - return COLVARS_OK; - } - - if ((subcmd == "get") || (subcmd == "set") || (subcmd == "state")) { - return proc_features(b, objc, objv); - } - - if (objc >= 4) { - std::string const param(obj_to_str(objv[3])); - if (subcmd == "count") { - int index; - if (!(std::istringstream(param) >> index)) { - result = "bin_count: error parsing bin index"; - return COLVARSCRIPT_ERROR; - } - result = cvm::to_str(b->bin_count(index)); - return COLVARS_OK; - } - - result = "Syntax error\n" + help_string(); - return COLVARSCRIPT_ERROR; - } - - result = "Syntax error\n" + help_string(); - return COLVARSCRIPT_ERROR; + return error_code; } int colvarscript::proc_features(colvardeps *obj, int objc, unsigned char *const objv[]) { + // size was already checked before calling - std::string const subcmd(obj_to_str(objv[2])); + std::string const subcmd(obj_to_str(objv[3])); - if (objc == 3) { - if (subcmd == "state") { - // TODO make this returned as result? - obj->print_state(); - return COLVARS_OK; + if (cvm::debug()) { + cvm::log("Called proc_features() with " + cvm::to_str(objc) + " args:"); + for (int i = 0; i < objc; i++) { + cvm::log(obj_to_str(objv[i])); } - - // get and set commands require more arguments - result = "Syntax error\n" + help_string(); - return COLVARSCRIPT_ERROR; } if ((subcmd == "get") || (subcmd == "set")) { std::vector const &features = obj->features(); - std::string const req_feature(obj_to_str(objv[3])); + std::string const req_feature(obj_to_str(objv[4])); colvardeps::feature *f = NULL; int fid = 0; for (fid = 0; fid < int(features.size()); fid++) { @@ -576,25 +374,25 @@ int colvarscript::proc_features(colvardeps *obj, if (f == NULL) { - result = "Error: feature \""+req_feature+"\" does not exist.\n"; + add_error_msg("Error: feature \""+req_feature+"\" does not exist.\n"); return COLVARSCRIPT_ERROR; } else { if (! obj->is_available(fid)) { - result = "Error: feature \""+req_feature+"\" is unavailable.\n"; + add_error_msg("Error: feature \""+req_feature+"\" is unavailable.\n"); return COLVARSCRIPT_ERROR; } if (subcmd == "get") { - result = cvm::to_str(obj->is_enabled(fid) ? 1 : 0); + set_result_str(cvm::to_str(obj->is_enabled(fid) ? 1 : 0)); return COLVARS_OK; } if (subcmd == "set") { - if (objc == 5) { + if (objc == 6) { std::string const yesno = - colvarparse::to_lower_cppstr(std::string(obj_to_str(objv[4]))); + colvarparse::to_lower_cppstr(std::string(obj_to_str(objv[5]))); if ((yesno == std::string("yes")) || (yesno == std::string("on")) || (yesno == std::string("1"))) { @@ -607,71 +405,156 @@ int colvarscript::proc_features(colvardeps *obj, return COLVARS_OK; } } - result = "Syntax error\n" + help_string(); + add_error_msg("Missing value when setting feature \""+req_feature+ + "\".\n"); return COLVARSCRIPT_ERROR; } } } - result = "Syntax error\n" + help_string(); + // This shouldn't be reached any more return COLVARSCRIPT_ERROR; } -std::string colvarscript::help_string() const +int colvarscript::unsupported_op() { - std::string buf; - buf = "Usage: cv [args...]\n\ -\n\ -Managing the Colvars module:\n\ - configfile -- read configuration from a file\n\ - config -- read configuration from the given string\n\ - getconfig -- get the module's configuration string\n\ - resetindexgroups -- clear the index groups loaded so far\n\ - reset -- delete all internal configuration\n\ - delete -- delete this Colvars module instance\n\ - version -- return version of Colvars code\n\ - \n\ -Input and output:\n\ - list -- return a list of all variables\n\ - list biases -- return a list of all biases\n\ - load -- load a state file (requires configuration)\n\ - save -- save a state file (requires configuration)\n\ - update -- recalculate colvars and biases\n\ - addenergy -- add to the total bias energy\n\ - printframe -- return a summary of the current frame\n\ - printframelabels -- return labels to annotate printframe's output\n"; + return cvm::error("Error: unsupported script operation.\n", + COLVARS_NOT_IMPLEMENTED); +} - long int tmp; - if (proxy->get_frame(tmp) != COLVARS_NOT_IMPLEMENTED) { - buf += "\ - frame -- return current frame number\n\ - frame -- set frame number\n"; + +int colvarscript::set_result_str(std::string const &s) +{ + if (cvm::get_error() != COLVARS_OK) { + // Avoid overwriting the error message + result += s; + } else { + result = s; + } + return COLVARS_OK; +} + + +void colvarscript::add_error_msg(std::string const &s) +{ + result += s; + // Ensure terminating newlines + if (s[s.size()-1] != '\n') { + result += "\n"; + } +} + + +int colvarscript::clear_str_result() +{ + result.clear(); + return COLVARS_OK; +} + + +extern "C" +int run_colvarscript_command(int objc, unsigned char *const objv[]) +{ + colvarmodule *cv = cvm::main(); + colvarscript *script = cv ? cv->proxy->script : NULL; + if (!script) { + cvm::error("Called run_colvarscript_command without a script object.\n", + BUG_ERROR); + return -1; + } + int retval = script->run(objc, objv); + return retval; +} + + +extern "C" +const char * get_colvarscript_result() +{ + colvarscript *script = colvarscript_obj(); + if (!script) { + cvm::error("Called get_colvarscript_result without a script object.\n"); + return NULL; + } + return script->str_result().c_str(); +} + + +#if defined(COLVARS_TCL) + +#if defined(VMDTCL) +// Function used by VMD to set up the module +int tcl_colvars_vmd_init(Tcl_Interp *interp, int molid); +#endif + +extern "C" +int tcl_run_colvarscript_command(ClientData /* clientData */, + Tcl_Interp *my_interp, + int objc, Tcl_Obj *const objv[]) +{ + colvarmodule *colvars = cvm::main(); + + if (!colvars) { +#if defined(VMDTCL) + if (objc >= 3) { + // require a molid to create the module + if (!strcmp(Tcl_GetString(objv[1]), "molid")) { + int molid = -1; + if (strcmp(Tcl_GetString(objv[2]), "top")) { + // If this is not "top", get the integer value + Tcl_GetIntFromObj(my_interp, objv[2], &molid); + } + return tcl_colvars_vmd_init(my_interp, molid); + } else { + // TODO allow calling cv help after this + Tcl_SetResult(my_interp, (char *) "Syntax error.", TCL_STATIC); + return TCL_ERROR; + } + } + Tcl_SetResult(my_interp, (char *) "First, setup the Colvars module with: " + "cv molid ", TCL_STATIC); +#else + Tcl_SetResult(my_interp, + const_cast("Error: Colvars module not yet initialized"), + TCL_STATIC); +#endif + return TCL_ERROR; } - buf += "\n\ -Accessing collective variables:\n\ - colvar value -- return the current value of colvar \n\ - colvar update -- recalculate colvar \n\ - colvar type -- return the type of colvar \n\ - colvar delete -- delete colvar \n\ - colvar addforce -- apply given force on colvar \n\ - colvar getappliedforce -- return applied force of colvar \n\ - colvar gettotalforce -- return total force of colvar \n\ - colvar getconfig -- return config string of colvar \n\ - colvar cvcflags -- enable or disable cvcs according to 0/1 flags\n\ - colvar modifycvcs -- pass new config strings to each CVC\n\ - colvar get -- get the value of the colvar feature \n\ - colvar set -- set the value of the colvar feature \n\ -\n\ -Accessing biases:\n\ - bias energy -- return the current energy of bias \n\ - bias update -- recalculate bias \n\ - bias delete -- delete bias \n\ - bias getconfig -- return config string of bias \n\ - bias get -- get the value of the bias feature \n\ - bias set -- set the value of the bias feature \n\ -"; + colvarproxy *proxy = colvars->proxy; + Tcl_Interp *interp = my_interp ? my_interp : + reinterpret_cast(proxy->get_tcl_interp()); + colvarscript *script = colvarscript_obj(); + if (!script) { + char const *errstr = "Called tcl_run_colvarscript_command " + "without a Colvars script interface set up.\n"; + Tcl_SetResult(interp, const_cast(errstr), TCL_VOLATILE); + return TCL_ERROR; + } - return buf; + cvm::clear_error(); + + int retval = script->run(objc, + reinterpret_cast(objv)); + + std::string result = proxy->get_error_msgs() + script->result; + + Tcl_SetResult(interp, const_cast(result.c_str()), + TCL_VOLATILE); + + if (proxy->delete_requested() || cvm::get_error_bit(FATAL_ERROR)) { + if (proxy->delete_requested() && !proxy->simulation_running()) { + // Running in VMD + Tcl_SetResult(interp, + const_cast("Deleting Colvars module" + ": to recreate, use cv molid "), + TCL_STATIC); + } + delete proxy; + proxy = NULL; + } + + return (retval == COLVARS_OK) ? TCL_OK : TCL_ERROR; } + +#endif // #if defined(COLVARS_TCL) diff --git a/lib/colvars/colvarscript.h b/lib/colvars/colvarscript.h index 69d52cbb51..d6f77668e6 100644 --- a/lib/colvars/colvarscript.h +++ b/lib/colvars/colvarscript.h @@ -8,7 +8,7 @@ // Colvars repository at GitHub. #ifndef COLVARSCRIPT_H -//#define COLVARSCRIPT_H // Delay definition until later +#define COLVARSCRIPT_H #include #include @@ -29,7 +29,7 @@ class colvarscript { private: - colvarproxy *proxy; + colvarproxy *proxy_; colvarmodule *colvars; inline colvarscript() {} // no-argument construction forbidden @@ -38,8 +38,9 @@ public: friend class colvarproxy; - colvarscript(colvarproxy * p); - inline ~colvarscript() {} + colvarscript(colvarproxy *p); + + ~colvarscript(); /// If an error is caught by the proxy through fatal_error(), this is set to /// COLVARSCRIPT_ERROR @@ -49,112 +50,196 @@ public: /// error message std::string result; - /// Run script command with given positional arguments (objects) + /// Run a script command with space-separated positional arguments (objects) int run(int objc, unsigned char *const objv[]); - /// Set the return value of the script command to the given string - inline void set_str_result(std::string const &s) + /// Get the string result of the current scripting call + inline std::string const &str_result() const { - result = s; + return result; } - /// Build and return a short help - std::string help_string(void) const; + /// Modify the string result of the current scripting call + inline std::string &modify_str_result() + { + return result; + } + + /// Set the return value to the given string + int set_result_str(std::string const &s); + + /// Clear the string result + int clear_str_result(); + + /// Add the given string to the error message of the script interface + void add_error_msg(std::string const &s); + + /// Commands available + enum command { +#define CVSCRIPT_ENUM_COMM(COMM) COMM, +#undef CVSCRIPT +#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + CVSCRIPT_ENUM_COMM(COMM) +#ifdef COLVARSCRIPT_COMMANDS_H +#undef COLVARSCRIPT_COMMANDS_H +#endif +#include "colvarscript_commands.h" +#undef COLVARSCRIPT_COMMANDS_H +#undef CVSCRIPT +#undef CVSCRIPT_ENUM_COMM + cv_n_commands + }; + + /// Type of object handling a script command + enum Object_type { + use_module, + use_colvar, + use_bias + }; + + /// Return the prefix of the individual command for each object function + std::string get_cmd_prefix(Object_type t); + + /// Get a pointer to the i-th argument of the command (NULL if not given) + template + unsigned char *get_cmd_arg(int iarg, int objc, unsigned char *const objv[]); + + /// Instantiation of get_cmd_arg<> for module-level commands + unsigned char *get_module_cmd_arg(int iarg, int objc, + unsigned char *const objv[]); + + /// Instantiation of get_cmd_arg<> for colvar-level commands + unsigned char *get_colvar_cmd_arg(int iarg, int objc, + unsigned char *const objv[]); + + /// Instantiation of get_cmd_arg<> for bias-level commands + unsigned char *get_bias_cmd_arg(int iarg, int objc, + unsigned char *const objv[]); + + /// Check the argument count of the command + template + int check_cmd_nargs(char const *cmd, int objc, + int n_args_min, int n_args_max); + + /// Instantiation of check_cmd_nargs<> for module-level commands + int check_module_cmd_nargs(char const *cmd, int objc, + int n_args_min, int n_args_max); + + /// Instantiation of check_cmd_nargs<> for colvar-level commands + int check_colvar_cmd_nargs(char const *cmd, int objc, + int n_args_min, int n_args_max); + + /// Instantiation of get_cmd_arg<> for bias-level commands + int check_bias_cmd_nargs(char const *cmd, int objc, + int n_args_min, int n_args_max); + + /// Number of positional arguments to shift for each object type + template + int cmd_arg_shift(); /// Use scripting language to get the string representation of an object inline char const *obj_to_str(unsigned char *const obj) { - return cvm::proxy->script_obj_to_str(obj); + return (obj == NULL ? NULL : proxy_->script_obj_to_str(obj)); } - enum command { - cv_help, - cv_version, - cv_config, - cv_getconfig, - cv_configfile, - cv_reset, - cv_resetindexgroups, - cv_delete, - cv_list, - cv_list_biases, - cv_load, - cv_save, - cv_update, - cv_addenergy, - cv_getenergy, - cv_printframe, - cv_printframelabels, - cv_frame, - cv_units, - cv_colvar, - cv_colvar_value, - cv_colvar_update, - cv_colvar_type, - cv_colvar_delete, - cv_colvar_addforce, - cv_colvar_getappliedforce, - cv_colvar_gettotalforce, - cv_colvar_cvcflags, - cv_colvar_getconfig, - cv_colvar_get, - cv_colvar_set, - cv_bias, - cv_bias_energy, - cv_bias_update, - cv_bias_delete, - cv_bias_getconfig, - cv_bias_get, - cv_bias_set, - cv_n_commands - }; + /// Get names of all commands + inline char const **get_command_names() const + { + return cmd_names; + } + + /// Get help string for a command (does not specify how it is launched) + /// \param cmd Name of the command's function (e.g. "cv_units") + std::string get_command_help(char const *cmd); + + /// Get summary of command line syntax for all commands of a given context + /// \param t One of use_module, use_colvar or use_bias + std::string get_cmdline_help_summary(Object_type t); + + /// Get a description of how the command should be used in a command line + /// \param t One of use_module, use_colvar or use_bias + /// \param c Value of the \link command \endlink enum + std::string get_command_cmdline_syntax(Object_type t, command c); + + /// Get the command line syntax following by the help string + /// \param t One of use_module, use_colvar or use_bias + /// \param cmd Name of the subcommand (e.g. "units") + std::string get_command_cmdline_help(Object_type t, std::string const &cmd); + + /// Set error code for unsupported script operation + int unsupported_op(); + + /// Pointer to the Colvars main object + inline colvarmodule *module() + { + return this->colvars; + } + + /// Pointer to the colvarproxy object (interface with host engine) + inline colvarproxy *proxy() + { + return this->proxy_; + } + +private: + + /// Set up all script API functions + int init_commands(); + + /// Set up a single script API function + int init_command(colvarscript::command const &comm, + char const *name, char const *help, + int n_args_min, int n_args_max, char const *arghelp, + int (*fn)(void *, int, unsigned char * const *)); /// Execute a script command inline int exec_command(command c, void *pobj, int objc, unsigned char * const *objv) { - return (*(comm_fns[c]))(pobj, objc, objv); + return (*(cmd_fns[c]))(pobj, objc, objv); } - /// Get help for a command (TODO reformat for each language?) - inline std::string command_help(colvarscript::command c) const - { - return comm_help[c]; - } - - /// Clear all object results - inline void clear_results() - { - result.clear(); - } - -private: - - /// Run subcommands on colvar - int proc_colvar(colvar *cv, int argc, unsigned char *const argv[]); - - /// Run subcommands on bias - int proc_bias(colvarbias *b, int argc, unsigned char *const argv[]); +public: // TODO this function will be removed soon /// Run subcommands on base colvardeps object (colvar, bias, ...) int proc_features(colvardeps *obj, int argc, unsigned char *const argv[]); +private: // TODO + /// Internal identifiers of command strings - std::map comm_str_map; + std::map cmd_str_map; + + /// Inverse of cmd_str_map (to be exported outside this class) + char const **cmd_names; /// Help strings for each command - std::vector comm_help; + std::vector cmd_help; - /// Number of arguments for each command - std::vector comm_n_args; + /// Minimum number of arguments for each command + std::vector cmd_n_args_min; - /// Arguments for each command - std::vector< std::vector > comm_args; + /// Maximum number of arguments for each command + std::vector cmd_n_args_max; + + /// Help strings for each command argument + std::vector< std::vector > cmd_arghelp; /// Implementations of each command - std::vector comm_fns; + std::vector cmd_fns; + + /// Get a pointer to the implementation of the given command + inline int (*get_cmd_fn(std::string const &cmd_key))(void *, + int, + unsigned char * const *) + { + if (cmd_str_map.count(cmd_key) > 0) { + return cmd_fns[cmd_str_map[cmd_key]]; + } + return NULL; + } }; @@ -165,12 +250,14 @@ inline static colvarscript *colvarscript_obj() return cvm::main()->proxy->script; } + /// Get a pointer to the colvar object pointed to by pobj inline static colvar *colvar_obj(void *pobj) { return reinterpret_cast(pobj); } + /// Get a pointer to the colvarbias object pointed to by pobj inline static colvarbias *colvarbias_obj(void *pobj) { @@ -178,137 +265,124 @@ inline static colvarbias *colvarbias_obj(void *pobj) } -#define CVSCRIPT_COMM_FNAME(COMM) cvscript_ ## COMM -#define CVSCRIPT_COMM_PROTO(COMM) \ - int CVSCRIPT_COMM_FNAME(COMM)(void *, int, unsigned char *const *); - -#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ - CVSCRIPT_COMM_PROTO(COMM) - -#undef COLVARSCRIPT_H -#endif // #ifndef COLVARSCRIPT_H +template +unsigned char *colvarscript::get_cmd_arg(int iarg, + int objc, + unsigned char *const objv[]) +{ + int const shift = cmd_arg_shift(); + return (shift+iarg < objc) ? objv[shift+iarg] : NULL; +} -#ifdef COLVARSCRIPT_CPP -#define CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ - extern "C" int CVSCRIPT_COMM_FNAME(COMM)(void *pobj, \ - int objc, \ - unsigned char *const objv[]) \ - { \ - colvarscript *script = colvarscript_obj(); \ - script->clear_results(); \ - if (objc < 2+N_ARGS_MIN) /* "cv" and "COMM" are 1st and 2nd */ { \ - script->set_str_result("Missing arguments\n" + \ - script->command_help(colvarscript::COMM)); \ - return COLVARSCRIPT_ERROR; \ - } \ - if (objc > 2+N_ARGS_MAX) { \ - script->set_str_result("Too many arguments\n" + \ - script->command_help(colvarscript::COMM)); \ - return COLVARSCRIPT_ERROR; \ - } \ - FN_BODY; \ +inline unsigned char *colvarscript::get_module_cmd_arg(int iarg, int objc, + unsigned char *const objv[]) +{ + return get_cmd_arg(iarg, objc, objv); +} + + +inline unsigned char *colvarscript::get_colvar_cmd_arg(int iarg, int objc, + unsigned char *const objv[]) +{ + return get_cmd_arg(iarg, objc, objv); +} + + +inline unsigned char *colvarscript::get_bias_cmd_arg(int iarg, int objc, + unsigned char *const objv[]) +{ + return get_cmd_arg(iarg, objc, objv); +} + + +template +int colvarscript::check_cmd_nargs(char const *cmd, + int objc, + int n_args_min, + int n_args_max) +{ + int const shift = cmd_arg_shift(); + if (objc < shift+n_args_min) { + add_error_msg("Missing arguments for script function \""+std::string(cmd)+ + "\":\n"+get_command_help(cmd)); + return COLVARSCRIPT_ERROR; } -#undef CVSCRIPT -#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ - CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) -#endif // #ifdef COLVARSCRIPT_CPP - - -#ifdef COLVARSCRIPT_INIT_FN -#define CVSCRIPT_COMM_INIT(COMM,HELP,ARGS) { \ - comm_str_map[#COMM] = COMM; \ - comm_help[COMM] = HELP; \ - comm_fns[COMM] = &(CVSCRIPT_COMM_FNAME(COMM)); \ + if (objc > shift+n_args_max) { + add_error_msg("Too many arguments for script function \""+std::string(cmd)+ + "\":\n"+get_command_help(cmd)); + return COLVARSCRIPT_ERROR; } -#undef CVSCRIPT -#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ - CVSCRIPT_COMM_INIT(COMM,HELP,ARGS) -#endif + return COLVARSCRIPT_OK; +} -#if !defined(COLVARSCRIPT_H) || defined(COLVARSCRIPT_INIT_FN) -#define COLVARSCRIPT_H +inline int colvarscript::check_module_cmd_nargs(char const *cmd, + int objc, + int n_args_min, + int n_args_max) +{ + return check_cmd_nargs(cmd, objc, n_args_min, n_args_max); +} + + +inline int colvarscript::check_colvar_cmd_nargs(char const *cmd, + int objc, + int n_args_min, + int n_args_max) +{ + return check_cmd_nargs(cmd, objc, n_args_min, n_args_max); +} + + +inline int colvarscript::check_bias_cmd_nargs(char const *cmd, + int objc, + int n_args_min, + int n_args_max) +{ + return check_cmd_nargs(cmd, objc, n_args_min, n_args_max); +} + + +template +int colvarscript::cmd_arg_shift() +{ + int shift = 0; + if (T == use_module) { + // "cv" and "COMMAND" are 1st and 2nd argument, and shift is equal to 2 + shift = 2; + } else if (T == use_colvar) { + // Same as above with additional arguments "colvar" and "NAME" + shift = 4; + } else if (T == use_bias) { + shift = 4; + } + return shift; +} + -#ifndef COLVARSCRIPT_INIT_FN -#ifdef __cplusplus extern "C" { -#endif -#endif - // Add optional arguments for command-specific help? - CVSCRIPT(cv_help, - "Print the help message", - 0, 0, - {}, - script->set_str_result(script->help_string()); - return COLVARS_OK; - ) +#if defined(COLVARS_TCL) + /// Run the script API via Tcl command-line interface + /// \param clientData Not used + /// \param my_interp Pointer to Tcl_Interp object (read from Colvars if NULL) + /// \param objc Number of Tcl command parameters + /// \param objv Array of command parameters + /// \return Result of the script command + int tcl_run_colvarscript_command(ClientData clientData, + Tcl_Interp *interp_in, + int objc, Tcl_Obj *const objv[]); +#endif // #if defined(COLVARS_TCL) - CVSCRIPT(cv_config, - "Read configuration from the given string", - 1, 1, - { "conf (str) - Configuration string" }, - std::string const conf(script->obj_to_str(objv[2])); - if (cvm::main()->read_config_string(conf) == COLVARS_OK) { - return COLVARS_OK; - } - script->set_str_result("Error parsing configuration string"); - return COLVARSCRIPT_ERROR; - ) + /// Generic wrapper for string-based scripting + int run_colvarscript_command(int objc, unsigned char *const objv[]); - CVSCRIPT(cv_getconfig, - "Get the module's configuration string read so far", - 0, 0, - { }, - script->set_str_result(cvm::main()->get_config()); - return COLVARS_OK; - ) + /// Get the string result of a script call + const char * get_colvarscript_result(); - CVSCRIPT(cv_resetindexgroups, - "Clear the index groups loaded so far, allowing to replace them", - 0, 0, - { }, - return cvm::main()->reset_index_groups(); - ) +} - CVSCRIPT(cv_addenergy, - "Add an energy to the MD engine", - 1, 1, - { "E (float) - Amount of energy to add" }, - cvm::main()->total_bias_energy += - strtod(script->obj_to_str(objv[2]), NULL); - return COLVARS_OK; - ) - - CVSCRIPT(cv_getenergy, - "Get the current Colvars energy", - 1, 1, - { "E (float) - Store the energy in this variable" }, - double *energy = reinterpret_cast(objv[2]); - *energy = cvm::main()->total_bias_energy; - return COLVARS_OK; - ) - - CVSCRIPT(cv_units, - "Get the current Colvars unit system", - 0, 1, - { }, - if (objc < 3) { - script->set_str_result(cvm::proxy->units); - return COLVARS_OK; - } else { - return cvm::proxy->set_unit_system(script->obj_to_str(objv[2]) , false); - } - ) - -#ifndef COLVARSCRIPT_INIT_FN -#ifdef __cplusplus -} // extern "C" -#endif -#endif - -#undef CVSCRIPT #endif // #ifndef COLVARSCRIPT_H diff --git a/lib/colvars/colvarscript_commands.cpp b/lib/colvars/colvarscript_commands.cpp new file mode 100644 index 0000000000..c74663d2fd --- /dev/null +++ b/lib/colvars/colvarscript_commands.cpp @@ -0,0 +1,65 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + +#include +#include +#include + +#include "colvarproxy.h" +#include "colvardeps.h" +#include "colvarscript.h" +#include "colvarscript_commands.h" + + + +extern "C" +int cvscript_n_commands() +{ + return static_cast(colvarscript::cv_n_commands); +} + + +extern "C" +char const **cvscript_command_names() +{ + colvarscript *script = colvarscript_obj(); + return script->get_command_names(); +} + + +// Instantiate the body of all script commands + +#define CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + int CVSCRIPT_COMM_FNAME(COMM)(void *pobj, \ + int objc, unsigned char *const objv[]) \ + { \ + if (cvm::debug()) { \ + cvm::log("Executing script function \""+std::string(#COMM)+"\""); \ + } \ + colvarscript *script = colvarscript_obj(); \ + script->clear_str_result(); \ + if (script->check_module_cmd_nargs(#COMM, \ + objc, N_ARGS_MIN, N_ARGS_MAX) != \ + COLVARSCRIPT_OK) { \ + return COLVARSCRIPT_ERROR; \ + } \ + FN_BODY; \ + } +#undef CVSCRIPT +#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) + +// Skips the colvar- and bias- specific commands +#define COLVARSCRIPT_COMMANDS_GLOBAL + +#undef COLVARSCRIPT_COMMANDS_H +#include "colvarscript_commands.h" + +#undef CVSCRIPT_COMM_FN +#undef CVSCRIPT diff --git a/lib/colvars/colvarscript_commands.h b/lib/colvars/colvarscript_commands.h new file mode 100644 index 0000000000..d90a3ac422 --- /dev/null +++ b/lib/colvars/colvarscript_commands.h @@ -0,0 +1,407 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + +#ifndef COLVARSCRIPT_COMMANDS_H +#define COLVARSCRIPT_COMMANDS_H + +// The following is a complete definition of the scripting API. + +// The CVSCRIPT macro is used in four distinct contexts: +// 1) Expand to the functions' prototypes (when included generically) +// 2) List colvarscript::command entries (when included in colvarscript.h) +// 3) Implement colvarscript::init() (when included in colvarscript.cpp) +// 4) Define the functions' bodies (when included in colvarscript_commands.cpp) + + +// Each command is created by an instance of the CVSCRIPT macro + +// The arguments of the CVSCRIPT macro are: + +// COMM = the id of the command (must be a member of colvarscript::command) + +// HELP = a one-line description (C string literal) for the command + +// N_ARGS_MIN = the lowest number of arguments allowed + +// N_ARGS_MAX = the highest number of arguments allowed + +// ARGS = multi-line string literal describing each parameter; each line +// follows the format "name : type - description" + +// FN_BODY = the implementation of the function; this should be a thin wrapper +// over existing functions; the "script" pointer to the colvarscript +// object is already set by the CVSCRIPT_COMM_FN macro; see also the +// functions in colvarscript_commands.h. + +#ifndef CVSCRIPT_COMM_FNAME +#define CVSCRIPT_COMM_FNAME(COMM) cvscript_ ## COMM +#endif + +// If CVSCRIPT is not defined, this file yields the function prototypes +#ifndef CVSCRIPT + +#ifdef __cplusplus +#define CVSCRIPT_COMM_PROTO(COMM) \ + extern "C" int CVSCRIPT_COMM_FNAME(COMM)(void *, \ + int, unsigned char *const *); +#else +#define CVSCRIPT_COMM_PROTO(COMM) \ + int CVSCRIPT_COMM_FNAME(COMM)(void *, int, unsigned char *const *); +#endif + +#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + CVSCRIPT_COMM_PROTO(COMM) + + +// Utility functions used to query the command database +extern "C" { + + /// Get the number of colvarscript commands + int cvscript_n_commands(); + + /// Get the names of all commands (array of strings) + char const ** cvscript_command_names(); + +} + +#endif + + +CVSCRIPT(cv_addenergy, + "Add an energy to the MD engine (no effect in VMD)", + 1, 1, + "E : float - Amount of energy to add", + char const *Earg = + script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)); + cvm::main()->total_bias_energy += strtod(Earg, NULL); + return cvm::get_error(); // TODO Make this multi-language + ) + +CVSCRIPT(cv_bias, + "Prefix for bias-specific commands", + 0, 0, + "", + // This cannot be executed from a command line + return COLVARS_OK; + ) + +CVSCRIPT(cv_colvar, + "Prefix for colvar-specific commands", + 0, 0, + "", + // This cannot be executed from a command line + return COLVARS_OK; + ) + +CVSCRIPT(cv_config, + "Read configuration from the given string", + 1, 1, + "conf : string - Configuration string", + char const *conf_str = + script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)); + std::string const conf(conf_str); + if (cvm::main()->read_config_string(conf) == COLVARS_OK) { + return COLVARS_OK; + } + script->add_error_msg("Error parsing configuration string"); + return COLVARSCRIPT_ERROR; + ) + +CVSCRIPT(cv_configfile, + "Read configuration from a file", + 1, 1, + "conf_file : string - Path to configuration file", + char const *conf_file_name = + script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)); + if (script->module()->read_config_file(conf_file_name) == COLVARS_OK) { + return COLVARS_OK; + } else { + script->add_error_msg("Error parsing configuration file"); + return COLVARSCRIPT_ERROR; + } + ) + +CVSCRIPT(cv_delete, + "Delete this Colvars module instance (VMD only)", + 0, 0, + "", + return script->proxy()->request_deletion(); + ) + +CVSCRIPT(cv_frame, + "Get or set current frame number (VMD only)", + 0, 1, + "frame : integer - Frame number", + char const *arg = + script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)); + if (arg == NULL) { + long int f = -1; + if (script->proxy()->get_frame(f) == COLVARS_OK) { + script->set_result_str(cvm::to_str(f)); + return COLVARS_OK; + } else { + script->add_error_msg("Frame number is not available"); + return COLVARSCRIPT_ERROR; + } + } else { + int const f = strtol(const_cast(arg), NULL, 10); + int error_code = script->proxy()->set_frame(f); + if (error_code == COLVARS_NO_SUCH_FRAME) { + script->add_error_msg("Invalid frame number: \""+std::string(arg)+ + "\"\n"); + } + return error_code; + } + return COLVARS_OK; + ) + +CVSCRIPT(cv_getconfig, + "Get the module's configuration string read so far", + 0, 0, + "", + script->set_result_str(cvm::main()->get_config()); + return COLVARS_OK; + ) + +CVSCRIPT(cv_getenergy, + "Get the current Colvars energy", + 0, 0, + "", + script->set_result_str(cvm::to_str(cvm::main()->total_bias_energy)); + return COLVARS_OK; + ) + +CVSCRIPT(cv_help, + "Get the help string of the Colvars scripting interface", + 0, 1, + "command : string - Get the help string of this specific command", + unsigned char *const cmdobj = + script->get_module_cmd_arg(0, objc, objv); + if (cmdobj) { + std::string const cmdstr(script->obj_to_str(cmdobj)); + if (cmdstr.size()) { + if (cmdstr == std::string("colvar")) { + script->set_result_str(script->get_cmdline_help_summary(colvarscript::use_colvar)); + } else if (cmdstr == std::string("bias")) { + script->set_result_str(script->get_cmdline_help_summary(colvarscript::use_bias)); + } else { + script->set_result_str(script->get_command_cmdline_help(colvarscript::use_module, + cmdstr)); + } + return cvm::get_error(); + } else { + return COLVARSCRIPT_ERROR; + } + } else { + script->set_result_str(script->get_cmdline_help_summary(colvarscript::use_module)); + return COLVARS_OK; + } + ) + +CVSCRIPT(cv_list, + "Return a list of all variables or biases", + 0, 1, + "param : string - \"colvars\" or \"biases\"; default is \"colvars\"", + std::string res; + unsigned char *const kwarg = script->get_module_cmd_arg(0, objc, objv); + std::string const kwstr = kwarg ? script->obj_to_str(kwarg) : + std::string("colvars"); + if (kwstr == "colvars") { + for (std::vector::iterator cvi = script->module()->variables()->begin(); + cvi != script->module()->variables()->end(); + ++cvi) { + res += (cvi == script->module()->variables()->begin() ? "" : " ") + (*cvi)->name; + } + script->set_result_str(res); + return COLVARS_OK; + } else if (kwstr == "biases") { + for (std::vector::iterator bi = script->module()->biases.begin(); + bi != script->module()->biases.end(); + ++bi) { + res += (bi == script->module()->biases.begin() ? "" : " ") + (*bi)->name; + } + script->set_result_str(res); + return COLVARS_OK; + } else { + script->add_error_msg("Wrong arguments to command \"list\"\n"); + return COLVARSCRIPT_ERROR; + } + ) + +CVSCRIPT(cv_listcommands, + "Get the list of script functions, prefixed with \"cv_\", \"colvar_\" or \"bias_\"", + 0, 0, + "", + int const n_commands = cvscript_n_commands(); + char const **command_names = cvscript_command_names(); + std::string result; + for (int i = 0; i < n_commands; i++) { + if (i > 0) result.append(1, ' '); + result.append(std::string(command_names[i])); + } + script->set_result_str(result); + return COLVARS_OK; + ) + +CVSCRIPT(cv_load, + "Load data from a state file into all matching colvars and biases", + 1, 1, + "prefix : string - Path to existing state file or input prefix", + char const *arg = + script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)); + script->proxy()->input_prefix() = cvm::state_file_prefix(arg); + if (script->module()->setup_input() == COLVARS_OK) { + return COLVARS_OK; + } else { + script->add_error_msg("Error loading state file"); + return COLVARSCRIPT_ERROR; + } + ) + +CVSCRIPT(cv_loadfromstring, + "Load state data from a string into all matching colvars and biases", + 1, 1, + "buffer : string - String buffer containing the state information", + char const *arg = + script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)); + script->proxy()->input_buffer() = arg; + if (script->module()->setup_input() == COLVARS_OK) { + return COLVARS_OK; + } else { + script->add_error_msg("Error loading state string"); + return COLVARSCRIPT_ERROR; + } + ) + +CVSCRIPT(cv_molid, + "Get or set the molecule ID on which Colvars is defined (VMD only)", + 0, 1, + "molid : integer - Molecule ID; -1 means undefined", + char const *arg = + script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)); + if (arg == NULL) { + int molid = -1; + script->proxy()->get_molid(molid); + script->set_result_str(cvm::to_str(molid)); + return COLVARS_OK; + } else { + script->add_error_msg("Error: To change the molecule ID in VMD, use cv delete first."); + return COLVARS_NOT_IMPLEMENTED; + } + ) + +CVSCRIPT(cv_printframe, + "Return the values that would be written to colvars.traj", + 0, 0, + "", + std::ostringstream os; + script->module()->write_traj(os); + script->set_result_str(os.str()); + return COLVARS_OK; + ) + +CVSCRIPT(cv_printframelabels, + "Return the labels that would be written to colvars.traj", + 0, 0, + "", + std::ostringstream os; + script->module()->write_traj_label(os); + script->set_result_str(os.str()); + return COLVARS_OK; + ) + +CVSCRIPT(cv_reset, + "Delete all internal configuration", + 0, 0, + "", + return script->module()->reset(); + ) + +CVSCRIPT(cv_resetindexgroups, + "Clear the index groups loaded so far, allowing to replace them", + 0, 0, + "", + cvm::main()->index_group_names.clear(); + cvm::main()->index_groups.clear(); + return COLVARS_OK; + ) + +CVSCRIPT(cv_save, + "Change the prefix of all output files and save them", + 1, 1, + "prefix : string - Output prefix with trailing \".colvars.state\" gets removed)", + std::string const prefix = + cvm::state_file_prefix(script->obj_to_str(script->get_module_cmd_arg(0, objc, objv))); + script->proxy()->output_prefix() = prefix; + int error_code = COLVARS_OK; + error_code |= script->module()->setup_output(); + error_code |= script->module()->write_restart_file(prefix+ + ".colvars.state"); + error_code |= script->module()->write_output_files(); + return error_code; + ) + +CVSCRIPT(cv_savetostring, + "Write the Colvars state to a string and return it", + 0, 0, + "", + return script->module()->write_restart_string(script->modify_str_result()); + ) + +CVSCRIPT(cv_units, + "Get or set the current Colvars unit system", + 0, 1, + "units : string - The new unit system", + char const *argstr = + script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)); + if (argstr) { + return cvm::proxy->set_unit_system(argstr, false); + } else { + script->set_result_str(cvm::proxy->units); + return COLVARS_OK; + } + ) + +CVSCRIPT(cv_update, + "Recalculate colvars and biases", + 0, 0, + "", + int error_code = script->proxy()->update_input(); + if (error_code) { + script->add_error_msg("Error updating the Colvars module (input)"); + return error_code; + } + error_code |= script->module()->calc(); + if (error_code) { + script->add_error_msg("Error updating the Colvars module (calc)"); + return error_code; + } + error_code |= script->proxy()->update_output(); + if (error_code) { + script->add_error_msg("Error updating the Colvars module (output)"); + } + return error_code; + ) + +CVSCRIPT(cv_version, + "Get the Colvars Module version number", + 0, 0, + "", + script->set_result_str(COLVARS_VERSION); + return COLVARS_OK; + ) + +// This guard allows compiling colvar and bias function bodies in their +// respecitve files instead of colvarscript_commands.o +#ifndef COLVARSCRIPT_COMMANDS_GLOBAL +#include "colvarscript_commands_colvar.h" +#include "colvarscript_commands_bias.h" +#endif + +#endif // #ifndef COLVARSCRIPT_COMMANDS_H diff --git a/lib/colvars/colvarscript_commands_bias.cpp b/lib/colvars/colvarscript_commands_bias.cpp new file mode 100644 index 0000000000..293fbb1fb4 --- /dev/null +++ b/lib/colvars/colvarscript_commands_bias.cpp @@ -0,0 +1,49 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + + +#include +#include +#include +#include + +#include "colvarproxy.h" +#include "colvardeps.h" +#include "colvarscript.h" +#include "colvarscript_commands.h" + + + +// Instantiate the body of all bias-specific script commands + +#define CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + int CVSCRIPT_COMM_FNAME(COMM)(void *pobj, \ + int objc, unsigned char *const objv[]) \ + { \ + if (cvm::debug()) { \ + cvm::log("Executing script function \""+std::string(#COMM)+"\""); \ + } \ + colvarscript *script = colvarscript_obj(); \ + script->clear_str_result(); \ + if (script->check_bias_cmd_nargs(#COMM, \ + objc, N_ARGS_MIN, N_ARGS_MAX) != \ + COLVARSCRIPT_OK) { \ + return COLVARSCRIPT_ERROR; \ + } \ + colvarbias *this_bias = colvarbias_obj(pobj); \ + FN_BODY; \ + } +#undef CVSCRIPT +#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) + +#include "colvarscript_commands_bias.h" + +#undef CVSCRIPT_COMM_FN +#undef CVSCRIPT diff --git a/lib/colvars/colvarscript_commands_bias.h b/lib/colvars/colvarscript_commands_bias.h new file mode 100644 index 0000000000..990902e239 --- /dev/null +++ b/lib/colvars/colvarscript_commands_bias.h @@ -0,0 +1,173 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + + +CVSCRIPT(bias_bin, + "Get the current grid bin index (1D ABF only for now)", + 0, 0, + "", + script->set_result_str(cvm::to_str(this_bias->current_bin())); + return COLVARS_OK; + ) + +CVSCRIPT(bias_bincount, + "Get the number of samples at the given grid bin (1D ABF only for now)", + 0, 1, + "index : integer - Grid index; defaults to current bin", + int index = this_bias->current_bin(); + char const *indexarg = + script->obj_to_str(script->get_bias_cmd_arg(0, objc, objv)); + if (indexarg) { + std::string const param(indexarg); + if (!(std::istringstream(param) >> index)) { + script->add_error_msg("bincount: error parsing bin index"); + return COLVARSCRIPT_ERROR; + } + } + script->set_result_str(cvm::to_str(this_bias->bin_count(index))); + return COLVARS_OK; + ) + +CVSCRIPT(bias_binnum, + "Get the total number of grid points of this bias (1D ABF only for now)", + 0, 0, + "", + int r = this_bias->bin_num(); + if (r < 0) { + script->add_error_msg("Error: calling bin_num() for bias " + + this_bias->name); + return COLVARSCRIPT_ERROR; + } + script->set_result_str(cvm::to_str(r)); + return COLVARS_OK; + ) + +CVSCRIPT(bias_delete, + "Delete this bias", + 0, 0, + "", + delete this_bias; + return COLVARS_OK; + ) + +CVSCRIPT(bias_energy, + "Get the current energy of this bias", + 0, 0, + "", + script->set_result_str(cvm::to_str(this_bias->get_energy())); + return COLVARS_OK; + ) + +CVSCRIPT(bias_get, + "Get the value of the given feature for this bias", + 1, 1, + "feature : string - Name of the feature", + return script->proc_features(this_bias, objc, objv); + ) + +CVSCRIPT(bias_getconfig, + "Return the configuration string of this bias", + 0, 0, + "", + script->set_result_str(this_bias->get_config()); + return COLVARS_OK; + ) + +CVSCRIPT(bias_help, + "Get a help summary or the help string of one bias subcommand", + 0, 1, + "command : string - Get the help string of this specific command", + unsigned char *const cmdobj = + script->get_colvar_cmd_arg(0, objc, objv); + if (this_bias) { + } + if (cmdobj) { + std::string const cmdstr(script->obj_to_str(cmdobj)); + if (cmdstr.size()) { + script->set_result_str(script->get_command_cmdline_help(colvarscript::use_bias, + cmdstr)); + return COLVARS_OK; + } else { + return COLVARSCRIPT_ERROR; + } + } else { + script->set_result_str(script->get_cmdline_help_summary(colvarscript::use_bias)); + return COLVARS_OK; + } + ) + +CVSCRIPT(bias_load, + "Load data into this bias", + 1, 1, + "prefix : string - Read from a file with this name or prefix", + char const *arg = + script->obj_to_str(script->get_bias_cmd_arg(0, objc, objv)); + return this_bias->read_state_prefix(std::string(arg)); + ) + +CVSCRIPT(bias_loadfromstring, + "Load state data into this bias from a string", + 1, 1, + "buffer : string - String buffer containing the state information", + char const *buffer = script->obj_to_str(script->get_bias_cmd_arg(0, objc, objv)); + return this_bias->read_state_string(buffer); + ) + +CVSCRIPT(bias_save, + "Save data from this bias into a file with the given prefix", + 1, 1, + "prefix : string - Prefix for the state file of this bias", + std::string const prefix = + cvm::state_file_prefix(script->obj_to_str(script->get_bias_cmd_arg(0, objc, objv))); + return this_bias->write_state_prefix(prefix); + ) + +CVSCRIPT(bias_savetostring, + "Save data from this bias into a string and return it", + 0, 0, + "", + return this_bias->write_state_string(script->modify_str_result()); + ) + +CVSCRIPT(bias_set, + "Set the given feature of this bias to a new value", + 2, 2, + "feature : string - Name of the feature\n" + "value : string - String representation of the new feature value", + return script->proc_features(this_bias, objc, objv); + ) + +CVSCRIPT(bias_share, + "Share bias information with other replicas (multiple-walker scheme)", + 0, 0, + "", + if (this_bias->replica_share() != COLVARS_OK) { + script->add_error_msg("Error: calling replica_share() for bias " + + this_bias->name); + return COLVARSCRIPT_ERROR; + } + return COLVARS_OK; + ) + +CVSCRIPT(bias_state, + "Print a string representation of the feature state of this bias", + 0, 0, + "", + this_bias->print_state(); + return COLVARS_OK; + ) + +CVSCRIPT(bias_update, + "Recompute this bias and return its up-to-date energy", + 0, 0, + "", + this_bias->update(); + script->set_result_str(cvm::to_str(this_bias->get_energy())); + return COLVARS_OK; + ) diff --git a/lib/colvars/colvarscript_commands_colvar.cpp b/lib/colvars/colvarscript_commands_colvar.cpp new file mode 100644 index 0000000000..12c90ceb2b --- /dev/null +++ b/lib/colvars/colvarscript_commands_colvar.cpp @@ -0,0 +1,49 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + + +#include +#include +#include +#include + +#include "colvarproxy.h" +#include "colvardeps.h" +#include "colvarscript.h" +#include "colvarscript_commands.h" + + + +// Instantiate the body of all colvar-specific script commands + +#define CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + int CVSCRIPT_COMM_FNAME(COMM)(void *pobj, \ + int objc, unsigned char *const objv[]) \ + { \ + if (cvm::debug()) { \ + cvm::log("Executing script function \""+std::string(#COMM)+"\""); \ + } \ + colvarscript *script = colvarscript_obj(); \ + script->clear_str_result(); \ + if (script->check_colvar_cmd_nargs(#COMM, \ + objc, N_ARGS_MIN, N_ARGS_MAX) != \ + COLVARSCRIPT_OK) { \ + return COLVARSCRIPT_ERROR; \ + } \ + colvar *this_colvar = colvar_obj(pobj); \ + FN_BODY; \ + } +#undef CVSCRIPT +#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ + CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) + +#include "colvarscript_commands_colvar.h" + +#undef CVSCRIPT_COMM_FN +#undef CVSCRIPT diff --git a/lib/colvars/colvarscript_commands_colvar.h b/lib/colvars/colvarscript_commands_colvar.h new file mode 100644 index 0000000000..b880b5b8be --- /dev/null +++ b/lib/colvars/colvarscript_commands_colvar.h @@ -0,0 +1,239 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/Colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + + +CVSCRIPT(colvar_addforce, + "Apply the given force onto this colvar and return the same", + 1, 1, + "force : float or array - Applied force; must match colvar dimensionality", + std::string const f_str(script->obj_to_str(script->get_colvar_cmd_arg(0, objc, objv))); + std::istringstream is(f_str); + is.width(cvm::cv_width); + is.precision(cvm::cv_prec); + colvarvalue force(this_colvar->value()); + force.is_derivative(); + if (force.from_simple_string(is.str()) != COLVARS_OK) { + script->add_error_msg("addforce : error parsing force value"); + return COLVARSCRIPT_ERROR; + } + this_colvar->add_bias_force(force); + script->set_result_str(force.to_simple_string()); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_cvcflags, + "Enable or disable individual components by setting their active flags", + 1, 1, + "flags : integer array - Zero/nonzero value disables/enables the CVC", + std::string const flags_str(script->obj_to_str(script->get_colvar_cmd_arg(0, objc, objv))); + std::istringstream is(flags_str); + std::vector flags; + int flag; + while (is >> flag) { + flags.push_back(flag != 0); + } + int res = this_colvar->set_cvc_flags(flags); + if (res != COLVARS_OK) { + script->add_error_msg("Error setting CVC flags"); + return COLVARSCRIPT_ERROR; + } + script->set_result_str("0"); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_delete, + "Delete this colvar, along with all biases that depend on it", + 0, 0, + "", + delete this_colvar; + return COLVARS_OK; + ) + +CVSCRIPT(colvar_get, + "Get the value of the given feature for this colvar", + 1, 1, + "feature : string - Name of the feature", + return script->proc_features(this_colvar, objc, objv); + ) + +CVSCRIPT(colvar_getappliedforce, + "Return the total of the forces applied to this colvar", + 0, 0, + "", + script->set_result_str((this_colvar->applied_force()).to_simple_string()); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_getatomgroups, + "Return the atom indices used by this colvar as a list of lists", + 0, 0, + "", + std::string result; + std::vector > lists = this_colvar->get_atom_lists(); + std::vector >::iterator li = lists.begin(); + for ( ; li != lists.end(); ++li) { + result += "{"; + std::vector::iterator lj = (*li).begin(); + for ( ; lj != (*li).end(); ++lj) { + result += cvm::to_str(*lj); + result += " "; + } + result += "} "; + } + script->set_result_str(result); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_getatomids, + "Return the list of atom indices used by this colvar", + 0, 0, + "", + std::string result; + std::vector::iterator li = this_colvar->atom_ids.begin(); + for ( ; li != this_colvar->atom_ids.end(); ++li) { + result += cvm::to_str(*li); + result += " "; + } + script->set_result_str(result); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_getconfig, + "Return the configuration string of this colvar", + 0, 0, + "", + script->set_result_str(this_colvar->get_config()); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_getgradients, + "Return the atomic gradients of this colvar", + 0, 0, + "", + std::string result; + std::vector::iterator li = + this_colvar->atomic_gradients.begin(); + for ( ; li != this_colvar->atomic_gradients.end(); ++li) { + result += "{"; + int j; + for (j = 0; j < 3; ++j) { + result += cvm::to_str((*li)[j]); + result += " "; + } + result += "} "; + } + script->set_result_str(result); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_gettotalforce, + "Return the sum of internal and external forces to this colvar", + 0, 0, + "", + script->set_result_str((this_colvar->total_force()).to_simple_string()); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_help, + "Get a help summary or the help string of one colvar subcommand", + 0, 1, + "command : string - Get the help string of this specific command", + unsigned char *const cmdobj = + script->get_colvar_cmd_arg(0, objc, objv); + if (this_colvar) { + } + if (cmdobj) { + std::string const cmdstr(script->obj_to_str(cmdobj)); + if (cmdstr.size()) { + script->set_result_str(script->get_command_cmdline_help(colvarscript::use_colvar, + cmdstr)); + return cvm::get_error(); + } else { + return COLVARSCRIPT_ERROR; + } + } else { + script->set_result_str(script->get_cmdline_help_summary(colvarscript::use_colvar)); + return COLVARS_OK; + } + ) + +CVSCRIPT(colvar_modifycvcs, + "Modify configuration of individual components by passing string arguments", + 1, 1, + "confs : sequence of strings - New configurations; empty strings are skipped", + std::vector const confs(script->proxy()->script_obj_to_str_vector(script->get_colvar_cmd_arg(0, objc, objv))); + cvm::increase_depth(); + int res = this_colvar->update_cvc_config(confs); + cvm::decrease_depth(); + if (res != COLVARS_OK) { + script->add_error_msg("Error setting CVC flags"); + return COLVARSCRIPT_ERROR; + } + script->set_result_str("0"); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_run_ave, + "Get the current running average of the value of this colvar", + 0, 0, + "", + script->set_result_str(this_colvar->run_ave().to_simple_string()); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_set, + "Set the given feature of this colvar to a new value", + 2, 2, + "feature : string - Name of the feature\n" + "value : string - String representation of the new feature value", + return script->proc_features(this_colvar, objc, objv); + ) + +CVSCRIPT(colvar_state, + "Print a string representation of the feature state of this colvar", + 0, 0, + "", + this_colvar->print_state(); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_type, + "Get the type description of this colvar", + 0, 0, + "", + script->set_result_str(this_colvar->value().type_desc(this_colvar->value().value_type)); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_update, + "Recompute this colvar and return its up-to-date value", + 0, 0, + "", + this_colvar->calc(); + this_colvar->update_forces_energy(); + script->set_result_str((this_colvar->value()).to_simple_string()); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_value, + "Get the current value of this colvar", + 0, 0, + "", + script->set_result_str(this_colvar->value().to_simple_string()); + return COLVARS_OK; + ) + +CVSCRIPT(colvar_width, + "Get the width of this colvar", + 0, 0, + "", + script->set_result_str(cvm::to_str(this_colvar->width, 0, + cvm::cv_prec)); + return COLVARS_OK; + ) diff --git a/lib/colvars/colvartypes.cpp b/lib/colvars/colvartypes.cpp index da00183323..3cbaed63a8 100644 --- a/lib/colvars/colvartypes.cpp +++ b/lib/colvars/colvartypes.cpp @@ -14,25 +14,19 @@ #include "colvartypes.h" #include "colvarparse.h" +#ifdef COLVARS_LAMMPS +// Use open-source Jacobi implementation +#include "math_eigen_impl.h" +#else +// Fall back to NR routine +#include "nr_jacobi.h" +#endif + bool colvarmodule::rotation::monitor_crossings = false; cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-02; -namespace { - -/// Numerical recipes diagonalization -static int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot); - -/// Eigenvector sort -static int eigsrt(cvm::real *d, cvm::real **v); - -/// Transpose the matrix -static int transpose(cvm::real **v); - -} - - std::string cvm::rvector::to_simple_string() const { std::ostringstream os; @@ -74,7 +68,7 @@ std::ostream & operator << (std::ostream &os, colvarmodule::rvector const &v) std::istream & operator >> (std::istream &is, colvarmodule::rvector &v) { - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); char sep; if ( !(is >> sep) || !(sep == '(') || !(is >> v.x) || !(is >> sep) || !(sep == ',') || @@ -130,7 +124,7 @@ std::ostream & operator << (std::ostream &os, colvarmodule::quaternion const &q) std::istream & operator >> (std::istream &is, colvarmodule::quaternion &q) { - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); std::string euler(""); @@ -248,6 +242,66 @@ cvm::quaternion::position_derivative_inner(cvm::rvector const &pos, // Seok C, Dill KA. Using quaternions to calculate RMSD. J Comput // Chem. 25(15):1849-57 (2004) DOI: 10.1002/jcc.20110 PubMed: 15376254 +#ifdef COLVARS_LAMMPS +namespace { + inline void *new_Jacobi_solver(int size) { + return reinterpret_cast(new MathEigen::Jacobi &, + cvm::matrix2d &>(4)); + } +} +#endif + + +colvarmodule::rotation::rotation() +{ + b_debug_gradients = false; +#ifdef COLVARS_LAMMPS + jacobi = new_Jacobi_solver(4); +#else + jacobi = NULL; +#endif +} + + +colvarmodule::rotation::rotation(cvm::quaternion const &qi) + : q(qi) +{ + b_debug_gradients = false; +#ifdef COLVARS_LAMMPS + jacobi = new_Jacobi_solver(4); +#else + jacobi = NULL; +#endif +} + + +colvarmodule::rotation::rotation(cvm::real angle, cvm::rvector const &axis) +{ + b_debug_gradients = false; + cvm::rvector const axis_n = axis.unit(); + cvm::real const sina = cvm::sin(angle/2.0); + q = cvm::quaternion(cvm::cos(angle/2.0), + sina * axis_n.x, sina * axis_n.y, sina * axis_n.z); +#ifdef COLVARS_LAMMPS + jacobi = new_Jacobi_solver(4); +#else + jacobi = NULL; +#endif +} + + +colvarmodule::rotation::~rotation() +{ +#ifdef COLVARS_LAMMPS + delete reinterpret_cast< + MathEigen::Jacobi &, + cvm::matrix2d &> *>(jacobi); +#endif +} + + void colvarmodule::rotation::build_correlation_matrix( std::vector const &pos1, std::vector const &pos2) @@ -291,10 +345,12 @@ void colvarmodule::rotation::compute_overlap_matrix() } -void colvarmodule::rotation::diagonalize_matrix( - cvm::matrix2d &m, - cvm::vector1d &eigval, - cvm::matrix2d &eigvec) +#ifndef COLVARS_LAMMPS +namespace { + +void diagonalize_matrix(cvm::matrix2d &m, + cvm::vector1d &eigval, + cvm::matrix2d &eigvec) { eigval.resize(4); eigval.reset(); @@ -303,15 +359,15 @@ void colvarmodule::rotation::diagonalize_matrix( // diagonalize int jac_nrot = 0; - if (jacobi(m.c_array(), eigval.c_array(), eigvec.c_array(), &jac_nrot) != + if (NR_Jacobi::jacobi(m.c_array(), eigval.c_array(), eigvec.c_array(), &jac_nrot) != COLVARS_OK) { - cvm::error("Too many iterations in routine jacobi.\n" + cvm::error("Too many iterations in jacobi diagonalization.\n" "This is usually the result of an ill-defined set of atoms for " "rotational alignment (RMSD, rotateReference, etc).\n"); } - eigsrt(eigval.c_array(), eigvec.c_array()); + NR_Jacobi::eigsrt(eigval.c_array(), eigvec.c_array()); // jacobi saves eigenvectors by columns - transpose(eigvec.c_array()); + NR_Jacobi::transpose(eigvec.c_array()); // normalize eigenvectors for (size_t ie = 0; ie < 4; ie++) { @@ -327,6 +383,9 @@ void colvarmodule::rotation::diagonalize_matrix( } } +} +#endif + // Calculate the rotation, plus its derivatives @@ -349,7 +408,28 @@ void colvarmodule::rotation::calc_optimal_rotation( cvm::log("S = "+cvm::to_str(S_backup, cvm::cv_width, cvm::cv_prec)+"\n"); } + S_eigval.resize(4); + S_eigvec.resize(4, 4); + +#ifdef COLVARS_LAMMPS + MathEigen::Jacobi &, + cvm::matrix2d &> *ecalc = + reinterpret_cast &, + cvm::matrix2d &> *>(jacobi); + + int ierror = ecalc->Diagonalize(S, S_eigval, S_eigvec); + if (ierror) { + cvm::error("Too many iterations in jacobi diagonalization.\n" + "This is usually the result of an ill-defined set of atoms for " + "rotational alignment (RMSD, rotateReference, etc).\n"); + } +#else diagonalize_matrix(S, S_eigval, S_eigvec); +#endif + + // eigenvalues and eigenvectors cvm::real const L0 = S_eigval[0]; cvm::real const L1 = S_eigval[1]; @@ -521,7 +601,11 @@ void colvarmodule::rotation::calc_optimal_rotation( // cvm::log("S_new = "+cvm::to_str(cvm::to_str (S_new), cvm::cv_width, cvm::cv_prec)+"\n"); +#ifdef COLVARS_LAMMPS + ecalc->Diagonalize(S_new, S_new_eigval, S_new_eigvec); +#else diagonalize_matrix(S_new, S_new_eigval, S_new_eigvec); +#endif cvm::real const &L0_new = S_new_eigval[0]; cvm::quaternion const Q0_new(S_new_eigvec[0]); @@ -544,138 +628,3 @@ void colvarmodule::rotation::calc_optimal_rotation( -// Numerical Recipes routine for diagonalization - -#define ROTATE(a,i,j,k,l) g=a[i][j]; \ - h=a[k][l]; \ - a[i][j]=g-s*(h+g*tau); \ - a[k][l]=h+s*(g-h*tau); - -#define n 4 - - -namespace { - -int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot) -{ - int j,iq,ip,i; - cvm::real tresh,theta,tau,t,sm,s,h,g,c; - - cvm::vector1d b(n); - cvm::vector1d z(n); - - for (ip=0;ip 4 && (cvm::real)(cvm::fabs(d[ip])+g) == (cvm::real)cvm::fabs(d[ip]) - && (cvm::real)(cvm::fabs(d[iq])+g) == (cvm::real)cvm::fabs(d[iq])) - a[ip][iq]=0.0; - else if (cvm::fabs(a[ip][iq]) > tresh) { - h=d[iq]-d[ip]; - if ((cvm::real)(cvm::fabs(h)+g) == (cvm::real)cvm::fabs(h)) - t=(a[ip][iq])/h; - else { - theta=0.5*h/(a[ip][iq]); - t=1.0/(cvm::fabs(theta)+cvm::sqrt(1.0+theta*theta)); - if (theta < 0.0) t = -t; - } - c=1.0/cvm::sqrt(1+t*t); - s=t*c; - tau=s/(1.0+c); - h=t*a[ip][iq]; - z[ip] -= h; - z[iq] += h; - d[ip] -= h; - d[iq] += h; - a[ip][iq]=0.0; - for (j=0;j<=ip-1;j++) { - ROTATE(a,j,ip,j,iq) - } - for (j=ip+1;j<=iq-1;j++) { - ROTATE(a,ip,j,j,iq) - } - for (j=iq+1;j= p) p=d[k=j]; - if (k != i) { - d[k]=d[i]; - d[i]=p; - for (j=0;j &v) { if (v.size() == 0) return is; - size_t const start_pos = is.tellg(); + std::streampos const start_pos = is.tellg(); char sep; if ( !(is >> sep) || !(sep == '(') ) { is.clear(); @@ -1389,30 +1389,16 @@ public: std::vector const &pos2); /// Default constructor - inline rotation() - : b_debug_gradients(false) - {} + rotation(); /// Constructor after a quaternion - inline rotation(cvm::quaternion const &qi) - : q(qi), - b_debug_gradients(false) - { - } + rotation(cvm::quaternion const &qi); /// Constructor after an axis of rotation and an angle (in radians) - inline rotation(cvm::real angle, cvm::rvector const &axis) - : b_debug_gradients(false) - { - cvm::rvector const axis_n = axis.unit(); - cvm::real const sina = cvm::sin(angle/2.0); - q = cvm::quaternion(cvm::cos(angle/2.0), - sina * axis_n.x, sina * axis_n.y, sina * axis_n.z); - } + rotation(cvm::real angle, cvm::rvector const &axis); /// Destructor - inline ~rotation() - {} + ~rotation(); /// Return the rotated vector inline cvm::rvector rotate(cvm::rvector const &v) const @@ -1432,7 +1418,6 @@ public: return q.rotation_matrix(); } - /// \brief Return the spin angle (in degrees) with respect to the /// provided axis (which MUST be normalized) inline cvm::real spin_angle(cvm::rvector const &axis) const @@ -1537,10 +1522,8 @@ protected: /// Compute the overlap matrix S (used by calc_optimal_rotation()) void compute_overlap_matrix(); - /// Diagonalize a given matrix m (used by calc_optimal_rotation()) - static void diagonalize_matrix(cvm::matrix2d &m, - cvm::vector1d &eigval, - cvm::matrix2d &eigvec); + /// Pointer to instance of Jacobi solver + void *jacobi; }; diff --git a/lib/gpu/Makefile.linux b/lib/gpu/Makefile.linux index 3fa1dcdce6..da18ae41ca 100644 --- a/lib/gpu/Makefile.linux +++ b/lib/gpu/Makefile.linux @@ -57,7 +57,7 @@ CUDA_INCLUDE = -I$(CUDA_HOME)/include CUDA_LIB = -L$(CUDA_HOME)/lib64 -L$(CUDA_HOME)/lib64/stubs CUDA_OPTS = -DUNIX -O3 --use_fast_math $(LMP_INC) -Xcompiler -fPIC -CUDR_CPP = mpicxx -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -DOMPI_SKIP_MPICXX=1 -fPIC +CUDR_CPP = mpicxx -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -DOMPI_SKIP_MPICXX=1 -fPIC -std=c++11 CUDR_OPTS = -O2 $(LMP_INC) # -xHost -no-prec-div -ansi-alias BIN_DIR = ./ diff --git a/lib/gpu/Makefile.linux.double b/lib/gpu/Makefile.linux.double index 4693c86d57..485b636e15 100644 --- a/lib/gpu/Makefile.linux.double +++ b/lib/gpu/Makefile.linux.double @@ -57,8 +57,8 @@ CUDA_INCLUDE = -I$(CUDA_HOME)/include CUDA_LIB = -L$(CUDA_HOME)/lib64 -L$(CUDA_HOME)/lib64/stubs CUDA_OPTS = -DUNIX -O3 --use_fast_math $(LMP_INC) -Xcompiler -fPIC -CUDR_CPP = mpic++ -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -CUDR_OPTS = -O2 # -xHost -no-prec-div -ansi-alias +CUDR_CPP = mpicxx -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -DOMPI_SKIP_MPICXX=1 -fPIC -std=c++11 +CUDR_OPTS = -O2 $(LMP_INC) # -xHost -no-prec-div -ansi-alias BIN_DIR = ./ OBJ_DIR = ./ diff --git a/lib/gpu/Makefile.linux.mixed b/lib/gpu/Makefile.linux.mixed index 03c776fad0..69c2de9ab0 100644 --- a/lib/gpu/Makefile.linux.mixed +++ b/lib/gpu/Makefile.linux.mixed @@ -58,8 +58,8 @@ CUDA_INCLUDE = -I$(CUDA_HOME)/include CUDA_LIB = -L$(CUDA_HOME)/lib64 -L$(CUDA_HOME)/lib64/stubs CUDA_OPTS = -DUNIX -O3 --use_fast_math $(LMP_INC) -Xcompiler -fPIC -CUDR_CPP = mpic++ -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -CUDR_OPTS = -O2 # -xHost -no-prec-div -ansi-alias +CUDR_CPP = mpicxx -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -DOMPI_SKIP_MPICXX=1 -fPIC -std=c++11 +CUDR_OPTS = -O2 $(LMP_INC) # -xHost -no-prec-div -ansi-alias BIN_DIR = ./ OBJ_DIR = ./ diff --git a/lib/gpu/Makefile.linux.single b/lib/gpu/Makefile.linux.single index 0c3d525b4e..38ea3dc204 100644 --- a/lib/gpu/Makefile.linux.single +++ b/lib/gpu/Makefile.linux.single @@ -57,8 +57,8 @@ CUDA_INCLUDE = -I$(CUDA_HOME)/include CUDA_LIB = -L$(CUDA_HOME)/lib64 -L$(CUDA_HOME)/lib64/stubs CUDA_OPTS = -DUNIX -O3 --use_fast_math $(LMP_INC) -Xcompiler -fPIC -CUDR_CPP = mpic++ -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -CUDR_OPTS = -O2 # -xHost -no-prec-div -ansi-alias +CUDR_CPP = mpicxx -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -DOMPI_SKIP_MPICXX=1 -fPIC -std=c++11 +CUDR_OPTS = -O2 $(LMP_INC) # -xHost -no-prec-div -ansi-alias BIN_DIR = ./ OBJ_DIR = ./ diff --git a/lib/gpu/Makefile.linux_multi b/lib/gpu/Makefile.linux_multi index d47f87e871..e0c250a951 100644 --- a/lib/gpu/Makefile.linux_multi +++ b/lib/gpu/Makefile.linux_multi @@ -51,9 +51,9 @@ CUDA_PRECISION = -D_SINGLE_DOUBLE CUDA_INCLUDE = -I$(CUDA_HOME)/include CUDA_LIB = -L$(CUDA_HOME)/lib64 -L$(CUDA_HOME)/lib64/stubs -CUDA_OPTS = -DUNIX -O3 --use_fast_math $(LMP_INC) -Xcompiler "-fPIC -std=c++98" +CUDA_OPTS = -DUNIX -O3 --use_fast_math $(LMP_INC) -Xcompiler -fPIC -CUDR_CPP = mpicxx -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -DOMPI_SKIP_MPICXX=1 -fPIC +CUDR_CPP = mpicxx -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -DOMPI_SKIP_MPICXX=1 -fPIC -std=c++11 CUDR_OPTS = -O2 $(LMP_INC) # -xHost -no-prec-div -ansi-alias BIN_DIR = ./ diff --git a/lib/gpu/Makefile.linux_opencl b/lib/gpu/Makefile.linux_opencl index 640562dca5..2aea7f5a46 100644 --- a/lib/gpu/Makefile.linux_opencl +++ b/lib/gpu/Makefile.linux_opencl @@ -17,8 +17,8 @@ OCL_TUNE = -DGENERIC_OCL # -- Uncomment for generic device LMP_INC = -DLAMMPS_SMALLBIG OCL_INC = -I/usr/local/cuda/include # Path to CL directory -OCL_CPP = mpic++ $(DEFAULT_DEVICE) -O3 -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK $(LMP_INC) $(OCL_INC) -OCL_LINK = -lOpenCL +OCL_CPP = mpic++ $(DEFAULT_DEVICE) -O3 -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK $(LMP_INC) $(OCL_INC) -std=c++11 +OCL_LINK = -L/usr/local/cuda/lib64 -lOpenCL OCL_PREC = -D_SINGLE_DOUBLE BIN_DIR = ./ diff --git a/lib/gpu/Makefile.mac b/lib/gpu/Makefile.mac deleted file mode 100644 index b571e8d85a..0000000000 --- a/lib/gpu/Makefile.mac +++ /dev/null @@ -1,32 +0,0 @@ -# /* ---------------------------------------------------------------------- -# Generic Mac Makefile for CUDA -# - 32-bit (requires adding -m32 to LAMMPS Makefile) -# - Change CUDA_ARCH for your GPU -# ------------------------------------------------------------------------- */ - -# which file will be copied to Makefile.lammps - -EXTRAMAKE = Makefile.lammps.standard - -CUDA_HOME = /usr/local/cuda -NVCC = nvcc -m64 - -CUDA_ARCH = -arch=sm_11 -CUDA_PRECISION = -D_SINGLE_SINGLE -CUDA_INCLUDE = -I$(CUDA_HOME)/include -CUDA_LIB = -L$(CUDA_HOME)/lib -L$(CUDA_HOME)/lib/stubs -CUDA_OPTS = -DUNIX -DUCL_NO_EXIT -O3 --use_fast_math - -CUDR_CPP = mpic++ -m64 -CUDR_OPTS = -O2 -g - -BIN_DIR = ./ -OBJ_DIR = ./ -LIB_DIR = ./ -AR = ar -BSH = /bin/sh - -CUDPP_OPT = -DUSE_CUDPP -Icudpp_mini - -include Nvidia.makefile - diff --git a/lib/gpu/Makefile.serial b/lib/gpu/Makefile.serial index dfe732ee80..82d10deea2 100644 --- a/lib/gpu/Makefile.serial +++ b/lib/gpu/Makefile.serial @@ -57,7 +57,7 @@ CUDA_INCLUDE = -I$(CUDA_HOME)/include CUDA_LIB = -L$(CUDA_HOME)/lib64 -L$(CUDA_HOME)/lib64/stubs -L../../src/STUBS -lmpi_stubs CUDA_OPTS = -DUNIX -O3 --use_fast_math $(LMP_INC) -Xcompiler -fPIC -CUDR_CPP = g++ -DMPI_GERYON -DUCL_NO_EXIT -fPIC -I../../src/STUBS +CUDR_CPP = g++ -DMPI_GERYON -DUCL_NO_EXIT -fPIC -I../../src/STUBS -std=c++11 CUDR_OPTS = -O2 $(LMP_INC) # -xHost -no-prec-div -ansi-alias BIN_DIR = ./ diff --git a/lib/gpu/Makefile.shannon b/lib/gpu/Makefile.shannon deleted file mode 100644 index b14bd01ec2..0000000000 --- a/lib/gpu/Makefile.shannon +++ /dev/null @@ -1,50 +0,0 @@ -# /* ---------------------------------------------------------------------- -# Generic Linux Makefile for CUDA -# - Change CUDA_ARCH for your GPU -# ------------------------------------------------------------------------- */ - -# which file will be copied to Makefile.lammps - -EXTRAMAKE = Makefile.lammps.standard - -CUDA_HOME = ${CUDA_ROOT} -NVCC = nvcc - -# Kepler CUDA -CUDA_ARCH = -arch=sm_35 -# Tesla CUDA -#CUDA_ARCH = -arch=sm_21 -# newer CUDA -#CUDA_ARCH = -arch=sm_13 -# older CUDA -#CUDA_ARCH = -arch=sm_10 -DCUDA_PRE_THREE - -# this setting should match LAMMPS Makefile -# one of LAMMPS_SMALLBIG (default), LAMMPS_BIGBIG and LAMMPS_SMALLSMALL - -LMP_INC = -DLAMMPS_SMALLBIG - -# precision for GPU calculations -# -D_SINGLE_SINGLE # Single precision for all calculations -# -D_DOUBLE_DOUBLE # Double precision for all calculations -# -D_SINGLE_DOUBLE # Accumulation of forces, etc. in double - -CUDA_PRECISION = -D_DOUBLE_DOUBLE - -CUDA_INCLUDE = -I$(CUDA_HOME)/include -CUDA_LIB = -L$(CUDA_HOME)/lib64 -L$(CUDA_HOME)/lib64/stubs -CUDA_OPTS = -DUNIX -O3 --use_fast_math - -CUDR_CPP = mpic++ -DMPI_GERYON -DUCL_NO_EXIT -DMPICH_IGNORE_CXX_SEEK -CUDR_OPTS = -O2 # -xHost -no-prec-div -ansi-alias - -BIN_DIR = ./ -OBJ_DIR = ./ -LIB_DIR = ./ -AR = ar -BSH = /bin/sh - -CUDPP_OPT = -DUSE_CUDPP -Icudpp_mini - -include Nvidia.makefile - diff --git a/lib/gpu/lal_gauss.cu b/lib/gpu/lal_gauss.cu index 6a50aa6725..2192fb39ca 100644 --- a/lib/gpu/lal_gauss.cu +++ b/lib/gpu/lal_gauss.cu @@ -60,11 +60,9 @@ __kernel void k_gauss(const __global numtyp4 *restrict x_, numtyp4 ix; fetch4(ix,i,pos_tex); //x_[i]; int itype=ix.w; - numtyp factor_lj; for ( ; nbor`. + + :param name: name of the property + :type name: string + :param dtype: type of the returned data (see :ref:`py_data_constants`) + :type dtype: int, optional + :param nelem: number of elements in array + :type nelem: int, optional + :param dim: dimension of each element + :type dim: int, optional + :return: requested data as NumPy array with direct access to C data + :rtype: numpy.array + """ + if dtype == LAMMPS_AUTODETECT: + dtype = self.lmp.extract_atom_datatype(name) + + if nelem == LAMMPS_AUTODETECT: + if name == "mass": + nelem = self.lmp.extract_global("ntypes") + 1 + else: + nelem = self.lmp.extract_global("nlocal") + if dim == LAMMPS_AUTODETECT: + if dtype in (LAMMPS_INT_2D, LAMMPS_DOUBLE_2D, LAMMPS_INT64_2D): + # TODO add other fields + if name in ("x", "v", "f", "angmom", "torque", "csforce", "vforce"): + dim = 3 + else: + dim = 2 + else: + dim = 1 + + raw_ptr = self.lmp.extract_atom(name, dtype) + + if dtype in (LAMMPS_DOUBLE, LAMMPS_DOUBLE_2D): + return self.darray(raw_ptr, nelem, dim) + elif dtype in (LAMMPS_INT, LAMMPS_INT_2D): + return self.iarray(c_int32, raw_ptr, nelem, dim) + elif dtype in (LAMMPS_INT64, LAMMPS_INT64_2D): + return self.iarray(c_int64, raw_ptr, nelem, dim) + return raw_ptr + def extract_atom_iarray(self, name, nelem, dim=1): + warnings.warn("deprecated, use extract_atom instead", DeprecationWarning) + if name in ['id', 'molecule']: c_int_type = self.lmp.c_tagint elif name in ['image']: @@ -484,15 +556,17 @@ class lammps(object): if dim == 1: raw_ptr = self.lmp.extract_atom(name, LAMMPS_INT) else: - raw_ptr = self.lmp.extract_atom(name, LAMMPS_INT2D) + raw_ptr = self.lmp.extract_atom(name, LAMMPS_INT_2D) return self.iarray(c_int_type, raw_ptr, nelem, dim) def extract_atom_darray(self, name, nelem, dim=1): + warnings.warn("deprecated, use extract_atom instead", DeprecationWarning) + if dim == 1: raw_ptr = self.lmp.extract_atom(name, LAMMPS_DOUBLE) else: - raw_ptr = self.lmp.extract_atom(name, LAMMPS_DOUBLE2D) + raw_ptr = self.lmp.extract_atom(name, LAMMPS_DOUBLE_2D) return self.darray(raw_ptr, nelem, dim) @@ -594,7 +668,7 @@ class lammps(object): def version(self): """Return a numerical representation of the LAMMPS version in use. - This is a wrapper around the :cpp:func:`lammps_close` function of the C-library interface. + This is a wrapper around the :cpp:func:`lammps_version` function of the C-library interface. :return: version number :rtype: int @@ -705,9 +779,9 @@ class lammps(object): underlying :cpp:func:`lammps_get_natoms` function returning a double. :return: number of atoms - :rtype: float + :rtype: int """ - return self.lib.lammps_get_natoms(self.lmp) + return int(self.lib.lammps_get_natoms(self.lmp)) # ------------------------------------------------------------------------- @@ -801,10 +875,35 @@ class lammps(object): else: return None return int(self.lib.lammps_extract_setting(self.lmp,name)) + # ------------------------------------------------------------------------- + # extract global info datatype + + def extract_global_datatype(self, name): + """Retrieve global property datatype from LAMMPS + + This is a wrapper around the :cpp:func:`lammps_extract_global_datatype` + function of the C-library interface. Its documentation includes a + list of the supported keywords. + This function returns ``None`` if the keyword is not + recognized. Otherwise it will return a positive integer value that + corresponds to one of the constants define in the :py:mod:`lammps` module: + ``LAMMPS_INT``, ``LAMMPS_INT_2D``, ``LAMMPS_DOUBLE``, ``LAMMPS_DOUBLE_2D``, + ``LAMMPS_INT64``, ``LAMMPS_INT64_2D``, and ``LAMMPS_STRING``. These values + are equivalent to the ones defined in :cpp:enum:`_LMP_DATATYPE_CONST`. + + :param name: name of the property + :type name: string + :return: datatype of global property + :rtype: int + """ + if name: name = name.encode() + else: return None + return self.lib.lammps_extract_global_datatype(self.lmp, name) + # ------------------------------------------------------------------------- # extract global info - def extract_global(self, name, type): + def extract_global(self, name, dtype=LAMMPS_AUTODETECT): """Query LAMMPS about global settings of different types. This is a wrapper around the :cpp:func:`lammps_extract_global` @@ -814,55 +913,87 @@ class lammps(object): of values. The :cpp:func:`lammps_extract_global` documentation includes a list of the supported keywords and their data types. Since Python needs to know the data type to be able to interpret - the result, the type has to be provided as an argument. For - that purpose the :py:mod:`lammps` module contains the constants - ``LAMMPS_INT``, ``LAMMPS_DOUBLE``, ``LAMMPS_BIGINT``, - ``LAMMPS_TAGINT``, and ``LAMMPS_STRING``. - This function returns ``None`` if either the keyword is not - recognized, or an invalid data type constant is used. + the result, by default, this function will try to auto-detect the data type + by asking the library. You can also force a specific data type. For that + purpose the :py:mod:`lammps` module contains the constants ``LAMMPS_INT``, + ``LAMMPS_DOUBLE``, ``LAMMPS_INT64``, and ``LAMMPS_STRING``. These values + are equivalent to the ones defined in :cpp:enum:`_LMP_DATATYPE_CONST`. + This function returns ``None`` if either the keyword is not recognized, + or an invalid data type constant is used. - :param name: name of the setting + :param name: name of the property :type name: string - :param type: type of the returned data - :type type: int - :return: value of the setting - :rtype: integer or double or string or None + :param dtype: data type of the returned data (see :ref:`py_data_constants`) + :type dtype: int, optional + :return: value of the property or None + :rtype: int, float, or NoneType + """ + if dtype == LAMMPS_AUTODETECT: + dtype = self.extract_global_datatype(name) + + if name: name = name.encode() + else: return None + + if dtype == LAMMPS_INT: + self.lib.lammps_extract_global.restype = POINTER(c_int32) + target_type = int + elif dtype == LAMMPS_INT64: + self.lib.lammps_extract_global.restype = POINTER(c_int64) + target_type = int + elif dtype == LAMMPS_DOUBLE: + self.lib.lammps_extract_global.restype = POINTER(c_double) + target_type = float + elif dtype == LAMMPS_STRING: + self.lib.lammps_extract_global.restype = c_char_p + target_type = lambda x: str(x, 'ascii') + + ptr = self.lib.lammps_extract_global(self.lmp, name) + if ptr: + return target_type(ptr[0]) + return None + + + # ------------------------------------------------------------------------- + # extract per-atom info datatype + + def extract_atom_datatype(self, name): + """Retrieve per-atom property datatype from LAMMPS + + This is a wrapper around the :cpp:func:`lammps_extract_atom_datatype` + function of the C-library interface. Its documentation includes a + list of the supported keywords. + This function returns ``None`` if the keyword is not + recognized. Otherwise it will return an integer value that + corresponds to one of the constants define in the :py:mod:`lammps` module: + ``LAMMPS_INT``, ``LAMMPS_INT_2D``, ``LAMMPS_DOUBLE``, ``LAMMPS_DOUBLE_2D``, + ``LAMMPS_INT64``, ``LAMMPS_INT64_2D``, and ``LAMMPS_STRING``. These values + are equivalent to the ones defined in :cpp:enum:`_LMP_DATATYPE_CONST`. + + :param name: name of the property + :type name: string + :return: data type of per-atom property (see :ref:`py_data_constants`) + :rtype: int """ if name: name = name.encode() else: return None - if type == LAMMPS_INT: - self.lib.lammps_extract_global.restype = POINTER(c_int) - elif type == LAMMPS_DOUBLE: - self.lib.lammps_extract_global.restype = POINTER(c_double) - elif type == LAMMPS_BIGINT: - self.lib.lammps_extract_global.restype = POINTER(self.c_bigint) - elif type == LAMMPS_TAGINT: - self.lib.lammps_extract_global.restype = POINTER(self.c_tagint) - elif type == LAMMPS_STRING: - self.lib.lammps_extract_global.restype = c_char_p - ptr = self.lib.lammps_extract_global(self.lmp,name) - return str(ptr,'ascii') - else: return None - ptr = self.lib.lammps_extract_global(self.lmp,name) - if ptr: return ptr[0] - else: return None + return self.lib.lammps_extract_atom_datatype(self.lmp, name) # ------------------------------------------------------------------------- # extract per-atom info - # NOTE: need to insure are converting to/from correct Python type - # e.g. for Python list or NumPy or ctypes - def extract_atom(self,name,type): + def extract_atom(self, name, dtype=LAMMPS_AUTODETECT): """Retrieve per-atom properties from LAMMPS This is a wrapper around the :cpp:func:`lammps_extract_atom` function of the C-library interface. Its documentation includes a list of the supported keywords and their data types. Since Python needs to know the data type to be able to interpret - the result, the type has to be provided as an argument. For + the result, by default, this function will try to auto-detect the data type + by asking the library. You can also force a specific data type. For that purpose the :py:mod:`lammps` module contains the constants - ``LAMMPS_INT``, ``LAMMPS_INT2D``, ``LAMMPS_DOUBLE``, - and ``LAMMPS_DOUBLE2D``. + ``LAMMPS_INT``, ``LAMMPS_INT_2D``, ``LAMMPS_DOUBLE``, ``LAMMPS_DOUBLE_2D``, + ``LAMMPS_INT64``, ``LAMMPS_INT64_2D``, and ``LAMMPS_STRING``. These values + are equivalent to the ones defined in :cpp:enum:`_LMP_DATATYPE_CONST`. This function returns ``None`` if either the keyword is not recognized, or an invalid data type constant is used. @@ -875,27 +1006,36 @@ class lammps(object): atoms. In some cases, this depends on a LAMMPS setting, see for example :doc:`comm_modify vel yes `. - :param name: name of the setting + :param name: name of the property :type name: string - :param type: type of the returned data - :type type: int - :return: requested data - :rtype: pointer to integer or double or None + :param dtype: data type of the returned data (see :ref:`py_data_constants`) + :type dtype: int, optional + :return: requested data or ``None`` + :rtype: ctypes.POINTER(ctypes.c_int32), ctypes.POINTER(ctypes.POINTER(ctypes.c_int32)), + ctypes.POINTER(ctypes.c_int64), ctypes.POINTER(ctypes.POINTER(ctypes.c_int64)), + ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.POINTER(ctypes.c_double)), + or NoneType """ - ntypes = int(self.extract_setting('ntypes')) - nmax = int(self.extract_setting('nmax')) + if dtype == LAMMPS_AUTODETECT: + dtype = self.extract_atom_datatype(name) + if name: name = name.encode() else: return None - if type == LAMMPS_INT: - self.lib.lammps_extract_atom.restype = POINTER(c_int) - elif type == LAMMPS_INT2D: - self.lib.lammps_extract_atom.restype = POINTER(POINTER(c_int)) - elif type == LAMMPS_DOUBLE: + + if dtype == LAMMPS_INT: + self.lib.lammps_extract_atom.restype = POINTER(c_int32) + elif dtype == LAMMPS_INT_2D: + self.lib.lammps_extract_atom.restype = POINTER(POINTER(c_int32)) + elif dtype == LAMMPS_DOUBLE: self.lib.lammps_extract_atom.restype = POINTER(c_double) - elif type == LAMMPS_DOUBLE2D: + elif dtype == LAMMPS_DOUBLE_2D: self.lib.lammps_extract_atom.restype = POINTER(POINTER(c_double)) + elif dtype == LAMMPS_INT64: + self.lib.lammps_extract_atom.restype = POINTER(c_int64) + elif dtype == LAMMPS_INT64_2D: + self.lib.lammps_extract_atom.restype = POINTER(POINTER(c_int64)) else: return None - ptr = self.lib.lammps_extract_atom(self.lmp,name) + ptr = self.lib.lammps_extract_atom(self.lmp, name) if ptr: return ptr else: return None @@ -1140,7 +1280,7 @@ class lammps(object): def gather_atoms(self,name,type,count): if name: name = name.encode() - natoms = self.lib.lammps_get_natoms(self.lmp) + natoms = self.get_natoms() if type == 0: data = ((count*natoms)*c_int)() self.lib.lammps_gather_atoms(self.lmp,name,type,count,data) @@ -1154,7 +1294,7 @@ class lammps(object): def gather_atoms_concat(self,name,type,count): if name: name = name.encode() - natoms = self.lib.lammps_get_natoms(self.lmp) + natoms = self.get_natoms() if type == 0: data = ((count*natoms)*c_int)() self.lib.lammps_gather_atoms_concat(self.lmp,name,type,count,data) @@ -1206,7 +1346,7 @@ class lammps(object): # e.g. for Python list or NumPy or ctypes def gather(self,name,type,count): if name: name = name.encode() - natoms = self.lib.lammps_get_natoms(self.lmp) + natoms = self.get_natoms() if type == 0: data = ((count*natoms)*c_int)() self.lib.lammps_gather(self.lmp,name,type,count,data) @@ -1218,7 +1358,7 @@ class lammps(object): def gather_concat(self,name,type,count): if name: name = name.encode() - natoms = self.lib.lammps_get_natoms(self.lmp) + natoms = self.get_natoms() if type == 0: data = ((count*natoms)*c_int)() self.lib.lammps_gather_concat(self.lmp,name,type,count,data) @@ -1525,8 +1665,8 @@ class lammps(object): def available_styles(self, category): """Returns a list of styles available for a given category - This is a wrapper around the functions :cpp:func:`lammps_style_count` - and :cpp:func`lammps_style_name` of the library interface. + This is a wrapper around the functions :cpp:func:`lammps_style_count()` + and :cpp:func:`lammps_style_name()` of the library interface. :param category: name of category :type category: string @@ -1723,8 +1863,8 @@ class OutputCapture(object): # ------------------------------------------------------------------------- class Variable(object): - def __init__(self, lammps_wrapper_instance, name, style, definition): - self.wrapper = lammps_wrapper_instance + def __init__(self, pylammps_instance, name, style, definition): + self._pylmp = pylammps_instance self.name = name self.style = style self.definition = definition.split() @@ -1732,9 +1872,9 @@ class Variable(object): @property def value(self): if self.style == 'atom': - return list(self.wrapper.lmp.extract_variable(self.name, "all", 1)) + return list(self._pylmp.lmp.extract_variable(self.name, "all", 1)) else: - value = self.wrapper.lmp_print('"${%s}"' % self.name).strip() + value = self._pylmp.lmp_print('"${%s}"' % self.name).strip() try: return float(value) except ValueError: @@ -1743,103 +1883,136 @@ class Variable(object): # ------------------------------------------------------------------------- class AtomList(object): - def __init__(self, lammps_wrapper_instance): - self.lmp = lammps_wrapper_instance - self.natoms = self.lmp.system.natoms - self.dimensions = self.lmp.system.dimensions + """ + A dynamic list of atoms that returns either an Atom or Atom2D instance for + each atom. Instances are only allocated when accessed. + + :ivar natoms: total number of atoms + :ivar dimensions: number of dimensions in system + """ + def __init__(self, pylammps_instance): + self._pylmp = pylammps_instance + self.natoms = self._pylmp.system.natoms + self.dimensions = self._pylmp.system.dimensions + self._loaded = {} def __getitem__(self, index): - if self.dimensions == 2: - return Atom2D(self.lmp, index + 1) - return Atom(self.lmp, index + 1) + """ + Return Atom with given local index + + :param index: Local index of atom + :type index: int + :rtype: Atom or Atom2D + """ + if index not in self._loaded: + if self.dimensions == 2: + atom = Atom2D(self._pylmp, index + 1) + else: + atom = Atom(self._pylmp, index + 1) + self._loaded[index] = atom + return self._loaded[index] + + def __len__(self): + return self.natoms + # ------------------------------------------------------------------------- class Atom(object): - def __init__(self, lammps_wrapper_instance, index): - self.lmp = lammps_wrapper_instance + """ + A wrapper class then represents a single atom inside of LAMMPS + + It provides access to properties of the atom and allows you to change some of them. + """ + def __init__(self, pylammps_instance, index): + self._pylmp = pylammps_instance self.index = index @property def id(self): - return int(self.lmp.eval("id[%d]" % self.index)) + return int(self._pylmp.eval("id[%d]" % self.index)) @property def type(self): - return int(self.lmp.eval("type[%d]" % self.index)) + return int(self._pylmp.eval("type[%d]" % self.index)) @property def mol(self): - return self.lmp.eval("mol[%d]" % self.index) + return self._pylmp.eval("mol[%d]" % self.index) @property def mass(self): - return self.lmp.eval("mass[%d]" % self.index) + return self._pylmp.eval("mass[%d]" % self.index) @property def position(self): - return (self.lmp.eval("x[%d]" % self.index), - self.lmp.eval("y[%d]" % self.index), - self.lmp.eval("z[%d]" % self.index)) + return (self._pylmp.eval("x[%d]" % self.index), + self._pylmp.eval("y[%d]" % self.index), + self._pylmp.eval("z[%d]" % self.index)) @position.setter def position(self, value): - self.lmp.set("atom", self.index, "x", value[0]) - self.lmp.set("atom", self.index, "y", value[1]) - self.lmp.set("atom", self.index, "z", value[2]) + self._pylmp.set("atom", self.index, "x", value[0]) + self._pylmp.set("atom", self.index, "y", value[1]) + self._pylmp.set("atom", self.index, "z", value[2]) @property def velocity(self): - return (self.lmp.eval("vx[%d]" % self.index), - self.lmp.eval("vy[%d]" % self.index), - self.lmp.eval("vz[%d]" % self.index)) + return (self._pylmp.eval("vx[%d]" % self.index), + self._pylmp.eval("vy[%d]" % self.index), + self._pylmp.eval("vz[%d]" % self.index)) @velocity.setter def velocity(self, value): - self.lmp.set("atom", self.index, "vx", value[0]) - self.lmp.set("atom", self.index, "vy", value[1]) - self.lmp.set("atom", self.index, "vz", value[2]) + self._pylmp.set("atom", self.index, "vx", value[0]) + self._pylmp.set("atom", self.index, "vy", value[1]) + self._pylmp.set("atom", self.index, "vz", value[2]) @property def force(self): - return (self.lmp.eval("fx[%d]" % self.index), - self.lmp.eval("fy[%d]" % self.index), - self.lmp.eval("fz[%d]" % self.index)) + return (self._pylmp.eval("fx[%d]" % self.index), + self._pylmp.eval("fy[%d]" % self.index), + self._pylmp.eval("fz[%d]" % self.index)) @property def charge(self): - return self.lmp.eval("q[%d]" % self.index) + return self._pylmp.eval("q[%d]" % self.index) # ------------------------------------------------------------------------- class Atom2D(Atom): - def __init__(self, lammps_wrapper_instance, index): - super(Atom2D, self).__init__(lammps_wrapper_instance, index) + """ + A wrapper class then represents a single 2D atom inside of LAMMPS + + It provides access to properties of the atom and allows you to change some of them. + """ + def __init__(self, pylammps_instance, index): + super(Atom2D, self).__init__(pylammps_instance, index) @property def position(self): - return (self.lmp.eval("x[%d]" % self.index), - self.lmp.eval("y[%d]" % self.index)) + return (self._pylmp.eval("x[%d]" % self.index), + self._pylmp.eval("y[%d]" % self.index)) @position.setter def position(self, value): - self.lmp.set("atom", self.index, "x", value[0]) - self.lmp.set("atom", self.index, "y", value[1]) + self._pylmp.set("atom", self.index, "x", value[0]) + self._pylmp.set("atom", self.index, "y", value[1]) @property def velocity(self): - return (self.lmp.eval("vx[%d]" % self.index), - self.lmp.eval("vy[%d]" % self.index)) + return (self._pylmp.eval("vx[%d]" % self.index), + self._pylmp.eval("vy[%d]" % self.index)) @velocity.setter def velocity(self, value): - self.lmp.set("atom", self.index, "vx", value[0]) - self.lmp.set("atom", self.index, "vy", value[1]) + self._pylmp.set("atom", self.index, "vx", value[0]) + self._pylmp.set("atom", self.index, "vy", value[1]) @property def force(self): - return (self.lmp.eval("fx[%d]" % self.index), - self.lmp.eval("fy[%d]" % self.index)) + return (self._pylmp.eval("fx[%d]" % self.index), + self._pylmp.eval("fy[%d]" % self.index)) # ------------------------------------------------------------------------- @@ -1919,11 +2092,41 @@ def get_thermo_data(output): class PyLammps(object): """ - More Python-like wrapper for LAMMPS (e.g., for IPython) - See examples/ipython for usage + This is a Python wrapper class around the lower-level + :py:class:`lammps` class, exposing a more Python-like, + object-oriented interface for prototyping system inside of IPython and + Jupyter notebooks. + + It either creates its own instance of :py:class:`lammps` or can be + initialized with an existing instance. The arguments are the same of the + lower-level interface. The original interface can still be accessed via + :py:attr:`PyLammps.lmp`. + + :param name: "machine" name of the shared LAMMPS library ("mpi" loads ``liblammps_mpi.so``, "" loads ``liblammps.so``) + :type name: string + :param cmdargs: list of command line arguments to be passed to the :cpp:func:`lammps_open` function. The executable name is automatically added. + :type cmdargs: list + :param ptr: pointer to a LAMMPS C++ class instance when called from an embedded Python interpreter. None means load symbols from shared library. + :type ptr: pointer + :param comm: MPI communicator (as provided by `mpi4py `_). ``None`` means use ``MPI_COMM_WORLD`` implicitly. + :type comm: MPI_Comm + + :ivar lmp: instance of original LAMMPS Python interface + :vartype lmp: :py:class:`lammps` + + :ivar runs: list of completed runs, each storing the thermo output + :vartype run: list """ - def __init__(self,name="",cmdargs=None,ptr=None,comm=None): + def __init__(self, name="", cmdargs=None, ptr=None, comm=None): + self.has_echo = False + + if cmdargs: + if '-echo' in cmdargs: + idx = cmdargs.index('-echo') + # ensures that echo line is ignored during output capture + self.has_echo = idx+1 < len(cmdargs) and cmdargs[idx+1] in ('screen', 'both') + if ptr: if isinstance(ptr,PyLammps): self.lmp = ptr.lmp @@ -1942,29 +2145,69 @@ class PyLammps(object): self.lmp = None def close(self): + """Explicitly delete a LAMMPS instance + + This is a wrapper around the :py:meth:`lammps.close` of the Python interface. + """ if self.lmp: self.lmp.close() self.lmp = None def version(self): + """Return a numerical representation of the LAMMPS version in use. + + This is a wrapper around the :py:meth:`lammps.version` function of the Python interface. + + :return: version number + :rtype: int + """ return self.lmp.version() - def file(self,file): + def file(self, file): + """Read LAMMPS commands from a file. + + This is a wrapper around the :py:meth:`lammps.file` function of the Python interface. + + :param path: Name of the file/path with LAMMPS commands + :type path: string + """ self.lmp.file(file) - def write_script(self,filename): - """ Write LAMMPS script file containing all commands executed up until now """ - with open(filename, "w") as f: - for cmd in self._cmd_history: - f.write("%s\n" % cmd) + def write_script(self, filepath): + """ + Write LAMMPS script file containing all commands executed up until now - def command(self,cmd): + :param filepath: path to script file that should be written + :type filepath: string + """ + with open(filepath, "w") as f: + for cmd in self._cmd_history: + print(cmd, file=f) + + def command(self, cmd): + """ + Execute LAMMPS command + + All commands executed will be stored in a command history which can be + written to a file using :py:meth:`PyLammps.write_script()` + + :param cmd: command string that should be executed + :type: cmd: string + """ self.lmp.command(cmd) self._cmd_history.append(cmd) def run(self, *args, **kwargs): + """ + Execute LAMMPS run command with given arguments + + All thermo output during the run is captured and saved as new entry in + :py:attr:`PyLammps.runs`. The latest run can be retrieved by + :py:attr:`PyLammps.last_run`. + """ output = self.__getattr__('run')(*args, **kwargs) - if(self.has_mpi4py): + comm = self.lmp.get_mpi_comm() + if comm: output = self.lmp.comm.bcast(output, root=0) self.runs += get_thermo_data(output) @@ -1972,48 +2215,102 @@ class PyLammps(object): @property def last_run(self): + """ + Return data produced of last completed run command + + :getter: Returns an object containing information about the last run command + :type: dict + """ if len(self.runs) > 0: return self.runs[-1] return None @property def atoms(self): + """ + All atoms of this LAMMPS instance + + :getter: Returns a list of atoms currently in the system + :type: AtomList + """ return AtomList(self) @property def system(self): + """ + The system state of this LAMMPS instance + + :getter: Returns an object with properties storing the current system state + :type: namedtuple + """ output = self.info("system") d = self._parse_info_system(output) return namedtuple('System', d.keys())(*d.values()) @property def communication(self): + """ + The communication state of this LAMMPS instance + + :getter: Returns an object with properties storing the current communication state + :type: namedtuple + """ output = self.info("communication") d = self._parse_info_communication(output) return namedtuple('Communication', d.keys())(*d.values()) @property def computes(self): + """ + The list of active computes of this LAMMPS instance + + :getter: Returns a list of computes that are currently active in this LAMMPS instance + :type: list + """ output = self.info("computes") return self._parse_element_list(output) @property def dumps(self): + """ + The list of active dumps of this LAMMPS instance + + :getter: Returns a list of dumps that are currently active in this LAMMPS instance + :type: list + """ output = self.info("dumps") return self._parse_element_list(output) @property def fixes(self): + """ + The list of active fixes of this LAMMPS instance + + :getter: Returns a list of fixes that are currently active in this LAMMPS instance + :type: list + """ output = self.info("fixes") return self._parse_element_list(output) @property def groups(self): + """ + The list of active atom groups of this LAMMPS instance + + :getter: Returns a list of atom groups that are currently active in this LAMMPS instance + :type: list + """ output = self.info("groups") return self._parse_groups(output) @property def variables(self): + """ + Returns a dictionary of all variables defined in the current LAMMPS instance + + :getter: Returns a dictionary of all variables that are defined in this LAMMPS instance + :type: dict + """ output = self.info("variables") vars = {} for v in self._parse_element_list(output): @@ -2021,6 +2318,15 @@ class PyLammps(object): return vars def eval(self, expr): + """ + Evaluate expression + + :param expr: the expression string that should be evaluated inside of LAMMPS + :type expr: string + + :return: the value of the evaluated expression + :rtype: float if numeric, string otherwise + """ value = self.lmp_print('"$(%s)"' % expr).strip() try: return float(value) @@ -2156,11 +2462,23 @@ class PyLammps(object): 'variable', 'velocity', 'write_restart'] def __getattr__(self, name): + """ + This method is where the Python 'magic' happens. If a method is not + defined by the class PyLammps, it assumes it is a LAMMPS command. It takes + all the arguments, concatinates them to a single string, and executes it using + :py:meth:`lammps.PyLammps.command()`. + + :param verbose: Print output of command + :type verbose: bool + :return: line or list of lines of output, None if no output + :rtype: list or string + """ def handler(*args, **kwargs): cmd_args = [name] + [str(x) for x in args] with OutputCapture() as capture: - self.command(' '.join(cmd_args)) + cmd = ' '.join(cmd_args) + self.command(cmd) output = capture.output if 'verbose' in kwargs and kwargs['verbose']: @@ -2168,6 +2486,9 @@ class PyLammps(object): lines = output.splitlines() + if self.has_echo: + lines = lines[1:] + if len(lines) > 1: return lines elif len(lines) == 1: @@ -2179,14 +2500,56 @@ class PyLammps(object): class IPyLammps(PyLammps): """ - IPython wrapper for LAMMPS which adds embedded graphics capabilities + IPython wrapper for LAMMPS which adds embedded graphics capabilities to PyLammmps interface + + It either creates its own instance of :py:class:`lammps` or can be + initialized with an existing instance. The arguments are the same of the + lower-level interface. The original interface can still be accessed via + :py:attr:`PyLammps.lmp`. + + :param name: "machine" name of the shared LAMMPS library ("mpi" loads ``liblammps_mpi.so``, "" loads ``liblammps.so``) + :type name: string + :param cmdargs: list of command line arguments to be passed to the :cpp:func:`lammps_open` function. The executable name is automatically added. + :type cmdargs: list + :param ptr: pointer to a LAMMPS C++ class instance when called from an embedded Python interpreter. None means load symbols from shared library. + :type ptr: pointer + :param comm: MPI communicator (as provided by `mpi4py `_). ``None`` means use ``MPI_COMM_WORLD`` implicitly. + :type comm: MPI_Comm """ def __init__(self,name="",cmdargs=None,ptr=None,comm=None): super(IPyLammps, self).__init__(name=name,cmdargs=cmdargs,ptr=ptr,comm=comm) def image(self, filename="snapshot.png", group="all", color="type", diameter="type", - size=None, view=None, center=None, up=None, zoom=1.0): + size=None, view=None, center=None, up=None, zoom=1.0, background_color="white"): + """ Generate image using write_dump command and display it + + See :doc:`dump image ` for more information. + + :param filename: Name of the image file that should be generated. The extension determines whether it is PNG or JPEG + :type filename: string + :param group: the group of atoms write_image should use + :type group: string + :param color: name of property used to determine color + :type color: string + :param diameter: name of property used to determine atom diameter + :type diameter: string + :param size: dimensions of image + :type size: tuple (width, height) + :param view: view parameters + :type view: tuple (theta, phi) + :param center: center parameters + :type center: tuple (flag, center_x, center_y, center_z) + :param up: vector pointing to up direction + :type up: tuple (up_x, up_y, up_z) + :param zoom: zoom factor + :type zoom: float + :param background_color: background color of scene + :type background_color: string + + :return: Image instance used to display image in notebook + :rtype: :py:class:`IPython.core.display.Image` + """ cmd_args = [group, "image", filename, color, diameter] if size: @@ -2215,12 +2578,22 @@ class IPyLammps(PyLammps): if zoom: cmd_args += ["zoom", zoom] - cmd_args.append("modify backcolor white") + cmd_args.append("modify backcolor " + background_color) self.write_dump(*cmd_args) from IPython.core.display import Image - return Image('snapshot.png') + return Image(filename) def video(self, filename): + """ + Load video from file + + Can be used to visualize videos from :doc:`dump movie `. + + :param filename: Path to video file + :type filename: string + :return: HTML Video Tag used by notebook to embed a video + :rtype: :py:class:`IPython.display.HTML` + """ from IPython.display import HTML return HTML("") diff --git a/src/.gitignore b/src/.gitignore index 54b5edd8e3..ebeb7076da 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -33,7 +33,6 @@ /pair_kim.h /superpose3d.h -/math_eigen.h /kokkos.cpp /kokkos.h diff --git a/src/BODY/body_nparticle.cpp b/src/BODY/body_nparticle.cpp index 2619f0cf1b..bfbb004ad5 100644 --- a/src/BODY/body_nparticle.cpp +++ b/src/BODY/body_nparticle.cpp @@ -17,6 +17,7 @@ #include "atom_vec_body.h" #include "error.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "my_pool_chunk.h" @@ -136,7 +137,7 @@ void BodyNparticle::data_body(int ibonus, int ninteger, int ndouble, double *inertia = bonus->inertia; double evectors[3][3]; - int ierror = MathExtra::jacobi(tensor,inertia,evectors); + int ierror = MathEigen::jacobi3(tensor,inertia,evectors); if (ierror) error->one(FLERR, "Insufficient Jacobi rotations for body nparticle"); diff --git a/src/BODY/body_rounded_polygon.cpp b/src/BODY/body_rounded_polygon.cpp index c7d006c67f..0787708a9d 100644 --- a/src/BODY/body_rounded_polygon.cpp +++ b/src/BODY/body_rounded_polygon.cpp @@ -22,6 +22,7 @@ #include "domain.h" #include "error.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "my_pool_chunk.h" @@ -198,7 +199,7 @@ void BodyRoundedPolygon::data_body(int ibonus, int ninteger, int ndouble, double *inertia = bonus->inertia; double evectors[3][3]; - int ierror = MathExtra::jacobi(tensor,inertia,evectors); + int ierror = MathEigen::jacobi3(tensor,inertia,evectors); if (ierror) error->one(FLERR, "Insufficient Jacobi rotations for body nparticle"); diff --git a/src/BODY/body_rounded_polyhedron.cpp b/src/BODY/body_rounded_polyhedron.cpp index 423a3b3443..1a4359f39a 100644 --- a/src/BODY/body_rounded_polyhedron.cpp +++ b/src/BODY/body_rounded_polyhedron.cpp @@ -21,6 +21,7 @@ #include "atom_vec_body.h" #include "error.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "my_pool_chunk.h" @@ -242,7 +243,7 @@ void BodyRoundedPolyhedron::data_body(int ibonus, int ninteger, int ndouble, double *inertia = bonus->inertia; double evectors[3][3]; - int ierror = MathExtra::jacobi(tensor,inertia,evectors); + int ierror = MathEigen::jacobi3(tensor,inertia,evectors); if (ierror) error->one(FLERR, "Insufficient Jacobi rotations for body nparticle"); diff --git a/src/COMPRESS/dump_atom_zstd.cpp b/src/COMPRESS/dump_atom_zstd.cpp index 8fb08db3c8..1ea21292e8 100644 --- a/src/COMPRESS/dump_atom_zstd.cpp +++ b/src/COMPRESS/dump_atom_zstd.cpp @@ -98,7 +98,7 @@ void DumpAtomZstd::openfile() try { writer.open(filecurrent); - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } @@ -185,7 +185,7 @@ int DumpAtomZstd::modify_param(int narg, char **arg) writer.setCompressionLevel(compression_level); return 2; } - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } diff --git a/src/COMPRESS/dump_cfg_zstd.cpp b/src/COMPRESS/dump_cfg_zstd.cpp index 5948a3f83e..3f2ae5425b 100644 --- a/src/COMPRESS/dump_cfg_zstd.cpp +++ b/src/COMPRESS/dump_cfg_zstd.cpp @@ -101,7 +101,7 @@ void DumpCFGZstd::openfile() try { writer.open(filecurrent); - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } @@ -187,7 +187,7 @@ int DumpCFGZstd::modify_param(int narg, char **arg) writer.setCompressionLevel(compression_level); return 2; } - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } diff --git a/src/COMPRESS/dump_custom_zstd.cpp b/src/COMPRESS/dump_custom_zstd.cpp index c7ede3b38c..0925652455 100644 --- a/src/COMPRESS/dump_custom_zstd.cpp +++ b/src/COMPRESS/dump_custom_zstd.cpp @@ -98,7 +98,7 @@ void DumpCustomZstd::openfile() try { writer.open(filecurrent); - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } @@ -185,7 +185,7 @@ int DumpCustomZstd::modify_param(int narg, char **arg) writer.setCompressionLevel(compression_level); return 2; } - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } diff --git a/src/COMPRESS/dump_local_zstd.cpp b/src/COMPRESS/dump_local_zstd.cpp index 9393654dd6..9c7c2fed34 100644 --- a/src/COMPRESS/dump_local_zstd.cpp +++ b/src/COMPRESS/dump_local_zstd.cpp @@ -100,7 +100,7 @@ void DumpLocalZstd::openfile() try { writer.open(filecurrent); - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } @@ -185,7 +185,7 @@ int DumpLocalZstd::modify_param(int narg, char **arg) writer.setCompressionLevel(compression_level); return 2; } - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } diff --git a/src/COMPRESS/dump_xyz_zstd.cpp b/src/COMPRESS/dump_xyz_zstd.cpp index eb0600f34b..5e871d7d87 100644 --- a/src/COMPRESS/dump_xyz_zstd.cpp +++ b/src/COMPRESS/dump_xyz_zstd.cpp @@ -98,7 +98,7 @@ void DumpXYZZstd::openfile() try { writer.open(filecurrent); - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } @@ -159,7 +159,7 @@ int DumpXYZZstd::modify_param(int narg, char **arg) writer.setCompressionLevel(compression_level); return 2; } - } catch (FileWriterException & e) { + } catch (FileWriterException &e) { error->one(FLERR, e.what()); } } diff --git a/src/COMPRESS/zstd_file_writer.cpp b/src/COMPRESS/zstd_file_writer.cpp index e764409c73..68ac1217f5 100644 --- a/src/COMPRESS/zstd_file_writer.cpp +++ b/src/COMPRESS/zstd_file_writer.cpp @@ -46,7 +46,7 @@ ZstdFileWriter::~ZstdFileWriter() /* ---------------------------------------------------------------------- */ -void ZstdFileWriter::open(const std::string & path) +void ZstdFileWriter::open(const std::string &path) { if(isopen()) return; diff --git a/src/COMPRESS/zstd_file_writer.h b/src/COMPRESS/zstd_file_writer.h index eec993bd4e..30afc86994 100644 --- a/src/COMPRESS/zstd_file_writer.h +++ b/src/COMPRESS/zstd_file_writer.h @@ -38,7 +38,7 @@ class ZstdFileWriter : public FileWriter { public: ZstdFileWriter(); virtual ~ZstdFileWriter(); - virtual void open(const std::string & path) override; + virtual void open(const std::string &path) override; virtual void close() override; virtual void flush() override; virtual size_t write(const void * buffer, size_t length) override; diff --git a/src/GPU/pair_eam_alloy_gpu.cpp b/src/GPU/pair_eam_alloy_gpu.cpp index 998ca92936..dabf4c6f57 100644 --- a/src/GPU/pair_eam_alloy_gpu.cpp +++ b/src/GPU/pair_eam_alloy_gpu.cpp @@ -438,7 +438,7 @@ void PairEAMAlloyGPU::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/GPU/pair_eam_fs_gpu.cpp b/src/GPU/pair_eam_fs_gpu.cpp index 5559bb470f..e2d2dc6bdf 100644 --- a/src/GPU/pair_eam_fs_gpu.cpp +++ b/src/GPU/pair_eam_fs_gpu.cpp @@ -441,7 +441,7 @@ void PairEAMFSGPU::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/KIM/kim_init.cpp b/src/KIM/kim_init.cpp index bbeffe2d82..5cd8f6a69f 100644 --- a/src/KIM/kim_init.cpp +++ b/src/KIM/kim_init.cpp @@ -313,7 +313,7 @@ void KimInit::do_init(char *model_name, char *user_units, char *model_units, KIM mesg += "# For Simulator : "; mesg += std::string(sim_name) + " " + sim_version + "\n"; mesg += "# Running on : LAMMPS "; - mesg += universe->version; + mesg += lmp->version; mesg += "\n"; mesg += "#\n"; diff --git a/src/KIM/kim_query.cpp b/src/KIM/kim_query.cpp index ec13210665..1fb003546f 100644 --- a/src/KIM/kim_query.cpp +++ b/src/KIM/kim_query.cpp @@ -338,8 +338,8 @@ char *do_query(char *qfunction, char * model_name, int narg, char **arg, /* ---------------------------------------------------------------------- */ -void KimQuery::echo_var_assign(const std::string & name, - const std::string & value) const +void KimQuery::echo_var_assign(const std::string &name, + const std::string &value) const { input->write_echo(fmt::format("variable {} string {}\n",name,value)); } diff --git a/src/KOKKOS/atom_vec_kokkos.h b/src/KOKKOS/atom_vec_kokkos.h index d414101966..09f02f61e2 100644 --- a/src/KOKKOS/atom_vec_kokkos.h +++ b/src/KOKKOS/atom_vec_kokkos.h @@ -137,24 +137,24 @@ class AtomVecKokkos : public AtomVec { size_t buffer_size; void* buffer; - #ifdef KOKKOS_ENABLE_CUDA + #ifdef LMP_KOKKOS_GPU template Kokkos::View > create_async_copy(const ViewType& src) { typedef Kokkos::View::value, - Kokkos::CudaHostPinnedSpace,typename ViewType::memory_space>::type, + LMPPinnedHostType,typename ViewType::memory_space>::type, Kokkos::MemoryTraits > mirror_type; if (buffer_size == 0) { - buffer = Kokkos::kokkos_malloc(src.span()); + buffer = Kokkos::kokkos_malloc(src.span()); buffer_size = src.span(); } else if (buffer_size < src.span()) { - buffer = Kokkos::kokkos_realloc(buffer,src.span()); + buffer = Kokkos::kokkos_realloc(buffer,src.span()); buffer_size = src.span(); } return mirror_type(buffer, src.d_view.layout()); @@ -166,13 +166,13 @@ class AtomVecKokkos : public AtomVec { typename ViewType::array_layout, typename std::conditional< std::is_same::value, - Kokkos::CudaHostPinnedSpace,typename ViewType::memory_space>::type, + LMPPinnedHostType,typename ViewType::memory_space>::type, Kokkos::MemoryTraits > mirror_type; if (buffer_size == 0) { - buffer = Kokkos::kokkos_malloc(src.span()*sizeof(typename ViewType::value_type)); + buffer = Kokkos::kokkos_malloc(src.span()*sizeof(typename ViewType::value_type)); buffer_size = src.span(); } else if (buffer_size < src.span()) { - buffer = Kokkos::kokkos_realloc(buffer,src.span()*sizeof(typename ViewType::value_type)); + buffer = Kokkos::kokkos_realloc(buffer,src.span()*sizeof(typename ViewType::value_type)); buffer_size = src.span(); } mirror_type tmp_view((typename ViewType::value_type*)buffer, src.d_view.layout()); diff --git a/src/KOKKOS/comm_kokkos.cpp b/src/KOKKOS/comm_kokkos.cpp index c6ba15febd..b9f3864981 100644 --- a/src/KOKKOS/comm_kokkos.cpp +++ b/src/KOKKOS/comm_kokkos.cpp @@ -419,7 +419,7 @@ void CommKokkos::forward_comm_pair_device(Pair *pair) if (sendproc[iswap] != me) { double* buf_send_pair; double* buf_recv_pair; - if (lmp->kokkos->cuda_aware_flag) { + if (lmp->kokkos->gpu_aware_flag) { buf_send_pair = k_buf_send_pair.view().data(); buf_recv_pair = k_buf_recv_pair.view().data(); } else { @@ -437,7 +437,7 @@ void CommKokkos::forward_comm_pair_device(Pair *pair) MPI_Send(buf_send_pair,n,MPI_DOUBLE,sendproc[iswap],0,world); if (recvnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE); - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf_recv_pair.modify(); k_buf_recv_pair.sync(); } diff --git a/src/KOKKOS/gridcomm_kokkos.cpp b/src/KOKKOS/gridcomm_kokkos.cpp index 0a175343c3..dfca97c13e 100644 --- a/src/KOKKOS/gridcomm_kokkos.cpp +++ b/src/KOKKOS/gridcomm_kokkos.cpp @@ -678,7 +678,7 @@ forward_comm_kspace_regular(KSpace *kspace, int nper, int which, KokkosBaseFFT* kspaceKKBase = dynamic_cast(kspace); FFT_SCALAR* buf1; FFT_SCALAR* buf2; - if (lmp->kokkos->cuda_aware_flag) { + if (lmp->kokkos->gpu_aware_flag) { buf1 = k_buf1.view().data(); buf2 = k_buf2.view().data(); } else { @@ -695,7 +695,7 @@ forward_comm_kspace_regular(KSpace *kspace, int nper, int which, if (swap[m].sendproc != me) { - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf1.modify(); k_buf1.sync(); } @@ -706,7 +706,7 @@ forward_comm_kspace_regular(KSpace *kspace, int nper, int which, swap[m].sendproc,0,gridcomm); if (swap[m].nunpack) MPI_Wait(&request,MPI_STATUS_IGNORE); - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf2.modify(); k_buf2.sync(); } @@ -731,7 +731,7 @@ forward_comm_kspace_tiled(KSpace *kspace, int nper, int which, KokkosBaseFFT* kspaceKKBase = dynamic_cast(kspace); FFT_SCALAR* buf1; FFT_SCALAR* buf2; - if (lmp->kokkos->cuda_aware_flag) { + if (lmp->kokkos->gpu_aware_flag) { buf1 = k_buf1.view().data(); buf2 = k_buf2.view().data(); } else { @@ -753,7 +753,7 @@ forward_comm_kspace_tiled(KSpace *kspace, int nper, int which, kspaceKKBase->pack_forward_grid_kokkos(which,k_buf1,send[m].npack,k_send_packlist,m); DeviceType().fence(); - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf1.modify(); k_buf1.sync(); } @@ -773,7 +773,7 @@ forward_comm_kspace_tiled(KSpace *kspace, int nper, int which, for (i = 0; i < nrecv; i++) { MPI_Waitany(nrecv,requests,&m,MPI_STATUS_IGNORE); - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf2.modify(); k_buf2.sync(); } @@ -814,7 +814,7 @@ reverse_comm_kspace_regular(KSpace *kspace, int nper, int which, KokkosBaseFFT* kspaceKKBase = dynamic_cast(kspace); FFT_SCALAR* buf1; FFT_SCALAR* buf2; - if (lmp->kokkos->cuda_aware_flag) { + if (lmp->kokkos->gpu_aware_flag) { buf1 = k_buf1.view().data(); buf2 = k_buf2.view().data(); } else { @@ -831,7 +831,7 @@ reverse_comm_kspace_regular(KSpace *kspace, int nper, int which, if (swap[m].recvproc != me) { - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf1.modify(); k_buf1.sync(); } @@ -843,7 +843,7 @@ reverse_comm_kspace_regular(KSpace *kspace, int nper, int which, if (swap[m].npack) MPI_Wait(&request,MPI_STATUS_IGNORE); - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf2.modify(); k_buf2.sync(); } @@ -869,7 +869,7 @@ reverse_comm_kspace_tiled(KSpace *kspace, int nper, int which, FFT_SCALAR* buf1; FFT_SCALAR* buf2; - if (lmp->kokkos->cuda_aware_flag) { + if (lmp->kokkos->gpu_aware_flag) { buf1 = k_buf1.view().data(); buf2 = k_buf2.view().data(); } else { @@ -891,7 +891,7 @@ reverse_comm_kspace_tiled(KSpace *kspace, int nper, int which, kspaceKKBase->pack_reverse_grid_kokkos(which,k_buf1,recv[m].nunpack,k_recv_unpacklist,m); DeviceType().fence(); - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf1.modify(); k_buf1.sync(); } @@ -911,7 +911,7 @@ reverse_comm_kspace_tiled(KSpace *kspace, int nper, int which, for (i = 0; i < nsend; i++) { MPI_Waitany(nsend,requests,&m,MPI_STATUS_IGNORE); - if (!lmp->kokkos->cuda_aware_flag) { + if (!lmp->kokkos->gpu_aware_flag) { k_buf2.modify(); k_buf2.sync(); } diff --git a/src/KOKKOS/kokkos.cpp b/src/KOKKOS/kokkos.cpp index 16d906ba3c..85365f8017 100644 --- a/src/KOKKOS/kokkos.cpp +++ b/src/KOKKOS/kokkos.cpp @@ -24,15 +24,20 @@ #include #include -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU -// for detecting CUDA-aware MPI support: -// the variable int have_cuda_aware -// - is 1 if CUDA-aware MPI support is available -// - is 0 if CUDA-aware MPI support is unavailable -// - is -1 if CUDA-aware MPI support is unknown +// for detecting GPU-aware MPI support: +// the variable int have_gpu_aware +// - is 1 if GPU-aware MPI support is available +// - is 0 if GPU-aware MPI support is unavailable +// - is -1 if GPU-aware MPI support is unknown -#define CUDA_AWARE_UNKNOWN static int have_cuda_aware = -1; +#define GPU_AWARE_UNKNOWN static int have_gpu_aware = -1; + +// TODO HIP: implement HIP-aware MPI support (UCX) detection +#if defined(KOKKOS_ENABLE_HIP) +GPU_AWARE_UNKNOWN +#elif defined(KOKKOS_ENABLE_CUDA) // OpenMPI supports detecting CUDA-aware MPI as of version 2.0.0 @@ -42,23 +47,25 @@ #include #if defined(MPIX_CUDA_AWARE_SUPPORT) && MPIX_CUDA_AWARE_SUPPORT -static int have_cuda_aware = 1; +static int have_gpu_aware = 1; #elif defined(MPIX_CUDA_AWARE_SUPPORT) && !MPIX_CUDA_AWARE_SUPPORT -static int have_cuda_aware = 0; +static int have_gpu_aware = 0; #else -CUDA_AWARE_UNKNOWN +GPU_AWARE_UNKNOWN #endif // defined(MPIX_CUDA_AWARE_SUPPORT) #else // old OpenMPI -CUDA_AWARE_UNKNOWN +GPU_AWARE_UNKNOWN #endif // (OMPI_MAJOR_VERSION >=2) #else // unknown MPI library -CUDA_AWARE_UNKNOWN +GPU_AWARE_UNKNOWN #endif // OPEN_MPI #endif // KOKKOS_ENABLE_CUDA +#endif // LMP_ENABLE_DEVICE + using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ @@ -185,9 +192,10 @@ KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) binsize = 0.0; #ifdef KOKKOS_ENABLE_CUDA - cuda_aware_flag = 1; + // TODO HIP: implement HIP-aware MPI testing + gpu_aware_flag = 1; #else - cuda_aware_flag = 0; + gpu_aware_flag = 0; #endif neigh_thread = 0; neigh_thread_set = 0; @@ -211,7 +219,7 @@ KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) exchange_comm_on_host = forward_comm_on_host = reverse_comm_on_host = 0; } -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU // check and warn about CUDA-aware MPI availability when using multiple MPI tasks // change default only if we can safely detect that CUDA-aware MPI is not available @@ -227,42 +235,42 @@ KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) char mpi_version[MPI_MAX_LIBRARY_VERSION_STRING]; MPI_Get_library_version(mpi_version, &len); if (strstr(&mpi_version[0], "Spectrum") != nullptr) { - cuda_aware_flag = 0; + gpu_aware_flag = 0; char* str; - if (str = getenv("OMPI_MCA_pml_pami_enable_cuda")) + if ((str = getenv("OMPI_MCA_pml_pami_enable_cuda"))) if((strcmp(str,"1") == 0)) { - have_cuda_aware = 1; - cuda_aware_flag = 1; + have_gpu_aware = 1; + gpu_aware_flag = 1; } - if (!cuda_aware_flag) + if (!gpu_aware_flag) if (me == 0) error->warning(FLERR,"The Spectrum MPI '-gpu' flag is not set. Disabling CUDA-aware MPI"); } #endif - if (cuda_aware_flag == 1 && have_cuda_aware == 0) { + if (gpu_aware_flag == 1 && have_gpu_aware == 0) { if (me == 0) error->warning(FLERR,"Turning off CUDA-aware MPI since it is not detected, " "use '-pk kokkos cuda/aware on' to override"); - cuda_aware_flag = 0; - } else if (have_cuda_aware == -1) { // maybe we are dealing with MPICH, MVAPICH2 or some derivative? + gpu_aware_flag = 0; + } else if (have_gpu_aware == -1) { // maybe we are dealing with MPICH, MVAPICH2 or some derivative? // MVAPICH2 #if defined(MPICH) && defined(MVAPICH2_VERSION) char* str; - cuda_aware_flag = 0; - if ((str = getenv("MV2_USE_CUDA"))) + gpu_aware_flag = 0; + if ((str = getenv("MV2_ENABLE_CUDA"))) if ((strcmp(str,"1") == 0)) - cuda_aware_flag = 1; + gpu_aware_flag = 1; - if (!cuda_aware_flag) + if (!gpu_aware_flag) if (me == 0) error->warning(FLERR,"MVAPICH2 'MV2_USE_CUDA' environment variable is not set. Disabling CUDA-aware MPI"); // pure MPICH or some unsupported MPICH derivative #elif defined(MPICH) && !defined(MVAPICH2_VERSION) if (me == 0) error->warning(FLERR,"Detected MPICH. Disabling CUDA-aware MPI"); - cuda_aware_flag = 0; + gpu_aware_flag = 0; #else if (me == 0) error->warning(FLERR,"Kokkos with CUDA assumes CUDA-aware MPI is available," @@ -270,9 +278,9 @@ KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) " '-pk kokkos cuda/aware off' if getting segmentation faults"); #endif - } // if (-1 == have_cuda_aware) + } // if (-1 == have_gpu_aware) } // nmpi > 0 -#endif // KOKKOS_ENABLE_CUDA +#endif // LMP_ENABLE_DEVICE #ifdef KILL_KOKKOS_ON_SIGSEGV signal(SIGSEGV, my_signal_handler); @@ -381,8 +389,8 @@ void KokkosLMP::accelerator(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"cuda/aware") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal package kokkos command"); - if (strcmp(arg[iarg+1],"off") == 0) cuda_aware_flag = 0; - else if (strcmp(arg[iarg+1],"on") == 0) cuda_aware_flag = 1; + 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"); iarg += 2; } else if (strcmp(arg[iarg],"neigh/thread") == 0) { @@ -395,14 +403,14 @@ void KokkosLMP::accelerator(int narg, char **arg) } else error->all(FLERR,"Illegal package kokkos command"); } -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU int nmpi = 0; MPI_Comm_size(world,&nmpi); // if "cuda/aware off" and "comm device", change to "comm host" - if (!cuda_aware_flag && nmpi > 1) { + if (!gpu_aware_flag && nmpi > 1) { if (exchange_comm_classic == 0 && exchange_comm_on_host == 0) { exchange_comm_on_host = 1; exchange_comm_changed = 1; @@ -419,7 +427,7 @@ void KokkosLMP::accelerator(int narg, char **arg) // if "cuda/aware on" and comm flags were changed previously, change them back - if (cuda_aware_flag) { + if (gpu_aware_flag) { if (exchange_comm_changed) { exchange_comm_on_host = 0; exchange_comm_changed = 0; diff --git a/src/KOKKOS/kokkos.h b/src/KOKKOS/kokkos.h index 72b7d19305..eb0eb2e71f 100644 --- a/src/KOKKOS/kokkos.h +++ b/src/KOKKOS/kokkos.h @@ -38,7 +38,7 @@ class KokkosLMP : protected Pointers { int nthreads,ngpus; int numa; int auto_sync; - int cuda_aware_flag; + int gpu_aware_flag; int neigh_thread; int neigh_thread_set; int newtonflag; diff --git a/src/KOKKOS/kokkos_type.h b/src/KOKKOS/kokkos_type.h index 0271c3d108..5930a9e207 100644 --- a/src/KOKKOS/kokkos_type.h +++ b/src/KOKKOS/kokkos_type.h @@ -42,6 +42,10 @@ enum{FULL=1u,HALFTHREAD=2u,HALF=4u}; #define MAX_TYPES_STACKPARAMS 12 #define NeighClusterSize 8 +namespace Kokkos { + using NoInit = ViewAllocateWithoutInitializing; +} + struct lmp_float3 { float x,y,z; KOKKOS_INLINE_FUNCTION @@ -211,6 +215,21 @@ struct ExecutionSpaceFromDevice { }; #endif +// set host pinned space +#if defined(KOKKOS_ENABLE_CUDA) +typedef Kokkos::CudaHostPinnedSpace LMPPinnedHostType; +#elif defined(KOKKOS_ENABLE_HIP) +typedef Kokkos::Experimental::HIPHostPinnedSpace LMPPinnedHostType; +#endif + +// create simple LMPDeviceSpace typedef for non HIP or CUDA specific +// behaviour +#if defined(KOKKOS_ENABLE_CUDA) +typedef Kokkos::Cuda LMPDeviceSpace; +#elif defined(KOKKOS_ENABLE_HIP) +typedef Kokkos::Experimental::HIP LMPDeviceSpace; +#endif + // Determine memory traits for force array // Do atomic trait when running HALFTHREAD neighbor list style @@ -239,7 +258,7 @@ struct AtomicDup { }; #endif -#if defined(KOKKOS_ENABLE_HIP) +#ifdef KOKKOS_ENABLE_HIP template<> struct AtomicDup { using value = Kokkos::Experimental::ScatterAtomic; diff --git a/src/KOKKOS/neigh_bond_kokkos.cpp b/src/KOKKOS/neigh_bond_kokkos.cpp index 2fdb09f880..8f054e46b5 100644 --- a/src/KOKKOS/neigh_bond_kokkos.cpp +++ b/src/KOKKOS/neigh_bond_kokkos.cpp @@ -75,30 +75,27 @@ void NeighBondKokkos::init_topology_kk() { // 1st time allocation of topology lists - if (atom->molecular && atom->nbonds && maxbond == 0) { - if (nprocs == 1) maxbond = atom->nbonds; - else maxbond = static_cast (LB_FACTOR * atom->nbonds / nprocs); - memoryKK->create_kokkos(k_bondlist,neighbor->bondlist,maxbond,3,"neigh:neighbor->bondlist"); - } - - if (atom->molecular && atom->nangles && maxangle == 0) { - if (nprocs == 1) maxangle = atom->nangles; - else maxangle = static_cast (LB_FACTOR * atom->nangles / nprocs); - memoryKK->create_kokkos(k_anglelist,neighbor->anglelist,maxangle,4,"neigh:neighbor->anglelist"); - } - - if (atom->molecular && atom->ndihedrals && maxdihedral == 0) { - if (nprocs == 1) maxdihedral = atom->ndihedrals; - else maxdihedral = static_cast - (LB_FACTOR * atom->ndihedrals / nprocs); - memoryKK->create_kokkos(k_dihedrallist,neighbor->dihedrallist,maxdihedral,5,"neigh:neighbor->dihedrallist"); - } - - if (atom->molecular && atom->nimpropers && maximproper == 0) { - if (nprocs == 1) maximproper = atom->nimpropers; - else maximproper = static_cast - (LB_FACTOR * atom->nimpropers / nprocs); - memoryKK->create_kokkos(k_improperlist,neighbor->improperlist,maximproper,5,"neigh:neighbor->improperlist"); + if (atom->molecular != Atom::ATOMIC) { + if (atom->nbonds && maxbond == 0) { + if (nprocs == 1) maxbond = atom->nbonds; + else maxbond = static_cast (LB_FACTOR * atom->nbonds / nprocs); + memoryKK->create_kokkos(k_bondlist,neighbor->bondlist,maxbond,3,"neigh:neighbor->bondlist"); + } + if (atom->nangles && maxangle == 0) { + if (nprocs == 1) maxangle = atom->nangles; + else maxangle = static_cast (LB_FACTOR * atom->nangles / nprocs); + memoryKK->create_kokkos(k_anglelist,neighbor->anglelist,maxangle,4,"neigh:neighbor->anglelist"); + } + if (atom->ndihedrals && maxdihedral == 0) { + if (nprocs == 1) maxdihedral = atom->ndihedrals; + else maxdihedral = static_cast (LB_FACTOR * atom->ndihedrals / nprocs); + memoryKK->create_kokkos(k_dihedrallist,neighbor->dihedrallist,maxdihedral,5,"neigh:neighbor->dihedrallist"); + } + if (atom->nimpropers && maximproper == 0) { + if (nprocs == 1) maximproper = atom->nimpropers; + else maximproper = static_cast (LB_FACTOR * atom->nimpropers / nprocs); + memoryKK->create_kokkos(k_improperlist,neighbor->improperlist,maximproper,5,"neigh:neighbor->improperlist"); + } } // set flags that determine which topology neighboring routines to use diff --git a/src/KOKKOS/neigh_list_kokkos.cpp b/src/KOKKOS/neigh_list_kokkos.cpp index 7db78e38d2..4246926c8b 100644 --- a/src/KOKKOS/neigh_list_kokkos.cpp +++ b/src/KOKKOS/neigh_list_kokkos.cpp @@ -40,10 +40,8 @@ void NeighListKokkos::grow(int nmax) k_ilist = DAT::tdual_int_1d("neighlist:ilist",maxatoms); d_ilist = k_ilist.view(); - k_numneigh = DAT::tdual_int_1d("neighlist:numneigh",maxatoms); - d_numneigh = k_numneigh.view(); - k_neighbors = DAT::tdual_neighbors_2d("neighlist:neighbors",maxatoms,maxneighs); - d_neighbors = k_neighbors.view(); + d_numneigh = typename ArrayTypes::t_int_1d("neighlist:numneigh",maxatoms); + d_neighbors = typename ArrayTypes::t_neighbors_2d(Kokkos::NoInit("neighlist:neighbors"),maxatoms,maxneighs); } /* ---------------------------------------------------------------------- */ diff --git a/src/KOKKOS/neigh_list_kokkos.h b/src/KOKKOS/neigh_list_kokkos.h index 8ae873036b..5de871166e 100644 --- a/src/KOKKOS/neigh_list_kokkos.h +++ b/src/KOKKOS/neigh_list_kokkos.h @@ -68,11 +68,9 @@ public: int maxneighs; void grow(int nmax); - DAT::tdual_neighbors_2d k_neighbors; typename ArrayTypes::t_neighbors_2d d_neighbors; DAT::tdual_int_1d k_ilist; // local indices of I atoms typename ArrayTypes::t_int_1d d_ilist; - DAT::tdual_int_1d k_numneigh; // # of J neighs for each I typename ArrayTypes::t_int_1d d_numneigh; NeighListKokkos(class LAMMPS *lmp); diff --git a/src/KOKKOS/neighbor_kokkos.cpp b/src/KOKKOS/neighbor_kokkos.cpp index cadfccfa6b..1795d87611 100644 --- a/src/KOKKOS/neighbor_kokkos.cpp +++ b/src/KOKKOS/neighbor_kokkos.cpp @@ -316,7 +316,7 @@ void NeighborKokkos::build_kokkos(int topoflag) // build topology lists for bonds/angles/etc - if (atom->molecular && topoflag) build_topology(); + if ((atom->molecular != Atom::ATOMIC) && topoflag) build_topology(); } template diff --git a/src/KOKKOS/npair_copy_kokkos.cpp b/src/KOKKOS/npair_copy_kokkos.cpp index 98f4b29c1c..eea0a14f86 100644 --- a/src/KOKKOS/npair_copy_kokkos.cpp +++ b/src/KOKKOS/npair_copy_kokkos.cpp @@ -73,16 +73,14 @@ void NPairCopyKokkos::copy_to_cpu(NeighList *list) NeighListKokkos* listcopy_kk = (NeighListKokkos*) listcopy; listcopy_kk->k_ilist.template sync(); - listcopy_kk->k_numneigh.template sync(); - listcopy_kk->k_neighbors.template sync(); int inum = listcopy->inum; int gnum = listcopy->gnum; int inum_all = inum; if (list->ghost) inum_all += gnum; auto h_ilist = listcopy_kk->k_ilist.h_view; - auto h_numneigh = listcopy_kk->k_numneigh.h_view; - auto h_neighbors = listcopy_kk->k_neighbors.h_view; + auto h_numneigh = Kokkos::create_mirror_view_and_copy(LMPHostType(),listcopy_kk->d_numneigh); + auto h_neighbors = Kokkos::create_mirror_view_and_copy(LMPHostType(),listcopy_kk->d_neighbors); list->inum = inum; list->gnum = gnum; diff --git a/src/KOKKOS/npair_halffull_kokkos.cpp b/src/KOKKOS/npair_halffull_kokkos.cpp index ca9c14b29d..653c1c4914 100644 --- a/src/KOKKOS/npair_halffull_kokkos.cpp +++ b/src/KOKKOS/npair_halffull_kokkos.cpp @@ -73,8 +73,6 @@ void NPairHalffullKokkos::build(NeighList *list) list->gnum = k_list_full->gnum; k_list->k_ilist.template modify(); - k_list->k_numneigh.template modify(); - k_list->k_neighbors.template modify(); } template diff --git a/src/KOKKOS/npair_kokkos.cpp b/src/KOKKOS/npair_kokkos.cpp index 4cad8632b4..dfa1a14dd5 100644 --- a/src/KOKKOS/npair_kokkos.cpp +++ b/src/KOKKOS/npair_kokkos.cpp @@ -212,7 +212,7 @@ void NPairKokkos::build(NeighList *list_) data.h_resize() = 0; Kokkos::deep_copy(d_scalars, h_scalars); -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU #define BINS_PER_BLOCK 2 const int factor = atoms_per_bin<64?2:1; #else @@ -226,7 +226,7 @@ void NPairKokkos::build(NeighList *list_) if (newton_pair) { if (SIZE) { NPairKokkosBuildFunctorSize f(data,atoms_per_bin * 5 * sizeof(X_FLOAT) * factor); -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU if (ExecutionSpaceFromDevice::space == Device) { int team_size = atoms_per_bin*factor; int team_size_max = Kokkos::TeamPolicy(team_size,Kokkos::AUTO).team_size_max(f,Kokkos::ParallelForTag()); @@ -244,7 +244,7 @@ void NPairKokkos::build(NeighList *list_) #endif } else { NPairKokkosBuildFunctor f(data,atoms_per_bin * 5 * sizeof(X_FLOAT) * factor); -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU if (ExecutionSpaceFromDevice::space == Device) { int team_size = atoms_per_bin*factor; int team_size_max = Kokkos::TeamPolicy(team_size,Kokkos::AUTO).team_size_max(f,Kokkos::ParallelForTag()); @@ -264,7 +264,7 @@ void NPairKokkos::build(NeighList *list_) } else { if (SIZE) { NPairKokkosBuildFunctorSize f(data,atoms_per_bin * 5 * sizeof(X_FLOAT) * factor); -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU if (ExecutionSpaceFromDevice::space == Device) { int team_size = atoms_per_bin*factor; int team_size_max = Kokkos::TeamPolicy(team_size,Kokkos::AUTO).team_size_max(f,Kokkos::ParallelForTag()); @@ -282,7 +282,7 @@ void NPairKokkos::build(NeighList *list_) #endif } else { NPairKokkosBuildFunctor f(data,atoms_per_bin * 5 * sizeof(X_FLOAT) * factor); -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU if (ExecutionSpaceFromDevice::space == Device) { int team_size = atoms_per_bin*factor; int team_size_max = Kokkos::TeamPolicy(team_size,Kokkos::AUTO).team_size_max(f,Kokkos::ParallelForTag()); @@ -305,8 +305,7 @@ void NPairKokkos::build(NeighList *list_) if(data.h_resize()) { list->maxneighs = data.h_new_maxneighs() * 1.2; - list->k_neighbors = DAT::tdual_neighbors_2d("neighbors", list->d_neighbors.extent(0), list->maxneighs); - list->d_neighbors = list->k_neighbors.template view(); + list->d_neighbors = typename AT::t_neighbors_2d(Kokkos::NoInit("neighbors"), list->d_neighbors.extent(0), list->maxneighs); data.neigh_list.d_neighbors = list->d_neighbors; data.neigh_list.maxneighs = list->maxneighs; } @@ -321,8 +320,6 @@ void NPairKokkos::build(NeighList *list_) } list->k_ilist.template modify(); - list->k_numneigh.template modify(); - list->k_neighbors.template modify(); } /* ---------------------------------------------------------------------- */ @@ -529,15 +526,33 @@ void NeighborKokkosExecute:: /* ---------------------------------------------------------------------- */ -#ifdef KOKKOS_ENABLE_CUDA -extern __shared__ X_FLOAT sharedmem[]; - -/* ---------------------------------------------------------------------- */ +#ifdef KOKKOS_ENABLE_HIP +#include +#if HIP_VERSION_MAJOR < 3 || (HIP_VERSION_MAJOR == 3 && HIP_VERSION_MINOR < 7) +// ROCm versions < 3.7 are missing __syncthreads_count, so we define a functional +// but (probably) not performant workaround +__device__ __forceinline__ int __syncthreads_count(int predicate) { + __shared__ int test_block[1]; + if (!(threadIdx.x || threadIdx.y || threadIdx.z)) + test_block[0] = 0; + __syncthreads(); + atomicAdd(test_block, predicate); + __threadfence_block(); + return test_block[0]; +} +#endif +#endif +#ifdef LMP_KOKKOS_GPU template template __device__ inline void NeighborKokkosExecute::build_ItemCuda(typename Kokkos::TeamPolicy::member_type dev) const { +#ifdef KOKKOS_ENABLE_HIP + HIP_DYNAMIC_SHARED(X_FLOAT, sharedmem); +#else + extern __shared__ X_FLOAT sharedmem[]; +#endif /* loop over atoms in i's bin, */ const int atoms_per_bin = c_bins.extent(1); @@ -971,11 +986,16 @@ void NeighborKokkosExecute:: /* ---------------------------------------------------------------------- */ -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU template template __device__ inline void NeighborKokkosExecute::build_ItemSizeCuda(typename Kokkos::TeamPolicy::member_type dev) const { +#ifdef KOKKOS_ENABLE_HIP + HIP_DYNAMIC_SHARED(X_FLOAT, sharedmem); +#else + extern __shared__ X_FLOAT sharedmem[]; +#endif /* loop over atoms in i's bin, */ const int atoms_per_bin = c_bins.extent(1); diff --git a/src/KOKKOS/npair_kokkos.h b/src/KOKKOS/npair_kokkos.h index 9090cd3083..be50fd6275 100644 --- a/src/KOKKOS/npair_kokkos.h +++ b/src/KOKKOS/npair_kokkos.h @@ -310,7 +310,7 @@ class NeighborKokkosExecute KOKKOS_FUNCTION void build_ItemSize(const int &i) const; -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU template __device__ inline void build_ItemCuda(typename Kokkos::TeamPolicy::member_type dev) const; @@ -387,7 +387,7 @@ struct NPairKokkosBuildFunctor { void operator() (const int & i) const { c.template build_Item(i); } -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU __device__ inline void operator() (typename Kokkos::TeamPolicy::member_type dev) const { @@ -445,7 +445,7 @@ struct NPairKokkosBuildFunctorSize { c.template build_ItemSize(i); } -#ifdef KOKKOS_ENABLE_CUDA +#ifdef LMP_KOKKOS_GPU __device__ inline void operator() (typename Kokkos::TeamPolicy::member_type dev) const { c.template build_ItemSizeCuda(dev); diff --git a/src/KOKKOS/npair_ssa_kokkos.cpp b/src/KOKKOS/npair_ssa_kokkos.cpp index ab509dc9ae..1a4ae01901 100644 --- a/src/KOKKOS/npair_ssa_kokkos.cpp +++ b/src/KOKKOS/npair_ssa_kokkos.cpp @@ -519,8 +519,6 @@ fprintf(stdout, "Fina%03d %6d inum %6d gnum, total used %6d, allocated %6d\n" #endif list->k_ilist.template modify(); - list->k_numneigh.template modify(); - list->k_neighbors.template modify(); } diff --git a/src/KOKKOS/pair_dpd_fdt_energy_kokkos.cpp b/src/KOKKOS/pair_dpd_fdt_energy_kokkos.cpp index f4dc0e867c..f5e284e28a 100644 --- a/src/KOKKOS/pair_dpd_fdt_energy_kokkos.cpp +++ b/src/KOKKOS/pair_dpd_fdt_energy_kokkos.cpp @@ -112,10 +112,10 @@ void PairDPDfdtEnergyKokkos::init_style() #endif } -#if defined(KOKKOS_ENABLE_CUDA) && defined(__CUDACC__) +#if (defined(KOKKOS_ENABLE_CUDA) && defined(__CUDACC__)) || defined(KOKKOS_ENABLE_HIP) // CUDA specialization of init_style to properly call rand_pool.init() template<> -void PairDPDfdtEnergyKokkos::init_style() +void PairDPDfdtEnergyKokkos::init_style() { PairDPDfdtEnergy::init_style(); @@ -125,10 +125,10 @@ void PairDPDfdtEnergyKokkos::init_style() int irequest = neighbor->nrequest - 1; neighbor->requests[irequest]-> - kokkos_host = std::is_same::value && - !std::is_same::value; + kokkos_host = std::is_same::value && + !std::is_same::value; neighbor->requests[irequest]-> - kokkos_device = std::is_same::value; + kokkos_device = std::is_same::value; if (neighflag == FULL) { neighbor->requests[irequest]->full = 1; diff --git a/src/KOKKOS/pair_eam_alloy_kokkos.cpp b/src/KOKKOS/pair_eam_alloy_kokkos.cpp index 52882c8be8..724de46057 100644 --- a/src/KOKKOS/pair_eam_alloy_kokkos.cpp +++ b/src/KOKKOS/pair_eam_alloy_kokkos.cpp @@ -1052,7 +1052,7 @@ void PairEAMAlloyKokkos::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/KOKKOS/pair_eam_fs_kokkos.cpp b/src/KOKKOS/pair_eam_fs_kokkos.cpp index d697cfbe9a..2667c21517 100644 --- a/src/KOKKOS/pair_eam_fs_kokkos.cpp +++ b/src/KOKKOS/pair_eam_fs_kokkos.cpp @@ -1055,7 +1055,7 @@ void PairEAMFSKokkos::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/KOKKOS/pppm_kokkos.cpp b/src/KOKKOS/pppm_kokkos.cpp index f4e3955f3c..9d9a26897f 100644 --- a/src/KOKKOS/pppm_kokkos.cpp +++ b/src/KOKKOS/pppm_kokkos.cpp @@ -811,22 +811,22 @@ void PPPMKokkos::allocate() // remap takes data from 3d brick to FFT decomposition int collective_flag = 0; // not yet supported in Kokkos version - int cuda_aware_flag = lmp->kokkos->cuda_aware_flag; + int gpu_aware_flag = lmp->kokkos->gpu_aware_flag; int tmp; fft1 = new FFT3dKokkos(lmp,world,nx_pppm,ny_pppm,nz_pppm, nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft, nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft, - 0,0,&tmp,collective_flag,cuda_aware_flag); + 0,0,&tmp,collective_flag,gpu_aware_flag); fft2 = new FFT3dKokkos(lmp,world,nx_pppm,ny_pppm,nz_pppm, nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft, nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in, - 0,0,&tmp,collective_flag,cuda_aware_flag); + 0,0,&tmp,collective_flag,gpu_aware_flag); remap = new RemapKokkos(lmp,world, nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in, nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft, - 1,0,0,FFT_PRECISION,collective_flag,cuda_aware_flag); + 1,0,0,FFT_PRECISION,collective_flag,gpu_aware_flag); // create ghost grid object for rho and electric field communication // also create 2 bufs for ghost grid cell comm, passed to GridComm methods diff --git a/src/KOKKOS/sna_kokkos_impl.h b/src/KOKKOS/sna_kokkos_impl.h index 06641e6019..3060aa9527 100644 --- a/src/KOKKOS/sna_kokkos_impl.h +++ b/src/KOKKOS/sna_kokkos_impl.h @@ -265,47 +265,47 @@ void SNAKokkos::grow_rij(int newnatom, int newnmax) natom = newnatom; nmax = newnmax; - inside = t_sna_2i(Kokkos::ViewAllocateWithoutInitializing("sna:inside"),natom,nmax); - element = t_sna_2i(Kokkos::ViewAllocateWithoutInitializing("sna:rcutij"),natom,nmax); - dedr = t_sna_3d(Kokkos::ViewAllocateWithoutInitializing("sna:dedr"),natom,nmax,3); + inside = t_sna_2i(Kokkos::NoInit("sna:inside"),natom,nmax); + element = t_sna_2i(Kokkos::NoInit("sna:rcutij"),natom,nmax); + dedr = t_sna_3d(Kokkos::NoInit("sna:dedr"),natom,nmax,3); #ifdef LMP_KOKKOS_GPU if (!host_flag) { - cayleyklein = t_sna_2ckp(Kokkos::ViewAllocateWithoutInitializing("sna:cayleyklein"), natom, nmax); - ulisttot = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot"),1,1,1); // dummy allocation - ulisttot_full = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot"),1,1,1); - ulisttot_re = t_sna_3d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot_re"),idxu_half_max,nelements,natom); - ulisttot_im = t_sna_3d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot_im"),idxu_half_max,nelements,natom); - ulisttot_pack = t_sna_4c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot_pack"),32,idxu_max,nelements,(natom+32-1)/32); - ulist = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulist"),1,1,1); - zlist = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:zlist"),1,1,1); - zlist_pack = t_sna_4c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:zlist_pack"),32,idxz_max,ndoubles,(natom+32-1)/32); - blist = t_sna_3d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:blist"),idxb_max,ntriples,natom); - blist_pack = t_sna_4d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:blist_pack"),32,idxb_max,ntriples,(natom+32-1)/32); - ylist = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ylist"),idxu_half_max,nelements,natom); - ylist_pack_re = t_sna_4d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ylist_pack_re"),32,idxu_half_max,nelements,(natom+32-1)/32); - ylist_pack_im = t_sna_4d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ylist_pack_im"),32,idxu_half_max,nelements,(natom+32-1)/32); - dulist = t_sna_4c3_ll(Kokkos::ViewAllocateWithoutInitializing("sna:dulist"),1,1,1); + cayleyklein = t_sna_2ckp(Kokkos::NoInit("sna:cayleyklein"), natom, nmax); + ulisttot = t_sna_3c_ll(Kokkos::NoInit("sna:ulisttot"),1,1,1); // dummy allocation + ulisttot_full = t_sna_3c_ll(Kokkos::NoInit("sna:ulisttot"),1,1,1); + ulisttot_re = t_sna_3d_ll(Kokkos::NoInit("sna:ulisttot_re"),idxu_half_max,nelements,natom); + ulisttot_im = t_sna_3d_ll(Kokkos::NoInit("sna:ulisttot_im"),idxu_half_max,nelements,natom); + ulisttot_pack = t_sna_4c_ll(Kokkos::NoInit("sna:ulisttot_pack"),32,idxu_max,nelements,(natom+32-1)/32); + ulist = t_sna_3c_ll(Kokkos::NoInit("sna:ulist"),1,1,1); + zlist = t_sna_3c_ll(Kokkos::NoInit("sna:zlist"),1,1,1); + zlist_pack = t_sna_4c_ll(Kokkos::NoInit("sna:zlist_pack"),32,idxz_max,ndoubles,(natom+32-1)/32); + blist = t_sna_3d_ll(Kokkos::NoInit("sna:blist"),idxb_max,ntriples,natom); + blist_pack = t_sna_4d_ll(Kokkos::NoInit("sna:blist_pack"),32,idxb_max,ntriples,(natom+32-1)/32); + ylist = t_sna_3c_ll(Kokkos::NoInit("sna:ylist"),idxu_half_max,nelements,natom); + ylist_pack_re = t_sna_4d_ll(Kokkos::NoInit("sna:ylist_pack_re"),32,idxu_half_max,nelements,(natom+32-1)/32); + ylist_pack_im = t_sna_4d_ll(Kokkos::NoInit("sna:ylist_pack_im"),32,idxu_half_max,nelements,(natom+32-1)/32); + dulist = t_sna_4c3_ll(Kokkos::NoInit("sna:dulist"),1,1,1); } else { #endif - rij = t_sna_3d(Kokkos::ViewAllocateWithoutInitializing("sna:rij"),natom,nmax,3); - wj = t_sna_2d(Kokkos::ViewAllocateWithoutInitializing("sna:wj"),natom,nmax); - rcutij = t_sna_2d(Kokkos::ViewAllocateWithoutInitializing("sna:rcutij"),natom,nmax); - ulisttot = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot"),idxu_half_max,nelements,natom); - ulisttot_full = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot_full"),idxu_max,nelements,natom); - ulisttot_re = t_sna_3d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot_re"),1,1,1); - ulisttot_im = t_sna_3d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot_im"),1,1,1); - ulisttot_pack = t_sna_4c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulisttot_pack"),1,1,1,1); - ulist = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ulist"),idxu_cache_max,natom,nmax); - zlist = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:zlist"),idxz_max,ndoubles,natom); - zlist_pack = t_sna_4c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:zlist_pack"),1,1,1,1); - blist = t_sna_3d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:blist"),idxb_max,ntriples,natom); - blist_pack = t_sna_4d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:blist_pack"),1,1,1,1); - ylist = t_sna_3c_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ylist"),idxu_half_max,nelements,natom); - ylist_pack_re = t_sna_4d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ylist_pack_re"),1,1,1,1); - ylist_pack_im = t_sna_4d_ll(Kokkos::ViewAllocateWithoutInitializing("sna:ylist_pack_im"),1,1,1,1); - dulist = t_sna_4c3_ll(Kokkos::ViewAllocateWithoutInitializing("sna:dulist"),idxu_cache_max,natom,nmax); + rij = t_sna_3d(Kokkos::NoInit("sna:rij"),natom,nmax,3); + wj = t_sna_2d(Kokkos::NoInit("sna:wj"),natom,nmax); + rcutij = t_sna_2d(Kokkos::NoInit("sna:rcutij"),natom,nmax); + ulisttot = t_sna_3c_ll(Kokkos::NoInit("sna:ulisttot"),idxu_half_max,nelements,natom); + ulisttot_full = t_sna_3c_ll(Kokkos::NoInit("sna:ulisttot_full"),idxu_max,nelements,natom); + ulisttot_re = t_sna_3d_ll(Kokkos::NoInit("sna:ulisttot_re"),1,1,1); + ulisttot_im = t_sna_3d_ll(Kokkos::NoInit("sna:ulisttot_im"),1,1,1); + ulisttot_pack = t_sna_4c_ll(Kokkos::NoInit("sna:ulisttot_pack"),1,1,1,1); + ulist = t_sna_3c_ll(Kokkos::NoInit("sna:ulist"),idxu_cache_max,natom,nmax); + zlist = t_sna_3c_ll(Kokkos::NoInit("sna:zlist"),idxz_max,ndoubles,natom); + zlist_pack = t_sna_4c_ll(Kokkos::NoInit("sna:zlist_pack"),1,1,1,1); + blist = t_sna_3d_ll(Kokkos::NoInit("sna:blist"),idxb_max,ntriples,natom); + blist_pack = t_sna_4d_ll(Kokkos::NoInit("sna:blist_pack"),1,1,1,1); + ylist = t_sna_3c_ll(Kokkos::NoInit("sna:ylist"),idxu_half_max,nelements,natom); + ylist_pack_re = t_sna_4d_ll(Kokkos::NoInit("sna:ylist_pack_re"),1,1,1,1); + ylist_pack_im = t_sna_4d_ll(Kokkos::NoInit("sna:ylist_pack_im"),1,1,1,1); + dulist = t_sna_4c3_ll(Kokkos::NoInit("sna:dulist"),idxu_cache_max,natom,nmax); #ifdef LMP_KOKKOS_GPU } diff --git a/src/MANYBODY/pair_adp.cpp b/src/MANYBODY/pair_adp.cpp index 3b98c91cb8..f293e51906 100644 --- a/src/MANYBODY/pair_adp.cpp +++ b/src/MANYBODY/pair_adp.cpp @@ -610,7 +610,7 @@ void PairADP::read_file(char *filename) reader.next_dvector(&file->w2r[i][j][1], file->nr); } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/MANYBODY/pair_airebo.cpp b/src/MANYBODY/pair_airebo.cpp index eb92e0c58a..470dbd838d 100644 --- a/src/MANYBODY/pair_airebo.cpp +++ b/src/MANYBODY/pair_airebo.cpp @@ -3634,12 +3634,12 @@ void PairAIREBO::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { std::string msg = fmt::format("ERROR reading {} section in {} file\n" "REASON: {}\n", current_section, potential_name, e.what()); error->one(FLERR, msg); - } catch (FileReaderException & fre) { + } catch (FileReaderException &fre) { error->one(FLERR, fre.what()); std::string msg = fmt::format("ERROR reading {} section in {} file\n" "REASON: {}\n", diff --git a/src/MANYBODY/pair_bop.cpp b/src/MANYBODY/pair_bop.cpp index 4c7d30e457..c47fc656c1 100644 --- a/src/MANYBODY/pair_bop.cpp +++ b/src/MANYBODY/pair_bop.cpp @@ -5223,9 +5223,9 @@ void _noopt PairBOP::read_table(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); - } catch (FileReaderException & fre) { + } catch (FileReaderException &fre) { error->one(FLERR, fre.what()); } } diff --git a/src/MANYBODY/pair_comb.cpp b/src/MANYBODY/pair_comb.cpp index 95b49b98f9..1c1bcfd6c3 100644 --- a/src/MANYBODY/pair_comb.cpp +++ b/src/MANYBODY/pair_comb.cpp @@ -679,7 +679,7 @@ void PairComb::read_file(char *file) params[nparams].cml2 = values.next_double(); params[nparams].coulcut = values.next_double(); params[nparams].hfocor = values.next_double(); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_comb3.cpp b/src/MANYBODY/pair_comb3.cpp index 01a1538f7b..534fcdafd5 100644 --- a/src/MANYBODY/pair_comb3.cpp +++ b/src/MANYBODY/pair_comb3.cpp @@ -450,9 +450,9 @@ void PairComb3::read_lib() } } - } catch (FileReaderException & fre) { + } catch (FileReaderException &fre) { error->one(FLERR, fre.what()); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } @@ -640,7 +640,7 @@ void PairComb3::read_file(char *file) params[nparams].addrep = values.next_double(); params[nparams].pcross = values.next_double(); params[nparams].powermint = int(params[nparams].powerm); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_eam.cpp b/src/MANYBODY/pair_eam.cpp index ac96c040bb..9325716110 100644 --- a/src/MANYBODY/pair_eam.cpp +++ b/src/MANYBODY/pair_eam.cpp @@ -506,7 +506,7 @@ void PairEAM::read_file(char *filename) for (int j = 1; j <= file->nr; ++j) file->zr[j] *= sqrt_conv; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/MANYBODY/pair_eam_alloy.cpp b/src/MANYBODY/pair_eam_alloy.cpp index f17d500a40..5307edee1a 100644 --- a/src/MANYBODY/pair_eam_alloy.cpp +++ b/src/MANYBODY/pair_eam_alloy.cpp @@ -184,7 +184,7 @@ void PairEAMAlloy::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/MANYBODY/pair_eam_fs.cpp b/src/MANYBODY/pair_eam_fs.cpp index 1c055e1bcf..6c721c81f8 100644 --- a/src/MANYBODY/pair_eam_fs.cpp +++ b/src/MANYBODY/pair_eam_fs.cpp @@ -189,7 +189,7 @@ void PairEAMFS::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/MANYBODY/pair_eim.cpp b/src/MANYBODY/pair_eim.cpp index 8f229060cf..620fa88d32 100644 --- a/src/MANYBODY/pair_eim.cpp +++ b/src/MANYBODY/pair_eim.cpp @@ -1071,7 +1071,7 @@ EIMPotentialFileReader::EIMPotentialFileReader(LAMMPS *lmp, fclose(fp); } -std::pair EIMPotentialFileReader::get_pair(const std::string & a, const std::string & b) { +std::pair EIMPotentialFileReader::get_pair(const std::string &a, const std::string &b) { if (a < b) { return std::make_pair(a, b); } diff --git a/src/MANYBODY/pair_gw.cpp b/src/MANYBODY/pair_gw.cpp index 6a97975d45..4b5901fd81 100644 --- a/src/MANYBODY/pair_gw.cpp +++ b/src/MANYBODY/pair_gw.cpp @@ -443,7 +443,7 @@ void PairGW::read_file(char *file) params[nparams].biga *= conversion_factor; params[nparams].bigb *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_gw_zbl.cpp b/src/MANYBODY/pair_gw_zbl.cpp index 69c677d0cf..a66c9bb795 100644 --- a/src/MANYBODY/pair_gw_zbl.cpp +++ b/src/MANYBODY/pair_gw_zbl.cpp @@ -138,7 +138,7 @@ void PairGWZBL::read_file(char *file) params[nparams].biga *= conversion_factor; params[nparams].bigb *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_nb3b_harmonic.cpp b/src/MANYBODY/pair_nb3b_harmonic.cpp index 859652dd10..6151c8ce22 100644 --- a/src/MANYBODY/pair_nb3b_harmonic.cpp +++ b/src/MANYBODY/pair_nb3b_harmonic.cpp @@ -344,7 +344,7 @@ void PairNb3bHarmonic::read_file(char *file) params[nparams].cutoff = values.next_double(); if (unit_convert) params[nparams].k_theta *= conversion_factor; - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_polymorphic.cpp b/src/MANYBODY/pair_polymorphic.cpp index 99eb2fec55..5520cad274 100644 --- a/src/MANYBODY/pair_polymorphic.cpp +++ b/src/MANYBODY/pair_polymorphic.cpp @@ -612,7 +612,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 &e) { error->one(FLERR,"Potential file incompatible with this pair style version"); } @@ -631,7 +631,7 @@ void PairPolymorphic::read_file(char *file) p.cutsq = p.cut*p.cut; p.xi = values.next_double(); } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/MANYBODY/pair_sw.cpp b/src/MANYBODY/pair_sw.cpp index b74eda0f85..aff333902f 100644 --- a/src/MANYBODY/pair_sw.cpp +++ b/src/MANYBODY/pair_sw.cpp @@ -414,7 +414,7 @@ void PairSW::read_file(char *file) params[nparams].powerp = values.next_double(); params[nparams].powerq = values.next_double(); params[nparams].tol = values.next_double(); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_tersoff.cpp b/src/MANYBODY/pair_tersoff.cpp index b8379d15cc..d6d5307ef7 100644 --- a/src/MANYBODY/pair_tersoff.cpp +++ b/src/MANYBODY/pair_tersoff.cpp @@ -466,7 +466,7 @@ void PairTersoff::read_file(char *file) params[nparams].biga *= conversion_factor; params[nparams].bigb *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_tersoff_mod.cpp b/src/MANYBODY/pair_tersoff_mod.cpp index ea40125ce4..b319977a09 100644 --- a/src/MANYBODY/pair_tersoff_mod.cpp +++ b/src/MANYBODY/pair_tersoff_mod.cpp @@ -121,7 +121,7 @@ void PairTersoffMOD::read_file(char *file) params[nparams].biga *= conversion_factor; params[nparams].bigb *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_tersoff_mod_c.cpp b/src/MANYBODY/pair_tersoff_mod_c.cpp index 6a6497afae..8fac2ff162 100644 --- a/src/MANYBODY/pair_tersoff_mod_c.cpp +++ b/src/MANYBODY/pair_tersoff_mod_c.cpp @@ -114,7 +114,7 @@ void PairTersoffMODC::read_file(char *file) params[nparams].bigb *= conversion_factor; params[nparams].c0 *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_tersoff_zbl.cpp b/src/MANYBODY/pair_tersoff_zbl.cpp index fad89195b2..ef6b1079ff 100644 --- a/src/MANYBODY/pair_tersoff_zbl.cpp +++ b/src/MANYBODY/pair_tersoff_zbl.cpp @@ -140,7 +140,7 @@ void PairTersoffZBL::read_file(char *file) params[nparams].biga *= conversion_factor; params[nparams].bigb *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MANYBODY/pair_vashishta.cpp b/src/MANYBODY/pair_vashishta.cpp index 10ac2c418f..61828949c7 100644 --- a/src/MANYBODY/pair_vashishta.cpp +++ b/src/MANYBODY/pair_vashishta.cpp @@ -432,7 +432,7 @@ void PairVashishta::read_file(char *file) params[nparams].bigb *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MOLECULE/angle_table.cpp b/src/MOLECULE/angle_table.cpp index 6e47bf7877..3fbda1cb99 100644 --- a/src/MOLECULE/angle_table.cpp +++ b/src/MOLECULE/angle_table.cpp @@ -411,7 +411,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 &e) { ++cerror; } } @@ -526,7 +526,7 @@ void AngleTable::param_extract(Table *tb, char *line) error->one(FLERR,"Invalid keyword in angle table parameters"); } } - } catch(TokenizerException & e) { + } catch(TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/MOLECULE/bond_table.cpp b/src/MOLECULE/bond_table.cpp index a7fbbb84d7..32bc6432b3 100644 --- a/src/MOLECULE/bond_table.cpp +++ b/src/MOLECULE/bond_table.cpp @@ -341,7 +341,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 &e) { ++cerror; } @@ -491,7 +491,7 @@ void BondTable::param_extract(Table *tb, char *line) error->one(FLERR,"Invalid keyword in bond table parameters"); } } - } catch(TokenizerException & e) { + } catch(TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/Makefile b/src/Makefile index 8216d5164c..149dedd35b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -364,7 +364,7 @@ yes-%: @if [ ! -e Makefile.package.settings ]; \ then cp Makefile.package.settings.empty Makefile.package.settings; fi @if [ ! -e $(YESDIR) ]; then \ - echo "Package $(@:yes-%=%) does not exist"; \ + echo "Package $(YESDIR) does not exist"; exit 1; \ elif [ -e $(YESDIR)/Install.sh ]; then \ echo "Installing package $(@:yes-%=%)"; \ cd $(YESDIR); $(SHELL) Install.sh 1; cd ..; \ @@ -378,7 +378,7 @@ yes-%: no-%: @if [ ! -e $(NODIR) ]; then \ - echo "Package $(@:no-%=%) does not exist"; \ + echo "Package $(NODIR) does not exist"; exit 1; \ elif [ -e $(NODIR)/Install.sh ]; then \ echo "Uninstalling package $(@:no-%=%)"; \ cd $(NODIR); $(SHELL) Install.sh 0; cd ..; \ diff --git a/src/POEMS/fix_poems.cpp b/src/POEMS/fix_poems.cpp index 3b53c1abc4..414c55d502 100644 --- a/src/POEMS/fix_poems.cpp +++ b/src/POEMS/fix_poems.cpp @@ -34,8 +34,7 @@ #include "citeme.h" #include "memory.h" #include "error.h" - - +#include "math_eigen.h" using namespace LAMMPS_NS; using namespace FixConst; @@ -44,7 +43,6 @@ using namespace FixConst; #define DELTA 128 #define TOLERANCE 1.0e-6 #define EPSILON 1.0e-7 -#define MAXJACOBI 50 static const char cite_fix_poems[] = "fix poems command:\n\n" @@ -492,7 +490,7 @@ void FixPOEMS::init() tensor[1][2] = tensor[2][1] = all[ibody][4]; tensor[0][2] = tensor[2][0] = all[ibody][5]; - ierror = jacobi(tensor,inertia[ibody],evectors); + ierror = MathEigen::jacobi3(tensor,inertia[ibody],evectors); if (ierror) error->all(FLERR,"Insufficient Jacobi rotations for POEMS body"); ex_space[ibody][0] = evectors[0][0]; @@ -1283,88 +1281,6 @@ int FixPOEMS::loopcheck(int nvert, int nedge, tagint **elist) return 0; } -/* ---------------------------------------------------------------------- - compute evalues and evectors of 3x3 real symmetric matrix - based on Jacobi rotations - adapted from Numerical Recipes jacobi() function -------------------------------------------------------------------------- */ - -int FixPOEMS::jacobi(double **matrix, double *evalues, double **evectors) -{ - int i,j,k; - double tresh,theta,tau,t,sm,s,h,g,c,b[3],z[3]; - - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) evectors[i][j] = 0.0; - evectors[i][i] = 1.0; - } - for (i = 0; i < 3; i++) { - b[i] = evalues[i] = matrix[i][i]; - z[i] = 0.0; - } - - for (int iter = 1; iter <= MAXJACOBI; iter++) { - sm = 0.0; - for (i = 0; i < 2; i++) - for (j = i+1; j < 3; j++) - sm += fabs(matrix[i][j]); - if (sm == 0.0) return 0; - - if (iter < 4) tresh = 0.2*sm/(3*3); - else tresh = 0.0; - - for (i = 0; i < 2; i++) { - for (j = i+1; j < 3; j++) { - g = 100.0*fabs(matrix[i][j]); - if (iter > 4 && fabs(evalues[i])+g == fabs(evalues[i]) - && fabs(evalues[j])+g == fabs(evalues[j])) - matrix[i][j] = 0.0; - else if (fabs(matrix[i][j]) > tresh) { - h = evalues[j]-evalues[i]; - if (fabs(h)+g == fabs(h)) t = (matrix[i][j])/h; - else { - theta = 0.5*h/(matrix[i][j]); - t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta)); - if (theta < 0.0) t = -t; - } - c = 1.0/sqrt(1.0+t*t); - s = t*c; - tau = s/(1.0+c); - h = t*matrix[i][j]; - z[i] -= h; - z[j] += h; - evalues[i] -= h; - evalues[j] += h; - matrix[i][j] = 0.0; - for (k = 0; k < i; k++) rotate(matrix,k,i,k,j,s,tau); - for (k = i+1; k < j; k++) rotate(matrix,i,k,k,j,s,tau); - for (k = j+1; k < 3; k++) rotate(matrix,i,k,j,k,s,tau); - for (k = 0; k < 3; k++) rotate(evectors,k,i,k,j,s,tau); - } - } - } - - for (i = 0; i < 3; i++) { - evalues[i] = b[i] += z[i]; - z[i] = 0.0; - } - } - return 1; -} - -/* ---------------------------------------------------------------------- - perform a single Jacobi rotation -------------------------------------------------------------------------- */ - -void FixPOEMS::rotate(double **matrix, int i, int j, int k, int l, - double s, double tau) -{ - double g = matrix[i][j]; - double h = matrix[k][l]; - matrix[i][j] = g-s*(h+g*tau); - matrix[k][l] = h+s*(g-h*tau); -} - /* ---------------------------------------------------------------------- compute omega from angular momentum w = omega = angular velocity in space frame diff --git a/src/POEMS/fix_poems.h b/src/POEMS/fix_poems.h index 6892c51d7e..7c81889639 100644 --- a/src/POEMS/fix_poems.h +++ b/src/POEMS/fix_poems.h @@ -106,8 +106,6 @@ class FixPOEMS : public Fix { void jointbuild(); void sortlist(int, tagint **); int loopcheck(int, int, tagint **); - int jacobi(double **, double *, double **); - void rotate(double **, int, int, int, int, double, double); void omega_from_mq(double *, double *, double *, double *, double *, double *); void set_v(); diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 5a94d33e98..c6482d36fd 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -235,12 +235,14 @@ void PythonImpl::command(int narg, char **arg) if (!pFunc) { PyGILState_Release(gstate); - error->all(FLERR,"Could not find Python function"); + error->all(FLERR,fmt::format("Could not find Python function {}", + pfuncs[ifunc].name)); } if (!PyCallable_Check(pFunc)) { PyGILState_Release(gstate); - error->all(FLERR,"Python function is not callable"); + error->all(FLERR,fmt::format("Python function {} is not callable", + pfuncs[ifunc].name)); } pfuncs[ifunc].pFunc = (void *) pFunc; diff --git a/src/REPLICA/fix_hyper_global.cpp b/src/REPLICA/fix_hyper_global.cpp index 9a396d2987..811346d959 100644 --- a/src/REPLICA/fix_hyper_global.cpp +++ b/src/REPLICA/fix_hyper_global.cpp @@ -125,7 +125,7 @@ void FixHyperGlobal::init() if (force->newton_pair == 0) error->all(FLERR,"Hyper global requires newton pair on"); - if (atom->molecular && me == 0) + if ((atom->molecular != Atom::ATOMIC) && (me == 0)) error->warning(FLERR,"Hyper global for molecular systems " "requires care in defining hyperdynamic bonds"); diff --git a/src/REPLICA/fix_hyper_local.cpp b/src/REPLICA/fix_hyper_local.cpp index c26a9a6735..3dec6bdc10 100644 --- a/src/REPLICA/fix_hyper_local.cpp +++ b/src/REPLICA/fix_hyper_local.cpp @@ -274,7 +274,7 @@ void FixHyperLocal::init() if (force->newton_pair == 0) error->all(FLERR,"Hyper local requires newton pair on"); - if (atom->molecular && me == 0) + if ((atom->molecular != Atom::ATOMIC) && (me == 0)) error->warning(FLERR,"Hyper local for molecular systems " "requires care in defining hyperdynamic bonds"); diff --git a/src/RIGID/fix_rigid.cpp b/src/RIGID/fix_rigid.cpp index dd40b0fe45..d2f4f5f6c8 100644 --- a/src/RIGID/fix_rigid.cpp +++ b/src/RIGID/fix_rigid.cpp @@ -17,6 +17,7 @@ #include #include "math_extra.h" +#include "math_eigen.h" #include "atom.h" #include "atom_vec_ellipsoid.h" #include "atom_vec_line.h" @@ -970,7 +971,7 @@ void FixRigid::apply_langevin_thermostat() { if (me == 0) { double gamma1,gamma2; - + double wbody[3],tbody[3]; double delta = update->ntimestep - update->beginstep; if (delta != 0.0) delta /= update->endstep - update->beginstep; t_target = t_start + delta * (t_stop-t_start); @@ -991,12 +992,23 @@ void FixRigid::apply_langevin_thermostat() gamma1 = -1.0 / t_period / ftm2v; gamma2 = tsqrt * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v; - langextra[i][3] = inertia[i][0]*gamma1*omega[i][0] + + + // convert omega from space frame to body frame + + MathExtra::transpose_matvec(ex_space[i],ey_space[i],ez_space[i],omega[i],wbody); + + // compute langevin torques in the body frame + + tbody[0] = inertia[i][0]*gamma1*wbody[0] + sqrt(inertia[i][0])*gamma2*(random->uniform()-0.5); - langextra[i][4] = inertia[i][1]*gamma1*omega[i][1] + + tbody[1] = inertia[i][1]*gamma1*wbody[1] + sqrt(inertia[i][1])*gamma2*(random->uniform()-0.5); - langextra[i][5] = inertia[i][2]*gamma1*omega[i][2] + + tbody[2] = inertia[i][2]*gamma1*wbody[2] + sqrt(inertia[i][2])*gamma2*(random->uniform()-0.5); + + // convert langevin torques from body frame back to space frame + + MathExtra::matvec(ex_space[i],ey_space[i],ez_space[i],tbody,&langextra[i][3]); } } @@ -1948,7 +1960,7 @@ void FixRigid::setup_bodies_static() tensor[0][2] = tensor[2][0] = all[ibody][4]; tensor[0][1] = tensor[1][0] = all[ibody][5]; - ierror = MathExtra::jacobi(tensor,inertia[ibody],evectors); + ierror = MathEigen::jacobi3(tensor,inertia[ibody],evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations for rigid body"); diff --git a/src/RIGID/fix_rigid_small.cpp b/src/RIGID/fix_rigid_small.cpp index 69f5b2b004..7699e49c41 100644 --- a/src/RIGID/fix_rigid_small.cpp +++ b/src/RIGID/fix_rigid_small.cpp @@ -18,6 +18,7 @@ #include #include #include "math_extra.h" +#include "math_eigen.h" #include "atom.h" #include "atom_vec_ellipsoid.h" #include "atom_vec_line.h" @@ -818,6 +819,7 @@ void FixRigidSmall::initial_integrate(int vflag) void FixRigidSmall::apply_langevin_thermostat() { double gamma1,gamma2; + double wbody[3],tbody[3]; // grow langextra if needed @@ -837,12 +839,15 @@ void FixRigidSmall::apply_langevin_thermostat() double mvv2e = force->mvv2e; double ftm2v = force->ftm2v; - double *vcm,*omega,*inertia; + double *vcm,*omega,*inertia,*ex_space,*ey_space,*ez_space; for (int ibody = 0; ibody < nlocal_body; ibody++) { vcm = body[ibody].vcm; omega = body[ibody].omega; inertia = body[ibody].inertia; + ex_space = body[ibody].ex_space; + ey_space = body[ibody].ey_space; + ez_space = body[ibody].ez_space; gamma1 = -body[ibody].mass / t_period / ftm2v; gamma2 = sqrt(body[ibody].mass) * tsqrt * @@ -853,12 +858,23 @@ void FixRigidSmall::apply_langevin_thermostat() gamma1 = -1.0 / t_period / ftm2v; gamma2 = tsqrt * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v; - langextra[ibody][3] = inertia[0]*gamma1*omega[0] + + + // convert omega from space frame to body frame + + MathExtra::transpose_matvec(ex_space,ey_space,ez_space,omega,wbody); + + // compute langevin torques in the body frame + + tbody[0] = inertia[0]*gamma1*wbody[0] + sqrt(inertia[0])*gamma2*(random->uniform()-0.5); - langextra[ibody][4] = inertia[1]*gamma1*omega[1] + + tbody[1] = inertia[1]*gamma1*wbody[1] + sqrt(inertia[1])*gamma2*(random->uniform()-0.5); - langextra[ibody][5] = inertia[2]*gamma1*omega[2] + + tbody[2] = inertia[2]*gamma1*wbody[2] + sqrt(inertia[2])*gamma2*(random->uniform()-0.5); + + // convert langevin torques from body frame back to space frame + + MathExtra::matvec(ex_space,ey_space,ez_space,tbody,&langextra[ibody][3]); } } @@ -2085,7 +2101,7 @@ void FixRigidSmall::setup_bodies_static() tensor[0][1] = tensor[1][0] = itensor[ibody][5]; inertia = body[ibody].inertia; - ierror = MathExtra::jacobi(tensor,inertia,evectors); + ierror = MathEigen::jacobi3(tensor,inertia,evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations for rigid body"); diff --git a/src/USER-ADIOS/dump_atom_adios.cpp b/src/USER-ADIOS/dump_atom_adios.cpp index 121bb193e1..fe6c67f60f 100644 --- a/src/USER-ADIOS/dump_atom_adios.cpp +++ b/src/USER-ADIOS/dump_atom_adios.cpp @@ -337,9 +337,9 @@ void DumpAtomADIOS::init_style() internal->io.DefineAttribute("boundarystr", boundstr); internal->io.DefineAttribute("LAMMPS/dump_style", "atom"); internal->io.DefineAttribute("LAMMPS/version", - universe->version); + lmp->version); internal->io.DefineAttribute("LAMMPS/num_ver", - universe->num_ver); + std::to_string(lmp->num_ver)); internal->io.DefineVariable( "nme", {adios2::LocalValueDim}); // local dimension variable diff --git a/src/USER-ADIOS/dump_custom_adios.cpp b/src/USER-ADIOS/dump_custom_adios.cpp index 921c725bc2..145b3ac3e5 100644 --- a/src/USER-ADIOS/dump_custom_adios.cpp +++ b/src/USER-ADIOS/dump_custom_adios.cpp @@ -424,9 +424,9 @@ void DumpCustomADIOS::init_style() internal->io.DefineAttribute("boundarystr", boundstr); internal->io.DefineAttribute("LAMMPS/dump_style", "custom"); internal->io.DefineAttribute("LAMMPS/version", - universe->version); + lmp->version); internal->io.DefineAttribute("LAMMPS/num_ver", - universe->num_ver); + std::to_string(lmp->num_ver)); internal->io.DefineVariable( "nme", {adios2::LocalValueDim}); // local dimension variable diff --git a/src/USER-BOCS/compute_pressure_bocs.cpp b/src/USER-BOCS/compute_pressure_bocs.cpp index 46aabf7903..b91a790d15 100644 --- a/src/USER-BOCS/compute_pressure_bocs.cpp +++ b/src/USER-BOCS/compute_pressure_bocs.cpp @@ -152,10 +152,12 @@ void ComputePressureBocs::init() vptr = nullptr; if (pairflag && force->pair) nvirial++; - if (bondflag && atom->molecular && force->bond) nvirial++; - if (angleflag && atom->molecular && force->angle) nvirial++; - if (dihedralflag && atom->molecular && force->dihedral) nvirial++; - if (improperflag && atom->molecular && force->improper) nvirial++; + if (atom->molecular != Atom::ATOMIC) { + if (bondflag && force->bond) nvirial++; + if (angleflag && force->angle) nvirial++; + if (dihedralflag && force->dihedral) nvirial++; + if (improperflag && force->improper) nvirial++; + } if (fixflag) for (int i = 0; i < modify->nfix; i++) if (modify->fix[i]->virial_flag) nvirial++; diff --git a/src/USER-BOCS/fix_bocs.cpp b/src/USER-BOCS/fix_bocs.cpp index 0dad793fd2..d9715362c1 100644 --- a/src/USER-BOCS/fix_bocs.cpp +++ b/src/USER-BOCS/fix_bocs.cpp @@ -64,11 +64,6 @@ enum{ISO,ANISO,TRICLINIC}; const int NUM_INPUT_DATA_COLUMNS = 2; // columns in the pressure correction file -// NB: -// - Keep error and warning messages less than 255 chars long. -// - Allocate your char buffer to be 1 char longer than this -const int MAX_MESSAGE_LENGTH = 255; - /* ---------------------------------------------------------------------- NVT,NPH,NPT integrators for improved Nose-Hoover equations of motion ---------------------------------------------------------------------- */ diff --git a/src/USER-COLVARS/colvarproxy_lammps.cpp b/src/USER-COLVARS/colvarproxy_lammps.cpp index f265271bb2..44b0b8b5ed 100644 --- a/src/USER-COLVARS/colvarproxy_lammps.cpp +++ b/src/USER-COLVARS/colvarproxy_lammps.cpp @@ -71,11 +71,9 @@ colvarproxy_lammps::colvarproxy_lammps(LAMMPS_NS::LAMMPS *lmp, _random = new LAMMPS_NS::RanPark(lmp,seed); first_timestep=true; - total_force_requested=false; previous_step=-1; t_target=temp; do_exit=false; - restart_every=0; // User-scripted forces are not available in LAMMPS force_script_defined = false; @@ -94,15 +92,17 @@ colvarproxy_lammps::colvarproxy_lammps(LAMMPS_NS::LAMMPS *lmp, // check if it is possible to save output configuration if ((!output_prefix_str.size()) && (!restart_output_prefix_str.size())) { - fatal_error("Error: neither the final output state file or " - "the output restart file could be defined, exiting.\n"); + error("Error: neither the final output state file or " + "the output restart file could be defined, exiting.\n"); } // try to extract a restart prefix from a potential restart command. LAMMPS_NS::Output *outp = _lmp->output; if ((outp->restart_every_single > 0) && (outp->restart1 != 0)) { - restart_output_prefix_str = std::string(outp->restart1); + restart_frequency_engine = outp->restart_every_single; + restart_output_prefix_str = std::string(outp->restart1); } else if ((outp->restart_every_double > 0) && (outp->restart2a != 0)) { + restart_frequency_engine = outp->restart_every_double; restart_output_prefix_str = std::string(outp->restart2a); } // trim off unwanted stuff from the restart prefix @@ -207,12 +207,18 @@ double colvarproxy_lammps::compute() first_timestep = false; } else { // Use the time step number from LAMMPS Update object - if ( _lmp->update->ntimestep - previous_step == 1 ) + if ( _lmp->update->ntimestep - previous_step == 1 ) { colvars->it++; - // Other cases could mean: - // - run 0 - // - beginning of a new run statement - // then the internal counter should not be incremented + b_simulation_continuing = false; + } else { + // Cases covered by this condition: + // - run 0 + // - beginning of a new run statement + // The internal counter is not incremented, and the objects are made + // aware of this via the following flag + b_simulation_continuing = true; + } + } previous_step = _lmp->update->ntimestep; @@ -275,13 +281,6 @@ void colvarproxy_lammps::serialize_status(std::string &rst) rst = os.str(); } -void colvarproxy_lammps::write_output_files() -{ - // TODO skip output if undefined - colvars->write_restart_file(cvm::output_prefix()+".colvars.state"); - colvars->write_output_files(); -} - // set status from string bool colvarproxy_lammps::deserialize_status(std::string &rst) { @@ -322,13 +321,6 @@ void colvarproxy_lammps::log(std::string const &message) void colvarproxy_lammps::error(std::string const &message) -{ - // In LAMMPS, all errors are fatal - fatal_error(message); -} - - -void colvarproxy_lammps::fatal_error(std::string const &message) { log(message); _lmp->error->one(FLERR, diff --git a/src/USER-COLVARS/colvarproxy_lammps.h b/src/USER-COLVARS/colvarproxy_lammps.h index 95e7d4fb32..aee268932e 100644 --- a/src/USER-COLVARS/colvarproxy_lammps.h +++ b/src/USER-COLVARS/colvarproxy_lammps.h @@ -41,11 +41,9 @@ class colvarproxy_lammps : public colvarproxy { // state of LAMMPS properties double t_target, my_timestep, my_boltzmann, my_angstrom; double bias_energy; - int restart_every; int previous_step; bool first_timestep; - bool total_force_requested; bool do_exit; std::vector atoms_types; @@ -59,7 +57,7 @@ class colvarproxy_lammps : public colvarproxy { const char *, const int, const double, MPI_Comm); virtual ~colvarproxy_lammps(); void init(const char*); - int setup(); + virtual int setup(); // disable default and copy constructor private: @@ -82,9 +80,6 @@ class colvarproxy_lammps : public colvarproxy { // set status from string bool deserialize_status(std::string &); - // Write files expected from Colvars (called by post_run()) - void write_output_files(); - // read additional config from file int add_config_file(char const *config_filename); @@ -103,14 +98,11 @@ class colvarproxy_lammps : public colvarproxy { inline cvm::real temperature() { return t_target; }; inline cvm::real dt() { return my_timestep; }; // return _lmp->update->dt * _lmp->force->femtosecond; }; - inline size_t restart_frequency() { return restart_every; }; - void add_energy(cvm::real energy) { bias_energy += energy; }; void request_total_force(bool yesno) { total_force_requested = yesno; }; void log(std::string const &message); void error(std::string const &message); - void fatal_error(std::string const &message); cvm::rvector position_distance(cvm::atom_pos const &pos1, cvm::atom_pos const &pos2) const; diff --git a/src/USER-COLVARS/colvarproxy_lammps_version.h b/src/USER-COLVARS/colvarproxy_lammps_version.h index 7f52fa5e01..d9f2955233 100644 --- a/src/USER-COLVARS/colvarproxy_lammps_version.h +++ b/src/USER-COLVARS/colvarproxy_lammps_version.h @@ -1,3 +1,3 @@ #ifndef COLVARPROXY_VERSION -#define COLVARPROXY_VERSION "2019-12-04" +#define COLVARPROXY_VERSION "2020-04-07" #endif diff --git a/src/USER-COLVARS/fix_colvars.cpp b/src/USER-COLVARS/fix_colvars.cpp index afa7f53353..6a86ae5959 100644 --- a/src/USER-COLVARS/fix_colvars.cpp +++ b/src/USER-COLVARS/fix_colvars.cpp @@ -499,7 +499,7 @@ int FixColvars::modify_param(int narg, char **arg) if (me == 0) { if (! proxy) error->one(FLERR,"Cannot use fix_modify before initialization"); - return proxy->add_config_file(arg[1]) == COLVARS_OK ? 0 : 2; + return proxy->add_config_file(arg[1]) == COLVARS_OK ? 2 : 0; } return 2; } else if (strcmp(arg[0],"config") == 0) { @@ -508,7 +508,7 @@ int FixColvars::modify_param(int narg, char **arg) if (! proxy) error->one(FLERR,"Cannot use fix_modify before initialization"); std::string const conf(arg[1]); - return proxy->add_config_string(conf) == COLVARS_OK ? 0 : 2; + return proxy->add_config_string(conf) == COLVARS_OK ? 2 : 0; } return 2; } else if (strcmp(arg[0],"load") == 0) { @@ -516,7 +516,7 @@ int FixColvars::modify_param(int narg, char **arg) if (me == 0) { if (! proxy) error->one(FLERR,"Cannot use fix_modify before initialization"); - return proxy->read_state_file(arg[1]) == COLVARS_OK ? 0 : 2; + return proxy->read_state_file(arg[1]) == COLVARS_OK ? 2 : 0; } return 2; } @@ -984,7 +984,7 @@ void FixColvars::restart(char *buf) void FixColvars::post_run() { if (me == 0) { - proxy->write_output_files(); + proxy->post_run(); } } diff --git a/src/USER-INTEL/fix_intel.cpp b/src/USER-INTEL/fix_intel.cpp index 21cc106e31..92b47179dd 100644 --- a/src/USER-INTEL/fix_intel.cpp +++ b/src/USER-INTEL/fix_intel.cpp @@ -441,7 +441,7 @@ void FixIntel::pair_init_check(const bool cdmessage) } #ifndef LMP_INTEL_NBOR_COMPAT - if (force->pair->manybody_flag && atom->molecular) { + if (force->pair->manybody_flag && (atom->molecular != Atom::ATOMIC)) { int flag = 0; if (atom->nbonds > 0 && force->special_lj[1] == 0.0 && force->special_coul[1] == 0.0) flag = 1; @@ -456,7 +456,7 @@ void FixIntel::pair_init_check(const bool cdmessage) #endif int need_tag = 0; - if (atom->molecular) need_tag = 1; + if (atom->molecular != Atom::ATOMIC) need_tag = 1; // Clear buffers used for pair style char kmode[80]; @@ -507,8 +507,8 @@ void FixIntel::pair_init_check(const bool cdmessage) void FixIntel::bond_init_check() { - if (_offload_balance != 0.0 && atom->molecular && - force->newton_pair != force->newton_bond) + if ((_offload_balance != 0.0) && (atom->molecular != Atom::ATOMIC) + && (force->newton_pair != force->newton_bond)) error->all(FLERR, "USER-INTEL package requires same setting for newton bond and non-bond."); diff --git a/src/USER-INTEL/intel_intrinsics.h b/src/USER-INTEL/intel_intrinsics.h index ee20cd1119..d1f019feea 100644 --- a/src/USER-INTEL/intel_intrinsics.h +++ b/src/USER-INTEL/intel_intrinsics.h @@ -35,114 +35,10 @@ #include #endif -// Vector classes for Cilk array notation -// This is experimental and doesn't yield good code yet -template -struct lmp_intel_an_fvec { - fscal data[VL]; - lmp_intel_an_fvec() {} - explicit lmp_intel_an_fvec(const fscal f) { data[:] = f; } - explicit lmp_intel_an_fvec(fscal f[VL]) { data[:] = f[:]; } - lmp_intel_an_fvec(const lmp_intel_an_fvec &a) { data[:] = a.data[:]; } - lmp_intel_an_fvec& operator =(const lmp_intel_an_fvec &a) { data[:] = a.data[:]; return *this; } - const lmp_intel_an_fvec operator +(const lmp_intel_an_fvec &b) const { - lmp_intel_an_fvec ret = *this; - ret.data[:] += b.data[:]; - return ret; - } - const lmp_intel_an_fvec operator -(const lmp_intel_an_fvec &b) const { - lmp_intel_an_fvec ret = *this; - ret.data[:] -= b.data[:]; - return ret; - } - const lmp_intel_an_fvec operator *(const lmp_intel_an_fvec &b) const { - lmp_intel_an_fvec ret = *this; - ret.data[:] *= b.data[:]; - return ret; - } - const lmp_intel_an_fvec operator /(const lmp_intel_an_fvec &b) const { - lmp_intel_an_fvec ret = *this; - ret.data[:] /= b.data[:]; - return ret; - } - lmp_intel_an_fvec& operator +=(const lmp_intel_an_fvec &b) { - data[:] += b.data[:]; return *this; - } - lmp_intel_an_fvec& operator -=(const lmp_intel_an_fvec &b) { - data[:] -= b.data[:]; return *this; - } - lmp_intel_an_fvec& operator *=(const lmp_intel_an_fvec &b) { - data[:] *= b.data[:]; return *this; - } - lmp_intel_an_fvec& operator /=(const lmp_intel_an_fvec &b) { - data[:] /= b.data[:]; return *this; - } - friend lmp_intel_an_fvec sqrt(const lmp_intel_an_fvec &a) __attribute__((always_inline)) { - lmp_intel_an_fvec ret; ret.data[:] = sqrt(a.data[:]); return ret; - } - friend lmp_intel_an_fvec exp(const lmp_intel_an_fvec &a) __attribute__((always_inline)) { - lmp_intel_an_fvec ret; ret.data[:] = exp(a.data[:]); return ret; - } - friend lmp_intel_an_fvec sin(const lmp_intel_an_fvec &a) __attribute__((always_inline)) { - lmp_intel_an_fvec ret; ret.data[:] = sin(a.data[:]); return ret; - } - friend lmp_intel_an_fvec invsqrt(const lmp_intel_an_fvec &a) __attribute__((always_inline)) { - lmp_intel_an_fvec ret; ret.data[:] = ((fscal)1.) / sqrt(a.data[:]); return ret; - } - friend lmp_intel_an_fvec pow(const lmp_intel_an_fvec &a, const lmp_intel_an_fvec &b) __attribute__((always_inline)) { - lmp_intel_an_fvec ret; ret.data[:] = pow(a.data[:], b.data[:]); return ret; - } - lmp_intel_an_fvec operator - () const { - lmp_intel_an_fvec ret; ret.data[:] = - data[:]; return ret; - } -}; -template -struct lmp_intel_an_ivec { - int data[VL]; - lmp_intel_an_ivec() {} - explicit lmp_intel_an_ivec(int i) { data[:] = i; } - explicit lmp_intel_an_ivec(const int * a) { data[:] = a[0:VL]; } - const lmp_intel_an_ivec operator &(const lmp_intel_an_ivec &b) { - lmp_intel_an_ivec ret = *this; - ret.data[:] &= b.data[:]; - return ret; - } - const lmp_intel_an_ivec operator |(const lmp_intel_an_ivec &b) { - lmp_intel_an_ivec ret = *this; - ret.data[:] |= b.data[:]; - return ret; - } - const lmp_intel_an_ivec operator +(const lmp_intel_an_ivec &b) { - lmp_intel_an_ivec ret = *this; - ret.data[:] += b.data[:]; - return ret; - } -}; -template -struct lmp_intel_an_bvec { - bool data[VL]; - lmp_intel_an_bvec() {} - lmp_intel_an_bvec(const lmp_intel_an_bvec &a) { data[:] = a.data[:]; } - lmp_intel_an_bvec& operator =(const lmp_intel_an_bvec &a) { data[:] = a.data[:]; return *this; } - explicit lmp_intel_an_bvec(int i) { data[:] = i; } - friend lmp_intel_an_bvec operator &(const lmp_intel_an_bvec &a, const lmp_intel_an_bvec &b) __attribute__((always_inline)) { - lmp_intel_an_bvec ret; ret.data[:] = a.data[:] & b.data[:]; return ret; - } - friend lmp_intel_an_bvec operator |(const lmp_intel_an_bvec &a, const lmp_intel_an_bvec &b) __attribute__((always_inline)) { - lmp_intel_an_bvec ret; ret.data[:] = a.data[:] | b.data[:]; return ret; - } - friend lmp_intel_an_bvec operator ~(const lmp_intel_an_bvec &a) __attribute__((always_inline)) { - lmp_intel_an_bvec ret; ret.data[:] = ! a.data[:]; return ret; - } - lmp_intel_an_bvec& operator &=(const lmp_intel_an_bvec &a) __attribute__((always_inline)) { - data[:] &= a.data[:]; return *this; - } -}; - namespace lmp_intel { -// Self explanatory mostly, KNC=IMCI and AVX-512, NONE=Scalar, AN=Array Not. -enum CalculationMode { KNC, AVX, AVX2, SSE, NONE, AN }; +// Self explanatory mostly, KNC=IMCI and AVX-512, NONE=Scalar. +enum CalculationMode {KNC, AVX, AVX2, SSE, NONE}; #ifdef __MIC__ #ifdef LMP_INTEL_VECTOR_MIC static const CalculationMode mode = LMP_INTEL_VECTOR_MIC; @@ -1916,148 +1812,6 @@ struct vector_ops { } }; -// Array notation implementation -template -struct vector_ops { - static const int VL = 4; - typedef flt_t fscal; - typedef lmp_intel_an_fvec fvec; - typedef lmp_intel_an_ivec ivec; - typedef lmp_intel_an_bvec bvec; - typedef flt_t farr[VL]; - typedef int iarr[VL]; - static fvec recip(const fvec &a) { - fvec ret; ret.data[:] = ((fscal)1.) / a.data[:]; return ret; - } - template - static void gather_prefetch_t0(const ivec &idx, const bvec &mask, const void *base) { - // nop - } - template - static fvec gather(const fvec &from, const bvec &mask, const ivec &idx, const void *base) { - fvec ret = from; - if (mask.data[:]) ret.data[:] = *reinterpret_cast(reinterpret_cast(base) + scale * idx.data[:]); - return ret; - } - template - static void gather_x(const ivec &idxs, const bvec &mask, const T *base, fvec *x, fvec *y, fvec *z, ivec *w) { - *x = gather<1>(*x, mask, idxs, &base->x); - *y = gather<1>(*y, mask, idxs, &base->y); - *z = gather<1>(*z, mask, idxs, &base->z); - *w = int_gather<1>(*w, mask, idxs, &base->w); - } - static void gather_8(const ivec &idxs, const bvec &mask, const void *base, - fvec *r0, fvec *r1, fvec *r2, fvec *r3, fvec *r4, fvec *r5, fvec *r6, fvec *r7) { - fvec a = zero(), b = zero(), c = zero(), d = zero(); - gather_4(idxs, mask, base, r0, r1, r2, r3); - gather_4(idxs, mask, reinterpret_cast(base) + 4 * sizeof(fscal), r4, r5, r6, r7); - } - static void gather_4(const ivec &idxs, const bvec &mask, const void *base, - fvec *r0, fvec *r1, fvec *r2, fvec *r3) { - *r0 = gather<4>(*r0, mask, idxs, reinterpret_cast(base) + 0 * sizeof(fscal)); - *r1 = gather<4>(*r1, mask, idxs, reinterpret_cast(base) + 1 * sizeof(fscal)); - *r2 = gather<4>(*r2, mask, idxs, reinterpret_cast(base) + 2 * sizeof(fscal)); - *r3 = gather<4>(*r3, mask, idxs, reinterpret_cast(base) + 3 * sizeof(fscal)); - } - static fvec blend(const bvec &mask, const fvec &a, const fvec &b) { - fvec ret = a; - if (mask.data[:]) ret.data[:] = b.data[:]; - return ret; - } - static ivec int_blend(const bvec &mask, const ivec &a, const ivec &b) { - fvec ret = a; - if (mask.data[:]) ret.data[:] = b.data[:]; - return ret; - } - static fvec fmadd(const fvec &a, const fvec &b, const fvec &c) { - fvec ret; ret.data[:] = a.data[:] * b.data[:] + c.data[:]; return ret; - } - static fvec zero() { - return fvec(0.); - } - static bvec cmpeq(const fvec &a, const fvec &b) { - bvec ret; ret.data[:] = a.data[:] == b.data[:]; return ret; - } - static bvec cmpnle(const fvec &a, const fvec &b) { - bvec ret; ret.data[:] = !(a.data[:] <= b.data[:]); return ret; - } - static bvec cmple(const fvec &a, const fvec &b) { - bvec ret; ret.data[:] = a.data[:] <= b.data[:]; return ret; - } - static bvec cmplt(const fvec &a, const fvec &b) { - bvec ret; ret.data[:] = a.data[:] < b.data[:]; return ret; - } - static bvec int_cmpneq(const ivec &a, const ivec &b) { - bvec ret; ret.data[:] = a.data[:] != b.data[:]; return ret; - } - static bvec int_cmplt(const ivec &a, const ivec &b) { - bvec ret; ret.data[:] = a.data[:] < b.data[:]; return ret; - } - static fvec invsqrt(const fvec &a) { - fvec ret; ret.data[:] = ((fscal)1.) / sqrt(a.data[:]); return ret; - } - static fvec sincos(fvec *c, const fvec &a) { - c->data[:] = cos(a.data[:]); - fvec ret; ret.data[:] = sin(a.data[:]); return ret; - } - static fscal reduce_add(const fvec &a) { - return __sec_reduce_add(a.data[:]); - } - static ivec int_mullo(const ivec &a, const ivec &b) { - ivec ret; ret.data[:] = a.data[:] * b.data[:]; return ret; - } - static ivec int_mask_add(const ivec &src, const bvec &mask, const ivec &a, const ivec &b) { - ivec ret = src; - if (mask.data[:]) ret.data[:] = a.data[:] + b.data[:]; - return ret; - } - template - static ivec int_gather(const ivec &from, bvec mask, const ivec &idx, const void *base) { - ivec ret = from; - if (mask.data[:]) ret.data[:] = reinterpret_cast(base)[scale * idx.data[:] / sizeof(int)]; - return ret; - } - static fvec mask_add(const fvec &src, const bvec &mask, const fvec &a, const fvec &b) { - fvec ret = src; - if (mask.data[:]) ret.data[:] = a.data[:] + b.data[:]; - return ret; - } - static void store(void *at, const fvec &a) { - reinterpret_cast(at)[0:VL] = a.data[:]; - } - static void int_store(int *at, const ivec &a) { - reinterpret_cast(at)[0:VL] = a.data[:]; - } - static void mask_store(int *at, const bvec &a) { - at[0:VL] = a.data[:]; - } - static fvec min(const fvec &a, const fvec &b) { - fvec ret = b; - if (a.data[:] < b.data[:]) ret.data[:] = a.data[:]; - return ret; - } - static bool mask_test_at(const bvec &mask, int at) { - return mask.data[at]; - } - static bool mask_testz(const bvec &mask) { - return ! __sec_reduce_or(mask.data[:]); - } - static bvec mask_enable_lower(int n) { - bvec ret; ret.data[:] = __sec_implicit_index(0) < n; return ret; - } - static ivec int_load_vl(const int *a) { - return ivec(a); - } - static void int_clear_arr(int *a) { - a[0:VL] = 0; - } - static bvec full_mask() { - return bvec(1); - } - static void int_print(const ivec &a) { - } -}; - // Mixins to implement mixed precision and single/single and double/double // This one is for single/single and double/double template @@ -2138,7 +1892,7 @@ struct AccumulatorTwiceMixin { }; // For cases where vector_ops::VL == vector_ops::VL -// i.e. scalar & AN + template struct AccumulatorTwiceMixinNone { typedef vector_ops BASE; @@ -2177,11 +1931,8 @@ struct vector_routines : public vector_ops, public template struct vector_routines : public vector_ops, public AccumulatorTwiceMixin {}; -// Specialize for AN and scalar +// Specialize for scalar template<> struct vector_routines : public vector_ops, public AccumulatorTwiceMixinNone {}; -template<> -struct vector_routines : public vector_ops, public AccumulatorTwiceMixinNone {}; - } // namespace lmp_intel diff --git a/src/USER-INTEL/npair_full_bin_ghost_intel.cpp b/src/USER-INTEL/npair_full_bin_ghost_intel.cpp index ae7ac78bc8..50a3586d31 100644 --- a/src/USER-INTEL/npair_full_bin_ghost_intel.cpp +++ b/src/USER-INTEL/npair_full_bin_ghost_intel.cpp @@ -88,7 +88,7 @@ void NPairFullBinGhostIntel::fbi(NeighList * list, _fix->nbor_pack_width()); int need_ic = 0; - if (atom->molecular) + if (atom->molecular != Atom::ATOMIC) dminimum_image_check(need_ic, neighbor->cutneighmax, neighbor->cutneighmax, neighbor->cutneighmax); @@ -420,7 +420,7 @@ void NPairFullBinGhostIntel::fbi(const int offload, NeighList * list, } } // for u - if (molecular && i < nlocal) { + if ((molecular != Atom::ATOMIC) && (i < nlocal)) { int alln = n; n = 0; #if defined(LMP_SIMD_COMPILER) diff --git a/src/USER-INTEL/pair_eam_alloy_intel.cpp b/src/USER-INTEL/pair_eam_alloy_intel.cpp index b78baf896f..e208212d79 100644 --- a/src/USER-INTEL/pair_eam_alloy_intel.cpp +++ b/src/USER-INTEL/pair_eam_alloy_intel.cpp @@ -183,7 +183,7 @@ void PairEAMAlloyIntel::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/USER-INTEL/pair_eam_fs_intel.cpp b/src/USER-INTEL/pair_eam_fs_intel.cpp index 84cfcb8a11..6e17d3d552 100644 --- a/src/USER-INTEL/pair_eam_fs_intel.cpp +++ b/src/USER-INTEL/pair_eam_fs_intel.cpp @@ -186,7 +186,7 @@ void PairEAMFSIntel::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/USER-MISC/compute_gyration_shape.cpp b/src/USER-MISC/compute_gyration_shape.cpp index 6aef8c80ec..50cd6d3ce2 100644 --- a/src/USER-MISC/compute_gyration_shape.cpp +++ b/src/USER-MISC/compute_gyration_shape.cpp @@ -21,6 +21,7 @@ #include #include "error.h" #include "math_extra.h" +#include "math_eigen.h" #include "math_special.h" #include "modify.h" #include "update.h" @@ -95,7 +96,7 @@ void ComputeGyrationShape::compute_vector() ione[1][2] = ione[2][1] = gyration_tensor[4]; ione[0][2] = ione[2][0] = gyration_tensor[5]; - int ierror = MathExtra::jacobi(ione,evalues,evectors); + int ierror = MathEigen::jacobi3(ione,evalues,evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations " "for gyration/shape"); diff --git a/src/USER-MISC/compute_gyration_shape_chunk.cpp b/src/USER-MISC/compute_gyration_shape_chunk.cpp index 2c9bf9d3ed..af9fcc6159 100644 --- a/src/USER-MISC/compute_gyration_shape_chunk.cpp +++ b/src/USER-MISC/compute_gyration_shape_chunk.cpp @@ -21,6 +21,7 @@ #include #include "error.h" #include "math_extra.h" +#include "math_eigen.h" #include "math_special.h" #include "modify.h" #include "memory.h" @@ -125,7 +126,7 @@ void ComputeGyrationShapeChunk::compute_array() ione[0][2] = ione[2][0] = gyration_tensor[ichunk][4]; ione[1][2] = ione[2][1] = gyration_tensor[ichunk][5]; - int ierror = MathExtra::jacobi(ione,evalues,evectors); + int ierror = MathEigen::jacobi3(ione,evalues,evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations " "for gyration/shape"); diff --git a/src/USER-MISC/dihedral_table.cpp b/src/USER-MISC/dihedral_table.cpp index d09684df98..2b9e829a83 100644 --- a/src/USER-MISC/dihedral_table.cpp +++ b/src/USER-MISC/dihedral_table.cpp @@ -1091,7 +1091,7 @@ void DihedralTable::read_table(Table *tb, char *file, char *keyword) tb->efile[i] = values.next_double(); tb->ffile[i] = values.next_double(); } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } //for (int i = 0; (i < tb->ninput) && fp; i++) { @@ -1316,7 +1316,7 @@ void DihedralTable::param_extract(Table *tb, char *line) else error->one(FLERR,fmt::format("Invalid keyword in dihedral angle " "table parameters ({})", word)); } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/USER-MISC/pair_tersoff_table.cpp b/src/USER-MISC/pair_tersoff_table.cpp index bc6be2d399..b823a17ca0 100644 --- a/src/USER-MISC/pair_tersoff_table.cpp +++ b/src/USER-MISC/pair_tersoff_table.cpp @@ -923,7 +923,7 @@ void PairTersoffTable::read_file(char *file) params[nparams].biga *= conversion_factor; params[nparams].bigb *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/USER-NETCDF/dump_netcdf.cpp b/src/USER-NETCDF/dump_netcdf.cpp index c48688df4d..6d2ab29615 100644 --- a/src/USER-NETCDF/dump_netcdf.cpp +++ b/src/USER-NETCDF/dump_netcdf.cpp @@ -512,7 +512,7 @@ void DumpNetCDF::openfile() NCERR( nc_put_att_text(ncid, NC_GLOBAL, "program", 6, "LAMMPS") ); NCERR( nc_put_att_text(ncid, NC_GLOBAL, "programVersion", - strlen(universe->version), universe->version) ); + strlen(lmp->version), lmp->version) ); // units if (!strcmp(update->unit_style, "lj")) { diff --git a/src/USER-NETCDF/dump_netcdf_mpiio.cpp b/src/USER-NETCDF/dump_netcdf_mpiio.cpp index 4288bf6bab..e0b193fc30 100644 --- a/src/USER-NETCDF/dump_netcdf_mpiio.cpp +++ b/src/USER-NETCDF/dump_netcdf_mpiio.cpp @@ -497,7 +497,7 @@ void DumpNetCDFMPIIO::openfile() NCERR( ncmpi_put_att_text(ncid, NC_GLOBAL, "program", 6, "LAMMPS") ); NCERR( ncmpi_put_att_text(ncid, NC_GLOBAL, "programVersion", - strlen(universe->version), universe->version) ); + strlen(lmp->version), lmp->version) ); // units if (!strcmp(update->unit_style, "lj")) { diff --git a/src/USER-OMP/pair_eam_alloy_omp.cpp b/src/USER-OMP/pair_eam_alloy_omp.cpp index 2f29aced65..b761fc8b8e 100644 --- a/src/USER-OMP/pair_eam_alloy_omp.cpp +++ b/src/USER-OMP/pair_eam_alloy_omp.cpp @@ -184,7 +184,7 @@ void PairEAMAlloyOMP::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/USER-OMP/pair_eam_fs_omp.cpp b/src/USER-OMP/pair_eam_fs_omp.cpp index a7fd0cac51..2aba40ba73 100644 --- a/src/USER-OMP/pair_eam_fs_omp.cpp +++ b/src/USER-OMP/pair_eam_fs_omp.cpp @@ -187,7 +187,7 @@ void PairEAMFSOMP::read_file(char *filename) } } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } } diff --git a/src/USER-OMP/pair_tersoff_zbl_omp.cpp b/src/USER-OMP/pair_tersoff_zbl_omp.cpp index 7bb3814549..2fb8360197 100644 --- a/src/USER-OMP/pair_tersoff_zbl_omp.cpp +++ b/src/USER-OMP/pair_tersoff_zbl_omp.cpp @@ -157,7 +157,7 @@ void PairTersoffZBLOMP::read_file(char *file) params[nparams].biga *= conversion_factor; params[nparams].bigb *= conversion_factor; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/USER-PTM/compute_ptm_atom.cpp b/src/USER-PTM/compute_ptm_atom.cpp index 508c3d0ffd..497fb7f972 100644 --- a/src/USER-PTM/compute_ptm_atom.cpp +++ b/src/USER-PTM/compute_ptm_atom.cpp @@ -285,7 +285,7 @@ void ComputePTMAtom::compute_peratom() { // zero output - memset(output,0,nmax*NUM_COLUMNS*sizeof(double)); + memset(&output[0][0],0,nmax*NUM_COLUMNS*sizeof(double)); for (int ii = 0; ii < inum; ii++) { @@ -304,21 +304,17 @@ void ComputePTMAtom::compute_peratom() { double scale, rmsd, interatomic_distance; double q[4]; bool standard_orientations = false; + + rmsd = INFINITY; + interatomic_distance = q[0] = q[1] = q[2] = q[3] = 0.0; + ptm_index(local_handle, i, get_neighbours, (void*)&nbrlist, input_flags, standard_orientations, &type, &alloy_type, &scale, &rmsd, q, nullptr, nullptr, nullptr, nullptr, &interatomic_distance, nullptr, nullptr); - if (rmsd > rmsd_threshold) { - type = PTM_MATCH_NONE; - } - - // printf("%d type=%d rmsd=%f\n", i, type, rmsd); - - if (type == PTM_MATCH_NONE) { - type = PTM_LAMMPS_OTHER; - rmsd = INFINITY; - } + if (rmsd > rmsd_threshold) type = PTM_MATCH_NONE; + if (type == PTM_MATCH_NONE) type = PTM_LAMMPS_OTHER; output[i][0] = type; output[i][1] = rmsd; @@ -329,7 +325,6 @@ void ComputePTMAtom::compute_peratom() { output[i][6] = q[3]; } - // printf("finished ptm analysis\n"); ptm_uninitialize_local(local_handle); } diff --git a/src/USER-REACTION/fix_bond_react.cpp b/src/USER-REACTION/fix_bond_react.cpp index 9f9a1ce00d..814f8a0fcf 100644 --- a/src/USER-REACTION/fix_bond_react.cpp +++ b/src/USER-REACTION/fix_bond_react.cpp @@ -201,7 +201,7 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) : memory->create(seed,nreacts,"bond/react:seed"); memory->create(limit_duration,nreacts,"bond/react:limit_duration"); memory->create(stabilize_steps_flag,nreacts,"bond/react:stabilize_steps_flag"); - memory->create(update_edges_flag,nreacts,"bond/react:update_edges_flag"); + memory->create(custom_charges_fragid,nreacts,"bond/react:custom_charges_fragid"); memory->create(constraints,1,MAXCONARGS,"bond/react:constraints"); memory->create(var_flag,NUMVARVALS,nreacts,"bond/react:var_flag"); memory->create(var_id,NUMVARVALS,nreacts,"bond/react:var_id"); @@ -221,7 +221,7 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) : seed[i] = 12345; max_rxn[i] = INT_MAX; stabilize_steps_flag[i] = 0; - update_edges_flag[i] = 0; + custom_charges_fragid[i] = -1; // set default limit duration to 60 timesteps limit_duration[i] = 60; reaction_count[i] = 0; @@ -367,13 +367,15 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) : limit_duration[rxn] = utils::numeric(FLERR,arg[iarg+1],false,lmp); stabilize_steps_flag[rxn] = 1; iarg += 2; - } else if (strcmp(arg[iarg],"update_edges") == 0) { + } else if (strcmp(arg[iarg],"custom_charges") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix bond/react command: " - "'update_edges' has too few arguments"); - if (strcmp(arg[iarg+1],"none") == 0) update_edges_flag[rxn] = 0; - else if (strcmp(arg[iarg+1],"charges") == 0) update_edges_flag[rxn] = 1; - else if (strcmp(arg[iarg+1],"custom") == 0) update_edges_flag[rxn] = 2; - else error->all(FLERR,"Illegal value for 'update_edges' keyword'"); + "'custom_charges' has too few arguments"); + if (strcmp(arg[iarg+1],"no") == 0) custom_charges_fragid[rxn] = -1; //default + else { + custom_charges_fragid[rxn] = atom->molecules[unreacted_mol[rxn]]->findfragment(arg[iarg+1]); + if (custom_charges_fragid[rxn] < 0) error->one(FLERR,"Bond/react: Molecule fragment for " + "'custom_charges' keyword does not exist"); + } iarg += 2; } else error->all(FLERR,"Illegal fix bond/react command: unknown keyword"); } @@ -389,15 +391,14 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) : memory->create(reverse_equiv,max_natoms,2,nreacts,"bond/react:reverse_equiv"); memory->create(edge,max_natoms,nreacts,"bond/react:edge"); memory->create(landlocked_atoms,max_natoms,nreacts,"bond/react:landlocked_atoms"); - memory->create(custom_edges,max_natoms,nreacts,"bond/react:custom_edges"); + memory->create(custom_charges,max_natoms,nreacts,"bond/react:custom_charges"); memory->create(delete_atoms,max_natoms,nreacts,"bond/react:delete_atoms"); memory->create(chiral_atoms,max_natoms,6,nreacts,"bond/react:chiral_atoms"); for (int j = 0; j < nreacts; j++) for (int i = 0; i < max_natoms; i++) { edge[i][j] = 0; - if (update_edges_flag[j] == 1) custom_edges[i][j] = 1; - else custom_edges[i][j] = 0; + custom_charges[i][j] = 1; // update all partial charges by default delete_atoms[i][j] = 0; for (int k = 0; k < 6; k++) { chiral_atoms[i][k][j] = 0; @@ -419,6 +420,7 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) : iatomtype[i] = onemol->type[ibonding[i]-1]; jatomtype[i] = onemol->type[jbonding[i]-1]; find_landlocked_atoms(i); + if (custom_charges_fragid[i] >= 0) CustomCharges(custom_charges_fragid[i],i); } // initialize Marsaglia RNG with processor-unique seed (Arrhenius prob) @@ -436,7 +438,7 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) : } delete [] files; - if (atom->molecular != Atom::ATOMIC) + if (atom->molecular != Atom::MOLECULAR) error->all(FLERR,"Bond/react: Cannot use fix bond/react with non-molecular systems"); // check if bonding atoms are 1-2, 1-3, or 1-4 bonded neighbors @@ -528,7 +530,7 @@ FixBondReact::~FixBondReact() memory->destroy(equivalences); memory->destroy(reverse_equiv); memory->destroy(landlocked_atoms); - memory->destroy(custom_edges); + memory->destroy(custom_charges); memory->destroy(delete_atoms); memory->destroy(chiral_atoms); @@ -545,7 +547,7 @@ FixBondReact::~FixBondReact() memory->destroy(var_flag); memory->destroy(var_id); memory->destroy(stabilize_steps_flag); - memory->destroy(update_edges_flag); + memory->destroy(custom_charges_fragid); memory->destroy(iatomtype); memory->destroy(jatomtype); @@ -2641,11 +2643,11 @@ void FixBondReact::update_everything() twomol = atom->molecules[reacted_mol[rxnID]]; for (int j = 0; j < twomol->natoms; j++) { int jj = equivalences[j][1][rxnID]-1; - if ((landlocked_atoms[j][rxnID] == 1 || custom_edges[jj][rxnID] == 1) && - atom->map(update_mega_glove[jj+1][i]) >= 0 && + if (atom->map(update_mega_glove[jj+1][i]) >= 0 && atom->map(update_mega_glove[jj+1][i]) < nlocal) { - type[atom->map(update_mega_glove[jj+1][i])] = twomol->type[j]; - if (twomol->qflag && atom->q_flag) { + if (landlocked_atoms[j][rxnID] == 1) + type[atom->map(update_mega_glove[jj+1][i])] = twomol->type[j]; + if (twomol->qflag && atom->q_flag && custom_charges[jj][rxnID] == 1) { double *q = atom->q; q[atom->map(update_mega_glove[jj+1][i])] = twomol->q[j]; } @@ -3155,7 +3157,6 @@ void FixBondReact::read(int myrxn) error->one(FLERR,"Bond/react: Number of equivalences in map file must " "equal number of atoms in reaction templates"); } - else if (strstr(line,"customIDs")) sscanf(line,"%d",&ncustom); else if (strstr(line,"deleteIDs")) sscanf(line,"%d",&ndelete); else if (strstr(line,"chiralIDs")) sscanf(line,"%d",&nchiral); else if (strstr(line,"constraints")) { @@ -3171,7 +3172,7 @@ void FixBondReact::read(int myrxn) // loop over sections of superimpose file - int equivflag = 0, bondflag = 0, customedgesflag = 0; + int equivflag = 0, bondflag = 0; while (strlen(keyword)) { if (strcmp(keyword,"BondingIDs") == 0) { bondflag = 1; @@ -3188,9 +3189,6 @@ void FixBondReact::read(int myrxn) } else if (strcmp(keyword,"Equivalences") == 0) { equivflag = 1; Equivalences(line, myrxn); - } else if (strcmp(keyword,"Custom Edges") == 0) { - customedgesflag = 1; - CustomEdges(line, myrxn); } else if (strcmp(keyword,"DeleteIDs") == 0) { DeleteAtoms(line, myrxn); } else if (strcmp(keyword,"ChiralIDs") == 0) { @@ -3206,12 +3204,6 @@ void FixBondReact::read(int myrxn) // error check if (bondflag == 0 || equivflag == 0) error->all(FLERR,"Bond/react: Map file missing BondingIDs or Equivalences section\n"); - - if (update_edges_flag[myrxn] == 2 && customedgesflag == 0) - error->all(FLERR,"Bond/react: Map file must have a Custom Edges section when using 'update_edges custom'\n"); - - if (update_edges_flag[myrxn] != 2 && customedgesflag == 1) - error->all(FLERR,"Bond/react: Specify 'update_edges custom' to include Custom Edges section in map file\n"); } void FixBondReact::EdgeIDs(char *line, int myrxn) @@ -3246,28 +3238,6 @@ void FixBondReact::Equivalences(char *line, int myrxn) } } -void FixBondReact::CustomEdges(char *line, int myrxn) -{ - // 0 for 'none', 1 for 'charges' - - int tmp; - int n = MAX(strlen("none"),strlen("charges")) + 1; - char *edgemode = new char[n]; - for (int i = 0; i < ncustom; i++) { - readline(line); - sscanf(line,"%d %s",&tmp,edgemode); - if (tmp > onemol->natoms) - error->one(FLERR,"Bond/react: Invalid template atom ID in map file"); - if (strcmp(edgemode,"none") == 0) - custom_edges[tmp-1][myrxn] = 0; - else if (strcmp(edgemode,"charges") == 0) - custom_edges[tmp-1][myrxn] = 1; - else - error->one(FLERR,"Bond/react: Illegal value in 'Custom Edges' section of map file"); - } - delete [] edgemode; -} - void FixBondReact::DeleteAtoms(char *line, int myrxn) { int tmp; @@ -3280,6 +3250,15 @@ void FixBondReact::DeleteAtoms(char *line, int myrxn) } } +void FixBondReact::CustomCharges(int ifragment, int myrxn) +{ + for (int i = 0; i < onemol->natoms; i++) + if (onemol->fragmentmask[ifragment][i]) + custom_charges[i][myrxn] = 1; + else + custom_charges[i][myrxn] = 0; +} + void FixBondReact::ChiralCenters(char *line, int myrxn) { int tmp; diff --git a/src/USER-REACTION/fix_bond_react.h b/src/USER-REACTION/fix_bond_react.h index 61a1bd4213..895a63b7ae 100644 --- a/src/USER-REACTION/fix_bond_react.h +++ b/src/USER-REACTION/fix_bond_react.h @@ -64,7 +64,7 @@ class FixBondReact : public Fix { int reset_mol_ids_flag; int custom_exclude_flag; int *stabilize_steps_flag; - int *update_edges_flag; + int *custom_charges_fragid; int nconstraints; int narrhenius; double **constraints; @@ -113,7 +113,7 @@ class FixBondReact : public Fix { int *ibonding,*jbonding; int *closeneigh; // indicates if bonding atoms of a rxn are 1-2, 1-3, or 1-4 neighbors - int nedge,nequivalent,ncustom,ndelete,nchiral,nconstr; // # edge, equivalent, custom atoms in mapping file + int nedge,nequivalent,ndelete,nchiral,nconstr; // # edge, equivalent atoms in mapping file int attempted_rxn; // there was an attempt! int *local_rxn_count; int *ghostly_rxn_count; @@ -127,7 +127,7 @@ class FixBondReact : public Fix { int ***equivalences; // relation between pre- and post-reacted templates int ***reverse_equiv; // re-ordered equivalences int **landlocked_atoms; // all atoms at least three bonds away from edge atoms - int **custom_edges; // atoms in molecule templates with incorrect valences + int **custom_charges; // atoms whose charge should be updated int **delete_atoms; // atoms in pre-reacted templates to delete int ***chiral_atoms; // pre-react chiral atoms. 1) flag 2) orientation 3-4) ordered atom types @@ -151,8 +151,8 @@ class FixBondReact : public Fix { void read(int); void EdgeIDs(char *, int); void Equivalences(char *, int); - void CustomEdges(char *, int); void DeleteAtoms(char *, int); + void CustomCharges(int, int); void ChiralCenters(char *, int); void Constraints(char *, int); void readID(char *, int, int, int); diff --git a/src/USER-REACTION/superpose3d.h b/src/USER-REACTION/superpose3d.h index e61e8e0c93..b0b290ddad 100644 --- a/src/USER-REACTION/superpose3d.h +++ b/src/USER-REACTION/superpose3d.h @@ -22,10 +22,10 @@ /// @author Andrew Jewett /// @license MIT -#ifndef _SUPERPOSE3D_H -#define _SUPERPOSE3D_H +#ifndef LMP_SUPERPOSE3D_H +#define LMP_SUPERPOSE3D_H -#include "math_eigen.h" //functions to calculate eigenvalues and eigenvectors +#include "math_eigen_impl.h" //functions to calculate eigenvalues and eigenvectors // ----------------------------------------------------------- // ------------------------ INTERFACE ------------------------ @@ -144,11 +144,6 @@ Superpose(ConstArrayOfCoords aaXf, // coords for the "frozen" object ConstArrayOfCoords aaXm, // coords for the "mobile" object bool allow_rescale) // rescale mobile object? (c!=1?) { - assert(aaXf && aaXm); - assert(aaXf_shifted && aaXm_shifted); - assert(aWeights); - assert(R && T); - // Find the center of mass of each object: Scalar aCenter_f[3] = {0.0, 0.0, 0.0}; Scalar aCenter_m[3] = {0.0, 0.0, 0.0}; @@ -161,7 +156,9 @@ Superpose(ConstArrayOfCoords aaXf, // coords for the "frozen" object } sum_weights += weight; } - assert(sum_weights != 0.0); + + //assert(sum_weights != 0.0); + for (int d=0; d < 3; d++) { aCenter_f[d] /= sum_weights; aCenter_m[d] /= sum_weights; @@ -425,7 +422,9 @@ Superpose3D(const Superpose3D& source) { Init(); Alloc(source.N); - assert(N == source.N); + + //assert(N == source.N); + for (int i = 0; i < N; i++) { std::copy(source.aaXf_shifted[i], source.aaXf_shifted[i] + 3, @@ -463,4 +462,4 @@ operator = (Superpose3D source) { } -#endif //#ifndef _SUPERPOSE3D_H +#endif //#ifndef LMP_SUPERPOSE3D_H diff --git a/src/atom.cpp b/src/atom.cpp index 21e6c87c7b..fbf7a067a9 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -31,6 +31,8 @@ #include "update.h" #include "variable.h" +#include "library.h" + #include #include @@ -2502,7 +2504,12 @@ length of the data area, and a short description. - 1 - 1 if the particle is a body particle, 0 if not +*See also* + :cpp:func:`lammps_extract_atom` + \endverbatim + * + * \sa extract_datatype * * \param name string with the keyword of the desired property. Typically the name of the pointer variable returned @@ -2512,6 +2519,8 @@ void *Atom::extract(const char *name) { // -------------------------------------------------------------------- // 4th customization section: customize by adding new variable name + // please see the following function to set the type of the data + // so that programs can detect it dynamically at run time. /* NOTE: this array is only of length ntypes+1 */ if (strcmp(name,"mass") == 0) return (void *) mass; @@ -2580,6 +2589,89 @@ void *Atom::extract(const char *name) return nullptr; } + +/** Provide data type info about internal data of the Atom class + * +\verbatim embed:rst + +.. versionadded:: 18Sep2020 + +\endverbatim + * + * \sa extract + * + * \param name string with the keyword of the desired property. + * \return data type constant for desired property or -1 */ + +int Atom::extract_datatype(const char *name) +{ + // -------------------------------------------------------------------- + // 5th customization section: customize by adding new variable name + + if (strcmp(name,"mass") == 0) return LAMMPS_DOUBLE; + + if (strcmp(name,"id") == 0) return LAMMPS_TAGINT; + if (strcmp(name,"type") == 0) return LAMMPS_INT; + if (strcmp(name,"mask") == 0) return LAMMPS_INT; + if (strcmp(name,"image") == 0) return LAMMPS_TAGINT; + if (strcmp(name,"x") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"v") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"f") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"molecule") == 0) return LAMMPS_TAGINT; + if (strcmp(name,"q") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"mu") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"omega") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"angmom") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"torque") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"radius") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"rmass") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"ellipsoid") == 0) return LAMMPS_INT; + if (strcmp(name,"line") == 0) return LAMMPS_INT; + if (strcmp(name,"tri") == 0) return LAMMPS_INT; + if (strcmp(name,"body") == 0) return LAMMPS_INT; + + if (strcmp(name,"vfrac") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"s0") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"x0") == 0) return LAMMPS_DOUBLE_2D; + + if (strcmp(name,"spin") == 0) return LAMMPS_INT; + if (strcmp(name,"eradius") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"ervel") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"erforce") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"ervelforce") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"cs") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"csforce") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"vforce") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name,"etag") == 0) return LAMMPS_INT; + + if (strcmp(name,"rho") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"drho") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"esph") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"desph") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"cv") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"vest") == 0) return LAMMPS_DOUBLE_2D; + + // USER-MESONT package + if (strcmp(name,"length") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"buckling") == 0) return LAMMPS_INT; + if (strcmp(name,"bond_nt") == 0) return LAMMPS_TAGINT_2D; + + if (strcmp(name, "contact_radius") == 0) return LAMMPS_DOUBLE; + if (strcmp(name, "smd_data_9") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name, "smd_stress") == 0) return LAMMPS_DOUBLE_2D; + if (strcmp(name, "eff_plastic_strain") == 0) return LAMMPS_DOUBLE; + if (strcmp(name, "eff_plastic_strain_rate") == 0) return LAMMPS_DOUBLE; + if (strcmp(name, "damage") == 0) return LAMMPS_DOUBLE; + + if (strcmp(name,"dpdTheta") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"edpd_temp") == 0) return LAMMPS_DOUBLE; + + // end of customization section + // -------------------------------------------------------------------- + + return -1; +} + /* ---------------------------------------------------------------------- return # of bytes of allocated memory call to avec tallies per-atom vectors diff --git a/src/atom.h b/src/atom.h index 10631d2435..bc69d3b27a 100644 --- a/src/atom.h +++ b/src/atom.h @@ -335,6 +335,7 @@ class Atom : protected Pointers { virtual void sync_modify(ExecutionSpace, unsigned int, unsigned int) {} void *extract(const char *); + int extract_datatype(const char *); inline int* get_map_array() {return map_array;}; inline int get_map_size() {return map_tag_max+1;}; diff --git a/src/atom_vec_tri.cpp b/src/atom_vec_tri.cpp index f5b6ff4245..138a9966a8 100644 --- a/src/atom_vec_tri.cpp +++ b/src/atom_vec_tri.cpp @@ -19,6 +19,7 @@ #include "fix.h" #include "math_const.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "modify.h" @@ -555,7 +556,7 @@ void AtomVecTri::data_atom_bonus(int m, char **values) tensor[0][2] = tensor[2][0] = inertia[4]; tensor[0][1] = tensor[1][0] = inertia[5]; - int ierror = MathExtra::jacobi(tensor,bonus[nlocal_bonus].inertia,evectors); + int ierror = MathEigen::jacobi3(tensor,bonus[nlocal_bonus].inertia,evectors); if (ierror) error->one(FLERR,"Insufficient Jacobi rotations for triangle"); double ex_space[3],ey_space[3],ez_space[3]; diff --git a/src/compute_omega_chunk.cpp b/src/compute_omega_chunk.cpp index 40f13f7483..b88db4be92 100644 --- a/src/compute_omega_chunk.cpp +++ b/src/compute_omega_chunk.cpp @@ -20,6 +20,7 @@ #include "compute_chunk_atom.h" #include "domain.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "error.h" @@ -250,10 +251,10 @@ void ComputeOmegaChunk::compute_array() // handle each (nearly) singular I matrix // due to 2-atom chunk or linear molecule - // use jacobi() and angmom_to_omega() to calculate valid omega + // use jacobi3() and angmom_to_omega() to calculate valid omega } else { - int ierror = MathExtra::jacobi(ione,idiag,evectors); + int ierror = MathEigen::jacobi3(ione,idiag,evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations for omega/chunk"); diff --git a/src/compute_pressure.cpp b/src/compute_pressure.cpp index ae1bb4747d..f626718596 100644 --- a/src/compute_pressure.cpp +++ b/src/compute_pressure.cpp @@ -189,10 +189,12 @@ void ComputePressure::init() if (pairhybridflag && force->pair) nvirial++; if (pairflag && force->pair) nvirial++; - if (bondflag && atom->molecular && force->bond) nvirial++; - if (angleflag && atom->molecular && force->angle) nvirial++; - if (dihedralflag && atom->molecular && force->dihedral) nvirial++; - if (improperflag && atom->molecular && force->improper) nvirial++; + if (atom->molecular != Atom::ATOMIC) { + if (bondflag && force->bond) nvirial++; + if (angleflag && force->angle) nvirial++; + if (dihedralflag && force->dihedral) nvirial++; + if (improperflag && force->improper) nvirial++; + } if (fixflag) for (int i = 0; i < modify->nfix; i++) if (modify->fix[i]->thermo_virial) nvirial++; diff --git a/src/domain.cpp b/src/domain.cpp index b725495828..b5d6675a3f 100644 --- a/src/domain.cpp +++ b/src/domain.cpp @@ -727,7 +727,7 @@ void Domain::image_check() // if running verlet/split, don't check on KSpace partition since // it has no ghost atoms and thus bond partners won't exist - if (!atom->molecular) return; + if (atom->molecular == Atom::ATOMIC) return; if (!xperiodic && !yperiodic && (dimension == 2 || !zperiodic)) return; if (strncmp(update->integrate_style,"verlet/split",12) == 0 && universe->iworld != 0) return; @@ -837,7 +837,7 @@ void Domain::box_too_small_check() // if running verlet/split, don't check on KSpace partition since // it has no ghost atoms and thus bond partners won't exist - if (!atom->molecular) return; + if (atom->molecular == Atom::ATOMIC) return; if (!xperiodic && !yperiodic && (dimension == 2 || !zperiodic)) return; if (strncmp(update->integrate_style,"verlet/split",12) == 0 && universe->iworld != 0) return; diff --git a/src/file_writer.h b/src/file_writer.h index 766ccc85e7..8597ab570d 100644 --- a/src/file_writer.h +++ b/src/file_writer.h @@ -27,7 +27,7 @@ class FileWriter { public: FileWriter() = default; virtual ~FileWriter() = default; - virtual void open(const std::string & path) = 0; + virtual void open(const std::string &path) = 0; virtual void close() = 0; virtual void flush() = 0; virtual size_t write(const void * buffer, size_t length) = 0; @@ -37,7 +37,7 @@ public: class FileWriterException : public std::exception { std::string message; public: - FileWriterException(const std::string & msg) : message(msg) { + FileWriterException(const std::string &msg) : message(msg) { } ~FileWriterException() throw() { diff --git a/src/finish.cpp b/src/finish.cpp index 3f057a00b8..7525f5e632 100644 --- a/src/finish.cpp +++ b/src/finish.cpp @@ -332,7 +332,7 @@ void Finish::end(int flag) mpi_timings("Pair",timer,Timer::PAIR, world,nprocs, nthreads,me,time_loop,screen,logfile); - if (atom->molecular) + if (atom->molecular != Atom::ATOMIC) mpi_timings("Bond",timer,Timer::BOND,world,nprocs, nthreads,me,time_loop,screen,logfile); @@ -391,7 +391,7 @@ void Finish::end(int flag) utils::logmesg(lmp,fmt::format(thr_fmt,me,thr_total,thr_total/time_loop*100.0)); omp_times(fixomp,"Pair",Timer::PAIR,nthreads,screen,logfile); - if (atom->molecular) + if (atom->molecular != Atom::ATOMIC) omp_times(fixomp,"Bond",Timer::BOND,nthreads,screen,logfile); if (force->kspace) omp_times(fixomp,"Kspace",Timer::KSPACE,nthreads,screen,logfile); @@ -585,7 +585,7 @@ void Finish::end(int flag) mesg += fmt::format("Total # of neighbors = {:.8g}\n",nall); if (atom->natoms > 0) mesg += fmt::format("Ave neighs/atom = {:.8}\n",nall/atom->natoms); - if (atom->molecular && atom->natoms > 0) + if ((atom->molecular != Atom::ATOMIC) && (atom->natoms > 0)) mesg += fmt::format("Ave special neighs/atom = {:.8}\n", nspec_all/atom->natoms); mesg += fmt::format("Neighbor list builds = {}\n",neighbor->ncalls); diff --git a/src/fmt/core.h b/src/fmt/core.h index f9155000ec..6d87ab290a 100644 --- a/src/fmt/core.h +++ b/src/fmt/core.h @@ -18,7 +18,7 @@ #include // The fmt library version in the form major * 10000 + minor * 100 + patch. -#define FMT_VERSION 70002 +#define FMT_VERSION 70003 #ifdef __clang__ # define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) @@ -177,6 +177,12 @@ # endif #endif +// LAMMPS customization +// use 'v7_lmp' namespace instead of 'v7' so that our +// bundled copy does not collide with linking other code +// using system wide installations which may be using +// a different version. + #ifndef FMT_BEGIN_NAMESPACE # if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \ FMT_MSC_VER >= 1900 @@ -299,7 +305,7 @@ template struct std_string_view {}; #ifdef FMT_USE_INT128 // Do nothing. -#elif defined(__SIZEOF_INT128__) && !FMT_NVCC +#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && !(FMT_CLANG_VERSION && FMT_MSC_VER) # define FMT_USE_INT128 1 using int128_t = __int128_t; using uint128_t = __uint128_t; @@ -489,6 +495,8 @@ constexpr basic_string_view to_string_view(const S& s) { return s; } +// LAMMPS customization using 'v7_lmp' instead of 'v7' + namespace detail { void to_string_view(...); using fmt::v7_lmp::to_string_view; @@ -1713,7 +1721,7 @@ template class basic_format_args { } template int get_id(basic_string_view name) const { - if (!has_named_args()) return {}; + if (!has_named_args()) return -1; const auto& named_args = (is_packed() ? values_[-1] : args_[-1].value_).named_args; for (size_t i = 0; i < named_args.size; ++i) { diff --git a/src/fmt/format.h b/src/fmt/format.h index 5427042b4e..a4911b9fdb 100644 --- a/src/fmt/format.h +++ b/src/fmt/format.h @@ -69,6 +69,12 @@ # define FMT_NOINLINE #endif +// LAMMPS customizations: +// 1) Intel compilers on MacOS have __clang__ defined +// but fail to recognize [[clang::fallthrough]] +// 2) Intel compilers on Linux identify as GCC compatible +// but fail to recognize [[gnu::fallthrough]] + #if __cplusplus == 201103L || __cplusplus == 201402L # if defined(__clang__) && !defined(__INTEL_COMPILER) # define FMT_FALLTHROUGH [[clang::fallthrough]] @@ -724,13 +730,18 @@ class FMT_API format_error : public std::runtime_error { namespace detail { +template +using is_signed = + std::integral_constant::is_signed || + std::is_same::value>; + // Returns true if value is negative, false otherwise. // Same as `value < 0` but doesn't produce warnings if T is an unsigned type. -template ::is_signed)> +template ::value)> FMT_CONSTEXPR bool is_negative(T value) { return value < 0; } -template ::is_signed)> +template ::value)> FMT_CONSTEXPR bool is_negative(T) { return false; } @@ -745,9 +756,9 @@ FMT_CONSTEXPR bool is_supported_floating_point(T) { // Smallest of uint32_t, uint64_t, uint128_t that is large enough to // represent all values of T. template -using uint32_or_64_or_128_t = conditional_t< - num_bits() <= 32, uint32_t, - conditional_t() <= 64, uint64_t, uint128_t>>; +using uint32_or_64_or_128_t = + conditional_t() <= 32, uint32_t, + conditional_t() <= 64, uint64_t, uint128_t>>; // Static data is placed in this class template for the header-only config. template struct FMT_EXTERN_TEMPLATE_API basic_data { @@ -1593,7 +1604,11 @@ template struct int_writer { make_checked(p, s.size())); } if (prefix_size != 0) p[-1] = static_cast('-'); - write(out, basic_string_view(buffer.data(), buffer.size()), specs); + using iterator = remove_reference_t; + auto data = buffer.data(); + out = write_padded(out, specs, size, size, [=](iterator it) { + return copy_str(data, data + size, it); + }); } void on_chr() { *out++ = static_cast(abs_value); } diff --git a/src/group.cpp b/src/group.cpp index 6b9121f506..7717323b52 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -23,6 +23,7 @@ #include "force.h" #include "input.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "modify.h" #include "output.h" @@ -1727,11 +1728,11 @@ void Group::omega(double *angmom, double inertia[3][3], double *w) // handle (nearly) singular I matrix // typically due to 2-atom group or linear molecule - // use jacobi() and angmom_to_omega() to calculate valid omega + // use jacobi3() and angmom_to_omega() to calculate valid omega // less exact answer than matrix inversion, due to iterative Jacobi method } else { - int ierror = MathExtra::jacobi(inertia,idiag,evectors); + int ierror = MathEigen::jacobi3(inertia, idiag, evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations for group::omega"); diff --git a/src/info.cpp b/src/info.cpp index 890919fdbf..dd913271a1 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -267,7 +267,7 @@ void Info::command(int narg, char **arg) if (flags & CONFIG) { fmt::print(out,"\nLAMMPS version: {} / {}\n", - universe->version, universe->num_ver); + lmp->version, lmp->num_ver); if (lmp->has_git_info) fmt::print(out,"Git info: {} / {} / {}\n", diff --git a/src/info.h b/src/info.h index ae61600b68..e14a2be8db 100644 --- a/src/info.h +++ b/src/info.h @@ -35,8 +35,8 @@ class Info : protected Pointers { bool is_defined(const char *, const char *); bool is_available(const char *, const char *); - bool has_style(const std::string & category, const std::string & name); - std::vector get_available_styles(const std::string & category); + bool has_style(const std::string &category, const std::string &name); + std::vector get_available_styles(const std::string &category); static bool has_gzip_support(); static bool has_png_support(); diff --git a/src/lammps.cpp b/src/lammps.cpp index 1d655f6fc4..afe490c0a7 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -114,6 +114,9 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : error = new Error(this); universe = new Universe(this,communicator); + version = (const char *) LAMMPS_VERSION; + num_ver = utils::date2num(version); + clientserver = 0; cslib = nullptr; cscomm = 0; @@ -460,7 +463,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : } if ((universe->me == 0) && !helpflag) - utils::logmesg(this,fmt::format("LAMMPS ({})\n",universe->version)); + utils::logmesg(this,fmt::format("LAMMPS ({})\n",version)); // universe is one or more worlds, as setup by partition switch // split universe communicator into separate world communicators @@ -538,15 +541,15 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : if ((universe->me == 0) && (!helpflag)) { const char fmt[] = "LAMMPS ({})\nRunning on {} partitions of processors\n"; if (universe->uscreen) - fmt::print(universe->uscreen,fmt,universe->version,universe->nworlds); + fmt::print(universe->uscreen,fmt,version,universe->nworlds); if (universe->ulogfile) - fmt::print(universe->ulogfile,fmt,universe->version,universe->nworlds); + fmt::print(universe->ulogfile,fmt,version,universe->nworlds); } if ((me == 0) && (!helpflag)) utils::logmesg(this,fmt::format("LAMMPS ({})\nProcessor partition = {}\n", - universe->version, universe->iworld)); + version, universe->iworld)); } // check consistency of datatype settings in lmptype.h diff --git a/src/lammps.h b/src/lammps.h index e1fcc0e319..0d9442ffb9 100644 --- a/src/lammps.h +++ b/src/lammps.h @@ -38,6 +38,12 @@ class LAMMPS { class Output *output; // thermo/dump/restart class Timer *timer; // CPU timing info + const char *version; // LAMMPS version string = date + int num_ver; // numeric version id derived from *version* + // that is constructed so that will be greater + // for newer versions in numeric or string + // value comparisons + MPI_Comm world; // MPI communicator FILE *infile; // infile FILE *screen; // screen output diff --git a/src/library.cpp b/src/library.cpp index 7ea8855e98..da9ece326e 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -48,6 +48,17 @@ using namespace LAMMPS_NS; +// for printing the non-null pointer argument warning only once + +static int ptr_argument_flag = 1; +static void ptr_argument_warning() +{ + if (!ptr_argument_flag) return; + fprintf(stderr,"Using a 'void **' argument to return the LAMMPS handle " + "is deprecated. Please use the return value instead.\n"); + ptr_argument_flag = 0; +} + // ---------------------------------------------------------------------- // utility macros // ---------------------------------------------------------------------- @@ -73,7 +84,7 @@ using namespace LAMMPS_NS; try #define END_CAPTURE \ - catch(LAMMPSAbortException & ae) { \ + catch(LAMMPSAbortException &ae) { \ int nprocs = 0; \ MPI_Comm_size(ae.universe, &nprocs ); \ \ @@ -82,7 +93,7 @@ using namespace LAMMPS_NS; } else { \ error->set_last_error(ae.message, ERROR_NORMAL); \ } \ - } catch(LAMMPSException & e) { \ + } catch(LAMMPSException &e) { \ error->set_last_error(e.message, ERROR_NORMAL); \ } #else @@ -111,13 +122,17 @@ will be called during creation of the LAMMPS class instance. If for some reason the creation or initialization of the LAMMPS instance fails a null pointer is returned. -.. versionchanged:: 15Sep2020 +.. versionchanged:: 18Sep2020 This function now has the pointer to the created LAMMPS class instance as return value. For backward compatibility it is still possible to provide the address of a pointer variable as final - argument *ptr*\ . This use is deprecated and may be removed in - the future. The *ptr* argument may be ``NULL`` and is then ignored. + argument *ptr*\ . + +.. deprecated:: 18Sep2020 + + The *ptr* argument will be removed in a future release of LAMMPS. + It should be set to ``NULL`` instead. .. note:: @@ -127,6 +142,9 @@ fails a null pointer is returned. ``#include "library.h"``. In that case, you must use the :cpp:func:`lammps_open_no_mpi` function. +*See also* + :cpp:func:`lammps_open_no_mpi`, :cpp:func:`lammps_open_fortran` + \endverbatim * * \param argc number of command line arguments @@ -140,6 +158,7 @@ void *lammps_open(int argc, char **argv, MPI_Comm comm, void **ptr) { LAMMPS *lmp = nullptr; lammps_mpi_init(); + if (ptr) ptr_argument_warning(); #ifdef LAMMPS_EXCEPTIONS try @@ -147,7 +166,7 @@ void *lammps_open(int argc, char **argv, MPI_Comm comm, void **ptr) lmp = new LAMMPS(argc, argv, comm); if (ptr) *ptr = (void *) lmp; } - catch(LAMMPSException & e) { + catch(LAMMPSException &e) { fmt::print(stderr, "LAMMPS Exception: {}", e.message); *ptr = nullptr; } @@ -177,13 +196,21 @@ be compatible with that of the calling code. If for some reason the creation or initialization of the LAMMPS instance fails a null pointer is returned. -.. versionchanged:: 15Sep2020 +.. versionchanged:: 18Sep2020 This function now has the pointer to the created LAMMPS class instance as return value. For backward compatibility it is still possible to provide the address of a pointer variable as final - argument *ptr*\ . This use is deprecated and may be removed in - the future. The *ptr* argument may be ``NULL`` and is then ignored. + argument *ptr*\ . + +.. deprecated:: 18Sep2020 + + The *ptr* argument will be removed in a future release of LAMMPS. + It should be set to ``NULL`` instead. + + +*See also* + :cpp:func:`lammps_open`, :cpp:func:`lammps_open_fortran` \endverbatim * @@ -214,7 +241,10 @@ communicator with ``MPI_Comm_f2c()`` and then calls If for some reason the creation or initialization of the LAMMPS instance fails a null pointer is returned. -.. versionadded:: 15Sep2020 +.. versionadded:: 18Sep2020 + +*See also* + :cpp:func:`lammps_open_fortran`, :cpp:func:`lammps_open_no_mpi` \endverbatim * @@ -263,7 +293,7 @@ The MPI standard requires that any MPI application must call calls. This function checks, whether MPI is already initialized and calls ``MPI_Init()`` in case it is not. -.. versionadded:: 15Sep2020 +.. versionadded:: 18Sep2020 \endverbatim */ @@ -295,7 +325,7 @@ before exiting the program to wait until all (parallel) tasks are completed and then MPI is cleanly shut down. After this function no more MPI calls may be made. -.. versionadded:: 15Sep2020 +.. versionadded:: 18Sep2020 \endverbatim */ @@ -529,7 +559,7 @@ growing with every new LAMMPS release. int lammps_version(void *handle) { LAMMPS *lmp = (LAMMPS *) handle; - return atoi(lmp->universe->num_ver); + return lmp->num_ver; } /* ---------------------------------------------------------------------- */ @@ -550,7 +580,7 @@ third number is the maximum amount of RAM (not swap) used by the process so far. If any of the two latter parameters is not supported by the operating system it will be set to zero. -.. versionadded:: 15Sep2020 +.. versionadded:: 18Sep2020 \endverbatim * @@ -579,10 +609,12 @@ to the C language representation use ``MPI_Comm_f2c()``. If LAMMPS was compiled with MPI_STUBS, this function returns -1. -.. versionadded:: 15Sep2020 +.. versionadded:: 18Sep2020 + +*See also* + :cpp:func:`lammps_open_fortran` \endverbatim - * \sa lammps_open_fortran * * \param handle pointer to a previously created LAMMPS instance * \return Fortran representation of the LAMMPS world communicator */ @@ -617,6 +649,13 @@ size and dereference it. The size of that integer (in bytes) can be queried by calling :cpp:func:`lammps_extract_setting` to return the size of a ``bigint`` integer. +.. versionchanged:: 18Sep2020 + + The type of the return value was changed from ``int`` to ``double`` + to accommodate reporting atom counts for larger systems that would + overflow a 32-bit int without having to depend on a 64-bit bit + integer type definition. + \endverbatim * * \param handle pointer to a previously created LAMMPS instance @@ -640,7 +679,7 @@ double lammps_get_natoms(void *handle) This function returns the current value of a :doc:`thermo keyword `. Unlike :cpp:func:`lammps_extract_global` it does not give access to the storage of the desired data but returns its value as -a double, so it can also return information that is computed on-the-fly. +a ``double``, so it can also return information that is computed on-the-fly. \endverbatim * @@ -789,7 +828,7 @@ void lammps_reset_box(void *handle, double *boxlo, double *boxhi, This function will retrieve or compute global properties. In contrast to :cpp:func:`lammps_get_thermo` this function returns an ``int``. The following keywords are currently supported. If a keyword is not -recognized, the function returns -1. Please also see :cpp:func:`lammps_extract_global`. +recognized, the function returns -1. .. list-table:: :header-rows: 1 @@ -833,6 +872,9 @@ recognized, the function returns -1. Please also see :cpp:func:`lammps_extract_ * - rmass_flag - 1 if the atom style includes per-atom masses, 0 if there are per-type masses. See :doc:`atom_style`. +*See also* + :cpp:func:`lammps_extract_global` + \endverbatim * * \param handle pointer to a previously created LAMMPS instance @@ -875,7 +917,7 @@ int lammps_extract_setting(void *handle, const char *keyword) This function returns a pointer to the location of some global property stored in one of the constituent classes of a LAMMPS instance. The returned pointer is cast to ``void *`` and needs to be cast to a pointer -of the type that the entity represents. The pointers returned by this +of the type that the entity represents. The pointers returned by this function are generally persistent; therefore it is not necessary to call the function again, unless a :doc:`clear` command is issued which wipes out and recreates the contents of the :cpp:class:`LAMMPS @@ -1185,7 +1227,7 @@ of data type that the entity represents. A table with supported keywords is included in the documentation of the :cpp:func:`Atom::extract() ` function. -.. note:: +.. warning:: The pointers returned by this function are generally not persistent since per-atom data may be re-distributed, re-allocated, and @@ -1206,6 +1248,117 @@ void *lammps_extract_atom(void *handle, const char *name) /* ---------------------------------------------------------------------- */ +/** Get data type of internal global LAMMPS variables or arrays. + * +\verbatim embed:rst + +This function returns an integer that encodes the data type of the global +property with the specified name. See :cpp:enum:`_LMP_DATATYPE_CONST` for valid +values. Callers of :cpp:func:`lammps_extract_global` can use this information +to then decide how to cast the (void*) pointer and access the data. + +.. versionadded:: 18Sep2020 + +\endverbatim + * + * \param handle pointer to a previously created LAMMPS instance + * \param name string with the name of the extracted property + * \return integer constant encoding the data type of the property + * or -1 if not found. */ + +int lammps_extract_global_datatype(void *handle, const char *name) +{ + LAMMPS *lmp = (LAMMPS *) handle; + + if (strcmp(name,"units") == 0) return LAMMPS_STRING; + if (strcmp(name,"dt") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"ntimestep") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"boxlo") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"boxhi") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"boxxlo") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"boxxhi") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"boxylo") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"boxyhi") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"boxzlo") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"boxzhi") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"periodicity") == 0) return LAMMPS_INT; + if (strcmp(name,"triclinic") == 0) return LAMMPS_INT; + if (strcmp(name,"xy") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"xz") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"yz") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"natoms") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"nbonds") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"nangles") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"ndihedrals") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"nimpropers") == 0) return LAMMPS_BIGINT; + if (strcmp(name,"nlocal") == 0) return LAMMPS_INT; + if (strcmp(name,"nghost") == 0) return LAMMPS_INT; + if (strcmp(name,"nmax") == 0) return LAMMPS_INT; + if (strcmp(name,"ntypes") == 0) return LAMMPS_INT; + + if (strcmp(name,"q_flag") == 0) return LAMMPS_INT; + + // update->atime can be referenced as a pointer + // thermo "timer" data cannot be, since it is computed on request + // lammps_get_thermo() can access all thermo keywords by value + + if (strcmp(name,"atime") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"atimestep") == 0) return LAMMPS_BIGINT; + + // global constants defined by units + + if (strcmp(name,"boltz") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"hplanck") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"mvv2e") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"ftm2v") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"mv2d") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"nktv2p") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"qqr2e") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"qe2f") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"vxmu2f") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"xxt2kmu") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"dielectric") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"qqrd2e") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"e_mass") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"hhmrr2e") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"mvh2r") == 0) return LAMMPS_DOUBLE; + + if (strcmp(name,"angstrom") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"femtosecond") == 0) return LAMMPS_DOUBLE; + if (strcmp(name,"qelectron") == 0) return LAMMPS_DOUBLE; + + return -1; +} + +/* ---------------------------------------------------------------------- */ + +/** Get data type of a LAMMPS per-atom property + * +\verbatim embed:rst + +This function returns an integer that encodes the data type of the per-atom +property with the specified name. See :cpp:enum:`_LMP_DATATYPE_CONST` for valid +values. Callers of :cpp:func:`lammps_extract_atom` can use this information +to then decide how to cast the (void*) pointer and access the data. + +.. versionadded:: 18Sep2020 + +\endverbatim + * + * \param handle pointer to a previously created LAMMPS instance + * \param name string with the name of the extracted property + * \return integer constant encoding the data type of the property + * or -1 if not found. + * */ + +int lammps_extract_atom_datatype(void *handle, const char *name) +{ + LAMMPS *lmp = (LAMMPS *) handle; + return lmp->atom->extract_datatype(name); +} + +/* ---------------------------------------------------------------------- */ + /** Create N atoms from list of coordinates * \verbatim embed:rst @@ -1430,11 +1583,13 @@ lists the available options. - ``int *`` - Number of local data columns -The pointers returned by this function are generally not persistent -since the computed data may be re-distributed, re-allocated, and -re-ordered at every invocation. It is advisable to re-invoke this -function before the data is accessed, or make a copy if the data shall -be used after other LAMMPS commands have been issued. +.. warning:: + + The pointers returned by this function are generally not persistent + since the computed data may be re-distributed, re-allocated, and + re-ordered at every invocation. It is advisable to re-invoke this + function before the data is accessed, or make a copy if the data shall + be used after other LAMMPS commands have been issued. .. note:: @@ -1614,12 +1769,14 @@ The following table lists the available options. - ``int *`` - Number of local data columns -The pointers returned by this function for per-atom or local data are -generally not persistent, since the computed data may be re-distributed, -re-allocated, and re-ordered at every invocation of the fix. It is thus -advisable to re-invoke this function before the data is accessed, or -make a copy, if the data shall be used after other LAMMPS commands have -been issued. +.. warning:: + + The pointers returned by this function for per-atom or local data are + generally not persistent, since the computed data may be re-distributed, + re-allocated, and re-ordered at every invocation of the fix. It is thus + advisable to re-invoke this function before the data is accessed, or + make a copy, if the data shall be used after other LAMMPS commands have + been issued. .. note:: diff --git a/src/library.h b/src/library.h index 4cf2dd6d19..2ddad86baa 100644 --- a/src/library.h +++ b/src/library.h @@ -40,6 +40,20 @@ #include /* for int64_t */ #endif +/** Data type constants for extracting data from atoms, computes and fixes + * + * Must be kept in sync with the equivalent constants in lammps.py */ + +enum _LMP_DATATYPE_CONST { + LAMMPS_INT = 0, /*!< 32-bit integer (array) */ + LAMMPS_INT_2D = 1, /*!< two-dimensional 32-bit integer array */ + LAMMPS_DOUBLE = 2, /*!< 64-bit double (array) */ + LAMMPS_DOUBLE_2D = 3, /*!< two-dimensional 64-bit double array */ + LAMMPS_INT64 = 4, /*!< 64-bit integer (array) */ + LAMMPS_INT64_2D = 5, /*!< two-dimensional 64-bit integer array */ + LAMMPS_STRING = 6 /*!< C-String */ +}; + /** Style constants for extracting data from computes and fixes. * * Must be kept in sync with the equivalent constants in lammps.py */ @@ -113,6 +127,9 @@ int lammps_extract_setting(void *handle, const char *keyword); void *lammps_extract_global(void *handle, const char *name); void *lammps_extract_atom(void *handle, const char *name); +int lammps_extract_global_datatype(void *handle, const char *name); +int lammps_extract_atom_datatype(void *handle, const char *name); + #if !defined(LAMMPS_BIGBIG) int lammps_create_atoms(void *handle, int n, int *id, int *type, double *x, double *v, int *image, int bexpand); diff --git a/src/lmptype.h b/src/lmptype.h index e0e081dd12..e5dba94be0 100644 --- a/src/lmptype.h +++ b/src/lmptype.h @@ -79,6 +79,7 @@ namespace LAMMPS_NS { // for atomic problems that exceed 2 billion (2^31) atoms // 32-bit smallint/imageint/tagint, 64-bit bigint +// atom IDs and molecule IDs are limited to 32-bit #ifdef LAMMPS_SMALLBIG @@ -101,6 +102,11 @@ typedef int64_t bigint; #define ATOTAGINT atoi #define ATOBIGINT ATOLL +#define LAMMPS_TAGINT LAMMPS_INT +#define LAMMPS_TAGINT_2D LAMMPS_INT_2D +#define LAMMPS_BIGINT LAMMPS_INT64 +#define LAMMPS_BIGINT_2D LAMMPS_INT64_2D + #define IMGMASK 1023 #define IMGMAX 512 #define IMGBITS 10 @@ -133,6 +139,11 @@ typedef int64_t bigint; #define ATOTAGINT ATOLL #define ATOBIGINT ATOLL +#define LAMMPS_TAGINT LAMMPS_INT64 +#define LAMMPS_TAGINT_2D LAMMPS_INT64_2D +#define LAMMPS_BIGINT LAMMPS_INT64 +#define LAMMPS_BIGINT_2D LAMMPS_INT64_2D + #define IMGMASK 2097151 #define IMGMAX 1048576 #define IMGBITS 21 @@ -164,6 +175,11 @@ typedef int bigint; #define ATOTAGINT atoi #define ATOBIGINT atoi +#define LAMMPS_TAGINT LAMMPS_INT +#define LAMMPS_TAGINT_2D LAMMPS_INT_2D +#define LAMMPS_BIGINT LAMMPS_INT +#define LAMMPS_BIGINT_2D LAMMPS_INT_2D + #define IMGMASK 1023 #define IMGMAX 512 #define IMGBITS 10 @@ -171,22 +187,21 @@ typedef int bigint; #endif - /// Data structe for packing 32-bit and 64-bit integers - /// into double (communication) buffers - /// - /// Using this union avoids aliasing issues by having member types - /// (double, int) referencing the same buffer memory location. - /// - /// The explicit constructor for 32-bit integers prevents compilers - /// from (incorrectly) calling the double constructor when storing - /// an int into a double buffer. - /* +/** Data structure for packing 32-bit and 64-bit integers + * into double (communication) buffers + * + * Using this union avoids aliasing issues by having member types + * (double, int) referencing the same buffer memory location. + * + * The explicit constructor for 32-bit integers prevents compilers + * from (incorrectly) calling the double constructor when storing + * an int into a double buffer. \verbatim embed:rst + **Usage:** -To copy an integer into a double buffer: - -.. code-block: c++ +.. code-block:: c++ + :caption: To copy an integer into a double buffer: double buf[2]; int foo = 1; @@ -194,14 +209,13 @@ To copy an integer into a double buffer: buf[1] = ubuf(foo).d; buf[2] = ubuf(bar).d; -To copy from a double buffer back to an int: - -.. code-block: c++ +.. code-block:: c++ + :caption: To copy from a double buffer back to an int: foo = (int) ubuf(buf[1]).i; bar = (tagint) ubuf(buf[2]).i; -The typecast prevents compiler warnings about possible truncations. +The typecasts prevent compiler warnings about possible truncation issues. \endverbatim */ union ubuf { diff --git a/src/math_eigen.cpp b/src/math_eigen.cpp new file mode 100644 index 0000000000..0c4895f0ed --- /dev/null +++ b/src/math_eigen.cpp @@ -0,0 +1,78 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Andrew Jewett (Scripps Research) +------------------------------------------------------------------------- */ + +#include "math_eigen.h" +#include "math_eigen_impl.h" + +#include + +using std::vector; +using std::array; +using namespace MathEigen; + +// Special case: 3x3 matrices + +typedef Jacobi Jacobi_v1; +typedef Jacobi Jacobi_v2; + +int MathEigen::jacobi3(double const mat[3][3], double *eval, double evec[3][3]) +{ + // make copy of const matrix + + double mat_cpy[3][3] = { {mat[0][0], mat[0][1], mat[0][2]}, + {mat[1][0], mat[1][1], mat[1][2]}, + {mat[2][0], mat[2][1], mat[2][2]} }; + double *M[3] = { &(mat_cpy[0][0]), &(mat_cpy[1][0]), &(mat_cpy[2][0]) }; + int midx[3]; + + // create instance of generic Jacobi class and get eigenvalues and -vectors + + Jacobi_v1 ecalc3(3, M, midx); + int ierror = ecalc3.Diagonalize(mat, eval, evec, Jacobi_v1::SORT_DECREASING_EVALS); + + // transpose the evec matrix + + for (int i=0; i<3; i++) + for (int j=i+1; j<3; j++) + std::swap(evec[i][j], evec[j][i]); + + return ierror; +} + +int MathEigen::jacobi3(double const* const* mat, double *eval, double **evec) +{ + // make copy of const matrix + + double mat_cpy[3][3] = { {mat[0][0], mat[0][1], mat[0][2]}, + {mat[1][0], mat[1][1], mat[1][2]}, + {mat[2][0], mat[2][1], mat[2][2]} }; + double *M[3] = { &(mat_cpy[0][0]), &(mat_cpy[1][0]), &(mat_cpy[2][0]) }; + int midx[3]; + + // create instance of generic Jacobi class and get eigenvalues and -vectors + + Jacobi_v2 ecalc3(3, M, midx); + int ierror = ecalc3.Diagonalize(mat, eval, evec, Jacobi_v2::SORT_DECREASING_EVALS); + + // transpose the evec matrix + + for (int i=0; i<3; i++) + for (int j=i+1; j<3; j++) + std::swap(evec[i][j], evec[j][i]); + + return ierror; +} diff --git a/src/math_eigen.h b/src/math_eigen.h new file mode 100644 index 0000000000..7abf7eb539 --- /dev/null +++ b/src/math_eigen.h @@ -0,0 +1,36 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, 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_MATH_EIGEN_H +#define LMP_MATH_EIGEN_H + +namespace MathEigen { + +/** A specialized function which finds the eigenvalues and eigenvectors + * of a 3x3 matrix (in double ** format). + * + * \param mat the 3x3 matrix you wish to diagonalize + * \param eval store the eigenvalues here + * \param evec store the eigenvectors here... + * \return 0 if eigenvalue calculation converged, 1 if it failed */ + +int jacobi3(double const* const* mat, double *eval, double **evec); + +/** \overload */ + +int jacobi3(double const mat[3][3], double *eval, double evec[3][3]); + +} + +#endif //#ifndef LMP_MATH_EIGEN_H diff --git a/src/USER-REACTION/math_eigen.h b/src/math_eigen_impl.h similarity index 61% rename from src/USER-REACTION/math_eigen.h rename to src/math_eigen_impl.h index f8d2be4e21..a48158de32 100644 --- a/src/USER-REACTION/math_eigen.h +++ b/src/math_eigen_impl.h @@ -16,31 +16,31 @@ Andrew Jewett (Scripps Research, Jacobi algorithm) ------------------------------------------------------------------------- */ -#ifndef _MATH_EIGEN_H -#define _MATH_EIGEN_H +#ifndef LMP_MATH_EIGEN_IMPL_H +#define LMP_MATH_EIGEN_IMPL_H -/// @file This file contains a library of functions and classes which can -/// efficiently perform eigendecomposition for an extremely broad -/// range of matrix types: both real and complex, dense and sparse. -/// Matrices need not be of type "double **", for example. -/// In principle, almost any type of C++ container can be used. -/// Some general C++11 compatible functions for allocating matrices and -/// calculating norms of real and complex vectors are also provided. -/// @note -/// The "Jacobi" and "PEigenDense" classes are used for calculating -/// eigenvalues and eigenvectors of conventional dense square matrices. -/// @note -/// The "LambdaLanczos" class can calculate eigenalues and eigenvectors -/// of more general types of matrices, especially large, sparse matrices. -/// It uses C++ lambda expressions to simplify and generalize the way -/// matrices can be represented. This allows it to be applied to -/// nearly any kind of sparse (or dense) matrix representation. -/// @note -/// The source code for Jacobi and LambdaLanczos is also available at: -/// https://github.com/jewettaij/jacobi_pd (CC0-1.0 license) -/// https://github.com/mrcdr/lambda-lanczos (MIT license) +// This file contains a library of functions and classes which can +// efficiently perform eigendecomposition for an extremely broad +// range of matrix types: both real and complex, dense and sparse. +// Matrices need not be of type "double **", for example. +// In principle, almost any type of C++ container can be used. +// Some general C++11 compatible functions for allocating matrices and +// calculating norms of real and complex vectors are also provided. +// note +// The "Jacobi" and "PEigenDense" classes are used for calculating +// eigenvalues and eigenvectors of conventional dense square matrices. +// note +// The "LambdaLanczos" class can calculate eigenalues and eigenvectors +// of more general types of matrices, especially large, sparse matrices. +// It uses C++ lambda expressions to simplify and generalize the way +// matrices can be represented. This allows it to be applied to +// nearly any kind of sparse (or dense) matrix representation. +// note +// The source code for Jacobi and LambdaLanczos is also available at: +// https://github.com/jewettaij/jacobi_pd (CC0-1.0 license) +// https://github.com/mrcdr/lambda-lanczos (MIT license) -#include +//#include #include #include #include @@ -51,408 +51,338 @@ namespace MathEigen { -// --- Memory allocation for matrices --- + // --- Memory allocation for matrices --- -/// @brief Allocate an arbitrary 2-dimensional array. (Uses row-major order.) -/// @note This function was intended for relatively small matrices (eg 4x4). -/// For large arrays, please use the 2d create() function from "memory.h" -template -void Alloc2D(size_t nrows, //!< size of the array (number of rows) - size_t ncols, //!< size of the array (number of columns) - Entry ***paaX); //!< pointer to a 2D C-style array + // Allocate an arbitrary 2-dimensional array. (Uses row-major order.) + // note This function was intended for relatively small matrices (eg 4x4). + // For large arrays, please use the 2d create() function from "memory.h" + template + void Alloc2D(size_t nrows, // size of the array (number of rows) + size_t ncols, // size of the array (number of columns) + Entry ***paaX); // pointer to a 2D C-style array -/// @brief Deallocate arrays that were created using Alloc2D(). -template -void Dealloc2D(Entry ***paaX); //!< pointer to 2D multidimensional array + // Deallocate arrays that were created using Alloc2D(). + template + void Dealloc2D(Entry ***paaX); // pointer to 2D multidimensional array -// --- Complex numbers --- + // --- Complex numbers --- -/// @brief "realTypeMap" struct is used to the define "real_t" type mapper -/// which returns the C++ type corresponding to the real component of T. -/// @details Consider a function ("l2_norm()") that calculates the -/// (Euclidian) length of a vector of numbers (either real or complex): -/// @code -/// template real_t l2_norm(const std::vector& vec); -/// @endcode -/// The l2_norm is always real by definition. -/// (See https://en.wikipedia.org/wiki/Norm_(mathematics)#Euclidean_norm) -/// The return type of this function ("real_t") indicates that -/// it returns a real number, even if the entries (of type T) -/// are complex numbers. In other words, by default, real_t returns T. -/// However real_t> returns T (not std::complex). -/// We define "real_t" below using C++ template specializations: + /// @brief + /// "realTypeMap" struct is used to the define "real_t" type mapper. + /// The "real_t" type mapper is used by the "LambdaLanczos" and "PEigenDense" + /// classes, so it is documented here to help users understand those classes. + /// "real_t" returns the C++ type corresponding to the real component of T. + /// + /// @details + /// For example, suppose you have a matrix of type std::complex**. + /// The eigenvalues calculated by "LambdaLanczos" and "PEigenDense" should be + /// of type "double" (which is the same as "real_T>"), + /// not "std::complex". (This is because the algorithm assumes the + /// matrix is Hermitian, and the eigenvalues of a Hermitian matrix are always + /// real. So if you attempt to pass a reference to a complex number as the + /// first argument to LambdaLanczos::run(), the compiler will complain.) + /// + /// Implementation details: "real_t" is defined using C++ template + /// specializations. -template -struct realTypeMap { - typedef T type; -}; -template -struct realTypeMap> { - typedef T type; -}; -template -using real_t = typename realTypeMap::type; + template + struct realTypeMap { + typedef T type; + }; + template + struct realTypeMap> { + typedef T type; + }; + template + using real_t = typename realTypeMap::type; -// --- Operations on vectors (of real and complex numbers) --- + // --- Operations on vectors (of real and complex numbers) --- -/// @brief Calculate the inner product of two vectors. -/// (For vectors of complex numbers, std::conj() is used.) -template -T inner_prod(const std::vector& v1, const std::vector& v2); + // Calculate the inner product of two vectors. + // (For vectors of complex numbers, std::conj() is used.) + template + T inner_prod(const std::vector& v1, const std::vector& v2); -/// @brief Compute the sum of the absolute values of the entries in v -/// @returns a real number (of type real_t). -template -real_t l1_norm(const std::vector& v); + // Compute the sum of the absolute values of the entries in v + // returns a real number (of type real_t). + template + real_t l1_norm(const std::vector& v); -/// @brief Calculate the l2_norm (Euclidian length) of vector v. -/// @returns a real number (of type real_t). -template -real_t l2_norm(const std::vector& v); + // Calculate the l2_norm (Euclidian length) of vector v. + // returns a real number (of type real_t). + template + real_t l2_norm(const std::vector& v); -/// @brief Multiply a vector (v) by a scalar (c). -template -void scalar_mul(T1 c, std::vector& v); + /// Multiply a vector (v) by a scalar (c). + template + void scalar_mul(T1 c, std::vector& v); -/// @brief Divide vector "v" in-place by it's length (l2_norm(v)). -template -void normalize(std::vector& v); + /// Divide vector "v" in-place by it's length (l2_norm(v)). + template + void normalize(std::vector& v); + // ---- Eigendecomposition of small dense symmetric matrices ---- -// ---- Eigendecomposition of small dense symmetric matrices ---- + /// @class Jacobi + /// @brief Calculate the eigenvalues and eigenvectors of a symmetric matrix + /// using the Jacobi eigenvalue algorithm. This code (along with tests + /// and benchmarks) is available free of license restrictions at: + /// https://github.com/jewettaij/jacobi_pd + /// @note The "Vector", "Matrix", and "ConstMatrix" type arguments can be any + /// C or C++ object that supports indexing, including pointers or vectors. -/// @class Jacobi -/// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix -/// using the Jacobi eigenvalue algorithm. Code for the Jacobi class -/// (along with tests and benchmarks) is available free of copyright at -/// https://github.com/jewettaij/jacobi_pd -/// @note The "Vector" and "Matrix" type arguments can be any -/// C or C++ object that support indexing, including pointers or vectors. -/// @details -/// -- Example: -- -/// -/// int n = 5; // Matrix size -/// double **M; // A symmetric n x n matrix you want to diagonalize -/// double *evals; // Store the eigenvalues here. -/// double **evects; // Store the eigenvectors here. -/// // Allocate space for M, evals, and evects, and load contents of M (omitted) -/// -/// // Now create an instance of Jacobi ("eigen_calc"). This will allocate space -/// // for storing intermediate calculations. Once created, it can be reused -/// // multiple times without paying the cost of allocating memory on the heap. -/// -/// Jacobi eigen_calc(n); -/// -/// // Note: -/// // If the matrix you plan to diagonalize (M) is read-only, use this instead: -/// // Jacobi eigen_calc(n); -/// // If you prefer using vectors over C-style pointers, this works also: -/// // Jacobi&, vector>&> eigen_calc(n); -/// -/// // Now, calculate the eigenvalues and eigenvectors of M -/// -/// eigen_calc.Diagonalize(M, evals, evects); -/// -/// --- end of example --- + template -template + class Jacobi + { + int n; //!< the size of the matrices you want to diagonalize + Scalar **M; //!< local copy of the current matrix being analyzed + // Precomputed cosine, sine, and tangent of the most recent rotation angle: + Scalar c; //!< = cos(θ) + Scalar s; //!< = sin(θ) + Scalar t; //!< = tan(θ), (note |t|<=1) + int *max_idx_row; //!< = keep track of the the maximum element in row i (>i) -class Jacobi -{ - int n; //!< the size of the matrices you want to diagonalize - Scalar **M; //!< local copy of the current matrix being analyzed - // Precomputed cosine, sine, and tangent of the most recent rotation angle: - Scalar c; //!< = cos(θ) - Scalar s; //!< = sin(θ) - Scalar t; //!< = tan(θ), (note |t|<=1) - int *max_idx_row; //!< = keep track of the the maximum element in row i (>i) + public: + /// @brief Specify the size of the matrices you want to diagonalize later. + /// @param n the size (ie. number of rows) of the (square) matrix. + Jacobi(int n); -public: + ~Jacobi(); - /// @brief Specify the size of the matrices you want to diagonalize later. - /// @param n the size (ie. number of rows) of the (square) matrix. - void SetSize(int n); + /// @brief Change the size of the matrices you want to diagonalize. + /// @param n the size (ie. number of rows) of the (square) matrix. + void SetSize(int n); - Jacobi(int n = 0) { Init(); SetSize(n); } + // @typedef choose the criteria for sorting eigenvalues and eigenvectors + typedef enum eSortCriteria { + DO_NOT_SORT, + SORT_DECREASING_EVALS, + SORT_INCREASING_EVALS, + SORT_DECREASING_ABS_EVALS, + SORT_INCREASING_ABS_EVALS + } SortCriteria; - ~Jacobi() { Dealloc(); } + /// @brief Calculate the eigenvalues and eigenvectors of a symmetric matrix + /// using the Jacobi eigenvalue algorithm. + /// @returns 0 if the algorithm converged, + /// 1 if the algorithm failed to converge. (IE, if the number of + /// pivot iterations exceeded max_num_sweeps * iters_per_sweep, + /// where iters_per_sweep = (n*(n-1)/2)) + /// @note To reduce the computation time further, set calc_evecs=false. + int + Diagonalize(ConstMatrix mat, //!< the matrix you wish to diagonalize (size n) + Vector eval, //!< store the eigenvalues here + Matrix evec, //!< store the eigenvectors here (in rows) + SortCriteria sort_criteria=SORT_DECREASING_EVALS,//!& source); - Jacobi(Jacobi&& other); - void swap(Jacobi &other); - Jacobi& operator = (Jacobi source); + // (Descriptions of private functions can be found in their implementation.) + void _Jacobi(int n, Scalar **M, int *max_idx_row); + void CalcRot(Scalar const *const *M, int i, int j); + void ApplyRot(Scalar **M, int i, int j); + void ApplyRotLeft(Matrix E, int i, int j); + int MaxEntryRow(Scalar const *const *M, int i) const; + void MaxEntry(Scalar const *const *M, int& i_max, int& j_max) const; + void SortRows(Vector v, Matrix M, int n, SortCriteria s=SORT_DECREASING_EVALS) const; + void Init(); + void Alloc(int n); + void Dealloc(); + public: + // C++ boilerplate: copy and move constructor, swap, and assignment operator + Jacobi(const Jacobi& source); + Jacobi(Jacobi&& other); + void swap(Jacobi &other); + Jacobi& operator = (Jacobi source); -}; // class Jacobi + }; // class Jacobi + // ---- Eigendecomposition of large sparse (or dense) matrices ---- + // The "LambdaLanczos" is a class useful for calculating eigenvalues + // and eigenvectors of large sparse matrices. Unfortunately, before the + // LambdaLanczos class can be declared, several additional expressions, + // classes and functions that it depends on must be declared first. + // Create random vectors used at the beginning of the Lanczos algorithm. + // note "Partially specialization of function" is not allowed, so + // it is mimicked by wrapping the "init" function with a class template. + template + struct VectorRandomInitializer { + public: + static void init(std::vector&); + }; + template + struct VectorRandomInitializer> { + public: + static void init(std::vector>&); + }; -// ---- Eigendecomposition of large sparse (and dense) matrices ---- - -// The "LambdaLanczos" is a class useful for calculating eigenvalues -// and eigenvectors of large sparse matrices. Unfortunately, before the -// LambdaLanczos class can be declared, several additional expressions, -// classes and functions that it depends on must be declared first. - -// @brief Create random vectors used at the beginning of the Lanczos algorithm. -// @note "Partially specialization of function" is not allowed, so -// it is mimicked by wrapping the "init" function with a class template. -template -struct VectorRandomInitializer { -public: - static void init(std::vector&); -}; - -template -struct VectorRandomInitializer> { -public: - static void init(std::vector>&); -}; - -/// @brief Return the number of significant decimal digits of type T. -template -inline constexpr int sig_decimal_digit() { - return (int)(std::numeric_limits::digits * - std::log10(std::numeric_limits::radix)); -} - -/// @brief Return 10^-n where n=number of significant decimal digits of type T. -template -inline constexpr T minimum_effective_decimal() { - return std::pow(10, -sig_decimal_digit()); -} - - -/// @brief The LambdaLanczos class provides a general way to calculate -/// the smallest or largest eigenvalue and the corresponding eigenvector -/// of a symmetric (Hermitian) matrix using the Lanczos algorithm. -/// The characteristic feature of LambdaLanczos is that the matrix-vector -/// multiplication routine used in the Lanczos algorithm is adaptable. -/// @details -/// @code -/// -/// //Example: -/// const int n = 3; -/// double M[n][n] = { {-1.0, -1.0, 1.0}, -/// {-1.0, 1.0, 1.0}, -/// { 1.0, 1.0, 1.0} }; -/// // (Its eigenvalues are {-2, 1, 2}) -/// -/// // Specify the matrix-vector multiplication function -/// auto mv_mul = [&](const vector& in, vector& out) { -/// for(int i = 0;i < n;i++) { -/// for(int j = 0;j < n;j++) { -/// out[i] += M[i][j]*in[j]; -/// } -/// } -/// }; -/// -/// LambdaLanczos engine(mv_mul, n, true); -/// // ("true" means to calculate the largest eigenvalue.) -/// engine.eigenvalue_offset = 3.0 # = max_i{Σ_j|Mij|} (see below) -/// double eigenvalue; -/// vector eigenvector(n); -/// int itern = engine.run(eigenvalue, eigenvector); -/// -/// cout << "Iteration count: " << itern << endl; -/// cout << "Eigen value: " << setprecision(16) << eigenvalue << endl; -/// cout << "Eigen vector:"; -/// for(int i = 0; i < n; i++) { -/// cout << eigenvector[i] << " "; -/// } -/// cout << endl; -/// -/// @endcode -/// This feature allows you to use a matrix whose elements are partially given, -/// e.g. a sparse matrix whose non-zero elements are stored as a list of -/// {row-index, column-index, value} tuples. You can also easily combine -/// LambdaLanczos with existing matrix libraries (e.g. Eigen) -/// -/// @note -/// If the matrices you want to analyze are ordinary square matrices, (as in -/// the example) it might be easier to use "PEigenDense" instead. (It is a -/// wrapper which takes care of all of the LambdaLanczos details for you.) -/// -/// @note -/// IMPORTANT: -/// The Lanczos algorithm finds the largest magnitude eigenvalue, so you -/// MUST ensure that the eigenvalue you are seeking has the largest magnitude -/// (regardless of whether it is the maximum or minimum eigenvalue). -/// To insure that this is so, you can add or subtract a number to all -/// of the eigenvalues of the matrix by specifying the "eigenvalue_offset". -/// This number should exceed the largest magnitude eigenvalue of the matrix. -/// According to the Gershgorin theorem, you can estimate this number using -/// r = max_i{Σ_j|Mij|} = max_j{Σ_i|Mij|} -/// (where Mij are the elements of the matrix and Σ_j denotes the sum over j). -/// If find_maximum == true (if you are seeking the maximum eigenvalue), then -/// eigenvalue_offset = +r -/// If find_maximum == false, then -/// eigenvalue_offset = -r -/// The eigenvalue_offset MUST be specified by the user. LambdaLanczos does -/// not have an efficient and general way to access the elements of the matrix. -/// -/// (You can omit this step if you are seeking the maximum eigenvalue, -/// and the matrix is positive definite, or if you are seeking the minimum -/// eigenvalue and the matrix is negative definite.) -/// -/// @note -/// LambdaLanczos is available under the MIT license and downloadable at: -/// https://github.com/mrcdr/lambda-lanczos - -template -class LambdaLanczos { -public: - LambdaLanczos(); - LambdaLanczos(std::function&, std::vector&)> mv_mul, int matrix_size, bool find_maximum); - LambdaLanczos(std::function&, std::vector&)> mv_mul, int matrix_size) : LambdaLanczos(mv_mul, matrix_size, true) {} - - /// @brief Calculate the principal (largest or smallest) eigenvalue - /// of the matrix (and its corresponding eigenvector). - int run(real_t&, std::vector&) const; - - // --- public data members --- - - /// @brief Specify the size of the matrix you will analyze. - /// (This equals the size of the eigenvector which will be returned.) - int matrix_size; - - /// @brief Specify the function used for matrix*vector multiplication - /// used by the Lanczos algorithm. For an ordinary dense matrix, - /// this function is the ordinary matrix*vector product. (See the - /// example above. For a sparse matrix, it will be something else.) - std::function&, std::vector&)> mv_mul; - - /// @brief Are we searching for the maximum or minimum eigenvalue? - /// @note (Usually, you must also specify eigenvalue_offset.) - bool find_maximum = false; - - /// @brief Shift all the eigenvalues by "eigenvalue_offset" during the Lanczos - /// iteration (ie. during LambdaLanczos::run()). The goal is to insure - /// that the correct eigenvalue is selected (the one with the maximum - /// magnitude). - /// @note The eigevalue returned by LambdaLanczos::run() is not effected - /// because after the iteration is finished, it will subtract this - /// number from the eigenvalue before it is returned to the caller. - /// @note Unless your matrix is positive definite or negative definite, - /// you MUST specify eigenvalue_offset. See comment above for details. - real_t eigenvalue_offset = 0.0; - - /// @brief This function sets "eigenvalue_offset" automatically. - /// @note Using this function is not recommended because it is very slow. - /// For efficiency, set the "eigenvalue_offset" yourself. - void ChooseOffset(); - - // The remaining data members usually can be left alone: - int max_iteration; - real_t eps = minimum_effective_decimal>() * 1e3; - real_t tridiag_eps_ratio = 1e-1; - int initial_vector_size = 200; - std::function&)> init_vector = - VectorRandomInitializer::init; - - // (for those who prefer "Set" functions...) - int SetSize(int matrix_size); - void SetMul(std::function&, - std::vector&)> mv_mul); - void SetInitVec(std::function&)> init_vector); - void SetFindMax(bool find_maximum); - void SetEvalOffset(T eigenvalue_offset); - void SetEpsilon(T eps); - void SetTriEpsRatio(T tridiag_eps_ratio); - -private: - static void schmidt_orth(std::vector&, const std::vector>&); - real_t find_minimum_eigenvalue(const std::vector>&, - const std::vector>&) const; - real_t find_maximum_eigenvalue(const std::vector>&, - const std::vector>&) const; - static real_t tridiagonal_eigen_limit(const std::vector>&, - const std::vector>&); - static int num_of_eigs_smaller_than(real_t, - const std::vector>&, - const std::vector>&); - real_t UpperBoundEvals() const; -}; - - - -/// @brief -/// PEigenDense is a class containing only one useful member function: -/// PrincipalEigen(). This function calculates the principal (largest -/// or smallest) eigenvalue and corresponding eigenvector of a square -/// n x n matrix. This can be faster than diagionalizing the entire matrix. -/// (For example by using the Lanczos algorithm or something similar.) -/// @note -/// This code is a wrapper. Internally, it uses the "LambdaLanczos" class. -/// @note -/// For matrices larger than 13x13, PEigenDense::PrincipleEigen() -/// is usually faster than Jacobi::Diagonalize().) - -template -class PEigenDense -{ - size_t n; // the size of the matrix - std::vector evec; // preallocated vector - -public: - void SetSize(int matrix_size) { - n = matrix_size; - evec.resize(n); + // Return the number of significant decimal digits of type T. + template + inline constexpr int sig_decimal_digit() { + return (int)(std::numeric_limits::digits * + std::log10(std::numeric_limits::radix)); } - PEigenDense(int matrix_size=0):evec(matrix_size) { - SetSize(matrix_size); + // Return 10^-n where n=number of significant decimal digits of type T. + template + inline constexpr T minimum_effective_decimal() { + return std::pow(10, -sig_decimal_digit()); } - /// @brief Calculate the principal eigenvalue and eigenvector of a matrix. - /// @return Return the principal eigenvalue of the matrix. - /// If you want the eigenvector, pass a non-null "evector" argument. - Scalar - PrincipalEigen(ConstMatrix matrix, //!< the input patrix - Vector evector, //!< the eigenvector is stored here - bool find_max=false); //!< want the max or min eigenvalue? -}; // class PEigenDense + /// @class LambdaLanczos + /// @brief The LambdaLanczos class provides a general way to calculate + /// the smallest or largest eigenvalue and the corresponding eigenvector + /// of a Hermitian matrix using the Lanczos algorithm. + /// The characteristic feature of LambdaLanczos is that the matrix-vector + /// multiplication routine used in the Lanczos algorithm is adaptable. + /// This code (along with automatic unit tests) is also distributed + /// under the MIT license at https://github.com/mrcdr/lambda-lanczos + /// + /// @note + /// If the matrices you want to analyze are ordinary square matrices, (as in + /// the example) it might be easier to use "PEigenDense" instead. (It is a + /// wrapper which takes care of all of the LambdaLanczos details for you.) + /// + /// @note + /// IMPORTANT: + /// Unless the matrix you are solving is positive or negative definite, you + /// MUST set the "eigenvalue_offset" parameter. See the "pg_developer" docs. + + template + class LambdaLanczos { + public: + LambdaLanczos(); + LambdaLanczos(std::function&, std::vector&)> mv_mul, int matrix_size, bool find_maximum); + LambdaLanczos(std::function&, std::vector&)> mv_mul, int matrix_size) : LambdaLanczos(mv_mul, matrix_size, true) {} + + /// @brief Calculate the principal (largest or smallest) eigenvalue + /// of the matrix (and its corresponding eigenvector). + int run(real_t&, std::vector&) const; + + // --- public data members --- + + /// @brief Specify the size of the matrix you will analyze. + /// (This equals the size of the eigenvector which will be returned.) + int matrix_size; + + /// @brief Specify the function used for matrix*vector multiplication + /// used by the Lanczos algorithm. For an ordinary dense matrix, + /// this function is the ordinary matrix*vector product. (See the + /// example above. For a sparse matrix, it will be something else.) + std::function&, std::vector&)> mv_mul; + + /// @brief Are we searching for the maximum or minimum eigenvalue? + /// @note (Usually, you must also specify eigenvalue_offset.) + bool find_maximum = false; + + /// @brief Shift all the eigenvalues by "eigenvalue_offset" during the Lanczos + /// iteration (ie. during LambdaLanczos::run()). The goal is to insure + /// that the correct eigenvalue is selected (the one with the maximum + /// magnitude). + /// @note Unless your matrix is positive definite or negative definite, you + /// MUST specify eigenvalue_offset. See comment above for details. + /// @note After LambdaLanczos::run() has finished, it will subtract this + /// number from the eigenvalue before it is returned to the caller. + real_t eigenvalue_offset = 0.0; + + /// @brief This function sets "eigenvalue_offset" automatically. + /// @note Using this function is not recommended because it is very slow. + /// For efficiency, set the "eigenvalue_offset" yourself. + void ChooseOffset(); + + // The remaining data members usually can be left alone: + int max_iteration; + real_t eps = minimum_effective_decimal>() * 1e3; + real_t tridiag_eps_ratio = 1e-1; + int initial_vector_size = 200; + std::function&)> init_vector = + VectorRandomInitializer::init; + + // (for those who prefer using "Set" functions...) + int SetSize(int matrix_size); + void SetMul(std::function&, + std::vector&)> mv_mul); + void SetInitVec(std::function&)> init_vector); + void SetFindMax(bool find_maximum); + void SetEvalOffset(T eigenvalue_offset); + void SetEpsilon(T eps); + void SetTriEpsRatio(T tridiag_eps_ratio); + + private: + static void schmidt_orth(std::vector&, const std::vector>&); + real_t find_minimum_eigenvalue(const std::vector>&, + const std::vector>&) const; + real_t find_maximum_eigenvalue(const std::vector>&, + const std::vector>&) const; + static real_t tridiagonal_eigen_limit(const std::vector>&, + const std::vector>&); + static int num_of_eigs_smaller_than(real_t, + const std::vector>&, + const std::vector>&); + real_t UpperBoundEvals() const; + }; + + + + /// @class PEigenDense + /// @brief + /// PEigenDense is a class containing only one useful member function: + /// PrincipalEigen(). This function calculates the principal (largest + /// or smallest) eigenvalue and corresponding eigenvector of a square + /// n x n matrix. This can be faster than diagonalizing the entire matrix. + /// @note + /// This code is a wrapper. Internally, it uses the "LambdaLanczos" class. + /// @note + /// For dense matrices smaller than 13x13, Jacobi::Diagonalize(), + /// is usually faster than PEigenDense::PrincipleEigen(). + + template + class PEigenDense + { + size_t n; // the size of the matrix + std::vector evec; // preallocated vector + + public: + PEigenDense(int matrix_size=0); + + /// @brief Calculate the principal eigenvalue and eigenvector of a matrix. + /// @return Return the principal eigenvalue of the matrix. + /// If you want the eigenvector, pass a non-null "evector" argument. + real_t + PrincipalEigen(ConstMatrix matrix, //!< the input matrix + Vector evector, //!< the eigenvector is stored here + bool find_max=false); //!< want the max or min eigenvalue? + + void SetSize(int matrix_size); //change matrix size after instantiation + + }; // class PEigenDense @@ -460,16 +390,13 @@ public: // ----------- IMPLEMENTATION ----------- // -------------------------------------- - - - // --- Implementation: Memory allocation for matrices --- template void Alloc2D(size_t nrows, // size of the array (number of rows) size_t ncols, // size of the array (number of columns) Entry ***paaX) // pointer to a 2D C-style array { - assert(paaX); + //assert(paaX); *paaX = new Entry* [nrows]; //conventional 2D C array (pointer-to-pointer) (*paaX)[0] = new Entry [nrows * ncols]; // 1D C array (contiguous memor) for(size_t iy=0; iy& vec) { scalar_mul(1.0/l2_norm(vec), vec); } - template inline real_t l1_norm(const std::vector& vec) { real_t norm = real_t(); // Zero initialization @@ -549,6 +475,52 @@ inline real_t l1_norm(const std::vector& vec) { // --- Implementation: Eigendecomposition of small dense matrices --- + +template +Jacobi:: +Jacobi(int n) { + _Jacobi(n, nullptr, nullptr); +} + + +template +Jacobi:: +Jacobi(int n, Scalar **M, int *max_idx_row) { + _Jacobi(n, M, max_idx_row); +} + + +// _Jacobi() is a function which is invoked by the two constructors and it +// does all of the work. (Splitting the constructor into multiple functions +// was technically unnecessary, but it makes documenting the code easier.) + +template +void +Jacobi:: +_Jacobi(int n, Scalar **M, int *max_idx_row) { + Init(); + if (M) { // if caller supplies their own "M" array, don't allocate M + is_preallocated = true; + this->n = n; + this->M = M; + this->max_idx_row = max_idx_row; + //assert(this->max_idx_row); + } + else { + is_preallocated = false; + SetSize(n); // allocate the "M" and "max_int_row" arrays + } +} + + +template +Jacobi:: +~Jacobi() { + if (! is_preallocated) + Dealloc(); +} + + template int Jacobi:: Diagonalize(ConstMatrix mat, // the matrix you wish to diagonalize (size n) @@ -602,7 +574,7 @@ Diagonalize(ConstMatrix mat, // the matrix you wish to diagonalize (size n) // Optional: Sort results by eigenvalue. SortRows(eval, evec, n, sort_criteria); - return n_iters / (n*(n-1)/2); //returns the number of "sweeps" (converged?) + return (n_iters == max_num_iters); } @@ -634,7 +606,7 @@ CalcRot(Scalar const *const *M, //!< matrix t = -t; } } - assert(std::abs(t) <= 1.0); + //assert(std::abs(t) <= 1.0); c = 1.0 / std::sqrt(1 + t*t); s = c*t; } @@ -699,7 +671,7 @@ ApplyRot(Scalar **M, // matrix M[j][j] += t * M[i][j]; //Update the off-diagonal elements of M which will change (above the diagonal) - assert(i < j); + //assert(i < j); M[i][j] = 0.0; //compute M[w][i] and M[i][w] for all w!=i,considering above-diagonal elements @@ -849,6 +821,7 @@ Init() { n = 0; M = nullptr; max_idx_row = nullptr; + is_preallocated = false; } template @@ -863,6 +836,7 @@ SetSize(int n) { template void Jacobi:: Alloc(int n) { + //assert(! is_preallocated); this->n = n; if (n > 0) { max_idx_row = new int[n]; @@ -873,8 +847,7 @@ Alloc(int n) { template void Jacobi:: Dealloc() { - if (max_idx_row) - delete [] max_idx_row; + //assert(! is_preallocated); Dealloc2D(&M); Init(); } @@ -887,7 +860,8 @@ Jacobi(const Jacobi& source) { Init(); SetSize(source.n); - assert(n == source.n); + + //assert(n == source.n); // The following lines aren't really necessary, because the contents // of source.M and source.max_idx_row are not needed (since they are // overwritten every time Jacobi::Diagonalize() is invoked). @@ -904,6 +878,7 @@ template void Jacobi:: swap(Jacobi &other) { std::swap(n, other.n); + std::swap(is_preallocated, other.is_preallocated); std::swap(max_idx_row, other.max_idx_row); std::swap(M, other.M); } @@ -913,7 +888,7 @@ template Jacobi:: Jacobi(Jacobi&& other) { Init(); - swap(*this, other); + this->swap(other); } // Using the "copy-swap" idiom for the assignment operator @@ -933,7 +908,7 @@ template inline LambdaLanczos::LambdaLanczos() { this->matrix_size = 0; this->max_iteration = 0; - this->find_maximum = 0; + this->find_maximum = false; } @@ -955,8 +930,8 @@ template inline int LambdaLanczos:: run(real_t& eigvalue, std::vector& eigvec) const { - assert(matrix_size > 0); - assert(0 < this->tridiag_eps_ratio && this->tridiag_eps_ratio < 1); + //assert(matrix_size > 0); + //assert(0 < this->tridiag_eps_ratio && this->tridiag_eps_ratio < 1); std::vector> u; // Lanczos vectors std::vector> alpha; // Diagonal elements of an approximated tridiagonal matrix @@ -1322,12 +1297,25 @@ init(std::vector>& v) // --- Implementation of PEigenDense template -Scalar PEigenDense:: +void PEigenDense:: +SetSize(int matrix_size) { + n = matrix_size; + evec.resize(n); +} + +template +PEigenDense:: +PEigenDense(int matrix_size):evec(matrix_size) { + SetSize(matrix_size); +} + +template +real_t PEigenDense:: PrincipalEigen(ConstMatrix matrix, Vector eigenvector, bool find_max) { - assert(n > 0); + //assert(n > 0); auto matmul = [&](const std::vector& in, std::vector& out) { for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { @@ -1365,7 +1353,7 @@ PrincipalEigen(ConstMatrix matrix, Scalar eval; // This line does all of the hard work: - size_t itern = ll_engine.run(eval, evec); + ll_engine.run(eval, evec); for (int i = 0; i < n; i++) eigenvector[i] = evec[i]; @@ -1373,8 +1361,12 @@ PrincipalEigen(ConstMatrix matrix, return eval; } - } //namespace MathEigen -#endif //#ifndef _MATH_EIGEN_H + + + + + +#endif //#ifndef LMP_MATH_EIGEN_IMPL_H diff --git a/src/math_extra.cpp b/src/math_extra.cpp index b04414a300..a7a8a98a90 100644 --- a/src/math_extra.cpp +++ b/src/math_extra.cpp @@ -19,8 +19,6 @@ #include #include -#define MAXJACOBI 50 - namespace MathExtra { /* ---------------------------------------------------------------------- @@ -92,88 +90,6 @@ int mldivide3(const double m[3][3], const double *v, double *ans) return 0; } -/* ---------------------------------------------------------------------- - compute evalues and evectors of 3x3 real symmetric matrix - based on Jacobi rotations - adapted from Numerical Recipes jacobi() function -------------------------------------------------------------------------- */ - -int jacobi(double matrix[3][3], double *evalues, double evectors[3][3]) -{ - int i,j,k; - double tresh,theta,tau,t,sm,s,h,g,c,b[3],z[3]; - - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) evectors[i][j] = 0.0; - evectors[i][i] = 1.0; - } - for (i = 0; i < 3; i++) { - b[i] = evalues[i] = matrix[i][i]; - z[i] = 0.0; - } - - for (int iter = 1; iter <= MAXJACOBI; iter++) { - sm = 0.0; - for (i = 0; i < 2; i++) - for (j = i+1; j < 3; j++) - sm += fabs(matrix[i][j]); - if (sm == 0.0) return 0; - - if (iter < 4) tresh = 0.2*sm/(3*3); - else tresh = 0.0; - - for (i = 0; i < 2; i++) { - for (j = i+1; j < 3; j++) { - g = 100.0*fabs(matrix[i][j]); - if (iter > 4 && fabs(evalues[i])+g == fabs(evalues[i]) - && fabs(evalues[j])+g == fabs(evalues[j])) - matrix[i][j] = 0.0; - else if (fabs(matrix[i][j]) > tresh) { - h = evalues[j]-evalues[i]; - if (fabs(h)+g == fabs(h)) t = (matrix[i][j])/h; - else { - theta = 0.5*h/(matrix[i][j]); - t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta)); - if (theta < 0.0) t = -t; - } - c = 1.0/sqrt(1.0+t*t); - s = t*c; - tau = s/(1.0+c); - h = t*matrix[i][j]; - z[i] -= h; - z[j] += h; - evalues[i] -= h; - evalues[j] += h; - matrix[i][j] = 0.0; - for (k = 0; k < i; k++) rotate(matrix,k,i,k,j,s,tau); - for (k = i+1; k < j; k++) rotate(matrix,i,k,k,j,s,tau); - for (k = j+1; k < 3; k++) rotate(matrix,i,k,j,k,s,tau); - for (k = 0; k < 3; k++) rotate(evectors,k,i,k,j,s,tau); - } - } - } - - for (i = 0; i < 3; i++) { - evalues[i] = b[i] += z[i]; - z[i] = 0.0; - } - } - return 1; -} - -/* ---------------------------------------------------------------------- - perform a single Jacobi rotation -------------------------------------------------------------------------- */ - -void rotate(double matrix[3][3], int i, int j, int k, int l, - double s, double tau) -{ - double g = matrix[i][j]; - double h = matrix[k][l]; - matrix[i][j] = g-s*(h+g*tau); - matrix[k][l] = h+s*(g-h*tau); -} - /* ---------------------------------------------------------------------- Richardson iteration to update quaternion from angular momentum return new normalized quaternion q diff --git a/src/math_extra.h b/src/math_extra.h index a818bae4f4..6c58bc93c2 100644 --- a/src/math_extra.h +++ b/src/math_extra.h @@ -85,7 +85,6 @@ namespace MathExtra { void write3(const double mat[3][3]); int mldivide3(const double mat[3][3], const double *vec, double *ans); - int jacobi(double matrix[3][3], double *evalues, double evectors[3][3]); void rotate(double matrix[3][3], int i, int j, int k, int l, double s, double tau); void richardson(double *q, double *m, double *w, double *moments, double dtq); diff --git a/src/molecule.cpp b/src/molecule.cpp index 4612d50a7f..f4e1e4c098 100644 --- a/src/molecule.cpp +++ b/src/molecule.cpp @@ -21,6 +21,7 @@ #include "error.h" #include "force.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "tokenizer.h" @@ -349,7 +350,7 @@ void Molecule::compute_inertia() tensor[0][2] = tensor[2][0] = itensor[4]; tensor[0][1] = tensor[1][0] = itensor[5]; - if (MathExtra::jacobi(tensor,inertia,evectors)) + if (MathEigen::jacobi3(tensor,inertia,evectors)) error->all(FLERR,"Insufficient Jacobi rotations for rigid molecule"); ex[0] = evectors[0][0]; @@ -491,7 +492,7 @@ void Molecule::read(int flag) if (nmatch != nwant) error->one(FLERR,"Invalid header in molecule file"); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid header in molecule file\n" "{}", e.what())); } @@ -534,6 +535,8 @@ void Molecule::read(int flag) if (flag) molecules(line); else skip_lines(natoms,line); } else if (strcmp(keyword,"Fragments") == 0) { + if (nfragments == 0) + error->all(FLERR,"Molecule file has fragments but no nfragments setting"); fragmentflag = 1; if (flag) fragments(line); else skip_lines(nfragments,line); @@ -633,6 +636,8 @@ void Molecule::read(int flag) error->all(FLERR,"Molecule file has no Body Integers section"); if (bodyflag && ndbody && dbodyflag == 0) error->all(FLERR,"Molecule file has no Body Doubles section"); + if (nfragments > 0 && !fragmentflag) + error->all(FLERR,"Molecule file has no Fragments section"); } // auto-generate special bonds if needed and not in file @@ -687,7 +692,7 @@ void Molecule::coords(char *line) x[i][1] *= sizescale; x[i][2] *= sizescale; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Coords section in molecule file\n" "{}", e.what())); } @@ -717,7 +722,7 @@ void Molecule::types(char *line) type[i] = values.next_int(); type[i] += toffset; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Types section in molecule file\n" "{}", e.what())); } @@ -747,7 +752,7 @@ void Molecule::molecules(char *line) molecule[i] = values.next_int(); // molecule[i] += moffset; // placeholder for possible molecule offset } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Molecules section in molecule file\n" "{}", e.what())); } @@ -784,7 +789,7 @@ void Molecule::fragments(char *line) fragmentmask[i][atomID-1] = 1; } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid atom ID in Fragments section of molecule file\n" "{}", e.what())); } @@ -801,12 +806,12 @@ void Molecule::charges(char *line) readline(line); ValueTokenizer values(line); - if (values.count() != 2) error->one(FLERR,"Invalid Charges section in molecule file"); + if ((int)values.count() != 2) error->one(FLERR,"Invalid Charges section in molecule file"); values.next_int(); q[i] = values.next_double(); } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Charges section in molecule file\n" "{}", e.what())); } @@ -832,7 +837,7 @@ void Molecule::diameters(char *line) radius[i] *= 0.5; maxradius = MAX(maxradius,radius[i]); } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Diameters section in molecule file\n" "{}", e.what())); } @@ -859,7 +864,7 @@ void Molecule::masses(char *line) rmass[i] = values.next_double(); rmass[i] *= sizescale*sizescale*sizescale; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Masses section in molecule file\n" "{}", e.what())); } @@ -897,7 +902,7 @@ void Molecule::bonds(int flag, char *line) itype = values.next_int(); atom1 = values.next_tagint(); atom2 = values.next_tagint(); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Bonds section in molecule file\n" "{}", e.what())); } @@ -966,7 +971,7 @@ void Molecule::angles(int flag, char *line) atom1 = values.next_tagint(); atom2 = values.next_tagint(); atom3 = values.next_tagint(); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Angles section in molecule file\n" "{}", e.what())); } @@ -1051,7 +1056,7 @@ void Molecule::dihedrals(int flag, char *line) atom2 = values.next_tagint(); atom3 = values.next_tagint(); atom4 = values.next_tagint(); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Dihedrals section in molecule file\n" "{}", e.what())); } @@ -1151,7 +1156,7 @@ void Molecule::impropers(int flag, char *line) atom2 = values.next_tagint(); atom3 = values.next_tagint(); atom4 = values.next_tagint(); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Impropers section in molecule file\n" "{}", e.what())); } @@ -1243,7 +1248,7 @@ void Molecule::nspecial_read(int flag, char *line) c1 = values.next_tagint(); c2 = values.next_tagint(); c3 = values.next_tagint(); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Special Bond Counts section in molecule file\n" "{}", e.what())); } @@ -1282,7 +1287,7 @@ void Molecule::special_read(char *line) error->one(FLERR,"Invalid special atom index in molecule file"); } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Molecule file special list\n" "{}", e.what())); } @@ -1414,7 +1419,7 @@ void Molecule::shakeflag_read(char *line) values.next_int(); shake_flag[i] = values.next_int(); } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid Shake Flags section in molecule file\n" "{}", e.what())); } @@ -1479,7 +1484,7 @@ void Molecule::shakeatom_read(char *line) error->one(FLERR,"Invalid shake atom in molecule file"); } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR,fmt::format("Invalid shake atom in molecule file\n" "{}", e.what())); } @@ -1544,7 +1549,7 @@ void Molecule::shaketype_read(char *line) if (nmatch != nwant) error->one(FLERR,"Invalid shake type data in molecule file"); } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid shake type data in molecule file\n", "{}", e.what())); } @@ -1597,7 +1602,7 @@ void Molecule::body(int flag, int pflag, char *line) } } else nword += ncount; } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, fmt::format("Invalid body params in molecule file\n", "{}", e.what())); } @@ -1690,6 +1695,7 @@ void Molecule::initialize() nmolecules = 1; nbondtypes = nangletypes = ndihedraltypes = nimpropertypes = 0; nibody = ndbody = 0; + nfragments = 0; bond_per_atom = angle_per_atom = dihedral_per_atom = improper_per_atom = 0; maxspecial = 0; diff --git a/src/molecule.h b/src/molecule.h index 5a3fa5a327..3316cd3f1f 100644 --- a/src/molecule.h +++ b/src/molecule.h @@ -241,6 +241,10 @@ E: Molecule file has impropers but no nimpropers setting Self-explanatory. +E: Molecule file has fragments but no nfragments setting + +Self-explanatory. + E: Molecule file shake flags not before shake atoms The order of the two sections is important. @@ -277,6 +281,10 @@ E: Molecule file has no Body Doubles section Self-explanatory. +E: Molecule file has no Fragments section + +Self-explanatory. + E: Cannot auto-generate special bonds before simulation box is defined UNDOCUMENTED diff --git a/src/neighbor.cpp b/src/neighbor.cpp index 4eabdcc7b4..58737b815d 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -1296,7 +1296,7 @@ void Neighbor::init_topology() { int i,m; - if (!atom->molecular) return; + if (atom->molecular == Atom::ATOMIC) return; // set flags that determine which topology neighbor classes to use // these settings could change from run to run, depending on fixes defined @@ -1801,7 +1801,7 @@ int Neighbor::choose_pair(NeighRequest *rq) if (molecular != Atom::ATOMIC) { if (mask & NP_ATOMONLY) continue; - } else if (!molecular) { + } else if (molecular == Atom::ATOMIC) { if (mask & NP_MOLONLY) continue; } @@ -2097,7 +2097,7 @@ void Neighbor::build(int topoflag) // build topology lists for bonds/angles/etc - if (atom->molecular && topoflag) build_topology(); + if ((atom->molecular != Atom::ATOMIC) && topoflag) build_topology(); } /* ---------------------------------------------------------------------- diff --git a/src/omp_compat.h b/src/omp_compat.h index d80d6f6f7f..366dd9371c 100644 --- a/src/omp_compat.h +++ b/src/omp_compat.h @@ -25,11 +25,30 @@ // so this is what LAMMPS primarily uses. For those compilers // that strictly implement OpenMP 4.0 (such as GCC 9.0 and later // or Clang 10.0 and later), we give up default(none). -#if LAMMPS_OMP_COMPAT == 4 -# define LMP_SHARED(...) -# define LMP_DEFAULT_NONE default(shared) -#else -# define LMP_SHARED(...) shared(__VA_ARGS__) -# define LMP_DEFAULT_NONE default(none) + +// autodetect OpenMP compatibility if not explicitly set + +#ifndef LAMMPS_OMP_COMPAT +# if defined(__INTEL_COMPILER) +# if __INTEL_COMPILER > 18 +# define LAMMPS_OMP_COMPAT 4 +# endif +# elif defined(__clang__) +# if __clang_major__ >= 10 +# define LAMMPS_OMP_COMPAT 4 +# endif +# elif defined(__GNUC__) +# if __GNUC__ >= 9 +# define LAMMPS_OMP_COMPAT 4 +# endif +# endif +#endif + +#if LAMMPS_OMP_COMPAT == 4 +# define LMP_SHARED(...) +# define LMP_DEFAULT_NONE default(shared) +#else +# define LMP_SHARED(...) shared(__VA_ARGS__) +# define LMP_DEFAULT_NONE default(none) #endif diff --git a/src/pair_coul_streitz.cpp b/src/pair_coul_streitz.cpp index 101aaf36a3..6fb7d63a86 100644 --- a/src/pair_coul_streitz.cpp +++ b/src/pair_coul_streitz.cpp @@ -280,7 +280,7 @@ void PairCoulStreitz::read_file(char *file) params[nparams].zeta = values.next_double(); params[nparams].zcore = values.next_double(); - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/pair_table.cpp b/src/pair_table.cpp index a92d2e4911..f7933f5d9a 100644 --- a/src/pair_table.cpp +++ b/src/pair_table.cpp @@ -402,7 +402,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 &e) { ++cerror; } @@ -571,7 +571,7 @@ void PairTable::param_extract(Table *tb, char *line) error->one(FLERR,fmt::format("Invalid keyword {} in pair table parameters", word).c_str()); } } - } catch (TokenizerException & e) { + } catch (TokenizerException &e) { error->one(FLERR, e.what()); } diff --git a/src/pointers.h b/src/pointers.h index 04f682f045..5dc1a63078 100644 --- a/src/pointers.h +++ b/src/pointers.h @@ -48,6 +48,20 @@ enum ExecutionSpace{Host,Device}; template class MyPoolChunk; template class MyPage; +/** \class LAMMPS_NS::Pointers + * \brief Base class for LAMMPS features + * + * The Pointers class contains references to many of the pointers + * and members of the LAMMPS_NS::LAMMPS class. Derived classes thus + * gain access to the constituent class instances in the LAMMPS + * composite class and thus to the core functionality of LAMMPS. + * + * This kind of construct is needed, since the LAMMPS constructor + * should only be run once per LAMMPS instance and thus classes + * cannot be derived from LAMMPS itself. The Pointers class + * constructor instead only initializes C++ references to component + * pointer in the LAMMPS class. */ + class Pointers { public: Pointers(LAMMPS *ptr) : diff --git a/src/potential_file_reader.cpp b/src/potential_file_reader.cpp index a71d7944d6..6b41a35f0a 100644 --- a/src/potential_file_reader.cpp +++ b/src/potential_file_reader.cpp @@ -30,13 +30,17 @@ using namespace LAMMPS_NS; * The value of the class member variable *ignore_comments* controls * whether any text following the pound sign (#) should be ignored (true) * or not (false). Default: true, i.e. ignore. +\verbatim embed:rst + +*See also* + :cpp:class:`TextFileReader` + +\endverbatim * * \param lmp Pointer to LAMMPS instance * \param filename Name of file to be read * \param potential_name Name of potential style for error messages - * \param auto_convert Bitmask of supported unit conversions - * - * \sa TextFileReader */ + * \param auto_convert Bitmask of supported unit conversions */ PotentialFileReader::PotentialFileReader(LAMMPS *lmp, const std::string &filename, @@ -57,7 +61,7 @@ PotentialFileReader::PotentialFileReader(LAMMPS *lmp, if(!reader) { error->one(FLERR, fmt::format("cannot open {} potential file {}", potential_name, filename)); } - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } } @@ -80,7 +84,7 @@ void PotentialFileReader::ignore_comments(bool value) { void PotentialFileReader::skip_line() { try { reader->skip_line(); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } } @@ -99,7 +103,7 @@ void PotentialFileReader::skip_line() { char *PotentialFileReader::next_line(int nparams) { try { return reader->next_line(nparams); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } return nullptr; @@ -117,7 +121,7 @@ char *PotentialFileReader::next_line(int nparams) { void PotentialFileReader::next_dvector(double * list, int n) { try { return reader->next_dvector(list, n); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } } @@ -132,10 +136,10 @@ void PotentialFileReader::next_dvector(double * list, int n) { * \param separators String with list of separators. * \return ValueTokenizer object for read in text */ -ValueTokenizer PotentialFileReader::next_values(int nparams, const std::string & separators) { +ValueTokenizer PotentialFileReader::next_values(int nparams, const std::string &separators) { try { return reader->next_values(nparams, separators); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } return ValueTokenizer(""); @@ -149,7 +153,7 @@ double PotentialFileReader::next_double() { try { char * line = reader->next_line(1); return ValueTokenizer(line).next_double(); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } return 0.0; @@ -163,7 +167,7 @@ int PotentialFileReader::next_int() { try { char * line = reader->next_line(1); return ValueTokenizer(line).next_int(); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } return 0; @@ -177,7 +181,7 @@ tagint PotentialFileReader::next_tagint() { try { char * line = reader->next_line(1); return ValueTokenizer(line).next_tagint(); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } return 0; @@ -191,7 +195,7 @@ bigint PotentialFileReader::next_bigint() { try { char * line = reader->next_line(1); return ValueTokenizer(line).next_bigint(); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } return 0; @@ -205,7 +209,7 @@ std::string PotentialFileReader::next_string() { try { char * line = reader->next_line(1); return ValueTokenizer(line).next_string(); - } catch (FileReaderException & e) { + } catch (FileReaderException &e) { error->one(FLERR, e.what()); } return ""; @@ -213,9 +217,15 @@ std::string PotentialFileReader::next_string() { /** Look up and open the potential file * +\verbatim embed:rst + +*See also* + :cpp:func:`utils::open_potential`, + :cpp:class:`TextFileReader` + +\endverbatim * \param path Path of the potential file to open - * \return Pointer to TextFileReader object created - * \sa TextFileReader */ + * \return Pointer to TextFileReader object created */ TextFileReader *PotentialFileReader::open_potential(const std::string &path) { std::string filepath = utils::get_potential_file_path(path); diff --git a/src/read_restart.cpp b/src/read_restart.cpp index ff7718f0f9..de1a089ebe 100644 --- a/src/read_restart.cpp +++ b/src/read_restart.cpp @@ -621,7 +621,7 @@ void ReadRestart::header() char *version = read_string(); if (me == 0) utils::logmesg(lmp,fmt::format(" restart file = {}, LAMMPS = {}\n", - version,universe->version)); + version,lmp->version)); delete [] version; // we have no forward compatibility, thus exit with error diff --git a/src/reader_native.cpp b/src/reader_native.cpp index 11241047a1..93a62e6cbf 100644 --- a/src/reader_native.cpp +++ b/src/reader_native.cpp @@ -334,7 +334,7 @@ void ReaderNative::read_atoms(int n, int nfield, double **fields) return index of match or -1 if no match ------------------------------------------------------------------------- */ -int ReaderNative::find_label(const std::string & label, const std::map & labels) +int ReaderNative::find_label(const std::string &label, const std::map & labels) { auto it = labels.find(label); if (it != labels.end()) { diff --git a/src/reader_native.h b/src/reader_native.h index d1c8433016..f34bd094ab 100644 --- a/src/reader_native.h +++ b/src/reader_native.h @@ -45,7 +45,7 @@ private: int nwords; // # of per-atom columns in dump file int *fieldindex; // - int find_label(const std::string & label, const std::map & labels); + int find_label(const std::string &label, const std::map & labels); void read_lines(int); }; diff --git a/src/reset_mol_ids.cpp b/src/reset_mol_ids.cpp index 10337fd18f..970ac6beb4 100644 --- a/src/reset_mol_ids.cpp +++ b/src/reset_mol_ids.cpp @@ -64,7 +64,7 @@ void ResetMolIDs::command(int narg, char **arg) error->all(FLERR,"Reset_mol_ids command before simulation box is defined"); if (atom->tag_enable == 0) error->all(FLERR,"Cannot use reset_mol_ids unless atoms have IDs"); - if (atom->molecular != 1) + if (atom->molecular != Atom::MOLECULAR) error->all(FLERR,"Can only use reset_mol_ids on molecular systems"); // process args diff --git a/src/set.cpp b/src/set.cpp index bda5c51248..253e9118d3 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -1351,17 +1351,10 @@ void Set::topology(int keyword) /* ---------------------------------------------------------------------- */ -void Set::varparse(char *name, int m) +void Set::varparse(const char *name, int m) { varflag = 1; - - name = &name[2]; - int n = strlen(name) + 1; - char *str = new char[n]; - strcpy(str,name); - - int ivar = input->variable->find(str); - delete [] str; + int ivar = input->variable->find(name+2); if (ivar < 0) error->all(FLERR,"Variable name for set command does not exist"); diff --git a/src/set.h b/src/set.h index 6788849677..29f1ea526e 100644 --- a/src/set.h +++ b/src/set.h @@ -48,7 +48,7 @@ class Set : protected Pointers { void set(int); void setrandom(int); void topology(int); - void varparse(char *, int); + void varparse(const char *, int); }; } diff --git a/src/table_file_reader.cpp b/src/table_file_reader.cpp index 50843c119e..9006b44af9 100644 --- a/src/table_file_reader.cpp +++ b/src/table_file_reader.cpp @@ -33,7 +33,7 @@ TableFileReader::TableFileReader(LAMMPS *lmp, TableFileReader::~TableFileReader() { } -char *TableFileReader::find_section_start(const std::string & keyword) { +char *TableFileReader::find_section_start(const std::string &keyword) { char *line = nullptr; while ((line = reader->next_line())) { ValueTokenizer values(line); diff --git a/src/text_file_reader.cpp b/src/text_file_reader.cpp index 3c63bba5fb..a1892edfad 100644 --- a/src/text_file_reader.cpp +++ b/src/text_file_reader.cpp @@ -30,11 +30,15 @@ using namespace LAMMPS_NS; * The value of the class member variable *ignore_comments* controls * whether any text following the pound sign (#) should be ignored (true) * or not (false). Default: true, i.e. ignore. +\verbatim embed:rst + +*See also* + :cpp:class:`TextFileReader` + +\endverbatim * * \param filename Name of file to be read - * \param filetype Description of file type for error messages - * - * \sa PotentialFileReader */ + * \param filetype Description of file type for error messages */ TextFileReader::TextFileReader(const std::string &filename, const std::string &filetype) : filename(filename), filetype(filetype), ignore_comments(true) @@ -160,6 +164,6 @@ void TextFileReader::next_dvector(double * list, int n) { * \param separators String with list of separators. * \return ValueTokenizer object for read in text */ -ValueTokenizer TextFileReader::next_values(int nparams, const std::string & separators) { +ValueTokenizer TextFileReader::next_values(int nparams, const std::string &separators) { return ValueTokenizer(next_line(nparams), separators); } diff --git a/src/text_file_reader.h b/src/text_file_reader.h index 65af0a08d9..0b90304911 100644 --- a/src/text_file_reader.h +++ b/src/text_file_reader.h @@ -41,13 +41,13 @@ namespace LAMMPS_NS char * next_line(int nparams = 0); void next_dvector(double * list, int n); - ValueTokenizer next_values(int nparams, const std::string & separators = TOKENIZER_DEFAULT_SEPARATORS); + ValueTokenizer next_values(int nparams, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS); }; class FileReaderException : public std::exception { std::string message; public: - FileReaderException(const std::string & msg) : message(msg) { + FileReaderException(const std::string &msg) : message(msg) { } ~FileReaderException() throw() { @@ -60,7 +60,7 @@ namespace LAMMPS_NS class EOFException : public FileReaderException { public: - EOFException(const std::string & msg) : FileReaderException(msg) { + EOFException(const std::string &msg) : FileReaderException(msg) { } }; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 3b172181a2..725f6f1b61 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -24,7 +24,7 @@ using namespace LAMMPS_NS; -TokenizerException::TokenizerException(const std::string & msg, const std::string & token){ +TokenizerException::TokenizerException(const std::string &msg, const std::string &token){ if(token.empty()) { message = msg; } else { @@ -37,18 +37,23 @@ TokenizerException::TokenizerException(const std::string & msg, const std::strin * This tokenizer will break down a string into sub-strings (i.e words) * separated by the given separator characters. * - * \param str string to be processed - * \param separators string with separator characters (default: " \t\r\n\f") - * - * \sa ValueTokenizer TokenizerException */ +\verbatim embed:rst -Tokenizer::Tokenizer(const std::string & str, const std::string & separators) : +*See also* + :cpp:class:`ValueTokenizer`, :cpp:func:`utils::split_words` + +\endverbatim + * + * \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) { reset(); } -Tokenizer::Tokenizer(const Tokenizer & rhs) : +Tokenizer::Tokenizer(const Tokenizer &rhs) : text(rhs.text), separators(rhs.separators), ntokens(rhs.ntokens) { reset(); @@ -70,7 +75,7 @@ void Tokenizer::reset() { * * \param str string to be searched for * \return true if string was found, false if not */ -bool Tokenizer::contains(const std::string & str) const { +bool Tokenizer::contains(const std::string &str) const { return text.find(str) != std::string::npos; } @@ -152,18 +157,25 @@ std::vector Tokenizer::as_vector() { /*! Class for reading text with numbers * +\verbatim embed:rst + +*See also* + :cpp:class:`Tokenizer` + +\endverbatim + * * \param str String to be processed * \param separators String with separator characters (default: " \t\r\n\f") * - * \sa Tokenizer InvalidIntegerException InvalidFloatException */ + * \see Tokenizer InvalidIntegerException InvalidFloatException */ -ValueTokenizer::ValueTokenizer(const std::string & str, const std::string & separators) : tokens(str, separators) { +ValueTokenizer::ValueTokenizer(const std::string &str, const std::string &separators) : tokens(str, separators) { } -ValueTokenizer::ValueTokenizer(const ValueTokenizer & rhs) : tokens(rhs.tokens) { +ValueTokenizer::ValueTokenizer(const ValueTokenizer &rhs) : tokens(rhs.tokens) { } -ValueTokenizer::ValueTokenizer(ValueTokenizer && rhs) : tokens(std::move(rhs.tokens)) { +ValueTokenizer::ValueTokenizer(ValueTokenizer &&rhs) : tokens(std::move(rhs.tokens)) { } /*! Indicate whether more tokens are available @@ -177,7 +189,7 @@ bool ValueTokenizer::has_next() const { * * \param value string with value to be searched for * \return true if string was found, false if not */ -bool ValueTokenizer::contains(const std::string & value) const { +bool ValueTokenizer::contains(const std::string &value) const { return tokens.contains(value); } diff --git a/src/universe.cpp b/src/universe.cpp index ecdd5aa04d..38d2d48990 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -30,11 +30,6 @@ using namespace LAMMPS_NS; Universe::Universe(LAMMPS *lmp, MPI_Comm communicator) : Pointers(lmp) { - version = (const char *) LAMMPS_VERSION; - auto tmp_ver = new char[10]; - snprintf(tmp_ver,10,"%08d",utils::date2num(version)); - num_ver = tmp_ver; - uworld = uorig = communicator; MPI_Comm_rank(uworld,&me); MPI_Comm_size(uworld,&nprocs); @@ -59,7 +54,6 @@ Universe::~Universe() memory->destroy(procs_per_world); memory->destroy(root_proc); memory->destroy(uni2orig); - delete [] num_ver; } /* ---------------------------------------------------------------------- diff --git a/src/universe.h b/src/universe.h index fd6655c749..e37f07930b 100644 --- a/src/universe.h +++ b/src/universe.h @@ -20,10 +20,6 @@ namespace LAMMPS_NS { class Universe : protected Pointers { public: - const char *version; // LAMMPS version string = date - const char *num_ver; // numeric version id derived from version that - // can be used for string or numeric comparisons - MPI_Comm uworld; // communicator for entire universe int me,nprocs; // my place in universe diff --git a/src/utils.h b/src/utils.h index 840ddf549b..7515f1f21b 100644 --- a/src/utils.h +++ b/src/utils.h @@ -247,6 +247,13 @@ namespace LAMMPS_NS { * command lines and similar text and not for time critical processing. * Use a tokenizer class for that. * +\verbatim embed:rst + +*See also* + :cpp:class:`Tokenizer`, :cpp:class:`ValueTokenizer` + +\endverbatim + * * \param text string that should be split * \return STL vector with the words */ diff --git a/src/variable.cpp b/src/variable.cpp index bc47d451d1..16677ef5ae 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -885,7 +885,7 @@ char *Variable::retrieve(const char *name) if (which[ivar] >= num[ivar]) return nullptr; if (eval_in_progress[ivar]) - print_var_error(FLERR,"Variable has a circular dependency",ivar); + print_var_error(FLERR,"has a circular dependency",ivar); eval_in_progress[ivar] = 1; @@ -931,8 +931,8 @@ char *Variable::retrieve(const char *name) } else if (style[ivar] == PYTHON) { int ifunc = python->variable_match(data[ivar][0],name,0); if (ifunc < 0) - error->all(FLERR,fmt::format("Python variable '{}' does not match " - "Python function", name)); + error->all(FLERR,fmt::format("Python variable {} does not match " + "Python function {}", name, data[ivar][0])); python->invoke_function(ifunc,data[ivar][1]); str = data[ivar][1]; // if Python func returns a string longer than VALUELENGTH @@ -960,7 +960,7 @@ char *Variable::retrieve(const char *name) double Variable::compute_equal(int ivar) { if (eval_in_progress[ivar]) - print_var_error(FLERR,"Variable has a circular dependency",ivar); + print_var_error(FLERR,"has a circular dependency",ivar); eval_in_progress[ivar] = 1; @@ -970,7 +970,8 @@ double Variable::compute_equal(int ivar) else if (style[ivar] == PYTHON) { int ifunc = python->find(data[ivar][0]); if (ifunc < 0) - print_var_error(FLERR,"Python variable has no function",ivar); + print_var_error(FLERR,fmt::format("cannot find python function {}", + data[ivar][0]),ivar); python->invoke_function(ifunc,data[ivar][1]); value = atof(data[ivar][1]); } @@ -1004,7 +1005,7 @@ void Variable::compute_atom(int ivar, int igroup, double *vstore; if (eval_in_progress[ivar]) - print_var_error(FLERR,"Variable has a circular dependency",ivar); + print_var_error(FLERR,"has a circular dependency",ivar); eval_in_progress[ivar] = 1; @@ -1080,7 +1081,7 @@ int Variable::compute_vector(int ivar, double **result) } if (eval_in_progress[ivar]) - print_var_error(FLERR,"Variable has a circular dependency",ivar); + print_var_error(FLERR,"has a circular dependency",ivar); eval_in_progress[ivar] = 1; @@ -1899,10 +1900,10 @@ double Variable::evaluate(char *str, Tree **tree, int ivar) int ivar = find(word+2); if (ivar < 0) - print_var_error(FLERR,"Invalid variable reference " - "in variable formula",ivar); + print_var_error(FLERR,fmt::format("Invalid variable reference " + "{} in variable formula",word),ivar); if (eval_in_progress[ivar]) - print_var_error(FLERR,"Variable has circular dependency",ivar); + print_var_error(FLERR,"has a circular dependency",ivar); // parse zero or one trailing brackets // point i beyond last bracket @@ -4217,7 +4218,7 @@ int Variable::special_function(char *word, char *contents, Tree **tree, print_var_error(FLERR,"Mis-matched special function variable " "in variable formula",ivar); if (eval_in_progress[ivar]) - print_var_error(FLERR,"Variable has circular dependency",ivar); + print_var_error(FLERR,"has a circular dependency",ivar); double *vec; nvec = compute_vector(ivar,&vec); @@ -4713,7 +4714,7 @@ int Variable::is_constant(char *word) double Variable::constant(char *word) { if (strcmp(word,"PI") == 0) return MY_PI; - if (strcmp(word,"version") == 0) return atof(universe->num_ver); + if (strcmp(word,"version") == 0) return lmp->num_ver; if (strcmp(word,"yes") == 0) return 1.0; if (strcmp(word,"no") == 0) return 0.0; if (strcmp(word,"on") == 0) return 1.0; diff --git a/src/version.h b/src/version.h index 1803ea012d..84d15a17dd 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define LAMMPS_VERSION "24 Aug 2020" +#define LAMMPS_VERSION "18 Sep 2020" diff --git a/src/write_coeff.cpp b/src/write_coeff.cpp index 3e247f19ce..f6d1af9e01 100644 --- a/src/write_coeff.cpp +++ b/src/write_coeff.cpp @@ -95,7 +95,7 @@ void WriteCoeff::command(int narg, char **arg) file+4, utils::getsyserror())); fprintf(two,"# LAMMPS coeff file via write_coeff, version %s\n", - universe->version); + lmp->version); while(1) { int coeff_mode = REGULAR_MODE; diff --git a/src/write_data.cpp b/src/write_data.cpp index d0490b1920..6b4c5ef209 100644 --- a/src/write_data.cpp +++ b/src/write_data.cpp @@ -229,7 +229,7 @@ void WriteData::write(const std::string &file) void WriteData::header() { fmt::print(fp,"LAMMPS data file via write_data, version {}, " - "timestep = {}\n\n",universe->version,update->ntimestep); + "timestep = {}\n\n",lmp->version,update->ntimestep); fmt::print(fp,"{} atoms\n{} atom types\n",atom->natoms,atom->ntypes); diff --git a/src/write_restart.cpp b/src/write_restart.cpp index 09fe85fd1a..6f2b393603 100644 --- a/src/write_restart.cpp +++ b/src/write_restart.cpp @@ -424,7 +424,7 @@ void WriteRestart::write(std::string file) void WriteRestart::header() { - write_string(VERSION,universe->version); + write_string(VERSION,lmp->version); write_int(SMALLINT,sizeof(smallint)); write_int(IMAGEINT,sizeof(imageint)); write_int(TAGINT,sizeof(tagint)); diff --git a/tools/lmp2arc/src/Makefile b/tools/lmp2arc/src/Makefile index a701e8f7a2..9f7c0f95ae 100644 --- a/tools/lmp2arc/src/Makefile +++ b/tools/lmp2arc/src/Makefile @@ -1,8 +1,8 @@ - +CC=gcc OBJS = lmp2arc.o ReadCarFile.o ProcessPosFile01.o ProcessPosFile05.o unwrap_molecules.o WriteArcFrame.o lmp2arc.exe: $(OBJS) - gcc -o lmp2arc.exe $(OBJS) + $(CC) -o lmp2arc.exe $(OBJS) lmp2arc.o: lmp2arc.c lmp2.h ReadCarFile.o: ReadCarFile.c lmp2.h @@ -12,7 +12,7 @@ WriteArcFrame.o: WriteArcFrame.c lmp2.h unwrap_molecules.o: unwrap_molecules.c lmp2.h .c.o: - gcc -O2 -c $< + $(CC) -O2 -c $< clean: rm lmp2arc.exe *.o diff --git a/tools/lmp2arc/src/ProcessPosFile01.c b/tools/lmp2arc/src/ProcessPosFile01.c index 9926baf91e..0cb5c3b4de 100644 --- a/tools/lmp2arc/src/ProcessPosFile01.c +++ b/tools/lmp2arc/src/ProcessPosFile01.c @@ -149,7 +149,7 @@ void ProcessPosFile01(int num_posfiles,char *posnames[],struct Sys *sysinfo,FILE } /* end while over LINES*/ - close(PosFile); + fclose(PosFile); } /* end for loop over POS FILES */ diff --git a/tools/lmp2arc/src/ProcessPosFile05.c b/tools/lmp2arc/src/ProcessPosFile05.c index 4d8433bb3f..9c7c72b6cb 100644 --- a/tools/lmp2arc/src/ProcessPosFile05.c +++ b/tools/lmp2arc/src/ProcessPosFile05.c @@ -147,7 +147,7 @@ fprintf(stderr,"HERE 1\n"); } /* end while over LINES*/ - close(PosFile); + fclose(PosFile); } /* end for loop over POS FILES */ diff --git a/tools/singularity/README.md b/tools/singularity/README.md index 7374beb898..bcc13fbaa1 100644 --- a/tools/singularity/README.md +++ b/tools/singularity/README.md @@ -52,8 +52,12 @@ make | 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 10.2 | -| ubuntu18.04_nvidia.def | Ubuntu 18.04LTS with Nvidia CUDA 10.2 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/centos8.def b/tools/singularity/centos8.def index eeead43cc8..c9d1b3b7ba 100644 --- a/tools/singularity/centos8.def +++ b/tools/singularity/centos8.def @@ -6,11 +6,11 @@ From: centos:8 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 gdb valgrind libubsan libasan libtsan \ + 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 \ + enchant python3-virtualenv doxygen diffutils latexmk \ texlive-latex-fonts texlive-pslatex texlive-collection-latexrecommended \ texlive-latex texlive-latexconfig doxygen-latex texlive-collection-latex \ texlive-latex-bin texlive-lualatex-math texlive-fncychap texlive-tabulary \ diff --git a/tools/singularity/fedora32_mingw.def b/tools/singularity/fedora32_mingw.def index fa0227c4e3..68ad7b2a59 100644 --- a/tools/singularity/fedora32_mingw.def +++ b/tools/singularity/fedora32_mingw.def @@ -30,12 +30,12 @@ From: fedora:32 mingw32-expat mingw64-expat \ mingw64-expat-static mingw32-expat-static \ mingw32-sqlite-static mingw64-sqlite-static \ - enchant python3-virtualenv doxygen \ + enchant python3-virtualenv doxygen latexmk \ texlive-latex-fonts texlive-pslatex texlive-collection-latexrecommended \ texlive-latex texlive-latexconfig doxygen-latex texlive-collection-latex \ texlive-latex-bin texlive-lualatex-math texlive-fncychap texlive-tabulary \ texlive-framed texlive-wrapfig texlive-upquote texlive-capt-of \ - texlive-needspace texlive-titlesec texlive-anysize texlive-dvipng \ + texlive-needspace texlive-titlesec texlive-anysize texlive-dvipng texlive-xindy \ blas-devel lapack-devel libyaml-devel openkim-models kim-api-devel \ zstd libzstd-devel dnf clean all diff --git a/tools/singularity/ubuntu18.04.def b/tools/singularity/ubuntu18.04.def index 921000c326..54c750955b 100644 --- a/tools/singularity/ubuntu18.04.def +++ b/tools/singularity/ubuntu18.04.def @@ -64,6 +64,8 @@ From: ubuntu:18.04 texlive-publishers \ texlive-science \ dvipng \ + latexmk \ + xindy \ vim-nox \ virtualenv \ voro++-dev \ diff --git a/tools/singularity/ubuntu20.04.def b/tools/singularity/ubuntu20.04.def index a5b1a68027..376c253000 100644 --- a/tools/singularity/ubuntu20.04.def +++ b/tools/singularity/ubuntu20.04.def @@ -60,6 +60,8 @@ From: ubuntu:20.04 texlive-publishers \ texlive-science \ dvipng \ + latexmk \ + xindy \ vim-nox \ virtualenv \ voro++-dev \ diff --git a/unittest/c-library/test_library_properties.cpp b/unittest/c-library/test_library_properties.cpp index eb0e1a7df6..a63dac9b01 100644 --- a/unittest/c-library/test_library_properties.cpp +++ b/unittest/c-library/test_library_properties.cpp @@ -16,6 +16,7 @@ using ::testing::HasSubstr; using ::testing::StartsWith; using ::testing::StrEq; +using ::LAMMPS_NS::tagint; class LibraryProperties : public ::testing::Test { protected: @@ -53,13 +54,13 @@ protected: TEST_F(LibraryProperties, version) { - EXPECT_GE(20200824, lammps_version(lmp)); + EXPECT_LT(20200917, lammps_version(lmp)); }; TEST_F(LibraryProperties, memory_usage) { double meminfo[3]; - lammps_memory_usage(lmp,meminfo); + lammps_memory_usage(lmp, meminfo); EXPECT_GT(meminfo[0], 0.0); #if defined(__linux__) || defined(_WIN32) EXPECT_GT(meminfo[1], 0.0); @@ -251,4 +252,89 @@ TEST_F(LibraryProperties, global) EXPECT_EQ((*b_ptr), 2); d_ptr = (double *)lammps_extract_global(lmp, "dt"); EXPECT_DOUBLE_EQ((*d_ptr), 0.1); + int dtype = lammps_extract_global_datatype(lmp, "dt"); + EXPECT_EQ(dtype, LAMMPS_DOUBLE); }; + +class AtomProperties : public ::testing::Test { +protected: + void *lmp; + + AtomProperties(){}; + ~AtomProperties() override{}; + + void SetUp() override + { + const char *args[] = {"LAMMPS_test", "-log", "none", "-echo", "screen", "-nocite"}; + + char **argv = (char **)args; + int argc = sizeof(args) / sizeof(char *); + + ::testing::internal::CaptureStdout(); + lmp = lammps_open_no_mpi(argc, argv, NULL); + std::string output = ::testing::internal::GetCapturedStdout(); + if (verbose) std::cout << output; + EXPECT_THAT(output, StartsWith("LAMMPS (")); + ::testing::internal::CaptureStdout(); + lammps_command(lmp, "region box block 0 2 0 2 0 2"); + lammps_command(lmp, "create_box 1 box"); + lammps_command(lmp, "mass 1 3.0"); + lammps_command(lmp, "create_atoms 1 single 1.0 1.0 1.5"); + lammps_command(lmp, "create_atoms 1 single 0.2 0.1 0.1"); + output = ::testing::internal::GetCapturedStdout(); + if (verbose) std::cout << output; + } + void TearDown() override + { + ::testing::internal::CaptureStdout(); + lammps_close(lmp); + std::string output = ::testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, HasSubstr("Total wall time:")); + if (verbose) std::cout << output; + lmp = nullptr; + } +}; + +TEST_F(AtomProperties, invalid) +{ + ASSERT_EQ(lammps_extract_atom(lmp, "UNKNOWN"), nullptr); +} + +TEST_F(AtomProperties, mass) +{ + EXPECT_EQ(lammps_extract_atom_datatype(lmp, "mass"), LAMMPS_DOUBLE); + double *mass = (double *)lammps_extract_atom(lmp, "mass"); + ASSERT_NE(mass, nullptr); + ASSERT_DOUBLE_EQ(mass[1], 3.0); +} + +TEST_F(AtomProperties, id) +{ + EXPECT_EQ(lammps_extract_atom_datatype(lmp, "id"), LAMMPS_TAGINT); + tagint *id = (tagint *)lammps_extract_atom(lmp, "id"); + ASSERT_NE(id, nullptr); + ASSERT_EQ(id[0], 1); + ASSERT_EQ(id[1], 2); +} + +TEST_F(AtomProperties, type) +{ + EXPECT_EQ(lammps_extract_atom_datatype(lmp, "type"), LAMMPS_INT); + int *type = (int *)lammps_extract_atom(lmp, "type"); + ASSERT_NE(type, nullptr); + ASSERT_EQ(type[0], 1); + ASSERT_EQ(type[1], 1); +} + +TEST_F(AtomProperties, position) +{ + EXPECT_EQ(lammps_extract_atom_datatype(lmp, "x"), LAMMPS_DOUBLE_2D); + double **x = (double **)lammps_extract_atom(lmp, "x"); + ASSERT_NE(x, nullptr); + EXPECT_DOUBLE_EQ(x[0][0], 1.0); + EXPECT_DOUBLE_EQ(x[0][1], 1.0); + EXPECT_DOUBLE_EQ(x[0][2], 1.5); + EXPECT_DOUBLE_EQ(x[1][0], 0.2); + EXPECT_DOUBLE_EQ(x[1][1], 0.1); + EXPECT_DOUBLE_EQ(x[1][2], 0.1); +} diff --git a/unittest/force-styles/test_angle_style.cpp b/unittest/force-styles/test_angle_style.cpp index 0a5a7af238..026dddc5d8 100644 --- a/unittest/force-styles/test_angle_style.cpp +++ b/unittest/force-styles/test_angle_style.cpp @@ -236,7 +236,7 @@ void generate_yaml_file(const char *outfile, const TestConfig &config) YamlWriter writer(outfile); // lammps_version - writer.emit("lammps_version", lmp->universe->version); + writer.emit("lammps_version", lmp->version); // date_generated std::time_t now = time(NULL); diff --git a/unittest/force-styles/test_bond_style.cpp b/unittest/force-styles/test_bond_style.cpp index 7faa0394d7..269ea5beae 100644 --- a/unittest/force-styles/test_bond_style.cpp +++ b/unittest/force-styles/test_bond_style.cpp @@ -236,7 +236,7 @@ void generate_yaml_file(const char *outfile, const TestConfig &config) YamlWriter writer(outfile); // lammps_version - writer.emit("lammps_version", lmp->universe->version); + writer.emit("lammps_version", lmp->version); // date_generated std::time_t now = time(NULL); diff --git a/unittest/force-styles/test_fix_timestep.cpp b/unittest/force-styles/test_fix_timestep.cpp index e5920199f9..e6d664b857 100644 --- a/unittest/force-styles/test_fix_timestep.cpp +++ b/unittest/force-styles/test_fix_timestep.cpp @@ -194,7 +194,7 @@ void generate_yaml_file(const char *outfile, const TestConfig &config) YamlWriter writer(outfile); // lammps_version - writer.emit("lammps_version", lmp->universe->version); + writer.emit("lammps_version", lmp->version); // date_generated std::time_t now = time(NULL); diff --git a/unittest/force-styles/test_pair_style.cpp b/unittest/force-styles/test_pair_style.cpp index 707568dcb7..acd7c16c6c 100644 --- a/unittest/force-styles/test_pair_style.cpp +++ b/unittest/force-styles/test_pair_style.cpp @@ -239,7 +239,7 @@ void generate_yaml_file(const char *outfile, const TestConfig &config) YamlWriter writer(outfile); // lammps_version - writer.emit("lammps_version", lmp->universe->version); + writer.emit("lammps_version", lmp->version); // date_generated std::time_t now = time(NULL); diff --git a/unittest/force-styles/tests/angle-charmm.yaml b/unittest/force-styles/tests/angle-charmm.yaml index f330ebc950..3d0dc17371 100644 --- a/unittest/force-styles/tests/angle-charmm.yaml +++ b/unittest/force-styles/tests/angle-charmm.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:34 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full angle charmm diff --git a/unittest/force-styles/tests/atomic-pair-edip.yaml b/unittest/force-styles/tests/atomic-pair-edip.yaml index 5c17154abf..b1a0ae521e 100644 --- a/unittest/force-styles/tests/atomic-pair-edip.yaml +++ b/unittest/force-styles/tests/atomic-pair-edip.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:22 202 -epsilon: 2e-14 +epsilon: 7.5e-13 prerequisites: ! | pair edip pre_commands: ! | diff --git a/unittest/force-styles/tests/atomic-pair-meam_c.yaml b/unittest/force-styles/tests/atomic-pair-meam_c.yaml index 976bd6a08b..308f734ab0 100644 --- a/unittest/force-styles/tests/atomic-pair-meam_c.yaml +++ b/unittest/force-styles/tests/atomic-pair-meam_c.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:23 202 -epsilon: 1e-14 +epsilon: 5e-13 prerequisites: ! | pair meam/c pre_commands: ! | diff --git a/unittest/force-styles/tests/atomic-pair-reax_c.yaml b/unittest/force-styles/tests/atomic-pair-reax_c.yaml index 4f7a6b5287..ed8c8fcb8f 100644 --- a/unittest/force-styles/tests/atomic-pair-reax_c.yaml +++ b/unittest/force-styles/tests/atomic-pair-reax_c.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:24 202 -epsilon: 7.5e-12 +epsilon: 1e-11 prerequisites: ! | pair reax/c fix qeq/reax diff --git a/unittest/force-styles/tests/fix-timestep-addforce_const.yaml b/unittest/force-styles/tests/fix-timestep-addforce_const.yaml index bc20d66151..13f4644815 100644 --- a/unittest/force-styles/tests/fix-timestep-addforce_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-addforce_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:39 202 -epsilon: 2e-13 +epsilon: 5e-12 prerequisites: ! | atom full fix addforce diff --git a/unittest/force-styles/tests/fix-timestep-addforce_variable.yaml b/unittest/force-styles/tests/fix-timestep-addforce_variable.yaml index 50b9de0c46..112b6d89c1 100644 --- a/unittest/force-styles/tests/fix-timestep-addforce_variable.yaml +++ b/unittest/force-styles/tests/fix-timestep-addforce_variable.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:39 202 -epsilon: 2e-13 +epsilon: 5e-12 prerequisites: ! | atom full fix addforce diff --git a/unittest/force-styles/tests/fix-timestep-aveforce_const.yaml b/unittest/force-styles/tests/fix-timestep-aveforce_const.yaml index 5495e5191d..bb8ec69e3e 100644 --- a/unittest/force-styles/tests/fix-timestep-aveforce_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-aveforce_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 2e-13 +epsilon: 5e-12 prerequisites: ! | atom full fix aveforce diff --git a/unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml b/unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml index d374c73a92..3f7832acfe 100644 --- a/unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml +++ b/unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 2e-13 +epsilon: 2e-11 prerequisites: ! | atom full fix aveforce diff --git a/unittest/force-styles/tests/fix-timestep-lineforce.yaml b/unittest/force-styles/tests/fix-timestep-lineforce.yaml index 31ce0a5ef3..8acfe82ce3 100644 --- a/unittest/force-styles/tests/fix-timestep-lineforce.yaml +++ b/unittest/force-styles/tests/fix-timestep-lineforce.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 2e-13 +epsilon: 5e-12 prerequisites: ! | atom full fix lineforce diff --git a/unittest/force-styles/tests/fix-timestep-momentum.yaml b/unittest/force-styles/tests/fix-timestep-momentum.yaml index afaf4a3e29..eb5f4e0235 100644 --- a/unittest/force-styles/tests/fix-timestep-momentum.yaml +++ b/unittest/force-styles/tests/fix-timestep-momentum.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix momentum diff --git a/unittest/force-styles/tests/fix-timestep-momentum_chunk.yaml b/unittest/force-styles/tests/fix-timestep-momentum_chunk.yaml index 7946b82f71..454d9c632c 100644 --- a/unittest/force-styles/tests/fix-timestep-momentum_chunk.yaml +++ b/unittest/force-styles/tests/fix-timestep-momentum_chunk.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix momentum/chunk diff --git a/unittest/force-styles/tests/fix-timestep-planeforce.yaml b/unittest/force-styles/tests/fix-timestep-planeforce.yaml index 836c440d60..e4ad9f124e 100644 --- a/unittest/force-styles/tests/fix-timestep-planeforce.yaml +++ b/unittest/force-styles/tests/fix-timestep-planeforce.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2e-13 +epsilon: 5e-12 prerequisites: ! | atom full fix planeforce diff --git a/unittest/force-styles/tests/fix-timestep-rattle_angle.yaml b/unittest/force-styles/tests/fix-timestep-rattle_angle.yaml index 527086e59a..03ba9a64b9 100644 --- a/unittest/force-styles/tests/fix-timestep-rattle_angle.yaml +++ b/unittest/force-styles/tests/fix-timestep-rattle_angle.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2e-13 +epsilon: 3e-10 prerequisites: ! | atom full fix rattle diff --git a/unittest/force-styles/tests/fix-timestep-rattle_bond.yaml b/unittest/force-styles/tests/fix-timestep-rattle_bond.yaml index 1d6daa0039..8f771d84b3 100644 --- a/unittest/force-styles/tests/fix-timestep-rattle_bond.yaml +++ b/unittest/force-styles/tests/fix-timestep-rattle_bond.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2e-13 +epsilon: 9e-12 prerequisites: ! | atom full fix rattle diff --git a/unittest/force-styles/tests/fix-timestep-rigid_group.yaml b/unittest/force-styles/tests/fix-timestep-rigid_group.yaml index a911989c25..00201c36b5 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_group.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_group.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:53 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid @@ -13,65 +13,65 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.4245356937318927e+03 -1.4496493315649675e+03 -3.6144360984224963e+03 8.4840626828643849e+02 2.0318336761611764e+02 -6.0622397707969685e+02 + -1.4245356937318884e+03 -1.4496493315649705e+03 -3.6144360984225009e+03 8.4840626828644258e+02 2.0318336761611707e+02 -6.0622397707970117e+02 global_scalar: 15.7115214231781 run_pos: ! |2 - 1 -2.7899546863891622e-01 2.4731857340328216e+00 -1.7290667740241872e-01 - 2 3.0296221610264007e-01 2.9517129916957545e+00 -8.5798904387772823e-01 - 3 -6.9368802364134852e-01 1.2445115421754183e+00 -6.2281111198650230e-01 - 4 -1.5764879647103172e+00 1.4919714415841274e+00 -1.2492069414674600e+00 - 5 -8.9434512967430013e-01 9.3651699743510730e-01 4.0191726558261431e-01 - 6 2.9454439634451690e-01 2.2724545792544065e-01 -1.2845195053960263e+00 - 7 3.4049112903270062e-01 -9.4655678322440595e-03 -2.4634480020857059e+00 - 8 1.1644354555804877e+00 -4.8367776650961369e-01 -6.7663643940735896e-01 - 9 1.3781717822696469e+00 -2.5332509530010827e-01 2.6864954436590061e-01 - 10 2.0186368606041905e+00 -1.4285861423625792e+00 -9.6712491252780297e-01 - 11 1.7929137227577470e+00 -1.9875455388407410e+00 -1.8836565352266557e+00 - 12 3.0032775230399604e+00 -4.8983022415173838e-01 -1.6190248017343647e+00 - 13 4.0448964162125947e+00 -9.0213155122390720e-01 -1.6385398399479572e+00 - 14 2.6035151245015831e+00 -4.0874995493218902e-01 -2.6555999074786611e+00 - 15 2.9761196776172314e+00 5.6287237454108840e-01 -1.2442626196083382e+00 - 16 2.6517373021566191e+00 -2.3957035508393720e+00 3.3389262100689376e-02 - 17 2.2311114924744988e+00 -2.1018393228798540e+00 1.1496088522377521e+00 - 18 2.1390642573201788e+00 3.0164773560693772e+00 -3.5143984803853874e+00 - 19 1.5353246655146275e+00 2.6305911186316124e+00 -4.2455871034737074e+00 - 20 2.7649421538938386e+00 3.6818603528430827e+00 -3.9364115785985558e+00 - 21 4.9043112657298868e+00 -4.0774268210397873e+00 -3.6200836396129810e+00 - 22 4.3665322424283302e+00 -4.2075138112953594e+00 -4.4636587264885854e+00 - 23 5.7355405581985170e+00 -3.5789558641908905e+00 -3.8805763324089964e+00 - 24 2.0692780332810123e+00 3.1504920436416004e+00 3.1571131300668775e+00 - 25 1.3007297593169085e+00 3.2745259354179486e+00 2.5110163874103657e+00 - 26 2.5819416446099748e+00 4.0104903120756585e+00 3.2150249624526013e+00 + 1 -2.7899546863891489e-01 2.4731857340328216e+00 -1.7290667740242327e-01 + 2 3.0296221610264151e-01 2.9517129916957532e+00 -8.5798904387773267e-01 + 3 -6.9368802364134807e-01 1.2445115421754180e+00 -6.2281111198650496e-01 + 4 -1.5764879647103154e+00 1.4919714415841261e+00 -1.2492069414674631e+00 + 5 -8.9434512967430058e-01 9.3651699743510919e-01 4.0191726558261187e-01 + 6 2.9454439634451712e-01 2.2724545792543988e-01 -1.2845195053960272e+00 + 7 3.4049112903270107e-01 -9.4655678322462800e-03 -2.4634480020857055e+00 + 8 1.1644354555804874e+00 -4.8367776650961330e-01 -6.7663643940735863e-01 + 9 1.3781717822696467e+00 -2.5332509530010694e-01 2.6864954436590061e-01 + 10 2.0186368606041896e+00 -1.4285861423625787e+00 -9.6712491252780097e-01 + 11 1.7929137227577463e+00 -1.9875455388407417e+00 -1.8836565352266530e+00 + 12 3.0032775230399609e+00 -4.8983022415173938e-01 -1.6190248017343634e+00 + 13 4.0448964162125947e+00 -9.0213155122390887e-01 -1.6385398399479545e+00 + 14 2.6035151245015831e+00 -4.0874995493219152e-01 -2.6555999074786603e+00 + 15 2.9761196776172318e+00 5.6287237454108718e-01 -1.2442626196083382e+00 + 16 2.6517373021566177e+00 -2.3957035508393694e+00 3.3389262100692485e-02 + 17 2.2311114924744970e+00 -2.1018393228798504e+00 1.1496088522377548e+00 + 18 2.1390642573201784e+00 3.0164773560693781e+00 -3.5143984803853878e+00 + 19 1.5353246655146278e+00 2.6305911186316133e+00 -4.2455871034737074e+00 + 20 2.7649421538938390e+00 3.6818603528430849e+00 -3.9364115785985550e+00 + 21 4.9043112657298877e+00 -4.0774268210397882e+00 -3.6200836396129836e+00 + 22 4.3665322424283310e+00 -4.2075138112953594e+00 -4.4636587264885881e+00 + 23 5.7355405581985188e+00 -3.5789558641908918e+00 -3.8805763324089981e+00 + 24 2.0692780332810115e+00 3.1504920436416004e+00 3.1571131300668789e+00 + 25 1.3007297593169076e+00 3.2745259354179481e+00 2.5110163874103675e+00 + 26 2.5819416446099739e+00 4.0104903120756576e+00 3.2150249624526035e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 4.7093289825842518e-04 2.6351122778447999e-04 -4.4905093064114991e-04 - 2 4.9594625316470484e-04 9.4561370489631939e-05 -5.4581359894047949e-04 - 3 3.3306085115756087e-04 2.3224943880673381e-04 -2.3659455671746045e-04 - 4 3.3692327392261114e-04 2.1926810694051279e-04 -2.4716631558862527e-04 - 5 3.3642542694186013e-04 4.1797578013265895e-04 -1.8011341766657651e-04 - 6 2.0926869754934733e-04 2.6449308951578761e-05 -1.0508938983871863e-04 - 7 1.4629043007907862e-04 -1.6873376665350138e-04 -6.8354048774351599e-05 - 8 1.5844101624224864e-04 3.7728761274000492e-05 -1.9162715667091517e-05 - 9 2.1299362072601976e-04 1.6917140529157604e-04 -6.3528165037846039e-05 - 10 5.4261629412254251e-05 -9.4655528376811197e-05 1.0511362869146629e-04 - 11 -3.2194160796503320e-05 -2.2025095264758748e-04 2.0300202946212385e-04 - 12 1.2640586304750342e-04 -2.9851080445665075e-04 -7.9476371818247547e-05 - 13 8.4523575162142323e-05 -4.0583135407330540e-04 -4.7551111331702706e-05 - 14 9.9954050381270240e-05 -4.2610816481298321e-04 -7.9255633594381333e-05 - 15 2.4417481119789840e-04 -2.3521002264677917e-04 -2.4875318161049140e-04 - 16 -9.0958138549664179e-06 3.7774817121227626e-06 2.4035199548835075e-04 - 17 5.7507224523612718e-05 2.2629217444843883e-04 2.0686920072684827e-04 - 18 2.9220264989359676e-04 -6.2478376436796309e-04 8.4222594596602344e-04 - 19 2.0572616567799036e-04 -5.0334424271726705e-04 8.4953929443210658e-04 - 20 4.1224811789512805e-04 -7.4115205416011576e-04 8.3678612337507888e-04 - 21 -1.0671858777656380e-03 -1.1531171045499509e-03 7.3720674900162192e-04 - 22 -1.1066511338291703e-03 -1.0433933757600456e-03 7.4544544325708616e-04 - 23 -9.7629260480941438e-04 -1.3100872491594094e-03 7.2687284219704804e-04 - 24 4.3308126651259334e-04 -6.6527658087322747e-04 8.4451298670663595e-04 - 25 4.4565811905442911e-04 -5.1298436273584274e-04 8.5878867884521559e-04 - 26 5.9865972692022798e-04 -7.6385263287080316e-04 8.4259943226842134e-04 + 1 4.7093289825842486e-04 2.6351122778447826e-04 -4.4905093064114855e-04 + 2 4.9594625316470495e-04 9.4561370489630651e-05 -5.4581359894047721e-04 + 3 3.3306085115756092e-04 2.3224943880673270e-04 -2.3659455671746018e-04 + 4 3.3692327392261152e-04 2.1926810694051195e-04 -2.4716631558862522e-04 + 5 3.3642542694185980e-04 4.1797578013265732e-04 -1.8011341766657692e-04 + 6 2.0926869754934785e-04 2.6449308951578490e-05 -1.0508938983871839e-04 + 7 1.4629043007907975e-04 -1.6873376665350062e-04 -6.8354048774351260e-05 + 8 1.5844101624224894e-04 3.7728761274000044e-05 -1.9162715667091402e-05 + 9 2.1299362072601955e-04 1.6917140529157490e-04 -6.3528165037845781e-05 + 10 5.4261629412254793e-05 -9.4655528376811116e-05 1.0511362869146627e-04 + 11 -3.2194160796502263e-05 -2.2025095264758662e-04 2.0300202946212347e-04 + 12 1.2640586304750418e-04 -2.9851080445665042e-04 -7.9476371818246096e-05 + 13 8.4523575162143095e-05 -4.0583135407330485e-04 -4.7551111331700809e-05 + 14 9.9954050381271487e-05 -4.2610816481298213e-04 -7.9255633594379828e-05 + 15 2.4417481119789889e-04 -2.3521002264677933e-04 -2.4875318161048917e-04 + 16 -9.0958138549662281e-06 3.7774817121223831e-06 2.4035199548835009e-04 + 17 5.7507224523612284e-05 2.2629217444843761e-04 2.0686920072684746e-04 + 18 2.9220264989359801e-04 -6.2478376436796276e-04 8.4222594596602355e-04 + 19 2.0572616567799155e-04 -5.0334424271726661e-04 8.4953929443210658e-04 + 20 4.1224811789512974e-04 -7.4115205416011565e-04 8.3678612337507910e-04 + 21 -1.0671858777656390e-03 -1.1531171045499513e-03 7.3720674900162170e-04 + 22 -1.1066511338291712e-03 -1.0433933757600460e-03 7.4544544325708584e-04 + 23 -9.7629260480941536e-04 -1.3100872491594103e-03 7.2687284219704793e-04 + 24 4.3308126651259350e-04 -6.6527658087322768e-04 8.4451298670663606e-04 + 25 4.4565811905442927e-04 -5.1298436273584263e-04 8.5878867884521559e-04 + 26 5.9865972692022809e-04 -7.6385263287080348e-04 8.4259943226842155e-04 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml b/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml index 0ecc6afe1b..418614b035 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:54 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid @@ -13,7 +13,7 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200116134790363e+01 -2.6907707565987732e+01 -6.0080860422282560e+00 -2.5620423972101747e+01 -1.3450224059984075e+01 -1.4947288487004844e+00 + -4.9200116134789894e+01 -2.6907707565987600e+01 -6.0080860422279923e+00 -2.5620423972101459e+01 -1.3450224059984031e+01 -1.4947288487004347e+00 global_scalar: 18.3405601674144 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 @@ -33,15 +33,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1392027588271301e+00 3.0171068018412783e+00 -3.5144628518856349e+00 - 19 1.5366124997074573e+00 2.6286809834111744e+00 -4.2452547844370221e+00 - 20 2.7628161763455852e+00 3.6842251687634779e+00 -3.9370881219352558e+00 - 21 4.9036621347791245e+00 -4.0757648442838548e+00 -3.6192617654515908e+00 + 18 2.1392027588271301e+00 3.0171068018412779e+00 -3.5144628518856349e+00 + 19 1.5366124997074571e+00 2.6286809834111748e+00 -4.2452547844370221e+00 + 20 2.7628161763455852e+00 3.6842251687634775e+00 -3.9370881219352554e+00 + 21 4.9036621347791245e+00 -4.0757648442838548e+00 -3.6192617654515904e+00 22 4.3655322291888483e+00 -4.2084949965552561e+00 -4.4622011117402334e+00 23 5.7380414793463101e+00 -3.5841969195032672e+00 -3.8827839830470219e+00 24 2.0701314765323930e+00 3.1499370533342330e+00 3.1565324852522938e+00 - 25 1.3030170721374783e+00 3.2711173927682244e+00 2.5081940917429759e+00 - 26 2.5776230782480041e+00 4.0127347068243884e+00 3.2182355138709284e+00 + 25 1.3030170721374779e+00 3.2711173927682249e+00 2.5081940917429768e+00 + 26 2.5776230782480045e+00 4.0127347068243875e+00 3.2182355138709275e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095704870e-04 -3.1032459262908302e-04 8.1043030117346052e-04 - 19 8.5103884665345441e-04 -1.4572280596788099e-03 1.0163621287634116e-03 - 20 -6.5204659278590758e-04 4.3989037444289831e-04 4.9909839028507966e-04 - 21 -1.3888125881903919e-03 -3.1978049143082570e-04 1.1455681499836646e-03 - 22 -1.6084223477729497e-03 -1.5355394240821158e-03 1.4772010826232373e-03 - 23 2.6392672378804886e-04 -3.9375414431174760e-03 -3.6991583139728127e-04 - 24 8.6062827067890290e-04 -9.4179873474469259e-04 5.5396395550012367e-04 - 25 1.5933645477487557e-03 -2.2139156625681682e-03 -5.5078029695647412e-04 - 26 -1.5679561743998888e-03 3.5146224354725948e-04 2.4446924193334482e-03 + 18 3.6149625095704908e-04 -3.1032459262908286e-04 8.1043030117346042e-04 + 19 8.5103884665345452e-04 -1.4572280596788108e-03 1.0163621287634116e-03 + 20 -6.5204659278590683e-04 4.3989037444289853e-04 4.9909839028507890e-04 + 21 -1.3888125881903923e-03 -3.1978049143082407e-04 1.1455681499836646e-03 + 22 -1.6084223477729508e-03 -1.5355394240821113e-03 1.4772010826232373e-03 + 23 2.6392672378805081e-04 -3.9375414431174812e-03 -3.6991583139728051e-04 + 24 8.6062827067890236e-04 -9.4179873474469237e-04 5.5396395550012442e-04 + 25 1.5933645477487542e-03 -2.2139156625681699e-03 -5.5078029695647488e-04 + 26 -1.5679561743998840e-03 3.5146224354726122e-04 2.4446924193334474e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_molecule_tri.yaml b/unittest/force-styles/tests/fix-timestep-rigid_molecule_tri.yaml index d1d1e9492d..f23297ece8 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_molecule_tri.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_molecule_tri.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 +date_generated: Tue Sep 15 22:36:54 202 epsilon: 5e-12 prerequisites: ! | atom full @@ -14,7 +14,7 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200116134791799e+01 -2.6907707565986644e+01 -6.0080860422294684e+00 -2.5620423972101577e+01 -1.3450224059984462e+01 -1.4947288487000847e+00 + -4.9200116134789241e+01 -2.6907707565985238e+01 -6.0080860422273377e+00 -2.5620423972099417e+01 -1.3450224059984127e+01 -1.4947288486998911e+00 global_scalar: 18.3405601674143 run_pos: ! |2 1 -2.7993683669226854e-01 2.4726588069312836e+00 -1.7200860244148508e-01 @@ -35,14 +35,14 @@ run_pos: ! |2 16 2.6517554244980301e+00 -2.3957110424978438e+00 3.2908335999177751e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 18 2.1392027588271310e+00 3.0171068018412779e+00 -3.5144628518856349e+00 - 19 1.5366124997074584e+00 2.6286809834111740e+00 -4.2452547844370230e+00 + 19 1.5366124997074566e+00 2.6286809834111740e+00 -4.2452547844370239e+00 20 2.7628161763455852e+00 3.6842251687634775e+00 -3.9370881219352558e+00 - 21 4.9036621347791245e+00 -4.0757648442838557e+00 -3.6192617654515917e+00 + 21 4.9036621347791245e+00 -4.0757648442838557e+00 -3.6192617654515900e+00 22 4.3655322291888483e+00 -4.2084949965552569e+00 -4.4622011117402334e+00 - 23 5.7380414793463084e+00 -3.5841969195032686e+00 -3.8827839830470223e+00 + 23 5.7380414793463101e+00 -3.5841969195032686e+00 -3.8827839830470232e+00 24 2.0701314765323913e+00 3.1499370533342308e+00 3.1565324852522920e+00 25 1.3030170721374779e+00 3.2711173927682236e+00 2.5081940917429755e+00 - 26 2.5776230782480036e+00 4.0127347068243875e+00 3.2182355138709280e+00 + 26 2.5776230782480054e+00 4.0127347068243875e+00 3.2182355138709262e+00 27 -1.9613581876744357e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678509e+00 29 -1.3108232656499084e+00 -3.5992986322410765e+00 2.2680459788743512e+00 @@ -64,15 +64,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095704496e-04 -3.1032459262907451e-04 8.1043030117346150e-04 - 19 8.5103884665346059e-04 -1.4572280596788069e-03 1.0163621287634041e-03 - 20 -6.5204659278589056e-04 4.3989037444288725e-04 4.9909839028508367e-04 - 21 -1.3888125881903861e-03 -3.1978049143082461e-04 1.1455681499836603e-03 - 22 -1.6084223477729506e-03 -1.5355394240821054e-03 1.4772010826232355e-03 - 23 2.6392672378804235e-04 -3.9375414431174561e-03 -3.6991583139728127e-04 - 24 8.6062827067889531e-04 -9.4179873474469281e-04 5.5396395550012681e-04 - 25 1.5933645477487551e-03 -2.2139156625681582e-03 -5.5078029695647629e-04 - 26 -1.5679561743998853e-03 3.5146224354725482e-04 2.4446924193334521e-03 + 18 3.6149625095704480e-04 -3.1032459262907435e-04 8.1043030117346128e-04 + 19 8.5103884665346124e-04 -1.4572280596788089e-03 1.0163621287634045e-03 + 20 -6.5204659278589121e-04 4.3989037444288817e-04 4.9909839028508280e-04 + 21 -1.3888125881903863e-03 -3.1978049143082245e-04 1.1455681499836596e-03 + 22 -1.6084223477729515e-03 -1.5355394240820991e-03 1.4772010826232349e-03 + 23 2.6392672378804170e-04 -3.9375414431174621e-03 -3.6991583139727824e-04 + 24 8.6062827067889477e-04 -9.4179873474469237e-04 5.5396395550012714e-04 + 25 1.5933645477487534e-03 -2.2139156625681600e-03 -5.5078029695647803e-04 + 26 -1.5679561743998831e-03 3.5146224354725699e-04 2.4446924193334539e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml index 84b1d84927..4e5c3cf1bc 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:55 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nph @@ -13,38 +13,38 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |2- - 4.3578059170174832e+01 1.7275105168494740e+01 6.7372361278298868e+01 5.1985075051780690e+01 -2.0990677390560389e+01 -7.5321398094463152e+00 -global_scalar: 29.0236364415722 + 4.3578059172167876e+01 1.7275105166465064e+01 6.7372361276630770e+01 5.1985075049901859e+01 -2.0990677389800858e+01 -7.5321398101845993e+00 +global_scalar: 29.023636440848 run_pos: ! |2 - 1 -6.3472039825537774e-01 3.0113983126285238e+00 -8.8148450172184312e-02 - 2 6.4798884173359994e-02 3.5870486860061543e+00 -9.1146271255437306e-01 - 3 -1.1328967478842920e+00 1.5344674077764360e+00 -6.2949567786978733e-01 - 4 -2.1941320441844692e+00 1.8319737599532431e+00 -1.3824693495475060e+00 - 5 -1.3741175247363460e+00 1.1637763350571220e+00 6.0220861483097998e-01 - 6 5.5368589242019262e-02 3.1209253712249385e-01 -1.4252606627468101e+00 - 7 1.1075313780256746e-01 2.8008314824816694e-02 -2.8425552056440306e+00 - 8 1.1011987966103707e+00 -5.4254536577072088e-01 -6.9472264392662098e-01 - 9 1.3580030945400914e+00 -2.6595138115347083e-01 4.4172536708307497e-01 - 10 2.1282964643832063e+00 -1.6781145595678426e+00 -1.0442216631471748e+00 - 11 1.8571593172391960e+00 -2.3497452731073585e+00 -2.1462323657666937e+00 - 12 3.3117732698471869e+00 -5.4913311816194721e-01 -1.8274356036323782e+00 - 13 4.5640183918456163e+00 -1.0445083545908478e+00 -1.8509716390299458e+00 - 14 2.8312769330519441e+00 -4.5135848464346751e-01 -3.0735173792334480e+00 - 15 3.2788434490966072e+00 7.1618295543704136e-01 -1.3765217601453035e+00 - 16 2.8895075000233614e+00 -2.8409365554013073e+00 1.5818504152562340e-01 - 17 2.3837073405560201e+00 -2.4882133308171541e+00 1.5000885103551340e+00 - 18 2.2738793194347995e+00 3.6743407122546436e+00 -4.1408965121169743e+00 - 19 1.6572750518209620e+00 3.2770314238218798e+00 -4.8886441786647481e+00 - 20 2.9120476452842148e+00 4.3568412675017782e+00 -4.5732834167711358e+00 - 21 5.6058485050574518e+00 -4.8495065176199610e+00 -4.2655497599977545e+00 - 22 5.0552709233227606e+00 -4.9851876751499695e+00 -5.1280564953937073e+00 - 23 6.4593933586526457e+00 -4.3461765106386885e+00 -4.5350231455787116e+00 - 24 2.1823354618683499e+00 3.8552931130562804e+00 3.8953804330779338e+00 - 25 1.3973696115700314e+00 3.9794119229081808e+00 3.2321313265763383e+00 - 26 2.7018361229436447e+00 4.7379517630363708e+00 3.9583193477160581e+00 - 27 -2.6559803075362280e+00 -5.1969823689083769e+00 2.6552621488558881e+00 - 28 -3.5927802460212037e+00 -4.7943885088606857e+00 2.0214142204097989e+00 - 29 -1.8739632618342412e+00 -4.2877858778717988e+00 2.8450749793922530e+00 + 1 -6.3472039825517168e-01 3.0113983126282058e+00 -8.8148450172235826e-02 + 2 6.4798884173500326e-02 3.5870486860057795e+00 -9.1146271255434463e-01 + 3 -1.1328967478840362e+00 1.5344674077762583e+00 -6.2949567786977667e-01 + 4 -2.1941320441841130e+00 1.8319737599530370e+00 -1.3824693495474225e+00 + 5 -1.3741175247360697e+00 1.1637763350569887e+00 6.0220861483086097e-01 + 6 5.5368589242158706e-02 3.1209253712244411e-01 -1.4252606627467266e+00 + 7 1.1075313780270069e-01 2.8008314824797154e-02 -2.8425552056438050e+00 + 8 1.1011987966104080e+00 -5.4254536577068713e-01 -6.9472264392660854e-01 + 9 1.3580030945401020e+00 -2.6595138115345840e-01 4.4172536708297194e-01 + 10 2.1282964643831388e+00 -1.6781145595676907e+00 -1.0442216631471304e+00 + 11 1.8571593172391605e+00 -2.3497452731071471e+00 -2.1462323657665392e+00 + 12 3.3117732698469986e+00 -5.4913311816190635e-01 -1.8274356036322548e+00 + 13 4.5640183918453143e+00 -1.0445083545907554e+00 -1.8509716390298214e+00 + 14 2.8312769330518019e+00 -4.5135848464344086e-01 -3.0735173792331993e+00 + 15 3.2788434490964296e+00 7.1618295543695254e-01 -1.3765217601452289e+00 + 16 2.8895075000232158e+00 -2.8409365554010479e+00 1.5818504152554702e-01 + 17 2.3837073405559277e+00 -2.4882133308169232e+00 1.5000885103549333e+00 + 18 2.2738793194357232e+00 3.6743407122553755e+00 -4.1408965121163197e+00 + 19 1.6572750518209336e+00 3.2770314238152451e+00 -4.8886441786593569e+00 + 20 2.9120476452800226e+00 4.3568412675031851e+00 -4.5732834167769187e+00 + 21 5.6058485050774536e+00 -4.8495065176300871e+00 -4.2655497599953458e+00 + 22 5.0552709232982114e+00 -4.9851876752032496e+00 -5.1280564953560424e+00 + 23 6.4593933585948218e+00 -4.3461765105422652e+00 -4.5350231456236889e+00 + 24 2.1823354619125279e+00 3.8552931130470363e+00 3.8953804330431208e+00 + 25 1.3973696115403698e+00 3.9794119228484153e+00 3.2321313266194949e+00 + 26 2.7018361227965517e+00 4.7379517631305443e+00 3.9583193478092706e+00 + 27 -2.6559803075358257e+00 -5.1969823689078796e+00 2.6552621488555683e+00 + 28 -3.5927802460207046e+00 -4.7943885088602283e+00 2.0214142204095413e+00 + 29 -1.8739632618339108e+00 -4.2877858778713946e+00 2.8450749793919066e+00 run_vel: ! |2 1 7.7867804888392077e-04 5.8970331623292821e-04 -2.2179517633030531e-04 2 2.7129529964126462e-03 4.6286427111164284e-03 3.5805549693846352e-03 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.0094600491857170e-04 -2.4312792028099414e-04 6.5542049134060274e-04 - 19 7.4731683461619846e-04 -1.2894119671259621e-03 8.4327024053358754e-04 - 20 -6.2333686370008492e-04 4.4115361642793068e-04 3.7135656431973134e-04 - 21 -1.1457423792961207e-03 -1.7337748147951398e-04 9.4510018428184666e-04 - 22 -1.3457150580799371e-03 -1.2816797359999673e-03 1.2470992249788205e-03 - 23 3.6277645396700405e-04 -3.4719859050652826e-03 -4.3796817842582582e-04 - 24 7.2410992459670976e-04 -7.6012809759400297e-04 4.3327155120506525e-04 - 25 1.3921349891892296e-03 -1.9207002802470775e-03 -5.7453335098664004e-04 - 26 -1.4901465945625163e-03 4.2012923513626613e-04 2.1578545406129362e-03 + 18 3.0094600491564739e-04 -2.4312792027781274e-04 6.5542049134062323e-04 + 19 7.4731683462770054e-04 -1.2894119671278408e-03 8.4327024053533386e-04 + 20 -6.2333686369976584e-04 4.4115361641690066e-04 3.7135656431834237e-04 + 21 -1.1457423793218525e-03 -1.7337748161437973e-04 9.4510018429417686e-04 + 22 -1.3457150581639319e-03 -1.2816797357047460e-03 1.2470992250388101e-03 + 23 3.6277645415306540e-04 -3.4719859048227848e-03 -4.3796817853449140e-04 + 24 7.2410992462873655e-04 -7.6012809744767037e-04 4.3327155128124932e-04 + 25 1.3921349892629666e-03 -1.9207002802664867e-03 -5.7453335109528100e-04 + 26 -1.4901465947638008e-03 4.2012923457099966e-04 2.1578545404178414e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml index 7844d7fcb7..5019d8fbe5 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:55 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nph/small @@ -13,38 +13,38 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |2- - 2.7340318969496678e+01 4.7963870140135469e+00 6.8884396850629400e+01 2.9853310008504316e+01 -1.0857139901179401e+01 -5.1889756547613537e+00 -global_scalar: 9.77678786322453 + 2.7340318973870428e+01 4.7963870091858531e+00 6.8884396847592484e+01 2.9853310007358978e+01 -1.0857139901347637e+01 -5.1889756561453346e+00 +global_scalar: 9.77678786310451 run_pos: ! |2 - 1 -5.1121862036607624e-01 2.8134872171085981e+00 -4.8993015395440764e-02 - 2 1.4735952488044823e-01 3.3535825972284670e+00 -9.3694001270740124e-01 - 3 -9.8023793775382462e-01 1.4277788160413873e+00 -6.3283768722999412e-01 - 4 -1.9793617512974810e+00 1.7069097152783730e+00 -1.4449221382956789e+00 - 5 -1.2073406578712493e+00 1.0799834439083895e+00 6.9555923026710076e-01 - 6 1.3848116183740711e-01 2.8090381873862391e-01 -1.4910727029129127e+00 - 7 1.9062418946015125e-01 1.4366032742495705e-02 -3.0196292835202954e+00 - 8 1.1231015082845470e+00 -5.2094745136408704e-01 -7.0318517336044728e-01 - 9 1.3648756844511940e+00 -2.6143726919536014e-01 5.2247754752749742e-01 - 10 2.0900856844466613e+00 -1.5863783165915786e+00 -1.0801209545801669e+00 - 11 1.8348175253566694e+00 -2.2165258198423707e+00 -2.2686429310674399e+00 - 12 3.2042965133156294e+00 -5.2712831182456732e-01 -1.9248196297791935e+00 - 13 4.3832508188729644e+00 -9.9190674157035730e-01 -1.9502033172904838e+00 - 14 2.7519224412447869e+00 -4.3539271970396598e-01 -3.2687227073824996e+00 - 15 3.1732939937025613e+00 6.6003562890635337e-01 -1.4385076445935461e+00 - 16 2.8067449168448011e+00 -2.6773787170020160e+00 2.1667842294155371e-01 - 17 2.3305479923928605e+00 -2.3464414104888620e+00 1.6639254952588054e+00 - 18 2.2269920241221968e+00 3.4328783208250648e+00 -4.4342132514643442e+00 - 19 1.6145347679280437e+00 3.0386658278250263e+00 -5.1868156516302486e+00 - 20 2.8608613711069921e+00 4.1100452338277211e+00 -4.8694049549850762e+00 - 21 5.3613621396753839e+00 -4.5653056926381028e+00 -4.5681019697332310e+00 - 22 4.8144754755163870e+00 -4.6999404673940806e+00 -5.4362066556515076e+00 - 23 6.2091840279374200e+00 -4.0659479263393665e+00 -4.8393130641406774e+00 - 24 2.1433208912156090e+00 3.5960988832244993e+00 4.2399236066761858e+00 - 25 1.3636453973791856e+00 3.7192408266937900e+00 3.5723762826039014e+00 - 26 2.6593036731430075e+00 4.4718649489299125e+00 4.3032623332451116e+00 - 27 -2.4141791756399114e+00 -4.8879035738861889e+00 2.9097838637423070e+00 - 28 -3.2961505257539727e+00 -4.5101758871992912e+00 2.2261768979311878e+00 - 29 -1.6779316575994772e+00 -4.0348635219032660e+00 3.1144975929061580e+00 + 1 -5.1121862036604515e-01 2.8134872171079977e+00 -4.8993015395518924e-02 + 2 1.4735952488047133e-01 3.3535825972277546e+00 -9.3694001270735150e-01 + 3 -9.8023793775378820e-01 1.4277788160410712e+00 -6.3283768722999234e-01 + 4 -1.9793617512974304e+00 1.7069097152779946e+00 -1.4449221382955635e+00 + 5 -1.2073406578712120e+00 1.0799834439081337e+00 6.9555923026692668e-01 + 6 1.3848116183742931e-01 2.8090381873852976e-01 -1.4910727029127884e+00 + 7 1.9062418946016990e-01 1.4366032742456625e-02 -3.0196292835199614e+00 + 8 1.1231015082845541e+00 -5.2094745136401599e-01 -7.0318517336042774e-01 + 9 1.3648756844511976e+00 -2.6143726919534771e-01 5.2247754752734465e-01 + 10 2.0900856844466578e+00 -1.5863783165912952e+00 -1.0801209545800976e+00 + 11 1.8348175253566659e+00 -2.2165258198419622e+00 -2.2686429310672072e+00 + 12 3.2042965133156098e+00 -5.2712831182449804e-01 -1.9248196297790088e+00 + 13 4.3832508188729271e+00 -9.9190674157019298e-01 -1.9502033172902991e+00 + 14 2.7519224412447691e+00 -4.3539271970391624e-01 -3.2687227073821310e+00 + 15 3.1732939937025400e+00 6.6003562890618639e-01 -1.4385076445934288e+00 + 16 2.8067449168447887e+00 -2.6773787170015133e+00 2.1667842294144180e-01 + 17 2.3305479923928516e+00 -2.3464414104884277e+00 1.6639254952584981e+00 + 18 2.2269920241232128e+00 3.4328783208254681e+00 -4.4342132514635013e+00 + 19 1.6145347679280793e+00 3.0386658278179439e+00 -5.1868156516245785e+00 + 20 2.8608613711028656e+00 4.1100452338287408e+00 -4.8694049549907970e+00 + 21 5.3613621396958795e+00 -4.5653056926475841e+00 -4.5681019697305372e+00 + 22 4.8144754754921184e+00 -4.6999404674483083e+00 -5.4362066556130868e+00 + 23 6.2091840278795729e+00 -4.0659479262420684e+00 -4.8393130641864568e+00 + 24 2.1433208912603074e+00 3.5960988832146015e+00 4.2399236066404100e+00 + 25 1.3636453973491918e+00 3.7192408266342980e+00 3.5723762826473990e+00 + 26 2.6593036729945752e+00 4.4718649490241678e+00 4.3032623333405660e+00 + 27 -2.4141791756398536e+00 -4.8879035738852403e+00 2.9097838637418292e+00 + 28 -3.2961505257539048e+00 -4.5101758871984199e+00 2.2261768979308005e+00 + 29 -1.6779316575994301e+00 -4.0348635219024889e+00 3.1144975929056571e+00 run_vel: ! |2 1 7.7867804888392077e-04 5.8970331623292821e-04 -2.2179517633030531e-04 2 2.7129529964126462e-03 4.6286427111164284e-03 3.5805549693846352e-03 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.1638284997374886e-04 -2.6313163919391785e-04 6.1054395248654240e-04 - 19 7.6494647251130164e-04 -1.3190724749194743e-03 7.9947132612800302e-04 - 20 -6.1620104632544958e-04 4.2577138775425278e-04 3.2526261653689488e-04 - 21 -1.2063428871264968e-03 -2.2879409865288636e-04 8.9132836537584854e-04 - 22 -1.4151473871025083e-03 -1.3502255396192354e-03 1.1972773108803675e-03 - 23 3.1280366090588076e-04 -3.5563936895860802e-03 -4.9548546521909192e-04 - 24 7.5594375538132891e-04 -8.1321044009404451e-04 3.9340911288127442e-04 - 25 1.4373446730971094e-03 -1.9778020567293888e-03 -6.1842201907464972e-04 - 26 -1.4806168648241629e-03 3.7766934332214119e-04 2.1280924227254782e-03 + 18 3.1638284997073288e-04 -2.6313163919070400e-04 6.1054395248656961e-04 + 19 7.6494647252307629e-04 -1.3190724749214317e-03 7.9947132612985744e-04 + 20 -6.1620104632513885e-04 4.2577138774295257e-04 3.2526261653548683e-04 + 21 -1.2063428871524097e-03 -2.2879409878999576e-04 8.9132836538734455e-04 + 22 -1.4151473871894464e-03 -1.3502255393198256e-03 1.1972773109437851e-03 + 23 3.1280366109607172e-04 -3.5563936893394407e-03 -4.9548546532774947e-04 + 24 7.5594375541558048e-04 -8.1321043994394464e-04 3.9340911295780760e-04 + 25 1.4373446731689036e-03 -1.9778020567486213e-03 -6.1842201918304457e-04 + 26 -1.4806168650325995e-03 3.7766934274110835e-04 2.1280924225288347e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml b/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml index 8409597e0b..f85f2119b5 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:56 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/npt @@ -12,65 +12,65 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.6326314448657713e+03 -1.4727331978534244e+03 -3.8557370515929333e+03 5.5052891601613476e+02 4.7346742977275369e+02 -6.2035591882215908e+02 -global_scalar: 106.866830724743 + -1.6326314448663304e+03 -1.4727331978532306e+03 -3.8557370515932275e+03 5.5052891601644728e+02 4.7346742977310510e+02 -6.2035591882122242e+02 +global_scalar: 106.866830724741 run_pos: ! |2 - 1 -2.6314711410821801e-01 2.4664715027249615e+00 -1.7093568570971751e-01 - 2 3.1632911016085430e-01 2.9434731493855670e+00 -8.5432214735894441e-01 - 3 -6.7623447816539795e-01 1.2410822625702851e+00 -6.1935152269952987e-01 - 4 -1.5552134736900181e+00 1.4878541801000127e+00 -1.2440909745472499e+00 - 5 -8.7601967096356681e-01 9.3417436540695586e-01 4.0272031680403497e-01 - 6 3.0755837780652939e-01 2.2629147986257614e-01 -1.2791162680675363e+00 - 7 3.5322094628055822e-01 -1.0043890952604606e-02 -2.4548503163676925e+00 - 8 1.1736205127906949e+00 -4.8269091330534497e-01 -6.7273784266497216e-01 - 9 1.3865071239751776e+00 -2.5278331076587346e-01 2.6996653369767554e-01 - 10 2.0239883243188919e+00 -1.4252201368166180e+00 -9.6228264545848585e-01 - 11 1.7991233925762300e+00 -1.9828365722523360e+00 -1.8762366544349351e+00 - 12 3.0044710092991540e+00 -4.8928363303993549e-01 -1.6126944183950824e+00 - 13 4.0415308387389697e+00 -9.0061411582067930e-01 -1.6321139880361839e+00 - 14 2.6064005411337394e+00 -4.0859653026992238e-01 -2.6465043951812257e+00 - 15 2.9775904824776660e+00 5.6065407887794816e-01 -1.2391617757507083e+00 - 16 2.6542663248050005e+00 -2.3895844048758690e+00 3.5746598094905657e-02 - 17 2.2355490747039930e+00 -2.0962135127176689e+00 1.1489434027787402e+00 - 18 2.0921160979688356e+00 2.9872159674132197e+00 -3.4902339097021988e+00 - 19 1.4908686219050935e+00 2.6025398330890352e+00 -4.2194623779111327e+00 - 20 2.7154518806596677e+00 3.6506388357590405e+00 -3.9111287168646642e+00 - 21 4.8435638296059782e+00 -4.0881941921713345e+00 -3.5957796498843582e+00 - 22 4.3080557005390165e+00 -4.2177797604315348e+00 -4.4370935526129456e+00 - 23 5.6713237924952811e+00 -3.5912865024270464e+00 -3.8555915013200188e+00 - 24 2.0228224543362074e+00 3.1208125399078126e+00 3.1634860992081633e+00 - 25 1.2576132296064850e+00 3.2447174749282715e+00 2.5191319958263714e+00 - 26 2.5334951322496941e+00 3.9783477827943221e+00 3.2212409164234250e+00 - 27 -1.8488304998563310e+00 -4.2601261704683537e+00 2.0568476369354167e+00 - 28 -2.6026086128772414e+00 -3.9329047688996477e+00 1.5399898445636326e+00 - 29 -1.2195954744860948e+00 -3.5211468177700955e+00 2.2116264666073553e+00 + 1 -2.6314711410922875e-01 2.4664715027241684e+00 -1.7093568570875561e-01 + 2 3.1632911015968190e-01 2.9434731493852482e+00 -8.5432214735778889e-01 + 3 -6.7623447816593885e-01 1.2410822625695044e+00 -6.1935152269903870e-01 + 4 -1.5552134736906362e+00 1.4878541800991378e+00 -1.2440909745466859e+00 + 5 -8.7601967096402067e-01 9.3417436540572218e-01 4.0272031680440712e-01 + 6 3.0755837780638462e-01 2.2629147986241449e-01 -1.2791162680673960e+00 + 7 3.5322094628053069e-01 -1.0043890952307954e-02 -2.4548503163676365e+00 + 8 1.1736205127907979e+00 -4.8269091330540537e-01 -6.7273784266507608e-01 + 9 1.3865071239751696e+00 -2.5278331076620741e-01 2.6996653369766221e-01 + 10 2.0239883243193546e+00 -1.4252201368162511e+00 -9.6228264545891751e-01 + 11 1.7991233925769246e+00 -1.9828365722517098e+00 -1.8762366544355809e+00 + 12 3.0044710092992837e+00 -4.8928363303895761e-01 -1.6126944183951402e+00 + 13 4.0415308387392486e+00 -9.0061411581930262e-01 -1.6321139880363669e+00 + 14 2.6064005411338655e+00 -4.0859653026870735e-01 -2.6465043951812621e+00 + 15 2.9775904824773907e+00 5.6065407887877150e-01 -1.2391617757503752e+00 + 16 2.6542663248057963e+00 -2.3895844048756363e+00 3.5746598094128501e-02 + 17 2.2355490747046538e+00 -2.0962135127180099e+00 1.1489434027780590e+00 + 18 2.0921160979727347e+00 2.9872159674143273e+00 -3.4902339097026891e+00 + 19 1.4908686219092431e+00 2.6025398330908249e+00 -4.2194623779121834e+00 + 20 2.7154518806645740e+00 3.6506388357595867e+00 -3.9111287168645399e+00 + 21 4.8435638296030810e+00 -4.0881941921728835e+00 -3.5957796498833634e+00 + 22 4.3080557005367073e+00 -4.2177797604324549e+00 -4.4370935526124242e+00 + 23 5.6713237924930837e+00 -3.5912865024293716e+00 -3.8555915013182531e+00 + 24 2.0228224543345528e+00 3.1208125399081723e+00 3.1634860992076259e+00 + 25 1.2576132296055036e+00 3.2447174749294536e+00 2.5191319958251963e+00 + 26 2.5334951322488237e+00 3.9783477827941720e+00 3.2212409164234312e+00 + 27 -1.8488304998563332e+00 -4.2601261704683342e+00 2.0568476369354265e+00 + 28 -2.6026086128772454e+00 -3.9329047688996304e+00 1.5399898445636406e+00 + 29 -1.2195954744860957e+00 -3.5211468177700818e+00 2.2116264666073615e+00 run_vel: ! |2 - 1 1.2393084479632990e-03 7.0215195817088653e-04 -1.1910956210641626e-03 - 2 1.3060936199990425e-03 2.5041119719272501e-04 -1.4496302699049824e-03 - 3 8.7069732478185780e-04 6.1866591813723552e-04 -6.2317312592577423e-04 - 4 8.8100215742054977e-04 5.8380213791498826e-04 -6.5145037264871986e-04 - 5 8.7979303398027825e-04 1.1152950208759250e-03 -4.7231382224803808e-04 - 6 5.3965146863318037e-04 6.8643008418777597e-05 -2.7149223435852534e-04 - 7 3.7117679682175872e-04 -4.5322194777188925e-04 -1.7317402888836805e-04 - 8 4.0378854177636902e-04 9.9015358993729126e-05 -4.1783685861320472e-05 - 9 5.4970639315548295e-04 4.5048022318715903e-04 -1.6045108899934789e-04 - 10 1.2521448037932167e-04 -2.5472783650505810e-04 2.9052485920883609e-04 - 11 -1.0599027352509822e-04 -5.9051612835328310e-04 5.5226010155811516e-04 - 12 3.1798607399596227e-04 -7.9980833669007897e-04 -2.0274707260252713e-04 - 13 2.0597404142647623e-04 -1.0865778699534437e-03 -1.1731137935602721e-04 - 14 2.4719215573317237e-04 -1.1410575874167027e-03 -2.0209037936245712e-04 - 15 6.3286464043707177e-04 -6.3068988069316188e-04 -6.5527927471316393e-04 - 16 -4.4100406049097274e-05 8.6869240447760984e-06 6.5198761255915241e-04 - 17 1.3407421346951786e-04 6.0357565278281160e-04 5.6233596575944243e-04 - 18 7.9277804690583290e-04 -1.5618239874403777e-03 2.1367192719678641e-03 - 19 5.6167660797931120e-04 -1.2371794194899347e-03 2.1562222137423708e-03 - 20 1.1137406410129261e-03 -1.8729421751404616e-03 2.1222207985342511e-03 - 21 -2.8426953558134279e-03 -2.9730185469798933e-03 1.8564402246260027e-03 - 22 -2.9480844379788478e-03 -2.6797216173783146e-03 1.8784164631756271e-03 - 23 -2.5997293519666649e-03 -3.3926375081648440e-03 1.8288830284145640e-03 - 24 1.1689404599038080e-03 -1.6701257754522614e-03 2.1428138286392188e-03 - 25 1.2027302640324651e-03 -1.2630861421198962e-03 2.1808987508666854e-03 - 26 1.6116362268904522e-03 -1.9337182438142464e-03 2.1377249582866698e-03 + 1 1.2393084479630032e-03 7.0215195817154908e-04 -1.1910956210640377e-03 + 2 1.3060936199988530e-03 2.5041119719347138e-04 -1.4496302699051106e-03 + 3 8.7069732478159932e-04 6.1866591813748793e-04 -6.2317312592554438e-04 + 4 8.8100215742025042e-04 5.8380213791515870e-04 -6.5145037264846355e-04 + 5 8.7979303397991721e-04 1.1152950208762108e-03 -4.7231382224758082e-04 + 6 5.3965146863311749e-04 6.8643008418756997e-05 -2.7149223435848598e-04 + 7 3.7117679682181569e-04 -4.5322194777211666e-04 -1.7317402888850959e-04 + 8 4.0378854177636355e-04 9.9015358993666161e-05 -4.1783685861269487e-05 + 9 5.4970639315540587e-04 4.5048022318729201e-04 -1.6045108899919846e-04 + 10 1.2521448037946088e-04 -2.5472783650533852e-04 2.9052485920877543e-04 + 11 -1.0599027352488030e-04 -5.9051612835384288e-04 5.5226010155799091e-04 + 12 3.1798607399623077e-04 -7.9980833669012060e-04 -2.0274707260294395e-04 + 13 2.0597404142686724e-04 -1.0865778699535142e-03 -1.1731137935659032e-04 + 14 2.4719215573349167e-04 -1.1410575874168849e-03 -2.0209037936298269e-04 + 15 6.3286464043726856e-04 -6.3068988069288280e-04 -6.5527927471360488e-04 + 16 -4.4100406048952316e-05 8.6869240444182845e-06 6.5198761255923058e-04 + 17 1.3407421346950843e-04 6.0357565278263792e-04 5.6233596575975002e-04 + 18 7.9277804690569055e-04 -1.5618239874425177e-03 2.1367192719678593e-03 + 19 5.6167660797942721e-04 -1.2371794194922850e-03 2.1562222137424718e-03 + 20 1.1137406410123482e-03 -1.8729421751430327e-03 2.1222207985340819e-03 + 21 -2.8426953558137735e-03 -2.9730185469781377e-03 1.8564402246257746e-03 + 22 -2.9480844379790160e-03 -2.6797216173769355e-03 1.8784164631754769e-03 + 23 -2.5997293519674954e-03 -3.3926375081633348e-03 1.8288830284141457e-03 + 24 1.1689404599043950e-03 -1.6701257754515664e-03 2.1428138286394673e-03 + 25 1.2027302640333160e-03 -1.2630861421196525e-03 2.1808987508670514e-03 + 26 1.6116362268906777e-03 -1.9337182438138849e-03 2.1377249582867847e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml index 466f5ac5fb..4b5a717e25 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:56 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/npt/small @@ -12,38 +12,38 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -8.7531774792845880e+01 5.5811525713967427e+00 -5.5468297751741936e+01 -1.5316306340330462e+02 1.4641268099032845e+02 1.7263710124990443e+01 -global_scalar: 77.7898343033466 + -8.7531774769722233e+01 5.5811525017967618e+00 -5.5468297744356789e+01 -1.5316306343483367e+02 1.4641268097314369e+02 1.7263710089631282e+01 +global_scalar: 77.7898343029329 run_pos: ! |2 - 1 -4.6333219629017464e-01 2.7511450055072171e+00 -1.2865946102804671e-01 - 2 1.7937148390197599e-01 3.2800405238541188e+00 -8.8510337855740406e-01 - 3 -9.2104620265683845e-01 1.3941717929286863e+00 -6.2603796687146485e-01 - 4 -1.8960869879713140e+00 1.6675144043870791e+00 -1.3178544214441361e+00 - 5 -1.1426748052070774e+00 1.0535885915280208e+00 5.0562616550060646e-01 - 6 1.7070712623534234e-01 2.7107933832759024e-01 -1.3571701846607818e+00 - 7 2.2159329060533217e-01 1.0068698962056644e-02 -2.6593507556861287e+00 - 8 1.1315940381700900e+00 -5.1414408469810713e-01 -6.8596713849764512e-01 - 9 1.3675404538221958e+00 -2.6001531899017039e-01 3.5817751536668574e-01 - 10 2.0752698846777538e+00 -1.5574812996955973e+00 -1.0070795245589732e+00 - 11 1.8261547470632262e+00 -2.1745615463232557e+00 -2.0195839000289277e+00 - 12 3.1626236108721919e+00 -5.2019677375527529e-01 -1.7266801053748662e+00 - 13 4.3131602274136434e+00 -9.7533717592330937e-01 -1.7483045222381550e+00 - 14 2.7211536303665351e+00 -4.3036348628164767e-01 -2.8715539682061753e+00 - 15 3.1323683805789226e+00 6.4234915962461692e-01 -1.3123899007467301e+00 - 16 2.7746546569033050e+00 -2.6258578189757298e+00 9.7666596945760631e-02 - 17 2.3099360535750968e+00 -2.3017831004885014e+00 1.3305794265748698e+00 - 18 2.2091748314050417e+00 3.3564440703049438e+00 -3.8370878209013126e+00 - 19 1.5986312961637505e+00 2.9614993054696921e+00 -4.5778944294659887e+00 - 20 2.8405364052349338e+00 4.0335971973396720e+00 -4.2659151034058365e+00 - 21 5.2651527409770740e+00 -4.4761614286051783e+00 -3.9518304737729775e+00 - 22 4.7192922285199597e+00 -4.6119045763260864e+00 -4.8062296932313151e+00 - 23 6.1127575785040520e+00 -3.9811721112979788e+00 -4.2204729622207884e+00 - 24 2.1290800759969954e+00 3.5132841007979358e+00 3.5392070210911051e+00 - 25 1.3519459805791634e+00 3.6349473856919570e+00 2.8807586651537935e+00 - 26 2.6413474240254864e+00 4.3893648731783070e+00 3.6035699963144729e+00 - 27 -2.3204235087830414e+00 -4.7905434153253355e+00 2.3919287951693260e+00 - 28 -3.1811356909799748e+00 -4.4206486004504146e+00 1.8095625809313809e+00 - 29 -1.6019226098505461e+00 -3.9551927030788505e+00 2.5663248522870763e+00 + 1 -4.6333219629007161e-01 2.7511450055070625e+00 -1.2865946102806269e-01 + 2 1.7937148390204793e-01 3.2800405238539234e+00 -8.8510337855738808e-01 + 3 -9.2104620265671233e-01 1.3941717929286011e+00 -6.2603796687145774e-01 + 4 -1.8960869879711328e+00 1.6675144043869761e+00 -1.3178544214440926e+00 + 5 -1.1426748052069362e+00 1.0535885915279550e+00 5.0562616550054784e-01 + 6 1.7070712623541162e-01 2.7107933832755826e-01 -1.3571701846607374e+00 + 7 2.2159329060539701e-01 1.0068698962042433e-02 -2.6593507556860114e+00 + 8 1.1315940381701060e+00 -5.1414408469809381e-01 -6.8596713849763802e-01 + 9 1.3675404538221994e+00 -2.6001531899016506e-01 3.5817751536664133e-01 + 10 2.0752698846777218e+00 -1.5574812996955254e+00 -1.0070795245589492e+00 + 11 1.8261547470632067e+00 -2.1745615463231482e+00 -2.0195839000288469e+00 + 12 3.1626236108721066e+00 -5.2019677375525752e-01 -1.7266801053747978e+00 + 13 4.3131602274134853e+00 -9.7533717592326674e-01 -1.7483045222380902e+00 + 14 2.7211536303664605e+00 -4.3036348628163701e-01 -2.8715539682060491e+00 + 15 3.1323683805788374e+00 6.4234915962457073e-01 -1.3123899007466848e+00 + 16 2.7746546569032322e+00 -2.6258578189755974e+00 9.7666596945726880e-02 + 17 2.3099360535750506e+00 -2.3017831004883886e+00 1.3305794265747686e+00 + 18 2.2091748314094701e+00 3.3564440703097080e+00 -3.8370878208998480e+00 + 19 1.5986312961639815e+00 2.9614993054417287e+00 -4.5778944294436021e+00 + 20 2.8405364052167421e+00 4.0335971973474170e+00 -4.2659151034329339e+00 + 21 5.2651527410670678e+00 -4.4761614286515128e+00 -3.9518304737634447e+00 + 22 4.7192922284117014e+00 -4.6119045765637390e+00 -4.8062296930647124e+00 + 23 6.1127575782518644e+00 -3.9811721108739997e+00 -4.2204729624242692e+00 + 24 2.1290800761933255e+00 3.5132841007593623e+00 3.5392070209389175e+00 + 25 1.3519459804490630e+00 3.6349473854278020e+00 2.8807586653452137e+00 + 26 2.6413474233716503e+00 4.3893648735951771e+00 3.6035699967293215e+00 + 27 -2.3204235087828389e+00 -4.7905434153250859e+00 2.3919287951691697e+00 + 28 -3.1811356909797261e+00 -4.4206486004501846e+00 1.8095625809312565e+00 + 29 -1.6019226098503827e+00 -3.9551927030786480e+00 2.5663248522869146e+00 run_vel: ! |2 1 7.7867804888392077e-04 5.8970331623292821e-04 -2.2179517633030531e-04 2 2.7129529964126462e-03 4.6286427111164284e-03 3.5805549693846352e-03 @@ -62,15 +62,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 7.2384391134040955e-04 -6.0015829216475349e-04 1.5957533238985767e-03 - 19 1.7583138221050250e-03 -3.0158245947715639e-03 2.0310435057846504e-03 - 20 -1.4153552731881595e-03 9.7835305937683196e-04 9.3881222519315256e-04 - 21 -2.7591188769548157e-03 -5.1180650667742274e-04 2.2758295070616427e-03 - 22 -3.2319732392443201e-03 -3.0809796458321497e-03 2.9861065761939520e-03 - 23 6.9767442924221611e-04 -8.1543313165593767e-03 -8.9929522622873284e-04 - 24 1.7345816996370428e-03 -1.8508160077952193e-03 1.0723416139295039e-03 - 25 3.2855417747190488e-03 -4.5284294759700113e-03 -1.2529298996019375e-03 - 26 -3.4004728773874863e-03 8.5952141315486798e-04 5.0505027866838918e-03 + 18 7.2384391131466962e-04 -6.0015829212802744e-04 1.5957533238990557e-03 + 19 1.7583138222551382e-03 -3.0158245948490800e-03 2.0310435058142466e-03 + 20 -1.4153552732353322e-03 9.7835305930749246e-04 9.3881222516217452e-04 + 21 -2.7591188772323472e-03 -5.1180650802276303e-04 2.2758295071994400e-03 + 22 -3.2319732401280494e-03 -3.0809796427949646e-03 2.9861065768383484e-03 + 23 6.9767443123301817e-04 -8.1543313142268207e-03 -8.9929522742256325e-04 + 24 1.7345816999787503e-03 -1.8508160062822960e-03 1.0723416147087285e-03 + 25 3.2855417755407170e-03 -4.5284294762327620e-03 -1.2529299007822620e-03 + 26 -3.4004728795728927e-03 8.5952140737749570e-04 5.0505027847540657e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml index b11626104d..ee40036bf9 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:57 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nve @@ -13,65 +13,65 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.4245356938010630e+03 -1.4496493316651863e+03 -3.6144360982531375e+03 8.4840626794791422e+02 2.0318336802435149e+02 -6.0622397695991776e+02 + -1.4245356938011612e+03 -1.4496493316650422e+03 -3.6144360982532016e+03 8.4840626794792297e+02 2.0318336802442892e+02 -6.0622397695978816e+02 global_scalar: 15.7115214231781 run_pos: ! |2 - 1 -2.7899546863889757e-01 2.4731857340328407e+00 -1.7290667740246246e-01 - 2 3.0296221610270047e-01 2.9517129916957696e+00 -8.5798904387773733e-01 - 3 -6.9368802364133009e-01 1.2445115421754502e+00 -6.2281111198657968e-01 - 4 -1.5764879647102630e+00 1.4919714415841832e+00 -1.2492069414675773e+00 - 5 -8.9434512967433699e-01 9.3651699743513128e-01 4.0191726558252272e-01 - 6 2.9454439634454876e-01 2.2724545792546230e-01 -1.2845195053960661e+00 - 7 3.4049112903278611e-01 -9.4655678322095593e-03 -2.4634480020857445e+00 - 8 1.1644354555804766e+00 -4.8367776650961408e-01 -6.7663643940736429e-01 - 9 1.3781717822695931e+00 -2.5332509530012332e-01 2.6864954436590760e-01 - 10 2.0186368606041754e+00 -1.4285861423625910e+00 -9.6712491252777666e-01 - 11 1.7929137227577672e+00 -1.9875455388407388e+00 -1.8836565352266459e+00 - 12 3.0032775230399946e+00 -4.8983022415176181e-01 -1.6190248017342788e+00 - 13 4.0448964162126213e+00 -9.0213155122394928e-01 -1.6385398399478248e+00 - 14 2.6035151245016692e+00 -4.0874995493219357e-01 -2.6555999074785932e+00 - 15 2.9761196776172660e+00 5.6287237454106087e-01 -1.2442626196082420e+00 - 16 2.6517373021565369e+00 -2.3957035508394062e+00 3.3389262100735007e-02 - 17 2.2311114924743678e+00 -2.1018393228798926e+00 1.1496088522377799e+00 - 18 2.1390642573193248e+00 3.0164773560690969e+00 -3.5143984803853079e+00 - 19 1.5353246655137389e+00 2.6305911186311701e+00 -4.2455871034735111e+00 - 20 2.7649421538927594e+00 3.6818603528429303e+00 -3.9364115785986051e+00 - 21 4.9043112657306356e+00 -4.0774268210394267e+00 -3.6200836396131266e+00 - 22 4.3665322424289670e+00 -4.2075138112951516e+00 -4.4636587264886334e+00 - 23 5.7355405581991068e+00 -3.5789558641903501e+00 -3.8805763324092997e+00 - 24 2.0692780332812601e+00 3.1504920436415342e+00 3.1571131300669530e+00 - 25 1.3007297593170202e+00 3.2745259354176830e+00 2.5110163874105687e+00 - 26 2.5819416446100352e+00 4.0104903120757118e+00 3.2150249624525613e+00 + 1 -2.7899546863905123e-01 2.4731857340327181e+00 -1.7290667740231969e-01 + 2 3.0296221610252227e-01 2.9517129916957194e+00 -8.5798904387756503e-01 + 3 -6.9368802364141247e-01 1.2445115421753310e+00 -6.2281111198650718e-01 + 4 -1.5764879647103560e+00 1.4919714415840475e+00 -1.2492069414674947e+00 + 5 -8.9434512967440649e-01 9.3651699743494377e-01 4.0191726558257690e-01 + 6 2.9454439634452678e-01 2.2724545792543693e-01 -1.2845195053960459e+00 + 7 3.4049112903278234e-01 -9.4655678321664549e-03 -2.4634480020857370e+00 + 8 1.1644354555804921e+00 -4.8367776650962330e-01 -6.7663643940738027e-01 + 9 1.3781717822695918e+00 -2.5332509530017322e-01 2.6864954436590494e-01 + 10 2.0186368606042460e+00 -1.4285861423625348e+00 -9.6712491252784183e-01 + 11 1.7929137227578726e+00 -1.9875455388406436e+00 -1.8836565352267429e+00 + 12 3.0032775230400142e+00 -4.8983022415161337e-01 -1.6190248017342870e+00 + 13 4.0448964162126639e+00 -9.0213155122374034e-01 -1.6385398399478515e+00 + 14 2.6035151245016883e+00 -4.0874995493201027e-01 -2.6555999074785985e+00 + 15 2.9761196776172243e+00 5.6287237454118566e-01 -1.2442626196081918e+00 + 16 2.6517373021566577e+00 -2.3957035508393689e+00 3.3389262100618433e-02 + 17 2.2311114924744668e+00 -2.1018393228799419e+00 1.1496088522376777e+00 + 18 2.1390642573199212e+00 3.0164773560692755e+00 -3.5143984803853900e+00 + 19 1.5353246655143720e+00 2.6305911186314508e+00 -4.2455871034736816e+00 + 20 2.7649421538935122e+00 3.6818603528430254e+00 -3.9364115785985936e+00 + 21 4.9043112657301942e+00 -4.0774268210396798e+00 -3.6200836396129796e+00 + 22 4.3665322424286144e+00 -4.2075138112953070e+00 -4.4636587264885614e+00 + 23 5.7355405581987764e+00 -3.5789558641907195e+00 -3.8805763324090350e+00 + 24 2.0692780332810026e+00 3.1504920436416008e+00 3.1571131300668833e+00 + 25 1.3007297593168636e+00 3.2745259354178766e+00 2.5110163874103986e+00 + 26 2.5819416446099002e+00 4.0104903120757012e+00 3.2150249624525742e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 4.7093289825842822e-04 2.6351122778447077e-04 -4.4905093064114498e-04 - 2 4.9594625316470929e-04 9.4561370489625745e-05 -5.4581359894047363e-04 - 3 3.3306085115756277e-04 2.3224943880672107e-04 -2.3659455671746167e-04 - 4 3.3692327392261439e-04 2.1926810694049314e-04 -2.4716631558863080e-04 - 5 3.3642542694186029e-04 4.1797578013264637e-04 -1.8011341766657562e-04 - 6 2.0926869754934836e-04 2.6449308951571896e-05 -1.0508938983872182e-04 - 7 1.4629043007908084e-04 -1.6873376665350970e-04 -6.8354048774359419e-05 - 8 1.5844101624224778e-04 3.7728761274000532e-05 -1.9162715667091917e-05 - 9 2.1299362072601795e-04 1.6917140529157899e-04 -6.3528165037841878e-05 - 10 5.4261629412252272e-05 -9.4655528376805682e-05 1.0511362869146485e-04 - 11 -3.2194160796505001e-05 -2.2025095264758494e-04 2.0300202946211710e-04 - 12 1.2640586304750337e-04 -2.9851080445663953e-04 -7.9476371818245541e-05 - 13 8.4523575162141496e-05 -4.0583135407328702e-04 -4.7551111331698668e-05 - 14 9.9954050381271663e-05 -4.2610816481297622e-04 -7.9255633594383908e-05 - 15 2.4417481119789943e-04 -2.3521002264676751e-04 -2.4875318161048533e-04 - 16 -9.0958138549712697e-06 3.7774817121341365e-06 2.4035199548835218e-04 - 17 5.7507224523607053e-05 2.2629217444844902e-04 2.0686920072685291e-04 - 18 2.9220264989358690e-04 -6.2478376436779113e-04 8.4222594596602713e-04 - 19 2.0572616567795615e-04 -5.0334424271708381e-04 8.4953929443210246e-04 - 20 4.1224811789515093e-04 -7.4115205415990477e-04 8.3678612337509482e-04 - 21 -1.0671858777655896e-03 -1.1531171045501079e-03 7.3720674900162972e-04 - 22 -1.1066511338291411e-03 -1.0433933757601768e-03 7.4544544325708855e-04 - 23 -9.7629260480932688e-04 -1.3100872491595415e-03 7.2687284219706961e-04 - 24 4.3308126651255062e-04 -6.6527658087326986e-04 8.4451298670662164e-04 - 25 4.4565811905435875e-04 -5.1298436273585293e-04 8.5878867884519347e-04 - 26 5.9865972692021269e-04 -7.6385263287081313e-04 8.4259943226841743e-04 + 1 4.7093289825841293e-04 2.6351122778450878e-04 -4.4905093064113820e-04 + 2 4.9594625316469953e-04 9.4561370489667690e-05 -5.4581359894048231e-04 + 3 3.3306085115754900e-04 2.3224943880673573e-04 -2.3659455671744771e-04 + 4 3.3692327392259743e-04 2.1926810694050262e-04 -2.4716631558861427e-04 + 5 3.3642542694184180e-04 4.1797578013266394e-04 -1.8011341766654835e-04 + 6 2.0926869754934465e-04 2.6449308951570318e-05 -1.0508938983871884e-04 + 7 1.4629043007908249e-04 -1.6873376665352393e-04 -6.8354048774366371e-05 + 8 1.5844101624224789e-04 3.7728761273996988e-05 -1.9162715667088746e-05 + 9 2.1299362072601516e-04 1.6917140529158729e-04 -6.3528165037833679e-05 + 10 5.4261629412260051e-05 -9.4655528376821931e-05 1.0511362869146147e-04 + 11 -3.2194160796493915e-05 -2.2025095264761762e-04 2.0300202946211090e-04 + 12 1.2640586304751801e-04 -2.9851080445664316e-04 -7.9476371818270898e-05 + 13 8.4523575162162963e-05 -4.0583135407329249e-04 -4.7551111331733104e-05 + 14 9.9954050381287994e-05 -4.2610816481298853e-04 -7.9255633594414862e-05 + 15 2.4417481119791065e-04 -2.3521002264675271e-04 -2.4875318161051281e-04 + 16 -9.0958138549621353e-06 3.7774817121143600e-06 2.4035199548835649e-04 + 17 5.7507224523608761e-05 2.2629217444844084e-04 2.0686920072687044e-04 + 18 2.9220264989358500e-04 -6.2478376436791039e-04 8.4222594596602756e-04 + 19 2.0572616567796797e-04 -5.0334424271721316e-04 8.4953929443210886e-04 + 20 4.1224811789512605e-04 -7.4115205416005038e-04 8.3678612337508614e-04 + 21 -1.0671858777656232e-03 -1.1531171045500114e-03 7.3720674900161617e-04 + 22 -1.1066511338291647e-03 -1.0433933757601002e-03 7.4544544325707944e-04 + 23 -9.7629260480938673e-04 -1.3100872491594617e-03 7.2687284219704544e-04 + 24 4.3308126651259079e-04 -6.6527658087322801e-04 8.4451298670663660e-04 + 25 4.4565811905441442e-04 -5.1298436273583461e-04 8.5878867884521515e-04 + 26 5.9865972692023438e-04 -7.6385263287079188e-04 8.4259943226842502e-04 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml index 733ae4bed0..d422c3d56e 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:57 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nve @@ -13,8 +13,8 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200114783104425e+01 -2.6907707681632978e+01 -6.0080872466970643e+00 -2.5620425754068116e+01 -1.3450222537284642e+01 -1.4947348675137455e+00 -global_scalar: 18.3405601681427 + -4.9200114774917928e+01 -2.6907707694141234e+01 -6.0080872444876876e+00 -2.5620425756344922e+01 -1.3450222538011758e+01 -1.4947348732783965e+00 +global_scalar: 18.3405601673644 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 2 3.0197083955402204e-01 2.9515239068888608e+00 -8.5689735572907566e-01 @@ -33,15 +33,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1392027588259426e+00 3.0171068018410385e+00 -3.5144628518857144e+00 - 19 1.5366124996933792e+00 2.6286809834308120e+00 -4.2452547844370390e+00 - 20 2.7628161763644057e+00 3.6842251687447973e+00 -3.9370881219349219e+00 - 21 4.9036621348239384e+00 -4.0757648444484591e+00 -3.6192617654929755e+00 - 22 4.3655322292403929e+00 -4.2084949963658875e+00 -4.4622011118416509e+00 - 23 5.7380414791158731e+00 -3.5841969190355476e+00 -3.8827839827804009e+00 - 24 2.0701314764430689e+00 3.1499370533656190e+00 3.1565324853444698e+00 - 25 1.3030170721374641e+00 3.2711173928413317e+00 2.5081940917372791e+00 - 26 2.5776230786045939e+00 4.0127347066259897e+00 3.2182355135086644e+00 + 18 2.1392027588270928e+00 3.0171068018423082e+00 -3.5144628518853867e+00 + 19 1.5366124996934336e+00 2.6286809834236959e+00 -4.2452547844313493e+00 + 20 2.7628161763597592e+00 3.6842251687468450e+00 -3.9370881219419189e+00 + 21 4.9036621348471368e+00 -4.0757648444604762e+00 -3.6192617654906609e+00 + 22 4.3655322292129357e+00 -4.2084949964269480e+00 -4.4622011117992786e+00 + 23 5.7380414790507261e+00 -3.5841969189265162e+00 -3.8827839828320116e+00 + 24 2.0701314764933532e+00 3.1499370533556008e+00 3.1565324853054118e+00 + 25 1.3030170721038390e+00 3.2711173927738786e+00 2.5081940917867680e+00 + 26 2.5776230784374867e+00 4.0127347067334345e+00 3.2182355136150917e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095274778e-04 -3.1032459262586538e-04 8.1043030117478813e-04 - 19 8.5103884663454885e-04 -1.4572280597095664e-03 1.0163621287550262e-03 - 20 -6.5204659274983282e-04 4.3989037446081253e-04 4.9909839028816031e-04 - 21 -1.3888125887768562e-03 -3.1978049174111308e-04 1.1455681505473695e-03 - 22 -1.6084223472408303e-03 -1.5355394238968283e-03 1.4772010818589064e-03 - 23 2.6392672559722471e-04 -3.9375414420642855e-03 -3.6991583288341215e-04 - 24 8.6062827042478272e-04 -9.4179873506334698e-04 5.5396395546095079e-04 - 25 1.5933645477524169e-03 -2.2139156628045906e-03 -5.5078029709943800e-04 - 26 -1.5679561733890394e-03 3.5146224505577979e-04 2.4446924196328459e-03 + 18 3.6149625094898083e-04 -3.1032459262177046e-04 8.1043030117471950e-04 + 19 8.5103884664914189e-04 -1.4572280597118458e-03 1.0163621287571445e-03 + 20 -6.5204659274939046e-04 4.3989037444674766e-04 4.9909839028631543e-04 + 21 -1.3888125888095134e-03 -3.1978049191290828e-04 1.1455681505629727e-03 + 22 -1.6084223473476298e-03 -1.5355394235202365e-03 1.4772010819351848e-03 + 23 2.6392672583440695e-04 -3.9375414417551127e-03 -3.6991583302200246e-04 + 24 8.6062827046548757e-04 -9.4179873487668705e-04 5.5396395555797225e-04 + 25 1.5933645478462869e-03 -2.2139156628290971e-03 -5.5078029723781006e-04 + 26 -1.5679561736454228e-03 3.5146224433513598e-04 2.4446924193838983e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml index 19416939d5..d72a0ff3b7 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:58 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nve @@ -13,26 +13,26 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.3754817467882001e+03 -1.4228425246443051e+03 -3.6087196200592211e+03 8.7407043142561224e+02 2.1665316510417915e+02 -6.0480791467760923e+02 -global_scalar: 4.53142303857025 + -1.3754817467882772e+03 -1.4228425246441275e+03 -3.6087196200592480e+03 8.7407043142559348e+02 2.1665316510426322e+02 -6.0480791467747576e+02 +global_scalar: 4.53142303857033 run_pos: ! |2 - 1 -2.7899546859691271e-01 2.4731857340428940e+00 -1.7290667720880570e-01 - 2 3.0296221616799635e-01 2.9517129917211671e+00 -8.5798904365355999e-01 - 3 -6.9368802362164272e-01 1.2445115422150048e+00 -6.2281111185293192e-01 - 4 -1.5764879646738923e+00 1.4919714416722523e+00 -1.2492069413382727e+00 - 5 -8.9434512967957924e-01 9.3651699743540839e-01 4.0191726569948305e-01 - 6 2.9454439635069130e-01 2.2724545796945167e-01 -1.2845195052894625e+00 - 7 3.4049112905320356e-01 -9.4655677385257209e-03 -2.4634480019885614e+00 - 8 1.1644354555589551e+00 -4.8367776651302752e-01 -6.7663643931661333e-01 - 9 1.3781717822376145e+00 -2.5332509534949033e-01 2.6864954447022071e-01 - 10 2.0186368605645622e+00 -1.4285861423743027e+00 -9.6712491246322974e-01 - 11 1.7929137227201126e+00 -1.9875455388074434e+00 -1.8836565351900285e+00 - 12 3.0032775230343445e+00 -4.8983022415937488e-01 -1.6190248016125284e+00 - 13 4.0448964161972523e+00 -9.0213155125610900e-01 -1.6385398398261353e+00 - 14 2.6035151245156194e+00 -4.0874995488538468e-01 -2.6555999073601440e+00 - 15 2.9761196776309022e+00 5.6287237451795524e-01 -1.2442626194415798e+00 - 16 2.6517373020763406e+00 -2.3957035509096727e+00 3.3389262134360442e-02 - 17 2.2311114923823547e+00 -2.1018393229880195e+00 1.1496088522769190e+00 + 1 -2.7899546859706881e-01 2.4731857340427750e+00 -1.7290667720866193e-01 + 2 3.0296221616781649e-01 2.9517129917211218e+00 -8.5798904365338713e-01 + 3 -6.9368802362172777e-01 1.2445115422148878e+00 -6.2281111185285920e-01 + 4 -1.5764879646739900e+00 1.4919714416721197e+00 -1.2492069413381908e+00 + 5 -8.9434512967965252e-01 9.3651699743522254e-01 4.0191726569953845e-01 + 6 2.9454439635066831e-01 2.2724545796942719e-01 -1.2845195052894431e+00 + 7 3.4049112905319934e-01 -9.4655677384814507e-03 -2.4634480019885556e+00 + 8 1.1644354555589707e+00 -4.8367776651303718e-01 -6.7663643931662931e-01 + 9 1.3781717822376129e+00 -2.5332509534954067e-01 2.6864954447021949e-01 + 10 2.0186368605646337e+00 -1.4285861423742481e+00 -9.6712491246329535e-01 + 11 1.7929137227202196e+00 -1.9875455388073511e+00 -1.8836565351901273e+00 + 12 3.0032775230343667e+00 -4.8983022415922672e-01 -1.6190248016125368e+00 + 13 4.0448964161972993e+00 -9.0213155125590028e-01 -1.6385398398261621e+00 + 14 2.6035151245156412e+00 -4.0874995488520105e-01 -2.6555999073601511e+00 + 15 2.9761196776308623e+00 5.6287237451808192e-01 -1.2442626194415292e+00 + 16 2.6517373020764632e+00 -2.3957035509096389e+00 3.3389262134244646e-02 + 17 2.2311114923824555e+00 -2.1018393229880719e+00 1.1496088522768189e+00 18 2.1384791188033843e+00 3.0177261773770208e+00 -3.5160827596876225e+00 19 1.5349125211132961e+00 2.6315969880333707e+00 -4.2472859440220647e+00 20 2.7641167828863153e+00 3.6833419064000221e+00 -3.9380850623312638e+00 @@ -46,23 +46,23 @@ run_pos: ! |2 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 4.7093296226166030e-04 2.6351124312056276e-04 -4.4905063547614088e-04 - 2 4.9594635271877621e-04 9.4561409237131533e-05 -5.4581325723052814e-04 - 3 3.3306088119083302e-04 2.3224949911014063e-04 -2.3659435306900835e-04 - 4 3.3692332940286982e-04 2.1926824120527540e-04 -2.4716611858556823e-04 - 5 3.3642541894624174e-04 4.1797578053942325e-04 -1.8011323945928826e-04 - 6 2.0926870695908416e-04 2.6449376032433866e-05 -1.0508922741401649e-04 - 7 1.4629046128363069e-04 -1.6873362379724041e-04 -6.8353900724078427e-05 - 8 1.5844098346817965e-04 3.7728756087618508e-05 -1.9162577392849601e-05 - 9 2.1299357198252983e-04 1.6917133003967010e-04 -6.3528006071196204e-05 - 10 5.4261569071245287e-05 -9.4655546204693502e-05 1.0511372702289562e-04 - 11 -3.2194218121523810e-05 -2.2025090185602106e-04 2.0300208519292106e-04 - 12 1.2640585449263605e-04 -2.9851081600945606e-04 -7.9476186245574772e-05 - 13 8.4523551795102371e-05 -4.0583140303606291e-04 -4.7550925831929232e-05 - 14 9.9954071734164831e-05 -4.2610809338913152e-04 -7.9255453072665335e-05 - 15 2.4417483202630110e-04 -2.3521005781667857e-04 -2.4875292755151528e-04 - 16 -9.0959360838858137e-06 3.7773746063309333e-06 2.4035204669042528e-04 - 17 5.7507084250805080e-05 2.2629200960630369e-04 2.0686926033794975e-04 + 1 4.7093296226164512e-04 2.6351124312060207e-04 -4.4905063547613525e-04 + 2 4.9594635271876732e-04 9.4561409237174874e-05 -5.4581325723053746e-04 + 3 3.3306088119081914e-04 2.3224949911015690e-04 -2.3659435306899615e-04 + 4 3.3692332940285356e-04 2.1926824120528714e-04 -2.4716611858555419e-04 + 5 3.3642541894622217e-04 4.1797578053944228e-04 -1.8011323945926297e-04 + 6 2.0926870695908053e-04 2.6449376032433595e-05 -1.0508922741401471e-04 + 7 1.4629046128363337e-04 -1.6873362379725315e-04 -6.8353900724086707e-05 + 8 1.5844098346817900e-04 3.7728756087615784e-05 -1.9162577392846985e-05 + 9 2.1299357198252555e-04 1.6917133003967901e-04 -6.3528006071188276e-05 + 10 5.4261569071252172e-05 -9.4655546204709209e-05 1.0511372702289220e-04 + 11 -3.2194218121513158e-05 -2.2025090185605299e-04 2.0300208519291455e-04 + 12 1.2640585449265077e-04 -2.9851081600945932e-04 -7.9476186245599193e-05 + 13 8.4523551795123811e-05 -4.0583140303606844e-04 -4.7550925831962043e-05 + 14 9.9954071734182138e-05 -4.2610809338914323e-04 -7.9255453072695788e-05 + 15 2.4417483202631259e-04 -2.3521005781666340e-04 -2.4875292755154174e-04 + 16 -9.0959360838789561e-06 3.7773746063112143e-06 2.4035204669043016e-04 + 17 5.7507084250803752e-05 2.2629200960629542e-04 2.0686926033796743e-04 18 -6.0936815808025862e-04 -9.3774557532468582e-04 -3.3558072507805731e-04 19 -6.9919768291957119e-04 -3.6060777270430031e-03 4.2833405289822791e-03 20 4.7777805013736515e-03 5.1003745845520452e-03 1.8002873923729241e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml index 799e039bae..74121559aa 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:58 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nve/small @@ -13,8 +13,8 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200114783104425e+01 -2.6907707681632978e+01 -6.0080872466970643e+00 -2.5620425754068116e+01 -1.3450222537284642e+01 -1.4947348675137455e+00 -global_scalar: 0.500731871980239 + -4.9200114774917928e+01 -2.6907707694141234e+01 -6.0080872444876876e+00 -2.5620425756344922e+01 -1.3450222538011758e+01 -1.4947348732783965e+00 +global_scalar: 0.50073187196632 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 2 3.0197083955402204e-01 2.9515239068888608e+00 -8.5689735572907566e-01 @@ -33,15 +33,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1392027588259426e+00 3.0171068018410385e+00 -3.5144628518857144e+00 - 19 1.5366124996933792e+00 2.6286809834308120e+00 -4.2452547844370390e+00 - 20 2.7628161763644057e+00 3.6842251687447973e+00 -3.9370881219349219e+00 - 21 4.9036621348239384e+00 -4.0757648444484591e+00 -3.6192617654929755e+00 - 22 4.3655322292403929e+00 -4.2084949963658875e+00 -4.4622011118416509e+00 - 23 5.7380414791158731e+00 -3.5841969190355476e+00 -3.8827839827804009e+00 - 24 2.0701314764430689e+00 3.1499370533656190e+00 3.1565324853444698e+00 - 25 1.3030170721374641e+00 3.2711173928413317e+00 2.5081940917372791e+00 - 26 2.5776230786045939e+00 4.0127347066259897e+00 3.2182355135086644e+00 + 18 2.1392027588270928e+00 3.0171068018423082e+00 -3.5144628518853867e+00 + 19 1.5366124996934336e+00 2.6286809834236959e+00 -4.2452547844313493e+00 + 20 2.7628161763597592e+00 3.6842251687468450e+00 -3.9370881219419189e+00 + 21 4.9036621348471368e+00 -4.0757648444604762e+00 -3.6192617654906609e+00 + 22 4.3655322292129357e+00 -4.2084949964269480e+00 -4.4622011117992786e+00 + 23 5.7380414790507261e+00 -3.5841969189265162e+00 -3.8827839828320116e+00 + 24 2.0701314764933532e+00 3.1499370533556008e+00 3.1565324853054118e+00 + 25 1.3030170721038390e+00 3.2711173927738786e+00 2.5081940917867680e+00 + 26 2.5776230784374867e+00 4.0127347067334345e+00 3.2182355136150917e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095274778e-04 -3.1032459262586538e-04 8.1043030117478813e-04 - 19 8.5103884663454885e-04 -1.4572280597095664e-03 1.0163621287550262e-03 - 20 -6.5204659274983282e-04 4.3989037446081253e-04 4.9909839028816031e-04 - 21 -1.3888125887768562e-03 -3.1978049174111308e-04 1.1455681505473695e-03 - 22 -1.6084223472408303e-03 -1.5355394238968283e-03 1.4772010818589064e-03 - 23 2.6392672559722471e-04 -3.9375414420642855e-03 -3.6991583288341215e-04 - 24 8.6062827042478272e-04 -9.4179873506334698e-04 5.5396395546095079e-04 - 25 1.5933645477524169e-03 -2.2139156628045906e-03 -5.5078029709943800e-04 - 26 -1.5679561733890394e-03 3.5146224505577979e-04 2.4446924196328459e-03 + 18 3.6149625094898083e-04 -3.1032459262177046e-04 8.1043030117471950e-04 + 19 8.5103884664914189e-04 -1.4572280597118458e-03 1.0163621287571445e-03 + 20 -6.5204659274939046e-04 4.3989037444674766e-04 4.9909839028631543e-04 + 21 -1.3888125888095134e-03 -3.1978049191290828e-04 1.1455681505629727e-03 + 22 -1.6084223473476298e-03 -1.5355394235202365e-03 1.4772010819351848e-03 + 23 2.6392672583440695e-04 -3.9375414417551127e-03 -3.6991583302200246e-04 + 24 8.6062827046548757e-04 -9.4179873487668705e-04 5.5396395555797225e-04 + 25 1.5933645478462869e-03 -2.2139156628290971e-03 -5.5078029723781006e-04 + 26 -1.5679561736454228e-03 3.5146224433513598e-04 2.4446924193838983e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nvt.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nvt.yaml index d2950b829d..8a3a1d9c31 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nvt.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nvt.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:36:59 202 epsilon: 5e-13 prerequisites: ! | atom full @@ -12,26 +12,26 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.3123962047751329e+03 -1.3675423591737690e+03 -3.5468492999580276e+03 7.8271738572462300e+02 2.6480486115425720e+02 -7.6950536863901277e+02 -global_scalar: 68.0865964742217 + -1.3123962047757550e+03 -1.3675423591710455e+03 -3.5468492999583855e+03 7.8271738572396384e+02 2.6480486115495091e+02 -7.6950536863736306e+02 +global_scalar: 68.0865964742317 run_pos: ! |2 - 1 -2.7802951913770868e-01 2.4737132264328308e+00 -1.7381271738810056e-01 - 2 3.0397800832728550e-01 2.9519031941438283e+00 -8.5908822750516822e-01 - 3 -6.9299720296286593e-01 1.2449766685883559e+00 -6.2329294828441417e-01 - 4 -1.5757894675962001e+00 1.4924105480993224e+00 -1.2497098747252475e+00 - 5 -8.9364750934319548e-01 9.3735293261268249e-01 4.0154813851909255e-01 - 6 2.9498813449207129e-01 2.2729986883011363e-01 -1.2847387164263608e+00 - 7 3.4080910885033866e-01 -9.8008218366116284e-03 -2.4635938021180581e+00 - 8 1.1647778042703230e+00 -4.8360070140693001e-01 -6.7668409924195017e-01 - 9 1.3786230528159205e+00 -2.5298559880078242e-01 2.6851325883864419e-01 - 10 2.0187712935455902e+00 -1.4287732348430000e+00 -9.6692440387054135e-01 - 11 1.7928755785816499e+00 -1.9879833661326805e+00 -1.8832605388676149e+00 - 12 3.0035558347416837e+00 -4.9042429038483137e-01 -1.6191927838344911e+00 - 13 4.0450911337524778e+00 -9.0293975523458492e-01 -1.6386440514131717e+00 - 14 2.6037405819191823e+00 -4.0959881564364919e-01 -2.6557674031620193e+00 - 15 2.9766330093341349e+00 5.6240461100592032e-01 -1.2447686007440930e+00 - 16 2.6517453810130034e+00 -2.3956939898031364e+00 3.3859750044474057e-02 - 17 2.2312525656134730e+00 -2.1013855689257279e+00 1.1500124166849996e+00 + 1 -2.7802951913990959e-01 2.4737132264311215e+00 -1.7381271738602289e-01 + 2 3.0397800832473609e-01 2.9519031941431444e+00 -8.5908822750267100e-01 + 3 -6.9299720296404743e-01 1.2449766685866726e+00 -6.2329294828335358e-01 + 4 -1.5757894675975461e+00 1.4924105480974301e+00 -1.2497098747240374e+00 + 5 -8.9364750934418624e-01 9.3735293261000852e-01 4.0154813851989335e-01 + 6 2.9498813449175199e-01 2.2729986882976547e-01 -1.2847387164260673e+00 + 7 3.4080910885027837e-01 -9.8008218359699473e-03 -2.4635938021179546e+00 + 8 1.1647778042705452e+00 -4.8360070140706557e-01 -6.7668409924218165e-01 + 9 1.3786230528159027e+00 -2.5298559880150862e-01 2.6851325883861188e-01 + 10 2.0187712935465942e+00 -1.4287732348422091e+00 -9.6692440387148870e-01 + 11 1.7928755785831587e+00 -1.9879833661313322e+00 -1.8832605388690278e+00 + 12 3.0035558347419657e+00 -4.9042429038271507e-01 -1.6191927838346238e+00 + 13 4.0450911337530959e+00 -9.0293975523160919e-01 -1.6386440514135796e+00 + 14 2.6037405819194577e+00 -4.0959881564101863e-01 -2.6557674031621108e+00 + 15 2.9766330093335447e+00 5.6240461100771322e-01 -1.2447686007433758e+00 + 16 2.6517453810147344e+00 -2.3956939898026426e+00 3.3859750042781744e-02 + 17 2.2312525656149020e+00 -2.1013855689264771e+00 1.1500124166835219e+00 18 2.1384791188033843e+00 3.0177261773770208e+00 -3.5160827596876225e+00 19 1.5349125211132961e+00 2.6315969880333707e+00 -4.2472859440220647e+00 20 2.7641167828863153e+00 3.6833419064000221e+00 -3.9380850623312638e+00 @@ -45,23 +45,23 @@ run_pos: ! |2 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 1.8443993556510503e-03 1.0121779579994334e-03 -1.7361326034903994e-03 - 2 1.9401022924564379e-03 3.6428754787360968e-04 -2.1069540627800783e-03 - 3 1.3158623602991188e-03 8.9265747656383358e-04 -9.2144725682236322e-04 - 4 1.3306255280105470e-03 8.4281508655937773e-04 -9.6194026572644226e-04 - 5 1.3289682243421974e-03 1.6048237018825233e-03 -7.0511232123213988e-04 - 6 8.4113718611853719e-04 1.0389683283150482e-04 -4.1697370456886506e-04 - 7 5.9950574545609200e-04 -6.4437674895145240e-04 -2.7586696717539212e-04 - 8 6.4634547270653927e-04 1.4734228826541389e-04 -8.7540766366893413e-05 - 9 8.5561404484529586e-04 6.5123532540296175e-04 -2.5782947158571319e-04 - 10 2.4688038968437656e-04 -3.5995975343979376e-04 3.8912416843293868e-04 - 11 -8.4672359473885383e-05 -8.4134349031467540e-04 7.6463157764253384e-04 - 12 5.2321633256236573e-04 -1.1418047427479729e-03 -3.1842516233433678e-04 - 13 3.6258187754787622e-04 -1.5531581259492578e-03 -1.9590476903839454e-04 - 14 4.2166181631225470e-04 -1.6310415916625015e-03 -3.1740232809197801e-04 - 15 9.7471807923322747e-04 -8.9939841791080669e-04 -9.6757308853273301e-04 - 16 4.1534888644708355e-06 1.7705740203958010e-05 9.0753010117789151e-04 - 17 2.5969943716028801e-04 8.7075266710323401e-04 7.7887058799549764e-04 + 1 1.8443993556501194e-03 1.0121779580014880e-03 -1.7361326034900004e-03 + 2 1.9401022924558353e-03 3.6428754787592717e-04 -2.1069540627804630e-03 + 3 1.3158623602983117e-03 8.9265747656461518e-04 -9.2144725682164765e-04 + 4 1.3306255280096098e-03 8.4281508655990065e-04 -9.6194026572564277e-04 + 5 1.3289682243410694e-03 1.6048237018834058e-03 -7.0511232123071578e-04 + 6 8.4113718611833759e-04 1.0389683283144291e-04 -4.1697370456874000e-04 + 7 5.9950574545626460e-04 -6.4437674895215539e-04 -2.7586696717582770e-04 + 8 6.4634547270651889e-04 1.4734228826522393e-04 -8.7540766366731677e-05 + 9 8.5561404484505246e-04 6.5123532540337949e-04 -2.5782947158524541e-04 + 10 2.4688038968480883e-04 -3.5995975344065598e-04 3.8912416843275036e-04 + 11 -8.4672359473207540e-05 -8.4134349031640384e-04 7.6463157764214765e-04 + 12 5.2321633256319677e-04 -1.1418047427480885e-03 -3.1842516233562650e-04 + 13 3.6258187754908706e-04 -1.5531581259494627e-03 -1.9590476904013686e-04 + 14 4.2166181631324295e-04 -1.6310415916630534e-03 -3.1740232809360442e-04 + 15 9.7471807923383419e-04 -8.9939841790992849e-04 -9.6757308853409715e-04 + 16 4.1534888649229478e-06 1.7705740202855492e-05 9.0753010117813307e-04 + 17 2.5969943716026037e-04 8.7075266710270329e-04 7.7887058799645153e-04 18 -6.0936815808025862e-04 -9.3774557532468582e-04 -3.3558072507805731e-04 19 -6.9919768291957119e-04 -3.6060777270430031e-03 4.2833405289822791e-03 20 4.7777805013736515e-03 5.1003745845520452e-03 1.8002873923729241e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml index 5a500df244..654b85416a 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:36:59 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nvt/small @@ -12,8 +12,8 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.4827261120559041e+02 -1.8411194247813761e+01 -1.0752762861073667e+02 -2.1814511473385389e+02 1.7027764309482512e+02 2.1058942295369583e+01 -global_scalar: 0.953260955609303 + -1.4827261116680450e+02 -1.8411194349753366e+01 -1.0752762859308652e+02 -2.1814511477016262e+02 1.7027764307147635e+02 2.1058942244057143e+01 +global_scalar: 0.953260955473961 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 2 3.0197083955402204e-01 2.9515239068888608e+00 -8.5689735572907566e-01 @@ -32,15 +32,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1395635672932589e+00 3.0168023048438113e+00 -3.5136606977881328e+00 - 19 1.5374727853250358e+00 2.6272080573122807e+00 -4.2442423140709664e+00 - 20 2.7621434608188427e+00 3.6846842324656390e+00 -3.9366036440732435e+00 - 21 4.9022821624140818e+00 -4.0760572703872384e+00 -3.6181235131011493e+00 - 22 4.3639257460005378e+00 -4.2100277322528781e+00 -4.4607219431898768e+00 - 23 5.7383384136101201e+00 -3.5881799321988401e+00 -3.8831848686362500e+00 - 24 2.0709922900187094e+00 3.1490053461587988e+00 3.1570777021928111e+00 - 25 1.3046262535950155e+00 3.2688902578411003e+00 2.5076144139609760e+00 - 26 2.5760050692221945e+00 4.0131166908052700e+00 3.2207051908682689e+00 + 18 2.1395635672981443e+00 3.0168023048492310e+00 -3.5136606977867388e+00 + 19 1.5374727853253387e+00 2.6272080572819609e+00 -4.2442423140467360e+00 + 20 2.7621434607990372e+00 3.6846842324743214e+00 -3.9366036441030396e+00 + 21 4.9022821625125470e+00 -4.0760572704380627e+00 -3.6181235130909242e+00 + 22 4.3639257458824501e+00 -4.2100277325126187e+00 -4.4607219430080747e+00 + 23 5.7383384133351401e+00 -3.5881799317362106e+00 -3.8831848688588710e+00 + 24 2.0709922902331592e+00 3.1490053461169678e+00 3.1570777020268803e+00 + 25 1.3046262534530633e+00 3.2688902575528282e+00 2.5076144141701078e+00 + 26 2.5760050685080813e+00 4.0131166912605272e+00 3.2207051913215210e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -62,15 +62,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 7.8522439442960720e-04 -6.6826115066907776e-04 1.7528441282148588e-03 - 19 1.8628941717468176e-03 -3.1840047050999288e-03 2.2062694139862180e-03 - 20 -1.4430972530733339e-03 9.7564145849438695e-04 1.0686492192934641e-03 - 21 -3.0047717243369713e-03 -6.6139343733813178e-04 2.4784169375747654e-03 - 22 -3.4980341561451885e-03 -3.3380963360956396e-03 3.2191613971836179e-03 - 23 5.9333930339444674e-04 -8.6231086246656499e-03 -8.2692040217646409e-04 - 24 1.8727912307154753e-03 -2.0349136837723969e-03 1.1951471744036815e-03 - 25 3.4887365949246578e-03 -4.8232966886339428e-03 -1.2263764476660806e-03 - 26 -3.4770257985509852e-03 7.8662050889240958e-04 5.3381090683576344e-03 + 18 7.8522439440007548e-04 -6.6826115062653757e-04 1.7528441282153480e-03 + 19 1.8628941719211860e-03 -3.1840047051916367e-03 2.2062694140207390e-03 + 20 -1.4430972531298200e-03 9.7564145841628493e-04 1.0686492192569896e-03 + 21 -3.0047717246574372e-03 -6.6139343888744952e-04 2.4784169377340712e-03 + 22 -3.4980341571643780e-03 -3.3380963325930985e-03 3.2191613979274045e-03 + 23 5.9333930569297963e-04 -8.6231086219834985e-03 -8.2692040355627789e-04 + 24 1.8727912311097637e-03 -2.0349136820274911e-03 1.1951471753018509e-03 + 25 3.4887365958745937e-03 -4.8232966889391275e-03 -1.2263764490291341e-03 + 26 -3.4770258010749858e-03 7.8662050223200905e-04 5.3381090661352281e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_single.yaml b/unittest/force-styles/tests/fix-timestep-rigid_single.yaml index 630cc3424d..e419416c7e 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_single.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_single.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:37:00 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid @@ -13,26 +13,26 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.3754817466835852e+03 -1.4228425246165939e+03 -3.6087196201913630e+03 8.7407043149698166e+02 2.1665316519768876e+02 -6.0480791462031175e+02 -global_scalar: 4.53142303857031 + -1.3754817466835989e+03 -1.4228425246166139e+03 -3.6087196201914344e+03 8.7407043149698939e+02 2.1665316519769868e+02 -6.0480791462033017e+02 +global_scalar: 4.53142303857029 run_pos: ! |2 - 1 -2.7899546859693181e-01 2.4731857340428789e+00 -1.7290667720876129e-01 - 2 3.0296221616793595e-01 2.9517129917211555e+00 -8.5798904365355089e-01 - 3 -6.9368802362166315e-01 1.2445115422149753e+00 -6.2281111185285432e-01 - 4 -1.5764879646739509e+00 1.4919714416722003e+00 -1.2492069413381559e+00 - 5 -8.9434512967954460e-01 9.3651699743538708e-01 4.0191726569957620e-01 - 6 2.9454439635065854e-01 2.2724545796943085e-01 -1.2845195052894232e+00 - 7 3.4049112905311674e-01 -9.4655677385591108e-03 -2.4634480019885245e+00 - 8 1.1644354555589662e+00 -4.8367776651302741e-01 -6.7663643931660777e-01 - 9 1.3781717822376685e+00 -2.5332509534947545e-01 2.6864954447021527e-01 - 10 2.0186368605645773e+00 -1.4285861423742925e+00 -9.6712491246325638e-01 - 11 1.7929137227200924e+00 -1.9875455388074488e+00 -1.8836565351900403e+00 - 12 3.0032775230343129e+00 -4.8983022415935262e-01 -1.6190248016126150e+00 - 13 4.0448964161972292e+00 -9.0213155125606903e-01 -1.6385398398262687e+00 - 14 2.6035151245155346e+00 -4.0874995488538102e-01 -2.6555999073602141e+00 - 15 2.9761196776308703e+00 5.6287237451798355e-01 -1.2442626194416762e+00 - 16 2.6517373020764223e+00 -2.3957035509096416e+00 3.3389262134315478e-02 - 17 2.2311114923824862e+00 -2.1018393229879826e+00 1.1496088522768946e+00 + 1 -2.7899546859693136e-01 2.4731857340428784e+00 -1.7290667720876285e-01 + 2 3.0296221616793728e-01 2.9517129917211546e+00 -8.5798904365355155e-01 + 3 -6.9368802362166204e-01 1.2445115422149751e+00 -6.2281111185285498e-01 + 4 -1.5764879646739487e+00 1.4919714416722010e+00 -1.2492069413381564e+00 + 5 -8.9434512967954416e-01 9.3651699743538730e-01 4.0191726569957442e-01 + 6 2.9454439635065910e-01 2.2724545796943096e-01 -1.2845195052894232e+00 + 7 3.4049112905311751e-01 -9.4655677385591108e-03 -2.4634480019885228e+00 + 8 1.1644354555589662e+00 -4.8367776651302724e-01 -6.7663643931660777e-01 + 9 1.3781717822376680e+00 -2.5332509534947545e-01 2.6864954447021416e-01 + 10 2.0186368605645764e+00 -1.4285861423742918e+00 -9.6712491246325605e-01 + 11 1.7929137227200918e+00 -1.9875455388074483e+00 -1.8836565351900385e+00 + 12 3.0032775230343125e+00 -4.8983022415935312e-01 -1.6190248016126132e+00 + 13 4.0448964161972283e+00 -9.0213155125606947e-01 -1.6385398398262669e+00 + 14 2.6035151245155355e+00 -4.0874995488538129e-01 -2.6555999073602123e+00 + 15 2.9761196776308694e+00 5.6287237451798222e-01 -1.2442626194416753e+00 + 16 2.6517373020764219e+00 -2.3957035509096407e+00 3.3389262134315700e-02 + 17 2.2311114923824857e+00 -2.1018393229879817e+00 1.1496088522768926e+00 18 2.1384791188033843e+00 3.0177261773770208e+00 -3.5160827596876225e+00 19 1.5349125211132961e+00 2.6315969880333707e+00 -4.2472859440220647e+00 20 2.7641167828863153e+00 3.6833419064000221e+00 -3.9380850623312638e+00 @@ -46,23 +46,23 @@ run_pos: ! |2 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 4.7093296226165759e-04 2.6351124312057328e-04 -4.4905063547614815e-04 - 2 4.9594635271877263e-04 9.4561409237138648e-05 -5.4581325723053584e-04 - 3 3.3306088119083106e-04 2.3224949911015489e-04 -2.3659435306900921e-04 - 4 3.3692332940286711e-04 2.1926824120529708e-04 -2.4716611858556546e-04 - 5 3.3642541894624088e-04 4.1797578053943778e-04 -1.8011323945929135e-04 - 6 2.0926870695908297e-04 2.6449376032441632e-05 -1.0508922741401441e-04 - 7 1.4629046128362895e-04 -1.6873362379723160e-04 -6.8353900724071678e-05 - 8 1.5844098346817962e-04 3.7728756087619151e-05 -1.9162577392849499e-05 - 9 2.1299357198253027e-04 1.6917133003966806e-04 -6.3528006071200595e-05 - 10 5.4261569071246100e-05 -9.4655546204698788e-05 1.0511372702289762e-04 - 11 -3.2194218121523160e-05 -2.2025090185602363e-04 2.0300208519292848e-04 - 12 1.2640585449263567e-04 -2.9851081600946788e-04 -7.9476186245575856e-05 - 13 8.4523551795102534e-05 -4.0583140303608248e-04 -4.7550925831931509e-05 - 14 9.9954071734163638e-05 -4.2610809338913916e-04 -7.9255453072662124e-05 - 15 2.4417483202630001e-04 -2.3521005781669064e-04 -2.4875292755152092e-04 - 16 -9.0959360838833471e-06 3.7773746063198897e-06 2.4035204669042528e-04 - 17 5.7507084250808007e-05 2.2629200960629450e-04 2.0686926033794596e-04 + 1 4.7093296226165726e-04 2.6351124312057247e-04 -4.4905063547614652e-04 + 2 4.9594635271877252e-04 9.4561409237138173e-05 -5.4581325723053399e-04 + 3 3.3306088119083085e-04 2.3224949911015443e-04 -2.3659435306900835e-04 + 4 3.3692332940286711e-04 2.1926824120529689e-04 -2.4716611858556487e-04 + 5 3.3642541894624033e-04 4.1797578053943675e-04 -1.8011323945929070e-04 + 6 2.0926870695908275e-04 2.6449376032441517e-05 -1.0508922741401380e-04 + 7 1.4629046128362901e-04 -1.6873362379723092e-04 -6.8353900724071163e-05 + 8 1.5844098346817922e-04 3.7728756087618725e-05 -1.9162577392849018e-05 + 9 2.1299357198252964e-04 1.6917133003966706e-04 -6.3528006071199931e-05 + 10 5.4261569071245721e-05 -9.4655546204699004e-05 1.0511372702289778e-04 + 11 -3.2194218121523377e-05 -2.2025090185602322e-04 2.0300208519292837e-04 + 12 1.2640585449263546e-04 -2.9851081600946783e-04 -7.9476186245574907e-05 + 13 8.4523551795102276e-05 -4.0583140303608237e-04 -4.7550925831930506e-05 + 14 9.9954071734163652e-05 -4.2610809338913862e-04 -7.9255453072661283e-05 + 15 2.4417483202629974e-04 -2.3521005781669077e-04 -2.4875292755151935e-04 + 16 -9.0959360838839976e-06 3.7773746063190714e-06 2.4035204669042517e-04 + 17 5.7507084250807059e-05 2.2629200960629290e-04 2.0686926033794590e-04 18 -6.0936815808025862e-04 -9.3774557532468582e-04 -3.3558072507805731e-04 19 -6.9919768291957119e-04 -3.6060777270430031e-03 4.2833405289822791e-03 20 4.7777805013736515e-03 5.1003745845520452e-03 1.8002873923729241e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_small.yaml index d729cd77bc..2c5fa3a2c0 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2.5e-13 +date_generated: Tue Sep 15 22:37:00 202 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/small @@ -13,7 +13,7 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200116134790363e+01 -2.6907707565987732e+01 -6.0080860422282560e+00 -2.5620423972101747e+01 -1.3450224059984075e+01 -1.4947288487004844e+00 + -4.9200116134789894e+01 -2.6907707565987600e+01 -6.0080860422279923e+00 -2.5620423972101459e+01 -1.3450224059984031e+01 -1.4947288487004347e+00 global_scalar: 18.3405601674144 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 @@ -33,15 +33,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1392027588271301e+00 3.0171068018412783e+00 -3.5144628518856349e+00 - 19 1.5366124997074573e+00 2.6286809834111744e+00 -4.2452547844370221e+00 - 20 2.7628161763455852e+00 3.6842251687634779e+00 -3.9370881219352558e+00 - 21 4.9036621347791245e+00 -4.0757648442838548e+00 -3.6192617654515908e+00 + 18 2.1392027588271301e+00 3.0171068018412779e+00 -3.5144628518856349e+00 + 19 1.5366124997074571e+00 2.6286809834111748e+00 -4.2452547844370221e+00 + 20 2.7628161763455852e+00 3.6842251687634775e+00 -3.9370881219352554e+00 + 21 4.9036621347791245e+00 -4.0757648442838548e+00 -3.6192617654515904e+00 22 4.3655322291888483e+00 -4.2084949965552561e+00 -4.4622011117402334e+00 23 5.7380414793463101e+00 -3.5841969195032672e+00 -3.8827839830470219e+00 24 2.0701314765323930e+00 3.1499370533342330e+00 3.1565324852522938e+00 - 25 1.3030170721374783e+00 3.2711173927682244e+00 2.5081940917429759e+00 - 26 2.5776230782480041e+00 4.0127347068243884e+00 3.2182355138709284e+00 + 25 1.3030170721374779e+00 3.2711173927682249e+00 2.5081940917429768e+00 + 26 2.5776230782480045e+00 4.0127347068243875e+00 3.2182355138709275e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095704870e-04 -3.1032459262908302e-04 8.1043030117346052e-04 - 19 8.5103884665345441e-04 -1.4572280596788099e-03 1.0163621287634116e-03 - 20 -6.5204659278590758e-04 4.3989037444289831e-04 4.9909839028507966e-04 - 21 -1.3888125881903919e-03 -3.1978049143082570e-04 1.1455681499836646e-03 - 22 -1.6084223477729497e-03 -1.5355394240821158e-03 1.4772010826232373e-03 - 23 2.6392672378804886e-04 -3.9375414431174760e-03 -3.6991583139728127e-04 - 24 8.6062827067890290e-04 -9.4179873474469259e-04 5.5396395550012367e-04 - 25 1.5933645477487557e-03 -2.2139156625681682e-03 -5.5078029695647412e-04 - 26 -1.5679561743998888e-03 3.5146224354725948e-04 2.4446924193334482e-03 + 18 3.6149625095704908e-04 -3.1032459262908286e-04 8.1043030117346042e-04 + 19 8.5103884665345452e-04 -1.4572280596788108e-03 1.0163621287634116e-03 + 20 -6.5204659278590683e-04 4.3989037444289853e-04 4.9909839028507890e-04 + 21 -1.3888125881903923e-03 -3.1978049143082407e-04 1.1455681499836646e-03 + 22 -1.6084223477729508e-03 -1.5355394240821113e-03 1.4772010826232373e-03 + 23 2.6392672378805081e-04 -3.9375414431174812e-03 -3.6991583139728051e-04 + 24 8.6062827067890236e-04 -9.4179873474469237e-04 5.5396395550012442e-04 + 25 1.5933645477487542e-03 -2.2139156625681699e-03 -5.5078029695647488e-04 + 26 -1.5679561743998840e-03 3.5146224354726122e-04 2.4446924193334474e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-setforce_const.yaml b/unittest/force-styles/tests/fix-timestep-setforce_const.yaml index 0c55c7a872..b932718f71 100644 --- a/unittest/force-styles/tests/fix-timestep-setforce_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-setforce_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2e-13 +epsilon: 5e-12 prerequisites: ! | atom full fix setforce diff --git a/unittest/force-styles/tests/fix-timestep-setforce_region.yaml b/unittest/force-styles/tests/fix-timestep-setforce_region.yaml index d1996c73fa..bf1d08df34 100644 --- a/unittest/force-styles/tests/fix-timestep-setforce_region.yaml +++ b/unittest/force-styles/tests/fix-timestep-setforce_region.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2e-13 +epsilon: 5e-12 prerequisites: ! | atom full fix setforce diff --git a/unittest/force-styles/tests/fix-timestep-setforce_variable.yaml b/unittest/force-styles/tests/fix-timestep-setforce_variable.yaml index 71e96365db..5c01ca714f 100644 --- a/unittest/force-styles/tests/fix-timestep-setforce_variable.yaml +++ b/unittest/force-styles/tests/fix-timestep-setforce_variable.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2e-13 +epsilon: 5e-12 prerequisites: ! | atom full fix setforce diff --git a/unittest/force-styles/tests/fix-timestep-temp_rescale.yaml b/unittest/force-styles/tests/fix-timestep-temp_rescale.yaml index 0df32c851f..6c53252d14 100644 --- a/unittest/force-styles/tests/fix-timestep-temp_rescale.yaml +++ b/unittest/force-styles/tests/fix-timestep-temp_rescale.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 2e-13 prerequisites: ! | atom full fix temp/rescale diff --git a/unittest/force-styles/tests/fix-timestep-wall_harmonic_const.yaml b/unittest/force-styles/tests/fix-timestep-wall_harmonic_const.yaml index 0f822964ac..2cb8904632 100644 --- a/unittest/force-styles/tests/fix-timestep-wall_harmonic_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-wall_harmonic_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix wall/harmonic diff --git a/unittest/force-styles/tests/kspace-msm_nopbc.yaml b/unittest/force-styles/tests/kspace-msm_nopbc.yaml index 028ee43aaf..4d3080bcc9 100644 --- a/unittest/force-styles/tests/kspace-msm_nopbc.yaml +++ b/unittest/force-styles/tests/kspace-msm_nopbc.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 14:47:38 202 +date_generated: Wed Sep 16 23:34:54 202 epsilon: 5e-11 prerequisites: ! | atom full @@ -11,10 +11,10 @@ pre_commands: ! | post_commands: ! | pair_modify compute no kspace_style msm 1.0e-4 - kspace_modify cutoff/adjust no + kspace_modify cutoff/adjust yes kspace_modify pressure/scalar no # required for USER-OMP with msm input_file: in.fourmol -pair_style: coul/msm 12.0 +pair_style: coul/msm 10.0 pair_coeff: ! | * * extract: ! "" @@ -24,67 +24,67 @@ init_coul: 0 init_stress: ! |2- 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 init_forces: ! |2 - 1 -1.0766173668302007e-01 3.3042340827626349e-01 -2.9550761278746868e-01 - 2 1.4576263044966863e-02 -2.2187776206184587e-01 2.1317727080129803e-01 - 3 -6.2277085668426338e-03 1.1652138650558974e-02 -1.3297461972937180e-02 - 4 2.8786238443846923e-02 -4.5768542246633188e-02 4.9349101662676420e-02 - 5 4.2979655856763686e-02 -5.4082950850616152e-02 5.4543059350179231e-02 - 6 4.0963202143681071e-02 -2.5177829287287617e-01 4.4685026134973971e-01 - 7 4.3752018459624321e-02 2.0781332786234075e-01 -4.5927449533997905e-01 - 8 1.7902097598623774e-02 2.1086807165304489e-01 -4.6243455927005356e-01 - 9 2.0355019954072114e-03 -1.5827691071752098e-01 2.7862824718724422e-01 - 10 -1.9772220824436811e-02 -2.2139108764682804e-02 7.8260376067917345e-02 - 11 -2.9153388383640691e-02 -2.2889984975802833e-02 1.0317906039578388e-01 - 12 1.2922943535921338e-01 9.7734055402007608e-02 -3.1908212769200051e-01 - 13 -5.4703693507262792e-02 -2.6149394426322036e-02 1.0994484599179440e-01 - 14 -4.2988225876533809e-02 -3.0099007171320122e-02 1.0262933028641755e-01 - 15 -3.7590864461845237e-02 -4.4176544191975885e-02 1.0017383244998040e-01 - 16 -1.9816142648538662e-01 -1.0441860078884198e-01 5.3904854977591932e-01 - 17 1.1181429866686794e-01 1.2719867318944633e-01 -4.3015678280050906e-01 - 18 3.1502200306647382e-01 4.1974825623470402e-01 -6.7479886734843464e-01 - 19 -1.6689905496966348e-01 -1.8680268140244130e-01 3.1219145983138630e-01 - 20 -1.5445789535736368e-01 -1.7976356547462513e-01 3.0246182814337153e-01 - 21 4.5519486932419828e-01 2.3683712353345862e-01 -8.7807403931732608e-01 - 22 -2.2220599724324458e-01 -1.2571032291855247e-01 3.9771867786752363e-01 - 23 -1.9325477274003933e-01 -1.2333786894453987e-01 4.0830652757809321e-01 - 24 -1.8286999844561756e-02 8.1021886775407503e-01 -3.7126337318324748e-01 - 25 5.5726795149239679e-02 -3.9672045025447300e-01 2.0847896698971494e-01 - 26 -2.7814896742372048e-02 -4.2032861857567699e-01 1.8697109800153439e-01 - 27 -5.3163776317893185e-01 2.5116155120314121e-01 -4.1286599443776800e-01 - 28 2.9735002262617338e-01 -1.6009440605268385e-01 2.2070546856483822e-01 - 29 2.5561709605369254e-01 -1.2916627825090182e-01 2.0454030119394306e-01 + 1 -1.9660766973632629e-02 2.4887690402810803e-01 -2.6641824613888343e-01 + 2 -1.3624815126340395e-02 -1.5639120626132319e-01 1.8350418308951177e-01 + 3 -1.4532868547754685e-03 9.7555317635889278e-03 -1.2103417264450246e-02 + 4 7.6255500027174235e-03 -3.9870497042105414e-02 4.9031780581162296e-02 + 5 1.4643527683300276e-02 -4.5719967123610657e-02 5.0151711197880880e-02 + 6 -2.3019967213719298e-02 -2.2641044879888725e-01 3.7031135553251365e-01 + 7 6.1586611801408619e-02 1.9950513148374674e-01 -3.7533383017612382e-01 + 8 4.7492865314090887e-02 2.0058339979109510e-01 -3.6338275231402373e-01 + 9 -2.4991261319178327e-02 -1.4222053551221250e-01 2.2190346484561033e-01 + 10 -1.5036583065172235e-02 -2.4812037454010148e-02 5.8719964820777154e-02 + 11 -2.0697714175288616e-02 -2.8371335465363762e-02 7.7546547743737815e-02 + 12 7.9810948413862506e-02 1.0103349868455645e-01 -2.3280969997596773e-01 + 13 -3.2100550418543303e-02 -2.9776304283801739e-02 7.8792969084893250e-02 + 14 -2.5963939878006975e-02 -3.1773907050873684e-02 7.5318001505625259e-02 + 15 -2.3640258353387851e-02 -3.8543177009452069e-02 7.3872181812136589e-02 + 16 -1.3866149465391214e-01 -1.4048040049076543e-01 4.0181819118801099e-01 + 17 9.5921555134325306e-02 1.5188889686042792e-01 -3.3616481164073736e-01 + 18 1.9119149973724631e-01 2.7600101101400065e-01 -4.9905235652772256e-01 + 19 -1.0295594643749159e-01 -1.2558699433459494e-01 2.2917035584235132e-01 + 20 -9.1871775273005676e-02 -1.1181712889505244e-01 2.2081667821655040e-01 + 21 3.0150101737002233e-01 2.0261067017020062e-01 -6.5578930195073504e-01 + 22 -1.4377760758729297e-01 -1.0711906550295265e-01 3.0195149743012700e-01 + 23 -1.3406879697935387e-01 -1.0456596809517928e-01 3.0755518683406996e-01 + 24 3.1811496439659706e-02 5.4487253646312184e-01 -3.3600934041328995e-01 + 25 6.7066514572999263e-03 -2.6954893693607662e-01 1.8641356801391348e-01 + 26 -3.0228329296046772e-02 -2.7036603292239825e-01 1.6655669613546273e-01 + 27 -3.0584140256599363e-01 1.2703307921788767e-01 -3.0787545284927331e-01 + 28 1.7594574310889624e-01 -8.4801753388695986e-02 1.6654491384366910e-01 + 29 1.3388378751500105e-01 -8.4218956507225592e-02 1.5904621975734043e-01 run_vdwl: 0 run_coul: 0 run_stress: ! |2- 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 run_forces: ! |2 - 1 -1.0725057415020919e-01 3.3019907950838151e-01 -2.9323265400347975e-01 - 2 1.4273516924286595e-02 -2.2195304769099961e-01 2.1172398888943439e-01 - 3 -6.2191160687439613e-03 1.1636479086601327e-02 -1.3193542766995693e-02 - 4 2.8789530000554349e-02 -4.5707077957577419e-02 4.8949304170325961e-02 - 5 4.2918140819301939e-02 -5.3982290008046191e-02 5.4071851700930415e-02 - 6 4.0693195898835278e-02 -2.5124364388294529e-01 4.4409525619111351e-01 - 7 4.3902199408654773e-02 2.0718378754835146e-01 -4.5693181215217060e-01 - 8 1.8355056045104463e-02 2.1019458646438235e-01 -4.5977818830587547e-01 - 9 1.6926987410114289e-03 -1.5785316258950571e-01 2.7688718669924633e-01 - 10 -1.9845368939794925e-02 -2.2016564601343797e-02 7.7877659664832483e-02 - 11 -2.9242294066982408e-02 -2.2678746148089381e-02 1.0272772972867131e-01 - 12 1.2960469545860479e-01 9.7367043788644400e-02 -3.1763881493481549e-01 - 13 -5.4829808348627301e-02 -2.6026456048508360e-02 1.0948080578658986e-01 - 14 -4.3113220503693823e-02 -2.9962591673432723e-02 1.0219446255502410e-01 - 15 -3.7688395823574243e-02 -4.4115392571750824e-02 9.9676983434799277e-02 - 16 -1.9855722830658068e-01 -1.0361163893486998e-01 5.3648057305505858e-01 - 17 1.1217353766495122e-01 1.2665752635347602e-01 -4.2776774483665475e-01 - 18 3.1619456057296186e-01 4.2101932424007404e-01 -6.7203553906529401e-01 - 19 -1.6723605125535490e-01 -1.8745079364937817e-01 3.1118730606879103e-01 - 20 -1.5510498316646221e-01 -1.8060202958376245e-01 3.0126314730021070e-01 - 21 4.5618585311145787e-01 2.3416325579619782e-01 -8.7525764015858531e-01 - 22 -2.2272028927958532e-01 -1.2422014484239144e-01 3.9660449946839177e-01 - 23 -1.9381556909487696e-01 -1.2213865056926680e-01 4.0697283949615592e-01 - 24 -1.7632222754297714e-02 8.0868006192947306e-01 -3.6871343152445346e-01 - 25 5.5196078243586418e-02 -3.9602778003476646e-01 2.0694223014380941e-01 - 26 -2.8010525620160029e-02 -4.1949748612714061e-01 1.8579634676877732e-01 - 27 -5.3081154989654455e-01 2.5084075406488837e-01 -4.1028201045412238e-01 - 28 2.9697439332712672e-01 -1.5978637451711275e-01 2.1926787644097381e-01 - 29 2.5525638787732113e-01 -1.2899390363572455e-01 2.0303208126884240e-01 + 1 -1.9435660649954035e-02 2.4862419866029895e-01 -2.6485844665282127e-01 + 2 -1.3780960856462642e-02 -1.5633484676368786e-01 1.8249149357092176e-01 + 3 -1.4477876045471730e-03 9.7405440850258148e-03 -1.2033329999524403e-02 + 4 7.6194046460355443e-03 -3.9808911118935496e-02 4.8750294710619230e-02 + 5 1.4608467030321211e-02 -4.5637118789836367e-02 4.9835152454995715e-02 + 6 -2.3197025068714773e-02 -2.2594830705873872e-01 3.6847037486285417e-01 + 7 6.1717500782434924e-02 1.9901033168712404e-01 -3.7369150128655199e-01 + 8 4.7749684660482718e-02 2.0006013114193463e-01 -3.6163643283185798e-01 + 9 -2.5180512710502947e-02 -1.4188045425384196e-01 2.2075702115831841e-01 + 10 -1.5077701688824005e-02 -2.4725085890842307e-02 5.8464945107114523e-02 + 11 -2.0748066671008640e-02 -2.8235558430685419e-02 7.7236489461803823e-02 + 12 8.0023983603549315e-02 1.0075069102465822e-01 -2.3185256345650801e-01 + 13 -3.2172515871576345e-02 -2.9683078834640497e-02 7.8481317271285753e-02 + 14 -2.6036585357780480e-02 -3.1674935431627041e-02 7.5022199352328886e-02 + 15 -2.3701869220455588e-02 -3.8482199838891257e-02 7.3549324869376057e-02 + 16 -1.3888759812427742e-01 -1.3988538328776859e-01 4.0004986508755819e-01 + 17 9.6133253653233317e-02 1.5140712273384951e-01 -3.3449829166546546e-01 + 18 1.9186403095769983e-01 2.7642237025637928e-01 -4.9703227944872203e-01 + 19 -1.0317157260407553e-01 -1.2584196384242616e-01 2.2840724039991533e-01 + 20 -9.2241024733318633e-02 -1.1214136339742799e-01 2.1992309661808374e-01 + 21 3.0213716795296858e-01 2.0109999025313266e-01 -6.5372676931043427e-01 + 22 -1.4412514967455967e-01 -1.0626480050449802e-01 3.0111000824875528e-01 + 23 -1.3445764535869267e-01 -1.0385869141008749e-01 3.0659542559194641e-01 + 24 3.2220069538097813e-02 5.4392955889866856e-01 -3.3403308893855654e-01 + 25 6.4038156742088235e-03 -2.6913137939730769e-01 1.8527285228807902e-01 + 26 -3.0378945332607477e-02 -2.6991095510242280e-01 1.6560531177520216e-01 + 27 -3.0526032461577285e-01 1.2664769564194714e-01 -3.0598133565740004e-01 + 28 1.7568759858096977e-01 -8.4510001331266793e-02 1.6549070835675123e-01 + 29 1.3366008104126817e-01 -8.3974642978063757e-02 1.5793844609842966e-01 ... diff --git a/unittest/force-styles/tests/manybody-pair-edip_multi.yaml b/unittest/force-styles/tests/manybody-pair-edip_multi.yaml index 7237a20a45..1f12c9955a 100644 --- a/unittest/force-styles/tests/manybody-pair-edip_multi.yaml +++ b/unittest/force-styles/tests/manybody-pair-edip_multi.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:29 202 -epsilon: 1e-14 +epsilon: 5e-14 prerequisites: ! | pair edip/multi pre_commands: ! | diff --git a/unittest/force-styles/tests/manybody-pair-meam_c.yaml b/unittest/force-styles/tests/manybody-pair-meam_c.yaml index 6b70bc175d..0efe79417c 100644 --- a/unittest/force-styles/tests/manybody-pair-meam_c.yaml +++ b/unittest/force-styles/tests/manybody-pair-meam_c.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:30 202 -epsilon: 1e-14 +epsilon: 7.5e-12 prerequisites: ! | pair meam/c pre_commands: ! | diff --git a/unittest/force-styles/tests/mol-pair-lj_charmm_coul_long_soft.yaml b/unittest/force-styles/tests/mol-pair-lj_charmm_coul_long_soft.yaml index 174f78aed2..aa9509679c 100644 --- a/unittest/force-styles/tests/mol-pair-lj_charmm_coul_long_soft.yaml +++ b/unittest/force-styles/tests/mol-pair-lj_charmm_coul_long_soft.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:14 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full pair lj/charmm/coul/long/soft diff --git a/unittest/force-styles/tests/mol-pair-lj_cut_coul_long_soft.yaml b/unittest/force-styles/tests/mol-pair-lj_cut_coul_long_soft.yaml index 772d8c6c36..c3a97c2f2f 100644 --- a/unittest/force-styles/tests/mol-pair-lj_cut_coul_long_soft.yaml +++ b/unittest/force-styles/tests/mol-pair-lj_cut_coul_long_soft.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:16 202 -epsilon: 7.5e-14 +epsilon: 5e-13 prerequisites: ! | atom full pair lj/cut/coul/long/soft diff --git a/unittest/formats/CMakeLists.txt b/unittest/formats/CMakeLists.txt index 0a3e7bce56..8b44bbc227 100644 --- a/unittest/formats/CMakeLists.txt +++ b/unittest/formats/CMakeLists.txt @@ -62,9 +62,11 @@ if (PKG_COMPRESS) set_tests_properties(DumpLocalGZ PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") set_tests_properties(DumpLocalGZ PROPERTIES ENVIRONMENT "GZIP_BINARY=${GZIP_BINARY}") + find_package(PkgConfig REQUIRED) + pkg_check_modules(Zstd IMPORTED_TARGET libzstd>=1.4) find_program(ZSTD_BINARY NAMES zstd) - if (ZSTD_BINARY) + if(Zstd_FOUND AND ZSTD_BINARY) add_executable(test_dump_atom_zstd test_dump_atom_zstd.cpp) target_link_libraries(test_dump_atom_zstd PRIVATE lammps GTest::GMock GTest::GTest) add_test(NAME DumpAtomZstd COMMAND test_dump_atom_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/unittest/formats/test_atom_styles.cpp b/unittest/formats/test_atom_styles.cpp index 12171ae1d3..ba1d5a9ba9 100644 --- a/unittest/formats/test_atom_styles.cpp +++ b/unittest/formats/test_atom_styles.cpp @@ -28,8 +28,8 @@ #include #include #include -#include #include +#include #if !defined(_FORTIFY_SOURCE) || (_FORTIFY_SOURCE == 0) #if defined(__INTEL_COMPILER) @@ -54,6 +54,8 @@ using LAMMPS_NS::utils::split_words; // whether to print verbose output (i.e. not capturing LAMMPS screen output). bool verbose = false; +const double EPSILON=5.0e-14; + namespace LAMMPS_NS { using ::testing::Eq; @@ -351,33 +353,33 @@ TEST_F(AtomStyleTest, atomic) auto x = lmp->atom->x; auto v = lmp->atom->v; auto tag = lmp->atom->tag; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); - ASSERT_NEAR(lmp->atom->mass[1], 4.0, 1.0e-14); - ASSERT_NEAR(lmp->atom->mass[2], 2.4, 1.0e-14); + EXPECT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1); ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY); @@ -406,21 +408,21 @@ TEST_F(AtomStyleTest, atomic) x = lmp->atom->x; v = lmp->atom->v; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); - ASSERT_NEAR(lmp->atom->mass[1], 4.0, 1.0e-14); - ASSERT_NEAR(lmp->atom->mass[2], 2.4, 1.0e-14); + EXPECT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1); ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY); @@ -439,54 +441,54 @@ TEST_F(AtomStyleTest, atomic) ASSERT_EQ(lmp->atom->map_tag_max, 16); x = lmp->atom->x; tag = lmp->atom->tag; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 6.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(7)][0], 6.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(7)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(7)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(8)][0], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(8)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(8)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(9)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(9)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(9)][2], 8.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(10)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(10)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(10)][2], 7.9, 1.0e-14); - ASSERT_NEAR(x[GETIDX(11)][0], 6.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(11)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(11)][2], 8.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(12)][0], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(12)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(12)][2], 7.9, 1.0e-14); - ASSERT_NEAR(x[GETIDX(13)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(13)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(13)][2], 8.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(14)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(14)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(14)][2], 7.9, 1.0e-14); - ASSERT_NEAR(x[GETIDX(15)][0], 6.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(15)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(15)][2], 8.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(16)][0], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(16)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(16)][2], 7.9, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 6.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(7)][0], 6.0, EPSILON); + EXPECT_NEAR(x[GETIDX(7)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(7)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(8)][0], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(8)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(8)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(9)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(9)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(9)][2], 8.1, EPSILON); + EXPECT_NEAR(x[GETIDX(10)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(10)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(10)][2], 7.9, EPSILON); + EXPECT_NEAR(x[GETIDX(11)][0], 6.0, EPSILON); + EXPECT_NEAR(x[GETIDX(11)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(11)][2], 8.1, EPSILON); + EXPECT_NEAR(x[GETIDX(12)][0], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(12)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(12)][2], 7.9, EPSILON); + EXPECT_NEAR(x[GETIDX(13)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(13)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(13)][2], 8.1, EPSILON); + EXPECT_NEAR(x[GETIDX(14)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(14)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(14)][2], 7.9, EPSILON); + EXPECT_NEAR(x[GETIDX(15)][0], 6.0, EPSILON); + EXPECT_NEAR(x[GETIDX(15)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(15)][2], 8.1, EPSILON); + EXPECT_NEAR(x[GETIDX(16)][0], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(16)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(16)][2], 7.9, EPSILON); } TEST_F(AtomStyleTest, charge) @@ -737,37 +739,37 @@ TEST_F(AtomStyleTest, charge) auto x = lmp->atom->x; auto v = lmp->atom->v; auto q = lmp->atom->q; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(1)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(2)], 0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(3)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(4)], 1.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(q[GETIDX(1)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(2)], 0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(3)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(4)], 1.0, EPSILON); - ASSERT_NEAR(lmp->atom->mass[1], 4.0, 1.0e-14); - ASSERT_NEAR(lmp->atom->mass[2], 2.4, 1.0e-14); + EXPECT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1); @@ -777,7 +779,7 @@ TEST_F(AtomStyleTest, charge) lmp->input->one("delete_atoms group two compress no"); lmp->input->one("write_restart test_atom_styles.restart"); lmp->input->one("clear"); - EXPECT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); + ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); lmp->input->one("read_restart test_atom_styles.restart"); if (!verbose) ::testing::internal::GetCapturedStdout(); ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("charge")); @@ -795,23 +797,23 @@ TEST_F(AtomStyleTest, charge) x = lmp->atom->x; v = lmp->atom->v; q = lmp->atom->q; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(1)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(3)], -1.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(q[GETIDX(1)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(3)], -1.0, EPSILON); - ASSERT_NEAR(lmp->atom->mass[1], 4.0, 1.0e-14); - ASSERT_NEAR(lmp->atom->mass[2], 2.4, 1.0e-14); + EXPECT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1); @@ -822,22 +824,22 @@ TEST_F(AtomStyleTest, charge) if (!verbose) ::testing::internal::GetCapturedStdout(); ASSERT_EQ(lmp->atom->map_tag_max, 16); q = lmp->atom->q; - ASSERT_NEAR(q[GETIDX(1)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(2)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(3)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(4)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(5)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(6)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(7)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(8)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(9)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(10)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(11)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(12)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(13)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(14)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(15)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(16)], -1.0, 1.0e-14); + EXPECT_NEAR(q[GETIDX(1)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(2)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(3)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(4)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(5)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(6)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(7)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(8)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(9)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(10)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(11)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(12)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(13)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(14)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(15)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(16)], -1.0, EPSILON); } TEST_F(AtomStyleTest, sphere) @@ -1094,46 +1096,46 @@ TEST_F(AtomStyleTest, sphere) auto v = lmp->atom->v; auto rmass = lmp->atom->rmass; auto omega = lmp->atom->omega; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(1)], 4.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][0], -0.5, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][1], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][0], 0.5, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][1], -0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][0], -1.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][1], 1.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(1)], 4.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][0], -0.5, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][1], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][0], 0.5, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][1], -0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][0], -1.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][1], 1.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][2], 0.0, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("pair_coeff * *"); @@ -1141,7 +1143,7 @@ TEST_F(AtomStyleTest, sphere) lmp->input->one("delete_atoms group two compress no"); lmp->input->one("write_restart test_atom_styles.restart"); lmp->input->one("clear"); - EXPECT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); + ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); lmp->input->one("read_restart test_atom_styles.restart"); lmp->input->one("replicate 1 1 2"); lmp->input->one("reset_atom_ids"); @@ -1160,22 +1162,22 @@ TEST_F(AtomStyleTest, sphere) rmass = lmp->atom->rmass; omega = lmp->atom->omega; - ASSERT_NEAR(rmass[GETIDX(1)], 4.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 4.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][0], -0.5, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][1], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][0], -1.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][0], -0.5, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][1], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][2], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][0], -1.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 4.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][0], -0.5, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][1], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][0], -1.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][0], -0.5, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][1], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][2], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][0], -1.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][2], 0.0, EPSILON); } TEST_F(AtomStyleTest, ellipsoid) @@ -1454,42 +1456,42 @@ TEST_F(AtomStyleTest, ellipsoid) auto rmass = lmp->atom->rmass; auto avec = (AtomVecEllipsoid *)lmp->atom->avec; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -1502,41 +1504,41 @@ TEST_F(AtomStyleTest, ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(4)], 3); ASSERT_EQ(ellipsoid[GETIDX(5)], -1); ASSERT_EQ(ellipsoid[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("group two id 2:4:2"); @@ -1581,43 +1583,43 @@ TEST_F(AtomStyleTest, ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(9)], 3); ASSERT_EQ(ellipsoid[GETIDX(11)], -1); ASSERT_EQ(ellipsoid[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573159, 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573159, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("reset_atom_ids"); @@ -1646,43 +1648,43 @@ TEST_F(AtomStyleTest, ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(6)], -1); ASSERT_EQ(ellipsoid[GETIDX(7)], 3); ASSERT_EQ(ellipsoid[GETIDX(8)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(8)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(8)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573159, 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573159, EPSILON); } TEST_F(AtomStyleTest, line) @@ -1950,42 +1952,42 @@ TEST_F(AtomStyleTest, line) auto rmass = lmp->atom->rmass; auto avec = (AtomVecLine *)lmp->atom->avec; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 3.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -3.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 3.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -3.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -1998,21 +2000,21 @@ TEST_F(AtomStyleTest, line) ASSERT_EQ(line[GETIDX(4)], 3); ASSERT_EQ(line[GETIDX(5)], -1); ASSERT_EQ(line[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[1].theta, MathConst::MY_PI * 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[2].theta, MathConst::MY_PI / 6.0, 1.0e-14); - ASSERT_NEAR(bonus[3].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[3].theta, MathConst::MY_PI / 3.0, 1.0e-14); + EXPECT_NEAR(bonus[0].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[0].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[1].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[1].theta, MathConst::MY_PI * 0.5, EPSILON); + EXPECT_NEAR(bonus[2].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[2].theta, MathConst::MY_PI / 6.0, EPSILON); + EXPECT_NEAR(bonus[3].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[3].theta, MathConst::MY_PI / 3.0, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("pair_coeff * *"); @@ -2059,23 +2061,23 @@ TEST_F(AtomStyleTest, line) ASSERT_EQ(line[GETIDX(9)], 3); ASSERT_EQ(line[GETIDX(11)], -1); ASSERT_EQ(line[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[1].theta, MathConst::MY_PI / 6.0, 1.0e-14); - ASSERT_NEAR(bonus[2].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[2].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[3].theta, MathConst::MY_PI / 6.0, 1.0e-14); + EXPECT_NEAR(bonus[0].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[0].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[1].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[1].theta, MathConst::MY_PI / 6.0, EPSILON); + EXPECT_NEAR(bonus[2].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[2].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[3].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[3].theta, MathConst::MY_PI / 6.0, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("reset_atom_ids"); @@ -2104,23 +2106,23 @@ TEST_F(AtomStyleTest, line) ASSERT_EQ(line[GETIDX(6)], -1); ASSERT_EQ(line[GETIDX(7)], 3); ASSERT_EQ(line[GETIDX(8)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(8)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(8)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[1].theta, MathConst::MY_PI / 6.0, 1.0e-14); - ASSERT_NEAR(bonus[2].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[2].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[3].theta, MathConst::MY_PI / 6.0, 1.0e-14); + EXPECT_NEAR(bonus[0].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[0].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[1].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[1].theta, MathConst::MY_PI / 6.0, EPSILON); + EXPECT_NEAR(bonus[2].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[2].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[3].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[3].theta, MathConst::MY_PI / 6.0, EPSILON); } TEST_F(AtomStyleTest, tri) @@ -2400,42 +2402,42 @@ TEST_F(AtomStyleTest, tri) auto radius = lmp->atom->radius; auto avec = (AtomVecTri *)lmp->atom->avec; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -2448,83 +2450,83 @@ TEST_F(AtomStyleTest, tri) ASSERT_EQ(tri[GETIDX(4)], 3); ASSERT_EQ(tri[GETIDX(5)], -1); ASSERT_EQ(tri[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5773502691896258, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(2)], 0.5773502691896258, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.8660254037844390, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(4)], 0.8660254037844390, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5773502691896258, EPSILON); + EXPECT_NEAR(radius[GETIDX(2)], 0.5773502691896258, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.8660254037844390, EPSILON); + EXPECT_NEAR(radius[GETIDX(4)], 0.8660254037844390, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); - ASSERT_NEAR(bonus[0].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 13.982119044342252, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 0.10811427523057447, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 13.945895752275419, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 19.15175691481879, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 19.018309360029388, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 0.36886008861549813, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 18.948744087979012, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 0.92373678792937974, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0067268233964605153, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.016239988275423625, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], -0.38262430562330857, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.92420701665838023, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.023090752704586423, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0095209086022933816, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], -0.38107421822833848, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.90191325590647364, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.20096813128512517, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.10027584751231088, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.36892959143125964, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.8851587738551242, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.093233030525564045, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], -0.26735735980719261, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.36921753647848277, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[0], -0.14933690186163631, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[1], -0.55767753582520529, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[2], -0.0052525338293288905, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[0], 0.18561232929671426, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[1], -0.18681344121910506, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[2], 0.51379191773154387, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[0], -0.78775285695558617, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[1], -0.28372571379613187, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[2], -0.22123552085772166, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[0], -0.69845793336676587, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[1], -0.47901475403318056, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[2], 0.18083523090249506, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[0], 0.55733290519255385, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[1], 0.14942924536134222, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[2], 0.019602723119529659, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[0], 0.2208094914375279, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[1], -0.22223836695322471, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[2], -0.48496042114630089, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[0], 0.6304379562181005, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[1], -0.56674478453558153, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[2], 0.17705460333259249, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[0], 0.22007613459534958, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[1], 0.15093208974463554, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[2], -0.8238847002262436, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[0], -0.40799600333091751, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[1], 0.40824829046386302, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[2], -0.014350189290200811, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[0], -0.40642182073424188, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[1], 0.40905180817232945, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[2], -0.028831496585242929, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[0], 0.15731490073748589, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[1], 0.85047049833171351, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[2], 0.044180917525129149, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[0], 0.47838179877141634, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[1], 0.32808266428854471, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[2], 0.64304946932374851, 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 13.982119044342252, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 13.945895752275419, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.10811427523057447, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.23541253382609079, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 19.018309360029388, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 18.948744087979012, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.36886008861549813, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 0.66466395261228639, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], -0.26579965871355399, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], -0.64169714094040209, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], -0.27531282359251713, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.63718542087921404, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.66984067651944412, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], -0.26272786480888066, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], -0.27619246288035992, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.70865471105868871, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.40297854431552654, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], -0.56684324752832238, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.11876668744732566, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.55997606330452898, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.69182747953492685, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.072026021657128514, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.45012642589672475, EPSILON); + EXPECT_NEAR(bonus[0].c1[0], -0.0052525338293288905, EPSILON); + EXPECT_NEAR(bonus[0].c1[1], -0.55767753582520529, EPSILON); + EXPECT_NEAR(bonus[0].c1[2], 0.14933690186163631, EPSILON); + EXPECT_NEAR(bonus[1].c1[0], 0.18561232929671426, EPSILON); + EXPECT_NEAR(bonus[1].c1[1], 0.51379191773154387, EPSILON); + EXPECT_NEAR(bonus[1].c1[2], 0.18681344121910506, EPSILON); + EXPECT_NEAR(bonus[2].c1[0], -0.22123552085772166, EPSILON); + EXPECT_NEAR(bonus[2].c1[1], -0.28372571379613187, EPSILON); + EXPECT_NEAR(bonus[2].c1[2], 0.78775285695558617, EPSILON); + EXPECT_NEAR(bonus[3].c1[0], -0.69845793336676587, EPSILON); + EXPECT_NEAR(bonus[3].c1[1], 0.18083523090249506, EPSILON); + EXPECT_NEAR(bonus[3].c1[2], 0.47901475403318056, EPSILON); + EXPECT_NEAR(bonus[0].c2[0], 0.019602723119529659, EPSILON); + EXPECT_NEAR(bonus[0].c2[1], 0.14942924536134222, EPSILON); + EXPECT_NEAR(bonus[0].c2[2], -0.55733290519255385, EPSILON); + EXPECT_NEAR(bonus[1].c2[0], 0.2208094914375279, EPSILON); + EXPECT_NEAR(bonus[1].c2[1], -0.4849604211463005, EPSILON); + EXPECT_NEAR(bonus[1].c2[2], 0.22223836695322477, EPSILON); + EXPECT_NEAR(bonus[2].c2[0], 0.17705460333259249, EPSILON); + EXPECT_NEAR(bonus[2].c2[1], -0.56674478453558153, EPSILON); + EXPECT_NEAR(bonus[2].c2[2], -0.6304379562181005, EPSILON); + EXPECT_NEAR(bonus[3].c2[0], 0.22007613459534958, EPSILON); + EXPECT_NEAR(bonus[3].c2[1], -0.82388470022624394, EPSILON); + EXPECT_NEAR(bonus[3].c2[2], -0.15093208974463557, EPSILON); + EXPECT_NEAR(bonus[0].c3[0], -0.014350189290200811, EPSILON); + EXPECT_NEAR(bonus[0].c3[1], 0.40824829046386302, EPSILON); + EXPECT_NEAR(bonus[0].c3[2], 0.40799600333091751, EPSILON); + EXPECT_NEAR(bonus[1].c3[0], -0.40642182073424188, EPSILON); + EXPECT_NEAR(bonus[1].c3[1], -0.028831496585242929, EPSILON); + EXPECT_NEAR(bonus[1].c3[2], -0.40905180817232945, EPSILON); + EXPECT_NEAR(bonus[2].c3[0], 0.044180917525129149, EPSILON); + EXPECT_NEAR(bonus[2].c3[1], 0.85047049833171351, EPSILON); + EXPECT_NEAR(bonus[2].c3[2], -0.15731490073748589, EPSILON); + EXPECT_NEAR(bonus[3].c3[0], 0.47838179877141634, EPSILON); + EXPECT_NEAR(bonus[3].c3[1], 0.64304946932374796, EPSILON); + EXPECT_NEAR(bonus[3].c3[2], -0.32808266428854477, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("group two id 2:4:2"); @@ -2570,87 +2572,87 @@ TEST_F(AtomStyleTest, tri) ASSERT_EQ(tri[GETIDX(9)], 3); ASSERT_EQ(tri[GETIDX(11)], -1); ASSERT_EQ(tri[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5773502691896258, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.8660254037844390, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(7)], 0.5773502691896258, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(9)], 0.8660254037844390, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(11)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(12)], 0.5, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5773502691896258, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.8660254037844390, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(7)], 0.5773502691896258, EPSILON); + EXPECT_NEAR(radius[GETIDX(9)], 0.8660254037844390, EPSILON); + EXPECT_NEAR(radius[GETIDX(11)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(12)], 0.5, EPSILON); - ASSERT_NEAR(bonus[0].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 19.15175691481879, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 19.15175691481879, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 0.92373678792937974, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0067268233964605153, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.016239988275423625, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], -0.38262430562330857, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.90191325590647364, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.20096813128512517, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.10027584751231088, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.36892959143125964, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.92373678792937974, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0067268233964605153, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.016239988275423625, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], -0.38262430562330857, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.90191325590647364, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.20096813128512517, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.10027584751231088, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.36892959143125964, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[0], -0.14933690186163631, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[1], -0.55767753582520529, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[2], -0.0052525338293288905, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[0], -0.78775285695558617, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[1], -0.28372571379613187, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[2], -0.22123552085772166, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[0], -0.14933690186163631, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[1], -0.55767753582520529, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[2], -0.0052525338293288905, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[0], -0.78775285695558617, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[1], -0.28372571379613187, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[2], -0.22123552085772166, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[0], 0.55733290519255385, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[1], 0.14942924536134222, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[2], 0.019602723119529659, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[0], 0.6304379562181005, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[1], -0.56674478453558153, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[2], 0.17705460333259249, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[0], 0.55733290519255385, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[1], 0.14942924536134222, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[2], 0.019602723119529659, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[0], 0.6304379562181005, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[1], -0.56674478453558153, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[2], 0.17705460333259249, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[0], -0.40799600333091751, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[1], 0.40824829046386302, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[2], -0.014350189290200811, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[0], 0.15731490073748589, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[1], 0.85047049833171351, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[2], 0.044180917525129149, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[0], -0.40799600333091751, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[1], 0.40824829046386302, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[2], -0.014350189290200811, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[0], 0.15731490073748589, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[1], 0.85047049833171351, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[2], 0.044180917525129149, 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.23541253382609079, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.23541253382609079, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 0.66466395261228639, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], -0.26579965871355399, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], -0.64169714094040209, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], -0.27531282359251713, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.70865471105868871, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.40297854431552654, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], -0.56684324752832238, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.11876668744732566, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.66466395261228639, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], -0.26579965871355399, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], -0.64169714094040209, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], -0.27531282359251713, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.70865471105868871, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.40297854431552654, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], -0.56684324752832238, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.11876668744732566, EPSILON); + EXPECT_NEAR(bonus[0].c1[0], -0.0052525338293288879, EPSILON); + EXPECT_NEAR(bonus[0].c1[1], -0.55767753582520529, EPSILON); + EXPECT_NEAR(bonus[0].c1[2], 0.14933690186163626, EPSILON); + EXPECT_NEAR(bonus[1].c1[0], -0.22123552085772158, EPSILON); + EXPECT_NEAR(bonus[1].c1[1], -0.28372571379613187, EPSILON); + EXPECT_NEAR(bonus[1].c1[2], 0.78775285695558628, EPSILON); + EXPECT_NEAR(bonus[2].c1[0], -0.0052525338293288905, EPSILON); + EXPECT_NEAR(bonus[2].c1[1], -0.55767753582520529, EPSILON); + EXPECT_NEAR(bonus[2].c1[2], 0.14933690186163631, EPSILON); + EXPECT_NEAR(bonus[3].c1[0], -0.22123552085772166, EPSILON); + EXPECT_NEAR(bonus[3].c1[1], -0.28372571379613187, EPSILON); + EXPECT_NEAR(bonus[3].c1[2], 0.78775285695558617, EPSILON); + EXPECT_NEAR(bonus[0].c2[0], 0.019602723119529659, EPSILON); + EXPECT_NEAR(bonus[0].c2[1], 0.14942924536134222, EPSILON); + EXPECT_NEAR(bonus[0].c2[2], -0.55733290519255385, EPSILON); + EXPECT_NEAR(bonus[1].c2[0], 0.17705460333259249, EPSILON); + EXPECT_NEAR(bonus[1].c2[1], -0.56674478453558153, EPSILON); + EXPECT_NEAR(bonus[1].c2[2], -0.6304379562181005, EPSILON); + EXPECT_NEAR(bonus[2].c2[0], 0.019602723119529659, EPSILON); + EXPECT_NEAR(bonus[2].c2[1], 0.14942924536134222, EPSILON); + EXPECT_NEAR(bonus[2].c2[2], -0.55733290519255385, EPSILON); + EXPECT_NEAR(bonus[3].c2[0], 0.17705460333259249, EPSILON); + EXPECT_NEAR(bonus[3].c2[1], -0.56674478453558153, EPSILON); + EXPECT_NEAR(bonus[3].c2[2], -0.6304379562181005, EPSILON); + EXPECT_NEAR(bonus[0].c3[0], -0.014350189290200811, EPSILON); + EXPECT_NEAR(bonus[0].c3[1], 0.40824829046386302, EPSILON); + EXPECT_NEAR(bonus[0].c3[2], 0.40799600333091751, EPSILON); + EXPECT_NEAR(bonus[1].c3[0], 0.044180917525129149, EPSILON); + EXPECT_NEAR(bonus[1].c3[1], 0.85047049833171351, EPSILON); + EXPECT_NEAR(bonus[1].c3[2], -0.15731490073748589, EPSILON); + EXPECT_NEAR(bonus[2].c3[0], -0.014350189290200811, EPSILON); + EXPECT_NEAR(bonus[2].c3[1], 0.40824829046386302, EPSILON); + EXPECT_NEAR(bonus[2].c3[2], 0.40799600333091751, EPSILON); + EXPECT_NEAR(bonus[3].c3[0], 0.044180917525129149, EPSILON); + EXPECT_NEAR(bonus[3].c3[1], 0.85047049833171351, EPSILON); + EXPECT_NEAR(bonus[3].c3[2], -0.15731490073748589, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("reset_atom_ids"); @@ -2679,18 +2681,18 @@ TEST_F(AtomStyleTest, tri) ASSERT_EQ(tri[GETIDX(6)], -1); ASSERT_EQ(tri[GETIDX(7)], 3); ASSERT_EQ(tri[GETIDX(8)], -1); - ASSERT_NEAR(bonus[0].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 19.15175691481879, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 19.15175691481879, 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.23541253382609079, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.23541253382609079, EPSILON); } TEST_F(AtomStyleTest, body_nparticle) @@ -2981,60 +2983,60 @@ TEST_F(AtomStyleTest, body_nparticle) auto radius = lmp->atom->radius; auto angmom = lmp->atom->angmom; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); ASSERT_EQ(type[GETIDX(4)], 2); ASSERT_EQ(type[GETIDX(5)], 3); ASSERT_EQ(type[GETIDX(6)], 3); - ASSERT_NEAR(angmom[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(angmom[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][2], 0.0, EPSILON); ASSERT_EQ(body[GETIDX(1)], 0); ASSERT_EQ(body[GETIDX(2)], 1); @@ -3042,47 +3044,47 @@ TEST_F(AtomStyleTest, body_nparticle) ASSERT_EQ(body[GETIDX(4)], 3); ASSERT_EQ(body[GETIDX(5)], -1); ASSERT_EQ(body[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(2)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(4)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(2)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(4)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); - ASSERT_NEAR(bonus[0].inertia[0], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 4.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 4.5, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 1.67188, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 1.7746273249544022, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 0.49099767504559777, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 12.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 12.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 4.5, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 4.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 1.7746273249544022, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 1.67188, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.49099767504559777, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 12.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 12.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), EPSILON); ASSERT_EQ(bonus[0].ilocal, 0); ASSERT_EQ(bonus[1].ilocal, 1); ASSERT_EQ(bonus[2].ilocal, 2); @@ -3153,60 +3155,60 @@ TEST_F(AtomStyleTest, body_nparticle) angmom = lmp->atom->angmom; avec = (AtomVecBody *)lmp->atom->avec; bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); ASSERT_EQ(type[GETIDX(4)], 2); ASSERT_EQ(type[GETIDX(5)], 3); ASSERT_EQ(type[GETIDX(6)], 3); - ASSERT_NEAR(angmom[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(angmom[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][2], 0.0, EPSILON); ASSERT_EQ(body[GETIDX(1)], 0); ASSERT_EQ(body[GETIDX(2)], 1); @@ -3214,47 +3216,47 @@ TEST_F(AtomStyleTest, body_nparticle) ASSERT_EQ(body[GETIDX(4)], 3); ASSERT_EQ(body[GETIDX(5)], -1); ASSERT_EQ(body[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(2)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(4)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(2)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(4)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); - ASSERT_NEAR(bonus[0].inertia[0], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 4.5, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 4.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 1.67188, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 1.7746273249544022, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 0.49099767504559777, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 12.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 12.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.25056280708573148, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.94328772332207422, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], -0.19726148412050853, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], -0.075803071317030998, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25602748346874377, 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 4.5, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 4.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 1.7746273249544022, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 1.67188, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.49099767504559777, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 12.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 12.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], -sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.25056280708573148, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.62499650256800654, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.47323774316465234, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.33072552332373728, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.52540083597613996, EPSILON); ASSERT_EQ(bonus[0].ilocal, 0); ASSERT_EQ(bonus[1].ilocal, 1); ASSERT_EQ(bonus[2].ilocal, 2); @@ -3326,50 +3328,50 @@ TEST_F(AtomStyleTest, body_nparticle) ASSERT_EQ(body[GETIDX(9)], 3); ASSERT_EQ(body[GETIDX(11)], -1); ASSERT_EQ(body[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(7)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(9)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(11)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(12)], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[0], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 1.67188, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 1.7746273249544022, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 0.49099767504559777, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 1.67188, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 1.7746273249544022, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 0.49099767504559777, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573148, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573148, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(7)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(9)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(11)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(12)], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].inertia[0], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 1.7746273249544022, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 1.67188, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.49099767504559777, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 2.0, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 2.0, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 1.7746273249544022, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 1.67188, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.49099767504559777, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573148, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573148, EPSILON); ASSERT_EQ(bonus[0].ilocal, 0); ASSERT_EQ(bonus[1].ilocal, 2); ASSERT_EQ(bonus[2].ilocal, 4); @@ -3775,42 +3777,42 @@ TEST_F(AtomStyleTest, bond) bond_type = lmp->atom->bond_type; bond_atom = lmp->atom->bond_atom; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -4337,42 +4339,42 @@ TEST_F(AtomStyleTest, angle) num_angle = lmp->atom->num_angle; angle_type = lmp->atom->angle_type; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -4788,95 +4790,95 @@ TEST_F(AtomStyleTest, full_ellipsoid) auto avec = (AtomVecEllipsoid *)hybrid->styles[1]; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); ASSERT_EQ(type[GETIDX(4)], 2); ASSERT_EQ(type[GETIDX(5)], 3); ASSERT_EQ(type[GETIDX(6)], 3); - ASSERT_NEAR(q[GETIDX(1)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(2)], 0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(3)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(4)], 1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(5)], 2.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(6)], -2.0, 1.0e-14); + EXPECT_NEAR(q[GETIDX(1)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(2)], 0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(3)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(4)], 1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(5)], 2.0, EPSILON); + EXPECT_NEAR(q[GETIDX(6)], -2.0, EPSILON); ASSERT_EQ(ellipsoid[GETIDX(1)], 0); ASSERT_EQ(ellipsoid[GETIDX(2)], 1); ASSERT_EQ(ellipsoid[GETIDX(3)], 2); ASSERT_EQ(ellipsoid[GETIDX(4)], 3); ASSERT_EQ(ellipsoid[GETIDX(5)], -1); ASSERT_EQ(ellipsoid[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("pair_coeff * *"); @@ -4927,43 +4929,43 @@ TEST_F(AtomStyleTest, full_ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(9)], 3); ASSERT_EQ(ellipsoid[GETIDX(11)], -1); ASSERT_EQ(ellipsoid[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573159, 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573159, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("reset_atom_ids"); @@ -4993,43 +4995,43 @@ TEST_F(AtomStyleTest, full_ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(6)], -1); ASSERT_EQ(ellipsoid[GETIDX(7)], 3); ASSERT_EQ(ellipsoid[GETIDX(8)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(8)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(8)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573159, 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573159, EPSILON); } } // namespace LAMMPS_NS diff --git a/unittest/python/CMakeLists.txt b/unittest/python/CMakeLists.txt index 574f7aab09..490314ca9d 100644 --- a/unittest/python/CMakeLists.txt +++ b/unittest/python/CMakeLists.txt @@ -17,9 +17,9 @@ if (Python_EXECUTABLE) # prepare to augment the environment so that the LAMMPS python module and the shared library is found. set(PYTHON_TEST_ENVIRONMENT PYTHONPATH=${LAMMPS_PYTHON_DIR}:$ENV{PYTHONPATH}) if(APPLE) - list(APPEND PYTHON_TEST_ENVIRONMENT DYLD_LIBRARY_PATH=${CMAKE_BINARY_DIR}:$ENV{DYLD_LIBRARY_PATH}) + list(APPEND PYTHON_TEST_ENVIRONMENT "DYLD_LIBRARY_PATH=${CMAKE_BINARY_DIR}:$ENV{DYLD_LIBRARY_PATH};LAMMPS_CMAKE_CACHE=${CMAKE_BINARY_DIR}/CMakeCache.txt") else() - list(APPEND PYTHON_TEST_ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}:$ENV{LD_LIBRARY_PATH}) + list(APPEND PYTHON_TEST_ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}:$ENV{LD_LIBRARY_PATH};LAMMPS_CMAKE_CACHE=${CMAKE_BINARY_DIR}/CMakeCache.txt") endif() if(LAMMPS_MACHINE) # convert from '_machine' to 'machine' @@ -27,20 +27,43 @@ if (Python_EXECUTABLE) list(APPEND PYTHON_TEST_ENVIRONMENT LAMMPS_MACHINE_NAME=${LAMMPS_MACHINE_NAME}) endif() + if(ENABLE_COVERAGE) + find_program(COVERAGE_BINARY coverage) + find_package_handle_standard_args(COVERAGE DEFAULT_MSG COVERAGE_BINARY) + + if(COVERAGE_FOUND) + set(PYTHON_TEST_RUNNER ${Python_EXECUTABLE} -u ${COVERAGE_BINARY} run --parallel-mode --include=${LAMMPS_PYTHON_DIR}/lammps.py --omit=${LAMMPS_PYTHON_DIR}/install.py) + else() + set(PYTHON_TEST_RUNNER ${Python_EXECUTABLE} -u) + endif() + else() + set(PYTHON_TEST_RUNNER ${Python_EXECUTABLE} -u) + endif() + add_test(NAME PythonOpen - COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/python-open.py -v + COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-open.py -v WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) set_tests_properties(PythonOpen PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}") add_test(NAME PythonCommands - COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/python-commands.py -v + COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-commands.py -v WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) set_tests_properties(PythonCommands PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}") add_test(NAME PythonNumpy - COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/python-numpy.py -v + COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-numpy.py -v WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) set_tests_properties(PythonNumpy PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}") + + add_test(NAME PythonCapabilities + COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-capabilities.py -v + WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + set_tests_properties(PythonCapabilities PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}") + + add_test(NAME PythonPyLammps + COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-pylammps.py -v + WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + set_tests_properties(PythonPyLammps PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}") else() message(STATUS "Skipping Tests for the LAMMPS Python Module: no suitable Python interpreter") endif() diff --git a/unittest/python/python-capabilities.py b/unittest/python/python-capabilities.py new file mode 100644 index 0000000000..e5dd63707b --- /dev/null +++ b/unittest/python/python-capabilities.py @@ -0,0 +1,64 @@ +import sys,os,unittest +from lammps import lammps + +class PythonCapabilities(unittest.TestCase): + def setUp(self): + machine = None + if 'LAMMPS_MACHINE_NAME' in os.environ: + machine=os.environ['LAMMPS_MACHINE_NAME'] + self.lmp = lammps(name=machine, cmdargs=['-nocite', '-log','none', '-echo','screen']) + + if 'LAMMPS_CMAKE_CACHE' in os.environ: + self.cmake_cache = {} + + with open(os.environ['LAMMPS_CMAKE_CACHE'], 'r') as f: + for line in f: + line = line.strip() + if not line or line.startswith('#') or line.startswith('//'): continue + parts = line.split('=') + key, value_type = parts[0].split(':') + if value_type == "UNINITIALIZED": continue + if value_type == "INTERNAL": continue + if len(parts) > 1: + value = parts[1] + if value_type == "BOOL": + value = (value.upper() == "ON") or (value.upper() == "YES") or (value == "1") + else: + value = None + self.cmake_cache[key] = value + + def tearDown(self): + del self.lmp + + def test_version(self): + self.assertGreaterEqual(self.lmp.version(), 20200824) + + def test_has_gzip_support(self): + self.assertEqual(self.lmp.has_gzip_support, self.cmake_cache['WITH_GZIP']) + + def test_has_png_support(self): + self.assertEqual(self.lmp.has_png_support, self.cmake_cache['WITH_PNG']) + + def test_has_jpeg_support(self): + self.assertEqual(self.lmp.has_jpeg_support, self.cmake_cache['WITH_JPEG']) + + def test_has_ffmpeg_support(self): + self.assertEqual(self.lmp.has_ffmpeg_support, self.cmake_cache['WITH_FFMPEG']) + + def test_installed_packages(self): + installed_packages = self.lmp.installed_packages + selected_packages = [key[4:] for key in self.cmake_cache.keys() if not key.startswith('PKG_CONFIG') and key.startswith('PKG_') and self.cmake_cache[key]] + + for pkg in selected_packages: + self.assertIn(pkg, installed_packages) + + def test_has_style(self): + self.assertTrue(self.lmp.has_style('pair', 'lj/cut')) + self.assertFalse(self.lmp.has_style('pair', 'lennard_jones')) + + def test_available_styles(self): + pairs = self.lmp.available_styles('pair') + self.assertIn('lj/cut', pairs) + +if __name__ == "__main__": + unittest.main() diff --git a/unittest/python/python-commands.py b/unittest/python/python-commands.py index f6d48c8bba..0b853a207e 100644 --- a/unittest/python/python-commands.py +++ b/unittest/python/python-commands.py @@ -43,46 +43,46 @@ create_atoms 1 single & ############################## def testFile(self): """Test reading commands from a file""" - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,0) self.lmp.file(self.demo_file) - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,1) self.lmp.file(self.cont_file) - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,2) def testNoFile(self): """Test (not) reading commands from no file""" self.lmp.file(None) - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,0) def testCommand(self): """Test executing individual commands""" - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,0) cmds = self.demo_input.splitlines() for cmd in cmds: self.lmp.command(cmd) - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,1) def testCommandsList(self): """Test executing commands from list of strings""" - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,0) cmds = self.demo_input.splitlines()+self.cont_input.splitlines() self.lmp.commands_list(cmds) - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,2) def testCommandsString(self): """Test executing block of commands from string""" - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,0) self.lmp.commands_string(self.demo_input+self.cont_input) - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,2) ############################## diff --git a/unittest/python/python-numpy.py b/unittest/python/python-numpy.py index 8fd41d2278..3c8ff9f512 100644 --- a/unittest/python/python-numpy.py +++ b/unittest/python/python-numpy.py @@ -1,7 +1,14 @@ import sys,os,unittest -from lammps import lammps, LMP_STYLE_GLOBAL, LMP_STYLE_LOCAL, LMP_STYLE_ATOM, LMP_TYPE_VECTOR, LMP_TYPE_SCALAR, LMP_TYPE_ARRAY +from lammps import lammps, LAMMPS_INT, LMP_STYLE_GLOBAL, LMP_STYLE_LOCAL, LMP_STYLE_ATOM, LMP_TYPE_VECTOR, LMP_TYPE_SCALAR, LMP_TYPE_ARRAY from ctypes import c_void_p +try: + import numpy + NUMPY_INSTALLED = True +except ImportError: + NUMPY_INSTALLED = False + +@unittest.skipIf(not NUMPY_INSTALLED, "numpy is not available") class PythonNumpy(unittest.TestCase): def setUp(self): machine = None @@ -25,7 +32,7 @@ class PythonNumpy(unittest.TestCase): self.lmp.command("create_atoms 1 single 1.0 1.0 1.0") self.lmp.command("create_atoms 1 single 1.0 1.0 1.5") self.lmp.command("compute coordsum all reduce sum x y z") - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,2) values = self.lmp.numpy.extract_compute("coordsum", LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR) self.assertEqual(len(values), 3) @@ -43,7 +50,7 @@ class PythonNumpy(unittest.TestCase): self.lmp.command("create_atoms 1 single 1.0 1.0 1.0") self.lmp.command("create_atoms 1 single 1.0 1.0 1.5") self.lmp.command("compute ke all ke/atom") - natoms = int(self.lmp.get_natoms()) + natoms = self.lmp.get_natoms() self.assertEqual(natoms,2) values = self.lmp.numpy.extract_compute("ke", LMP_STYLE_ATOM, LMP_TYPE_VECTOR) self.assertEqual(len(values), 2) @@ -66,5 +73,67 @@ class PythonNumpy(unittest.TestCase): # TODO pass + def testExtractAtomDeprecated(self): + self.lmp.command("units lj") + self.lmp.command("atom_style atomic") + self.lmp.command("atom_modify map array") + self.lmp.command("region box block 0 2 0 2 0 2") + self.lmp.command("create_box 1 box") + + x = [ + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.5 + ] + + types = [1, 1] + + self.assertEqual(self.lmp.create_atoms(2, id=None, type=types, x=x), 2) + nlocal = self.lmp.extract_global("nlocal", LAMMPS_INT) + self.assertEqual(nlocal, 2) + + ident = self.lmp.numpy.extract_atom_iarray("id", nlocal, dim=1) + self.assertEqual(len(ident), 2) + + ntypes = self.lmp.extract_global("ntypes", LAMMPS_INT) + self.assertEqual(ntypes, 1) + + x = self.lmp.numpy.extract_atom_darray("x", nlocal, dim=3) + v = self.lmp.numpy.extract_atom_darray("v", nlocal, dim=3) + self.assertEqual(len(x), 2) + self.assertTrue((x[0] == (1.0, 1.0, 1.0)).all()) + self.assertTrue((x[1] == (1.0, 1.0, 1.5)).all()) + self.assertEqual(len(v), 2) + + def testExtractAtom(self): + self.lmp.command("units lj") + self.lmp.command("atom_style atomic") + self.lmp.command("atom_modify map array") + self.lmp.command("region box block 0 2 0 2 0 2") + self.lmp.command("create_box 1 box") + + x = [ + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.5 + ] + + types = [1, 1] + + self.assertEqual(self.lmp.create_atoms(2, id=None, type=types, x=x), 2) + nlocal = self.lmp.extract_global("nlocal") + self.assertEqual(nlocal, 2) + + ident = self.lmp.numpy.extract_atom("id") + self.assertEqual(len(ident), 2) + + ntypes = self.lmp.extract_global("ntypes") + self.assertEqual(ntypes, 1) + + x = self.lmp.numpy.extract_atom("x") + v = self.lmp.numpy.extract_atom("v") + self.assertEqual(len(x), 2) + self.assertTrue((x[0] == (1.0, 1.0, 1.0)).all()) + self.assertTrue((x[1] == (1.0, 1.0, 1.5)).all()) + self.assertEqual(len(v), 2) + if __name__ == "__main__": unittest.main() diff --git a/unittest/python/python-open.py b/unittest/python/python-open.py index 2ace52296f..6ad7d335d5 100644 --- a/unittest/python/python-open.py +++ b/unittest/python/python-open.py @@ -12,7 +12,11 @@ except: pass try: - lmp = lammps() + if 'LAMMPS_MACHINE_NAME' in os.environ: + machine = os.environ['LAMMPS_MACHINE_NAME'] + else: + machine = "" + lmp = lammps(name=machine) has_mpi = lmp.has_mpi_support lmp.close() except: diff --git a/unittest/python/python-pylammps.py b/unittest/python/python-pylammps.py new file mode 100644 index 0000000000..f703d206fa --- /dev/null +++ b/unittest/python/python-pylammps.py @@ -0,0 +1,88 @@ +import sys,os,unittest +from lammps import PyLammps + +class PythonPyLammps(unittest.TestCase): + def setUp(self): + machine = None + if 'LAMMPS_MACHINE_NAME' in os.environ: + machine=os.environ['LAMMPS_MACHINE_NAME'] + self.pylmp = PyLammps(name=machine, cmdargs=['-nocite', '-log','none', '-echo', 'screen']) + self.pylmp.units("lj") + self.pylmp.atom_style("atomic") + self.pylmp.atom_modify("map array") + + if 'LAMMPS_CMAKE_CACHE' in os.environ: + self.cmake_cache = {} + + with open(os.environ['LAMMPS_CMAKE_CACHE'], 'r') as f: + for line in f: + line = line.strip() + if not line or line.startswith('#') or line.startswith('//'): continue + parts = line.split('=') + key, value_type = parts[0].split(':') + if len(parts) > 1: + value = parts[1] + if value_type == "BOOL": + value = (value.upper() == "ON") + else: + value = None + self.cmake_cache[key] = value + + def tearDown(self): + self.pylmp.close() + del self.pylmp + + def test_version(self): + self.assertGreaterEqual(self.pylmp.version(), 20200824) + + def test_create_atoms(self): + self.pylmp.region("box block", 0, 2, 0, 2, 0, 2) + self.pylmp.create_box(1, "box") + + x = [ + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.5 + ] + + types = [1, 1] + + self.assertEqual(self.pylmp.lmp.create_atoms(2, id=None, type=types, x=x), 2) + self.assertEqual(self.pylmp.system.natoms, 2) + self.assertEqual(len(self.pylmp.atoms), 2) + self.assertEqual(self.pylmp.atoms[0].position, tuple(x[0:3])) + self.assertEqual(self.pylmp.atoms[1].position, tuple(x[3:6])) + self.assertEqual(self.pylmp.last_run, None) + + + def test_write_script(self): + outfile = 'in.test_write_script' + self.pylmp.write_script(outfile) + self.assertTrue(os.path.exists(outfile)) + os.remove(outfile) + + def test_runs(self): + self.pylmp.lattice("fcc", 0.8442), + self.pylmp.region("box block", 0, 4, 0, 4, 0, 4) + self.pylmp.create_box(1, "box") + self.pylmp.create_atoms(1, "box") + self.pylmp.mass(1, 1.0) + self.pylmp.velocity("all create", 1.44, 87287, "loop geom") + self.pylmp.pair_style("lj/cut", 2.5) + self.pylmp.pair_coeff(1, 1, 1.0, 1.0, 2.5) + self.pylmp.neighbor(0.3, "bin") + self.pylmp.neigh_modify("delay 0 every 20 check no") + self.pylmp.fix("1 all nve") + self.pylmp.variable("fx atom fx") + self.pylmp.run(10) + + self.assertEqual(len(self.pylmp.runs), 1) + self.assertEqual(self.pylmp.last_run, self.pylmp.runs[0]) + self.assertEqual(len(self.pylmp.last_run.thermo.Step), 2) + self.assertEqual(len(self.pylmp.last_run.thermo.Temp), 2) + self.assertEqual(len(self.pylmp.last_run.thermo.E_pair), 2) + self.assertEqual(len(self.pylmp.last_run.thermo.E_mol), 2) + self.assertEqual(len(self.pylmp.last_run.thermo.TotEng), 2) + self.assertEqual(len(self.pylmp.last_run.thermo.Press), 2) + +if __name__ == "__main__": + unittest.main() diff --git a/unittest/utils/CMakeLists.txt b/unittest/utils/CMakeLists.txt index 5b5b931210..1a10613403 100644 --- a/unittest/utils/CMakeLists.txt +++ b/unittest/utils/CMakeLists.txt @@ -14,3 +14,7 @@ set_tests_properties(Utils PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_PO add_executable(test_fmtlib test_fmtlib.cpp) target_link_libraries(test_fmtlib PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) add_test(FmtLib test_fmtlib) + +add_executable(test_math_eigen_impl test_math_eigen_impl.cpp) +target_include_directories(test_math_eigen_impl PRIVATE ${LAMMPS_SOURCE_DIR}) +add_test(MathEigen test_math_eigen_impl 10 5) diff --git a/unittest/utils/test_math_eigen_impl.cpp b/unittest/utils/test_math_eigen_impl.cpp new file mode 100644 index 0000000000..3ff60c2eb6 --- /dev/null +++ b/unittest/utils/test_math_eigen_impl.cpp @@ -0,0 +1,766 @@ +// THIS FILE USED TO BE EASY TO READ until I added "#if defined" statements. +// (They were added to test for many different kinds of array formats.) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "math_eigen_impl.h" + +using std::cout; +using std::cerr; +using std::endl; +using std::setprecision; +using std::vector; +using std::array; +using namespace MathEigen; + + +// This code works with various types of C++ matrices (for example, +// double **, vector> array,5>). +// I use "#if defined" statements to test different matrix types. +// For some of these (eg. array,5>), the size of the matrix +// must be known at compile time. I specify that size now. +#if defined USE_ARRAY_OF_ARRAYS +const int NF=5; //(the array size must be known at compile time) +#elif defined USE_C_FIXED_SIZE_ARRAYS +const int NF=5; //(the array size must be known at compile time) +#endif + + +// @brief Are two numbers "similar"? +template +inline static bool Similar(Scalar a, Scalar b, + Scalar eps=1.0e-06, + Scalar ratio=1.0e-06, + Scalar ratio_denom=1.0) +{ + return ((std::abs(a-b)<=std::abs(eps)) + || + (std::abs(ratio_denom)*std::abs(a-b) + <= + std::abs(ratio)*0.5*(std::abs(a)+std::abs(b)))); +} + +/// @brief Are two vectors (containing n numbers) similar? +template +inline static bool SimilarVec(Vector a, Vector b, int n, + Scalar eps=1.0e-06, + Scalar ratio=1.0e-06, + Scalar ratio_denom=1.0) +{ + for (int i = 0; i < n; i++) + if (not Similar(a[i], b[i], eps, ratio, ratio_denom)) + return false; + return true; +} + +/// @brief Are two vectors (or their reflections) similar? +template +inline static bool SimilarVecUnsigned(Vector a, Vector b, int n, + Scalar eps=1.0e-06, + Scalar ratio=1.0e-06, + Scalar ratio_denom=1.0) +{ + if (SimilarVec(a, b, n, eps)) + return true; + else { + for (int i = 0; i < n; i++) + if (not Similar(a[i], -b[i], eps, ratio, ratio_denom)) + return false; + return true; + } +} + + +/// @brief Multiply two matrices A and B, store the result in C. (C = AB). + +template +void mmult(ConstMatrix A, // +void +SortRows(Vector eval, + Matrix evec, + int n, + bool sort_decreasing=true, + bool sort_abs=false) +{ + for (int i = 0; i < n-1; i++) { + int i_max = i; + for (int j = i+1; j < n; j++) { + if (sort_decreasing) { + if (sort_abs) { //sort by absolute value? + if (std::abs(eval[j]) > std::abs(eval[i_max])) + i_max = j; + } + else if (eval[j] > eval[i_max]) + i_max = j; + } + else { + if (sort_abs) { //sort by absolute value? + if (std::abs(eval[j]) < std::abs(eval[i_max])) + i_max = j; + } + else if (eval[j] < eval[i_max]) + i_max = j; + } + } + std::swap(eval[i], eval[i_max]); // sort "eval" + for (int k = 0; k < n; k++) + std::swap(evec[i][k], evec[i_max][k]); // sort "evec" + } +} + + + +/// @brief Generate a random orthonormal n x n matrix + +template +void GenRandOrth(Matrix R, + int n, + std::default_random_engine &rand_generator) +{ + std::normal_distribution gaussian_distribution(0,1); + std::vector v(n); + + for (int i = 0; i < n; i++) { + // Generate a vector, "v", in a random direction subject to the constraint + // that it is orthogonal to the first i-1 rows-vectors of the R matrix. + Scalar rsq = 0.0; + while (rsq == 0.0) { + // Generate a vector in a random direction + // (This works because we are using a normal (Gaussian) distribution) + for (int j = 0; j < n; j++) + v[j] = gaussian_distribution(rand_generator); + + //Now subtract from v, the projection of v onto the first i-1 rows of R. + //This will produce a vector which is orthogonal to these i-1 row-vectors. + //(They are already normalized and orthogonal to each other.) + for (int k = 0; k < i; k++) { + Scalar v_dot_Rk = 0.0; + for (int j = 0; j < n; j++) + v_dot_Rk += v[j] * R[k][j]; + for (int j = 0; j < n; j++) + v[j] -= v_dot_Rk * R[k][j]; + } + // check if it is linearly independent of the other vectors and non-zero + rsq = 0.0; + for (int j = 0; j < n; j++) + rsq += v[j]*v[j]; + } + // Now normalize the vector + Scalar r_inv = 1.0 / std::sqrt(rsq); + for (int j = 0; j < n; j++) + v[j] *= r_inv; + // Now copy this vector to the i'th row of R + for (int j = 0; j < n; j++) + R[i][j] = v[j]; + } //for (int i = 0; i < n; i++) +} //void GenRandOrth() + + + +/// @brief Generate a random symmetric n x n matrix, M. +/// This function generates random numbers for the eigenvalues ("evals_known") +/// as well as the eigenvectors ("evecs_known"), and uses them to generate M. +/// The "eval_magnitude_range" argument specifies the the base-10 logarithm +/// of the range of eigenvalues desired. The "n_degeneracy" argument specifies +/// the number of repeated eigenvalues desired (if any). +/// @returns This function does not return a value. However after it is +/// invoked, the M matrix will be filled with random numbers. +/// Additionally, the "evals" and "evecs" arguments will contain +/// the eigenvalues and eigenvectors (one eigenvector per row) +/// of the matrix. Later, they can be compared with the eigenvalues +/// and eigenvectors calculated by Jacobi::Diagonalize() + +template +void GenRandSymm(Matrix M, // random_real01; + std::normal_distribution gaussian_distribution(0, max_eval_size); + bool use_log_uniform_distribution = false; + if (min_eval_size > 0.0) + use_log_uniform_distribution = true; + #if defined USE_VECTOR_OF_VECTORS + vector > D(n, vector(n)); + vector > tmp(n, vector(n)); + #elif defined USE_ARRAY_OF_ARRAYS + array, NF> D; + array, NF> tmp; + #elif defined USE_C_FIXED_SIZE_ARRAYS + Scalar D[NF][NF], tmp[NF][NF]; + #else + #define USE_C_POINTER_TO_POINTERS + Scalar **D, **tmp; + Alloc2D(n, n, &D); + Alloc2D(n, n, &tmp); + #endif + + // Randomly generate the eigenvalues + for (int i = 0; i < n; i++) { + if (use_log_uniform_distribution) { + // Use a "log-uniform distribution" (a.k.a. "reciprocal distribution") + // (This is a way to specify numbers with a precise range of magnitudes.) + assert((min_eval_size > 0.0) && (max_eval_size > 0.0)); + Scalar log_min = std::log(std::abs(min_eval_size)); + Scalar log_max = std::log(std::abs(max_eval_size)); + Scalar log_eval = (log_min + random_real01(rand_generator)*(log_max-log_min)); + evals[i] = std::exp(log_eval); + // also consider both positive and negative eigenvalues: + if (random_real01(rand_generator) < 0.5) + evals[i] = -evals[i]; + } + else { + evals[i] = gaussian_distribution(rand_generator); + } + } + + // Does the user want us to force some of the eigenvalues to be the same? + if (n_degeneracy > 1) { + int *permutation = new int[n]; //a random permutation from 0...n-1 + for (int i = 0; i < n; i++) + permutation[i] = i; + std::shuffle(permutation, permutation+n, rand_generator); + for (int i = 1; i < n_degeneracy; i++) //set the first n_degeneracy to same + evals[permutation[i]] = evals[permutation[0]]; + delete [] permutation; + } + + // D is a diagonal matrix whose diagonal elements are the eigenvalues + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + D[i][j] = ((i == j) ? evals[i] : 0.0); + + // Now randomly generate the (transpose of) the "evecs" matrix + GenRandOrth(evecs, n, rand_generator); //(will transpose it later) + + // Construct the test matrix, M, where M = Rt * D * R + + // Original code: + //mmult(evecs, D, tmp, n); // <--> tmp = Rt * D + // Unfortunately, C++ guesses the types incorrectly. Must manually specify: + // #ifdefs making the code ugly again: + #if defined USE_VECTOR_OF_VECTORS + mmult >&, const vector >&> + #elif defined USE_ARRAY_OF_ARRAYS + mmult,NF>&, const array,NF>&> + #elif defined USE_C_FIXED_SIZE_ARRAYS + mmult + #else + mmult + #endif + (evecs, D, tmp, n); + + for (int i = 0; i < n-1; i++) + for (int j = i+1; j < n; j++) + std::swap(evecs[i][j], evecs[j][i]); //transpose "evecs" + + // Original code: + //mmult(tmp, evecs, M, n); + // Unfortunately, C++ guesses the types incorrectly. Must manually specify: + // #ifdefs making the code ugly again: + #if defined USE_VECTOR_OF_VECTORS + mmult >&, const vector >&> + #elif defined USE_ARRAY_OF_ARRAYS + mmult,NF>&, const array,NF>&> + #elif defined USE_C_FIXED_SIZE_ARRAYS + mmult + #else + mmult + #endif + (tmp, evecs, M, n); + //at this point M = Rt*D*R (where "R"="evecs") + + #if defined USE_C_POINTER_TO_POINTERS + Dealloc2D(&D); + Dealloc2D(&tmp); + #endif +} // GenRandSymm() + + + +template +void TestJacobi(int n, //&, + vector >&, + const vector >& > ecalc(n); + + // allocate the matrix, eigenvalues, eigenvectors + vector > M(n, vector(n)); + vector > evecs(n, vector(n)); + vector > evecs_known(n, vector(n)); + vector evals(n); + vector evals_known(n); + vector test_evec(n); + + #elif defined USE_ARRAY_OF_ARRAYS + + n = NF; + cout << "Testing std::array (fixed size).\n" + "(Ignoring first argument, and setting matrix size to " << n << ")" << endl; + + Jacobi&, + array, NF>&, + const array, NF>&> ecalc(n); + + // allocate the matrix, eigenvalues, eigenvectors + array, NF> M; + array, NF> evecs; + array, NF> evecs_known; + array evals; + array evals_known; + array test_evec; + + #elif defined USE_C_FIXED_SIZE_ARRAYS + + n = NF; + cout << "Testing C fixed size arrays.\n" + "(Ignoring first argument, and setting matrix size to " << n << ")" << endl; + Jacobi ecalc(n); + + // allocate the matrix, eigenvalues, eigenvectors + Scalar M[NF][NF]; + Scalar evecs[NF][NF]; + Scalar evecs_known[NF][NF]; + Scalar evals[NF]; + Scalar evals_known[NF]; + Scalar test_evec[NF]; + + #else + + #define USE_C_POINTER_TO_POINTERS + + // Note: Normally, you would just use this to instantiate Jacobi: + // Jacobi ecalc(n); + // ------------------------- + // ..but since Jacobi manages its own memory using new and delete, I also want + // to test that the copy constructors, copy operators, and destructors work. + // The following lines do this: + Jacobi ecalc_test_mem1(n); + Jacobi ecalc_test_mem2(2); + // test the = operator + ecalc_test_mem2 = ecalc_test_mem1; + // test the copy constructor + Jacobi ecalc(ecalc_test_mem2); + // allocate the matrix, eigenvalues, eigenvectors + Scalar **M, **evecs, **evecs_known; + Alloc2D(n, n, &M); + Alloc2D(n, n, &evecs); + Alloc2D(n, n, &evecs_known); + Scalar *evals = new Scalar[n]; + Scalar *evals_known = new Scalar[n]; + Scalar *test_evec = new Scalar[n]; + + #endif + + + // -------------------------------------------------------------------- + // Now, generate random matrices and test Jacobi::Diagonalize() on them. + // -------------------------------------------------------------------- + + for(int imat = 0; imat < n_matrices; imat++) { + + // Create a randomly generated symmetric matrix. + //This function generates random numbers for the eigenvalues ("evals_known") + //as well as the eigenvectors ("evecs_known"), and uses them to generate M. + + #if defined USE_VECTOR_OF_VECTORS + GenRandSymm&, vector >&> + #elif defined USE_ARRAY_OF_ARRAYS + GenRandSymm&, array,NF>&> + #elif defined USE_C_FIXED_SIZE_ARRAYS + GenRandSymm + #else + GenRandSymm + #endif + (M, + n, + evals_known, + evecs_known, + rand_generator, + min_eval_size, + max_eval_size, + n_degeneracy); + + // Sort the matrix evals and eigenvector rows: + // Original code: + //SortRows(evals_known, evecs_known, n); + // Unfortunately, C++ guesses the types incorrectly. Must use #ifdefs again: + #if defined USE_VECTOR_OF_VECTORS + SortRows&, vector >&> + #elif defined USE_ARRAY_OF_ARRAYS + SortRows&, array,NF>&> + #elif defined USE_C_FIXED_SIZE_ARRAYS + SortRows + #else + SortRows + #endif + (evals_known, evecs_known, n); + + + if (n_matrices == 1) { + cout << "Eigenvalues (after sorting):\n"; + for (int i = 0; i < n; i++) + cout << evals_known[i] << " "; + cout << "\n"; + cout << "Eigenvectors (rows) which are known in advance:\n"; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) + cout << evecs_known[i][j] << " "; + cout << "\n"; + } + cout << " (The eigenvectors calculated by Jacobi::Diagonalize() should match these.)\n"; + } + + for (int i_test = 0; i_test < n_tests_per_matrix; i_test++) { + + if (test_code_coverage) { + + // test SORT_INCREASING_ABS_EVALS: + #if defined USE_VECTOR_OF_VECTORS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + vector >&, + const vector >& >::SORT_INCREASING_ABS_EVALS); + #elif defined USE_ARRAY_OF_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + array,NF>&, + const array,NF>&>::SORT_INCREASING_ABS_EVALS); + #elif defined USE_C_FIXED_SIZE_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_INCREASING_ABS_EVALS); + #else + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_INCREASING_ABS_EVALS); + #endif + + for (int i = 1; i < n; i++) + assert(std::abs(evals[i-1])<=std::abs(evals[i])); + + // test SORT_DECREASING_ABS_EVALS: + #if defined USE_VECTOR_OF_VECTORS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + vector >&, + const vector >& >::SORT_DECREASING_ABS_EVALS); + #elif defined USE_ARRAY_OF_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + array,NF>&, + const array,NF>&>::SORT_DECREASING_ABS_EVALS); + #elif defined USE_C_FIXED_SIZE_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_DECREASING_ABS_EVALS); + #else + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_DECREASING_ABS_EVALS); + #endif + + for (int i = 1; i < n; i++) + assert(std::abs(evals[i-1])>=std::abs(evals[i])); + + // test SORT_INCREASING_EVALS: + #if defined USE_VECTOR_OF_VECTORS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + vector >&, + const vector >& >::SORT_INCREASING_EVALS); + #elif defined USE_ARRAY_OF_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + array,NF>&, + const array,NF>&>::SORT_INCREASING_EVALS); + #elif defined USE_C_FIXED_SIZE_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_INCREASING_EVALS); + #else + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_INCREASING_EVALS); + #endif + for (int i = 1; i < n; i++) + assert(evals[i-1] <= evals[i]); + + // test DO_NOT_SORT + #if defined USE_VECTOR_OF_VECTORS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + vector >&, + const vector >& >::DO_NOT_SORT); + #elif defined USE_ARRAY_OF_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + array,NF>&, + const array,NF>&>::DO_NOT_SORT); + #elif defined USE_C_FIXED_SIZE_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::DO_NOT_SORT); + #else + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::DO_NOT_SORT); + #endif + + } //if (test_code_coverage) + + + // Now (finally) calculate the eigenvalues and eigenvectors + int n_sweeps = ecalc.Diagonalize(M, evals, evecs); + + if ((n_matrices == 1) && (i_test == 0)) { + cout <<"Jacobi::Diagonalize() ran for "< Σ_b M[a][b]*evecs[i][b] = evals[i]*evecs[i][b] (for all a) + for (int i = 0; i < n; i++) { + for (int a = 0; a < n; a++) { + test_evec[a] = 0.0; + for (int b = 0; b < n; b++) + test_evec[a] += M[a][b] * evecs[i][b]; + assert(Similar(test_evec[a], + evals[i] * evecs[i][a], + eps, // tolerance (absolute difference) + eps*max_eval_size, // tolerance ratio (numerator) + evals_known[i] // tolerance ration (denominator) + )); + } + } + + } //for (int i_test = 0; i_test < n_tests_per_matrix; i++) + + } //for(int imat = 0; imat < n_matrices; imat++) { + + #if defined USE_C_POINTER_TO_POINTERS + Dealloc2D(&M); + Dealloc2D(&evecs); + Dealloc2D(&evecs_known); + delete [] evals; + delete [] evals_known; + delete [] test_evec; + #endif + +} //TestJacobi() + + +int main(int argc, char **argv) { + int n_size = 2; + int n_matr = 1; + double emin = 0.0; + double emax = 1.0; + int n_tests = 1; + int n_degeneracy = 1; + unsigned seed = 0; + + if (argc <= 1) { + cerr << + "Error: This program requires at least 1 argument.\n" + "\n" + "Description: Run Jacobi::Diagonalize() on randomly generated matrices.\n" + "\n" + "Arguments: n_size [n_matr emin emax n_degeneracy n_tests seed eps]\n" + " n_size = the size of the matrices\n" + " (NOTE: The remaining arguments are optional.)\n" + " n_matr = the number of randomly generated matrices to test\n" + " emin = the smallest possible eigenvalue magnitude (eg. 1e-05)\n" + " emax = the largest possible eigenvalue magnitude (>0 eg. 1e+05)\n" + " (NOTE: If emin=0, a normal distribution is used centered at 0.\n" + " Otherwise a log-uniform distribution is used from emin to emax.)\n" + " n_degeneracy = the number of repeated eigenvalues (1 disables, default)\n" + " n_tests = the number of times the eigenvalues and eigenvectors\n" + " are calculated for EACH matrix. By default this is 1.\n" + " (Increase this to at least 20 if you plan to use this\n" + " program for benchmarking (speed testing), because the time\n" + " needed for generating a random matrix is not negligible.)\n" + " (IF THIS NUMBER IS 0, it will test CODE-COVERAGE instead.)\n" + " seed = the seed used by the random number \"rand_generator\".\n" + " (If this number is 0, which is the default, the system\n" + " clock is used to choose a random seed.)\n" + " eps = the tolerance. The difference between eigenvalues and their\n" + " true value, cannot exceed this (multiplied by the eigenvalue\n" + " of maximum magnitude). Similarly, the difference between\n" + " the eigenvectors after multiplication by the matrix and by\n" + " and after multiplication by the eigenvalue, cannot exceed\n" + " eps*maximum_eigenvalue/eigenvalue. The default value is\n" + " 1.0e-06 (which works well for double precision numbers).\n" + << endl; + return 1; + } + + n_size = std::stoi(argv[1]); + if (argc > 2) + n_matr = std::stoi(argv[2]); + if (argc > 3) + emin = std::stof(argv[3]); + if (argc > 4) + emax = std::stof(argv[4]); + if (argc > 5) + n_degeneracy = std::stoi(argv[5]); + if (argc > 6) + n_tests = std::stoi(argv[6]); + if (argc > 7) + seed = std::stoi(argv[7]); + double eps = 1.0e-06; + if (argc > 8) + eps = std::stof(argv[8]); + + TestJacobi(n_size, n_matr, emin, emax, n_tests, n_degeneracy, seed, eps); + + cout << "test passed\n" << endl; + return EXIT_SUCCESS; +}