lib*.pc
Doxyfile
doxygen-doc
+.project
+.cproject
cmake_minimum_required(VERSION 2.6)
project(Gromacs)
+include(Dart)
# PROJECT_VERSION should have the following structure:
# VERSION[-dev-SUFFIX] where the VERSION can have any form and the suffix
set(PROJECT_VERSION "4.0.99-dev-20100315"
# Cmake modules/macros are in a subdirectory to keep this file cleaner
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
+endif(NOT CMAKE_BUILD_TYPE)
+
+enable_language(C)
+
+
+########################################################################
+# Fix stupid flags on MSVC
+########################################################################
+IF(CMAKE_GENERATOR MATCHES "Visual Studio")
+ STRING(REPLACE /MD /MT CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
+ SET(CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} CACHE STRING "" FORCE)
+ STRING(REPLACE /MD /MT CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
+ SET(CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} CACHE STRING "" FORCE)
+ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio")
+
+set(GMX_EXTRA_LIBRARIES)
+
+######################################################################
+# compiler tests
+# these need ot be done early (before further tests).
+#####################################################################
+
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+
+# check for buggy GCC 4.1.x
+include(gmxCheckGCCVersion)
+
+include(gmxCFlags)
+gmx_c_flags()
+
########################################################################
# User input options #
########################################################################
option(GMX_DISABLE_FFTW_MEASURE
"Do not optimize FFTW setups (not needed with SSE)" OFF)
set(GMX_QMMM_PROGRAM "none"
- CACHE STRING "QM package choices: none,gaussian,mopac,gamess")
+ CACHE STRING "QM package choices: none,gaussian,mopac,gamess,orca")
option(GMX_BROKEN_CALLOC "Work around broken calloc()" OFF)
option(BUILD_SHARED_LIBS "Enable shared libraries (can be problematic with MPI)" OFF)
option(GMX_MPI_IN_PLACE "Enable MPI_IN_PLACE for MPIs that have it defined" ON)
option(GMX_DLOPEN "Compile with dlopen, needed to read VMD supported file formats" ON)
mark_as_advanced(GMX_MPI_IN_PLACE)
-enable_language(C)
option(GMX_IA32_ASM "Add SSE assembly files for IA32" OFF)
option(GMX_X86_64_ASM "Add SSE assembly files for X86_64" OFF)
option(USE_VERSION_H "Generate development version string/information" ON)
+option(GMX_DISABLE_GCC41_CHECK "Disable check for (buggy) gcc 4.1.x" OFF)
-#######################################################################
-# Check for options incompatible with OpenMM build #
-#######################################################################
-if(GMX_OPENMM)
- cmake_minimum_required(VERSION 2.6.4)
- # we'll use the built-in fft to avoid unnecessary dependencies
- set (GMX_FFT_LIBRARY "fftpack")
- if(GMX_MPI)
- message(FATAL_ERROR "The OpenMM build is not compatible with MPI!")
- endif(GMX_MPI)
- if(GMX_THREADS)
- message(STATUS "Threads not compatible with OpenMM build, disabled")
- set(GMX_THREADS OFF)
- endif(GMX_THREADS)
- if(GMX_SOFTWARE_INVSQRT)
- set(GMX_SOFTWARE_INVSQRT OFF)
- endif(GMX_SOFTWARE_INVSQRT)
- if(NOT GMX_ACCELERATION MATCHES "none")
- message(WARNING "The OpenMM build does not support other acceleration modes!")
- set(GMX_ACCELERATION "none")
- endif()
- if(GMX_FAHCORE)
- message(FATAL_ERROR "The OpenMM build does not support FAH build!")
- endif(GMX_FAHCORE)
-endif(GMX_OPENMM)
-
+set(GMX_BINARY_SUFFIX "" CACHE STRING "Suffix for GROMACS binaries.")
-########################################################################
-# Fix stupid flags on MSVC
-########################################################################
-IF(CMAKE_GENERATOR MATCHES "Visual Studio")
- STRING(REPLACE /MD /MT CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
- SET(CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} CACHE STRING "" FORCE)
- STRING(REPLACE /MD /MT CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
- SET(CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} CACHE STRING "" FORCE)
-ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio")
-set(GMX_EXTRA_LIBRARIES)
########################################################################
#Process MPI settings
set(GMX_LIB_MPI 1)
endif(GMX_MPI)
+
+#######################################################################
+# Check for options incompatible with OpenMM build #
+#######################################################################
+if(GMX_OPENMM)
+ cmake_minimum_required(VERSION 2.6.4)
+ # we'll use the built-in fft to avoid unnecessary dependencies
+ set (GMX_FFT_LIBRARY "fftpack")
+ if(GMX_MPI)
+ message(FATAL_ERROR "The OpenMM build is not compatible with MPI!")
+ endif(GMX_MPI)
+ if(GMX_THREADS)
+ message(STATUS "Threads not compatible with OpenMM build, disabled")
+ set(GMX_THREADS OFF)
+ endif(GMX_THREADS)
+ if(GMX_SOFTWARE_INVSQRT)
+ set(GMX_SOFTWARE_INVSQRT OFF)
+ endif(GMX_SOFTWARE_INVSQRT)
+ if(NOT GMX_ACCELERATION MATCHES "none|None|NONE" OR NOT ${GMX_ACCELERATION} STREQUAL "")
+ message(WARNING "The OpenMM build does not support other acceleration modes!")
+ set(GMX_ACCELERATION "none")
+ endif()
+ if(GMX_FAHCORE)
+ message(FATAL_ERROR "The OpenMM build does not support FAH build!")
+ endif(GMX_FAHCORE)
+endif(GMX_OPENMM)
+
+
+
########################################################################
# Basic system tests (standard libraries, headers, functions, types) #
########################################################################
include(CheckIncludeFiles)
check_include_files(string.h HAVE_STRING_H)
+check_include_files(math.h HAVE_MATH_H)
check_include_files(limits.h HAVE_LIMITS_H)
check_include_files(memory.h HAVE_MEMORY_H)
check_include_files(unistd.h HAVE_UNISTD_H)
check_include_files(dirent.h HAVE_DIRENT_H)
check_include_files(inttypes.h HAVE_INTTYPES_H)
check_include_files(regex.h HAVE_REGEX_H)
+check_include_files(copyfile.h HAVE_COPYFILE_H)
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
check_include_files(sys/stat.h HAVE_SYS_STAT_H)
check_include_files(sys/time.h HAVE_SYS_TIME_H)
check_include_files(emmintrin.h HAVE_EMMINTRIN_H)
check_include_files(pmmintrin.h HAVE_PMMINTRIN_H)
check_include_files(smmintrin.h HAVE_SMMINTRIN_H)
+check_include_files(io.h HAVE_IO_H)
+
include(CheckFunctionExists)
check_function_exists(strcasecmp HAVE_STRCASECMP)
check_function_exists(strdup HAVE_STRDUP)
check_function_exists(vprintf HAVE_VPRINTF)
check_function_exists(memcmp HAVE_MEMCMP)
+check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN)
+check_function_exists(memalign HAVE_MEMALIGN)
+check_function_exists(_aligned_malloc HAVE__ALIGNED_MALLOC)
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
check_function_exists(isnan HAVE_ISNAN)
check_function_exists(_isnan HAVE__ISNAN)
check_function_exists(isfinite HAVE_ISFINITE)
check_function_exists(_isfinite HAVE__ISFINITE)
+check_function_exists(fsync HAVE_FSYNC)
+check_function_exists(_fileno HAVE__FILENO)
+check_function_exists(fileno HAVE_FILENO)
+check_function_exists(_commit HAVE__COMMIT)
+check_function_exists(copyfile HAVE_COPYFILE)
+# check_function_exists(CopyFile HAVE_WIN_COPYFILE)
# After large files? check_function_exists(fseeko HAVE_FSEEKO)
include(CheckLibraryExists)
check_library_exists(m sqrt "" HAVE_LIBM)
+check_library_exists(m cbrt "" HAVE_CBRT)
include(CheckTypeSize)
check_type_size("bool" SIZEOF_BOOL) # will also set HAVE_BOOL
check_type_size("off_t" SIZEOF_OFF_T)
check_type_size("void *" SIZEOF_VOIDP)
+if (SIZEOF_VOIDP LESS 8)
+ set(GMX_64_BIT FALSE)
+else (SIZEOF_VOIDP LESS 8)
+ set(GMX_64_BIT TRUE)
+endif (SIZEOF_VOIDP LESS 8)
+
# Check for some basic types that we *need*, so set these to int if they are not present
check_type_size(uid_t uid_t)
if(NOT uid_t)
+
########################################################################
# Find external packages #
########################################################################
# We need at least git v1.5.1 be able to parse git's date output. If not
# fund or the version is too small, we can't generate version information.
find_package(Git 1.5.1)
- if(NOT Git_FOUND OR Git_VERSION VERSION_LESS "1.5.1")
+ # this should at some point become VERSION_LESS
+ if(NOT Git_FOUND OR Git_VERSION STRLESS "1.5.1")
message("No compatible git version found, won't be able to generate proper development version information.")
endif()
endif()
set(USE_VERSION_H OFF)
endif()
+if (GMX_DLOPEN)
+ list(APPEND GMX_EXTRA_LIBRARIES ${CMAKE_DL_LIBS})
+endif (GMX_DLOPEN)
+
########################################################################
# Generate development version info for cache
########################################################################
# Our own GROMACS tests
########################################################################
-include(gmxCFlags)
-gmx_c_flags()
-
add_definitions( -DHAVE_CONFIG_H )
include_directories(${CMAKE_BINARY_DIR}/src)
include_directories(${CMAKE_SOURCE_DIR}/include)
gmx_test_inline_asm_gcc_x86(GMX_X86_GCC_INLINE_ASM)
gmx_test_inline_asm_msvc_x86(GMX_X86_MSVC_INLINE_ASM)
+# reasonable defaults for fast binaries.
+if (NOT DEFINED GMX_SSE_SET)
+ if (GMX_X86_GCC_INLINE_ASM)
+ set(GMX_ACCELERATION "SSE" CACHE STRING "Accelerated kernels. Pick one of: SSE, BlueGene, Power6, ia64, altivec" FORCE)
+ if (GMX_64_BIT)
+ set(GMX_X86_64_ASM ON CACHE BOOL
+ "Add SSE assembly files for x86_64" FORCE)
+ else (GMX_64_BIT)
+ set(GMX_IA32_ASM ON CACHE BOOL
+ "Add SSE assembly files for IA32" FORCE)
+ endif (GMX_64_BIT)
+ endif (GMX_X86_GCC_INLINE_ASM)
+ set (GMX_SSE_SET true CACHE INTERNAL "SSE is set" FORCE)
+endif (NOT DEFINED GMX_SSE_SET)
+
+
+
+
include(gmxTestXDR)
gmx_test_xdr(GMX_SYSTEM_XDR)
if(NOT GMX_SYSTEM_XDR)
if(${GMX_ACCELERATION} STREQUAL "NONE")
# nothing to do
elseif(${GMX_ACCELERATION} STREQUAL "SSE")
+ if (NOT GMX_64_BIT)
+ # for 32-bit compiles, we might need to turn on sse
+ CHECK_C_COMPILER_FLAG("-msse2" XFLAGS_SSE)
+ if (XFLAGS_SSE)
+ set(GROMACS_C_FLAGS "-msse2 ${GROMACS_C_FLAGS}")
+ endif (XFLAGS_SSE)
+ CHECK_CXX_COMPILER_FLAG("-msse2" XXFLAGS_SSE)
+ if (XXFLAGS_SSE)
+ set(GROMACS_CXX_FLAGS "-msse2 ${GROMACS_CXX_FLAGS}")
+ endif (XXFLAGS_SSE)
+ endif (NOT GMX_64_BIT)
if(HAVE_XMMINTRIN_H)
if(GMX_IA32_ASM)
option(GMX_ASM_USEASM-ATT "Use ATT-style assembly" ON)
set(GMX_QMMM_MOPAC 1)
elseif(${GMX_QMMM_PROGRAM} STREQUAL "GAMESS")
set(GMX_QMMM_GAMESS 1)
+elseif(${GMX_QMMM_PROGRAM} STREQUAL "ORCA")
+ set(GMX_QMMM_ORCA 1)
elseif(${GMX_QMMM_PROGRAM} STREQUAL "NONE")
# nothing to do
else(${GMX_QMMM_PROGRAM} STREQUAL "GAUSSIAN")
- MESSAGE(FATAL_ERROR "Invalid QM/MM program option: ${GMX_QMMM_PROGRAM}. Choose one of: Gaussian, Mopac, Gamess, None")
+ MESSAGE(FATAL_ERROR "Invalid QM/MM program option: ${GMX_QMMM_PROGRAM}. Choose one of: Gaussian, Mopac, Gamess, Orca, None")
endif(${GMX_QMMM_PROGRAM} STREQUAL "GAUSSIAN")
# Process FFT library settings - if not OpenMM build
endif(GMX_FAHCORE)
# # # # # # # # # # NO MORE TESTS AFTER THIS LINE! # # # # # # # # # # #
-set(CMAKE_C_FLAGS ${GROMACS_C_FLAGS} CACHE STRING "Compiler flags")
-set(CMAKE_EXE_LINKER_FLAGS ${GROMACS_LINKER_FLAGS} CACHE STRING "Linker flags")
+# these are set after everything else
+if (NOT DEFINED GROMACS_C_FLAGS_SET)
+ set(GROMACS_C_FLAGS_SET true CACHE INTERNAL "Whether to reset the C flags"
+ FORCE)
+ set(CMAKE_C_FLAGS "${GROMACS_C_FLAGS} ${CMAKE_C_FLAGS}" CACHE STRING
+ "Flags used by the compiler during all build types" FORCE)
+ set(CMAKE_CXX_FLAGS "${GROMACS_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" CACHE STRING
+ "Flags used by the compiler during all build types" FORCE)
+ set(CMAKE_EXE_LINKER_FLAGS
+ "${GROMACS_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}"
+ CACHE STRING "Linker flags" FORCE)
+endif (NOT DEFINED GROMACS_C_FLAGS_SET)
########################################################################
# Specify install locations and which subdirectories to process #
add_subdirectory(src)
+########################################################################
+# Tests #
+########################################################################
+
+enable_testing()
+add_test(TestBuildAll make)
+add_subdirectory(tests)
--- /dev/null
+GROMACS is free software, distributed under the GNU General Public License.
+The GROMACS-GPU release however includes / relies on code covered by several
+different licences as described below.
+
+
+1. GROMACS source
+
+The major parts of the GROMACS source are covered by the GNU General Public
+License, a copy of this license can be found in the file COPYING.
+
+
+2. The memtestG80 library
+
+The memtestG80 library, written by Imran Haque, is Copyright 2009 Stanford University,
+covered by the LGPL license. It may be used under the following terms:
+
+IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION PROVIDED HEREUNDER IS PROVIDED "AS IS". Folding@home HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+Restrictions:
+
+You may use this software on a computer system only if you own the system or have the written permission of the owner.
+
+You may not alter the software or associated data files.
+
+Certain builds of this software incorporate by linkage code from the libintl
+and libiconv libraries, which are covered by the Library GNU Public License,
+available at http://www.gnu.org/licenses/lgpl-3.0.txt.
+
+
+3. OpenMM (binary distributions only)
+
+There are several licenses which cover different parts of OpenMM as described
+in the file openmm/licenses/Licenses.txt accompanying the binary distribution.
+
+
+4. FindCUDA.cmake script
+
+The FindCUDA.cmake script may be used under the terms of the MIT License:
+
+ James Bigler, NVIDIA Corp (nvidia.com - jbigler)
+ Abe Stephens, SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html
+
+ Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved.
+
+ Copyright (c) 2007-2009
+ Scientific Computing and Imaging Institute, University of Utah
+
+ This code is licensed under the MIT License. See the FindCUDA.cmake script
+ for the text of the license.
- Welcome to GROMACS 3.1!
+ Welcome to GROMACS!
Note: Detailed, step-by-step installation instructions
are available on the website http://www.gromacs.org .
* SHORT INSTRUCTIONS FOR THE IMPATIENT:
-Starting with version 3.0, the GROMACS compile and install procedure
-was changed to simplify things for you. We now use a standard
-autoconf script and makefiles created by automake, like most
-GNU programs. This means your normal installation actions are
-limited to:
+GROMACS uses a standard autoconf script and makefiles created
+by automake, like most GNU programs. This means your normal
+installation actions are limited to:
./configure
make
--- /dev/null
+
+ Welcome to GROMACS-GPU!
+
+Note: Detailed, step-by-step installation instructions as
+well as additional information are available on the website
+http://www.gromacs.org/gpu
+
+
+* INSTALLING FROM BINARY DISTRIBUTION:
+
+0. Prerequisites:
+ - OpenMM (included in the binary release)
+ - NVIDIA CUDA libraries (version >=3.0);
+ - NVIDIA driver (for details on compatiblity consult
+ http://www.nvidia.com/Download/index5.aspx);
+ - NVIDIA CUDA-enabled GPU (for compatiblity list see
+ http://www.gromacs.org/gpu).
+
+
+1. Download and unpack the binary package for the respective
+OS and architecture. Copy the content of the package to your
+normal GROMACS installation directory (or to a custom location).
+Note that as the distributed Gromacs-GPU packages do not contain
+the entire set of tools and utilities included in a full GROAMCS
+installation. Therefore, it is recommended to have a ≥v4.5
+standard Gromacs installation along the GPU accelerated one.
+e.g. on unix:
+
+tar -xvf gromacs-4.5-GPU.tar.gz
+cp -R gromacs-4.5-GPU/* PATH_TO_GROMACS_INSTALLATION
+
+
+2. Add the openmm/lib directory to your library path, e.g. in bash:
+
+export LD_LIBRARY_PATH=PATH_TO_GROMACS/openmm/lib:$LD_LIBRARY_PATH
+
+If there are other OpenMM versions installed, make sure that the
+supplied libraries have preference when running mdrun-gpu.
+Also, make sure that the CUDA libraries installed match the version
+of CUDA with which GROMACS-GPU is compiled.
+
+
+3. Set the OPENMM_PLUGIN_DIR environment variable to contain the path
+to the openmm/lib/plugins directory, e.g. in bash:
+
+export OPENMM_PLUGIN_DIR=PATH_TO_GROMACS/openmm/lib/plugins
+
+
+4. At this point, running the command:
+
+PATH_TO_GROMACS/bin/mdrun-gpu -h
+
+should display the standard mdrun help which means that all the
+necessary libraries are accessible.
+
+
+
+* INSTALLING FROM SOURCE DISTRIBUTION:
+
+GROMACS-GPU uses a cmake build-generator and makefiles on unix.
+This means your normal installation actions are limited to:
+
+cmake PATH_TO_SOURCE_DIRECTORY -DGMX_OPENMM=ON -DGMX_THREADS=OFF
+make mdrun
+make install-mdrun
+
+
+
+* ARE YOU STILL HAVING PROBLEMS?
+
+Post it to the GROMACS mailing lists. We read these on a regular basis,
+and in many cases another user might already be familiar with the
+task you're trying to perform!
mdrun:
(cd $(top_builddir)/src/gmxlib && $(MAKE) ; exit 0)
(cd $(top_builddir)/src/mdlib && $(MAKE) ; exit 0)
- (cd $(top_builddir)/src/kernel && $(MAKE) lib_LTLIBRARIES ; exit 0)
(cd $(top_builddir)/src/kernel && $(MAKE) mdrun ; exit 0)
install-mdrun:
Welcome to the official version of GROMACS!
-There are no significant changes to the installation or use between version
-3.1 and 3.0, so if you're already used to 3.0 you can just go ahead and update.
-A lot of things changed with version 3.0, though. Not only is the code
-significantly faster, but we also introduced a completely new installation
-process and licensed the package under the GPL (see the COPYING file).
-
If you are familiar with unix, it should be fairly trivial to compile and
install GROMACS. Installation instructions are available in the INSTALL file,
and a more extended step-by-step guide can be found on http://www.gromacs.org .
included in the main distribution. We'll be happy to consider any decent
code. If it's a separate program it can probably be included in the contrib
directory straight away (not supported by us), but for major changes in the
-main code we appreciate if you first test that it works with MPI,
-double precision, fortran code, etc.
+main code we appreciate if you first test that it works with (and without)
+MPI, threads, double precision, etc.
If you still want to distribute a modified version or use part of GROMACS
in your own program, remember that the entire modified must be licensed
H.J.C. Berendsen, D. van der Spoel and R. van Drunen
Comp. Phys. Comm. 91, 43-56 (1995)
-* GROMACS 3.0: A package for molecular simulation and trajectory analysis
- Erik Lindahl, Berk Hess and David van der Spoel
- J. Mol. Mod. 7, 306-317 (2001)
+* GROMACS 4: Algorithms for highly efficient, load-balanced, and scalable
+ molecular simulation
+ B. Hess and C. Kutzner and D. van der Spoel and E. Lindahl
+ J. Chem. Theory Comput. 4 (2008) pp. 435-447
There are a lot of cool features we'd like to include in future versions,
but our resources are limited. All kinds of donations are welcome, both in
--- /dev/null
+
+ Welcome to the official version of GROMACS-GPU!
+
+
+GROMACS-GPU provides GPU-accelerated MD simulations.
+The current release uses the OpenMM library.
+
+This is a first beta release and therefore it is targeted at developers
+and advanced users and is NOT intended for production use.
+
+Installation instructions are available in the INSTALL-GPU file.
+More details on the GPU accelerated release are available on the
+GROMACS-GPU website: http://www.gromacs.org/gpu.
+
+Also see the README file for general GROMACS information.
+
+ * * * * *
+
+GROMACS is free software, distributed under the GNU General Public License.
+The GROMACS-GPU release however includes / relies on code covered by several
+different licences. For details see the COPYING-GPU file.
esac
ACX_CHECK_CC_FLAGS(-funroll-all-loops,funroll_all_loops,xCFLAGS="$xCFLAGS -funroll-all-loops")
ACX_CHECK_CC_FLAGS(-std=gnu99,stdgnu99,xCFLAGS="$xCFLAGS -std=gnu99")
+ # C99 requires strict IEEE 754 floating point compliance. Since gcc>=4.5.0
+ # this is on when asking for c99, potentially impacting floating point
+ # performance, so we turn it off here.
+ ACX_CHECK_CC_FLAGS(-fexcess-precision=fast, fexcess_precision_fast,
+ xCFLAGS="$xCFLAGS -fexcess-precision=fast")
fi
if test "$enable_debug" = "yes"; then
g_sham|read/write xmgr and xvgr data sets
g_spatial|calculates the spatial distribution function (more control than g_sdf)
g_sdf|calculates the spatial distribution function (faster than g_spatial)
+g_select|selects groups of atoms based on flexible textual selections
END
HEAD|Distances between structures
g_order|computes the order parameter per atom for carbon tails
g_h2order|computes the orientation of water molecules
g_bundle|analyzes bundles of axes, e.g. transmembrane helices
+g_membed|embeds a protein into a lipid bilayer
END
# specified. All of the non CUDA C files are compiled using the standard
# build rules specified by CMAKE and the cuda files are compiled to object
# files using nvcc and the host compiler. In addition CUDA_INCLUDE_DIRS is
-# added automatically to include_directories(). Standard CMake target calls
-# can be used on the target after calling this macro
-# (e.g. set_target_properties and target_link_libraries).
+# added automatically to include_directories(). Some standard CMake target
+# calls can be used on the target after calling this macro
+# (e.g. set_target_properties and target_link_libraries), but setting
+# properties that adjust compilation flags will not affect code compiled by
+# nvcc. Such flags should be modified before calling CUDA_ADD_EXECUTABLE,
+# CUDA_ADD_LIBRARY or CUDA_WRAP_SRCS.
#
# CUDA_ADD_LIBRARY( cuda_target file0 file1 ...
# [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [OPTIONS ...] )
if(CUDA_NVCC_EXECUTABLE AND NOT CUDA_VERSION)
# Compute the version.
- exec_program(${CUDA_NVCC_EXECUTABLE} ARGS "--version" OUTPUT_VARIABLE NVCC_OUT)
+ execute_process (COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT)
string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR ${NVCC_OUT})
string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR ${NVCC_OUT})
set(CUDA_VERSION "${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}" CACHE STRING "Version of CUDA as computed from nvcc.")
# CUDA_LIBRARIES
find_library_local_first(CUDA_CUDART_LIBRARY cudart "\"cudart\" library")
set(CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY})
+if(APPLE)
+ # We need to add the path to cudart to the linker using rpath, since the
+ # library name for the cuda libraries is prepended with @rpath.
+ get_filename_component(_cuda_path_to_cudart "${CUDA_CUDART_LIBRARY}" PATH)
+ if(_cuda_path_to_cudart)
+ list(APPEND CUDA_LIBRARIES -Wl,-rpath "-Wl,${_cuda_path_to_cudart}")
+ endif()
+endif()
# 1.1 toolkit on linux doesn't appear to have a separate library on
# some platforms.
if(CUDA_HOST_COMPILATION_CPP)
set(CUDA_C_OR_CXX CXX)
else(CUDA_HOST_COMPILATION_CPP)
- set(nvcc_flags ${nvcc_flags} --host-compilation C)
+ if(CUDA_VERSION VERSION_LESS "3.0")
+ set(nvcc_flags ${nvcc_flags} --host-compilation C)
+ else()
+ message(WARNING "--host-compilation flag is deprecated in CUDA version >= 3.0. Removing --host-compilation C flag" )
+ endif()
set(CUDA_C_OR_CXX C)
endif(CUDA_HOST_COMPILATION_CPP)
cmake_policy(POP)
endif()
+# nvcc doesn't define __CUDACC__ for some reason when generating dependency files. This
+# can cause incorrect dependencies when #including files based on this macro which is
+# defined in the generating passes of nvcc invokation. We will go ahead and manually
+# define this for now until a future version fixes this bug.
+set(CUDACC_DEFINE -D__CUDACC__)
+
# Generate the dependency file
cuda_execute_process(
"Generating dependency file: ${NVCC_generated_dependency_file}"
COMMAND "${CUDA_NVCC_EXECUTABLE}"
+ -M
+ ${CUDACC_DEFINE}
"${source_file}"
- ${depends_CUDA_NVCC_FLAGS}
- ${nvcc_flags}
+ -o "${NVCC_generated_dependency_file}"
${CCBIN}
+ ${nvcc_flags}
${nvcc_host_compiler_flags}
+ ${depends_CUDA_NVCC_FLAGS}
-DNVCC
- -M
- -o "${NVCC_generated_dependency_file}"
${CUDA_NVCC_INCLUDE_ARGS}
)
"Generating ${generated_file}"
COMMAND "${CUDA_NVCC_EXECUTABLE}"
"${source_file}"
- ${CUDA_NVCC_FLAGS}
- ${nvcc_flags}
+ ${format_flag} -o "${generated_file}"
${CCBIN}
+ ${nvcc_flags}
${nvcc_host_compiler_flags}
+ ${CUDA_NVCC_FLAGS}
-DNVCC
- ${format_flag} -o "${generated_file}"
${CUDA_NVCC_INCLUDE_ARGS}
)
# Git_VERSION - git version
# Git_FOUND - tru if git was found, false otherwise
#
-# Szilard Pall (pszilard@cbr.su.se)
+# Author: Szilard Pall (pszilard@cbr.su.se)
if(Git_EXECUTABLE AND Git_VERSION)
set(Git_FIND_QUIETLY TRUE)
# search for git binary
find_program(Git_EXECUTABLE git
- DOC "Git version control tool")
+ PATHS ENV PATH
+ CACHE DOC "Git version control tool")
if(NOT Git_EXECUTABLE)
set(_err_msg "Git executable not found")
# check version
set(_git_version_ok TRUE)
- if(Git_FIND_VERSION_EXACT AND NOT Git_VERSION VERSION_EQUAL Git_FIND_VERSION)
+ # this should at some point become VERSION_EQUAL
+ if(Git_FIND_VERSION_EXACT AND NOT Git_VERSION STREQUAL Git_FIND_VERSION)
set(_err_msg "Found git version ${Git_VERSION} but this does not match the requested ${Git_FIND_VERSION}")
if(Git_FIND_REQUIRED)
message(FATAL_ERROR " ${_err_msg}")
endif()
set(_git_version_ok FALSE)
endif()
- if(Git_FIND_VERSION AND Git_VERSION VERSION_LESS Git_FIND_VERSION)
+ # this should at some point become VERSION_LESS
+ if(Git_FIND_VERSION AND Git_VERSION STRLESS Git_FIND_VERSION)
set(_err_msg "Found git version ${Git_VERSION} but this is less then the requested ${Git_FIND_VERSION}")
if(Git_FIND_REQUIRED)
message(FATAL_ERROR " ${_err_msg}")
-# Find OpenMM library
+# Find OpenMM library.
#
-# Defines:
+# Looks for the OpenMM libraries at the default (/usr/local) location
+# or custom location found in the OPENMM_ROOT_DIR environment variable.
+#
+# The script defines defines:
# OpenMM_FOUND
# OpenMM_ROOT_DIR
# OpenMM_INCLUDE_DIR
# OpenMM_LIBRARY_DIR
-# OpenMM_LIBRARIES
+# OpenMM_LIBRARIES
+# OpenMM_LIBRARIES_D - debug version of libraries
# OpenMM_PLUGIN_DIR
#
-# include(LibFindMacros) TODO get this: http://zi.fi/cmake/Modules/LibFindMacros.cmake
+# Author: Szilard Pall (pszilard@cbr.su.se)
if(OpenMM_INCLUDE_DIR AND OpenMM_LIBRARY_DIR AND OpenMM_PLUGIN_DIR)
set(OpenMM_FIND_QUIETLY)
endif()
-if(IS_DIRECTORY "$ENV{OPENMM_ROOT_DIR}")
- set(OpenMM_ROOT_DIR $ENV{OPENMM_ROOT_DIR} CACHE PATH "OpenMM installation directory" FORCE)
+file(TO_CMAKE_PATH "$ENV{OPENMM_ROOT_DIR}" _env_OPENMM_ROOT_DIR)
+
+if(IS_DIRECTORY ${_env_OPENMM_ROOT_DIR})
+ set(OpenMM_ROOT_DIR "${_env_OPENMM_ROOT_DIR}" CACHE PATH "OpenMM installation directory" FORCE)
else()
if(IS_DIRECTORY "/usr/local/openmm")
set(OpenMM_ROOT_DIR "/usr/local/openmm" CACHE PATH "OpenMM installation directory" FORCE)
find_library(OpenMM_LIBRARIES
NAMES OpenMM
- PATHS "${OpenMM_ROOT_DIR}/lib")
+ PATHS "${OpenMM_ROOT_DIR}/lib"
+ CACHE STRING "OpenMM libraries")
+
+find_library(OpenMM_LIBRARIES_D
+ NAMES OpenMM_d
+ PATHS "${OpenMM_ROOT_DIR}/lib"
+ CACHE STRING "OpenMM debug libraries")
+
+if(OpenMM_LIBRARIES_D AND NOT OpenMM_LIBRARIES)
+ set(OpenMM_LIBRARIES ${OpenMM_LIBRARIES_D}
+ CACHE STRING "OpenMM libraries" FORCE)
+ message(WARNING " Only found debug versions of the OpenMM libraries!")
+endif()
get_filename_component(OpenMM_LIBRARY_DIR
${OpenMM_LIBRARIES}
if (IS_DIRECTORY "${OpenMM_LIBRARY_DIR}/..") # just double-checking
get_filename_component(OpenMM_ROOT_DIR
"${OpenMM_LIBRARY_DIR}/.."
- ABSOLUTE
- CACHE PATH "OpenMM installation directory")
- endif()
+ ABSOLUTE)
+ endif()
endif()
if(NOT IS_DIRECTORY ${OpenMM_ROOT_DIR})
"variable to the path where your OpenMM installation is located or install it to the default location (/usr/local/openmm)!")
endif()
-if(NOT OpenMM_LIBRARY_DIR)
+if(NOT IS_DIRECTORY ${OpenMM_LIBRARY_DIR})
message(FATAL_ERROR "Can't find OpenMM libraries. Check your OpenMM installation!")
endif()
if(IS_DIRECTORY "${OpenMM_LIBRARY_DIR}/plugins")
get_filename_component(OpenMM_PLUGIN_DIR
"${OpenMM_LIBRARY_DIR}/plugins"
- ABSOLUTE
- CACHE PATH "OpenMM plugins directory")
+ ABSOLUTE)
+ set(OpenMM_PLUGIN_DIR ${OpenMM_PLUGIN_DIR} CACHE PATH "OpenMM plugins directory")
else()
message(WARNING "Could not detect the OpenMM plugin directory at the default location (${OpenMM_LIBRARY_DIR}/plugins)."
"Check you OpenMM installation or manually set the OPENMM_PLUGIN_DIR environment variable!")
message(FATAL_ERROR "Can't find OpenMM includes. Check your OpenMM installation!")
endif()
-include (FindPackageHandleStandardArgs)
+set(OpenMM_ROOT_DIR ${OpenMM_ROOT_DIR} CACHE PATH "OpenMM installation directory")
+
+include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenMM DEFAULT_MSG
OpenMM_ROOT_DIR
OpenMM_LIBRARIES
OpenMM_LIBRARY_DIR
- OpenMM_INCLUDE_DIR
- OpenMM_PLUGIN_DIR)
+ OpenMM_INCLUDE_DIR)
+
+mark_as_advanced(OpenMM_INCLUDE_DIR
+ OpenMM_LIBRARIES
+ OpenMM_LIBRARIES_D
+ OpenMM_LIBRARY_DIR)
#option(THREAD_PTHREADS "Use posix threads" ON)
+MACRO(TEST_TMPI_ATOMICS VARIABLE)
+ if (NOT DEFINED TMPI_ATOMICS)
+ try_compile(TEST_ATOMICS "${CMAKE_BINARY_DIR}"
+ "${CMAKE_SOURCE_DIR}/cmake/TestAtomics.c"
+ COMPILE_DEFINITIONS "-I${CMAKE_SOURCE_DIR}/include" )
+
+ if (TEST_ATOMICS)
+ message(STATUS "Atomics found")
+ set(${VARIABLE} CACHE INTERNAL 1)
+ else (TEST_ATOMICS)
+ message(WARNING "Atomics not found for this compiler+cpu combination. Thread support will be unbearably slow: disable threads.
+ Atomics should work on all but the most obscure CPU+compiler combinations; if your system is not obscure -- like, for example, x86 with gcc -- please contact the developers.
+ ")
+ set(${VARIABLE} CACHE INTERNAL 0)
+ endif(TEST_ATOMICS)
+ endif(NOT DEFINED TMPI_ATOMICS)
+ENDMACRO(TEST_TMPI_ATOMICS VARIABLE)
+
+
include(FindThreads)
if (CMAKE_USE_PTHREADS_INIT)
check_include_files(pthread.h HAVE_PTHREAD_H)
#check_include_files(windows.h HAVE_WINDOWS_H)
#check_function_exists(GetSystemInfo HAVE_SYSTEM_INFO)
-try_compile(TEST_ATOMICS "${CMAKE_BINARY_DIR}"
- "${CMAKE_SOURCE_DIR}/cmake/TestAtomics.c"
- COMPILE_DEFINITIONS "-I${CMAKE_SOURCE_DIR}/include" )
-
-if (TEST_ATOMICS)
- message(STATUS "Atomics found")
- set(TMPI_ATOMICS 1)
-else (TEST_ATOMICS)
- message(WARNING "Atomics not found for this compiler+cpu combination. Thread support will be unbearably slow: disable threads.
-Atomics should work on all but the most obscure CPU+compiler combinations; if your system is not obscure -- like, for example, x86 with gcc -- please contact the developers.
-")
- set(TMPI_ATOMICS 0)
-endif(TEST_ATOMICS)
-
+test_tmpi_atomics(TMPI_ATOMICS)
+
+# Test C flags FLAGS, and set VARIABLE to true if the work. Also add the
+# flags to CFLAGSVAR.
+MACRO(GMX_TEST_CFLAG VARIABLE FLAGS CFLAGSVAR)
+ IF(NOT DEFINED ${VARIABLE})
+ CHECK_C_COMPILER_FLAG("${FLAGS}" ${VARIABLE})
+ IF (${VARIABLE})
+ SET (${CFLAGSVAR} "${FLAGS} ${${CFLAGSVAR}}")
+ ENDIF (${VARIABLE})
+ ENDIF(NOT DEFINED ${VARIABLE})
+ENDMACRO(GMX_TEST_CFLAG VARIABLE FLAGS CFLAGSVAR)
+
+# Test C++ flags FLAGS, and set VARIABLE to true if the work. Also add the
+# flags to CXXFLAGSVAR.
+MACRO(GMX_TEST_CXXFLAG VARIABLE FLAGS CXXFLAGSVAR)
+ IF(NOT DEFINED ${VARIABLE})
+ CHECK_CXX_COMPILER_FLAG("${FLAGS}" ${VARIABLE})
+ IF (${VARIABLE})
+ SET (${CXXFLAGSVAR} "${FLAGS} ${${CXXFLAGSVAR}}")
+ ENDIF (${VARIABLE})
+ ENDIF(NOT DEFINED ${VARIABLE})
+ENDMACRO(GMX_TEST_CXXFLAG VARIABLE FLAGS CXXFLAGSVAR)
+
+
+# This is the actual exported function to be called
MACRO(gmx_c_flags)
-include(CheckCCompilerFlag)
+ include(CheckCCompilerFlag)
+ include(CheckCXXCompilerFlag)
-if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
- CHECK_C_COMPILER_FLAG( "-O3" XFLAGS_O3)
- IF (XFLAGS_O3)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
- ENDIF(XFLAGS_O3)
+ # gcc
+ if(CMAKE_COMPILER_IS_GNUCC)
+ GMX_TEST_CFLAG(CFLAGS_WARN "-Wall -Wno-unused" GMXC_CFLAGS)
+ # new in gcc 4.5
+ GMX_TEST_CFLAG(CFLAGS_EXCESS_PREC "-fexcess-precision=fast" GMXC_CFLAGS)
+ GMX_TEST_CFLAG(CFLAGS_COPT "-fomit-frame-pointer -finline-functions -funroll-all-loops"
+ GMXC_CFLAGS_RELEASE)
+ GMX_TEST_CFLAG(CFLAGS_NOINLINE "-fno-inline" GMXC_CFLAGS_DEBUG)
+ endif()
+ # g++
+ if(CMAKE_COMPILER_IS_GNUCXX)
+ GMX_TEST_CXXFLAG(CXXFLAGS_WARN "-Wall -Wno-unused" GMXC_CXXFLAGS)
+ # new in gcc 4.5
+ GMX_TEST_CXXFLAG(CXXFLAGS_EXCESS_PREC "-fexcess-precision=fast"
+ GMXC_CXXFLAGS)
+ GMX_TEST_CXXFLAG(CXXFLAGS_COPT "-fomit-frame-pointer -finline-functions -funroll-all-loops"
+ GMXC_CXXFLAGS_RELEASE)
+ GMX_TEST_CXXFLAG(CXXFLAGS_NOINLINE "-fno-inline" GMXC_CXXFLAGS_DEBUG)
+ endif()
- CHECK_C_COMPILER_FLAG( "-Wall -Wno-unused" XFLAGS_WARN)
- IF (XFLAGS_WARN)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-unused")
- ENDIF(XFLAGS_WARN)
- CHECK_C_COMPILER_FLAG( "-std=gnu99" XFLAGS_GNU99)
- IF (XFLAGS_GNU99)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
- ENDIF(XFLAGS_GNU99)
+ # icc
+ if (CMAKE_C_COMPILER_ID MATCHES "Intel")
+ if (NOT WIN32)
+ GMX_TEST_CFLAG(CFLAGS_OPT "-ip -w -funroll-all-loops -std=gnu99"
+ GMXC_CFLAGS)
+ GMX_TEST_CFLAG(CFLAGS_SSE2 "-msse2" GMXC_CFLAGS)
+ GMX_TEST_CFLAG(CFLAGS_X86 "-mtune=core2" GMXC_CFLAGS_RELEASE)
+ GMX_TEST_CFLAG(CFLAGS_IA64 "-mtune=itanium2" GMXC_CFLAGS_RELEASE)
+ else()
+ GMX_TEST_CFLAG(CFLAGS_SSE2 "/arch:SSE2" GMXC_CFLAGS)
+ GMX_TEST_CFLAG(CFLAGS_X86 "/Qip" GMXC_CFLAGS_RELEASE)
+ endif()
+ endif()
- CHECK_C_COMPILER_FLAG( "-march=native" XFLAGS_MARCH)
- IF (XFLAGS_MARCH)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
- ENDIF(XFLAGS_MARCH)
-endif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+ if (CMAKE_CXX_COMPILER_ID MATCHES "Intel")
+ if (NOT WIN32)
+ GMX_TEST_CXXFLAG(CXXFLAGS_OPT
+ "-ip -w -funroll-all-loops -std=gnu99"
+ GMXC_CXXFLAGS)
+ GMX_TEST_CXXFLAG(CXXFLAGS_SSE2 "-msse2" GMXC_CXXFLAGS)
+ GMX_TEST_CXXFLAG(CXXFLAGS_X86 "-mtune=core2" GMXC_CXXFLAGS_RELEASE)
+ GMX_TEST_CXXFLAG(CXXFLAGS_IA64 "-mtune=itanium2"
+ GMXC_CXXFLAGS_RELEASE)
+ else()
+ GMX_TEST_CXXFLAG(CXXFLAGS_SSE2 "/arch:SSE2" GMXC_CXXFLAGS)
+ GMX_TEST_CXXFLAG(CXXFLAGS_X86 "/Qip" GMXC_CXXFLAGS_RELEASE)
+ endif()
+ endif()
-MARK_AS_ADVANCED(XFLAGS_O3 XFLAGS_WARN XFLAGS_GNU99 XFLAGS_MARCH)
+ # pgi
+ if (CMAKE_C_COMPILER_ID MATCHES "PGI")
+ GMX_TEST_CFLAG(CFLAGS_OPT "-fastsse" GMXC_CFLAGS_RELEASE)
+ endif()
+ if (CMAKE_CXX_COMPILER_ID MATCHES "PGI")
+ GMX_TEST_CXXFLAG(CXXFLAGS_OPT "-fastsse" GMXC_CXXFLAGS_RELEASE)
+ endif()
+ # Pathscale
+ if (CMAKE_C_COMPILER_ID MATCHES "PathScale")
+ GMX_TEST_CFLAG(CFLAGS_OPT "-OPT:Ofast -fno-math-errno -ffast-math"
+ GMXC_CFLAGS_RELEASE)
+ GMX_TEST_CFLAG(CFLAGS_LANG "-std=gnu99" GMXC_CFLAGS)
+ endif()
+ if (CMAKE_CXX_COMPILER_ID MATCHES "PathScale")
+ GMX_TEST_CXXFLAG(CXXFLAGS_OPT "-OPT:Ofast -fno-math-errno -ffast-math"
+ GMXC_CXXFLAGS_RELEASE)
+ endif()
+
+ # xlc
+ if (CMAKE_C_COMPILER_ID MATCHES "XL")
+ GMX_TEST_CFLAG(CFLAGS_OPT "-qarch=auto -qtune=auto" GMXC_CFLAGS)
+ GMX_TEST_CFLAG(CFLAGS_LANG "-qlanglvl=extc99" GMXC_CFLAGS)
+ endif()
+ if (CMAKE_CXX_COMPILER_ID MATCHES "XL")
+ GMX_TEST_CXXFLAG(CFLAGS_OPT "-qarch=auto -qtune=auto" GMXC_CXXFLAGS)
+ endif()
+
+
+ # now actually set the flags:
+ if (NOT DEFINED GMXCFLAGS_SET)
+ set(GMXCFLAGS_SET true CACHE INTERNAL "Whether to reset the C flags"
+ FORCE)
+ # C
+ set(CMAKE_C_FLAGS "${GMXC_CFLAGS} ${CMAKE_C_FLAGS}"
+ CACHE STRING "Flags used by the compiler during all build types."
+ FORCE)
+ set(CMAKE_C_FLAGS_RELEASE "${GMXC_CFLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}"
+ CACHE STRING "Flags used by the compiler during release builds."
+ FORCE)
+ set(CMAKE_C_FLAGS_DEBUG "${GMXC_CFLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}"
+ CACHE STRING "Flags used by the compiler during debug builds."
+ FORCE)
+ # C++
+ set(CMAKE_CXX_FLAGS "${GMXC_CXXFLAGS} ${CMAKE_CXX_FLAGS}"
+ CACHE STRING "Flags used by the compiler during all build types."
+ FORCE)
+ set(CMAKE_CXX_FLAGS_RELEASE
+ "${GMXC_CXXFLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}"
+ CACHE STRING "Flags used by the compiler during release builds."
+ FORCE)
+ set(CMAKE_CXX_FLAGS_DEBUG
+ "${GMXC_CXXFLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}"
+ CACHE STRING "Flags used by the compiler during debug builds."
+ FORCE)
+ endif()
ENDMACRO(gmx_c_flags)
+
--- /dev/null
+# Check GCC version and if any of the 4.1.x family compiler suites is found
+# quit the build system generating process.
+#
+# The GCC 4.1.x compilers contain an optimization related bug which might
+# results in code that exhibits incorrect behaviour and often leads to
+# exploding systems or crashes.
+#
+# For further details see e.g.
+# https://bugs.launchpad.net/ubuntu/+source/gcc-4.1/+bug/158799
+#
+# Szilard Pall (pszilard@cbr.su.se)
+#
+
+if(NOT GMX_DISABLE_GCC41_CHECK)
+
+if(CMAKE_COMPILER_IS_GNUCC)
+ # if we have -dumpversion flag use that, otherwise try the --version
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ RESULT_VARIABLE _gcc_dumpversion_res
+ OUTPUT_VARIABLE _gcc_dumpversion_out
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ # if gcc returned with error the -dumpversion is not available
+ if(${_gcc_dumpversion_res} EQUAL 0)
+ if(${_gcc_dumpversion_out} MATCHES ".*4\\.1\\.[0-9]+.*")
+ message(FATAL_ERROR " The GCC compiler in use seems to belong to the 4.1.x
+ family (detected version: ${_gcc_dumpversion_out}). These compilers
+ contain an optimization related bug which might results in code that
+ exhibits incorrect behaviour and often leads to exploding systems or
+ crashes. To disable this check set GMX_DISABLE_GCC41_CHECK=YES.")
+ endif()
+ else()
+ message(WARNING " The GCC compiler in use does not support the -dumpversion flag.
+ Will attempt parsing the version from the \"gcc --version\" output.")
+ execute_process(COMMAND ${CMAKE_C_COMPILER} --version
+ OUTPUT_VARIABLE _gcc_version_out
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if("${_gcc_version_out}" MATCHES ".*4\\.1\\.[0-9]+.*")
+ message(FATAL_ERROR " The GCC compiler in use seems to belong to the 4.1.x
+ family. These compiler compilers contain an optimization related bug
+ which might results in code that exhibits incorrect behaviour and
+ often leads to exploding systems or crashes. To disable this check set
+ GMX_DISABLE_GCC41_CHECK=YES.")
+ endif()
+ endif()
+endif()
+
+endif()
# if git executable xists and it's compatible version
# build the development version string
-if(EXISTS ${Git_EXECUTABLE} AND NOT Git_VERSION VERSION_LESS "1.5.1")
+# this should at some point become VERSION_LESS
+if(EXISTS ${Git_EXECUTABLE} AND NOT Git_VERSION STRLESS "1.5.1")
# refresh git index
execute_process(COMMAND ${Git_EXECUTABLE} update-index -q --refresh
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
# if git is older then 1.5.3 we need to extract the RFC2822 style date
# and massage it, otherwise the ISO 8601 format is more trusworthy
- if (NOT Git_VERSION STREQUAL "" AND Git_VERSION VERSION_LESS "1.5.3")
+ # this should at some point become VERSION_LESS
+ if (NOT Git_VERSION STREQUAL "" AND Git_VERSION STRLESS "1.5.3")
execute_process(COMMAND ${Git_EXECUTABLE} rev-list -n1 "--pretty=format:%cD" HEAD
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE HEAD_DATE
ERROR_VARIABLE EXEC_ERR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
- string(REGEX REPLACE ".*, ([0-9]+) ([A-Z][a-z]+) ([0-9]+).*" "\\3\\2\\1"
+ # date format: day, D Mmm YYYY -> YYYY-MM-DD
+ # if the day is single sigit need to insert a "0"
+ string(REGEX REPLACE ".*(, )([0-9] )(.*)" "\\10\\2\\3"
+ HEAD_DATE ${HEAD_DATE})
+ string(REGEX REPLACE ".*, ([0-9][0-9]) ([A-Z][a-z]+) ([0-9]+).*" "\\3\\2\\1"
HEAD_DATE ${HEAD_DATE})
string(TOUPPER ${HEAD_DATE} HEAD_DATE)
string(REGEX REPLACE "JAN" "01" HEAD_DATE ${HEAD_DATE})
set(${VARIABLE} 0 CACHE INTERNAL "Result of test for GCC x86 inline asm" FORCE)
endif(${VARIABLE})
+
ENDIF(NOT DEFINED ${VARIABLE})
ENDMACRO(GMX_TEST_INLINE_ASM_GCC_X86 VARIABLE)
AM_CONFIG_HEADER(src/config.h)
dnl This is the version info according to the libtool versioning system.
dnl It does *not* correspond to the release number.
-SHARED_VERSION_INFO="5:0:0"
+SHARED_VERSION_INFO="6:0:0"
AC_SUBST(SHARED_VERSION_INFO)
AC_DISABLE_SHARED
# Simple options and makefile variables
#######################################################################
-# This is currently not defined by CMake, because it's tricky to generate
-# version.h portably (the autoconf rules for it are in src/gmxlib/Makefile.am).
-AC_DEFINE(USE_VERSION_H,,[Use the version string from generated version.h])
-
### Single/Double
AC_ARG_ENABLE(float,
[AC_HELP_STRING([--disable-float],
esac
fi
+###################################
+## Detect buggy version of gcc
+###################################
+AC_ARG_ENABLE(gcc41_check,
+ [AC_HELP_STRING([--disable-gcc41-check],
+ [Disable the check for buggy gcc 4.1])],,enable_gcc41_check=yes)
+
### ia64 assembly code
AC_ARG_ENABLE(ia64_asm,
- [AC_HELP_STRING([--disable-ia64-asm],
- [Don't build assembly loops on ia64])],,enable_ia64_asm=yes)
+ [AC_HELP_STRING([--enable-ia64-asm],
+ [Build assembly loops on ia64])],,enable_ia64_asm=no)
case "${host_cpu}" in
ia64) ;;
*) enable_ia64_asm=no ;;
AC_DEFINE(GMX_QMMM_MOPAC,,[Use (modified) Mopac 7 for QM-MM calculations])
fi
+
+AC_ARG_WITH(qmmm_orca,
+ [AC_HELP_STRING([--without-qmmm-mopac],
+ [Use ORCA for QM-MM])],,with_qmmm_orca=no)
+if test "$with_qmmm_orca"="yes"; then
+ AC_DEFINE(GMX_QMMM_ORCA,,[Use ORCA for QM-MM calculations])
+fi
+
+
AC_ARG_WITH(dlopen,
[AC_HELP_STRING([--without-dlopen],
[do not compile with dlopen, needed to read VMD]
-
-
############################################################
# Add some debug info: Who is building, and on what machine?
############################################################
AC_DEFINE_UNQUOTED([BUILD_MACHINE],["`uname -srm`"],[Hardware and OS version for build host])
+############################################################
+# Checks for requirements for version information generation
+############################################################
+generate_version=no
+if test -d $srcdir/.git ; then
+ AC_CHECK_PROG(have_git, git, yes, no)
+ if test "$have_git" = "yes" ; then
+ AC_MSG_CHECKING(for git >= 1.5.1)
+ if test "`git --version`" \< "git version 1.5.1" ; then
+ AC_MSG_RESULT(no)
+ else
+ AC_MSG_RESULT(yes)
+ generate_version=yes
+ AC_DEFINE(USE_VERSION_H,,[Use generated version info])
+ fi
+ fi
+ if test "$generate_version" = "no" ; then
+ AC_MSG_WARN([No compatible git version found, won't be able to generate proper development version information.])
+ fi
+fi
+AM_CONDITIONAL([USE_VERSION_H],[test "$generate_version" = "yes"])
+
############################################################
# Checks for programs
if test -z "$CC_FOR_BUILD"; then
CC_FOR_BUILD=$CC
fi
+
+if test "$enable_gcc41_check" = "yes"; then
+ if $CC --version 2>&1 | grep 'gcc.* 4\.1' > /dev/null 2>&1; then
+ AC_MSG_ERROR([Uh-oh. Your compilers appears to be GCC version 4.1, which unfortunately produces]
+[buggy code at high optimimzation levels. It would be a good idea to update or]
+[use a different compiler. If you are ABSOLUTELY sure what you are doing, you]
+[can override this check with --disable-gcc41-check.])
+ fi
+fi
+
+
+
AC_SUBST(CC_FOR_BUILD)
if test "$enable_fortran" = "yes"; then
AC_CHECK_HEADERS(sys/types.h)
AC_CHECK_HEADERS(sys/time.h)
AC_CHECK_HEADERS(dirent.h)
+AC_CHECK_HEADERS(copyfile.h)
AC_CHECK_HEADERS(regex.h,,[AC_MSG_WARN(
[No regex.h found.
Regular expression matching in selections will be disabled.
AC_CHECK_FUNCS(strcasecmp)
AC_CHECK_FUNCS(strdup)
AC_CHECK_FUNCS(gettimeofday)
+AC_CHECK_FUNCS(cbrt)
AC_CHECK_FUNCS(isnan)
AC_CHECK_FUNCS(_isnan)
AC_CHECK_FUNCS(isfinite)
AC_CHECK_FUNCS(_isfinite)
+AC_CHECK_FUNCS(fsync)
+AC_CHECK_FUNCS(fileno)
+AC_CHECK_FUNCS(copyfile)
# check for bool (must come late, since CFLAGS/includes might affect it)
AC_CHECK_TYPES([bool])
+AC_SEARCH_LIBS(posix_memalign, c, AC_DEFINE(HAVE_POSIX_MEMALIGN, 1, Define to 1 if you have the posix_memalign function))
+AC_SEARCH_LIBS(memalign, c, AC_DEFINE(HAVE_MEMALIGN, 1, Define to 1 if you have the memalign function))
+AC_CHECK_FUNCS(_aligned_malloc)
+#AC_SEARCH_LIBS(_aligned_malloc, c, AC_DEFINE(HAVE__ALIGNED_MALLOC, 1, Define to 1 if you have the _aligned_malloc function))
+
AC_CHECK_HEADERS([libxml/parser.h],AC_CHECK_LIB(xml2,main))
if test "$ac_cv_lib_xml2_main" = "yes"; then
INCLUDES="$INCLUDES -I/usr/include/libxml2"
+ PKG_XML2="libxml-2.0"
+ AC_SUBST(PKG_XML2)
+ if test "$enable_all_static" = "yes"; then
+ LDFLAGS_RET=$LDFLAGS
+ LDFLAGS="-static $LDFLAGS"
+ LIBS_RET="$LIBS"
+ LIBS="$LIBS -lz"
+ AC_MSG_CHECKING(for broken libxml2)
+ AC_TRY_RUN([
+#include <libxml/parser.h>
+main() {
+ xmlInitParser();
+ return 0;
+}],
+ AC_MSG_RESULT([no]),[AC_MSG_RESULT([yes])
+ AC_MSG_ERROR([Your libxml2 is broken for static linking, recompile it without threads or build gromacs without libxml])],[-lz])
+ LDFLAGS=$LDFLAGS_RET
+ LIBS="$LIBS_RET"
+ fi
fi
- PKG_XML2="libxml-2.0"
- AC_SUBST(PKG_XML2)
# restore CPPFLAGS
CPPFLAGS="$ac_save_CPPFLAGS"
fi
*/
extern bool zoom_3d(t_3dview *view,real fac);
-/* Zoom in or out with factor fac, returns TRUE when zoom succesful,
+/* Zoom in or out with factor fac, returns TRUE when zoom successful,
* FALSE otherwise.
*/
edsam.h \
enxio.h \
ffscanf.h \
-fftgrid.h \
filenm.h \
force.h \
futil.h \
gmx_fft.h \
gmx_ga2la.h \
gmx_lapack.h \
+gmx_matrix.h \
gmx_parallel_3dfft.h \
gmx_random.h \
+gmx_sort.h \
gmx_sse2_single.h \
gmx_statistics.h \
gmx_system_xdr.h \
selmethod.h \
selparam.h \
selvalue.h \
+sfactor.h \
shellfc.h \
shift.h \
smalloc.h \
sparsematrix.h \
split.h \
splitter.h \
-statusio.h \
statutil.h \
strdb.h \
string2.h \
extern real calc_grid(FILE *fp,
matrix box,real gr_sp,
- int *nx,int *ny,int *nz,int nnodes);
+ int *nx,int *ny,int *nz);
/* Sets the number of grid points for each zero n* to the first reasonable
* number which gives a spacing equal to or smaller than gr_sp.
- * nx and ny should be divisible by nnodes, an error is generated when this
- * can not be achieved by calc_grid.
* Returns the maximum grid spacing.
*/
extern "C" {
#endif
-/* Write a checkpoint to fn */
-extern void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
+/* the name of the environment variable to disable fsync failure checks with */
+#define GMX_IGNORE_FSYNC_FAILURE_ENV "GMX_IGNORE_FSYNC_FAILURE"
+
+/* Write a checkpoint to <fn>.cpt
+ * Appends the _step<step>.cpt with bNumberAndKeep,
+ * otherwise moves the previous <fn>.cpt to <fn>_prev.cpt
+ */
+extern void write_checkpoint(const char *fn,bool bNumberAndKeep,
+ FILE *fplog,t_commrec *cr,
int eIntegrator,int simulation_part,
gmx_large_int_t step,double t,
t_state *state);
gmx_large_int_t *step,double *t,t_state *state);
/* Read everything that can be stored in t_trxframe from a checkpoint file */
-extern void read_checkpoint_trxframe(int fp,t_trxframe *fr);
+extern void read_checkpoint_trxframe(t_fileio *fp,t_trxframe *fr);
/* Print the complete contents of checkpoint file fn to out */
extern void list_checkpoint(const char *fn,FILE *out);
#endif
#include <stdio.h>
-#include <types/simple.h>
+#include "types/simple.h"
#ifdef __cplusplus
extern "C" {
gmx_mtop_t *mtop,t_inputrec *ir,
matrix box,rvec *x,
gmx_ddbox_t *ddbox,
- int *npme_major);
+ int *npme_x, int *npme_y);
extern void dd_init_bondeds(FILE *fplog,
gmx_domdec_t *dd,gmx_mtop_t *mtop,
/* In domdec_setup.c */
extern real comm_box_frac(ivec dd_nc,real cutoff,gmx_ddbox_t *ddbox);
-/* Returns the volume fraction of the system communicated by each node */
+/* Returns the volume fraction of the system that is communicated */
extern real dd_choose_grid(FILE *fplog,
t_commrec *cr,gmx_domdec_t *dd,t_inputrec *ir,
extern void
dd_gather(gmx_domdec_t *dd,int nbytes,void *src,void *dest);
+/* If rcount==0, rbuf is allowed to be NULL */
extern void
dd_scatterv(gmx_domdec_t *dd,
- int *scounts,int *disps,void *sbuf,
- int rcount,void *rbuf);
+ int *scounts,int *disps,void *sbuf,
+ int rcount,void *rbuf);
+/* If scount==0, sbuf is allowed to be NULL */
extern void
dd_gatherv(gmx_domdec_t *dd,
- int scount,void *sbuf,
- int *rcounts,int *disps,void *rbuf);
+ int scount,void *sbuf,
+ int *rcounts,int *disps,void *rbuf);
#ifdef __cplusplus
}
extern "C" {
#endif
-extern void do_edsam(t_inputrec *ir,int step,t_mdatoms *md,
+extern void do_edsam(t_inputrec *ir,gmx_large_int_t step,t_mdatoms *md,
t_commrec *cr,rvec xs[],rvec v[],matrix box,gmx_edsam_t ed);
/* Essential dynamics constraints, called from constrain() */
-extern gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],t_commrec *cr);
+extern gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],unsigned long Flags,t_commrec *cr);
/* Sets the ED input/output filenames, opens output (.edo) file */
extern void init_edsam(gmx_mtop_t *mtop,t_inputrec *ir,t_commrec *cr,
#include "sysstuff.h"
#include "typedefs.h"
#include "pbc.h"
+#include "gmxfio.h"
#ifdef __cplusplus
extern "C" {
typedef struct {
double t; /* Timestamp of this frame */
- gmx_large_int_t step; /* MD step */
- gmx_large_int_t nsteps; /* The number of steps between frames */
- gmx_large_int_t nsum; /* The number of terms for the sums in ener */
+ gmx_large_int_t step; /* MD step */
+ gmx_large_int_t nsteps; /* The number of steps between frames */
+ int nsum; /* The number of terms for the sums in ener */
int nre; /* Number of energies */
int ndisre; /* Number of distance restraints */
int nblock; /* Number of following energy blocks */
extern ener_file_t open_enx(const char *fn,const char *mode);
- extern int enx_file_pointer(const ener_file_t ef);
+ extern t_fileio *enx_file_pointer(const ener_file_t ef);
extern void close_enx(ener_file_t ef);
+++ /dev/null
-/*
- *
- * This source code is part of
- *
- * G R O M A C S
- *
- * GROningen MAchine for Chemical Simulations
- *
- * VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- *
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _fftgrid_h
-#define _fftgrid_h
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include "typedefs.h"
-#include "gmxcomplex.h"
-#include "network.h"
-#include "gmx_fft.h"
-
-#ifdef GMX_MPI
-#include "gmx_parallel_3dfft.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Use FFTW */
-
-#define INDEX(i,j,k) ((i)*la12+(j)*la2+(k))
-
-typedef struct {
- int local_nx,local_x_start,local_ny_after_transpose;
- int local_y_start_after_transpose;
-} t_parfft;
-
-typedef struct {
- real * ptr;
- bool bParallel;
- real * workspace;
- int nx,ny,nz,la2r,la2c,la12r,la12c;
- int nptr,nxyz;
- gmx_fft_t fft_setup;
-#ifdef GMX_MPI
- gmx_parallel_3dfft_t mpi_fft_setup;
- t_parfft pfft;
-#endif
-} t_fftgrid;
-
-extern t_fftgrid *mk_fftgrid(int nx,
- int ny,
- int nz,
- int *node2slab,
- int *slab2grid_x,
- t_commrec * cr,
- bool bReproducible);
-
-/* Create an FFT grid (1 Dimensional), to be indexed by the INDEX macro
- * Setup FFT plans and extract local sizes for the grid.
- * If the file pointer is given, information is printed to it.
- * If cr is non-NULL and cr->nnodes>1, a parallel grid and FFT will be created.
- * The node2slab array translates to node ids to slab indices,
- * when NULL the slab ids are assumed to be identical to the node ids.
- * The slab2grid_x array determines which grid x-indices beling to which slab
- * (array size nnodes+1), when NULL this is determined automatically.
- * Set bReproducible to avoid FFTW timing and other optimizations that
- * could affect reproducibility of simulations.
- */
-
-extern void pr_fftgrid(FILE *fp,char *title,t_fftgrid *grid);
-/* Dump a grid to a file */
-
-extern void done_fftgrid(t_fftgrid *grid);
-/* And throw it away again */
-
-extern void gmxfft3D(t_fftgrid *grid,enum gmx_fft_direction dir,t_commrec *cr);
-/* Do the FFT, direction may be either
- * FFTW_FORWARD (sign -1) for real -> complex transform
- * FFTW_BACKWARD (sign 1) for complex -> real transform
- */
-
-extern void clear_fftgrid(t_fftgrid *grid);
-/* Set it to zero */
-
-extern void unpack_fftgrid(t_fftgrid *grid,int *nx,int *ny,int *nz,
- int *nx2,int *ny2,int *nz2,
- int *la2, int *la12,bool bReal, real **ptr);
-
-/* Get the values for the constants into local copies */
-
-
-
-
-/************************************************************************
- *
- * For backward compatibility (for testing the ewald code vs. PPPM etc)
- * some old grid routines are retained here.
- *
- ************************************************************************/
-
-extern real ***mk_rgrid(int nx,int ny,int nz);
-
-extern void free_rgrid(real ***grid,int nx,int ny);
-
-extern real print_rgrid(FILE *fp,char *title,int nx,int ny,int nz,
- real ***grid);
-
-extern void print_rgrid_pdb(char *fn,int nx,int ny,int nz,real ***grid);
-
-extern t_complex ***mk_cgrid(int nx,int ny,int nz);
-
-extern void free_cgrid(t_complex ***grid,int nx,int ny);
-
-extern t_complex print_cgrid(FILE *fp,char *title,int nx,int ny,int nz,
- t_complex ***grid);
-
-extern void clear_cgrid(int nx,int ny,int nz,t_complex ***grid);
-
-extern void clear_rgrid(int nx,int ny,int nz,real ***grid);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-
-
-
-
/* duplicate the filename list (to make a private copy for each thread,
for example) */
t_filenm *dup_tfn(int nf, const t_filenm tfn[]);
+
+/* Free memory allocated for file names by parse_file_args(). */
+void done_filenms(int nf, t_filenm fnm[]);
#ifdef __cplusplus
}
int natoms_force,int natoms_f_novirsum);
/* Set the number of cg's and atoms for the force calculation */
+extern bool can_use_allvsall(const t_inputrec *ir, const gmx_mtop_t *mtop,
+ bool bPrintNote,t_commrec *cr,FILE *fp);
+/* Returns if we can use all-vs-all loops.
+ * If bPrintNote==TRUE, prints a note, if necessary, to stderr
+ * and fp (if !=NULL) on the master node.
+ */
+
extern void init_forcerec(FILE *fplog,
const output_env_t oenv,
t_forcerec *fr,
extern bool is_pipe(FILE *fp);
/* Check whether the file (opened by ffopen) is a pipe */
-extern char *backup_fn(const char *file);
-/* Return a backup name for file (name with # before and after) */
-
/* Make a backup of file if necessary.
Return false if there was a problem.
*/
extern bool make_backup(const char * file);
extern FILE *ffopen(const char *file, const char *mode);
-/* Return a valid file pointer when succesfull, exits otherwise
+/* Return a valid file pointer when successful, exits otherwise
* If the file is in compressed format, open a pipe which uncompresses
* the file! Therefore, files must be closed with ffclose (see below)
*/
*/
extern void gmx_tmpnam(char *buf);
-int
-gmx_truncatefile(char *path, off_t length);
+/* truncte the file to the specified length */
+int gmx_truncatefile(char *path, off_t length);
+
+/* rename/move the file (atomically, if the OS makes that available) oldname
+ to newname */
+int gmx_file_rename(const char *oldname, const char *newname);
+
+/* copy the file (data only) oldname to newname. if copy_if_empty==FALSE,
+ the file won't be copied if it's empty.*/
+int gmx_file_copy(const char *oldname, const char *newname, bool copy_if_empty);
#ifdef __cplusplus
}
int
gmx_xpm2ps(int argc,char *argv[]);
+int
+gmx_membed(int argc,char *argv[]);
+
#ifdef __cplusplus
}
#endif
extern void
gmx_fatal_collective(int f_errno,const char *file,int line,
- bool bMaster,
+ t_commrec *cr,gmx_domdec_t *dd,
const char *fmt,...);
-/* As gmx_fatal, but only process with bMaster=TRUE prints the error message.
+/* As gmx_fatal, but only the master process prints the error message.
+ * This should only be called one of the following two situations:
+ * 1) On all nodes in cr->mpi_comm_mysim, with cr!=NULL,dd==NULL.
+ * 2) On all nodes in dd->mpi_comm_all, with cr==NULL,dd!=NULL.
+ * This will call MPI_Finalize instead of MPI_Abort when possible,
* This is useful for handling errors in code that is executed identically
* for all processes.
*/
gmx_fft_flag flags);
+/*! \brief Setup multiple 1-dimensional complex-to-complex transform
+ *
+ * \param fft Pointer to opaque Gromacs FFT datatype
+ * \param nx Length of transform
+ * \param howmany Howmany 1D FFT
+ * \param flags FFT options
+ *
+ * \return status - 0 or a standard error message.
+ *
+ * \note Since some of the libraries (e.g. MKL) store work array data in their
+ * handles this datatype should only be used for one thread at a time,
+ * i.e. you should create one copy per thread when executing in parallel.
+ */
+int
+gmx_fft_init_many_1d (gmx_fft_t * fft,
+ int nx,
+ int howmany,
+ gmx_fft_flag flags);
+
/*! \brief Setup a 1-dimensional real-to-complex transform
*
gmx_fft_flag flags);
+/*! \brief Setup multiple 1-dimensional real-to-complex transform
+ *
+ * \param fft Pointer to opaque Gromacs FFT datatype
+ * \param nx Length of transform in real space
+ * \param howmany Homany 1D FFTs
+ * \param flags FFT options
+ *
+ * \return status - 0 or a standard error message.
+ *
+ * \note Since some of the libraries (e.g. MKL) store work array data in their
+ * handles this datatype should only be used for one thread at a time,
+ * i.e. you should create one copy per thread when executing in parallel.
+ */
+int
+gmx_fft_init_many_1d_real (gmx_fft_t * fft,
+ int nx,
+ int howmany,
+ gmx_fft_flag flags);
+
+
/*! \brief Setup a 2-dimensional complex-to-complex transform
*
* \note Data pointers are declared as void, to avoid casting pointers
* depending on your grid type.
*/
-int
+ int
gmx_fft_1d (gmx_fft_t setup,
enum gmx_fft_direction dir,
void * in_data,
void * out_data);
+/*! \brief Perform many 1-dimensional complex-to-complex transforms
+ *
+ * Performs many instances of a transform previously initiated.
+ *
+ * \param setup Setup returned from gmx_fft_init_1d()
+ * \param dir Forward or Backward
+ * \param in_data Input grid data. This should be allocated with gmx_new()
+ * to make it 16-byte aligned for better performance.
+ * \param out_data Output grid data. This should be allocated with gmx_new()
+ * to make it 16-byte aligned for better performance.
+ * You can provide the same pointer for in_data and out_data
+ * to perform an in-place transform.
+ *
+ * \return 0 on success, or an error code.
+ *
+ * \note Data pointers are declared as void, to avoid casting pointers
+ * depending on your grid type.
+ */
+ int
+gmx_fft_many_1d (gmx_fft_t setup,
+ enum gmx_fft_direction dir,
+ void * in_data,
+ void * out_data);
+
+
/*! \brief Perform a 1-dimensional real-to-complex transform
*
* Performs an instance of a transform previously initiated.
void * in_data,
void * out_data);
+/*! \brief Perform many 1-dimensional real-to-complex transforms
+ *
+ * Performs many instances of a transform previously initiated.
+ *
+ * \param setup Setup returned from gmx_fft_init_1d_real()
+ * \param dir Real-to-complex or complex-to-real
+ * \param in_data Input grid data. This should be allocated with gmx_new()
+ * to make it 16-byte aligned for better performance.
+ * \param out_data Output grid data. This should be allocated with gmx_new()
+ * to make it 16-byte aligned for better performance.
+ * You can provide the same pointer for in_data and out_data
+ * to perform an in-place transform.
+ *
+ * If you are doing an in-place transform, the array must be padded up to
+ * an even integer length so n/2 complex numbers can fit. Out-of-place arrays
+ * should not be padded (although it doesn't matter in 1d).
+ *
+ * \return 0 on success, or an error code.
+ *
+ * \note Data pointers are declared as void, to avoid casting pointers
+ * depending on transform direction.
+ */
+int
+gmx_fft_many_1d_real (gmx_fft_t setup,
+ enum gmx_fft_direction dir,
+ void * in_data,
+ void * out_data);
+
/*! \brief Perform a 2-dimensional complex-to-complex transform
*
void
gmx_fft_destroy (gmx_fft_t setup);
+/*! \brief Release a many FFT setup structure
+ *
+ * Destroy setup and release all allocated memory.
+ *
+ * \param setup Setup returned from gmx_fft_init_1d(), or one
+ * of the other initializers.
+ *
+ */
+void
+gmx_many_fft_destroy (gmx_fft_t setup);
+
/*! \brief Transpose 2d complex matrix, in-place or out-of-place.
*
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ * $Id: gmx_matrix.h,v 1.2 2008/11/26 11:06:21 spoel Exp $
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 4.0.99
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Groningen Machine for Chemical Simulation
+ */
+
+#ifndef _gmx_matrix_h
+#define _gmx_matrix_h
+
+#include <stdio.h>
+
+extern double **alloc_matrix(int n,int m);
+
+extern void free_matrix(double **a,int n);
+
+extern void matrix_multiply(FILE *fp,int n,int m,double **x,double **y,double **z);
+
+/* Return 0 if OK or row number where inversion failed otherwise. */
+extern int matrix_invert(FILE *fp,int n,double **a);
+
+extern double multi_regression(FILE *fp,int ny,double *y,
+ int nx,double **xx,double *a0);
+/* Perform a regression analysis to fit
+ * y' = a0[0] xx[0] + a0[1] xx[1] ... + a0[nx-1] xx[nx-1]
+ * with ny data points in each vector.
+ * The coefficients are returned in vector a0.
+ * The return value of the function is the chi2 value:
+ * sum_{j=0}^{ny-1} (y[j] - y'[j])^2
+ * If fp is not NULL debug information will be written to it.
+ */
+
+#endif
#include <config.h>
#endif
-#ifdef GMX_MPI
#include "types/simple.h"
+#include "types/commrec.h"
#include "gmxcomplex.h"
#include "gmx_fft.h"
-/* We NEED MPI here. */
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
typedef struct gmx_parallel_3dfft *
gmx_parallel_3dfft_t;
*/
int
gmx_parallel_3dfft_init (gmx_parallel_3dfft_t * pfft_setup,
- int ngridx,
- int ngridy,
- int ngridz,
- int *node2slab,
- int *slab2grid_x,
- MPI_Comm comm,
+ ivec ndata,
+ real ** real_data,
+ t_complex ** complex_data,
+ MPI_Comm comm[2],
+ int * slab2index_major,
+ int * slab2index_minor,
bool bReproducible);
-
+
/*! \brief Get direct space grid index limits
- *
- * The z dimension is never distributed. In the direct space, the x dimension
- * is distributed over nodes, and after the real-to-complex FFT we work with
- * a transposed grid where the y dimension is partitioned over nodes.
- *
- * The node2slab array translates to node ids to slab indices,
- * when NULL the slab ids are assumed to be identical to the node ids
- * in the communicator comm.
*/
int
-gmx_parallel_3dfft_limits(gmx_parallel_3dfft_t pfft_setup,
- int * local_x_start,
- int * local_nx,
- int * local_y_start,
- int * local_ny);
+gmx_parallel_3dfft_real_limits(gmx_parallel_3dfft_t pfft_setup,
+ ivec local_ndata,
+ ivec local_offset,
+ ivec local_size);
-int
-gmx_parallel_transpose(t_complex * data,
- t_complex * work,
- int nx,
- int ny,
- int local_x_start,
- int local_nx,
- int local_y_start,
- int local_ny,
- int nelem,
- int nnodes,
- int *node2slab,
- MPI_Comm comm);
-
-
-/*! \brief Perform forward parallel MPI FFT.
- *
- * Direction is either GMX_FFT_REAL_TO_COMPLEX or GMX_FFT_COMPLEX_TO_REAL.
- *
- * If input and output arrays are separate there is no packing to consider.
- * Input is simply nx*ny*nz in real, and output ny*nx*nzc in complex.
- *
- * In they are identical we need to make sure there is room for the complex
- * (length nzc=nz/2+1) in the array, so the _real_ space dimensions is
- * always padded to nzc*2.
- * In this case, the real dimensions are nx*ny*(nzc*2) while the complex
- * dimensions is ny*nx*nzc (of type complex).
- *
- * Note that the X and Y dimensions are transposed in the reciprocal space
- * to avoid extra communication!
- *
- * The node2slab array translates to node ids to slab indices,
- * when NULL the slab ids are assumed to be identical to the node ids
- * in the communicator comm.
+/*! \brief Get reciprocal space grid index limits
*/
int
-gmx_parallel_3dfft(gmx_parallel_3dfft_t pfft_setup,
- enum gmx_fft_direction dir,
- void * in_data,
- void * out_data);
+gmx_parallel_3dfft_complex_limits(gmx_parallel_3dfft_t pfft_setup,
+ ivec complex_order,
+ ivec local_ndata,
+ ivec local_offset,
+ ivec local_size);
+int
+gmx_parallel_3dfft_execute(gmx_parallel_3dfft_t pfft_setup,
+ enum gmx_fft_direction dir,
+ void * in_data,
+ void * out_data);
+
/*! \brief Release all data in parallel fft setup
*
int
gmx_parallel_3dfft_destroy(gmx_parallel_3dfft_t pfft_setup);
-#ifdef __cplusplus
-}
-#endif
-#endif /* GMX_MPI */
+
#endif /* _gmx_parallel_3dfft_h_ */
#include <stdio.h>
-#include <types/simple.h>
+#include "types/simple.h"
#ifdef __cplusplus
extern "C" {
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This file is part of Gromacs Copyright (c) 1991-2010
+ * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org
+ *
+ * And Hey:
+ * Gnomes, ROck Monsters And Chili Sauce
+ */
+#ifndef _GMX_SORT_H_
+#define _GMX_SORT_H_
+
+/** @file gmx_sort.h
+ *
+ * @brief Portable implementation of thread-safe sort routines.
+ *
+ *
+ * This module provides a Gromacs version of the qsort() routine defined.
+ * It is not highly optimized, but it is thread safe, i.e. multiple threads
+ * can simultaneously call gmx_qsort with different data.
+ */
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#if 0
+} /* fixes auto-indentation problems */
+#endif
+
+
+/*
+ * @param base Pointer to first element in list to sort
+ * @param nmemb Number of elements in list
+ * @param size Size in bytes of each element
+ * @param compar Comparison function that takes two pointers to elements
+ * being compared as arguments. The function should return an
+ * integer less than, equal to, or greater than zero if the
+ * first argument is considered to be respectively less than,
+ * equal to, or greater than the second.
+ */
+void
+gmx_qsort(void * base,
+ size_t nmemb,
+ size_t size,
+ int (*compar)(const void *, const void *));
+
+
+#ifdef GMX_THREADS
+/* Some implementations of qsort are not threadsafe.
+ * For instance qsort in glibc contains a bug which makes it non-threadsafe:
+ * http://sources.redhat.com/bugzilla/show_bug.cgi?id=11655
+ */
+#define qsort_threadsafe gmx_qsort
+#else
+/* System qsort might be faster than our own */
+#define qsort_threadsafe qsort
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _GMX_SORT_H_ */
#if (defined (_MSC_VER) || defined(__INTEL_COMPILER))
# define gmx_mm_castsi128_ps(a) _mm_castsi128_ps(a)
# define gmx_mm_castps_si128(a) _mm_castps_si128(a)
+# define gmx_mm_castps_ps128(a) (a)
#elif defined(__GNUC__)
# define gmx_mm_castsi128_ps(a) ((__m128)(a))
# define gmx_mm_castps_si128(a) ((__m128i)(a))
+# define gmx_mm_castps_ps128(a) ((__m128)(a))
#else
static __m128 gmx_mm_castsi128_ps(__m128i a) { return *(__m128 *) &a; }
static __m128i gmx_mm_castps_si128(__m128 a) { return *(__m128i *) &a; }
+static __m128 gmx_mm_castps_ps128(__m128 a) { return *(__m128 *) &a; }
#endif
}
-/* This exp-routine has a relative precision of 2^-22.33 bits (essentially single precision :-) ) */
+/* This exp-routine has a relative precision of:
+ * 2^-22.33 bits (essentially single precision :-)
+ * WARNING: no check against over or underflows (x beyond +-87)
+ */
static __m128
gmx_mm_exp_ps(__m128 x)
{
- const __m128i half = _mm_set_epi32(0x3F000000, 0x3F000000, 0x3F000000, 0x3F000000); // 0.5e+0f
- const __m128i base = _mm_set_epi32(0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F); // 127
- const __m128i CC = _mm_set_epi32(0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B); // log2(e)
+ const __m128i half = _mm_set_epi32(0x3F000000, 0x3F000000, 0x3F000000, 0x3F000000); /* 0.5e+0f */
+ const __m128i base = _mm_set_epi32(0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F); /* 127 */
+ const __m128i CC = _mm_set_epi32(0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B); /* log2(e) */
- const __m128i D5 = _mm_set_epi32(0x3AF61905, 0x3AF61905, 0x3AF61905, 0x3AF61905); // 1.8775767e-3f
- const __m128i D4 = _mm_set_epi32(0x3C134806, 0x3C134806, 0x3C134806, 0x3C134806); // 8.9893397e-3f
- const __m128i D3 = _mm_set_epi32(0x3D64AA23, 0x3D64AA23, 0x3D64AA23, 0x3D64AA23); // 5.5826318e-2f
- const __m128i D2 = _mm_set_epi32(0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4); // 2.4015361e-1f
- const __m128i D1 = _mm_set_epi32(0x3F31727B, 0x3F31727B, 0x3F31727B, 0x3F31727B); // 6.9315308e-1f
- const __m128i D0 = _mm_set_epi32(0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF); // 9.9999994e-1f
+ const __m128i D5 = _mm_set_epi32(0x3AF61905, 0x3AF61905, 0x3AF61905, 0x3AF61905); /* 1.8775767e-3f */
+ const __m128i D4 = _mm_set_epi32(0x3C134806, 0x3C134806, 0x3C134806, 0x3C134806); /* 8.9893397e-3f */
+ const __m128i D3 = _mm_set_epi32(0x3D64AA23, 0x3D64AA23, 0x3D64AA23, 0x3D64AA23); /* 5.5826318e-2f */
+ const __m128i D2 = _mm_set_epi32(0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4); /* 2.4015361e-1f */
+ const __m128i D1 = _mm_set_epi32(0x3F31727B, 0x3F31727B, 0x3F31727B, 0x3F31727B); /* 6.9315308e-1f */
+ const __m128i D0 = _mm_set_epi32(0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF); /* 9.9999994e-1f */
__m128 xmm0,xmm1;
__m128i xmm2;
xmm0 = _mm_mul_ps(x,gmx_mm_castsi128_ps(CC));
- xmm1 = _mm_sub_ps(xmm0, gmx_mm_castsi128_ps(half));
+ xmm1 = _mm_sub_ps(xmm0,gmx_mm_castsi128_ps(half));
xmm2 = _mm_cvtps_epi32(xmm1);
xmm1 = _mm_cvtepi32_ps(xmm2);
- xmm2 = _mm_add_epi32(xmm2,gmx_mm_castps_si128(base));
+ xmm2 = _mm_add_epi32(xmm2,base);
xmm2 = _mm_slli_epi32(xmm2,23);
xmm0 = _mm_sub_ps(xmm0,xmm1);
- xmm1 = _mm_mul_ps(xmm0,gmx_mm_castsi128_ps( D5));
+ xmm1 = _mm_mul_ps(xmm0,gmx_mm_castsi128_ps(D5));
xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D4));
xmm1 = _mm_mul_ps(xmm1,xmm0);
xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D3));
}
+/* Same as gmx_mm_exp_ps, but has a lower bound check, such that it can
+ * be safely called with x < -87.33.
+ * WARNING: no check against overflows (x > 87)
+ */
+static __m128
+gmx_mm_exp_ps_lbc(__m128 x)
+{
+ const __m128i lim = _mm_set_epi32(0xC2AE0000, 0xC2AE0000, 0xC2AE0000, 0xC2AE0000); /* -87 */
+ const __m128i half = _mm_set_epi32(0x3F000000, 0x3F000000, 0x3F000000, 0x3F000000); /* 0.5e+0f */
+ const __m128i base = _mm_set_epi32(0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F); /* 127 */
+ const __m128i CC = _mm_set_epi32(0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B); /* log2(e) */
+
+ const __m128i D5 = _mm_set_epi32(0x3AF61905, 0x3AF61905, 0x3AF61905, 0x3AF61905); /* 1.8775767e-3f */
+ const __m128i D4 = _mm_set_epi32(0x3C134806, 0x3C134806, 0x3C134806, 0x3C134806); /* 8.9893397e-3f */
+ const __m128i D3 = _mm_set_epi32(0x3D64AA23, 0x3D64AA23, 0x3D64AA23, 0x3D64AA23); /* 5.5826318e-2f */
+ const __m128i D2 = _mm_set_epi32(0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4); /* 2.4015361e-1f */
+ const __m128i D1 = _mm_set_epi32(0x3F31727B, 0x3F31727B, 0x3F31727B, 0x3F31727B); /* 6.9315308e-1f */
+ const __m128i D0 = _mm_set_epi32(0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF); /* 9.9999994e-1f */
+
+ __m128 xmm0,xmm1;
+ __m128i xmm2;
+
+ xmm1 = _mm_max_ps(x,gmx_mm_castsi128_ps(lim)); /* x<-87 gives exp(-87) */
+ xmm0 = _mm_mul_ps(xmm1,gmx_mm_castsi128_ps(CC));
+ xmm1 = _mm_sub_ps(xmm0,gmx_mm_castsi128_ps(half));
+ xmm2 = _mm_cvtps_epi32(xmm1);
+ xmm1 = _mm_cvtepi32_ps(xmm2);
+
+ xmm2 = _mm_add_epi32(xmm2,base);
+ xmm2 = _mm_slli_epi32(xmm2,23);
+
+ xmm0 = _mm_sub_ps(xmm0,xmm1);
+ xmm1 = _mm_mul_ps(xmm0,gmx_mm_castsi128_ps(D5));
+ xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D4));
+ xmm1 = _mm_mul_ps(xmm1,xmm0);
+ xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D3));
+ xmm1 = _mm_mul_ps(xmm1,xmm0);
+ xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D2));
+ xmm1 = _mm_mul_ps(xmm1,xmm0);
+ xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D1));
+ xmm1 = _mm_mul_ps(xmm1,xmm0);
+ xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D0));
+ xmm1 = _mm_mul_ps(xmm1,gmx_mm_castsi128_ps(xmm2));
+
+ /* 19 instructions currently + pipeline latenct after max_ps */
+ return xmm1;
+}
+
#define GMX_MM_SINCOS_PS(x,sinval,cosval) \
{ \
enum { elsqWEIGHT_NONE, elsqWEIGHT_X, elsqWEIGHT_Y,
elsqWEIGHT_XY, elsqWEIGHT_NR };
+enum { ehistoX, ehistoY, ehistoNR };
+
extern gmx_stats_t gmx_stats_init();
extern int gmx_stats_done(gmx_stats_t stats);
/* Make a histogram of the data present. Uses either bindwith to
determine the number of bins, or nbins to determine the binwidth,
- therefore one of these should be zero, but not the other. If
+ therefore one of these should be zero, but not the other. If *nbins = 0
+ the number of bins will be returned in this variable. ehisto should be one of
+ ehistoX or ehistoY. If
normalized not equal to zero, the integral of the histogram will be
normalized to one. The output is in two arrays, *x and *y, to which
you should pass a pointer. Memory for the arrays will be allocated
as needed. Function returns one of the estats codes. */
-extern int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int nbins,
+extern int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int *nbins,
+ int ehisto,
int normalized,real **x,real **y);
/* Return message belonging to error code */
eCPP_INVALID_HANDLE,
eCPP_FILE_NOT_OPEN, eCPP_UNKNOWN, eCPP_NR };
+/* THESE FUNCTIONS ARE NOT THREAD SAFE!! */
+
/* Open the file to be processed. The handle variable holds internal
info for the cpp emulator. The cppopt variable (null terminated)
- can hold cpp options like -IXXX and -DXXX. Return integer status. */
+ can hold cpp options like -IXXX and -DXXX. Return integer status.
+
+ NOT THREAD SAFE
+ */
extern int cpp_open_file(const char *filenm,gmx_cpp_t *handlep, char **cppopts);
/* Return one whole line from the file into buf which holds at most n
- characters, for subsequent processing. Returns integer status. */
+ characters, for subsequent processing. Returns integer status.
+
+ NOT THREAD SAFE
+ */
extern int cpp_read_line(gmx_cpp_t *handlep,int n,char buf[]);
-/* Return the file currently being read. */
+/* Return the file currently being read.
+
+ NOT THREAD SAFE
+ */
extern char *cpp_cur_file(const gmx_cpp_t *handlep);
-/* Return the current line number. */
+/* Return the current line number.
+
+ NOT THREAD SAFE
+ */
extern int cpp_cur_linenr(const gmx_cpp_t *handlep);
-/* Close the file! Return integer status. */
+/* Close the file! Return integer status.
+
+ NOT THREAD SAFE
+ */
extern int cpp_close_file(gmx_cpp_t *handlep);
/* Return a string containing the error message coresponding to status
- variable. */
+ variable.
+
+ NOT THREAD SAFE
+ */
extern char *cpp_error(gmx_cpp_t *handlep,int status);
#include "typedefs.h"
#include "xdrf.h"
-/* Note that some functions list beow are NOT THREADSAFE
- * when multiple threads use the same file pointer.
- */
-
-/* Highest number of open input/output files. This is usually limited to 1024 by the OS, anyway. */
-#define GMX_MAXFILES 1024
+/* types */
/* Enumerated for different items in files */
enum { eitemHEADER, eitemIR, eitemBOX,
eioUCHAR, eioNUCHAR, eioUSHORT,
eioRVEC, eioNRVEC, eioIVEC, eioSTRING, eioNR };
-/* Functions for reading and writing data */
-typedef bool do_func(void *item,int nitem,int eio,
- const char *desc,const char *srcfile,int line);
-
-/* Global variables defined in gmxfio.h */
-extern do_func *do_read;
-extern do_func *do_write;
+typedef struct t_fileio t_fileio;
+
extern const char *itemstr[eitemNR];
extern const char *comment_str[eitemNR];
+
/********************************************************
* Open and Close
********************************************************/
-int gmx_fio_open(const char *fn,const char *mode);
+t_fileio *gmx_fio_open(const char *fn,const char *mode);
/* Open a new file for reading or writing.
* The file type will be deduced from the file name.
* If fn is NULL, stdin / stdout will be used for Ascii I/O (TPA type)
* unix, but is important on windows.
*/
-int gmx_fio_close(int fp);
+int gmx_fio_close(t_fileio *fp);
/* Close the file corresponding to fp (if not stdio)
* The routine will exit when an invalid fio is handled.
* Returns 0 on success.
*/
-int gmx_fio_fp_close(int fp);
+int gmx_fio_fp_close(t_fileio *fp);
/* Close the file corresponding to fp without closing the FIO entry
* Needed e.g. for trxio because the FIO entries are used to store
* additional data.
* Returns 0 on success.
*/
-void gmx_fio_select(int fp);
-/* This routine sets the global variables do_read and do_write
- * to point to the correct routines for fp.
- */
+
+/* Open a file, return a stream, record the entry in internal FIO object */
+FILE* gmx_fio_fopen(const char *fn,const char *mode);
+
+/* Close a file previously opened with gmx_fio_fopen.
+ * Do not mix these calls with standard fopen/fclose ones!
+ * Returns 0 on success. */
+int gmx_fio_fclose(FILE *fp);
+
+
/********************************************************
* Change properties of the open file
********************************************************/
-extern void gmx_fio_setprecision(int fio,bool bDouble);
+extern void gmx_fio_setprecision(t_fileio *fio,bool bDouble);
/* Select the floating point precision for reading and writing files */
-extern char *gmx_fio_getname(int fio);
+extern char *gmx_fio_getname(t_fileio *fio);
/* Return the filename corresponding to the fio index */
-extern int gmx_fio_getftp(int fio);
-/* Return the filetype corresponding to the fio index */
+extern int gmx_fio_getftp(t_fileio *fio);
+/* Return the filetype corresponding to the fio index.
+ There is as of now no corresponding setftp function because the file
+ was opened as a specific file type and changing that midway is most
+ likely an evil hack. */
-extern void gmx_fio_setftp_fio(int fio,int ftp);
-/* And set it */
-
-extern void gmx_fio_setdebug(int fio,bool bDebug);
+extern void gmx_fio_setdebug(t_fileio *fio,bool bDebug);
/* Set the debug mode */
-extern bool gmx_fio_getdebug(int fio);
+extern bool gmx_fio_getdebug(t_fileio *fio);
/* Return whether debug mode is on in fio */
-extern bool gmx_fio_getread(int fio);
+extern bool gmx_fio_getread(t_fileio *fio);
/* Return whether read mode is on in fio */
+
+extern void gmx_fio_checktype(t_fileio *fio);
+/* Check whether the fio is of a sane type */
+
/***************************************************
* FILE Operations
***************************************************/
-extern void gmx_fio_rewind(int fio);
+extern void gmx_fio_rewind(t_fileio *fio);
/* Rewind the tpa file in fio */
-int gmx_fio_flush(int fio);
+int gmx_fio_flush(t_fileio *fio);
/* Flush the fio, returns 0 on success */
-extern off_t gmx_fio_ftell(int fio);
+int gmx_fio_fsync(t_fileio *fio);
+/* fsync the fio, returns 0 on success.
+ NOTE: don't use fsync function unless you're absolutely sure you need it
+ because it deliberately interferes with the OS's caching mechanisms and
+ can cause dramatically slowed down IO performance. Some OSes (Linux,
+ for example), may implement fsync as a full sync() point. */
+
+extern off_t gmx_fio_ftell(t_fileio *fio);
/* Return file position if possible */
-extern int gmx_fio_seek(int fio,off_t fpos);
+extern int gmx_fio_seek(t_fileio *fio,off_t fpos);
/* Set file position if possible, quit otherwise */
-extern FILE *gmx_fio_getfp(int fio);
+extern FILE *gmx_fio_getfp(t_fileio *fio);
/* Return the file pointer itself */
-extern XDR *gmx_fio_getxdr(int fio);
+extern XDR *gmx_fio_getxdr(t_fileio *fio);
/* Return the file pointer itself */
-/* Open a file, return a stream, record the entry in internal FIO object */
-FILE * gmx_fio_fopen(const char *fn,const char *mode);
-/* Close a file previously opened with gmx_fio_fopen.
- * Do not mix these calls with standard fopen/fclose ones!
- * Returns 0 on success.
- */
-int gmx_fio_fclose(FILE *fp);
+
+
/* Element with information about position in a currently open file.
* off_t should be defined by autoconf if your system does not have it.
- * If you do not have it on some other platform you do not have largefile support
- * at all, and you can define it to int (or better, find out how to enable large files).
- */
+ * If you do not have it on some other platform you do not have largefile
+ * support at all, and you can define it to int (or better, find out how to
+ * enable large files). */
typedef struct
{
char filename[STRLEN];
gmx_file_position_t;
-/*
- * Check if the file position is out of the range of off_t.
+int gmx_fio_check_file_position(t_fileio *fio);
+/* Check if the file position is out of the range of off_t.
* The result is stored along with the other file data of fio.
*/
-int
-gmx_fio_check_file_position(int fio);
-/*
- * Return the name and file pointer positions for all currently open
+int gmx_fio_get_output_file_positions(gmx_file_position_t ** outputfiles,
+ int *nfiles );
+/* Return the name and file pointer positions for all currently open
* output files. This is used for saving in the checkpoint files, so we
* can truncate output files upon restart-with-appending.
*
* For the first argument you should use a pointer, which will be set to
* point to a list of open files.
*/
-int
-gmx_fio_get_output_file_positions (gmx_file_position_t ** outputfiles,
- int *nfiles );
-int gmx_fio_get_file_md5(int fio, off_t offset, unsigned char digest[]);
+t_fileio *gmx_fio_all_output_fsync(void);
+/* fsync all open output files. This is used for checkpointing, where
+ we need to ensure that all output is actually written out to
+ disk.
+ This is most important in the case of some networked file systems,
+ where data is not synced with the file server until close() or
+ fsync(), so data could remain in cache for days.
+ Note the caveats reported with gmx_fio_fsync().
+
+ returns: NULL if no error occurred, or a pointer to the first file that
+ failed if an error occurred
+*/
+
+int gmx_fio_get_file_md5(t_fileio *fio, off_t offset, unsigned char digest[]);
-extern int xtc_seek_frame(int frame, int fio, int natoms);
-extern int xtc_seek_time(real time, int fio, int natoms);
+extern int xtc_seek_frame(t_fileio *fio, int frame, int natoms);
+
+extern int xtc_seek_time(t_fileio *fio, real time, int natoms);
-extern void set_comment(const char *comment);
/* Add this to the comment string for debugging */
+extern void gmx_fio_set_comment(t_fileio *fio, const char *comment);
-extern void unset_comment(void);
/* Remove previously set comment */
+extern void gmx_fio_unset_comment(t_fileio *fio);
+
+
/********************************************************
- * Dirty C macros... Try this in FORTRAN
- * (Oh, and you can do structured programming in C too)
- *********************************************************/
-#define do_real(item) (bRead ?\
- do_read ((void *)&(item),1,eioREAL,(#item),__FILE__,__LINE__) : \
- do_write((void *)&(item),1,eioREAL,(#item),__FILE__,__LINE__))
-
-#define do_double(item) (bRead ? \
- do_read ((void *)&(item),1,eioDOUBLE,(#item),__FILE__,__LINE__) : \
- do_write((void *)&(item),1,eioDOUBLE,(#item),__FILE__,__LINE__))
-
-#define do_int(item) (bRead ?\
- do_read ((void *)&(item),1,eioINT,(#item),__FILE__,__LINE__) :\
- do_write((void *)&(item),1,eioINT,(#item),__FILE__,__LINE__))
+ * Read and write
+ ********************************************************/
+
+
+/* basic reading & writing */
+bool gmx_fio_reade_real(t_fileio *fio, real *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_double(t_fileio *fio, double *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_int(t_fileio *fio, int *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_uchar(t_fileio *fio, unsigned char *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_ushort(t_fileio *fio, unsigned short *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_rvec(t_fileio *fio, rvec *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_ivec(t_fileio *fio, ivec *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_string(t_fileio *fio, char *item,
+ const char *desc, const char *srcfile, int line);
+
+bool gmx_fio_writee_real(t_fileio *fio, real item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_double(t_fileio *fio, double item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_int(t_fileio *fio, int item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_gmx_large_int(t_fileio *fio, gmx_large_int_t item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_uchar(t_fileio *fio, unsigned char item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_ushort(t_fileio *fio, unsigned short item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_rvec(t_fileio *fio, rvec *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_ivec(t_fileio *fio, ivec *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_string(t_fileio *fio, const char *item,
+ const char *desc, const char *srcfile, int line);
+
+/* reading or writing, depending on the file's opening mode string */
+bool gmx_fio_doe_real(t_fileio *fio, real *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_double(t_fileio *fio, double *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_bool(t_fileio *fio, bool *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_int(t_fileio *fio, int *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_uchar(t_fileio *fio, unsigned char *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_ushort(t_fileio *fio, unsigned short *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_rvec(t_fileio *fio, rvec *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_ivec(t_fileio *fio, ivec *item,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_string(t_fileio *fio, char *item,
+ const char *desc, const char *srcfile, int line);
+
+
+
+
+/* array reading & writing */
+bool gmx_fio_nreade_real(t_fileio *fio, real *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_double(t_fileio *fio, double *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_int(t_fileio *fio, int *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n,
+ const char *desc, const char *srcfile,
+ int line);
+bool gmx_fio_nreade_uchar(t_fileio *fio, unsigned char *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_ushort(t_fileio *fio, unsigned short *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_rvec(t_fileio *fio, rvec *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_ivec(t_fileio *fio, ivec *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_string(t_fileio *fio, char *item[], int n,
+ const char *desc, const char *srcfile, int line);
+
+bool gmx_fio_nwritee_real(t_fileio *fio, const real *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_double(t_fileio *fio, const double *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_int(t_fileio *fio, const int *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_gmx_large_int(t_fileio *fio,
+ const gmx_large_int_t *item, int n,
+ const char *desc, const char *srcfile,
+ int line);
+bool gmx_fio_nwritee_uchar(t_fileio *fio, const unsigned char *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_ushort(t_fileio *fio, const unsigned short *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_rvec(t_fileio *fio, const rvec *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_ivec(t_fileio *fio, const ivec *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_string(t_fileio *fio, const char *item[], int n,
+ const char *desc, const char *srcfile, int line);
+
+bool gmx_fio_ndoe_real(t_fileio *fio, real *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_double(t_fileio *fio, double *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_bool(t_fileio *fio, bool *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_int(t_fileio *fio, int *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n,
+ const char *desc, const char *srcfile,
+ int line);
+bool gmx_fio_ndoe_uchar(t_fileio *fio, unsigned char *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_ushort(t_fileio *fio, unsigned short *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_rvec(t_fileio *fio, rvec *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_ivec(t_fileio *fio, ivec *item, int n,
+ const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_string(t_fileio *fio, char *item[], int n,
+ const char *desc, const char *srcfile, int line);
+
+
+
+/* convenience macros */
+#define gmx_fio_read_real(fio, item) gmx_fio_reade_real(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_double(fio, item) gmx_fio_reade_double(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_int(fio, item) gmx_fio_reade_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_gmx_large_int(fio, item) gmx_fio_reade_gmx_large_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_uchar(fio, item) gmx_fio_reade_uchar(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_ushort(fio, item) gmx_fio_reade_ushort(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_rvec(fio, item) gmx_fio_reade_rvec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_ivec(fio, item) gmx_fio_reade_ivec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_string(fio, item) gmx_fio_reade_string(fio, item, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_write_real(fio, item) gmx_fio_writee_real(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_double(fio, item) gmx_fio_writee_double(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_int(fio, item) gmx_fio_writee_int(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_gmx_large_int(fio, item) gmx_fio_writee_gmx_large_int(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_uchar(fio, item) gmx_fio_writee_uchar(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_ushort(fio, item) gmx_fio_writee_ushort(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_rvec(fio, item) gmx_fio_writee_rvec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_ivec(fio, item) gmx_fio_writee_ivec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_string(fio, item) gmx_fio_writee_string(fio, item, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_do_real(fio, item) gmx_fio_doe_real(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_double(fio, item) gmx_fio_doe_double(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_bool(fio, item) gmx_fio_doe_bool(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_int(fio, item) gmx_fio_doe_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_gmx_large_int(fio, item) gmx_fio_doe_gmx_large_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_uchar(fio, item) gmx_fio_doe_uchar(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_ushort(fio, item) gmx_fio_doe_ushort(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_rvec(fio, item) gmx_fio_doe_rvec(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_ivec(fio, item) gmx_fio_doe_ivec(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_string(fio, item) gmx_fio_doe_string(fio, item, (#item), __FILE__, __LINE__)
+
+
+
+
+#define gmx_fio_nread_real(fio, item, n) gmx_fio_nreade_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_double(fio, item, n) gmx_fio_nreade_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_int(fio, item, n) gmx_fio_nreade_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_gmx_large_int(fio, item, n) gmx_fio_nreade_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_uchar(fio, item, n) gmx_fio_nreade_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_ushort(fio, item, n) gmx_fio_nreade_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_rvec(fio, item, n) gmx_fio_nreade_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_ivec(fio, item, n) gmx_fio_nreade_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_string(fio, item, n) gmx_fio_nreade_string(fio, item, n, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_nwrite_real(fio, item, n) gmx_fio_nwritee_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_double(fio, item, n) gmx_fio_nwritee_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_int(fio, item, n) gmx_fio_nwritee_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_gmx_large_int(fio, item, n) gmx_fio_nwritee_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_uchar(fio, item, n) gmx_fio_nwritee_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_ushort(fio, item, n) gmx_fio_nwritee_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_rvec(fio, item, n) gmx_fio_nwritee_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_ivec(fio, item, n) gmx_fio_nwritee_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_string(fio, item, n) gmx_fio_nwritee_string(fio, item, n, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_ndo_real(fio, item, n) gmx_fio_ndoe_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_double(fio, item, n) gmx_fio_ndoe_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_bool(fio, item, n) gmx_fio_ndoe_bool(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_int(fio, item, n) gmx_fio_ndoe_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_gmx_large_int(fio, item, n) gmx_fio_ndoe_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_uchar(fio, item, n) gmx_fio_ndoe_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_ushort(fio, item, n) gmx_fio_ndoe_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_rvec(fio, item, n) gmx_fio_ndoe_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_ivec(fio, item, n) gmx_fio_ndoe_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_string(fio, item, n) gmx_fio_ndoe_string(fio, item, n, (#item), __FILE__, __LINE__)
+
-#define do_gmx_large_int(item) (bRead ? \
- do_read ((void *)&(item),1,eioGMX_LARGE_INT,(#item),__FILE__,__LINE__) :\
- do_write((void *)&(item),1,eioGMX_LARGE_INT,(#item),__FILE__,__LINE__))
-
-#define do_uchar(item) (bRead ?\
- do_read ((void *)&(item),1,eioUCHAR,(#item),__FILE__,__LINE__) :\
- do_write((void *)&(item),1,eioUCHAR,(#item),__FILE__,__LINE__))
-
-#define do_nuchar(item,n) (bRead ?\
- do_read ((void *)(item),n,eioNUCHAR,(#item),__FILE__,__LINE__) :\
- do_write((void *)(item),n,eioNUCHAR,(#item),__FILE__,__LINE__))
-
-#define do_ushort(item) (bRead ?\
- do_read ((void *)&(item),1,eioUSHORT,(#item),__FILE__,__LINE__) :\
- do_write((void *)&(item),1,eioUSHORT,(#item),__FILE__,__LINE__))
-
-#define do_rvec(item) (bRead ?\
- do_read ((void *)(item),1,eioRVEC,(#item),__FILE__,__LINE__) :\
- do_write((void *)(item),1,eioRVEC,(#item),__FILE__,__LINE__))
-
-#define do_ivec(item) (bRead ?\
- do_read ((void *)(item),1,eioIVEC,(#item),__FILE__,__LINE__) :\
- do_write((void *)(item),1,eioIVEC,(#item),__FILE__,__LINE__))
-
-#define do_string(item) (bRead ?\
- do_read ((void *)(item),1,eioSTRING,(#item),__FILE__,__LINE__) :\
- do_write((void *)(item),1,eioSTRING,(#item),__FILE__,__LINE__))
-
-#define ndo_real(item,n,bOK) {\
- bOK=TRUE;\
- for(i=0; (i<n); i++) {\
- char buf[128];\
- sprintf(buf,"%s[%d]",#item,i);\
- bOK = bOK && (bRead ?\
- do_read ((void *)&((item)[i]),1,eioREAL,buf,__FILE__,__LINE__):\
- do_write((void *)&(item[i]),1,eioREAL,buf,__FILE__,__LINE__));\
- }\
-}
-
-#define ndo_double(item,n,bOK) {\
- bOK=TRUE;\
- for(i=0; (i<n); i++) {\
- char buf[128];\
- sprintf(buf,"%s[%d]",#item,i);\
- bOK = bOK && (bRead ?\
- do_read ((void *)&((item)[i]),1,eioDOUBLE,buf,__FILE__,__LINE__):\
- do_write((void *)&(item[i]),1,eioDOUBLE,buf,__FILE__,__LINE__));\
- }\
-}
-
-#define ndo_int(item,n,bOK) {\
- bOK=TRUE;\
- for(i=0; (i<n); i++) {\
- char buf[128];\
- sprintf(buf,"%s[%d]",#item,i);\
- bOK = bOK && (bRead ?\
- do_read ((void *)&(item[i]),1,eioINT,buf,__FILE__,__LINE__):\
- do_write((void *)&(item[i]),1,eioINT,buf,__FILE__,__LINE__));\
- }\
-}
-
-#define ndo_nuchar(item,n,bOK) {\
- bOK=TRUE;\
- for(i=0; (i<n); i++) {\
- char buf[128];\
- sprintf(buf,"%s[%d]",#item,i);\
- bOK = bOK && (bRead ?\
- do_read ((void *)&(item[i]),1,eioNUCHAR,buf,__FILE__,__LINE__):\
- do_write((void *)&(item[i]),1,eioNUCHAR,buf,__FILE__,__LINE__));\
- }\
-}
-
-#define ndo_rvec(item,n) (bRead ?\
- do_read ((void *)(item),n,eioNRVEC,(#item),__FILE__,__LINE__) :\
- do_write((void *)(item),n,eioNRVEC,(#item),__FILE__,__LINE__))
-
-#define ndo_ivec(item,n,bOK) {\
- bOK=TRUE;\
- for(i=0; (i<n); i++) {\
- char buf[128];\
- sprintf(buf,"%s[%d]",#item,i);\
- bOK = bOK && (bRead ?\
- do_read ((void *)(item)[i],1,eioIVEC,buf,__FILE__,__LINE__):\
- do_write((void *)(item)[i],1,eioIVEC,buf,__FILE__,__LINE__));\
- }\
-}
-
-#define ndo_string(item,n,bOK) {\
- bOK=TRUE;\
- for(i=0; (i<n); i++) {\
- char buf[128];\
- sprintf(buf,"%s[%d]",#item,i);\
- bOK = bOK && (bRead ?\
- do_read ((void *)(item)[i],1,eioSTRING,buf,__FILE__,__LINE__):\
- do_write((void *)(item)[i],1,eioSTRING,buf,__FILE__,__LINE__));\
- }\
-}
#endif
extern bool is_int(double x);
/* Returns TRUE when x is integer */
-extern void print_top_comment(FILE *out,const char *filename,const char *title,bool bITP);
+extern void print_top_comment(FILE *out,const char *filename,const char *generator,bool bITP);
extern void print_top_header(FILE *out,const char *filename,const char *title,bool bITP,
const char *ffdir,real mHmult);
int nctl; /* How many control atoms there are */
char *a[4]; /* Control atoms i,j,k,l */
bool bAlreadyPresent;
+ bool bXSet;
rvec newx; /* calculated new position */
atom_id newi; /* new atom index number (after additions) */
} t_hack;
*
* Use gmx_histogram_add_item() or gmx_histogram_add_item_to_bin() to sample.
*/
- HIST_BINAVER,
+ HIST_BINAVER
} e_histogram_t;
/** Whether bins are centered at integer values. */
/* Assume the group file is generated, so the
* format need not be user-friendly. The format is:
* nr of groups, total nr of atoms
- * for each group: name nr of element, elements
- * The function opens a file, reads ngrps groups, puts the
- * sizes in isize, the atom_id s in index and the names of
+ * for each group: name nr of element, elements.
+ *
+ * The function opens a file, reads ngrps groups, asks the
+ * user for group numbers, and puts the resulting sizes in
+ * isize, the atom_id s in index and the names of
* the groups in grpnames.
*
* It is also assumed, that when ngrps groups are requested
extern bool is_protein(t_aa_names *aan,char *resnm);
/* gives true if resnm occurs in aminoacids.dat */
+extern bool is_residue(t_aa_names *aan,char *resnm);
+/* gives true if resnm occurs in aminoacids.dat or is DNA or RNA */
+
extern void done_aa_names(t_aa_names **aan);
/* Free memory. Pass address of the pointer youget from get_aa_names */
INDEX_ATOM, /**< Each atom in a separate block.*/
INDEX_RES, /**< Each residue in a separate block.*/
INDEX_MOL, /**< Each molecule in a separate block.*/
- INDEX_ALL, /**< All atoms in a single block.*/
+ INDEX_ALL /**< All atoms in a single block.*/
} e_index_t;
/*! \brief
/** Reserves memory for an index group mapping. */
extern void
gmx_ana_indexmap_reserve(gmx_ana_indexmap_t *m, int nr, int isize);
-/** Initialize index group mapping. */
+/** Initializes an index group mapping. */
extern void
gmx_ana_indexmap_init(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
t_topology *top, e_index_t type);
+/** Sets an index group mapping to be static. */
+extern void
+gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b);
/** Frees memory allocated for index group mapping. */
extern void
gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m);
extern void init_multisystem(t_commrec *cr,int nsim,int nfile,
const t_filenm fnm[], bool bParFn);
-/* Splits the communication into nsim seperate simulations
+/* Splits the communication into nsim separate simulations
* and creates a communication structure between the master
* these simulations.
* If bParFn is set, the nodeid is appended to the tpx and each output file.
* array of argument strings.
*/
-extern t_commrec *init_par_threads(t_commrec *cro);
-/* Initiate the communication records for thread-parallel simulations.
- Must be called before any communication takes place by the individual
- threads. cro is the old shared commrec */
-
-extern void cancel_par_threads(t_commrec *cr);
-/* Cancel threads (for when there is no parallel version of the integration
- algorithm). Cancels threads (actually, it calls tMPI_Finalize() on them)
- and re-writes commrec to new serial situation. */
+extern t_commrec *init_par_threads(const t_commrec *cro);
+/* Initialize communication records for thread-parallel simulations.
+ Must be called on all threads before any communication takes place by
+ the individual threads. Copies the original commrec to
+ thread-local versions (a small memory leak results because we don't
+ deallocate the old shared version). */
extern t_commrec *init_cr_nopar(void);
/* Returns t_commrec for non-parallel functionality */
#endif
#include <stdio.h>
+#include <time.h>
#include "typedefs.h"
#include "network.h"
#include "tgroup.h"
#include "filenm.h"
#include "mshift.h"
#include "force.h"
-#include "time.h"
#include "edsam.h"
#include "mdebin.h"
#include "vcm.h"
extern "C" {
#endif
-#define MD_POLARISE (1<<2)
-#define MD_IONIZE (1<<3)
-#define MD_RERUN (1<<4)
-#define MD_RERUN_VSITE (1<<5)
-#define MD_FFSCAN (1<<6)
-#define MD_SEPPOT (1<<7)
-#define MD_PARTDEC (1<<9)
-#define MD_DDBONDCHECK (1<<10)
-#define MD_DDBONDCOMM (1<<11)
-#define MD_CONFOUT (1<<12)
-#define MD_REPRODUCIBLE (1<<14)
-#define MD_READ_RNG (1<<15)
-#define MD_APPENDFILES (1<<16)
-#define MD_READ_EKIN (1<<17)
-#define MD_STARTFROMCPT (1<<18)
+#define MD_POLARISE (1<<2)
+#define MD_IONIZE (1<<3)
+#define MD_RERUN (1<<4)
+#define MD_RERUN_VSITE (1<<5)
+#define MD_FFSCAN (1<<6)
+#define MD_SEPPOT (1<<7)
+#define MD_PARTDEC (1<<9)
+#define MD_DDBONDCHECK (1<<10)
+#define MD_DDBONDCOMM (1<<11)
+#define MD_CONFOUT (1<<12)
+#define MD_REPRODUCIBLE (1<<13)
+#define MD_READ_RNG (1<<14)
+#define MD_APPENDFILES (1<<15)
+#define MD_KEEPANDNUMCPT (1<<16)
+#define MD_READ_EKIN (1<<17)
+#define MD_STARTFROMCPT (1<<18)
#define MD_RESETCOUNTERSHALFWAY (1<<19)
/* Define a number of flags to better control the information
} gmx_runtime_t;
typedef struct {
- int fp_trn;
- int fp_xtc;
+ t_fileio *fp_trn;
+ t_fileio *fp_xtc;
int xtc_prec;
ener_file_t fp_ene;
const char *fn_cpt;
+ bool bKeepAndNumCPT;
int eIntegrator;
int simulation_part;
FILE *fp_dhdl;
extern matrix deform_init_box_tpx;
#ifdef GMX_THREADS
extern tMPI_Thread_mutex_t deform_init_box_mutex;
+
+/* The minimum number of atoms per thread. With fewer atoms than this,
+ * the number of threads will get lowered.
+ */
+#define MIN_ATOMS_PER_THREAD 90
#endif
/* Communicate statistics over cr->mpi_comm_mysim */
extern gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],
- bool bAppendFiles,
+ int mdrun_flags,
const t_commrec *cr,const t_inputrec *ir,
const output_env_t oenv);
/* Returns a pointer to a data structure with all output file pointers
extern void check_nnodes_top(char *fn,t_topology *top);
/* Reset the tpr file to work with one node if necessary */
-extern void init_single(FILE *log, t_inputrec *inputrec, const char *tpbfile,
- gmx_mtop_t *mtop, t_state *state);
- /*
- * Allocates space for the topology (top), the coordinates x, the
- * velocities v, masses mass. Reads the parameters, topology,
- * coordinates and velocities from the file specified in tpbfile
- */
/* check the version */
void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
t_inputrec *ir,gmx_mtop_t *mtop);
+/* Allocate and initialize node-local state entries. */
+void set_state_entries(t_state *state,t_inputrec *ir,int nnodes);
+
+/* Broadcast the data for a simulation, and allocate node-specific settings
+ such as rng generators. */
+extern void init_parallel(FILE *log, t_commrec *cr, t_inputrec *inputrec,
+ gmx_mtop_t *mtop, t_state *state);
-extern void init_parallel(FILE *log,const char *tpxfile, t_commrec *cr,
- t_inputrec *inputrec,gmx_mtop_t *mtop,
- t_state *state, int list);
- /*
- * Loads the data for a simulation from the ring. Parameters, topology
- * coordinates, velocities, and masses are initialised equal to using
- * init_single() in the single processor version. The extra argument
- * f_add is allocated to use for the update of the forces, the load
- * array specifies in which part of the x and f array the subsystems
- * of the other processors are located. Homenr0, homenr1, nparts0 and
- * nparts1 are necessary to calculate the non bonded interaction using
- * the symmetry and thus calculating every force only once. List is a
- * facility for logging (and debugging). One can decide to print none or a
- * set of * selected parameters to the file specified by log. Parameters
- * are printed by or-ing the corresponding items from t_listitem. A 0
- * (zero) specifies that nothing is to be printed on the file. The function
- * returns the number of shifts over the ring to perform to calculate
- * all interactions.
- *
- * NOTE: for threaded simulations that don't support parallel runs (at
- * the moment that's only the LBGFS integrator), this function may
- * cancel them and re-write the commrec.
- */
extern void do_constrain_first(FILE *log,gmx_constr_t constr,
t_inputrec *inputrec,t_mdatoms *md,
* based on their coordinates in the "dimension" direction.
*/
-int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
- const output_env_t oenv, bool bVerbose,bool bCompact,
- int nstglobalcomm, ivec ddxyz,int dd_node_order,real rdd,
- real rconstr, const char *dddlb_opt,real dlb_scale,
+int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
+ const t_filenm fnm[], const output_env_t oenv, bool bVerbose,
+ bool bCompact, int nstglobalcomm, ivec ddxyz,int dd_node_order,
+ real rdd, real rconstr, const char *dddlb_opt,real dlb_scale,
const char *ddcsx,const char *ddcsy,const char *ddcsz,
- int nstepout, int resetstep, int nmultisim, int repl_ex_nst,int repl_ex_seed,
- real pforce,real cpt_period,real max_hours,
+ int nstepout, int resetstep, int nmultisim, int repl_ex_nst,
+ int repl_ex_seed, real pforce,real cpt_period,real max_hours,
const char *deviceOptions, unsigned long Flags);
/* Driver routine, that calls the different methods */
-int mdrunner_threads(int nthreads,
- FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
- const output_env_t oenv, bool bVerbose,bool bCompact,
- int nstglobalcomm,
- ivec ddxyz,int dd_node_order,real rdd,real rconstr,
- const char *dddlb_opt,real dlb_scale,
- const char *ddcsx,const char *ddcsy,const char *ddcsz,
- int nstepout,int resetstep,int nmultisim, int repl_ex_nst,
- int repl_ex_seed, real pforce,real cpt_period,
- real max_hours, const char *deviceOptions, unsigned long Flags);
-/* initializes nthread threads before running mdrunner: is the preferred
- way to start a simulation (even if nthreads=1 and no threads are started) */
-
extern void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf);
/* Print a warning message to stderr on the master node
* and to fplog if fplog!=NULL.
#endif
#ifdef USE_MPE
-#include "mpe.h"
+#include <mpe.h>
/* Define MPE logging events here */
/* General events */
int ev_timestep1, ev_timestep2;
extern int
gmx_ana_nbsearch_pos_init(gmx_ana_nbsearch_t *d, t_pbc *pbc,
struct gmx_ana_pos_t *p);
+/** Sets the exclusions for the next neighborhood search. */
+extern int
+gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[]);
/** Check whether a point is within a neighborhood. */
extern bool
gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, rvec x);
extern real
gmx_ana_nbsearch_pos_mindist(gmx_ana_nbsearch_t *d,
struct gmx_ana_pos_t *p, int i);
+/** Finds the first reference position within the cutoff. */
+extern bool
+gmx_ana_nbsearch_first_within(gmx_ana_nbsearch_t *d, rvec x, int *jp);
+/** Finds the first reference position within the cutoff. */
+extern bool
+gmx_ana_nbsearch_pos_first_within(gmx_ana_nbsearch_t *d,
+ struct gmx_ana_pos_t *p, int i, int *jp);
+/** Finds the next reference position within the cutoff. */
+extern bool
+gmx_ana_nbsearch_next_within(gmx_ana_nbsearch_t *d, int *jp);
#ifdef __cplusplus
}
#include <stdio.h>
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
+#include "types/simple.h"
+#include "types/commrec.h"
#include "typedefs.h"
#include "main.h"
#include "gmx_fatal.h"
extern void gmx_sumd(int nr,double r[],const t_commrec *cr);
/* Calculate the global sum of an array of doubles */
-#ifdef GMX_MPI
extern void gmx_sumf_comm(int nr,float r[],MPI_Comm mpi_comm);
/* Calculate the global sum of an array of floats */
extern void gmx_sumd_comm(int nr,double r[],MPI_Comm mpi_comm);
/* Calculate the global sum of an array of doubles */
-#endif
extern void gmx_sumi_sim(int nr,int r[],const gmx_multisim_t *ms);
/* Calculate the sum over the simulations of an array of ints */
t_dih *dih;
int npp;
t_phipsi *pp;
- int traj;
+ t_trxstatus *traj;
int natoms;
int amin,amax;
real t;
int verbosity; /* The level of verbosity for this program */
int debug_level; /* the debug level */
- const char *program_name; /* the program name */
+ char *program_name; /* the program name */
char *cmd_line; /* the re-assembled command line */
};
/* initialize an output_env structure, with reasonable default settings.
(the time unit is set to time_ps, which means no conversion). */
+extern void output_env_done(output_env_t oenv);
+/* free memory allocated for an output_env structure. */
+
extern int output_env_get_verbosity(const output_env_t oenv);
/* return the verbosity */
/* If bSet, use wider format for occupancy and bfactor */
extern void pdb_use_ter(bool bSet);
-/* set read_pdbatoms to read upto 'TER' or 'ENDMDL' (default, bSet=FALSE) */
+/* set read_pdbatoms to read upto 'TER' or 'ENDMDL' (default, bSet=FALSE).
+ This function is fundamentally broken as far as thread-safety is concerned.*/
extern void gmx_write_pdb_box(FILE *out,int ePBC,matrix box);
/* write the box in the CRYST1 record,
* with ePBC=-1 the pbc is guessed from the box
+ * This function is fundamentally broken as far as thread-safety is concerned.
*/
extern void write_pdbfile_indexed(FILE *out,const char *title,t_atoms *atoms,
#include <stdio.h>
#include "typedefs.h"
#include "gmxcomplex.h"
-#include "fftgrid.h"
#include "gmx_wallcycle.h"
#ifdef __cplusplus
enum { GMX_SUM_QGRID_FORWARD, GMX_SUM_QGRID_BACKWARD };
-extern int pme_inconvenient_nnodes(int nkx,int nky,int nnodes);
-/* Checks for FFT + solve_pme load imbalance, returns:
- * 0 when no or negligible load imbalance is expected
- * 1 when a slight load imbalance is expected
- * 2 when using less PME nodes is expected to be faster
- */
-
-extern int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,int nnodes_major,
+extern int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,
+ int nnodes_major,int nnodes_minor,
t_inputrec *ir,int homenr,
bool bFreeEnergy, bool bReproducible);
#define GMX_PME_SPREAD_Q (1<<0)
#define GMX_PME_SOLVE (1<<1)
#define GMX_PME_CALC_F (1<<2)
-#define GMX_PME_DO_ALL (GMX_PME_SPREAD_Q | GMX_PME_SOLVE | GMX_PME_CALC_F)
+#define GMX_PME_CALC_ENER_VIR (1<<3)
+#define GMX_PME_DO_ALL_F (GMX_PME_SPREAD_Q | GMX_PME_SOLVE | GMX_PME_CALC_F)
extern int gmx_pme_do(gmx_pme_t pme,
int start, int homenr,
/* Called on the nodes that do PME exclusively (as slaves)
*/
-extern void gmx_sum_qgrid(gmx_pme_t pme,t_commrec *cr,t_fftgrid *grid,
- int direction);
-
extern void gmx_pme_calc_energy(gmx_pme_t pme,int n,rvec *x,real *q,real *V);
/* Calculate the PME grid energy V for n charges with a potential
* in the pme struct determined before with a call to gmx_pme_do
/* Send the charges and maxshift to out PME-only node. */
extern void gmx_pme_send_x(t_commrec *cr, matrix box, rvec *x,
- bool bFreeEnergy, real lambda, gmx_large_int_t step);
+ bool bFreeEnergy, real lambda,
+ bool bEnerVir,
+ gmx_large_int_t step);
/* Send the coordinates to our PME-only node and request a PME calculation */
extern void gmx_pme_finish(t_commrec *cr);
matrix box, rvec **x,rvec **f,
int *maxshift0,int *maxshift1,
bool *bFreeEnergy,real *lambda,
+ bool *bEnerVir,
gmx_large_int_t *step);
/* Receive charges and/or coordinates from the PP-only nodes.
* Returns the number of atoms, or -1 when the run is finished.
extern void gmx_pme_send_force_vir_ener(gmx_pme_pp_t pme_pp,
rvec *f, matrix vir,
real energy, real dvdlambda,
- float cycles,
- bool bGotStopNextStepSignal,
- bool bGotStopNextNbrStepSignal);
+ float cycles);
/* Send the PME mesh force, virial and energy to the PP-only nodes */
#ifdef __cplusplus
POS_RES, /**< Calculate center for each residue. */
POS_MOL, /**< Calculate center for each molecule. */
POS_ALL, /**< Calculate center for the whole group. */
- POS_ALL_PBC, /**< Calculate center for the whole group with PBC. */
+ POS_ALL_PBC /**< Calculate center for the whole group with PBC. */
} e_poscalc_t;
/** Collection of \c gmx_ana_poscalc_t structures for the same topology. */
#include <stdio.h>
#include "typedefs.h"
#include "gmxcomplex.h"
-#include "fftgrid.h"
#ifdef __cplusplus
extern "C" {
bool bSet; /* whether it it has been read out */
char *name; /* name of the parameter */
char *value; /* parameter value string */
+ int inp_count; /* number of einps read. Only valid for the first item
+ in the inpfile list. */
} t_inpfile;
/* entry in input files (like .mdp files).
Initally read in with read_inpfile, then filled in with missing values
extern t_restp *search_rtp(const char *key,int nrtp,t_restp rtp[]);
/* Search for an entry in the rtp database */
-extern gpp_atomtype_t read_atype(const char *ffdir,t_symtab *tab);
+extern gpp_atomtype_t read_atype(const char *ffdir,bool bAddCWD,t_symtab *tab);
/* read atom type database(s) */
extern void read_resall(char *resdb, int *nrtp,t_restp **rtp,
extern "C" {
#endif
-extern void rm_pbc(t_idef *idef,int ePBC,int natoms,matrix box,rvec x[],
- rvec x_s[]);
-/* Correct coordinates for atoms within every molecule for the periodic
- * boundary conditions such that every molecule is whole.
- * (note that mdrun only writes whole molecules)
- * x are the input coordinates, x_s the shifted coordinates where
- * the molecules are whole. x and x_s can be the same array.
- * natoms is the size of x and x_s and can be smaller than the number
- * of atoms in idef, but should only contain complete molecules.
- * When ePBC=-1, the type of pbc is guessed from the box matrix.
- */
-
-extern void rm_gropbc(t_atoms *atoms,rvec x[],matrix box);
-/* Simple routine for use in analysis tools that just have a pdb or
- * similar file.
- */
+ typedef struct gmx_rmpbc *gmx_rmpbc_t;
+
+ extern gmx_rmpbc_t gmx_rmpbc_init(t_idef *idef,int ePBC,int natoms,
+ matrix box);
+
+ extern void gmx_rmpbc_done(gmx_rmpbc_t gpbc);
+ extern void gmx_rmpbc(gmx_rmpbc_t gpbc,matrix box,rvec x[],rvec x_s[]);
+ /* Correct coordinates for atoms within every molecule for the periodic
+ * boundary conditions such that every molecule is whole.
+ * (note that mdrun only writes whole molecules)
+ * x are the input coordinates, x_s the shifted coordinates where
+ * the molecules are whole. x and x_s can be the same array.
+ * natoms is the size of x and x_s and can be smaller than the number
+ * of atoms in idef, but should only contain complete molecules.
+ * When ePBC=-1, the type of pbc is guessed from the box matrix.
+ */
+
+ /*extern void rm_pbc(t_idef *idef,int ePBC,int natoms,
+ matrix box,rvec x[],rvec x_s[]);*/
+ /* Convenience function that still holds a static variable. */
+
+ extern void rm_gropbc(t_atoms *atoms,rvec x[],matrix box);
+ /* Simple routine for use in analysis tools that just have a pdb or
+ * similar file.
+ */
+
#ifdef __cplusplus
}
#endif
typedef enum
{
CFRAC_NONE, /**< No covered fraction (everything covered). */
- CFRAC_SOLIDANGLE, /**< Fraction of a solid (3D) angle covered. */
+ CFRAC_SOLIDANGLE /**< Fraction of a solid (3D) angle covered. */
} e_coverfrac_t;
/*! \brief
gmx_ana_indexgrps_t *grps);
/* In compiler.c */
+/** Set debugging flag for selection compilation. */
+extern void
+gmx_ana_selcollection_set_compile_debug(gmx_ana_selcollection_t *sc, bool bDebug);
/** Prepares the selections for evaluation and performs some optimizations. */
extern int
gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc);
* number of values.
* The number of values is determined based on the values given by the user
* to the method parameters (see \ref selmethods_params).
- *
+ * .
+ * If either of these flags is specified (and the method type is not
+ * \ref GROUP_VALUE), the group passed to the evaluation callback should not
+ * be used as it can be NULL.
* Currently, the above flags only work (have been tested) for \ref POS_VALUE
* methods.
*
* In general, any of the callbacks can be NULL, but the presence of
* parameters or other callbacks imposes some restrictions:
* - sel_datafunc() should be provided if the method takes parameters.
- * - sel_initfunc() and sel_freefunc() should be provided if the method takes
+ * - sel_initfunc() should be provided if the method takes
* any parameters with the \ref SPAR_VARNUM or \ref SPAR_ATOMVAL flags,
* except if those parameters have a \ref POS_VALUE.
* - sel_outinitfunc() should be provided for \ref POS_VALUE methods
* - sel_freefunc() should be provided if sel_datafunc() and/or
* sel_initfunc() allocate any dynamic memory in addition to the data
* structure itself.
- * - sel_framefunc() and sel_updatefunc_pos() only make sense for methods with
- * \ref SMETH_DYNAMIC set.
+ * - sel_updatefunc_pos() only makes sense for methods with \ref SMETH_DYNAMIC
+ * set.
* - At least one update function should be provided unless the method type is
* \ref NO_VALUE.
*
* If a parameter had the \ref SPAR_VARNUM or \ref SPAR_ATOMVAL flag (and
* is not \ref POS_VALUE), a pointer to the memory allocated for the values is
* found in \c gmx_ana_selparam_t::val.
- * The pointer should be stored by this function, otherwise the memory
- * (and the values) are lost.
+ * The pointer should be stored by this function, otherwise the values
+ * cannot be accessed.
* For \ref SPAR_VARNUM parameters, the number of values can be accessed
* through \c gmx_ana_selparam_t::val. For parameters with \ref SPAR_DYNAMIC,
* the number is the maximum number of values (the actual number can be
* The data structure itself should not be freed; this is handled automatically.
* If there is no dynamically allocated data within the structure,
* this function is not needed.
- * The value pointers for \ref SPAR_VARNUM and \ref SPAR_ATOMVAL parameters
- * stored in sel_initfunc() should also be freed.
+ * Any memory pointers received as values of parameters are managed externally,
+ * and should not be freed.
* Pointers set as the value pointer of \ref SPAR_ENUMVAL parameters should not
* be freed.
*/
* It is ensured that this function will be called before
* \p sel_updatefunc_* for each frame, and that it will be called at most
* once for each frame.
+ * For static methods, it is called once, with \p fr and \p pbc set to
+ * NULL.
*/
typedef int (*sel_framefunc)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
void *data);
#ifndef SELVALUE_H
#define SELVALUE_H
-#include <types/simple.h>
+#include "types/simple.h"
#ifdef __cplusplus
extern "C"
REAL_VALUE, /**< One or more real values. */
STR_VALUE, /**< One or more string values. */
POS_VALUE, /**< One or more position values. */
- GROUP_VALUE, /**< One group of atoms. */
+ GROUP_VALUE /**< One group of atoms. */
} e_selvalue_t;
/*! \brief
--- /dev/null
+/*
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+
+#ifndef _sfactor_h
+#define _sfactor_h
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "index.h"
+#include "types/simple.h"
+#include "gmxcomplex.h"
+#include "oenv.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct gmx_structurefactors gmx_structurefactors_t;
+
+typedef struct structure_factor structure_factor_t;
+
+typedef struct reduced_atom reduced_atom_t;
+
+extern int * create_indexed_atom_type (reduced_atom_t * atm, int size);
+
+extern void compute_structure_factor (structure_factor_t * sft, matrix box,
+ reduced_atom_t * red, int isize, real start_q,
+ real end_q, int group,real **sf_table);
+
+extern gmx_structurefactors_t *gmx_structurefactors_init(const char *datfn);
+
+extern void gmx_structurefactors_done(gmx_structurefactors_t *gsf);
+
+extern int gmx_structurefactors_get_sf(gmx_structurefactors_t *gsf, int elem, real a[4], real b[4], real *c);
+
+extern real **gmx_structurefactors_table(gmx_structurefactors_t *gsf,real momentum, real ref_k,
+ real lambda, int n_angles);
+
+extern void save_data (structure_factor_t * sft, const char *file, int ngrps,
+ real start_q, real end_q, const output_env_t oenv);
+
+extern double CMSF (gmx_structurefactors_t *gsf,int type,int nh,double lambda, double sin_theta);
+
+extern int return_atom_type (const char *name,gmx_structurefactors_t *gsf);
+
+extern void rearrange_atoms (reduced_atom_t * positions, t_trxframe *fr, atom_id * index,
+ int isize, t_topology * top, bool flag,gmx_structurefactors_t *gsf);
+
+extern int do_scattering_intensity (const char* fnTPS, const char* fnNDX,
+ const char* fnXVG, const char *fnTRX,
+ const char* fnDAT,
+ real start_q,real end_q,
+ real energy,int ng,const output_env_t oenv);
+
+extern t_complex *** rc_tensor_allocation(int x, int y, int z);
+
+extern real **compute_scattering_factor_table (gmx_structurefactors_t *gsf,structure_factor_t * sft,int *nsftable);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
extern "C" {
#endif
-/* The following two variables and the signal_handler function
- * are used from md.c and pme.c as well
- *
- * Do not fear these global variables: they represent inherently process-global
- * information that needs to be shared across threads
- */
+/* NOTE: the terminology is:
+ incoming signals (provided by the operating system, or transmitted from
+ other nodes) lead to stop conditions. These stop conditions should be
+ checked for and acted on by the outer loop of the simulation */
+/* the stop conditions. They are explicitly allowed to be compared against
+ each other. */
+typedef enum
+{
+ gmx_stop_cond_none=0,
+ gmx_stop_cond_next_ns, /* stop a the next neighbour searching step */
+ gmx_stop_cond_next, /* stop a the next step */
+ gmx_stop_cond_abort /* stop now. (this should never be seen) */
+} gmx_stop_cond_t;
-/* we got a signal to stop in the next step: */
-extern volatile sig_atomic_t bGotStopNextStepSignal;
-/* we got a signal to stop in the next neighbour search step: */
-extern volatile sig_atomic_t bGotStopNextNSStepSignal;
+/* Our names for the stop conditions.
+ These must match the number given in gmx_stop_cond_t.*/
+extern const char *gmx_stop_cond_name[];
-/* our names for the handled signals. These must match the number given
- in signal_handler.*/
-extern const char *signal_name[];
-/* the last signal received, according to the numbering
- we use in signal_name. Is set to -1 if no signal has (yet)
- been received */
-extern volatile sig_atomic_t last_signal_number_recvd;
+/* the externally visible functions: */
+/* install the signal handlers that can set the stop condition. */
+void signal_handler_install(void);
-/* prototype for the signal handler */
-extern RETSIGTYPE signal_handler(int n);
+/* get the current stop condition */
+gmx_stop_cond_t gmx_get_stop_condition(void);
+
+/* set the stop condition upon receiving a remote one */
+void gmx_set_stop_condition(gmx_stop_cond_t recvd_stop_cond);
+
+/* get the signal name that lead to the current stop condition. */
+const char *gmx_get_signal_name(void);
+
+/* check whether we received a USR1 signal.
+ The condition is reset once a TRUE value is returned, so this function
+ only returns TRUE once for a single signal. */
+bool gmx_got_usr_signal(void);
-/* install the signal handlers */
-void signal_handler_install(void);
#ifdef __cplusplus
}
* sfree(ptr)
* Frees memory referenced by ptr.
*
+ * snew_aligned(ptr,nelem,alignment)
+ * Allocates memory for nelem elements and returns this in ptr.
+ * The allocated memory is initialized to zeroes.
+ * alignment=n will constrain ptr to be n-byte aligned.
+ * This pointer should only be freed with sfree_aligned, since
+ * it may not be the value returned by the underlying malloc.
+ *
+ * sfree_aligned(ptr)
+ * Frees aligned memory referenced by ptr.
+ *
****************************************************************************
*
* Functions which are used by the macro's:
* the sum of the previously allocated space. As mentioned with maxavail,
* it is important that free can undo the effect of a malloc.
*
+ * extern void *save_malloc_aligned(char *name,char *file,int line,size_t size,size_t alignment);
+ * Like alloc, returns a pointer to the allocated space, uses name, file
+ * and line to generate an error message when allocation failed.
+ * The returned pointer will be n-byte aligned, where n=alignment.
+ * The pointer should only be freed with a call to save_free.
+ *
+ * extern void save_free_aligned(char *name,char *file,int line, void *ptr);
+ * Like free, uses name, file and line to generate an error message when
+ * the free failed. This function is intended to be called for
+ * pointers allocated with save_malloc_aligned, and may not work
+ * on normal pointers.
*/
#ifdef __cplusplus
size_t maxavail(void);
size_t memavail(void);
+/* Aligned-memory counterparts */
+
+void *save_calloc_aligned(const char *name,const char *file,int line,
+ unsigned nelem,size_t elsize,size_t alignment);
+void save_free_aligned(const char *name,const char *file,int line, void *ptr);
+
#ifdef __cplusplus
}
+/* Use of sizeof(T) in _snew() and _srenew() can cause obscure bugs if
+ * several files define distinct data structures with identical names and
+ * allocate memory for them using the macros below.
+ * For this reason, the size of an element is passed as a parameter.
+ *
+ * The C versions work fine in such cases, but when compiled with a C++
+ * compiler (and if the compiler does not inline the calls), the linker cannot
+ * tell that data structures with identical names are actually different and
+ * links calls to these template functions incorrectly, which can result in
+ * allocation of an incorrect amount of memory if the element size is computed
+ * within the function. Even with the size passed as a parameter, incorrect
+ * linkage will occur, but as the type is now only present in the cast, it
+ * should not cause problems.
+ */
template <typename T>
-void _snew(const char *name, T *&ptr, int nelem)
+void _snew(const char *name, const char *file, int line,
+ T *&ptr, size_t nelem, size_t elsize)
{
- ptr = (T *)save_calloc(name, __FILE__, __LINE__, nelem, sizeof(T));
+ ptr = (T *)save_calloc(name, file, line, nelem, elsize);
}
template <typename T>
-void _srenew(const char *name, T *&ptr, int nelem)
+void _srenew(const char *name, const char *file, int line,
+ T *&ptr, size_t nelem, size_t elsize)
{
- ptr = (T *)save_realloc(name, __FILE__, __LINE__, ptr, nelem, sizeof(T));
+ ptr = (T *)save_realloc(name, file, line, ptr, nelem, elsize);
}
template <typename T>
-void _smalloc(const char *name, T *&ptr, size_t size)
+void _smalloc(const char *name, const char *file, int line, T *&ptr, size_t size)
{
- ptr = (T *)save_malloc(name, __FILE__, __LINE__, size);
+ ptr = (T *)save_malloc(name, file, line, size);
}
template <typename T>
-void _srealloc(const char *name, T *&ptr, size_t size)
+void _srealloc(const char *name, const char *file, int line, T *&ptr, size_t size)
{
- ptr = (T *)save_realloc(name, __FILE__, __LINE__, ptr, size, sizeof(char));
+ ptr = (T *)save_realloc(name, file, line, ptr, size, sizeof(char));
+}
+template <typename T>
+void _snew_aligned(const char *name, const char *file, int line,
+ T *&ptr, size_t nelem, size_t elsize,size_t alignment)
+{
+ ptr = (T *)save_calloc_aligned(name, file, line, nelem, elsize, alignment);
}
-
-
-#define snew(ptr,nelem) _snew(#ptr,(ptr),(nelem))
-#define srenew(ptr,nelem) _srenew(#ptr,(ptr),(nelem))
-#define smalloc(ptr, size) _smalloc(#ptr,(ptr),(size))
-#define srealloc(ptr, size) _srealloc(#ptr,(ptr),(size))
+#define snew(ptr,nelem) _snew(#ptr,__FILE__,__LINE__,(ptr),(nelem),sizeof(*(ptr)))
+#define srenew(ptr,nelem) _srenew(#ptr,__FILE__,__LINE__,(ptr),(nelem),sizeof(*(ptr)))
+#define smalloc(ptr, size) _smalloc(#ptr,__FILE__,__LINE__,(ptr),(size))
+#define srealloc(ptr, size) _srealloc(#ptr,__FILE__,__LINE__,(ptr),(size))
+#define snew_aligned(ptr,nelem,alignment) _snew_aligned(#ptr,__FILE__,__LINE__,(ptr),(nelem),sizeof(*(ptr)),alignment)
#else
(ptr)=save_calloc(#ptr,__FILE__,__LINE__,nelem,elsize)
#define srealloc(ptr,size) (ptr)=save_realloc(#ptr,__FILE__,__LINE__,\
(ptr),size,1)
+#define snew_aligned(ptr,nelem,alignment) (ptr)=save_calloc_aligned(#ptr,__FILE__,__LINE__,(nelem),sizeof(*(ptr)),alignment)
#endif
#define sfree(ptr) save_free(#ptr,__FILE__,__LINE__,(ptr))
+/* call this ONLY with a pointer obtained through snew_aligned or
+ smalloc_aligned: */
+#define sfree_aligned(ptr) save_free_aligned(#ptr,__FILE__,__LINE__,(ptr))
+
#endif /* _smalloc_h */
/* Randomize the order of nwater molecules of length nwatom, the
* first atom of which is at astart.
* If v is not NULL it will be shuffled along
+ * IS NOT THREAD SAFE
*/
extern void sortwater(int astart,int nwater,int nwatom,rvec x[],rvec v[]);
/* Sort the order of nwater molecules of length nwatom on X coordinate
* If v is not NULL it will be shuffled along
+ * IS NOT THREAD SAFE
*/
extern void mkcompact(int astart,int nwater,int nwatom,rvec x[],rvec v[],
int nnode,matrix box);
-/* Make compact subboxes */
+/* Make compact subboxes
+ * IS NOT THREAD SAFE */
#ifdef __cplusplus
}
+++ /dev/null
-/*
- *
- * This source code is part of
- *
- * G R O M A C S
- *
- * GROningen MAchine for Chemical Simulations
- *
- * VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- *
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _statusio_h
-#define _statusio_h
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "typedefs.h"
-#include "sheader.h"
-
-/*
- * This module handles status file io. All read and write operations from
- * and to a status file should use this functions to be independent of the
- * actual file layout (text versus binary file).
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern size_t wr_status(FILE *fp,int step,real t,real lambda,
- t_inputrec *ir,rvec *box,rvec *vir,rvec *pres,
- int natoms,rvec *x,rvec *v,rvec *f,
- int nre,t_energy *e,t_topology *top);
-/*
- * Writes a complete status to the file, specified by fp. NULL pointers
- * indicate that this field should not be written. The function returns
- * the number of bytes written.
- */
-
-extern char *rd_hstatus(FILE *fp,t_statheader *sh,int *step,real *t,
- real *lambda,t_inputrec *ir,rvec *box,
- rvec *vir,rvec *pres,int *natoms,
- rvec *x,rvec *v,rvec *f,int *nre,t_energy *e,
- t_topology *top);
-/*
- * Reads a complete status from the file, specified by fp. It uses
- * the status header to find the items in the file, also the file
- * should be positioned right for reading the first item. The function
- * returns the version string from the header.
- */
-
-extern char *rd_status(FILE *fp,int *step,real *t,real *lambda,
- t_inputrec *ir,rvec *box,rvec *vir,rvec *pres,
- int *natoms,rvec *x,
- rvec *v,rvec *f,int *nre,t_energy *e,
- t_topology *top);
-/*
- * Reads a complete status from the file, specified by fp. First it
- * reads the header and then invokes rd_hstatus() to read the rest
- * of the status. It returns the version returned from rd_hstatus().
- */
-
-extern void write_status(char *fn,int step,real t,real lambda,t_inputrec *ir,
- rvec *box,rvec *vir,rvec *pres,
- int natoms,rvec *x,rvec *v,rvec *f,
- int nre,t_energy *e,t_topology *top);
-/*
- * Writes a complete status to the file, specified by fn. NULL pointers
- * indicate that this field should not be written.
- */
-
-extern char *read_status(char *fn,int *step,real *t,real *lambda,
- t_inputrec *ir,rvec *box,rvec *vir,rvec *pres,
- int *natoms,rvec *x,
- rvec *v,rvec *f,int *nre,t_energy *e,
- t_topology *top);
-/*
- * Reads a complete status from the file, specified by fn. It returns
- * the version returned from rd_hstatus().
- */
-
-extern void read_status_header(char *fn,t_statheader *header);
-/*
- * Reads a (status) header from the file, specified by fn. If
- * available, it returns the version string from the file, else
- * it returns a version string from the statusio module.
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _statusio_h */
#include "wman.h"
#include "pdbio.h"
#include "oenv.h"
+#include "gmxfio.h"
#ifdef __cplusplus
extern void setTimeValue(int tcontrol,real value);
/* End trajectory time control */
+
+/* a dedicated status type contains fp, etc. */
+typedef struct t_trxstatus t_trxstatus;
-typedef int t_first_x(int *status,const char *fn,real *t,rvec **x,matrix box);
+typedef int t_first_x(t_trxstatus **status,const char *fn,real *t,rvec **x,
+ matrix box);
-typedef bool t_next_x(int status,real *t,int natoms,rvec x[],matrix box);
+typedef bool t_next_x(t_trxstatus *status,real *t,int natoms,rvec x[],
+ matrix box);
/* I/O function types */
extern void set_trxframe_ePBC(t_trxframe *fr,int ePBC);
/* Set the type of periodic boundary conditions, ePBC=-1 is not set */
-extern int nframes_read(void);
+extern int nframes_read(t_trxstatus *status);
/* Returns the number of frames read from the trajectory */
-int write_trxframe_indexed(int status,t_trxframe *fr,int nind,atom_id *ind,
- gmx_conect gc);
+int write_trxframe_indexed(t_trxstatus *status,t_trxframe *fr,int nind,
+ atom_id *ind, gmx_conect gc);
/* Write an indexed frame to a TRX file, see write_trxframe. gc may be NULL */
-int write_trxframe(int status,t_trxframe *fr,gmx_conect gc);
+int write_trxframe(t_trxstatus *status,t_trxframe *fr,gmx_conect gc);
/* Write a frame to a TRX file.
* Only entries for which the boolean is TRUE will be written,
* except for step, time, lambda and/or box, which may not be
* gc is important for pdb file writing only and may be NULL.
*/
-int write_trx(int status,int nind,atom_id *ind,t_atoms *atoms,
+int write_trx(t_trxstatus *status,int nind,atom_id *ind,t_atoms *atoms,
int step,real time,matrix box,rvec x[],rvec *v,
gmx_conect gc);
/* Write an indexed frame to a TRX file.
* atoms can be NULL for file types which don't need atom names.
*/
-void close_trx(int status);
+void close_trx(t_trxstatus *status);
/* Close trj file as opened with read_first_x, read_frist_frame
* or open_trx. Identical to close_trj.
*/
-int open_trx(const char *outfile,const char *filemode);
-/* Open a TRX file and return the file number */
+t_trxstatus *open_trx(const char *outfile,const char *filemode);
+/* Open a TRX file and return an allocated status pointer */
+
+/* get a fileio from a trxstatus */
+t_fileio *trx_get_fileio(t_trxstatus *status);
+
extern bool bRmod_fd(double a, double b, double c,bool bDouble);
/* Returns TRUE when (a - b) MOD c = 0, using a margin which is slightly
#define DATA_NOT_OK (1<<1)
#define FRAME_NOT_OK (HEADER_NOT_OK | DATA_NOT_OK)
-extern int read_first_frame(const output_env_t oenv,int *status,const char *fn,
- t_trxframe *fr,int flags);
+extern int read_first_frame(const output_env_t oenv,t_trxstatus **status,
+ const char *fn, t_trxframe *fr,int flags);
/* Read the first frame which is in accordance with flags, which are
* defined further up in this file.
* Returns natoms when succeeded, 0 otherwise.
* Returns TRUE when succeeded, FALSE otherwise.
*/
-extern bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr);
+extern bool read_next_frame(const output_env_t oenv,t_trxstatus *status,
+ t_trxframe *fr);
/* Reads the next frame which is in accordance with fr->flags.
* Returns TRUE when succeeded, FALSE otherwise.
*/
-extern int read_first_x(const output_env_t oenv,int *status,const char *fn,
- real *t,rvec **x,matrix box);
+extern int read_first_x(const output_env_t oenv,t_trxstatus **status,
+ const char *fn, real *t,rvec **x,matrix box);
/* These routines read first coordinates and box, and allocates
* memory for the coordinates, for a trajectory file.
* The routine returns the number of atoms, or 0 when something is wrong.
* The integer in status should be passed to calls of read_next_x
*/
-extern bool read_next_x(const output_env_t oenv,int status,real *t,int natoms,
- rvec x[],matrix box);
+extern bool read_next_x(const output_env_t oenv,t_trxstatus *status,real *t,
+ int natoms, rvec x[],matrix box);
/* Read coordinates and box from a trajectory file. Return TRUE when all well,
* or FALSE when end of file (or last frame requested by user).
* status is the integer set in read_first_x.
*/
-extern void close_trj(int status);
+extern void close_trj(t_trxstatus *status);
/* Close trj file as opened with read_first_x, read_frist_frame
* or open_trx. Identical to close_trx.
*/
-extern void rewind_trj(int status);
+extern void rewind_trj(t_trxstatus *status);
/* Rewind trj file as opened with read_first_x */
extern t_topology *read_top(const char *fn,int *ePBC);
pkgincludethread_mpidir = ${pkgincludedir}/thread_mpi
pkgincludethread_mpi_HEADERS = \
- atomic.h list.h nothreads.h threads.h \
- winthreads.h collective.h mpi_bindings.h pthreads.h \
- tmpi.h
-
+ atomic.h hwinfo.h nothreads.h wait.h \
+ barrier.h list.h pthreads.h winthreads.h \
+ collective.h lock.h threads.h \
+ event.h mpi_bindings.h tmpi.h
*
* \return 1 if the spinlock is locked, 0 otherwise.
*/
-static inline int tMPI_Spinlock_islocked(tMPI_Spinlock_t *x)
+static inline int tMPI_Spinlock_islocked(const tMPI_Spinlock_t *x)
{
int rc;
#endif
-
-#if 0
-/** Spinlock-based barrier type
- *
- * This barrier has the same functionality as the standard
- * tMPI_Thread_barrier_t, but since it is based on spinlocks
- * it provides faster synchronization at the cost of busy-waiting.
- *
- * Variables of this type should be initialized by calling
- * tMPI_Spinlock_barrier_init() to set the number of threads
- * that should be synchronized.
- *
- * \see
- * - tMPI_Spinlock_barrier_init
- * - tMPI_Spinlock_barrier_wait
- */
-typedef struct tMPI_Spinlock_barrier
-{
- tMPI_Atomic_t count; /*!< Number of threads remaining */
- int threshold; /*!< Total number of threads */
- volatile int cycle; /*!< Current cycle (alternating 0/1) */
-}
-tMPI_Spinlock_barrier_t;
-
-
-
-
-/** Initialize spinlock-based barrier
- *
- * \param barrier Pointer to _spinlock_ barrier. Note that this is not
- * the same datatype as the full, thread based, barrier.
- * \param count Number of threads to synchronize. All threads
- * will be released after \a count calls to
- * tMPI_Spinlock_barrier_wait().
- */
-static inline void tMPI_Spinlock_barrier_init(tMPI_Spinlock_barrier_t *barrier,
- int count)
-{
- barrier->threshold = count;
- barrier->cycle = 0;
- tMPI_Atomic_set(&(barrier->count),count);
-}
-
-
-
-
-/** Perform busy-waiting barrier synchronization
-*
-* This routine blocks until it has been called N times,
-* where N is the count value the barrier was initialized with.
-* After N total calls all threads return. The barrier automatically
-* cycles, and thus requires another N calls to unblock another time.
-*
-* Note that spinlock-based barriers are completely different from
-* standard ones (using mutexes and condition variables), only the
-* functionality and names are similar.
-*
-* \param barrier Pointer to previously create barrier.
-*
-* \return The last thread returns -1, all the others 0.
-*/
-static inline int tMPI_Spinlock_barrier_wait(tMPI_Spinlock_barrier_t *barrier)
-{
- int cycle;
- int status;
- /*int i;*/
-
- /* We don't need to lock or use atomic ops here, since the cycle index
- * cannot change until after the last thread has performed the check
- * further down. Further, they cannot reach this point in the next
- * barrier iteration until all of them have been released, and that
- * happens after the cycle value has been updated.
- *
- * No synchronization == fast synchronization.
- */
- cycle = barrier->cycle;
-
- /* Decrement the count atomically and check if it is zero.
- * This will only be true for the last thread calling us.
- */
- if( tMPI_Atomic_add_return( &(barrier->count), -1 ) <= 0)
- {
- tMPI_Atomic_set(&(barrier->count), barrier->threshold);
- barrier->cycle = !barrier->cycle;
-
- status = -1;
- }
- else
- {
- /* Wait until the last thread changes the cycle index.
- * We are both using a memory barrier, and explicit
- * volatile pointer cast to make sure the compiler
- * doesn't try to be smart and cache the contents.
- */
- do
- {
- tMPI_Atomic_memory_barrier();
- }
- while( *(volatile int *)(&(barrier->cycle)) == cycle);
-
- status = 0;
- }
- return status;
-}
-#endif
-
-
+/* this allows us to use the inline keyword without breaking support for
+ some compilers that don't support it: */
#ifdef inline_defined_in_atomic
#undef inline
#endif
"\tpause\n" /* otherwise: small pause
as recommended by Intel */
"\tjmp 1b\n" /* and jump back */
+ "2:\n"
: "=m"(x->lock) /* input & output var */
:
: "memory"/* we changed memory */
* particular when it comes to clobbered variables. Since this implementation
* _could_ be buggy, we have separated it from the known-to-be-working gcc
* one above.
+ *
+ * For now, we just disable the inline keyword if we're compiling C code:
*/
+#ifndef __cplusplus
+#define inline_defined_in_atomic 1
+#define inline
+#endif
+
#define tMPI_Atomic_memory_barrier() { __asm__ __volatile__("\t eieio\n"\
: : :"memory" ); }
#ifndef _TMPI_BARRIER_H_
#define _TMPI_BARRIER_H_
+#include "wait.h"
+
/** Fast (possibly busy-wait-based) barrier type
*
* This barrier has the same functionality as the standard
* barrier for when waits are expected to be reasonably short.
*
* Variables of this type should be initialized by calling
- * tMPI_Spinlock_barrier_init() to set the number of threads
+ * tMPI_Barrier_init() to set the number of threads
* that should be synchronized.
*
* \see
- * - tMPI_Spinlock_barrier_init
- * - tMPI_Spinlock_barrier_wait
+ * - tMPI_Barrier_init
+ * - tMPI_Barrier_wait
*/
-typedef struct tMPI_Spinlock_barrier tMPI_Spinlock_barrier_t;
+typedef struct tMPI_Barrier_t tMPI_Barrier_t;
+struct tMPI_Barrier_t
+{
+ tMPI_Atomic_t count; /*!< Number of threads remaining */
+ int threshold; /*!< Total number of threads */
+ volatile int cycle; /*!< Current cycle (alternating 0/1) */
+ TMPI_YIELD_WAIT_DATA
+};
+
+
/** Initialize barrier
*
* the same datatype as the full, thread based, barrier.
* \param count Number of threads to synchronize. All threads
* will be released after \a count calls to
- * tMPI_Spinlock_barrier_wait().
+ * tMPI_Barrier_wait().
*/
-void tMPI_Spinlock_barrier_init(tMPI_Spinlock_barrier_t *barrier, int count);
+void tMPI_Barrier_init(tMPI_Barrier_t *barrier, int count);
/** Perform yielding, busy-waiting barrier synchronization
*
* \return The last thread returns -1, all the others 0.
*/
-int tMPI_Spinlock_barrier_wait(tMPI_Spinlock_barrier_t *barrier);
+int tMPI_Barrier_wait(tMPI_Barrier_t *barrier);
#ifdef DOXYGEN
*
* \return the number of threads to synchronize
*/
-int tMPI_Spinlock_barrier_N(tMPI_Spinlock_barrier_t *barrier);
+int tMPI_Barrier_N(tMPI_Barrier_t *barrier);
#else
-#define tMPI_Spinlock_barrier_N(barrier) ((barrier)->threshold)
+#define tMPI_Barrier_N(barrier) ((barrier)->threshold)
#endif
#endif
-#include "thread_mpi/atomic.h"
+#include "atomic.h"
typedef struct
{
#ifndef _TMPI_EVENT_H_
#define _TMPI_EVENT_H_
+#include "wait.h"
+
/*! \file
\brief Event notification wait and signaling functions.
This structure allows notification of a single thread by any number of
threads*/
-typedef struct tMPI_Event tMPI_Event;
+typedef struct tMPI_Event_t tMPI_Event;
+struct tMPI_Event_t
+{
+ tMPI_Atomic_t sync; /* the event sync counter */
+ int last_sync; /* the last sync event looked at */
+ TMPI_YIELD_WAIT_DATA /* data associated with yielding */
+};
+
/*! \brief Initialize the event object.
#ifndef _TMPI_LIST_H_
#define _TMPI_LIST_H_
-#include "thread_mpi/atomic.h"
+#include "atomic.h"
/** \file
files.
*/
+#ifndef _TMPI_FASTLOCK_H_
+#define _TMPI_FASTLOCK_H_
-struct tMPI_Event
+#include "wait.h"
+
+/** Fast (possibly busy-wait-based) lock type
+ *
+ * This lock type forms an intermediate between the spinlocks and mutexes:
+ * it is based on a busy-wait loop, but yields to the scheduler if the lock
+ * is locked. This is therefore the preferred type of lock for when waits
+ * are expected to be reasonably short.
+ *
+ * Variables of this type should be initialized by calling
+ * tMPI_Lock_init().
+ *
+ * \see
+ * - tMPI_Lock_init
+ * - tMPI_Lock_lock
+ */
+typedef struct tMPI_Lock tMPI_Lock_t;
+struct tMPI_Lock
{
- tMPI_Atomic_t sync; /* the event sync counter */
- int last_sync; /* the last sync event looked at */
- TMPI_YIELD_WAIT_DATA /* data associated with yielding */
+ tMPI_Spinlock_t lock; /*!< The underlying spin lock */
+ TMPI_YIELD_WAIT_DATA
};
+/** Initialize lock
+ *
+ * \param lock Pointer to the new lock.
+ */
+void tMPI_Lock_init(tMPI_Lock_t *lock);
+
+
+/** Perform yielding, busy-waiting locking
+ *
+ * This function blocks until the lock is locked.
+ *
+ * \param lock Pointer to previously created lock.
+ */
+void tMPI_Lock_lock(tMPI_Lock_t *lock);
+
+/** Unlock the lock
+ *
+ * \param lock Pointer to previously created lock.
+ */
+void tMPI_Lock_unlock(tMPI_Lock_t *lock);
+
+/** Try to lock the lock but don't block if it is locked.
+ *
+ * \param lock Pointer to previously created lock.
+ */
+int tMPI_Lock_trylock(tMPI_Lock_t *lock);
+
+/** Check the status of the lock without affecting its state
+ *
+ * \param lock Pointer to previously created lock.
+ */
+int tMPI_Lock_islocked(const tMPI_Lock_t *lock);
+
+
+
+#endif
#define MPI_ANY_SOURCE TMPI_ANY_SOURCE
#define MPI_ANY_TAG TMPI_ANY_TAG
+/* comm_compare defines */
+#define MPI_IDENT TMPI_IDENT
+#define MPI_CONGRUENT TMPI_CONGRUENT
+#define MPI_SIMILAR TMPI_SIMILAR
+#define MPI_UNEQUAL TMPI_UNEQUAL
+
+
/* topology test defines */
#define MPI_CART TMPI_CART
#define MPI_GRAPH TMPI_GRAPH
#define MPI_Comm_size tMPI_Comm_size
#define MPI_Comm_rank tMPI_Comm_rank
+#define MPI_Comm_compare tMPI_Comm_compare
#define MPI_Comm_free tMPI_Comm_free
#define MPI_Comm_create tMPI_Comm_create
#define MPI_Comm_split tMPI_Comm_split
#include <stdio.h>
-#include "thread_mpi/atomic.h"
+#include "atomic.h"
#ifdef __cplusplus
} /* Avoids screwing up auto-indentation */
#endif
-/*#include "thread_mpi/threads.h"
-#include "thread_mpi/atomic.h"*/
/** tMPI Communicator
/** pre-defined error handler that tries to continue on every error */
extern tMPI_Errhandler TMPI_ERRORS_RETURN;
+/*! \name tMPI_Comm_compare() return codes */
+/*! \{ */
+/** Identical comms*/
+#define TMPI_IDENT 0
+/** Comms with the same members in the same order*/
+#define TMPI_CONGRUENT 1
+/** Comms with the same members in the different order*/
+#define TMPI_SIMILAR 2
+/** Comms with the different members */
+#define TMPI_UNEQUAL 3
+/*! \} */
+
/** Source number wildcard so tMPI_Recv(), etc. can receive from
any source. */
If N==0, the number of threads will be the recommended number of
threads for this platform as obtained from tMPI_Get_recommended_ntreads().
-
- \param[in] N The number of threads to start (or 0 to
- automatically determine this).
- \param[in] start_function The function to start threads at (including
- main thread).
- \param[in] arg An optional argument for start_function().
-
- \return TMPI_FAILURE on failure, TMPI_SUCCESS on succes, after all
- threads have finished.
- */
-int tMPI_Init_fn(int N, void (*start_function)(void*), void *arg);
+ \param[in] main_thread_returns whether the control in the main thread
+ should return immediately (if true), or
+ the start_function() should be called
+ from the main thread, too (if false).
+ \param[in] N The number of threads to start (or 0 to
+ automatically determine this).
+ \param[in] start_function The function to start threads at
+ (including main thread if
+ main_thread_returns).
+ \param[in] arg An optional argument for start_function().
+
+ \return TMPI_FAILURE on failure, TMPI_SUCCESS on succes (after all
+ threads have finished if main_thread_returns=true). */
+int tMPI_Init_fn(int main_thread_returns, int N,
+ void (*start_function)(void*), void *arg);
/** get the number of threads from the command line
can be called before tMPI_Init()
- \param[in] argc argc from main()
- \param[in] argv argv from main()
- \param[in] optname name of the argument specifying the number of
- threads to run. If this is NULL, this function
- will read the first argument and interpret
- it as the number of threads.
- \param[out] nthreads the number of threads
+ \param[in] argc argc from main()
+ \param[in] argv argv from main()
+ \param[in] optname name of the argument specifying the
+ number of threads to run. If this is
+ NULL, this function will read the first
+ argument and interpret it as the number
+ of threads.
+ \param[out] nthreads the number of threads
\return TMPI_SUCCESS on success, TMPI_FAILURE on failure. */
int tMPI_Get_N(int *argc, char ***argv, const char *optname, int *nthreads);
\return TMPI_SUCCESS on success, TMPI_FAILURE on failure. */
int tMPI_Comm_rank(tMPI_Comm comm, int *rank);
+/** Compare two comms. Returns TMPI_IDENT if the two comms point to
+ the same underlying comm structure, TMPI_CONGRUENT if all
+ members appear in the both comms in the same order, TMPI_SIMILAR
+ if both comms have the smae members but not in the same order, or
+ TMPI_UNEQUAL if the comms have different members.
+
+ \param[in] comm1 The first comm to compare.
+ \param[in] comm2 The second comm to compare.
+ \param[out] result The output result, one of the values
+ described above.
+ \return TMPI_SUCCESS on success, TMPI_FAILURE on failure. */
+int tMPI_Comm_compare(tMPI_Comm comm1, tMPI_Comm comm2, int *result);
+
+
/** De-allocate a comm
Collective function.
*
**************************************************************/
#include "typedefs.h"
+#include "gmxfio.h"
#ifdef __cplusplus
extern "C" {
* but double and single precision can be read by either.
*/
-extern int open_tpx(const char *fn, const char *mode);
-/* Return an integer corresponding to the file you have just opened */
+extern t_fileio *open_tpx(const char *fn, const char *mode);
+/* Return an file pointer corresponding to the file you have just opened */
-extern void close_tpx(int fp);
-/* Close the file corresponding to fp */
+extern void close_tpx(t_fileio *fio);
+/* Close the file corresponding to fio */
extern void read_tpxheader(const char *fn, t_tpxheader *tpx, bool TopOnlyOK,
int *version, int *generation);
* else if bMass=TRUE, read the masses into top.atoms from the mass database.
*/
-void
-tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols);
+void tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols);
#ifdef __cplusplus
}
**************************************************************/
#include "typedefs.h"
+#include "gmxfio.h"
#ifdef __cplusplus
extern "C" {
real lambda; /* Current value of lambda */
} t_trnheader;
-extern int open_trn(const char *fn,const char *mode);
+extern t_fileio *open_trn(const char *fn,const char *mode);
/* Open a trj / trr file */
-extern void close_trn(int fp);
+extern void close_trn(t_fileio *fio);
/* Close it */
-extern bool fread_trnheader(int fp,t_trnheader *trn,bool *bOK);
+extern bool fread_trnheader(t_fileio *fio,t_trnheader *trn,bool *bOK);
/* Read the header of a trn file. Return FALSE if there is no frame.
* bOK will be FALSE when the header is incomplete.
*/
* afterwards.
*/
-extern void fwrite_trn(int fp,int step,real t,real lambda,
+extern void fwrite_trn(t_fileio *fio,int step,real t,real lambda,
rvec *box,int natoms,rvec *x,rvec *v,rvec *f);
/* Write a trn frame to file fp, box, x, v, f may be NULL */
-extern bool fread_htrn(int fp,t_trnheader *sh,
+extern bool fread_htrn(t_fileio *fio,t_trnheader *sh,
rvec *box,rvec *x,rvec *v,rvec *f);
/* Extern read a frame except the header (that should be pre-read,
* using routine read_trnheader, see above) from a trn file.
* Return FALSE on error
*/
-extern bool fread_trn(int fp,int *step,real *t,real *lambda,
+extern bool fread_trn(t_fileio *fio,int *step,real *t,real *lambda,
rvec *box,int *natoms,rvec *x,rvec *v,rvec *f);
/* Read a trn frame, including the header from fp. box, x, v, f may
* be NULL, in which case the data will be skipped over.
#include <sys/types.h>
#include <sysstuff.h>
-#include <types/simple.h>
-#include <types/enums.h>
-#include <types/block.h>
-#include <types/symtab.h>
-#include <types/idef.h>
-#include <types/atoms.h>
-#include <types/trx.h>
-#include <types/topology.h>
-#include <types/energy.h>
-#include <types/inputrec.h>
-#include <types/ishift.h>
-#include <types/graph.h>
-#include <types/nrnb.h>
-#include <types/nblist.h>
-#include <types/nsgrid.h>
-#include <types/commrec.h>
-#include <types/forcerec.h>
-#include <types/fcdata.h>
-#include <types/mdatom.h>
-#include <types/pbc.h>
-#include <types/ifunc.h>
-#include <types/filenm.h>
-#include <types/group.h>
-#include <types/state.h>
-#include <types/shellfc.h>
-#include <types/constr.h>
-#include <types/matrix.h>
-#include <types/oenv.h>
+#include "types/simple.h"
+#include "types/enums.h"
+#include "types/block.h"
+#include "types/symtab.h"
+#include "types/idef.h"
+#include "types/atoms.h"
+#include "types/trx.h"
+#include "types/topology.h"
+#include "types/energy.h"
+#include "types/inputrec.h"
+#include "types/ishift.h"
+#include "types/graph.h"
+#include "types/nrnb.h"
+#include "types/nblist.h"
+#include "types/nsgrid.h"
+#include "types/commrec.h"
+#include "types/forcerec.h"
+#include "types/fcdata.h"
+#include "types/mdatom.h"
+#include "types/pbc.h"
+#include "types/ifunc.h"
+#include "types/filenm.h"
+#include "types/group.h"
+#include "types/state.h"
+#include "types/shellfc.h"
+#include "types/constr.h"
+#include "types/matrix.h"
+#include "types/oenv.h"
#ifdef __cplusplus
extern "C" {
*/
void free_t_atoms(t_atoms *atoms,bool bFreeNames);
-/* free all the arrays and set the nr and nres to 0 */
+/* Free all the arrays and set the nr and nres to 0.
+ * bFreeNames tells if to free the atom and residue name strings,
+ * don't free them if they still need to be used in e.g. the topology struct.
+ */
t_atoms *mtop2atoms(gmx_mtop_t *mtop);
/* generate a t_atoms struct for the system from gmx_mtop_t */
* And Hey:
* GRoups of Organic Molecules in ACtion for Science
*/
+#ifndef _commrec_h
+#define _commrec_h
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef GMX_LIB_MPI
#include <mpi.h>
-#endif
+#else
#ifdef GMX_THREADS
-#include "tmpi.h"
+#include "../tmpi.h"
+#else
+typedef void* MPI_Comm;
+typedef void* MPI_Request;
+typedef void* MPI_Group;
+#endif
#endif
#include "idef.h"
} gmx_ddbox_t;
-#if defined(GMX_MPI) && !defined(GMX_THREADS) && !defined(MPI_IN_PLACE_EXISTS)
typedef struct {
/* these buffers are used as destination buffers if MPI_IN_PLACE isn't
supported.*/
double *dbuf; /* for doubles */
int dbuf_alloc;
} mpi_in_place_buf_t;
-#endif
typedef struct {
* defined in dd->comm in domdec.c
*/
int nnodes;
-#ifdef GMX_MPI
MPI_Comm mpi_comm_all;
-#endif
/* Use MPI_Sendrecv communication instead of non-blocking calls */
bool bSendRecv2;
/* The local DD cell index and rank */
int pme_nodeid;
bool pme_receive_vir_ener;
gmx_pme_comm_n_box_p_t cnb;
-#ifdef GMX_MPI
int nreq_pme;
MPI_Request req_pme[4];
-#endif
/* The communication setup, identical for each cell, cartesian index */
typedef struct {
int nsim;
int sim;
-#ifdef GMX_MPI
MPI_Group mpi_group_masters;
MPI_Comm mpi_comm_masters;
-#if !defined(GMX_THREADS) && !defined(MPI_IN_PLACE_EXISTS)
/* these buffers are used as destination buffers if MPI_IN_PLACE isn't
supported.*/
mpi_in_place_buf_t *mpb;
-#endif
-#endif
} gmx_multisim_t;
#define DUTY_PP (1<<0)
typedef struct {
int bUse;
-#ifdef GMX_MPI
MPI_Comm comm_intra;
int rank_intra;
MPI_Comm comm_inter;
-#endif
} gmx_nodecomm_t;
} gmx_commrec_thread_t;
typedef struct {
- /* The nodids in one sim are numbered sequentially from 0.
+ /* The nodeids in one sim are numbered sequentially from 0.
* All communication within some simulation should happen
* in mpi_comm_mysim, or its subset mpi_comm_mygroup.
*/
int sim_nodeid,nnodes,npmenodes;
- int threadid,nthreads;
+
+ /* thread numbers: */
+ int threadid, nthreads;
/* The nodeid in the PP/PME, PP or PME group */
int nodeid;
-#ifdef GMX_MPI
MPI_Comm mpi_comm_mysim;
MPI_Comm mpi_comm_mygroup;
-#endif
#ifdef GMX_THREAD_SHM_FDECOMP
gmx_commrec_thread_t thread;
gmx_multisim_t *ms;
-#if defined(GMX_MPI) && !defined(GMX_THREADS) && !defined(MPI_IN_PLACE_EXISTS)
/* these buffers are used as destination buffers if MPI_IN_PLACE isn't
supported.*/
mpi_in_place_buf_t *mpb;
-#endif
} t_commrec;
#define MASTERNODE(cr) ((cr)->nodeid == 0)
#ifdef __cplusplus
}
#endif
-
+#endif
#include <config.h>
#endif
+#include <types/commrec.h>
+
#ifdef __cplusplus
extern "C" {
#endif
real *Rt_6; /* The calculated inst. ens. averaged r^-6 (nr) */
real *Rtav_6; /* The calculated time and ens. averaged r^-6 (nr) */
int nsystems; /* The number of systems for ensemble averaging */
-#ifdef GMX_MPI
MPI_Comm mpi_comm_ensemble; /* For ensemble averaging */
-#endif
} t_disresdata;
rvec5 *tmp; /* An array of temporary 5-vectors (nex); */
real ***TMP; /* An array of temporary 5x5 matrices (nex); */
real *eig; /* Eigenvalues/vectors, for output only (nex x 12) */
+
+ /* variables for diagonalization with diagonalize_orires_tensors()*/
+ double **M;
+ double *eig_diag;
+ double **v;
} t_oriresdata;
/*
* function to use. Every "bond" with the same function but different
* force parameters is a different force type. The type identifier in the
* forceatoms[] array is an index in this array.
- t_iparams *iparams;
+ * t_iparams *iparams
* array of length ntypes, defines the parameters for every interaction
* type. The type identifier in the actual interaction list
- * (bondeds.iatoms[] or shakes.iatoms[]) is an index in this array.
+ * (ilist[ftype].iatoms[]) is an index in this array.
+ * gmx_cmap_t cmap_grid
+ * the grid for the dihedral pair correction maps.
+ * t_iparams *iparams_posres
+ * defines the parameters for position restraints only.
+ * Position restraints are the only interactions that have different
+ * parameters (reference positions) for different molecules
+ * of the same type. ilist[F_POSRES].iatoms[] is an index in this array.
* t_ilist il[F_NRE]
* The list of interactions for each type. Note that some,
* such as LJ and COUL will have 0 entries.
#endif
-#include "types/simple.h"
+#include "simple.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
- int nrQMatoms; /* total nr of QM atoms */
- rvec *xQM; /* shifted to center of box */
- int *indexQM; /* atom i = atom indexQM[i] in mdrun */
- int *atomicnumberQM;/* atomic numbers of QM atoms */
- real *QMcharges; /* atomic charges of QM atoms(ONIOM) */
- int *shiftQM;
- int QMcharge; /* charge of the QM system */
- int multiplicity; /* multipicity (no of unpaired eln) */
- int QMmethod; /* see enums.h for all methods */
- int QMbasis; /* see enums.h for all bases */
- int nelectrons; /* total number of elecs in QM region*/
- bool bTS; /* Optimize a TS, only steep, no md */
- bool bOPT; /* Optimize QM subsys, only steep, no md */
- bool *frontatoms; /* qm atoms on the QM side of a QM-MM bond */
- /* Gaussian specific stuff */
- int nQMcpus; /* no. of CPUs used for the QM calc. */
- int QMmem; /* memory for the gaussian calc. */
- int accuracy; /* convergence criterium (E(-x)) */
- bool cpmcscf; /* using cpmcscf(l1003)*/
- char *gauss_dir;
- char *gauss_exe;
- char *devel_dir;
- real *c6;
- real *c12;
- /* Surface hopping stuff */
- bool bSH; /* surface hopping (diabatic only) */
- real SAon; /* at which energy gap the SA starts */
- real SAoff; /* at which energy gap the SA stops */
- int SAsteps; /* stepwise switchinng on the SA */
- int SAstep; /* current state of SA */
- int CIdim;
- real *CIvec1;
- real *CIvec2;
- real *CIvec1old;
- real *CIvec2old;
- ivec SHbasis;
- int CASelectrons;
- int CASorbitals;
+ int nrQMatoms; /* total nr of QM atoms */
+ rvec *xQM; /* shifted to center of box */
+ int *indexQM; /* atom i = atom indexQM[i] in mdrun */
+ int *atomicnumberQM;/* atomic numbers of QM atoms */
+ real *QMcharges; /* atomic charges of QM atoms(ONIOM) */
+ int *shiftQM;
+ int QMcharge; /* charge of the QM system */
+ int multiplicity; /* multipicity (no of unpaired eln) */
+ int QMmethod; /* see enums.h for all methods */
+ int QMbasis; /* see enums.h for all bases */
+ int nelectrons; /* total number of elecs in QM region*/
+ bool bTS; /* Optimize a TS, only steep, no md */
+ bool bOPT; /* Optimize QM subsys, only steep, no md */
+ bool *frontatoms; /* qm atoms on the QM side of a QM-MM bond */
+ /* Gaussian specific stuff */
+ int nQMcpus; /* no. of CPUs used for the QM calc. */
+ int QMmem; /* memory for the gaussian calc. */
+ int accuracy; /* convergence criterium (E(-x)) */
+ bool cpmcscf; /* using cpmcscf(l1003)*/
+ char *gauss_dir;
+ char *gauss_exe;
+ char *devel_dir;
+ char *orca_basename; /* basename for I/O with orca */
+ real *c6;
+ real *c12;
+ /* Surface hopping stuff */
+ bool bSH; /* surface hopping (diabatic only) */
+ real SAon; /* at which energy gap the SA starts */
+ real SAoff; /* at which energy gap the SA stops */
+ int SAsteps; /* stepwise switchinng on the SA */
+ int SAstep; /* current state of SA */
+ int CIdim;
+ real *CIvec1;
+ real *CIvec2;
+ real *CIvec1old;
+ real *CIvec2old;
+ ivec SHbasis;
+ int CASelectrons;
+ int CASorbitals;
} t_QMrec;
typedef struct {
*/
/* for now, define the length of the NH chains here */
-#define NHCHAINLENGTH 5
+#define NHCHAINLENGTH 10
/* These enums are used in flags as (1<<est...).
* The order of these enums should not be changed,
*/
#define ggrpnr(groups,egc,i) ((groups)->grpnr[egc] ? (groups)->grpnr[egc][i] : 0)
-/* The global topology struct, based on molecule types */
+/* The global, complete system topology struct, based on molecule types */
typedef struct {
char **name; /* Name of the topology */
gmx_ffparams_t ffparams;
t_symtab symtab; /* The symbol table */
} gmx_mtop_t;
-/* The mdrun local topology struct, completely written out */
+/* The mdrun node-local topology struct, completely written out */
typedef struct {
t_idef idef; /* The interaction function definition */
t_atomtypes atomtypes; /* Atomtype properties */
* not be allocated.
*/
-#include "molfile_plugin.h"
-#include "vmdio.h"
+#include "../molfile_plugin.h"
+#include "../vmdio.h"
#ifdef __cplusplus
extern "C" {
extern void destroy_bufstate(t_state *state);
-extern void trotter_update(t_inputrec *ir,gmx_ekindata_t *ekind, gmx_enerdata_t *enerd,
+extern void trotter_update(t_inputrec *ir,gmx_large_int_t step,
+ gmx_ekindata_t *ekind, gmx_enerdata_t *enerd,
t_state *state, tensor vir, t_mdatoms *md,
t_extmass *MassQ, int *trotter_seq);
* versions if your hardware supports it.
*
* To use those routines, your memory HAS TO BE CACHE-ALIGNED.
- * Start by allocating 31 bytes more than you need, put
- * this in a temp variable (e.g. _buf, so you can free it later), and
- * create your aligned array buf with
- *
- * buf=(real *) ( ( (unsigned long int)_buf + 31 ) & (~0x1f) );
+ * Use snew_aligned(ptr,size,32) to allocate and sfree_aligned to free.
*/
gmx_angle(const rvec a, const rvec b)
{
rvec w;
- real wlen,s,theta;
+ real wlen,s;
cprod(a,b,w);
bool bV;
} t_gmxvmdplugin;
-int read_first_vmd_frame(int *status,const char *fn, struct trxframe *fr,int flags);
+int read_first_vmd_frame(int *status,const char *fn, struct trxframe *fr,int flags);
bool read_next_vmd_frame(int status,struct trxframe *fr);
int load_vmd_library(const char *fn, t_gmxvmdplugin *vmdplugin);
extern "C" {
#endif
-int xdropen(XDR *xdrs, const char *filename, const char *type);
-
+/* THESE 3 FUNCTIONS (xdropen, xdrclose and xdr_get_fp) ARE NOW OBSOLETE
+ AND ONLY PROVIDED FOR BACKWARD COMPATIBILITY OF 3D PARTY TOOLS.
+ THEY SHOULD NOT BE USED ANYWHERE IN GROMACS ITSELF.
+int xdropen(XDR *xdrs, const char *filename, const char *type);
int xdrclose(XDR *xdrs);
+*/
-FILE * xdr_get_fp(int xdrid);
/* Read or write reduced precision *float* coordinates */
-int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision);
+int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision, bool bRead);
/* Read or write a *real* value (stored as float) */
/* Read or write reduced precision *real* coordinates */
-int xdr3drcoord(XDR *xdrs,real *fp,int *size,real *precision);
+int xdr3drcoord(XDR *xdrs,real *fp,int *size,real *precision, bool bRead);
extern int xdr_gmx_large_int(XDR *xdrs,gmx_large_int_t *i,const char *warn);
#include "typedefs.h"
+#include "gmxfio.h"
#include "xdrf.h"
#ifdef __cplusplus
extern "C" {
#endif
-/* All functions return 1 if succesfull, 0 otherwise
+/* All functions return 1 if successful, 0 otherwise
* bOK tells if a frame is not corrupted
*/
-extern int open_xtc(const char *filename,const char *mode);
+extern t_fileio *open_xtc(const char *filename,const char *mode);
/* Open a file for xdr I/O */
-extern void close_xtc(int fp);
+extern void close_xtc(t_fileio *fio);
/* Close the file for xdr I/O */
-extern int read_first_xtc(int fp,
+extern int read_first_xtc(t_fileio *fio,
int *natoms,int *step,real *time,
matrix box,rvec **x,real *prec,bool *bOK);
/* Open xtc file, read xtc file first time, allocate memory for x */
-extern int read_next_xtc(int fp,
+extern int read_next_xtc(t_fileio *fio,
int natoms,int *step,real *time,
matrix box,rvec *x,real *prec,bool *bOK);
/* Read subsequent frames */
-extern int write_xtc(int fp,
+extern int write_xtc(t_fileio *fio,
int natoms,int step,real time,
matrix box,rvec *x,real prec);
/* Write a frame to xtc file */
# taken directly from ifp43a1.dat. For a description of what the numbers
# mean, see the GROMOS96 manual and the fie ifp43a1.dat
-# set the input seperator to #--- so we read one atom entry at a time
-# make sure the records are actually seperated by #---\n and not by say #--\n!!
-# don't put a seperator at the end of the file, only between records
+# set the input separator to #--- so we read one atom entry at a time
+# make sure the records are actually separated by #---\n and not by say #--\n!!
+# don't put a separator at the end of the file, only between records
$/= "#---\n";
# start arrays with 1 instead of 0
f.getRESname(f.all[resnum]) # residue name
f.getNATOM (f.all[resnum]) # number of atoms
- if f.nlin != 0: # 0 for a seperate molecule
+ if f.nlin != 0: # 0 for a separate molecule
f.getEXCLUS(f.all[resnum]) # number of exclusions
f.getATOM (f.all[resnum]) # atoms => f.atoms
<dt><b>md</b></dt>
<dd>A <!--Idx-->leap-frog<!--EIdx--> algorithm for integrating Newton's
equations of motion.</dd>
+<dt><b>md-vv</b></dt>
+<dd>A velocity Verlet algorithm for integrating Newton's equations of motion.
+For constant NVE simulations started from corresponding points in the same trajectory, the trajectories
+are analytically, but not binary, identical to the <b>md</b> leap-frog integrator. The the kinetic
+energy, which is determined from the whole step velocities and is therefore
+slightly too high. The advantage of this integrator is more accurate,
+reversible Nose-Hoover and Parrinello-Rahman coupling integration
+based on Trotter expansion, as well as (slightly too small) full step velocity
+output. This all comes at the cost off extra computation, especially with
+constraints and extra communication in parallel. Note that for nearly all
+production simulations the <b>md</b> integrator is accurate enough.
+</dd>
+<dt><b>md-vv-avek</b></dt>
+<dd>A velocity Verlet algorithm identical to <b>md-vv</b>, except that
+the kinetic energy is determined as the average of
+the two half step kinetic energies as in the <b>md</b> integrator, and this thus more accurate.
+With Nose-Hoover and/or Parrinello-Rahman coupling this comes with
+a slight increase in computational cost.
+</dd>
<dt><b>sd</b></dt>
<dd> An accurate leap-frog stochastic dynamics integrator.
Four Gaussian random number are required
<dd>time step for integration (only makes sense for integrators <tt>md</tt>,
<tt>sd</tt> and <tt>bd</tt>)</dd>
<dt><h4>nsteps: (0)</h4></dt>
-<dd>maximum number of steps to integrate</dd>
+<dd>maximum number of steps to integrate or minimize, -1 is no maximum</dd>
<dt><h4>init_step: (0)</h4></dt>
<dd>The starting step.
The time at an step i in a run is calculated as: t = <tt>tinit</tt> + <tt>dt</tt>*(<tt>init_step</tt> + i).
set <tt>init_step</tt> to the step number of the restart frame.
<tt>tpbconv</tt> does this automatically.
</dd>
-<dt><h4>nstcalcenergy: (1)</h4></dt>
+<dt><h4>nstcalcenergy: (-1)</h4></dt>
<dd>The frequency for calculating the energies, including the temperature
and the pressure, 0 is never.
This option is only relevant with dynamics.
processes which can become a bottleneck at high parallelization.
With global temperature and/or pressure coupling the time step for
the coupling algorithm is <b>nstcalcenergy</b>*<b>dt</b>.
-Take this into account when setting <b>tau_t</b> and/or <b>tau_p</b>.</dd>
+Take this into account when setting <b>tau_t</b> and/or <b>tau_p</b>.
+The default value of -1 sets <b>nstcalcenergy</b> equal to <b>nstlist</b>,
+unless <b>nstlist</b> &le 0, then a value of 10 is used;
+for velocity Verlet integrators <b>nstcalcenergy</b> is set to 1.</dd>
<dt><h4>comm_mode:</h4></dt>
<dd><dl compact>
<dt><b>Linear</b></dt>
<dt><b>No</b></dt>
<dd>No restriction on the center of mass motion
</dl></dd>
-<dt><h4>nstcomm: (1) [steps]</h4></dt>
+<dt><h4>nstcomm: (10) [steps]</h4></dt>
<dd>frequency for center of mass motion removal</dd>
<dt><h4>comm_grps:</h4></dt>
<dd>group(s) for center of mass motion removal, default is the whole system</dd>
<dd>frequency to write forces to output trajectory.</dd>
<dt><h4>nstlog: (100) [steps]</h4></dt>
<dd>frequency to write energies to <!--Idx-->log file<!--EIdx-->,
-the last energies are always written,
-should be a multiple of <b>nstcalcenergy</b></dd>
+the last energies are always written</dd>
<dt><h4>nstenergy: (100) [steps]</h4></dt>
<dd>frequency to write energies to energy file,
the last energies are always written,
Reasonable grid spacing for PPPM is 0.05-0.1 nm.
See <tt>Shift</tt> for the details of the particle-particle potential.
<br>
-NOTE: the pressure in incorrect when using PPPM.</dd>
+NOTE: PPPM is not functional in the current version, we plan to implement
+PPPM through a small modification of the PME code.</dd>
<dt><b><!--Idx-->Reaction-Field<!--EIdx--></b></dt>
<dd>Reaction field with Coulomb cut-off <b>rcoulomb</b>,
Several groups can be coupled separately, these are specified in the
<b>tc_grps</b> field separated by spaces.</dd>
<dt><b>nose-hoover</b></dt>
-<dd>Temperature coupling with a by using a Nose-Hoover extended
+<dd>Temperature coupling using a Nose-Hoover extended
ensemble. The reference temperature and coupling groups are selected
as above, but in this case <b>tau_t</b> [ps] controls the period
of the temperature fluctuations at equilibrium, which is slightly
For NVT simulations the conserved energy quantity is written
to the energy and log file.</dd>
</dl>
-
+<dt><h4>nh-chain-length (10)</h4></dt>
+<dd>the number of chained Nose-Hoover thermostats for velocity Verlet integrators, the leap-frog <b>md</b> integrator only supports 1. Data for the NH chain variables is not printed to the .edr, but can be using the GMX_NOSEHOOVER_CHAINS environment variable</dd>
<dt><h4>tc_grps:</h4></dt>
<dd>groups to couple separately to temperature bath</dd>
<dt><h4>tau_t: [ps]</h4></dt>
but it is the most efficient way to scale a box at the beginning
of a run.</dd>
<dt><b>Parrinello-Rahman</b></dt>
-<dd>Extended-ensemble pressure coupling where the box vectors
-are subject to an equation of motion. The equation of motion for
-the atoms is coupled to this. No instantaneous scaling takes place.
+<dd>Extended-ensemble pressure coupling where the box vectors are
+subject to an equation of motion. The equation of motion for the atoms
+is coupled to this. No instantaneous scaling takes place. As for
+Nose-Hoover temperature coupling the time constant <b>tau_p</b> [ps]
+is the period of pressure fluctuations at equilibrium. This is
+probably a better method when you want to apply pressure scaling
+during data collection, but beware that you can get very large
+oscillations if you are starting from a different pressure. For
+simulations where the exact fluctation of the NPT ensemble are
+important, or if the pressure coupling time is very short,it may not
+be appropriate, as the previous time step pressure is used in some
+steps of the gromacs implementation for the current time step pressure.</dd>
+</dl></dd>
+<dt><b>MTTK</b></dt>
+<dd>Martyna-Tuckerman-Tobias-Klein implementation, only useable with <b>md-vv</b>
+or <b>md-vv-avek</b>, very similar to Parinello-Raphman.
As for Nose-Hoover temperature coupling the time constant <b>tau_p</b>
[ps] is the period of pressure fluctuations at equilibrium. This is
probably a better method when you want to apply pressure scaling
during data collection, but beware that you can get very large
-oscillations if you are starting from a different pressure.</dd>
+oscillations if you are starting from a different pressure. Currently only supports isotropic scaling.</dd>
</dl></dd>
</dl>
For determining the COM, all atoms in the group are put at their periodic image
which is closest to <b>pull_pbcatom1</b>.
A value of 0 means that the middle atom (number wise) is used.
-This parameter is not used with geometry <b>cylinder</b>.</dd>
+This parameter is not used with geometry <b>cylinder</b>.
+A value of -1 turns on cosine weighting, which is useful for a group
+of molecules in a periodic system, e.g. a water slab (see Engin et al.
+J. Chem. Phys. B 2010).</dd>
<dt><h4>pull_vec1: (0.0 0.0 0.0)</h4></dt>
<dd>The pull direction. <tt>grompp</tt> normalizes the vector.</dd>
<dt><h4>pull_init1: (0.0) / (0.0 0.0 0.0) [nm]</h4></dt>
restraint information in topology file)</dd>
<dt><b>simple</b></dt>
<dd>simple (per-molecule) distance restraints,
-ensemble averaging can be performed with <tt>mdrun -multi</tt></dd>
+ensemble averaging can be performed with <tt>mdrun -multi</tt>
+where the environment variable GMX_DISRE_ENSEMBLE_SIZE sets the number
+of systems within each ensemble (usually equal to the mdrun -multi value)</dd>
<dt><b>ensemble</b></dt>
<dd>distance restraints over an ensemble of molecules in one simulation box,
-should only be used for special cases, such as dimers</dd>
+should only be used for special cases, such as dimers
+(this option is not fuctional in the current version of GROMACS)</dd>
</dl></dd>
<dt><h4>disre_weighting:</h4></dt>
<dd><dl compact>
<A HREF="#bond2">morse</A><br>
<A HREF="#em">nbfgscorr</A><br>
<A HREF="#xmdrun">niter</A><br>
+<A HREF="#tc">nh-chain-length</A><br>
<A HREF="#em">nstcgsteep</A><br>
<A HREF="#run">nstcalcenergy</A><br>
<A HREF="#run">nstcomm</A><br>
in sequence are usually close in space too (e.g. a water molecule).
To this end, the <i>xdr</i> library is extended with a special routine
to write 3-D float coordinates. This routine was written by Frans van Hoesel
-as part of an Europort project, and can be obtianed through <a href="http://hpcv100.rc.rug.nl/xdrf.html">this link</a>.
+as part of an Europort project, and can be obtained through <a href="http://hpcv100.rc.rug.nl/xdrf.html">this link</a>.
<p>
All the data is stored using calls to <i>xdr</i> routines.
<h3>Using xtc in your "C" programs</h3>
To read and write these files the following "C" routines are available:
<pre>
-/* All functions return 1 if succesfull, 0 otherwise */
+/* All functions return 1 if successful, 0 otherwise */
extern int open_xtc(XDR *xd,char *filename,char *mode);
/* Open a file for xdr I/O */
charmm27.ff
topol_DATA = \
- 1mlg.itp 2mlg.itp benzamide.itp bondadd.itp \
- buck.itp decane.itp dlg.itp dmso.itp \
- fa.itp ff_dum.itp flexspc.itp flexspce.itp \
- flexwat-ferguson.itp h2p4o13.itp h2p8o25.itp \
- h2po4.itp ions.itp methanol.itp spc.itp \
- spce.itp tfe.itp tip3p.itp tip4p.itp \
- urea.itp dgsolv.dat electroneg.dat \
- dec50.gro dmso.gro spc216.gro tip4p.gro \
- urea+h2o.gro \
+ ff_dum.itp flexspc.itp \
+ flexspce.itp flexwat-ferguson.itp ions.itp \
+ spc.itp spce.itp tip3p.itp tip4p.itp \
+ dgsolv.dat electroneg.dat \
+ spc216.gro tip4p.gro \
aminoacids.dat atommass.dat bromacs.dat ca-shift.dat \
cb-shift.dat co-shift.dat edissoc.dat \
gurgle.dat ha-shift.dat links.dat phbres.dat \
+++ /dev/null
-[ moleculetype ]
-; Name nrexcl
-Benz 3
-
-[ atoms ]
-; nr type resnr residu atom cgnr charge mass
- 1 CB 1 BEN C1 1 0 ; qtot: 0
- 2 CR6 1 BEN C2 2 -0.14 ; qtot: -0.14
- 3 HCR 1 BEN H2 2 0.14 ; qtot: 0
- 4 CR6 1 BEN C3 3 -0.14 ; qtot: -0.14
- 5 HCR 1 BEN H3 3 0.14 ; qtot: 0
- 6 CR6 1 BEN C4 4 -0.14 ; qtot: -0.14
- 7 HCR 1 BEN H4 4 0.14 ; qtot: 0
- 8 CR6 1 BEN C5 5 -0.14 ; qtot: -0.14
- 9 HCR 1 BEN H5 5 0.14 ; qtot: 0
- 10 CR6 1 BEN C6 6 -0.14 ; qtot: -0.14
- 11 HCR 1 BEN H6 6 0.14 ; qtot: 0
- 12 C 1 BEN C7 7 0.56 ; qtot: 0.56
- 13 NZ 1 BEN N1 7 -0.26 ; qtot: 0.3
- 14 H 1 BEN H11 7 0.24 ; qtot: 0.54
- 15 H 1 BEN H12 7 0.24 ; qtot: 0.78
- 16 NZ 1 BEN N2 7 -0.26 ; qtot: 0.52
- 17 H 1 BEN H21 7 0.24 ; qtot: 0.76
- 18 H 1 BEN H22 7 0.24 ; qtot: 1
-
-[ bonds ]
-; ai aj funct
- 1 2 1
- 1 10 1
- 1 12 1
- 2 3 1
- 2 4 1
- 4 5 1
- 4 6 1
- 6 7 1
- 6 8 1
- 8 9 1
- 8 10 1
- 10 11 1
- 12 13 1
- 12 16 1
- 13 14 1
- 13 15 1
- 16 17 1
- 16 18 1
-
-[ pairs ]
-; ai aj funct
- 1 5 1
- 1 6 1
- 1 9 1
- 1 14 1
- 1 15 1
- 1 17 1
- 1 18 1
- 2 7 1
- 2 8 1
- 2 11 1
- 2 13 1
- 2 16 1
- 3 6 1
- 3 10 1
- 3 12 1
- 4 9 1
- 4 10 1
- 4 12 1
- 5 8 1
- 6 11 1
- 7 10 1
- 8 12 1
- 10 13 1
- 10 16 1
- 11 12 1
- 13 17 1
- 13 18 1
- 14 16 1
- 15 16 1
-
-[ angles ]
-; ai aj ak funct
- 2 1 10 1
- 2 1 12 1
- 10 1 12 1
- 1 2 3 1
- 1 2 4 1
- 3 2 4 1
- 2 4 5 1
- 2 4 6 1
- 5 4 6 1
- 4 6 7 1
- 4 6 8 1
- 7 6 8 1
- 6 8 9 1
- 6 8 10 1
- 9 8 10 1
- 1 10 8 1
- 1 10 11 1
- 8 10 11 1
- 1 12 13 1 120. 400.
- 1 12 16 1 120. 400.
- 13 12 16 1
- 12 13 14 1
- 12 13 15 1
- 14 13 15 1
- 12 16 17 1
- 12 16 18 1
- 17 16 18 1
-
-[ dihedrals ]
-; ai aj ak al funct
- 1 12 13 14 1
- 1 12 16 17 1
-
-[ dihedrals ]
-; ai aj ak al funct
- 1 2 4 6 2
- 1 10 2 12 2
- 2 1 4 3 2
- 2 1 10 8 2
- 2 4 6 8 2
- 2 1 12 13 2 0.0 167.0
- 4 2 6 5 2
- 4 6 8 10 2
- 6 8 10 1 2
- 6 4 8 7 2
- 8 10 1 2 2
- 8 6 10 9 2
- 10 1 2 4 2
- 10 8 1 11 2
- 10 1 12 16 2 0.0 167.0
- 12 13 16 1 2
- 13 14 15 12 2
- 16 17 18 12 2
-
+++ /dev/null
-[ dihedraltypes ]
-CP2 CP2 3 9.2789 12.156 -13.120 -3.0597 26.240 -31.495
-CH2 CH2 3 9.2789 12.156 -13.120 -3.0597 26.240 -31.495
+++ /dev/null
-[ nonbond_params ]
-; ai aj funct a b c
-#ifdef MM3
-; Parameters from MM3
-C C 2 2.07861e+04 2.94117e+01 1.17244e-03
-C H 2 1.77067e+04 3.37078e+01 4.40743e-04
-H H 2 1.53971e+04 3.70370e+01 2.17819e-04
-#else
-; Parameters from Dauchez et. al. (JCC Vol 14 No. 3 1992)
-C C 2 3.49908e+05 3.60000e+01 2.37651e-03
-C O 2 1.59912e+05 3.88100e+01 1.10709e-03
-C H 2 3.66769e+04 3.67000e+01 5.23000e-04
-O O 2 4.03756e+05 4.33300e+01 1.44766e-03
-O H 2 2.40580e+05 4.72700e+01 5.10448e-04
-H H 2 1.11043e+04 3.74000e+01 1.14223e-04
-#endif
aminoacids.hdb cmap.itp forcefield.doc rna.rtp \
aminoacids.n.tdb dna.rtp forcefield.itp spc.itp \
aminoacids.r2b ffbon.itp gb.itp tip3p.itp \
-aminoacids.rtp ffnabon.itp ions.itp tip4p.itp
+aminoacids.rtp ffnabon.itp ions.itp tip4p.itp \
+spce.itp tips3p.itp watermodels.dat
EXTRA_DIST = ${topol_DATA}
[ impropers ]
C CA OT2 OT1
-; Not part of CHARMM27, created by Michel Cuendet.
+; Created by Cuendet and Bjelkmar.
[ COOH ]
[ replace ]
- C CD 12.011 0.72
+ C C CD 12.011 0.72
+ O OT1 OB 15.9994 -0.55
+ OXT OT2 OH 15.9994 -0.61
[ add ]
2 8 OT C CA N
OB 15.9994 -0.55
1 2 HT2 OT2 C CA
H 1.008 0.44
[ replace ]
- OT2 OH1 15.9994 -0.61
-[ delete ]
- O
+ OT2 OT2 OH1 15.9994 -0.61
[ impropers ]
C CA OT2 OT1
-HISA HSD
-HISB HSE
+HISD HSD
+HISE HSE
HISH HSP
-CYSH CYS
-LYS LSN
-LYSH LYS
+HIS1 HSD
+LYSN LSN
ASPH ASPP
GLUH GLUP
OH2 H1
OH2 H2
+[ HO4 ]
+; TIP4P
+ [ atoms ]
+ OW OWT4 0.00 0
+ HW1 HWT4 0.52 0
+ HW2 HWT4 0.52 0
+ MW MWT4 -1.04 0
+ [ bonds ]
+ OW HW1
+ OW HW2
+
[ SOD ]
[ atoms ]
SOD SOD 1.00 0
HC 1.00800 ; N-ter H
HA 1.00800 ; nonpolar H
HT 1.00800 ; TIPS3P WATER HYDROGEN
+HT0 1.00800 ; TIP3P WATER HYDROGEN
HP 1.00800 ; aromatic H
HB 1.00800 ; backbone H
HR1 1.00800 ; his he1, (+) his HG,HD2
ON2B 15.999400 ; Nucleic acid phosphate ester oxygen (pres tp1/tp2, toppar_tyr_ser_thr_phosphate.str) ### For DNA
FN1 18.998400 ; Fluorine for sugar derivatives (NF) ### For DNA
FNA 18.998400 ; Aromatic fluorine ### For DNA
-CC1A 12.011000 ; alkene conjugation ### For DNA
-CC1B 12.011000 ; alkene conjugation ### For DNA
-CC2 12.011000 ; alkene conjugation ### For DNA
-NS1 14.007000 ; N for deprotonated Schiff's base ### For DNA
-NS2 14.007000 ; N for protonated Schiff's base ### For DNA
-SP 32.060000 ; positive Sulphur, S-adenosylmethionine (SAM) ### For DNA
-CPH1 12.011000 ; For imidazole model compound (NF)
-CPH2 12.011000 ; For imidazole model compound (NF)
-HR3 1.008000 ; For imidazole model compound (NF)
-HR1 1.008000 ; For imidazole model compound (NF)
-NR1 14.007000 ; For nitrogen in imidazol (NF)
-NR2 14.007000 ; For nitrogen in imidazol (NF)
+OWT4 15.999400 ; For TIP4P
+HWT4 1.008000 ; For TIP4P
+MWT4 0.000000 ; For TIP4P
HR2 1 1.008000 0.18 A 0.12472582054 0.192464
HR3 1 1.008000 0.09 A 0.261567863646 0.0326352
HS 1 1.008000 0.16 A 0.0801808846326 0.4184
-#ifdef CHARMM_TIP3P
+; CHARMM_TIP3P
#ifdef HEAVY_H
-HT 1 4.032 0.417 A 0.0400013524445 0.192464
+HT 1 4.032 0.417 A 0.0400013524445 0.192464
#else
-; CHARMM_TIP3P, but not HEAVY_H
+; CHARMM_TIP3P, but not HEAVY_H
HT 1 1.008000 0.417 A 0.0400013524445 0.192464
#endif
-#else
; normal TIP3p
#ifdef HEAVY_H
-HT 1 4.032 0.417 A 0.0 0.0
+HT0 1 4.032 0.417 A 0.0 0.0
#else
-; normal TIP3P, but not HEAVY_H
-HT 1 1.008000 0.417 A 0.0 0.0
-#endif
+; normal TIP3P, but not HEAVY_H
+HT0 1 1.008000 0.417 A 0.0 0.0
#endif
HA1 1 1.008000 0.000 A 0.235197261589 0.092048 ; partial charge def not found
HA2 1 1.008000 0.000 A 0.238760856462 0.117152 ; partial charge def not found
CP1 HR2 1 0.231633666716 0.0897368027066
CP1 HR3 1 0.300054688269 0.0369520874647
CP1 HS 1 0.209361198763 0.132309697301
-CP1 HT 1 0.189271432669 0.0897368027066
CP1 HA1 1 0.286869387241 0.06205874894
CP1 HA2 1 0.288651184678 0.0700117110204
CP1 HA3 1 0.288651184678 0.0648182492821
CP2 HR2 1 0.231633666716 0.0897368027066
CP2 HR3 1 0.300054688269 0.0369520874647
CP2 HS 1 0.209361198763 0.132309697301
-CP2 HT 1 0.189271432669 0.0897368027066
CP2 HA1 1 0.286869387241 0.06205874894
CP2 HA2 1 0.288651184678 0.0700117110204
CP2 HA3 1 0.288651184678 0.0648182492821
CP3 HR2 1 0.231633666716 0.0897368027066
CP3 HR3 1 0.300054688269 0.0369520874647
CP3 HS 1 0.209361198763 0.132309697301
-CP3 HT 1 0.189271432669 0.0897368027066
CP3 HA1 1 0.286869387241 0.06205874894
CP3 HA2 1 0.288651184678 0.0700117110204
CP3 HA3 1 0.288651184678 0.0648182492821
CPT HR2 1 0.231633666716 0.26921040812
CPT HR3 1 0.300054688269 0.110856262394
CPT HS 1 0.209361198763 0.396929091904
-CPT HT 1 0.189271432669 0.26921040812
CPT HA1 1 0.286869387241 0.18617624682
CPT HA2 1 0.288651184678 0.210035133061
CPT HA3 1 0.288651184678 0.194454747846
CT1 HR2 1 0.231633666716 0.0897368027066
CT1 HR3 1 0.300054688269 0.0369520874647
CT1 HS 1 0.209361198763 0.132309697301
-CT1 HT 1 0.189271432669 0.0897368027066
CT1 HA1 1 0.286869387241 0.06205874894
CT1 HA2 1 0.288651184678 0.0700117110204
CT1 HA3 1 0.288651184678 0.0648182492821
CT2 HR2 1 0.231633666716 0.0897368027066
CT2 HR3 1 0.300054688269 0.0369520874647
CT2 HS 1 0.209361198763 0.132309697301
-CT2 HT 1 0.189271432669 0.0897368027066
CT2 HA1 1 0.286869387241 0.06205874894
CT2 HA2 1 0.288651184678 0.0700117110204
CT2 HA3 1 0.288651184678 0.0648182492821
CT3 HR2 1 0.231633666716 0.0897368027066
CT3 HR3 1 0.300054688269 0.0369520874647
CT3 HS 1 0.209361198763 0.132309697301
-CT3 HT 1 0.189271432669 0.0897368027066
CT3 HA1 1 0.286869387241 0.06205874894
CT3 HA2 1 0.288651184678 0.0700117110204
CT3 HA3 1 0.288651184678 0.0648182492821
CT HR2 1 0.231633666716 0.0897368027066
CT HR3 1 0.300054688269 0.0369520874647
CT HS 1 0.209361198763 0.132309697301
-CT HT 1 0.189271432669 0.0897368027066
CT HA1 1 0.286869387241 0.06205874894
CT HA2 1 0.288651184678 0.0700117110204
CT HA3 1 0.288651184678 0.0648182492821
CT1x HR2 1 0.231633666716 0.0897368027066
CT1x HR3 1 0.300054688269 0.0369520874647
CT1x HS 1 0.209361198763 0.132309697301
-CT1x HT 1 0.189271432669 0.0897368027066
CT1x HA1 1 0.286869387241 0.06205874894
CT1x HA2 1 0.288651184678 0.0700117110204
CT1x HA3 1 0.288651184678 0.0648182492821
CT2x HR2 1 0.231633666716 0.0897368027066
CT2x HR3 1 0.300054688269 0.0369520874647
CT2x HS 1 0.209361198763 0.132309697301
-CT2x HT 1 0.189271432669 0.0897368027066
CT2x HA1 1 0.286869387241 0.06205874894
CT2x HA2 1 0.288651184678 0.0700117110204
CT2x HA3 1 0.288651184678 0.0648182492821
CT3x HR2 1 0.231633666716 0.0897368027066
CT3x HR3 1 0.300054688269 0.0369520874647
CT3x HS 1 0.209361198763 0.132309697301
-CT3x HT 1 0.189271432669 0.0897368027066
CT3x HA1 1 0.286869387241 0.06205874894
CT3x HA2 1 0.288651184678 0.0700117110204
CT3x HA3 1 0.288651184678 0.0648182492821
HP HR2 1 0.183364774168 0.155428701597
HP HR3 1 0.251785795721 0.0640028929346
HP HS 1 0.161092306214 0.22916711806
-HP HT 1 0.14100254012 0.155428701597
HP HA1 1 0.238600494692 0.107488906218
HP HA2 1 0.240382292129 0.121263840612
HP HA3 1 0.240382292129 0.112268501014
N HR2 1 0.227179173126 0.00897368027066
N HR3 1 0.295600194679 0.00369520874647
N HS 1 0.204906705172 0.0132309697301
-N HT 1 0.184816939078 0.00897368027066
N HA1 1 0.28241489365 0.006205874894
N HA2 1 0.284196691087 0.00700117110204
N HA3 1 0.284196691087 0.00648182492821
NH1 HR2 1 0.200452211582 0.401315181871
NH1 HR3 1 0.268873233135 0.165254758963
NH1 HS 1 0.178179743628 0.591706954497
-NH1 HT 1 0.158089977534 0.401315181871
NH1 HA1 1 0.255687932106 0.277535162457
NH1 HA2 1 0.257469729543 0.313101890125
NH1 HA3 1 0.257469729543 0.289876023155
O HR2 1 0.18708873081 0.310857403193
O HR3 1 0.255509752363 0.128005785869
O HS 1 0.164816262856 0.45833423612
-O HT 1 0.144726496762 0.310857403193
O HA1 1 0.242324451334 0.214977812437
O HA2 1 0.24410624877 0.242527681224
O HA3 1 0.24410624877 0.224537002029
OB HR2 1 0.18708873081 0.310857403193
OB HR3 1 0.255509752363 0.128005785869
OB HS 1 0.164816262856 0.45833423612
-OB HT 1 0.144726496762 0.310857403193
OB HA1 1 0.242324451334 0.214977812437
OB HA2 1 0.24410624877 0.242527681224
OB HA3 1 0.24410624877 0.224537002029
OCA HR2 1 0.18708873081 0.310857403193
OCA HR3 1 0.255509752363 0.128005785869
OCA HS 1 0.164816262856 0.45833423612
-OCA HT 1 0.144726496762 0.310857403193
OCA HA1 1 0.242324451334 0.214977812437
OCA HA2 1 0.24410624877 0.242527681224
OCA HA3 1 0.24410624877 0.224537002029
CTL1 HR2 1 0.231633666716 0.0897368027066
CTL1 HR3 1 0.300054688269 0.0369520874647
CTL1 HS 1 0.209361198763 0.132309697301
-CTL1 HT 1 0.189271432669 0.0897368027066
CTL1 HA1 1 0.286869387241 0.06205874894
CTL1 HA2 1 0.288651184678 0.0700117110204
CTL1 HA3 1 0.288651184678 0.0648182492821
CTL2 HR2 1 0.231633666716 0.0897368027066
CTL2 HR3 1 0.300054688269 0.0369520874647
CTL2 HS 1 0.209361198763 0.132309697301
-CTL2 HT 1 0.189271432669 0.0897368027066
CTL2 HA1 1 0.286869387241 0.06205874894
CTL2 HA2 1 0.288651184678 0.0700117110204
CTL2 HA3 1 0.288651184678 0.0648182492821
CTL3 HR2 1 0.231633666716 0.0897368027066
CTL3 HR3 1 0.300054688269 0.0369520874647
CTL3 HS 1 0.209361198763 0.132309697301
-CTL3 HT 1 0.189271432669 0.0897368027066
CTL3 HA1 1 0.286869387241 0.06205874894
CTL3 HA2 1 0.288651184678 0.0700117110204
CTL3 HA3 1 0.288651184678 0.0648182492821
CTL5 HR2 1 0.231633666716 0.0897368027066
CTL5 HR3 1 0.300054688269 0.0369520874647
CTL5 HS 1 0.209361198763 0.132309697301
-CTL5 HT 1 0.189271432669 0.0897368027066
CTL5 HA1 1 0.286869387241 0.06205874894
CTL5 HA2 1 0.288651184678 0.0700117110204
CTL5 HA3 1 0.288651184678 0.0648182492821
OBL HR2 1 0.18708873081 0.310857403193
OBL HR3 1 0.255509752363 0.128005785869
OBL HS 1 0.164816262856 0.45833423612
-OBL HT 1 0.144726496762 0.310857403193
OBL HA1 1 0.242324451334 0.214977812437
OBL HA2 1 0.24410624877 0.242527681224
OBL HA3 1 0.24410624877 0.224537002029
; Atom type sar st pi gbr hct
NH1 0.155 1 1.028 0.17063 0.79 ; N
- N 0.155 1 1 0.155 0.79 ; Proline backbone N
- NP 0.155 1 1 0.155 0.79 ; Proline backbone N for Proline N-terminus
- H 0.1 1 1 0.115 0.85 ; H
+ N 0.155 1 1 0.17063 0.79 ; Proline backbone N
+ NP 0.155 1 1 0.17063 0.79 ; Proline backbone N-termini
+ H 0.1 1 1 0.115 0.85 ; Should be 0.105 when hydroxyl or carboxylic hydrogen
CT1 0.180 1 1.276 0.190 0.72 ; C
HB 0.1 1 1 0.125 0.85 ; H
CT3 0.200 1 0.880 0.190 0.72 ; C
HR1 0.1 1 1 0.125 0.85 ; H
HR2 0.1 1 1 0.125 0.85 ; H
NR2 0.155 1 1.215 0.17063 0.79 ; N
- HR3 0.1 1 1 0.115 0.85 ; H
+ HR3 0.1 1 1 0.125 0.85 ; H
NR3 0.155 1 1.215 0.17063 0.79 ; N
NH3 0.160 1 1.215 0.1625 0.79 ; N
HP 0.1 1 1 0.125 0.85 ; H
--- /dev/null
+[ moleculetype ]
+; molname nrexcl
+SOL 2
+
+[ atoms ]
+; nr type resnr residue atom cgnr charge mass
+ 1 OW 1 SOL OW 1 -0.8476
+ 2 HW 1 SOL HW1 1 0.4238
+ 3 HW 1 SOL HW2 1 0.4238
+
+#ifndef FLEXIBLE
+[ settles ]
+; OW funct doh dhh
+1 1 0.1 0.16330
+
+[ exclusions ]
+1 2 3
+2 1 3
+3 1 2
+#else
+[ bonds ]
+; i j funct length force.c.
+1 2 1 0.1 345000 0.1 345000
+1 3 1 0.1 345000 0.1 345000
+
+[ angles ]
+; i j k funct angle force.c.
+2 1 3 1 109.47 383 109.47 383
+#endif
[ atoms ]
; id at type res nr residu name at name cg nr charge
-#ifdef _FF_CHARMM
1 OT 1 SOL OW 1 -0.834
-2 HT 1 SOL HW1 1 0.417
-3 HT 1 SOL HW2 1 0.417
-#endif
-
+2 HT0 1 SOL HW1 1 0.417
+3 HT0 1 SOL HW2 1 0.417
-#ifdef FLEXIBLE
+#ifndef FLEXIBLE
+[ settles ]
+; i j funct length
+1 1 0.09572 0.15139
-#ifdef CHARMM_TIP3P
-[ bonds ]
-; i j funct length force.c.
-1 2 1 0.09572 376560.0 0.09572 376560.0
-1 3 1 0.09572 376560.0 0.09572 376560.0
-
-[ angles ]
-; i j k funct angle force.c.
-2 1 3 1 104.52 460.24 104.52 460.24
+[ exclusions ]
+1 2 3
+2 1 3
+3 1 2
#else
[ bonds ]
; i j funct length force.c.
; i j k funct angle force.c.
2 1 3 1 104.52 628.02 104.52 628.02
#endif
-
-
-#else
-[ settles ]
-; i j funct length
-1 1 0.09572 0.15139
-
-[ exclusions ]
-1 2 3
-2 1 3
-3 1 2
-#endif
--- /dev/null
+[ moleculetype ]
+; molname nrexcl
+SOL 2
+
+[ atoms ]
+; id at type res nr residu name at name cg nr charge
+1 OT 1 SOL OW 1 -0.834
+2 HT 1 SOL HW1 1 0.417
+3 HT 1 SOL HW2 1 0.417
+
+#ifndef FLEXIBLE
+[ settles ]
+; i j funct length
+1 1 0.09572 0.15139
+
+[ exclusions ]
+1 2 3
+2 1 3
+3 1 2
+#else
+[ bonds ]
+; i j funct length force.c.
+1 2 1 0.09572 376560.0 0.09572 376560.0
+1 3 1 0.09572 376560.0 0.09572 376560.0
+
+[ angles ]
+; i j k funct angle force.c.
+2 1 3 1 104.52 460.24 104.52 460.24
+#endif
--- /dev/null
+tip3p TIP3P TIP 3-point, recommended
+tip4p TIP4P TIP 4-point
+tip5p TIP5P TIP 5-point
+tips3p TIPS3P CHARMM TIP 3-point with LJ on H's (note: twice as slow in GROMACS)
+spc SPC simple point charge
+spce SPC/E extended simple point charge
"Protein-H" protein and not name "H*" "[0-9]?H.*";
"C-alpha" protein and name CA;
"Backbone" protein and name N CA C;
-"MainChain" protein and name N CA C O O1 O2 OXT;
-"MainChain+Cb" protein and name N CA CB C O O1 O2 OXT;
-"MainChain+H" protein and name N CA C O O1 O2 OT OXT H1 H2 H3 H "[0-9]?H";
+"MainChain" protein and name N CA C O O1 O2 OC1 OC2 OT OXT;
+"MainChain+Cb" protein and name N CA CB C O O1 O2 OC1 OC2 OT OXT;
+"MainChain+H" protein and name N CA C O O1 O2 OC1 OC2 OT OXT H1 H2 H3 H "[0-9]?H";
"SideChain" protein and not name N CA C O O1 O2 OT OXT H1 H2 H3 H "[0-9]?H";
"SideChain-H" protein and not name N CA C O O1 O2 OT OXT "H*" "[0-9]?H.*";
"Prot-Masses" protein and not name MN1 MN2 MCB1 MCB2 MCG1 MCG2 MCD1 MCD2 MCE1 MCE2 MNZ1 MNZ2;
+++ /dev/null
-Pure DMSO, 200 ps Equilibration run at 300 K. DvdS 26/02/95
- 832
- 1DMSO SD 1 2.915 1.878 2.580 -0.2435 0.1688 -0.2164
- 1DMSO CD1 2 2.764 1.908 2.461 -0.0608 0.4317 -0.3840
- 1DMSO OD 3 2.852 1.844 2.715 -0.1943 -0.6301 -0.3887
- 1DMSO CD2 4 2.964 1.705 2.506 -0.8067 -0.2363 0.3290
- 2DMSO SD 5 2.893 0.696 1.134 0.1596 0.0027 0.2853
- 2DMSO CD1 6 2.787 0.578 1.020 -0.3099 0.3434 0.3729
- 2DMSO OD 7 2.839 0.838 1.116 -0.0463 -0.1506 -0.3567
- 2DMSO CD2 8 2.843 0.624 1.308 0.5615 0.0386 0.4130
- 3DMSO SD 9 0.620 1.691 1.180 0.1682 -0.0369 -0.0753
- 3DMSO CD1 10 0.718 1.778 1.036 -0.1599 -0.0405 -0.3042
- 3DMSO OD 11 0.584 1.563 1.104 0.0159 -0.0079 -0.0551
- 3DMSO CD2 12 0.767 1.654 1.303 -0.3406 0.0902 0.5836
- 4DMSO SD 13 2.264 2.260 2.008 0.2096 0.0293 0.1754
- 4DMSO CD1 14 2.186 2.165 1.857 0.3713 0.3718 -0.1247
- 4DMSO OD 15 2.283 2.409 1.979 -0.1800 0.0529 0.0423
- 4DMSO CD2 16 2.093 2.260 2.102 0.1315 0.0484 0.0353
- 5DMSO SD 17 1.725 2.836 1.513 -0.0783 -0.1507 -0.2909
- 5DMSO CD1 18 1.854 2.798 1.654 -0.2961 -0.0955 -0.0768
- 5DMSO OD 19 1.591 2.798 1.576 -0.1178 0.3079 -0.0997
- 5DMSO CD2 20 1.745 3.029 1.521 0.5401 -0.2434 0.4994
- 6DMSO SD 21 1.005 0.466 0.330 -0.3035 -0.4799 0.1949
- 6DMSO CD1 22 0.860 0.373 0.420 -0.6714 -0.1368 -0.0370
- 6DMSO OD 23 0.955 0.490 0.188 -0.1032 -0.7419 0.0758
- 6DMSO CD2 24 0.974 0.633 0.425 -0.2182 -0.2018 -0.2728
- 7DMSO SD 25 0.187 1.467 0.054 -0.0656 -0.2666 0.1195
- 7DMSO CD1 26 0.091 1.589 -0.065 0.4751 -0.2864 -0.3392
- 7DMSO OD 27 0.159 1.326 0.002 0.4067 -0.2758 -0.1154
- 7DMSO CD2 28 0.375 1.507 0.020 -0.0589 -0.6598 -0.3131
- 8DMSO SD 29 0.117 0.736 1.833 -0.0278 -0.1966 -0.0829
- 8DMSO CD1 30 0.063 0.899 1.924 -0.6302 -0.3517 -0.1602
- 8DMSO OD 31 0.132 0.627 1.940 -0.4293 -0.1368 0.0324
- 8DMSO CD2 32 -0.050 0.691 1.745 0.0488 -0.2570 -0.2059
- 9DMSO SD 33 1.222 1.472 0.491 -0.4523 0.3486 -0.4296
- 9DMSO CD1 34 1.122 1.343 0.384 -0.3135 -0.2618 0.1527
- 9DMSO OD 35 1.196 1.448 0.640 0.3825 0.3794 -0.2733
- 9DMSO CD2 36 1.402 1.409 0.448 -0.3399 0.6361 -0.3836
- 10DMSO SD 37 0.850 0.792 2.553 0.0360 0.1920 -0.1967
- 10DMSO CD1 38 0.885 0.605 2.594 0.0380 0.1875 -0.2160
- 10DMSO OD 39 0.751 0.830 2.663 0.2662 -0.1098 0.1159
- 10DMSO CD2 40 1.028 0.857 2.597 0.2414 -0.3881 -0.1625
- 11DMSO SD 41 1.151 0.225 0.819 -0.2380 -0.1951 0.2490
- 11DMSO CD1 42 1.166 0.189 0.628 -0.3387 0.1023 0.1884
- 11DMSO OD 43 1.030 0.315 0.844 -0.0672 0.1090 0.0015
- 11DMSO CD2 44 1.095 0.044 0.862 0.0251 -0.2353 0.4298
- 12DMSO SD 45 2.787 1.781 1.382 -0.1556 -0.0358 -0.0186
- 12DMSO CD1 46 2.697 1.845 1.222 -0.2487 -0.2713 -0.0663
- 12DMSO OD 47 2.938 1.772 1.359 -0.1462 0.5978 -0.2086
- 12DMSO CD2 48 2.753 1.936 1.495 1.0564 0.3097 -0.1110
- 13DMSO SD 49 2.146 1.962 0.831 -0.4005 0.0201 -0.2676
- 13DMSO CD1 50 2.000 1.843 0.782 -0.1510 -0.3073 -0.2163
- 13DMSO OD 51 2.085 2.100 0.860 0.0322 0.0772 0.4092
- 13DMSO CD2 52 2.187 1.897 1.010 0.3011 0.4826 -0.2452
- 14DMSO SD 53 1.687 1.547 0.674 0.1017 -0.2890 -0.2877
- 14DMSO CD1 54 1.685 1.660 0.833 -0.2577 -0.2230 -0.3375
- 14DMSO OD 55 1.838 1.528 0.653 0.2129 -0.0980 0.3211
- 14DMSO CD2 56 1.619 1.394 0.774 0.1941 -0.1277 0.0257
- 15DMSO SD 57 2.630 2.290 2.069 -0.1191 -0.7534 -0.0608
- 15DMSO CD1 58 2.689 2.453 2.159 0.4199 -0.8949 -0.1525
- 15DMSO OD 59 2.724 2.271 1.950 -0.1684 1.0946 -0.4280
- 15DMSO CD2 60 2.672 2.144 2.191 -0.1770 -0.5909 0.1558
- 16DMSO SD 61 2.228 0.713 2.313 -0.2089 0.0723 -0.0471
- 16DMSO CD1 62 2.156 0.567 2.204 0.3440 -0.4807 0.3076
- 16DMSO OD 63 2.143 0.739 2.438 -0.2857 0.2572 -0.1374
- 16DMSO CD2 64 2.386 0.614 2.370 -0.4013 -0.2731 -0.1012
- 17DMSO SD 65 1.452 1.450 2.681 -0.2099 -0.2486 0.1148
- 17DMSO CD1 66 1.501 1.630 2.626 -0.3949 -0.1878 0.1452
- 17DMSO OD 67 1.464 1.438 2.833 0.3079 -0.3054 0.0714
- 17DMSO CD2 68 1.262 1.472 2.645 -0.1256 -0.3092 -0.3765
- 18DMSO SD 69 2.729 0.530 0.123 0.1503 0.2629 0.0744
- 18DMSO CD1 70 2.881 0.650 0.148 0.2716 0.0883 0.2315
- 18DMSO OD 71 2.766 0.434 0.010 0.0451 0.0851 0.1925
- 18DMSO CD2 72 2.757 0.416 0.278 -0.1110 0.7131 0.4579
- 19DMSO SD 73 2.528 2.660 0.691 0.1116 0.1910 0.3180
- 19DMSO CD1 74 2.709 2.710 0.638 -0.0274 0.3599 -0.0084
- 19DMSO OD 75 2.516 2.509 0.674 -0.3023 0.2384 0.1575
- 19DMSO CD2 76 2.552 2.712 0.877 -0.1496 0.2762 0.3304
- 20DMSO SD 77 2.179 2.187 0.519 -0.1965 -0.1237 0.2664
- 20DMSO CD1 78 1.993 2.244 0.508 -0.1430 -0.0480 -0.3707
- 20DMSO OD 79 2.251 2.260 0.405 -0.1152 -0.4990 0.0734
- 20DMSO CD2 80 2.213 2.300 0.674 0.1804 0.4423 -0.2325
- 21DMSO SD 81 1.170 1.582 0.971 0.0536 0.4675 -0.1386
- 21DMSO CD1 82 1.213 1.630 1.155 -0.5253 0.1177 0.0956
- 21DMSO OD 83 1.039 1.658 0.946 -0.3586 -0.2832 -0.3068
- 21DMSO CD2 84 1.307 1.696 0.894 0.2375 0.3996 0.0844
- 22DMSO SD 85 0.243 0.353 1.218 0.1199 0.0907 -0.0836
- 22DMSO CD1 86 0.395 0.282 1.316 0.1801 0.4442 0.0911
- 22DMSO OD 87 0.249 0.506 1.224 0.1678 0.0862 -0.0075
- 22DMSO CD2 88 0.288 0.276 1.044 -0.1555 0.3827 -0.2864
- 23DMSO SD 89 1.880 1.177 0.518 0.1186 0.1922 -0.0372
- 23DMSO CD1 90 1.931 1.188 0.706 -0.1752 0.1760 0.0474
- 23DMSO OD 91 1.729 1.202 0.513 -0.0308 -0.6801 -0.0132
- 23DMSO CD2 92 1.968 1.332 0.440 -0.3749 0.5990 0.2067
- 24DMSO SD 93 2.535 2.684 1.838 -0.4172 -0.2809 0.0905
- 24DMSO CD1 94 2.396 2.721 1.970 0.0463 0.3810 0.4055
- 24DMSO OD 95 2.493 2.772 1.720 -0.5212 -0.0112 0.3241
- 24DMSO CD2 96 2.679 2.784 1.925 -0.2818 -0.2048 -0.2268
- 25DMSO SD 97 2.676 1.166 1.779 0.3963 0.2202 -0.1794
- 25DMSO CD1 98 2.496 1.091 1.785 0.4791 0.0060 -0.2478
- 25DMSO OD 99 2.727 1.154 1.923 -0.3194 -0.0958 0.0564
- 25DMSO CD2 100 2.757 1.028 1.667 0.9429 0.3781 0.0297
- 26DMSO SD 101 2.834 1.188 1.352 -0.0298 0.3201 0.0668
- 26DMSO CD1 102 2.861 1.240 1.165 0.2325 0.4812 0.1479
- 26DMSO OD 103 2.701 1.115 1.374 0.3037 -0.2467 0.1999
- 26DMSO CD2 104 2.966 1.045 1.354 0.2112 0.5428 0.3179
- 27DMSO SD 105 0.061 2.744 0.984 -0.0076 0.0200 0.2086
- 27DMSO CD1 106 0.035 2.556 1.029 0.0623 -0.0079 0.1476
- 27DMSO OD 107 -0.046 2.797 0.888 0.0888 -0.4305 -0.1425
- 27DMSO CD2 108 0.039 2.846 1.149 -0.2318 -0.4628 0.4843
- 28DMSO SD 109 2.103 1.229 2.460 -0.2184 0.1146 0.1781
- 28DMSO CD1 110 2.205 1.064 2.473 -0.0373 0.2396 0.3573
- 28DMSO OD 111 2.021 1.203 2.333 0.3576 0.4179 -0.2679
- 28DMSO CD2 112 1.985 1.209 2.614 -0.6566 -0.3816 -0.2209
- 29DMSO SD 113 0.509 0.613 1.474 -0.0756 -0.5906 0.0699
- 29DMSO CD1 114 0.316 0.621 1.503 -0.0190 0.5901 0.1457
- 29DMSO OD 115 0.558 0.470 1.496 -0.0174 -0.4771 0.7317
- 29DMSO CD2 116 0.491 0.655 1.285 0.1436 -0.7317 0.0241
- 30DMSO SD 117 2.708 0.540 2.137 -0.1059 0.1653 0.3879
- 30DMSO CD1 118 2.820 0.691 2.187 0.3035 0.0754 -0.2382
- 30DMSO OD 119 2.645 0.567 2.000 0.4600 0.2983 0.1484
- 30DMSO CD2 120 2.852 0.410 2.112 -0.5324 -0.1613 -0.3995
- 31DMSO SD 121 2.590 1.296 2.570 -0.0598 -0.3898 0.3481
- 31DMSO CD1 122 2.679 1.277 2.742 0.2285 -0.2792 0.2065
- 31DMSO OD 123 2.442 1.262 2.584 -0.2216 0.1888 0.1075
- 31DMSO CD2 124 2.607 1.490 2.558 -0.2594 -0.4079 -0.3246
- 32DMSO SD 125 1.315 2.657 2.830 -0.0496 -0.0017 0.0106
- 32DMSO CD1 126 1.444 2.790 2.891 -0.1667 0.1978 -0.1781
- 32DMSO OD 127 1.177 2.706 2.872 -0.1373 -0.2564 0.0252
- 32DMSO CD2 128 1.325 2.692 2.638 0.7142 0.2966 0.0972
- 33DMSO SD 129 2.376 0.240 0.119 0.5156 0.1365 0.1799
- 33DMSO CD1 130 2.552 0.169 0.072 0.2991 -0.6268 0.5352
- 33DMSO OD 131 2.393 0.303 0.258 0.0978 -0.4506 0.5026
- 33DMSO CD2 132 2.387 0.388 -0.006 0.3366 0.0488 0.0593
- 34DMSO SD 133 0.087 2.526 1.935 0.0499 -0.4439 0.3131
- 34DMSO CD1 134 0.168 2.356 1.985 0.2730 -0.1661 0.9006
- 34DMSO OD 135 0.195 2.628 1.899 -0.4533 -0.3138 -0.8676
- 34DMSO CD2 136 0.019 2.467 1.762 0.2806 0.3664 -0.0616
- 35DMSO SD 137 1.780 1.497 0.093 0.0308 -0.0973 -0.0447
- 35DMSO CD1 138 1.760 1.616 0.247 0.0917 0.1693 -0.2531
- 35DMSO OD 139 1.927 1.458 0.087 0.2242 0.4259 0.9654
- 35DMSO CD2 140 1.674 1.352 0.171 -0.6565 0.6431 0.4416
- 36DMSO SD 141 1.713 1.039 2.399 -0.1739 -0.4488 -0.1576
- 36DMSO CD1 142 1.731 1.163 2.250 -0.3588 0.4050 0.5288
- 36DMSO OD 143 1.565 1.000 2.405 -0.4125 0.3701 -0.5449
- 36DMSO CD2 144 1.808 0.895 2.307 0.4724 -0.2579 0.2197
- 37DMSO SD 145 1.205 2.088 1.233 0.2683 -0.3870 0.0229
- 37DMSO CD1 146 1.219 2.050 1.424 0.6694 0.0153 0.0862
- 37DMSO OD 147 1.325 2.025 1.163 0.6024 0.3748 -0.0996
- 37DMSO CD2 148 1.045 1.987 1.186 -0.1242 0.1562 0.1702
- 38DMSO SD 149 1.527 1.063 0.771 -0.2351 0.0684 0.2590
- 38DMSO CD1 150 1.673 0.948 0.712 -0.9106 -0.6749 0.0169
- 38DMSO OD 151 1.430 1.063 0.652 0.3864 -0.1877 -0.2604
- 38DMSO CD2 152 1.471 0.934 0.906 -0.0202 -0.3912 -0.0900
- 39DMSO SD 153 0.742 0.518 0.825 0.1332 -0.1282 -0.0785
- 39DMSO CD1 154 0.579 0.603 0.888 0.2281 0.0497 -0.0545
- 39DMSO OD 155 0.723 0.503 0.674 0.6199 -0.0676 -0.1493
- 39DMSO CD2 156 0.890 0.635 0.876 0.0991 -0.3299 0.5023
- 40DMSO SD 157 2.501 1.735 0.818 0.0200 -0.1881 -0.2182
- 40DMSO CD1 158 2.462 1.906 0.733 0.0687 -0.1470 -0.1642
- 40DMSO OD 159 2.370 1.656 0.833 -0.4013 0.5568 0.0647
- 40DMSO CD2 160 2.618 1.659 0.682 0.5548 0.1726 0.0259
- 41DMSO SD 161 2.135 0.930 0.503 0.7237 -0.2773 -0.3028
- 41DMSO CD1 162 2.232 0.794 0.605 0.0737 0.0629 0.8043
- 41DMSO OD 163 2.190 0.935 0.360 0.5485 0.1016 -0.3583
- 41DMSO CD2 164 1.968 0.829 0.501 0.5520 -0.0004 -0.0949
- 42DMSO SD 165 2.674 0.651 0.543 0.2518 0.0202 0.0833
- 42DMSO CD1 166 2.589 0.711 0.708 0.4877 -0.2151 0.2990
- 42DMSO OD 167 2.709 0.503 0.564 0.0927 -0.0817 -0.3501
- 42DMSO CD2 168 2.508 0.646 0.442 0.2481 -0.1867 0.0972
- 43DMSO SD 169 1.788 0.630 1.010 0.1339 0.4230 -0.0259
- 43DMSO CD1 170 1.657 0.489 1.038 0.1867 0.4944 0.6152
- 43DMSO OD 171 1.900 0.624 1.115 0.2049 0.3765 -0.1029
- 43DMSO CD2 172 1.858 0.565 0.840 -0.4005 0.5273 -0.2863
- 44DMSO SD 173 0.541 2.392 2.832 -0.1214 -0.3109 0.3017
- 44DMSO CD1 174 0.458 2.547 2.915 -0.3363 0.0163 -0.5013
- 44DMSO OD 175 0.595 2.306 2.947 0.0372 -0.3303 0.2128
- 44DMSO CD2 176 0.367 2.322 2.776 -0.0279 0.0421 -0.4390
- 45DMSO SD 177 2.335 0.683 1.898 0.1493 0.2021 0.4730
- 45DMSO CD1 178 2.389 0.722 1.715 -0.3334 -0.0426 0.2762
- 45DMSO OD 179 2.184 0.705 1.895 0.0653 -0.3931 0.1720
- 45DMSO CD2 180 2.362 0.490 1.884 -0.7851 0.0895 0.1001
- 46DMSO SD 181 1.028 0.932 0.142 0.0263 0.2181 -0.2843
- 46DMSO CD1 182 0.888 0.997 0.261 -0.2457 -0.9359 0.0400
- 46DMSO OD 183 1.119 0.852 0.236 0.0628 0.2312 -0.3083
- 46DMSO CD2 184 0.916 0.793 0.065 0.4231 -0.0945 -0.3031
- 47DMSO SD 185 0.481 2.641 1.065 0.1310 -0.0900 0.0108
- 47DMSO CD1 186 0.531 2.582 1.244 -0.0782 0.0188 0.1020
- 47DMSO OD 187 0.340 2.699 1.068 0.1002 -0.1658 0.0779
- 47DMSO CD2 188 0.609 2.786 1.043 0.2021 -0.2059 -0.3592
- 48DMSO SD 189 0.844 2.651 2.727 0.3758 0.2468 -0.0340
- 48DMSO CD1 190 0.953 2.543 2.606 0.1400 0.3682 -0.3618
- 48DMSO OD 191 0.694 2.628 2.705 0.4326 -0.1438 -0.0323
- 48DMSO CD2 192 0.877 2.536 2.881 0.7531 0.0874 -0.2322
- 49DMSO SD 193 2.244 2.120 1.388 0.3070 0.2701 0.0923
- 49DMSO CD1 194 2.408 2.046 1.315 -0.2396 -0.6592 -0.2165
- 49DMSO OD 195 2.263 2.135 1.539 0.2594 0.0875 0.1165
- 49DMSO CD2 196 2.232 2.284 1.283 -0.0486 -0.0700 -0.4088
- 50DMSO SD 197 1.290 2.161 0.048 -0.3284 0.1788 0.0095
- 50DMSO CD1 198 1.329 2.307 0.171 -0.7131 0.1776 0.1218
- 50DMSO OD 199 1.162 2.099 0.106 0.3246 -0.2261 1.0687
- 50DMSO CD2 200 1.242 2.277 -0.101 -0.9757 0.1800 0.2196
- 51DMSO SD 201 1.850 2.733 2.166 -0.2294 0.3676 0.1750
- 51DMSO CD1 202 1.982 2.696 2.027 -0.3343 0.1036 0.1525
- 51DMSO OD 203 1.861 2.629 2.277 0.1549 0.0234 -0.1775
- 51DMSO CD2 204 1.925 2.896 2.244 -0.0744 0.2626 0.2499
- 52DMSO SD 205 0.128 2.273 1.430 -0.1938 0.2382 0.1840
- 52DMSO CD1 206 0.145 2.085 1.381 0.3888 0.2348 0.3961
- 52DMSO OD 207 0.257 2.345 1.390 -0.2507 0.2283 -0.0374
- 52DMSO CD2 208 -0.016 2.335 1.314 -0.3275 -0.3250 0.0557
- 53DMSO SD 209 1.673 2.548 0.776 0.1001 -0.2487 0.2280
- 53DMSO CD1 210 1.617 2.539 0.962 0.2773 0.2156 0.3070
- 53DMSO OD 211 1.822 2.582 0.767 -0.0104 0.4432 0.8765
- 53DMSO CD2 212 1.678 2.359 0.730 -0.4963 -0.1650 -0.1914
- 54DMSO SD 213 0.683 1.094 0.577 0.0528 0.4805 -0.0152
- 54DMSO CD1 214 0.488 1.098 0.580 0.0367 0.2320 -0.5618
- 54DMSO OD 215 0.723 1.155 0.711 -0.0961 -0.0114 0.2564
- 54DMSO CD2 216 0.710 0.901 0.577 0.3510 0.5205 0.0795
- 55DMSO SD 217 2.404 1.765 2.187 -0.0769 -0.0402 0.4017
- 55DMSO CD1 218 2.431 1.901 2.050 -0.3313 -0.2591 0.1333
- 55DMSO OD 219 2.328 1.651 2.118 0.1788 0.0130 0.0238
- 55DMSO CD2 220 2.592 1.713 2.173 -0.1342 -0.1092 -0.1576
- 56DMSO SD 221 1.039 0.776 1.361 -0.1611 -0.0454 -0.5522
- 56DMSO CD1 222 1.078 0.887 1.206 0.1819 0.4723 -0.0845
- 56DMSO OD 223 1.119 0.835 1.476 0.4097 -0.3068 -0.8124
- 56DMSO CD2 224 0.854 0.836 1.373 0.0628 0.4897 0.2574
- 57DMSO SD 225 0.267 2.743 0.525 -0.2281 -0.2874 -0.2623
- 57DMSO CD1 226 0.291 2.812 0.705 0.3034 0.0577 -0.4574
- 57DMSO OD 227 0.142 2.814 0.473 -0.1143 0.1209 0.0354
- 57DMSO CD2 228 0.418 2.813 0.423 -0.1113 -0.2099 -0.0377
- 58DMSO SD 229 1.910 -0.014 0.189 0.3568 0.2791 -0.1395
- 58DMSO CD1 230 2.049 0.103 0.118 0.0381 0.6681 -0.1254
- 58DMSO OD 231 1.786 0.076 0.188 -0.1907 -0.4617 -0.1746
- 58DMSO CD2 232 1.878 -0.122 0.030 0.0827 0.5195 -0.2504
- 59DMSO SD 233 1.692 2.575 2.635 0.1422 -0.1786 0.1876
- 59DMSO CD1 234 1.873 2.501 2.623 0.2931 0.2272 -0.1829
- 59DMSO OD 235 1.635 2.569 2.776 -0.8243 0.7250 -0.1569
- 59DMSO CD2 236 1.762 2.754 2.602 -0.4378 0.0502 0.1825
- 60DMSO SD 237 0.247 2.755 1.466 0.1361 -0.1887 0.0088
- 60DMSO CD1 238 0.071 2.708 1.537 0.2185 -0.2666 0.1698
- 60DMSO OD 239 0.280 2.901 1.497 -0.0577 -0.0489 -0.4091
- 60DMSO CD2 240 0.351 2.664 1.603 0.2560 0.1873 0.1707
- 61DMSO SD 241 0.919 2.885 0.362 -0.2171 -0.2644 0.2843
- 61DMSO CD1 242 0.772 2.758 0.349 -0.7689 0.3806 0.1106
- 61DMSO OD 243 0.993 2.860 0.493 0.2020 -0.4638 0.0117
- 61DMSO CD2 244 1.036 2.820 0.220 0.3204 0.5897 0.3255
- 62DMSO SD 245 1.765 1.899 1.954 0.0621 -0.3148 0.0089
- 62DMSO CD1 246 1.878 1.942 2.108 -0.7523 0.1355 0.4848
- 62DMSO OD 247 1.624 1.880 2.009 0.0783 0.1917 0.2342
- 62DMSO CD2 248 1.791 2.064 1.852 -1.5073 0.0695 0.2115
- 63DMSO SD 249 0.531 1.552 2.394 0.2963 0.1261 -0.0898
- 63DMSO CD1 250 0.563 1.613 2.576 0.5276 -0.2019 -0.0191
- 63DMSO OD 251 0.402 1.470 2.392 0.2330 0.2112 0.3945
- 63DMSO CD2 252 0.486 1.733 2.335 0.2668 0.1490 0.0008
- 64DMSO SD 253 0.999 2.503 1.238 0.2144 -0.5212 -0.0845
- 64DMSO CD1 254 0.854 2.397 1.161 -0.3054 0.1355 -0.0237
- 64DMSO OD 255 1.122 2.417 1.267 0.1835 -0.4257 0.3394
- 64DMSO CD2 256 1.028 2.601 1.072 -0.2681 -0.0793 0.0970
- 65DMSO SD 257 0.186 1.451 1.396 -0.2131 0.0928 0.4137
- 65DMSO CD1 258 0.302 1.608 1.401 -0.0843 0.0273 -0.0657
- 65DMSO OD 259 0.267 1.327 1.432 0.0049 0.0107 -0.3290
- 65DMSO CD2 260 0.087 1.502 1.556 0.0208 0.5463 0.4175
- 66DMSO SD 261 2.584 2.762 2.532 0.0846 0.0029 0.0567
- 66DMSO CD1 262 2.757 2.701 2.465 -0.3510 -0.1628 -0.9489
- 66DMSO OD 263 2.600 2.797 2.680 -0.3105 0.0340 0.0936
- 66DMSO CD2 264 2.577 2.921 2.419 0.2614 -0.0024 0.0334
- 67DMSO SD 265 2.417 0.985 1.260 0.1395 0.3214 0.0216
- 67DMSO CD1 266 2.510 0.894 1.115 0.3184 0.6994 -0.1033
- 67DMSO OD 267 2.271 0.944 1.236 0.1918 0.0140 0.2282
- 67DMSO CD2 268 2.496 0.871 1.396 -0.2905 0.4508 0.3903
- 68DMSO SD 269 0.886 2.113 1.621 0.0093 -0.1189 -0.2469
- 68DMSO CD1 270 0.912 2.194 1.446 -0.4310 0.7362 0.0771
- 68DMSO OD 271 0.839 2.218 1.722 0.5566 -0.2197 0.1193
- 68DMSO CD2 272 0.722 2.023 1.566 -0.2488 0.1260 0.1121
- 69DMSO SD 273 2.009 2.448 1.779 0.3434 -0.0230 -0.2909
- 69DMSO CD1 274 2.137 2.554 1.677 0.5728 -0.4838 -0.4928
- 69DMSO OD 275 1.884 2.530 1.809 0.2027 -0.2877 -0.1338
- 69DMSO CD2 276 1.978 2.342 1.618 0.1452 0.0366 -0.2931
- 70DMSO SD 277 1.024 1.926 0.531 0.1133 0.1842 0.2663
- 70DMSO CD1 278 0.941 1.756 0.485 0.3126 0.2754 -0.4282
- 70DMSO OD 279 0.917 2.035 0.526 -0.0725 0.0153 0.5167
- 70DMSO CD2 280 1.044 1.881 0.720 0.4977 0.3526 0.2698
- 71DMSO SD 281 0.043 1.269 2.428 -0.2869 0.1290 -0.0142
- 71DMSO CD1 282 0.189 1.356 2.522 -0.1204 -0.4742 0.2903
- 71DMSO OD 283 -0.027 1.383 2.353 -0.4144 0.0752 0.0160
- 71DMSO CD2 284 0.165 1.185 2.302 -0.4993 -0.3822 0.1168
- 72DMSO SD 285 2.350 1.191 0.640 -0.0370 -0.0751 -0.3322
- 72DMSO CD1 286 2.454 1.093 0.773 -0.6264 -0.1031 0.1093
- 72DMSO OD 287 2.226 1.243 0.713 0.2837 0.4143 -0.1299
- 72DMSO CD2 288 2.479 1.326 0.586 0.2970 -0.1690 0.2111
- 73DMSO SD 289 2.770 0.363 2.525 -0.2007 0.1757 0.0142
- 73DMSO CD1 290 2.783 0.207 2.642 -0.2736 -0.0916 -0.3176
- 73DMSO OD 291 2.746 0.309 2.384 0.2942 -0.1436 0.0507
- 73DMSO CD2 292 2.615 0.453 2.604 -0.1944 0.2067 -0.0068
- 74DMSO SD 293 2.236 0.060 1.634 -0.0874 -0.0814 -0.3781
- 74DMSO CD1 294 2.191 0.207 1.755 0.7511 -0.3038 0.2145
- 74DMSO OD 295 2.120 0.053 1.535 -0.4038 -0.1388 -0.0029
- 74DMSO CD2 296 2.398 0.136 1.555 -0.0920 0.6115 0.2649
- 75DMSO SD 297 2.844 0.143 1.695 0.1931 0.2422 0.1509
- 75DMSO CD1 298 2.973 0.244 1.589 0.1241 0.1849 0.0098
- 75DMSO OD 299 2.906 0.114 1.832 -0.4973 -0.8505 0.2448
- 75DMSO CD2 300 2.706 0.278 1.720 -0.4525 -0.3423 -0.2191
- 76DMSO SD 301 0.238 1.014 0.844 -0.2510 0.1348 -0.0107
- 76DMSO CD1 302 0.074 0.909 0.846 -0.3869 0.3133 -0.5234
- 76DMSO OD 303 0.209 1.154 0.898 0.4028 -0.0007 0.6925
- 76DMSO CD2 304 0.336 0.925 0.987 0.2843 -0.1254 -0.5163
- 77DMSO SD 305 0.470 1.189 1.255 -0.2774 0.1474 0.1152
- 77DMSO CD1 306 0.447 1.275 1.081 -0.1172 -0.5935 -0.2787
- 77DMSO OD 307 0.558 1.066 1.233 -0.1954 0.2735 -0.2705
- 77DMSO CD2 308 0.576 1.337 1.325 -0.0882 0.2734 -0.4421
- 78DMSO SD 309 1.977 1.814 -0.014 0.0196 -0.1883 -0.0596
- 78DMSO CD1 310 2.011 1.846 0.175 -0.2822 0.0025 -0.0287
- 78DMSO OD 311 1.831 1.771 -0.029 -0.0557 0.0163 0.0835
- 78DMSO CD2 312 1.988 1.995 -0.088 0.2347 -0.1885 -0.0276
- 79DMSO SD 313 1.440 0.411 1.485 -0.4680 0.0041 -0.1350
- 79DMSO CD1 314 1.274 0.510 1.506 -0.1648 0.4558 0.1441
- 79DMSO OD 315 1.508 0.430 1.349 0.2066 0.2558 0.2307
- 79DMSO CD2 316 1.535 0.529 1.607 0.4519 -0.7171 -0.1454
- 80DMSO SD 317 1.406 1.032 2.777 0.3337 0.0059 -0.1681
- 80DMSO CD1 318 1.591 1.081 2.738 0.1922 0.5690 -0.1050
- 80DMSO OD 319 1.410 0.885 2.821 0.1883 0.2067 0.5331
- 80DMSO CD2 320 1.385 1.131 2.944 0.3617 -0.4594 0.1105
- 81DMSO SD 321 0.202 1.473 2.062 0.1886 -0.2555 0.0201
- 81DMSO CD1 322 0.134 1.325 1.954 0.6196 -0.5666 0.1863
- 81DMSO OD 323 0.276 1.576 1.976 -0.3531 0.1094 -0.0125
- 81DMSO CD2 324 0.022 1.533 2.105 0.2148 -0.3192 0.2404
- 82DMSO SD 325 1.252 0.717 2.313 0.3641 0.0143 -0.4423
- 82DMSO CD1 326 1.312 0.634 2.147 -0.3322 -0.6231 -0.3810
- 82DMSO OD 327 1.165 0.615 2.387 0.2760 0.4267 0.0285
- 82DMSO CD2 328 1.425 0.711 2.402 0.0280 0.0236 0.2171
- 83DMSO SD 329 2.854 1.414 0.696 0.0873 0.4357 -0.1701
- 83DMSO CD1 330 3.038 1.394 0.757 -0.0544 0.1824 0.1825
- 83DMSO OD 331 2.859 1.430 0.544 -0.0007 -0.2717 -0.2508
- 83DMSO CD2 332 2.800 1.233 0.746 -0.2836 0.5877 0.0022
- 84DMSO SD 333 0.458 1.141 2.882 0.0406 0.1368 -0.5473
- 84DMSO CD1 334 0.571 0.982 2.883 -0.2845 -0.0915 -0.5729
- 84DMSO OD 335 0.559 1.256 2.876 0.3446 -0.1031 -0.0927
- 84DMSO CD2 336 0.375 1.120 2.706 -0.1355 -0.0858 -0.4311
- 85DMSO SD 337 1.326 2.068 1.838 -0.4710 0.1070 0.1613
- 85DMSO CD1 338 1.470 2.134 1.952 0.1499 -0.1132 -0.4902
- 85DMSO OD 339 1.360 2.101 1.693 0.1074 -0.1674 0.2357
- 85DMSO CD2 340 1.347 1.876 1.868 -0.5788 -0.0064 -0.4247
- 86DMSO SD 341 0.507 0.812 2.131 -0.3622 0.1311 0.0973
- 86DMSO CD1 342 0.506 0.743 1.949 1.0399 0.1046 0.0828
- 86DMSO OD 343 0.509 0.965 2.129 -0.4392 0.1337 0.1599
- 86DMSO CD2 344 0.326 0.777 2.194 -0.6060 0.1135 -0.6088
- 87DMSO SD 345 1.878 0.137 0.737 -0.3480 -0.0439 0.0104
- 87DMSO CD1 346 1.794 -0.018 0.821 -0.0744 -0.1608 0.0694
- 87DMSO OD 347 1.794 0.252 0.793 -0.3597 0.2386 -0.5780
- 87DMSO CD2 348 2.048 0.146 0.832 -0.5044 0.8185 0.2198
- 88DMSO SD 349 1.287 2.246 0.704 0.3400 -0.1291 -0.0172
- 88DMSO CD1 350 1.134 2.286 0.817 -0.1205 -0.3798 -0.5398
- 88DMSO OD 351 1.387 2.359 0.682 0.6020 -0.3512 0.0114
- 88DMSO CD2 352 1.380 2.128 0.828 0.1035 -0.4888 -0.1783
- 89DMSO SD 353 1.076 1.778 1.603 -0.0350 -0.2041 0.0272
- 89DMSO CD1 354 1.194 1.656 1.508 -0.4932 -0.3460 -0.3662
- 89DMSO OD 355 1.009 1.858 1.491 0.3567 0.2618 0.1228
- 89DMSO CD2 356 0.944 1.653 1.674 -0.7520 0.4644 -0.1072
- 90DMSO SD 357 0.096 0.179 0.764 0.5645 0.0202 0.2037
- 90DMSO CD1 358 -0.009 0.176 0.600 0.2315 0.2899 0.3994
- 90DMSO OD 359 0.175 0.310 0.776 0.0274 0.3736 0.0298
- 90DMSO CD2 360 -0.050 0.208 0.890 -0.0480 0.2204 -0.5428
- 91DMSO SD 361 0.060 1.781 0.893 -0.0520 -0.2076 -0.0605
- 91DMSO CD1 362 0.113 1.871 1.058 -0.3251 0.2745 -0.2362
- 91DMSO OD 363 -0.049 1.677 0.921 -0.3295 -0.0305 -0.4673
- 91DMSO CD2 364 -0.045 1.931 0.827 -1.1358 -0.4189 1.1207
- 92DMSO SD 365 0.428 2.194 1.795 -0.0482 -0.0398 0.2562
- 92DMSO CD1 366 0.473 2.277 1.625 0.5035 -0.1042 0.3673
- 92DMSO OD 367 0.349 2.067 1.763 0.0886 -0.1346 0.2623
- 92DMSO CD2 368 0.598 2.122 1.857 -0.1521 -0.5822 -0.0796
- 93DMSO SD 369 2.024 2.825 1.273 0.0652 -0.1376 0.2408
- 93DMSO CD1 370 2.052 3.018 1.282 -0.3660 -0.0825 0.5839
- 93DMSO OD 371 1.963 2.799 1.135 -0.6171 0.7119 0.3720
- 93DMSO CD2 372 2.217 2.797 1.268 0.1040 0.1566 -0.0515
- 94DMSO SD 373 0.345 0.670 2.675 -0.0395 0.1156 -0.1345
- 94DMSO CD1 374 0.525 0.606 2.714 0.1072 -0.0335 -1.0145
- 94DMSO OD 375 0.296 0.763 2.786 -0.4529 -0.2473 -0.0075
- 94DMSO CD2 376 0.390 0.799 2.536 0.4865 -0.2826 -0.3409
- 95DMSO SD 377 1.476 0.189 2.634 0.4367 0.0356 0.2774
- 95DMSO CD1 378 1.421 0.371 2.591 -0.2664 -0.2371 0.0148
- 95DMSO OD 379 1.387 0.099 2.548 0.6624 -0.6973 0.8047
- 95DMSO CD2 380 1.651 0.186 2.549 0.4637 -1.1716 0.3566
- 96DMSO SD 381 1.462 1.887 0.497 0.1601 0.0265 0.4470
- 96DMSO CD1 382 1.654 1.921 0.510 0.2173 -0.0352 -0.1064
- 96DMSO OD 383 1.407 1.849 0.634 -0.0871 -0.2783 0.2656
- 96DMSO CD2 384 1.407 2.068 0.451 -0.0868 -0.1509 0.0441
- 97DMSO SD 385 0.961 1.195 2.706 0.0539 0.0910 0.1299
- 97DMSO CD1 386 0.913 1.328 2.572 0.9387 0.2065 -0.0843
- 97DMSO OD 387 1.112 1.171 2.693 -0.0243 -0.1685 -0.3172
- 97DMSO CD2 388 0.938 1.303 2.868 0.3846 -0.1615 0.3418
- 98DMSO SD 389 2.585 1.470 1.402 -0.2832 0.2655 0.1449
- 98DMSO CD1 390 2.442 1.602 1.396 -0.2198 0.3372 0.3468
- 98DMSO OD 391 2.678 1.520 1.512 -0.0324 0.7367 -0.2652
- 98DMSO CD2 392 2.488 1.315 1.469 -0.1997 0.1020 -0.1314
- 99DMSO SD 393 2.038 0.874 0.934 0.0099 0.1452 0.0585
- 99DMSO CD1 394 1.911 0.971 1.046 -0.3307 -0.1245 -0.0809
- 99DMSO OD 395 1.986 0.886 0.791 -0.3915 -0.5618 0.1344
- 99DMSO CD2 396 2.176 1.009 0.955 0.2420 -0.1675 0.5711
- 100DMSO SD 397 0.608 0.068 2.360 0.2726 -0.2182 -0.2080
- 100DMSO CD1 398 0.738 -0.070 2.406 0.0656 -0.2271 0.3965
- 100DMSO OD 399 0.464 0.017 2.344 0.0339 0.2191 0.5265
- 100DMSO CD2 400 0.619 0.187 2.513 0.0178 -0.8021 0.2797
- 101DMSO SD 401 2.541 0.968 2.291 0.0963 0.1489 -0.1637
- 101DMSO CD1 402 2.490 0.919 2.109 0.2565 -0.0835 -0.1403
- 101DMSO OD 403 2.597 0.847 2.367 -0.4964 0.0572 0.1389
- 101DMSO CD2 404 2.707 1.050 2.232 0.3061 -0.1277 0.0346
- 102DMSO SD 405 0.629 1.973 0.719 0.3509 -0.0200 0.5390
- 102DMSO CD1 406 0.676 2.162 0.714 0.3938 -0.0401 0.1071
- 102DMSO OD 407 0.515 1.961 0.821 -0.1986 -0.4479 -0.1136
- 102DMSO CD2 408 0.553 1.967 0.539 0.4058 -0.2096 0.5117
- 103DMSO SD 409 2.039 0.982 0.029 0.1833 0.0424 -0.1325
- 103DMSO CD1 410 2.010 0.834 0.152 0.0457 -0.1040 -0.3238
- 103DMSO OD 411 1.906 0.998 -0.045 0.2686 0.1808 -0.2516
- 103DMSO CD2 412 2.057 1.129 0.155 0.3392 -0.2314 0.1656
- 104DMSO SD 413 0.876 2.324 0.384 -0.2570 -0.0049 -0.0039
- 104DMSO CD1 414 0.878 2.214 0.224 0.2622 -0.5095 0.3540
- 104DMSO OD 415 0.925 2.464 0.347 -0.6843 0.0747 -0.2733
- 104DMSO CD2 416 0.682 2.341 0.400 -0.2055 0.5763 0.0523
- 105DMSO SD 417 1.597 0.932 0.372 0.1206 0.2313 0.0519
- 105DMSO CD1 418 1.412 0.872 0.349 0.2772 -0.0461 -0.5012
- 105DMSO OD 419 1.663 0.797 0.399 -0.4849 -0.1604 -0.3926
- 105DMSO CD2 420 1.647 0.973 0.188 0.4992 0.6778 0.2516
- 106DMSO SD 421 2.606 1.658 0.232 -0.1397 -0.1376 -0.1464
- 106DMSO CD1 422 2.738 1.514 0.234 -0.2130 -0.2158 -0.1342
- 106DMSO OD 423 2.628 1.751 0.352 -0.5670 -0.6492 0.3407
- 106DMSO CD2 424 2.690 1.766 0.093 0.1366 -0.2356 -0.0564
- 107DMSO SD 425 2.613 2.220 1.658 0.0119 0.0243 0.0181
- 107DMSO CD1 426 2.531 2.053 1.717 -0.1463 0.2493 0.4400
- 107DMSO OD 427 2.626 2.234 1.506 -0.0278 0.2090 0.0312
- 107DMSO CD2 428 2.476 2.344 1.719 -0.2533 -0.2320 -0.0536
- 108DMSO SD 429 1.733 0.864 1.841 -0.1562 -0.2969 -0.0235
- 108DMSO CD1 430 1.858 0.777 1.962 0.0554 -0.0410 -0.0588
- 108DMSO OD 431 1.718 0.774 1.718 0.2288 -0.0845 -0.2297
- 108DMSO CD2 432 1.586 0.813 1.958 -0.2254 -0.2918 -0.1063
- 109DMSO SD 433 1.224 0.496 0.028 -0.1609 0.0779 0.2900
- 109DMSO CD1 434 1.205 0.608 -0.131 0.0134 -0.0909 0.1495
- 109DMSO OD 435 1.341 0.403 -0.003 -0.0598 0.2145 0.2596
- 109DMSO CD2 436 1.302 0.642 0.131 0.3869 0.3299 -0.4742
- 110DMSO SD 437 2.282 2.546 2.809 0.2257 0.0805 -0.2098
- 110DMSO CD1 438 2.168 2.522 2.966 -0.3378 0.5472 -0.5387
- 110DMSO OD 439 2.183 2.558 2.693 0.0147 0.2780 -0.0086
- 110DMSO CD2 440 2.320 2.732 2.854 -0.2651 0.2164 -0.3520
- 111DMSO SD 441 0.804 2.723 1.491 0.0517 0.3680 -0.5189
- 111DMSO CD1 442 0.699 2.570 1.552 0.0996 0.2953 -0.6139
- 111DMSO OD 443 0.818 2.735 1.339 0.3318 0.3542 -0.4953
- 111DMSO CD2 444 0.668 2.852 1.548 0.3761 0.5181 -0.0781
- 112DMSO SD 445 1.181 0.519 1.099 -0.0826 -0.0729 0.4382
- 112DMSO CD1 446 1.278 0.360 1.156 0.1448 -0.1238 -0.0911
- 112DMSO OD 447 1.061 0.533 1.193 0.0809 -0.0790 0.6515
- 112DMSO CD2 448 1.318 0.648 1.148 0.2776 -0.3487 0.1354
- 113DMSO SD 449 0.457 2.509 2.383 0.1696 0.3233 0.0752
- 113DMSO CD1 450 0.641 2.458 2.422 -0.1013 -0.0961 0.8221
- 113DMSO OD 451 0.370 2.385 2.407 0.2973 0.1611 -0.2936
- 113DMSO CD2 452 0.422 2.622 2.538 -0.8641 0.0554 0.0463
- 114DMSO SD 453 2.401 0.836 2.808 -0.2128 -0.1463 -0.0981
- 114DMSO CD1 454 2.248 0.759 2.716 -0.2328 0.1590 -0.3216
- 114DMSO OD 455 2.496 0.727 2.858 -0.4117 -0.5898 -0.6822
- 114DMSO CD2 456 2.489 0.887 2.641 -0.0253 0.4162 0.1670
- 115DMSO SD 457 1.770 2.585 0.424 -0.0344 0.4057 0.2767
- 115DMSO CD1 458 1.617 2.622 0.308 -0.0173 -0.8045 -0.1565
- 115DMSO OD 459 1.896 2.556 0.342 -0.4847 -0.3446 -0.1652
- 115DMSO CD2 460 1.781 2.767 0.491 -0.2077 0.3592 0.4356
- 116DMSO SD 461 1.048 2.513 2.212 0.4781 0.2156 0.1028
- 116DMSO CD1 462 0.964 2.358 2.294 0.1961 0.4278 0.2207
- 116DMSO OD 463 0.973 2.633 2.271 -0.3278 -0.2685 0.0908
- 116DMSO CD2 464 1.218 2.490 2.305 0.4885 0.3585 0.1330
- 117DMSO SD 465 0.309 0.273 2.710 -0.4076 0.2875 -0.2674
- 117DMSO CD1 466 0.218 0.283 2.882 0.1233 -0.2716 0.0488
- 117DMSO OD 467 0.452 0.311 2.747 -0.3140 -0.6537 0.3729
- 117DMSO CD2 468 0.299 0.081 2.681 -0.1564 0.2214 0.0721
- 118DMSO SD 469 2.140 2.505 0.996 0.0912 -0.1371 -0.3457
- 118DMSO CD1 470 2.117 2.638 0.855 0.1457 -0.2322 -0.4480
- 118DMSO OD 471 2.221 2.561 1.112 0.0943 0.0021 -0.4066
- 118DMSO CD2 472 1.958 2.484 1.064 0.2792 0.3482 0.2983
- 119DMSO SD 473 1.142 1.579 2.039 0.0294 -0.2290 -0.1878
- 119DMSO CD1 474 1.096 1.433 1.918 0.3358 -0.2270 -0.2993
- 119DMSO OD 475 1.097 1.710 1.973 0.4293 0.0516 0.0982
- 119DMSO CD2 476 1.001 1.555 2.171 0.2286 0.1365 0.0964
- 120DMSO SD 477 0.324 1.059 1.605 0.2198 0.0240 -0.4507
- 120DMSO CD1 478 0.502 1.014 1.537 0.3518 0.4225 -0.3698
- 120DMSO OD 479 0.242 0.930 1.610 0.3337 -0.0506 -0.4857
- 120DMSO CD2 480 0.368 1.108 1.788 0.4653 -0.9913 -0.2319
- 121DMSO SD 481 0.880 0.411 2.249 -0.0859 0.1027 -0.4500
- 121DMSO CD1 482 0.774 0.562 2.187 -0.2706 0.0611 -0.2542
- 121DMSO OD 483 0.815 0.278 2.213 0.3090 -0.0896 -0.4612
- 121DMSO CD2 484 1.032 0.440 2.131 -0.0434 -0.5380 -0.5579
- 122DMSO SD 485 1.772 1.961 1.094 -0.1146 0.1997 -0.0458
- 122DMSO CD1 486 1.700 2.005 0.918 0.2429 0.7871 -0.0506
- 122DMSO OD 487 1.861 1.836 1.087 -0.3834 0.0174 -0.1813
- 122DMSO CD2 488 1.888 2.117 1.108 0.0931 0.0578 -0.0269
- 123DMSO SD 489 1.420 1.356 1.780 -0.1739 -0.1670 0.0523
- 123DMSO CD1 490 1.467 1.325 1.594 0.8104 -0.5050 0.3452
- 123DMSO OD 491 1.546 1.313 1.855 -0.0606 -0.4869 -0.3185
- 123DMSO CD2 492 1.440 1.550 1.769 -0.3335 -0.1727 -0.3403
- 124DMSO SD 493 1.602 1.608 2.313 0.4085 -0.2796 0.0905
- 124DMSO CD1 494 1.616 1.549 2.127 0.1305 -0.7141 0.2055
- 124DMSO OD 495 1.732 1.683 2.343 0.4296 -0.2294 -0.1166
- 124DMSO CD2 496 1.441 1.715 2.291 0.7070 0.2418 0.4127
- 125DMSO SD 497 0.549 1.608 0.734 -0.1525 -0.0255 0.5367
- 125DMSO CD1 498 0.547 1.416 0.766 0.0623 -0.1228 -0.0210
- 125DMSO OD 499 0.483 1.644 0.601 0.5245 0.2849 0.2742
- 125DMSO CD2 500 0.410 1.666 0.858 -0.9275 -0.2114 -0.2482
- 126DMSO SD 501 0.718 1.491 0.375 -0.2052 -0.3118 0.6995
- 126DMSO CD1 502 0.607 1.347 0.305 0.5428 -0.5009 -0.1221
- 126DMSO OD 503 0.854 1.479 0.305 -0.1991 -0.0021 0.6538
- 126DMSO CD2 504 0.632 1.634 0.275 -0.4927 -0.6809 0.4176
- 127DMSO SD 505 0.903 2.163 2.683 0.2428 0.0757 -0.4779
- 127DMSO CD1 506 0.963 2.020 2.801 -0.3007 0.0693 -0.2046
- 127DMSO OD 507 1.012 2.219 2.591 0.0249 0.5391 -0.4580
- 127DMSO CD2 508 0.778 2.077 2.560 0.0112 -0.4252 0.1084
- 128DMSO SD 509 1.434 2.617 1.971 -0.0859 0.1283 -0.3023
- 128DMSO CD1 510 1.299 2.736 1.895 -0.3933 -0.0947 -0.1116
- 128DMSO OD 511 1.359 2.489 2.010 0.0457 0.2286 0.2792
- 128DMSO CD2 512 1.517 2.590 1.796 0.0374 -0.1441 -0.2023
- 129DMSO SD 513 2.504 0.201 0.746 -0.3364 -0.0633 -0.0937
- 129DMSO CD1 514 2.459 0.388 0.783 0.1093 -0.1392 0.8600
- 129DMSO OD 515 2.374 0.121 0.762 0.1032 -0.8447 -0.3458
- 129DMSO CD2 516 2.533 0.209 0.553 -0.4621 0.3827 -0.0963
- 130DMSO SD 517 2.757 2.190 0.393 -0.1574 0.3281 -0.3412
- 130DMSO CD1 518 2.687 2.365 0.441 -0.6692 -0.0163 0.1980
- 130DMSO OD 519 2.865 2.159 0.497 -0.0507 0.3532 -0.4407
- 130DMSO CD2 520 2.608 2.078 0.448 0.5738 -0.3141 0.3603
- 131DMSO SD 521 0.682 1.250 2.266 0.1973 0.0018 0.3190
- 131DMSO CD1 522 0.663 1.082 2.363 0.4996 -0.4440 -0.3847
- 131DMSO OD 523 0.769 1.241 2.140 -0.1852 -0.3345 0.0728
- 131DMSO CD2 524 0.499 1.249 2.196 0.2899 0.6675 0.0545
- 132DMSO SD 525 1.504 0.058 2.159 0.0986 -0.1232 -0.2844
- 132DMSO CD1 526 1.402 0.196 2.252 0.3875 0.1905 -0.4296
- 132DMSO OD 527 1.649 0.099 2.182 0.1503 -0.1545 -0.5521
- 132DMSO CD2 528 1.450 -0.094 2.269 -0.3381 0.3558 0.1695
- 133DMSO SD 529 1.551 0.907 1.301 0.0302 0.4445 -0.1303
- 133DMSO CD1 530 1.586 0.976 1.480 -0.0725 -0.2787 0.1624
- 133DMSO OD 531 1.597 1.015 1.204 -0.2682 0.5460 -0.1608
- 133DMSO CD2 532 1.676 0.757 1.283 0.2005 0.6067 -0.3126
- 134DMSO SD 533 0.376 0.408 2.352 0.1977 -0.1167 0.4029
- 134DMSO CD1 534 0.348 0.382 2.161 -0.2598 0.2795 0.4078
- 134DMSO OD 535 0.428 0.552 2.363 -0.0606 0.0324 -0.1992
- 134DMSO CD2 536 0.189 0.400 2.406 -0.0780 -0.3566 -0.5636
- 135DMSO SD 537 2.878 2.311 2.551 -0.1371 0.2657 -0.0181
- 135DMSO CD1 538 2.961 2.479 2.604 0.5002 0.1187 -0.5305
- 135DMSO OD 539 2.728 2.342 2.544 -0.2185 -0.1299 -0.1708
- 135DMSO CD2 540 2.938 2.341 2.368 0.4312 0.0793 0.1359
- 136DMSO SD 541 0.699 2.552 0.789 -0.3341 -0.2693 -0.1130
- 136DMSO CD1 542 0.531 2.543 0.691 -0.3915 0.1928 -0.0456
- 136DMSO OD 543 0.745 2.423 0.857 -0.3594 0.0057 0.4315
- 136DMSO CD2 544 0.815 2.616 0.645 -0.0451 0.2491 0.3449
- 137DMSO SD 545 1.472 0.291 0.325 -0.1886 0.2542 0.1314
- 137DMSO CD1 546 1.370 0.139 0.257 0.3951 0.0895 -0.3888
- 137DMSO OD 547 1.374 0.382 0.399 -0.6422 -0.2500 0.1591
- 137DMSO CD2 548 1.576 0.209 0.468 -0.0191 0.5139 0.1521
- 138DMSO SD 549 0.476 0.126 1.872 0.3415 -0.0462 0.2664
- 138DMSO CD1 550 0.316 0.024 1.917 0.2154 -0.0807 -0.2612
- 138DMSO OD 551 0.585 0.028 1.828 0.5961 0.5114 -0.3713
- 138DMSO CD2 552 0.407 0.207 1.708 0.3921 0.5502 0.5344
- 139DMSO SD 553 2.116 0.912 1.635 0.1312 -0.1593 -0.0031
- 139DMSO CD1 554 2.034 0.920 1.459 -0.0192 0.0382 0.0739
- 139DMSO OD 555 2.254 0.973 1.610 -0.1758 0.6495 0.2151
- 139DMSO CD2 556 2.007 1.059 1.703 -0.5409 -0.8247 0.3789
- 140DMSO SD 557 0.493 2.206 1.247 -0.4223 -0.0542 0.0498
- 140DMSO CD1 558 0.478 2.014 1.275 0.0058 -0.1650 -0.4512
- 140DMSO OD 559 0.643 2.228 1.271 -0.3654 -0.0491 -0.3284
- 140DMSO CD2 560 0.460 2.187 1.056 -0.1231 -0.2276 0.0098
- 141DMSO SD 561 1.367 0.380 1.932 -0.1687 -0.5778 -0.1172
- 141DMSO CD1 562 1.491 0.258 1.844 0.2418 -0.0939 -0.2013
- 141DMSO OD 563 1.429 0.520 1.920 -0.1027 -0.6343 -0.4107
- 141DMSO CD2 564 1.215 0.360 1.812 -0.1037 0.2856 -0.3650
- 142DMSO SD 565 1.355 2.628 0.550 -0.0999 -0.0832 0.0556
- 142DMSO CD1 566 1.198 2.550 0.465 -0.2682 -0.1349 0.4175
- 142DMSO OD 567 1.396 2.758 0.480 -0.6365 0.2184 0.3019
- 142DMSO CD2 568 1.273 2.665 0.723 -0.1094 0.2233 -0.0039
- 143DMSO SD 569 1.054 1.283 1.460 0.3902 0.1688 -0.4272
- 143DMSO CD1 570 0.886 1.186 1.476 0.2590 0.4657 0.0056
- 143DMSO OD 571 1.087 1.366 1.584 0.2149 0.0923 -0.3287
- 143DMSO CD2 572 1.166 1.123 1.460 -0.2174 -0.2652 0.5351
- 144DMSO SD 573 1.761 2.339 2.246 -0.4389 0.1733 -0.2614
- 144DMSO CD1 574 1.570 2.310 2.276 -0.2967 -0.1323 0.3738
- 144DMSO OD 575 1.823 2.200 2.237 0.4928 0.5481 0.2193
- 144DMSO CD2 576 1.730 2.416 2.070 -0.0901 0.5084 -0.1719
- 145DMSO SD 577 1.817 0.364 2.133 -0.4628 -0.2088 -0.0437
- 145DMSO CD1 578 1.668 0.484 2.171 -0.4804 -0.0461 -0.6171
- 145DMSO OD 579 1.912 0.457 2.058 -0.2502 -0.1616 0.2826
- 145DMSO CD2 580 1.895 0.350 2.311 0.2323 0.0226 -0.3303
- 146DMSO SD 581 2.246 2.018 2.400 -0.3376 0.0613 0.2552
- 146DMSO CD1 582 2.110 2.152 2.441 -0.1727 0.3195 -0.0336
- 146DMSO OD 583 2.350 2.073 2.302 -0.4981 -0.1498 -0.0324
- 146DMSO CD2 584 2.333 1.986 2.571 -0.0744 0.7261 0.2563
- 147DMSO SD 585 0.259 2.042 2.281 0.2419 0.0130 -0.0623
- 147DMSO CD1 586 0.258 1.940 2.115 0.2771 0.1321 -0.1373
- 147DMSO OD 587 0.252 1.959 2.409 0.0100 0.4371 0.2050
- 147DMSO CD2 588 0.445 2.099 2.279 0.0476 0.6331 0.0665
- 148DMSO SD 589 1.048 2.460 1.697 0.1255 0.0430 0.0201
- 148DMSO CD1 590 1.127 2.351 1.838 0.3987 0.2525 0.0355
- 148DMSO OD 591 1.037 2.608 1.735 0.1327 0.0515 -0.0086
- 148DMSO CD2 592 1.198 2.456 1.572 -0.0175 -0.0880 -0.1489
- 149DMSO SD 593 2.504 1.655 1.792 -0.0640 -0.2806 -0.0496
- 149DMSO CD1 594 2.681 1.575 1.812 0.1608 0.1786 -0.1236
- 149DMSO OD 595 2.501 1.731 1.659 0.6272 -0.2788 -0.0716
- 149DMSO CD2 596 2.399 1.494 1.765 0.2910 -0.3886 -0.8544
- 150DMSO SD 597 2.096 1.612 2.556 0.2447 -0.0497 -0.0682
- 150DMSO CD1 598 2.071 1.696 2.382 0.2567 1.0148 0.4405
- 150DMSO OD 599 2.174 1.710 2.644 -0.3421 -0.1163 0.5318
- 150DMSO CD2 600 1.912 1.604 2.619 0.3438 0.1645 0.2525
- 151DMSO SD 601 1.215 0.081 1.571 -0.5589 0.0651 -0.2396
- 151DMSO CD1 602 1.175 -0.069 1.452 0.1236 -0.1781 -0.1634
- 151DMSO OD 603 1.181 0.212 1.501 -0.0402 0.1105 -0.4187
- 151DMSO CD2 604 1.082 0.041 1.708 -0.3162 0.7320 0.1859
- 152DMSO SD 605 2.293 0.605 1.038 0.1429 -0.4849 0.1823
- 152DMSO CD1 606 2.203 0.661 1.202 0.8484 0.1564 0.3499
- 152DMSO OD 607 2.425 0.539 1.079 0.3471 -0.1771 0.0331
- 152DMSO CD2 608 2.155 0.473 0.996 -0.2997 -0.0333 0.1661
- 153DMSO SD 609 1.172 2.044 2.366 -0.0449 0.1729 0.1518
- 153DMSO CD1 610 1.259 2.010 2.537 -0.2338 0.1899 0.2526
- 153DMSO OD 611 1.288 2.070 2.270 0.1103 -0.2843 0.2080
- 153DMSO CD2 612 1.107 1.861 2.347 0.2508 0.0072 0.7309
- 154DMSO SD 613 1.320 1.742 0.029 -0.0595 -0.3656 0.0203
- 154DMSO CD1 614 1.186 1.799 0.159 -0.0817 -0.2133 -0.0686
- 154DMSO OD 615 1.263 1.794 -0.103 -0.4796 -0.2233 0.2549
- 154DMSO CD2 616 1.471 1.848 0.092 0.0985 -0.2867 -0.4825
- 155DMSO SD 617 1.150 0.996 0.772 0.0993 0.2196 -0.2073
- 155DMSO CD1 618 1.123 1.173 0.849 -0.6772 -0.0474 0.1523
- 155DMSO OD 619 1.071 0.889 0.847 0.1662 0.0500 -0.3701
- 155DMSO CD2 620 1.067 1.030 0.599 -0.3142 0.1968 -0.0091
- 156DMSO SD 621 0.778 0.517 1.777 0.3797 0.0661 0.0544
- 156DMSO CD1 622 0.799 0.325 1.805 0.3310 0.0080 -0.2983
- 156DMSO OD 623 0.846 0.599 1.886 0.3763 -0.2121 0.2657
- 156DMSO CD2 624 0.886 0.536 1.615 -0.1285 -0.6314 -0.3843
- 157DMSO SD 625 0.480 1.548 1.713 -0.0474 -0.0907 -0.1302
- 157DMSO CD1 626 0.499 1.725 1.792 -0.0201 0.2339 -0.8574
- 157DMSO OD 627 0.567 1.548 1.588 0.3403 0.2287 0.1374
- 157DMSO CD2 628 0.570 1.443 1.850 -0.4316 -0.2750 -0.0154
- 158DMSO SD 629 0.856 2.065 2.111 -0.1651 -0.0590 -0.0391
- 158DMSO CD1 630 0.839 1.879 2.056 -0.0812 0.1094 -0.6167
- 158DMSO OD 631 0.850 2.081 2.263 0.2694 -0.0854 -0.0191
- 158DMSO CD2 632 1.035 2.085 2.037 -0.0659 1.5751 0.6037
- 159DMSO SD 633 2.838 0.900 2.619 0.2990 -0.0475 -0.3719
- 159DMSO CD1 634 2.875 0.950 2.804 0.1332 -0.4595 -0.2259
- 159DMSO OD 635 2.938 0.961 2.520 0.2830 0.5296 -0.0333
- 159DMSO CD2 636 2.871 0.709 2.646 0.0858 -0.0978 -0.3972
- 160DMSO SD 637 0.729 1.039 1.855 0.4033 -0.3943 0.3485
- 160DMSO CD1 638 0.855 1.188 1.852 0.1356 -0.1763 0.2640
- 160DMSO OD 639 0.734 0.962 1.723 -0.2241 -0.2957 0.2627
- 160DMSO CD2 640 0.816 0.925 1.987 -0.0295 -0.9507 0.1513
- 161DMSO SD 641 1.068 0.016 2.096 -0.0591 0.0677 -0.1827
- 161DMSO CD1 642 0.884 0.018 2.031 0.0347 0.0448 -0.4495
- 161DMSO OD 643 1.139 0.140 2.041 -0.3527 0.2661 -0.1240
- 161DMSO CD2 644 1.038 0.068 2.282 -0.4505 0.5552 -0.3757
- 162DMSO SD 645 2.070 1.404 0.961 0.2323 -0.6975 0.0547
- 162DMSO CD1 646 2.265 1.413 0.958 0.1705 0.8047 0.4531
- 162DMSO OD 647 2.039 1.315 1.082 -0.7955 -0.0415 0.2867
- 162DMSO CD2 648 2.035 1.591 1.001 -0.0895 -0.7003 -0.2125
- 163DMSO SD 649 1.961 1.936 1.562 -0.4267 0.3436 0.4410
- 163DMSO CD1 650 2.001 1.831 1.403 -0.2991 0.4544 0.3989
- 163DMSO OD 651 1.830 1.891 1.626 -0.2833 0.7110 1.0046
- 163DMSO CD2 652 2.108 1.850 1.659 -0.2323 -0.1017 -0.2518
- 164DMSO SD 653 1.188 0.944 1.911 -0.2782 -0.2675 0.1878
- 164DMSO CD1 654 1.135 0.758 1.880 0.8256 -0.7036 0.8622
- 164DMSO OD 655 1.263 0.936 2.044 0.0089 -0.1018 0.0347
- 164DMSO CD2 656 1.319 0.971 1.770 0.0026 0.1839 0.5326
- 165DMSO SD 657 1.791 0.450 0.154 0.0215 0.3325 -0.2383
- 165DMSO CD1 658 1.703 0.339 0.020 -0.5234 -0.0636 0.4493
- 165DMSO OD 659 1.918 0.505 0.090 0.0240 0.5022 -0.0794
- 165DMSO CD2 660 1.645 0.578 0.173 -0.0378 0.1825 0.4341
- 166DMSO SD 661 2.064 1.503 1.486 -0.0331 -0.0087 0.4572
- 166DMSO CD1 662 2.094 1.311 1.484 -0.0302 -0.0043 0.1865
- 166DMSO OD 663 2.148 1.581 1.384 0.1960 -0.5856 0.1940
- 166DMSO CD2 664 1.885 1.499 1.410 -0.0712 -1.3472 0.6192
- 167DMSO SD 665 2.263 2.122 0.108 -0.2297 0.1813 0.1929
- 167DMSO CD1 666 2.403 2.255 0.132 -0.3150 0.3548 -0.2026
- 167DMSO OD 667 2.265 2.084 -0.041 0.4679 0.2043 0.1915
- 167DMSO CD2 668 2.363 1.982 0.200 0.4052 0.2834 -0.3283
- 168DMSO SD 669 0.117 2.269 0.737 -0.1346 -0.0546 -0.3640
- 168DMSO CD1 670 0.305 2.223 0.712 -0.1321 -0.0391 -0.3489
- 168DMSO OD 671 0.085 2.255 0.886 -0.4892 -0.3039 -0.4624
- 168DMSO CD2 672 0.119 2.460 0.694 0.0889 0.1445 0.5230
- 169DMSO SD 673 0.596 0.146 0.132 0.0566 0.3260 -0.3020
- 169DMSO CD1 674 0.649 0.017 -0.004 0.1754 -0.2245 0.2572
- 169DMSO OD 675 0.639 0.097 0.270 -0.1787 -0.6318 -0.5615
- 169DMSO CD2 676 0.733 0.268 0.066 0.1099 0.3647 -0.1238
- 170DMSO SD 677 0.538 1.880 2.809 0.4107 -0.1246 0.0415
- 170DMSO CD1 678 0.617 2.006 2.935 0.3454 0.2421 -0.2837
- 170DMSO OD 679 0.569 1.749 2.883 -0.4922 -0.4225 -0.0924
- 170DMSO CD2 680 0.351 1.926 2.837 0.2746 -0.2459 -0.6329
- 171DMSO SD 681 2.566 2.694 1.307 -0.1653 -0.0415 -0.1119
- 171DMSO CD1 682 2.632 2.826 1.435 -0.3651 -0.0646 0.0175
- 171DMSO OD 683 2.679 2.630 1.227 0.5546 0.7292 0.2639
- 171DMSO CD2 684 2.501 2.568 1.441 -0.1863 0.0849 -0.0005
- 172DMSO SD 685 1.675 2.096 2.529 -0.3535 0.1203 -0.1738
- 172DMSO CD1 686 1.607 1.982 2.671 -0.4500 0.4515 0.0430
- 172DMSO OD 687 1.762 2.205 2.591 0.0834 -0.3155 -0.0107
- 172DMSO CD2 688 1.822 1.980 2.474 -0.3094 0.1946 -0.2161
- 173DMSO SD 689 1.266 1.260 2.274 -0.0234 0.2192 -0.1372
- 173DMSO CD1 690 1.256 1.126 2.414 -0.2467 0.3253 -0.0511
- 173DMSO OD 691 1.332 1.385 2.332 0.0195 0.0229 0.2428
- 173DMSO CD2 692 1.382 1.191 2.132 0.6480 0.8817 0.0812
- 174DMSO SD 693 2.343 1.339 2.089 -0.2559 0.2204 0.1801
- 174DMSO CD1 694 2.375 1.381 2.277 0.0271 -0.1672 0.2233
- 174DMSO OD 695 2.475 1.293 2.026 -0.3816 0.3194 -0.1596
- 174DMSO CD2 696 2.223 1.188 2.116 0.2451 -0.1707 0.2670
- 175DMSO SD 697 2.127 0.392 0.495 0.0122 0.3820 0.3899
- 175DMSO CD1 698 2.162 0.494 0.333 -0.6112 -0.3095 -0.1854
- 175DMSO OD 699 2.140 0.488 0.614 0.4100 0.5191 0.2433
- 175DMSO CD2 700 1.935 0.375 0.470 0.0303 0.1945 0.4298
- 176DMSO SD 701 0.239 1.785 0.401 -0.5069 0.2832 0.0894
- 176DMSO CD1 702 0.230 1.590 0.391 0.0746 0.2518 0.1275
- 176DMSO OD 703 0.231 1.817 0.252 -0.9473 -0.3318 -0.0230
- 176DMSO CD2 704 0.064 1.799 0.485 -0.2960 0.5595 0.4891
- 177DMSO SD 705 1.396 0.016 1.071 -0.1144 0.1569 0.0587
- 177DMSO CD1 706 1.503 0.128 0.953 0.1135 -0.0272 0.0886
- 177DMSO OD 707 1.365 -0.107 0.986 0.3799 0.0701 0.0062
- 177DMSO CD2 708 1.553 -0.023 1.181 0.3381 -0.1884 -0.7117
- 178DMSO SD 709 2.319 0.193 2.237 -0.2670 0.0102 0.3959
- 178DMSO CD1 710 2.471 0.275 2.147 -0.4940 -0.4100 -0.3750
- 178DMSO OD 711 2.272 0.280 2.354 -0.1281 0.1917 0.3198
- 178DMSO CD2 712 2.201 0.220 2.085 0.7844 0.0157 -0.4319
- 179DMSO SD 713 0.230 0.620 0.617 0.1583 -0.2518 -0.1791
- 179DMSO CD1 714 0.130 0.664 0.456 0.0641 0.6493 0.1216
- 179DMSO OD 715 0.271 0.765 0.647 -0.1482 -0.0426 -0.7612
- 179DMSO CD2 716 0.069 0.585 0.720 0.0834 0.3038 -0.1042
- 180DMSO SD 717 2.359 2.527 2.307 -0.1165 -0.0396 -0.2913
- 180DMSO CD1 718 2.200 2.601 2.392 0.1767 -0.0575 0.2958
- 180DMSO OD 719 2.464 2.638 2.298 0.0850 -0.2782 -0.9689
- 180DMSO CD2 720 2.414 2.407 2.451 0.2623 -0.1531 -0.5156
- 181DMSO SD 721 1.881 1.433 1.866 0.3126 0.0091 -0.0188
- 181DMSO CD1 722 1.831 1.593 1.767 -0.1053 0.1206 0.3704
- 181DMSO OD 723 1.982 1.363 1.775 0.3560 -0.4274 0.3566
- 181DMSO CD2 724 1.981 1.517 2.012 0.3822 0.4205 -0.3030
- 182DMSO SD 725 0.326 2.397 0.306 -0.0782 0.0883 0.0799
- 182DMSO CD1 726 0.136 2.374 0.344 -0.0743 -0.0801 0.0063
- 182DMSO OD 727 0.385 2.412 0.446 0.2287 -0.5969 0.0220
- 182DMSO CD2 728 0.350 2.211 0.254 -0.4572 -0.0446 0.3519
- 183DMSO SD 729 0.067 1.084 0.291 -0.1385 -0.2201 -0.2065
- 183DMSO CD1 730 0.171 1.086 0.456 0.4652 -0.1882 -0.5817
- 183DMSO OD 731 0.016 0.942 0.268 0.0739 -0.1577 -1.1117
- 183DMSO CD2 732 -0.082 1.192 0.354 0.3045 0.4748 -0.3061
- 184DMSO SD 733 0.039 2.149 -0.022 -0.1551 0.5456 -0.1496
- 184DMSO CD1 734 -0.155 2.168 -0.033 -0.1401 0.7730 -0.0391
- 184DMSO OD 735 0.100 2.275 0.038 0.3040 0.5380 -0.5956
- 184DMSO CD2 736 0.065 2.013 0.116 0.2010 0.7491 -0.0147
- 185DMSO SD 737 0.809 0.351 1.104 0.0639 -0.1681 0.2080
- 185DMSO CD1 738 0.888 0.181 1.158 -0.0080 -0.1683 0.3252
- 185DMSO OD 739 0.658 0.331 1.088 0.0164 -0.0265 0.4699
- 185DMSO CD2 740 0.820 0.443 1.276 -0.1125 0.4117 -0.0879
- 186DMSO SD 741 1.582 1.429 1.178 -0.0836 -0.3788 0.2447
- 186DMSO CD1 742 1.724 1.321 1.098 0.0486 -0.3623 0.4322
- 186DMSO OD 743 1.517 1.509 1.066 0.0144 -0.0023 0.4566
- 186DMSO CD2 744 1.458 1.283 1.218 -0.4545 -0.1671 -0.1037
- 187DMSO SD 745 0.026 2.726 -0.025 0.0808 0.1849 -0.1883
- 187DMSO CD1 746 0.014 2.816 0.147 -0.1929 0.3271 -0.2842
- 187DMSO OD 747 0.172 2.681 -0.029 0.0264 0.0114 -0.2821
- 187DMSO CD2 748 -0.097 2.576 -0.000 0.2227 0.1327 0.2141
- 188DMSO SD 749 2.308 1.625 0.476 0.1520 0.1563 0.1143
- 188DMSO CD1 750 2.287 1.526 0.309 0.0827 0.2038 0.0899
- 188DMSO OD 751 2.276 1.772 0.449 -0.0720 0.2359 0.7602
- 188DMSO CD2 752 2.158 1.568 0.587 0.2636 -0.8618 -0.2621
- 189DMSO SD 753 2.593 0.288 1.271 0.1819 -0.2789 -0.4347
- 189DMSO CD1 754 2.546 0.457 1.356 1.4617 -0.1239 0.0028
- 189DMSO OD 755 2.637 0.211 1.396 -0.3781 -0.0059 -0.0657
- 189DMSO CD2 756 2.410 0.237 1.227 0.0538 0.2526 -0.5684
- 190DMSO SD 757 2.393 1.477 -0.043 0.0426 -0.5414 0.0704
- 190DMSO CD1 758 2.340 1.662 -0.015 0.4222 -0.3593 -0.3541
- 190DMSO OD 759 2.475 1.438 0.080 0.0837 -0.1082 0.1761
- 190DMSO CD2 760 2.222 1.386 -0.019 -0.2866 -0.0182 -0.2640
- 191DMSO SD 761 1.426 0.509 0.682 -0.1246 0.0377 0.1999
- 191DMSO CD1 762 1.565 0.603 0.583 -0.0945 -0.5540 -0.3254
- 191DMSO OD 763 1.431 0.544 0.831 0.9135 0.4520 0.0736
- 191DMSO CD2 764 1.271 0.612 0.624 0.3751 0.4102 -0.4852
- 192DMSO SD 765 0.458 0.771 0.309 0.2015 0.3997 -0.2951
- 192DMSO CD1 766 0.554 0.660 0.181 0.1738 -0.3338 0.3085
- 192DMSO OD 767 0.527 0.905 0.329 0.5907 0.1408 0.1112
- 192DMSO CD2 768 0.309 0.815 0.191 -0.0749 -0.3164 -0.2203
- 193DMSO SD 769 0.141 2.931 2.317 -0.2157 -0.2062 -0.0861
- 193DMSO CD1 770 0.016 2.899 2.171 0.0250 0.0049 -0.3403
- 193DMSO OD 771 0.065 2.969 2.444 -0.5411 -0.5072 -0.1906
- 193DMSO CD2 772 0.208 2.748 2.326 -0.0677 -0.1434 0.1048
- 194DMSO SD 773 2.525 2.209 0.910 0.1612 -0.1880 -0.0201
- 194DMSO CD1 774 2.688 2.182 1.013 0.0767 0.7284 0.3851
- 194DMSO OD 775 2.414 2.123 0.971 0.1267 0.0851 0.2987
- 194DMSO CD2 776 2.485 2.384 0.987 0.7945 0.0585 -0.2435
- 195DMSO SD 777 2.050 0.204 2.586 0.1599 -0.0480 0.2195
- 195DMSO CD1 778 2.217 0.127 2.651 0.0037 0.3714 1.1371
- 195DMSO OD 779 1.949 0.129 2.673 0.4907 -0.3491 0.3453
- 195DMSO CD2 780 2.085 0.383 2.655 -0.4045 0.2899 -0.3580
- 196DMSO SD 781 1.744 0.642 2.585 0.0504 0.0463 -0.5525
- 196DMSO CD1 782 1.910 0.717 2.655 0.3088 -1.0352 0.0215
- 196DMSO OD 783 1.731 0.490 2.596 0.5257 0.0490 0.1210
- 196DMSO CD2 784 1.628 0.688 2.735 0.4828 -0.0142 -0.1985
- 197DMSO SD 785 2.479 0.980 0.366 -0.1036 -0.1347 0.2435
- 197DMSO CD1 786 2.603 0.920 0.228 0.0702 -0.4369 0.5299
- 197DMSO OD 787 2.555 1.019 0.493 -0.0647 -0.0442 0.1936
- 197DMSO CD2 788 2.394 1.121 0.260 0.2174 -0.4294 -0.4146
- 198DMSO SD 789 2.073 0.553 1.652 -0.2987 0.3349 0.0174
- 198DMSO CD1 790 1.953 0.439 1.754 -0.3820 0.1532 -0.2817
- 198DMSO OD 791 2.185 0.466 1.594 -0.2211 0.3388 0.1617
- 198DMSO CD2 792 1.942 0.585 1.511 0.0405 -0.7390 -0.5612
- 199DMSO SD 793 2.348 2.792 0.411 -0.0739 -0.1142 0.1751
- 199DMSO CD1 794 2.248 2.627 0.439 -0.2279 -0.0411 0.0694
- 199DMSO OD 795 2.329 2.857 0.274 0.7038 -0.2502 0.0011
- 199DMSO CD2 796 2.226 2.897 0.522 -0.0331 0.6099 -0.4490
- 200DMSO SD 797 0.605 0.134 0.647 -0.0462 -0.2846 0.0058
- 200DMSO CD1 798 0.796 0.155 0.680 -0.0575 -0.4839 0.2066
- 200DMSO OD 799 0.579 -0.014 0.677 0.6258 -0.4649 -0.2767
- 200DMSO CD2 800 0.542 0.228 0.805 -0.0580 -0.0760 -0.1219
- 201DMSO SD 801 1.585 1.731 1.446 -0.1947 -0.0247 0.3547
- 201DMSO CD1 802 1.530 1.888 1.547 0.5073 0.5125 -0.0998
- 201DMSO OD 803 1.506 1.607 1.491 -0.4009 0.2261 0.6904
- 201DMSO CD2 804 1.515 1.781 1.271 0.1125 -0.6604 0.0497
- 202DMSO SD 805 -0.037 1.908 1.848 0.3234 0.0831 0.1783
- 202DMSO CD1 806 0.113 1.787 1.816 0.3056 0.1751 -0.2702
- 202DMSO OD 807 -0.040 1.937 1.998 0.3274 -0.8189 0.3496
- 202DMSO CD2 808 0.037 2.055 1.743 -0.2584 0.1357 -0.1816
- 203DMSO SD 809 0.613 2.508 2.047 -0.1770 -0.1717 -0.5288
- 203DMSO CD1 810 0.537 2.641 1.927 -0.1501 0.2539 -0.0802
- 203DMSO OD 811 0.523 2.385 2.034 -0.1143 -0.2151 -0.5655
- 203DMSO CD2 812 0.783 2.488 1.953 0.5404 0.5641 0.5760
- 204DMSO SD 813 1.037 0.098 2.608 0.3241 -0.2840 -0.2910
- 204DMSO CD1 814 1.140 0.139 2.768 0.0354 -0.5712 -0.0290
- 204DMSO OD 815 0.894 0.060 2.647 0.1065 0.2757 -0.5254
- 204DMSO CD2 816 1.027 0.284 2.550 -0.6331 -0.3315 -0.3341
- 205DMSO SD 817 0.396 0.367 0.319 -0.2819 -0.1180 -0.0154
- 205DMSO CD1 818 0.276 0.281 0.446 0.0777 0.1885 0.5338
- 205DMSO OD 819 0.303 0.473 0.261 -0.6565 -0.1986 0.4438
- 205DMSO CD2 820 0.517 0.439 0.453 0.2228 -0.5648 -0.2129
- 206DMSO SD 821 0.816 1.213 1.124 -0.4610 0.0448 0.0922
- 206DMSO CD1 822 0.766 1.082 0.988 -0.2183 0.0845 -0.0384
- 206DMSO OD 823 0.950 1.149 1.159 -0.0710 0.6546 -0.2924
- 206DMSO CD2 824 0.837 1.363 1.001 0.5192 0.0666 0.2725
- 207DMSO SD 825 1.541 2.288 1.281 0.1023 0.1094 0.0821
- 207DMSO CD1 826 1.483 2.469 1.325 -0.1763 0.1235 -0.3533
- 207DMSO OD 827 1.659 2.317 1.187 0.2348 -0.3310 0.1077
- 207DMSO CD2 828 1.602 2.207 1.447 -0.1681 0.0018 0.1306
- 208DMSO SD 829 1.691 2.239 0.183 -0.4203 -0.0751 0.3402
- 208DMSO CD1 830 1.648 2.274 -0.004 0.1103 0.0923 0.2410
- 208DMSO OD 831 1.653 2.094 0.216 0.0492 -0.2086 0.2908
- 208DMSO CD2 832 1.881 2.242 0.139 -0.6149 0.8721 -0.4796
- 2.89162 2.89162 2.89162
+++ /dev/null
-[ moleculetype ]
-; name nrexcl
-DMSO 2
-
-[ atoms ]
-; nr type resnr residu atom cgnr charge
- 1 SD 1 DMSO SD 1 0.139
- 2 CD 1 DMSO CD1 1 0.16
- 3 OD 1 DMSO OD 1 -0.459
- 4 CD 1 DMSO CD2 1 0.16
-
-[ bonds ]
-; ai aj funct b0 kb
- 1 2 1 0.195 376560 ; kb from Methionine
- 1 3 1 0.153 502080 ; kb from C=O bond
- 1 4 1 0.195 376560
-
-[ angles ]
-; ai aj ak funct theta kt
-3 1 2 1 106.75 460.240
-3 1 4 1 106.75 460.240
-2 1 4 1 97.40 460.240 ; kt from Methionine
-
-[ dihedrals ]
-; ai aj ak al funct xi kxi
-1 2 4 3 2 35.264 334.720 ; default params
aminoacids.hdb ffbonded.itp \
aminoacids.n.tdb ffnonbonded.itp \
aminoacids.rtp forcefield.doc \
-forcefield.itp
+aminoacids.r2b forcefield.itp watermodels.dat
EXTRA_DIST = ${topol_DATA}
[ COO- ]
[ replace ]
-C Abis 12.011 0.84
+C C Abis 12.011 0.84
+O O1 Obis 15.9994 -0.92
+OXT O2 Obis 15.9994 -0.92
[ add ]
2 8 O C CA N
Obis 15.9994 -0.92
-[ delete ]
-O
[ dihedrals ]
N CA C O2
[ impropers ]
[ Gly-COO- ]
[ replace ]
-C Abis 12.011 0.84
+C C Abis 12.011 0.84
+O O Obis 15.9994 -0.92
+OXT O2 Obis 15.9994 -0.92
[ add ]
2 8 O C CA N
Obis 15.9994 -0.92
-[ delete ]
-O
[ dihedrals ]
N CA C O2
[ impropers ]
[ COOH ]
[ replace ]
-C Aprime 12.011 0.38
-O OH 15.9994 -0.38
+C C Aprime 12.011 0.38
+O O OH 15.9994 -0.38
+OXT OT O 15.9994 -0.433
[ add ]
1 2 OT C CA N
O 15.9994 -0.433
1 2 HO O C CA
HO 1.008 0.433
[ dihedrals ]
-N CA C O1
+N CA C O
[ impropers ]
-O2 CA C O1 improper_X_X_A_X
+OT CA C O improper_X_X_A_X
--- /dev/null
+; rtp residue to rtp building block table
+;GMX Force-field
+CYS CYSH
+HISD HISA
+HISE HISB
+LYS LYSH
+LYSN LYS
-Encad all-atom force field, using full solvent charges
+[DEPRECATED] Encad all-atom force field, using full solvent charges
--- /dev/null
+f3c F3C flexible three-centered water model
aminoacids.hdb ffbonded.itp \
aminoacids.n.tdb ffnonbonded.itp \
aminoacids.rtp forcefield.doc \
-forcefield.itp
+aminoacids.r2b forcefield.itp watermodels.dat
EXTRA_DIST = ${topol_DATA}
[ COO- ]
[ replace ]
-C Abis 12.011 0.64
+C C Abis 12.011 0.64
+O O1 Obis 15.9994 -0.42
+OXT O2 Obis 15.9994 -0.42
[ add ]
2 8 O C CA N
- Obis 15.9994 -0.42
-[ delete ]
-O
+ Obis 15.9994 -0.92
[ dihedrals ]
N CA C O2
[ impropers ]
[ COOH ]
[ replace ]
-C Aprime 12.011 0.38
-O OH 15.9994 -0.38
+C C Aprime 12.011 0.38
+O O OH 15.9994 -0.38
+OXT OT O 15.9994 -0.433
[ add ]
1 2 OT C CA N
O 15.9994 -0.433
1 2 HO O C CA
HO 1.008 0.433
[ dihedrals ]
-N CA C O1
+N CA C O
[ impropers ]
-O2 CA C O1 improper_X_X_A_X
+OT CA C O improper_X_X_A_X
--- /dev/null
+; rtp residue to rtp building block table
+;GMX Force-field
+CYS CYSH
+HISD HISA
+HISE HISB
+LYS LYSH
+LYSN LYS
-Encad all-atom force field, using scaled-down vacuum charges
+[DEPRECATED] Encad all-atom force field, using scaled-down vacuum charges
--- /dev/null
+f3c F3C flexible three-centered water model
aminoacids.hdb ffbonded.itp spc.itp \
aminoacids.n.tdb ffnonbonded.itp spce.itp \
aminoacids.rtp forcefield.doc tip3p.itp \
-aminoacids.vsd forcefield.itp tip4p.itp
+aminoacids.vsd forcefield.itp tip4p.itp \
+h2p4o13.itp h2p8o25.itp h2po4.itp \
+1mlg.itp 2mlg.itp decane.itp \
+dlg.itp fa.itp tfe.itp \
+decane50.gro watermodels.dat
EXTRA_DIST = ${topol_DATA}
OW OWT4 0.0 0
HW1 HW 0.52 0
HW2 HW 0.52 0
- HW3 IW -1.04 0
+ MW IW -1.04 0
[ bonds ]
OW HW1 gb_35
OW HW2 gb_35
- OW HW3 gb_35
[ HYP ]
[ atoms ]
--- /dev/null
+spc SPC simple point charge, recommended
+spce SPC/E extended simple point charge
+tip3p TIP3P TIP 3-point
+tip4p TIP4P TIP 4-point
aminoacids.hdb ffbonded.itp spc.itp \
aminoacids.n.tdb ffnonbonded.itp spce.itp \
aminoacids.rtp forcefield.doc tip3p.itp \
-aminoacids.vsd forcefield.itp tip4p.itp
+aminoacids.vsd forcefield.itp tip4p.itp \
+watermodels.dat
EXTRA_DIST = ${topol_DATA}
OW OWT4 0.0 0
HW1 H 0.52 0
HW2 H 0.52 0
- HW3 IW -1.04 0
+ MW IW -1.04 0
[ bonds ]
OW HW1
OW HW2
- OW HW3
[ HYP ]
[ atoms ]
--- /dev/null
+spc SPC simple point charge, recommended
+spce SPC/E extended simple point charge
+tip3p TIP3P TIP 3-point
+tip4p TIP4P TIP 4-point
aminoacids.hdb ffbonded.itp spc.itp \
aminoacids.n.tdb ffnonbonded.itp spce.itp \
aminoacids.rtp forcefield.doc tip3p.itp \
-aminoacids.vsd forcefield.itp tip4p.itp
+aminoacids.vsd forcefield.itp tip4p.itp \
+aminoacids.r2b methanol.itp methanol216.gro \
+watermodels.dat
EXTRA_DIST = ${topol_DATA}
--- /dev/null
+; rtp residue to rtp building block table
+;GMX Force-field
+CYS CYSH
+HISD HISA
+HISE HISB
+LYS LYSH
+LYSN LYS
; bonds angles dihedrals impropers all_dihedrals nrexcl HH14 RemoveDih
2 2 1 2 0 3 0 1
-
[ ACE ]
[ atoms ]
CA CH3 0.000 0
C O gb_4
C +N gb_9
[ angles ]
+ CA C O ga_30
CA C +N ga_18
O C +N ga_32
[ impropers ]
OW OWT4 0.0 0
HW1 H 0.52 0
HW2 H 0.52 0
- HW3 IW -1.04 0
+ MW IW -1.04 0
[ bonds ]
OW HW1 gb_35
OW HW2 gb_35
- OW HW3 gb_35
[ angles ]
; ai aj ak gromos type
[ impropers ]
[ CHCL3 ]
[ atoms ]
- CChl CCHL 0.17900 0
- HChl HCHL 0.08200 0
-CLCh1 CLCHL -0.08700 0
-CLCh2 CLCHL -0.08700 0
-CLCh3 CLCHL -0.08700 0
+ CChl CChl 0.17900 0
+ HChl HChl 0.08200 0
+CLCh1 CLChl -0.08700 0
+CLCh2 CLChl -0.08700 0
+CLCh3 CLChl -0.08700 0
[ bonds ]
CChl CLCh1 gb_37
CChl CLCh2 gb_37
[ DMSO ]
[ atoms ]
-SDmso SDMSO 0.13900 0
-ODmso ODMSO -0.45900 0
-CDms1 CDMSO 0.16000 0
-CDms2 CDMSO 0.16000 0
+SDmso SDmso 0.13900 0
+ODmso ODmso -0.45900 0
+CDms1 CDmso 0.16000 0
+CDms2 CDmso 0.16000 0
[ bonds ]
SDmso ODmso gb_38
SDmso CDms1 gb_39
[ CH3OH ]
[ atoms ]
- Omet OMET -0.57400 0
+ Omet OMet -0.57400 0
HMet H 0.39800 0
- CMet CMET 0.17600 0
+ CMet CMet 0.17600 0
[ bonds ]
Omet HMet gb_1
Omet CMet gb_17
[ CCL4 ]
[ atoms ]
- CCl4 CCL4 0.00000 0
-CLCl1 CLCL4 0.00000 0
-CLCl2 CLCL4 0.00000 0
-CLCl3 CLCL4 0.00000 0
-CLCl4 CLCL4 0.00000 0
+ CCl4 CCl4 0.00000 0
+CLCl1 CLCl4 0.00000 0
+CLCl2 CLCl4 0.00000 0
+CLCl3 CLCl4 0.00000 0
+CLCl4 CLCl4 0.00000 0
[ bonds ]
CCl4 CLCl1 gb_40
CCl4 CLCl2 gb_40
F 18.99840 ; fluor (non-ionic)
CL 35.45300 ; chlorine (non-ionic)
BR 79.90400 ; bromine (non-ionic)
- CMET 15.035 ; CH3-group in methanol (solvent)
- OMET 15.9994 ; oxygen in methanol (solvent)
+ CMet 15.035 ; CH3-group in methanol (solvent)
+ OMet 15.9994 ; oxygen in methanol (solvent)
NA+ 22.9898 ; sodium (charge 1+)
CL- 35.45300 ; chlorine (charge 1-)
- CCHL 12.011 ; carbon in chloroform (solvent)
-CLCHL 35.453 ; chloride in chloroform (solvent)
- HCHL 1.008 ; hydrogen in chloroform (solvent)
-SDMSO 32.06000 ; DMSO Sulphur (solvent)
-CDMSO 15.03500 ; DMSO Carbon (solvent)
-ODMSO 15.99940 ; DMSO Oxygen (solvent)
- CCL4 12.011 ; carbon in carbontetrachloride (solvent)
-CLCL4 35.453 ; chloride in carbontetrachloride (solvent)
+ CChl 12.011 ; carbon in chloroform (solvent)
+CLChl 35.453 ; chloride in chloroform (solvent)
+ HChl 1.008 ; hydrogen in chloroform (solvent)
+SDmso 32.06000 ; DMSO Sulphur (solvent)
+CDmso 15.03500 ; DMSO Carbon (solvent)
+ODmso 15.99940 ; DMSO Oxygen (solvent)
+ CCl4 12.011 ; carbon in carbontetrachloride (solvent)
+CLCl4 35.453 ; chloride in carbontetrachloride (solvent)
SI 28.08 ; silicon
MNH3 0 ; Dummy mass in rigid tetraedrical NH3 group
MW 0 ; Dummy mass in rigid tyrosine rings
F 9 0.000 0.000 A 0.0011778624 7.6073284e-07
CL 17 0.000 0.000 A 0.0087647044 1.5295921e-05
BR 35 0.000 0.000 A 0.0011792356 6.5480464e-05
- CMET 6 0.000 0.000 A 0.0088755241 2.0852922e-05
- OMET 8 0.000 0.000 A 0.0022619536 1.505529e-06
+ CMet 6 0.000 0.000 A 0.0088755241 2.0852922e-05
+ OMet 8 0.000 0.000 A 0.0022619536 1.505529e-06
NA+ 11 0.000 0.000 A 7.2063121e-05 2.1025e-08
CL- 17 0.000 0.000 A 0.01380625 0.0001069156
- CCHL 6 0.000 0.000 A 0.0026308693 4.064256e-06
-CLCHL 17 0.000 0.000 A 0.0083066819 1.3764842e-05
- HCHL 1 0.000 0.000 A 3.76996e-05 4.2999495e-09
-SDMSO 16 0.000 0.000 A 0.010561673 2.149806e-05
-CDMSO 6 0.000 0.000 A 0.0090514293 2.175756e-05
-ODMSO 8 0.000 0.000 A 0.0022707131 7.5144626e-07
- CCL4 6 0.000 0.000 A 0.0026308693 7.5999462e-06
-CLCL4 17 0.000 0.000 A 0.0076040144 1.2767758e-05
+ CChl 6 0.000 0.000 A 0.0026308693 4.064256e-06
+CLChl 17 0.000 0.000 A 0.0083066819 1.3764842e-05
+ HChl 1 0.000 0.000 A 3.76996e-05 4.2999495e-09
+SDmso 16 0.000 0.000 A 0.010561673 2.149806e-05
+CDmso 6 0.000 0.000 A 0.0090514293 2.175756e-05
+ODmso 8 0.000 0.000 A 0.0022707131 7.5144626e-07
+ CCl4 6 0.000 0.000 A 0.0026308693 7.5999462e-06
+CLCl4 17 0.000 0.000 A 0.0076040144 1.2767758e-05
SI 14 0.000 0.000 A 0.01473796 2.2193521e-05
MNH3 0 0.000 0.000 A 0.0 0.0
OWT3 8 15.9994 0.000 A 0.24889E-02 0.24352E-05
BR AR 1 0.002718011 2.5392696e-05
BR F 1 0.0011785488 7.0578424e-06
BR CL 1 0.0032149108 3.1647812e-05
- CMET O 1 0.0044806276 3.9322131e-06
- CMET OM 1 0.0044806276 3.9322131e-06
- CMET OA 1 0.0044806276 5.1373125e-06
- CMET OW 1 0.0048197836 7.050676e-06
- CMET N 1 0.0046502056 5.9410165e-06
- CMET NT 1 0.0046502056 5.9410165e-06
- CMET NL 1 0.0046502056 5.9410165e-06
- CMET NR 1 0.0046502056 5.9410165e-06
- CMET NZ 1 0.0046502056 5.9410165e-06
- CMET NE 1 0.0046502056 5.9410165e-06
- CMET C 1 0.0045578798 8.3886605e-06
- CMET CH1 1 0.0057920308 1.5402804e-05
- CMET CH2 1 0.0079409609 2.318412e-05
- CMET CH3 1 0.0093814318 2.6458301e-05
- CMET CH4 1 0.010815308 2.6768823e-05
- CMET CR1 1 0.0069950925 1.7754552e-05
- CMET HC 1 0.000866732 5.616795e-07
- CMET H 1 0 0
- CMET DUM 1 0 0
- CMET S 1 0.0094134632 1.6512464e-05
- CMET CU1+ 1 0.0019265945 3.2691574e-07
- CMET CU2+ 1 0.0019265945 3.2691574e-07
- CMET FE 1 0 0
- CMET ZN2+ 1 0.0019265945 4.4368114e-07
- CMET MG2+ 1 0.0007612168 2.6659227e-07
- CMET CA2+ 1 0.002986457 3.222579e-06
- CMET P 1 0.011437094 2.1512782e-05
- CMET AR 1 0.0074567215 1.4329677e-05
- CMET F 1 0.0032332872 3.9829013e-06
- CMET CL 1 0.0088199402 1.7859582e-05
- CMET BR 1 0.0032351714 3.6952118e-05
- OMET O 1 0.0022619536 1.380375e-06
- OMET OM 1 0.0022619536 2.258907e-06
- OMET OA 1 0.0022619536 1.505529e-06
- OMET OW 1 0.0024331696 1.991421e-06
- OMET N 1 0.0023475616 2.384061e-06
- OMET NT 1 0.0023475616 2.76075e-06
- OMET NL 1 0.0023475616 3.764436e-06
- OMET NR 1 0.0023475616 2.258907e-06
- OMET NZ 1 0.0023475616 2.635596e-06
- OMET NE 1 0.0023475616 2.434368e-06
- OMET C 1 0.0023009528 2.066625e-06
- OMET CH1 1 0.0029239888 3.794625e-06
- OMET CH2 1 0.0040088324 5.711625e-06
- OMET CH3 1 0.0047360248 6.51825e-06
- OMET CH4 1 0.005459888 6.59475e-06
- OMET CR1 1 0.00353133 4.374e-06
- OMET HC 1 0.000437552 1.38375e-07
- OMET H 1 0 0
- OMET DUM 1 0 0
- OMET S 1 0.0047521952 4.068e-06
- OMET CU1+ 1 0.000972602 2.76075e-07
- OMET CU2+ 1 0.000972602 5.019657e-07
- OMET FE 1 0 0
- OMET ZN2+ 1 0.000972602 1.1921532e-07
- OMET MG2+ 1 0.0003842848 7.163226e-08
- OMET CA2+ 1 0.001507652 8.658939e-07
- OMET P 1 0.005773784 5.780397e-06
- OMET AR 1 0.003764374 3.53025e-06
- OMET F 1 0.0016322592 1.505529e-06
- OMET CL 1 0.0044525672 4.798797e-06
- OMET BR 1 0.0016332104 9.928884e-06
- OMET CMET 1 0.0044806276 5.1373125e-06
+ CMet O 1 0.0044806276 3.9322131e-06
+ CMet OM 1 0.0044806276 3.9322131e-06
+ CMet OA 1 0.0044806276 5.1373125e-06
+ CMet OW 1 0.0048197836 7.050676e-06
+ CMet N 1 0.0046502056 5.9410165e-06
+ CMet NT 1 0.0046502056 5.9410165e-06
+ CMet NL 1 0.0046502056 5.9410165e-06
+ CMet NR 1 0.0046502056 5.9410165e-06
+ CMet NZ 1 0.0046502056 5.9410165e-06
+ CMet NE 1 0.0046502056 5.9410165e-06
+ CMet C 1 0.0045578798 8.3886605e-06
+ CMet CH1 1 0.0057920308 1.5402804e-05
+ CMet CH2 1 0.0079409609 2.318412e-05
+ CMet CH3 1 0.0093814318 2.6458301e-05
+ CMet CH4 1 0.010815308 2.6768823e-05
+ CMet CR1 1 0.0069950925 1.7754552e-05
+ CMet HC 1 0.000866732 5.616795e-07
+ CMet H 1 0 0
+ CMet DUM 1 0 0
+ CMet S 1 0.0094134632 1.6512464e-05
+ CMet CU1+ 1 0.0019265945 3.2691574e-07
+ CMet CU2+ 1 0.0019265945 3.2691574e-07
+ CMet FE 1 0 0
+ CMet ZN2+ 1 0.0019265945 4.4368114e-07
+ CMet MG2+ 1 0.0007612168 2.6659227e-07
+ CMet CA2+ 1 0.002986457 3.222579e-06
+ CMet P 1 0.011437094 2.1512782e-05
+ CMet AR 1 0.0074567215 1.4329677e-05
+ CMet F 1 0.0032332872 3.9829013e-06
+ CMet CL 1 0.0088199402 1.7859582e-05
+ CMet BR 1 0.0032351714 3.6952118e-05
+ OMet O 1 0.0022619536 1.380375e-06
+ OMet OM 1 0.0022619536 2.258907e-06
+ OMet OA 1 0.0022619536 1.505529e-06
+ OMet OW 1 0.0024331696 1.991421e-06
+ OMet N 1 0.0023475616 2.384061e-06
+ OMet NT 1 0.0023475616 2.76075e-06
+ OMet NL 1 0.0023475616 3.764436e-06
+ OMet NR 1 0.0023475616 2.258907e-06
+ OMet NZ 1 0.0023475616 2.635596e-06
+ OMet NE 1 0.0023475616 2.434368e-06
+ OMet C 1 0.0023009528 2.066625e-06
+ OMet CH1 1 0.0029239888 3.794625e-06
+ OMet CH2 1 0.0040088324 5.711625e-06
+ OMet CH3 1 0.0047360248 6.51825e-06
+ OMet CH4 1 0.005459888 6.59475e-06
+ OMet CR1 1 0.00353133 4.374e-06
+ OMet HC 1 0.000437552 1.38375e-07
+ OMet H 1 0 0
+ OMet DUM 1 0 0
+ OMet S 1 0.0047521952 4.068e-06
+ OMet CU1+ 1 0.000972602 2.76075e-07
+ OMet CU2+ 1 0.000972602 5.019657e-07
+ OMet FE 1 0 0
+ OMet ZN2+ 1 0.000972602 1.1921532e-07
+ OMet MG2+ 1 0.0003842848 7.163226e-08
+ OMet CA2+ 1 0.001507652 8.658939e-07
+ OMet P 1 0.005773784 5.780397e-06
+ OMet AR 1 0.003764374 3.53025e-06
+ OMet F 1 0.0016322592 1.505529e-06
+ OMet CL 1 0.0044525672 4.798797e-06
+ OMet BR 1 0.0016332104 9.928884e-06
+ OMet CMet 1 0.0044806276 5.1373125e-06
NA+ O 1 0.00040373684 1.63125e-07
NA+ OM 1 0.00040373684 4.4486e-07
NA+ OA 1 0.00040373684 1.77915e-07
NA+ F 1 0.00029134248 1.77915e-07
NA+ CL 1 0.00079474018 5.67095e-07
NA+ BR 1 0.00029151226 1.17334e-06
- NA+ CMET 1 0.00079974869 6.621425e-07
- NA+ OMET 1 0.00040373684 1.77915e-07
+ NA+ CMet 1 0.00079974869 6.621425e-07
+ NA+ OMet 1 0.00040373684 1.77915e-07
CL- O 1 0.0055883 8.903774e-06
CL- OM 1 0.0055883 8.903774e-06
CL- OA 1 0.0055883 1.268718e-05
CL- F 1 0.0040326 9.018548e-06
CL- CL 1 0.01100035 4.043974e-05
CL- BR 1 0.00403495 8.367128e-05
- CL- CMET 1 0.011069675 4.721761e-05
- CL- OMET 1 0.0055883 1.268718e-05
+ CL- CMet 1 0.011069675 4.721761e-05
+ CL- OMet 1 0.0055883 1.268718e-05
CL- NA+ 1 0.0009974575 1.4993e-06
- CCHL O 1 0.0024394475 1.7359776e-06
- CCHL OM 1 0.0024394475 1.7359776e-06
- CCHL OA 1 0.0024394475 2.268e-06
- CCHL OW 1 0.0026240987 3.112704e-06
- CCHL N 1 0.0025317731 2.622816e-06
- CCHL NT 1 0.0025317731 2.622816e-06
- CCHL NL 1 0.0025317731 2.622816e-06
- CCHL NR 1 0.0025317731 2.622816e-06
- CCHL NZ 1 0.0025317731 2.622816e-06
- CCHL NE 1 0.0025317731 2.622816e-06
- CCHL C 1 0.002481507 3.703392e-06
- CCHL CH1 1 0.0031534322 6.799968e-06
- CCHL CH2 1 0.0043234027 1.0235232e-05
- CCHL CH3 1 0.0051076574 1.1680704e-05
- CCHL CH4 1 0.0058883216 1.1817792e-05
- CCHL CR1 1 0.003808431 7.838208e-06
- CCHL HC 1 0.0004718864 2.47968e-07
- CCHL H 1 0 0
- CCHL DUM 1 0 0
- CCHL S 1 0.0051250966 7.289856e-06
- CCHL CU1+ 1 0.0010489214 1.4432544e-07
- CCHL CU2+ 1 0.0010489214 1.4432544e-07
- CCHL FE 1 0 0
- CCHL ZN2+ 1 0.0010489214 1.9587456e-07
- CCHL MG2+ 1 0.00041443936 1.1769408e-07
- CCHL CA2+ 1 0.0016259564 1.4226912e-06
- CCHL P 1 0.0062268488 9.497376e-06
- CCHL AR 1 0.0040597618 6.326208e-06
- CCHL F 1 0.0017603414 1.7583552e-06
- CCHL CL 1 0.004801957 7.884576e-06
- CCHL BR 1 0.0017613673 1.6313472e-05
- CCHL CMET 1 0.0048322193 9.206064e-06
- CCHL OMET 1 0.0024394475 2.268e-06
- CCHL NA+ 1 0.00043541779 2.9232e-07
- CCHL CL- 1 0.00602681 2.084544e-05
- CLCHL O 1 0.004334666 3.1947671e-06
- CLCHL OM 1 0.004334666 3.1947671e-06
- CLCHL OA 1 0.004334666 4.1738625e-06
- CLCHL OW 1 0.0046627736 5.7283944e-06
- CLCHL N 1 0.0044987198 4.8268401e-06
- CLCHL NT 1 0.0044987198 4.8268401e-06
- CLCHL NL 1 0.0044987198 4.8268401e-06
- CLCHL NR 1 0.0044987198 4.8268401e-06
- CLCHL NZ 1 0.0044987198 4.8268401e-06
- CLCHL NE 1 0.0044987198 4.8268401e-06
- CLCHL C 1 0.0044094016 6.8154537e-06
- CLCHL CH1 1 0.0056033487 1.2514167e-05
- CLCHL CH2 1 0.0076822749 1.8836178e-05
- CLCHL CH3 1 0.0090758208 2.1496319e-05
- CLCHL CH4 1 0.010462987 2.1748606e-05
- CLCHL CR1 1 0.0067672192 1.4424869e-05
- CLCHL HC 1 0.0008384972 4.563423e-07
- CLCHL H 1 0 0
- CLCHL DUM 1 0 0
- CLCHL S 1 0.0091068087 1.3415722e-05
- CLCHL CU1+ 1 0.0018638335 2.6560606e-07
- CLCHL CU2+ 1 0.0018638335 2.6560606e-07
- CLCHL FE 1 0 0
- CLCHL ZN2+ 1 0.0018638335 3.6047332e-07
- CLCHL MG2+ 1 0.00073641928 2.1659564e-07
- CLCHL CA2+ 1 0.0028891697 2.6182176e-06
- CLCHL P 1 0.011064517 1.7478281e-05
- CLCHL AR 1 0.0072138101 1.1642294e-05
- CLCHL F 1 0.0031279591 3.2359492e-06
- CLCHL CL 1 0.0085326204 1.4510201e-05
- CLCHL BR 1 0.0031297819 3.0022129e-05
- CLCHL CMET 1 0.0085863936 1.6942172e-05
- CLCHL OMET 1 0.004334666 4.1738625e-06
- CLCHL NA+ 1 0.00077369595 5.379645e-07
- CLCHL CL- 1 0.010709067 3.8362434e-05
- CLCHL CCHL 1 0.0046754 7.4813E-6
- HCHL O 1 0.0002920184 5.6465771e-08
- HCHL OM 1 0.0002920184 5.6465771e-08
- HCHL OA 1 0.0002920184 7.377075e-08
- HCHL OW 1 0.0003141224 1.0124626e-07
- HCHL N 1 0.0003030704 8.5311774e-08
- HCHL NT 1 0.0003030704 8.5311774e-08
- HCHL NL 1 0.0003030704 8.5311774e-08
- HCHL NR 1 0.0003030704 8.5311774e-08
- HCHL NZ 1 0.0003030704 8.5311774e-08
- HCHL NE 1 0.0003030704 8.5311774e-08
- HCHL C 1 0.0002970532 1.2045944e-07
- HCHL CH1 1 0.0003774872 2.211811e-07
- HCHL CH2 1 0.0005175406 3.329192e-07
- HCHL CH3 1 0.0006114212 3.7993576e-07
- HCHL CH4 1 0.000704872 3.8439479e-07
- HCHL CR1 1 0.000455895 2.5495171e-07
- HCHL HC 1 5.6488e-05 8.065602e-09
- HCHL H 1 0 0
- HCHL DUM 1 0 0
- HCHL S 1 0.0006135088 2.3711558e-07
- HCHL CU1+ 1 0.000125563 4.6944427e-09
- HCHL CU2+ 1 0.000125563 4.6944427e-09
- HCHL FE 1 0 0
- HCHL ZN2+ 1 0.000125563 6.3711698e-09
- HCHL MG2+ 1 4.96112e-05 3.8282101e-09
- HCHL CA2+ 1 0.000194638 4.6275572e-08
- HCHL P 1 0.000745396 3.0891911e-07
- HCHL AR 1 0.000485981 2.0577121e-07
- HCHL F 1 0.0002107248 5.7193643e-08
- HCHL CL 1 0.0005748268 2.5645991e-07
- HCHL BR 1 0.0002108476 5.3062481e-07
- HCHL CMET 1 0.0005784494 2.9944367e-07
- HCHL OMET 1 0.0002920184 7.377075e-08
- HCHL NA+ 1 5.212246e-05 9.50823e-09
- HCHL CL- 1 0.00072145 6.7803516e-07
- HCHL CCHL 1 0.0003622 0.1745E-6
- HCHL CLCHL 1 0.0006493 0.3266E-6
- SDMSO O 1 0.0048877412 3.9925763e-06
- SDMSO OM 1 0.0048877412 3.9925763e-06
- SDMSO OA 1 0.0048877412 5.216175e-06
- SDMSO OW 1 0.0052577132 7.1589104e-06
- SDMSO N 1 0.0050727272 6.0322166e-06
- SDMSO NT 1 0.0050727272 6.0322166e-06
- SDMSO NL 1 0.0050727272 6.0322166e-06
- SDMSO NR 1 0.0050727272 6.0322166e-06
- SDMSO NZ 1 0.0050727272 6.0322166e-06
- SDMSO NE 1 0.0050727272 6.0322166e-06
- SDMSO C 1 0.0049720126 8.5174342e-06
- SDMSO CH1 1 0.0063182996 1.5639252e-05
- SDMSO CH2 1 0.0086624833 2.3540018e-05
- SDMSO CH3 1 0.010233837 2.686446e-05
- SDMSO CH4 1 0.011797996 2.7179749e-05
- SDMSO CR1 1 0.0076306725 1.8027101e-05
- SDMSO HC 1 0.000945484 5.703018e-07
- SDMSO H 1 0 0
- SDMSO DUM 1 0 0
- SDMSO S 1 0.010268778 1.6765946e-05
- SDMSO CU1+ 1 0.0021016465 3.3193419e-07
- SDMSO CU2+ 1 0.0021016465 3.3193419e-07
- SDMSO FE 1 0 0
- SDMSO ZN2+ 1 0.0021016465 4.5049206e-07
- SDMSO MG2+ 1 0.0008303816 2.7068471e-07
- SDMSO CA2+ 1 0.003257809 3.2720486e-06
- SDMSO P 1 0.012476278 2.1843023e-05
- SDMSO AR 1 0.0081342455 1.4549651e-05
- SDMSO F 1 0.0035270664 4.0440425e-06
- SDMSO CL 1 0.0096213274 1.8133743e-05
- SDMSO BR 1 0.0035291218 3.7519367e-05
- SDMSO CMET 1 0.0096819617 2.1173034e-05
- SDMSO OMET 1 0.0048877412 5.216175e-06
- SDMSO NA+ 1 0.00087241453 6.72307e-07
- SDMSO CL- 1 0.012075475 4.7942444e-05
- SDMSO CCHL 1 0.0052712788 9.3473856e-06
- SDMSO CLCHL 1 0.0093665606 1.720225e-05
- SDMSO HCHL 1 0.0006310078 3.0404041e-07
- CDMSO O 1 0.0045248108 4.016601e-06
- CDMSO OM 1 0.0045248108 4.016601e-06
- CDMSO OA 1 0.0045248108 5.2475625e-06
- CDMSO OW 1 0.0048673112 7.201988e-06
- CDMSO N 1 0.004696061 6.0685145e-06
- CDMSO NT 1 0.004696061 6.0685145e-06
- CDMSO NL 1 0.004696061 6.0685145e-06
- CDMSO NR 1 0.004696061 6.0685145e-06
- CDMSO NZ 1 0.004696061 6.0685145e-06
- CDMSO NE 1 0.004696061 6.0685145e-06
- CDMSO C 1 0.0046028248 8.5686865e-06
- CDMSO CH1 1 0.0058491457 1.5733359e-05
- CDMSO CH2 1 0.0080192663 2.3681667e-05
- CDMSO CH3 1 0.0094739416 2.7026113e-05
- CDMSO CH4 1 0.010921957 2.7343299e-05
- CDMSO CR1 1 0.0070640708 1.8135576e-05
- CDMSO HC 1 0.0008752788 5.737335e-07
- CDMSO H 1 0 0
- CDMSO DUM 1 0 0
- CDMSO S 1 0.0095062889 1.6866832e-05
- CDMSO CU1+ 1 0.0019455925 3.3393156e-07
- CDMSO CU2+ 1 0.0019455925 3.3393156e-07
- CDMSO FE 1 0 0
- CDMSO ZN2+ 1 0.0019455925 4.5320282e-07
- CDMSO MG2+ 1 0.00076872312 2.7231351e-07
- CDMSO CA2+ 1 0.0030159063 3.2917377e-06
- CDMSO P 1 0.011549875 2.197446e-05
- CDMSO AR 1 0.0075302519 1.4637201e-05
- CDMSO F 1 0.0032651705 4.0683769e-06
- CDMSO CL 1 0.0089069132 1.824286e-05
- CDMSO BR 1 0.0032670733 3.7745134e-05
- CDMSO CMET 1 0.0089630452 2.1300439e-05
- CDMSO OMET 1 0.0045248108 5.2475625e-06
- CDMSO NA+ 1 0.00080763497 6.763525e-07
- CDMSO CL- 1 0.011178832 4.823093e-05
- CDMSO CCHL 1 0.0048798696 9.403632e-06
- CDMSO CLCHL 1 0.0086710636 1.7305761e-05
- CDMSO HCHL 1 0.00058415346 3.0586992e-07
- CDMSO SDMSO 1 0.0097827 21.6523E-6
- ODMSO O 1 0.0022663291 7.4645315e-07
- ODMSO OM 1 0.0022663291 7.4645315e-07
- ODMSO OA 1 0.0022663291 1.380375e-06
- ODMSO OW 1 0.0024378763 1.825875e-06
- ODMSO N 1 0.0023521027 2.185875e-06
- ODMSO NT 1 0.0023521027 2.53125e-06
- ODMSO NL 1 0.0023521027 3.4515e-06
- ODMSO NR 1 0.0023521027 2.071125e-06
- ODMSO NZ 1 0.0023521027 2.4165e-06
- ODMSO NE 1 0.0023521027 2.232e-06
- ODMSO C 1 0.0023054038 1.5924218e-06
- ODMSO CH1 1 0.002929645 2.9239188e-06
- ODMSO CH2 1 0.0040165871 4.4010482e-06
- ODMSO CH3 1 0.0047451862 5.0225868e-06
- ODMSO CH4 1 0.0054704496 5.0815333e-06
- ODMSO CR1 1 0.003538161 3.3703517e-06
- ODMSO HC 1 0.0004383984 1.0662378e-07
- ODMSO H 1 0 0
- ODMSO DUM 1 0 0
- ODMSO S 1 0.0047613878 3.1345658e-06
- ODMSO CU1+ 1 0.0009744834 2.53125e-07
- ODMSO CU2+ 1 0.0009744834 4.602375e-07
- ODMSO FE 1 0 0
- ODMSO ZN2+ 1 0.0009744834 1.09305e-07
- ODMSO MG2+ 1 0.00038502816 6.56775e-08
- ODMSO CA2+ 1 0.0015105684 7.939125e-07
- ODMSO P 1 0.0057849528 5.299875e-06
- ODMSO AR 1 0.0037716558 2.7202067e-06
- ODMSO F 1 0.0016354166 7.5607529e-07
- ODMSO CL 1 0.0044611802 3.3902895e-06
- ODMSO BR 1 0.0016363697 7.0146311e-06
- ODMSO CMET 1 0.0044892949 3.9585162e-06
- ODMSO OMET 1 0.0022663291 1.380375e-06
- ODMSO NA+ 1 0.00040451783 1.63125e-07
- ODMSO CL- 1 0.00559911 8.9633324e-06
- ODMSO CCHL 1 0.0024441664 1.7475898e-06
- ODMSO CLCHL 1 0.0043430509 3.2161373e-06
- ODMSO HCHL 1 0.00029258328 5.6843478e-08
- ODMSO SDMSO 1 0.0052442 4.6094E-6
- ODMSO CDMSO 1 0.0049187 4.7597E-6
- CCL4 O 1 0.0024394475 2.3738805e-06
- CCL4 OM 1 0.0024394475 2.3738805e-06
- CCL4 OA 1 0.0024394475 3.1014e-06
- CCL4 OW 1 0.0026240987 4.2564992e-06
- CCL4 N 1 0.0025317731 3.5865968e-06
- CCL4 NT 1 0.0025317731 3.5865968e-06
- CCL4 NL 1 0.0025317731 3.5865968e-06
- CCL4 NR 1 0.0025317731 3.5865968e-06
- CCL4 NZ 1 0.0025317731 3.5865968e-06
- CCL4 NE 1 0.0025317731 3.5865968e-06
- CCL4 C 1 0.002481507 5.0642416e-06
- CCL4 CH1 1 0.0031534322 9.2986864e-06
- CCL4 CH2 1 0.0043234027 1.3996274e-05
- CCL4 CH3 1 0.0051076574 1.5972899e-05
- CCL4 CH4 1 0.0058883216 1.6160362e-05
- CCL4 CR1 1 0.003808431 1.0718438e-05
- CCL4 HC 1 0.0004718864 3.390864e-07
- CCL4 H 1 0 0
- CCL4 DUM 1 0 0
- CCL4 S 1 0.0051250966 9.9685888e-06
- CCL4 CU1+ 1 0.0010489214 1.9735931e-07
- CCL4 CU2+ 1 0.0010489214 1.9735931e-07
- CCL4 FE 1 0 0
- CCL4 ZN2+ 1 0.0010489214 2.6785069e-07
- CCL4 MG2+ 1 0.00041443936 1.6094198e-07
- CCL4 CA2+ 1 0.0016259564 1.9454738e-06
- CCL4 P 1 0.0062268488 1.2987285e-05
- CCL4 AR 1 0.0040597618 8.6508384e-06
- CCL4 F 1 0.0017603414 2.404481e-06
- CCL4 CL 1 0.004801957 1.0781845e-05
- CCL4 BR 1 0.0017613673 2.2308026e-05
- CCL4 CMET 1 0.0048322193 1.2588927e-05
- CCL4 OMET 1 0.0024394475 3.1014e-06
- CCL4 NA+ 1 0.00043541779 3.99736e-07
- CCL4 CL- 1 0.00602681 2.8505312e-05
- CCL4 CCHL 1 0.0026308693 5.5577088e-06
- CCL4 CLCHL 1 0.0046748042 1.0228004e-05
- CCL4 HCHL 1 0.00031493288 1.807744e-07
- CCL4 SDMSO 1 0.0052712788 1.2782179e-05
- CCL4 CDMSO 1 0.0048798696 1.2859094e-05
- CCL4 ODMSO 1 0.0024441664 2.3897596e-06
- CLCL4 O 1 0.0041472796 3.0768825e-06
- CLCL4 OM 1 0.0041472796 3.0768825e-06
- CLCL4 OA 1 0.0041472796 4.01985e-06
- CLCL4 OW 1 0.0044612032 5.5170208e-06
- CLCL4 N 1 0.0043042414 4.6487332e-06
- CLCL4 NT 1 0.0043042414 4.6487332e-06
- CLCL4 NL 1 0.0043042414 4.6487332e-06
- CLCL4 NR 1 0.0043042414 4.6487332e-06
- CLCL4 NZ 1 0.0043042414 4.6487332e-06
- CLCL4 NE 1 0.0043042414 4.6487332e-06
- CLCL4 C 1 0.0042187844 6.5639684e-06
- CLCL4 CH1 1 0.0053611175 1.2052404e-05
- CLCL4 CH2 1 0.0073501723 1.8141136e-05
- CLCL4 CH3 1 0.0086834756 2.0703121e-05
- CLCL4 CH4 1 0.010010675 2.0946098e-05
- CLCL4 CR1 1 0.0064746742 1.3892602e-05
- CLCL4 HC 1 0.0008022492 4.395036e-07
- CLCL4 H 1 0 0
- CLCL4 DUM 1 0 0
- CLCL4 S 1 0.0087131239 1.2920691e-05
- CLCL4 CU1+ 1 0.0017832604 2.5580539e-07
- CLCL4 CU2+ 1 0.0017832604 2.5580539e-07
- CLCL4 FE 1 0 0
- CLCL4 ZN2+ 1 0.0017832604 3.4717211e-07
- CLCL4 MG2+ 1 0.00070458408 2.0860342e-07
- CLCL4 CA2+ 1 0.0027642717 2.5216072e-06
- CLCL4 P 1 0.010586201 1.6833345e-05
- CLCL4 AR 1 0.0069019592 1.1212702e-05
- CLCL4 F 1 0.0029927383 3.116545e-06
- CLCL4 CL 1 0.0081637576 1.3974785e-05
- CLCL4 BR 1 0.0029944823 2.8914334e-05
- CLCL4 CMET 1 0.0082152062 1.6317018e-05
- CLCL4 OMET 1 0.0041472796 4.01985e-06
- CLCL4 NA+ 1 0.00074024929 5.18114e-07
- CLCL4 CL- 1 0.010246117 3.6946888e-05
- CLCL4 CCHL 1 0.0044727137 7.2035712e-06
- CLCL4 CLCHL 1 0.0079475863 1.3256929e-05
- CLCL4 HCHL 1 0.00053541414 2.3430902e-07
- CLCL4 SDMSO 1 0.0089616468 1.6567499e-05
- CLCL4 CDMSO 1 0.0082962159 1.6667191e-05
- CLCL4 ODMSO 1 0.0041553021 3.0974642e-06
- CLCL4 CCL4 1 0.0044727137 9.8505978e-06
+ CChl O 1 0.0024394475 1.7359776e-06
+ CChl OM 1 0.0024394475 1.7359776e-06
+ CChl OA 1 0.0024394475 2.268e-06
+ CChl OW 1 0.0026240987 3.112704e-06
+ CChl N 1 0.0025317731 2.622816e-06
+ CChl NT 1 0.0025317731 2.622816e-06
+ CChl NL 1 0.0025317731 2.622816e-06
+ CChl NR 1 0.0025317731 2.622816e-06
+ CChl NZ 1 0.0025317731 2.622816e-06
+ CChl NE 1 0.0025317731 2.622816e-06
+ CChl C 1 0.002481507 3.703392e-06
+ CChl CH1 1 0.0031534322 6.799968e-06
+ CChl CH2 1 0.0043234027 1.0235232e-05
+ CChl CH3 1 0.0051076574 1.1680704e-05
+ CChl CH4 1 0.0058883216 1.1817792e-05
+ CChl CR1 1 0.003808431 7.838208e-06
+ CChl HC 1 0.0004718864 2.47968e-07
+ CChl H 1 0 0
+ CChl DUM 1 0 0
+ CChl S 1 0.0051250966 7.289856e-06
+ CChl CU1+ 1 0.0010489214 1.4432544e-07
+ CChl CU2+ 1 0.0010489214 1.4432544e-07
+ CChl FE 1 0 0
+ CChl ZN2+ 1 0.0010489214 1.9587456e-07
+ CChl MG2+ 1 0.00041443936 1.1769408e-07
+ CChl CA2+ 1 0.0016259564 1.4226912e-06
+ CChl P 1 0.0062268488 9.497376e-06
+ CChl AR 1 0.0040597618 6.326208e-06
+ CChl F 1 0.0017603414 1.7583552e-06
+ CChl CL 1 0.004801957 7.884576e-06
+ CChl BR 1 0.0017613673 1.6313472e-05
+ CChl CMet 1 0.0048322193 9.206064e-06
+ CChl OMet 1 0.0024394475 2.268e-06
+ CChl NA+ 1 0.00043541779 2.9232e-07
+ CChl CL- 1 0.00602681 2.084544e-05
+ CLChl O 1 0.004334666 3.1947671e-06
+ CLChl OM 1 0.004334666 3.1947671e-06
+ CLChl OA 1 0.004334666 4.1738625e-06
+ CLChl OW 1 0.0046627736 5.7283944e-06
+ CLChl N 1 0.0044987198 4.8268401e-06
+ CLChl NT 1 0.0044987198 4.8268401e-06
+ CLChl NL 1 0.0044987198 4.8268401e-06
+ CLChl NR 1 0.0044987198 4.8268401e-06
+ CLChl NZ 1 0.0044987198 4.8268401e-06
+ CLChl NE 1 0.0044987198 4.8268401e-06
+ CLChl C 1 0.0044094016 6.8154537e-06
+ CLChl CH1 1 0.0056033487 1.2514167e-05
+ CLChl CH2 1 0.0076822749 1.8836178e-05
+ CLChl CH3 1 0.0090758208 2.1496319e-05
+ CLChl CH4 1 0.010462987 2.1748606e-05
+ CLChl CR1 1 0.0067672192 1.4424869e-05
+ CLChl HC 1 0.0008384972 4.563423e-07
+ CLChl H 1 0 0
+ CLChl DUM 1 0 0
+ CLChl S 1 0.0091068087 1.3415722e-05
+ CLChl CU1+ 1 0.0018638335 2.6560606e-07
+ CLChl CU2+ 1 0.0018638335 2.6560606e-07
+ CLChl FE 1 0 0
+ CLChl ZN2+ 1 0.0018638335 3.6047332e-07
+ CLChl MG2+ 1 0.00073641928 2.1659564e-07
+ CLChl CA2+ 1 0.0028891697 2.6182176e-06
+ CLChl P 1 0.011064517 1.7478281e-05
+ CLChl AR 1 0.0072138101 1.1642294e-05
+ CLChl F 1 0.0031279591 3.2359492e-06
+ CLChl CL 1 0.0085326204 1.4510201e-05
+ CLChl BR 1 0.0031297819 3.0022129e-05
+ CLChl CMet 1 0.0085863936 1.6942172e-05
+ CLChl OMet 1 0.004334666 4.1738625e-06
+ CLChl NA+ 1 0.00077369595 5.379645e-07
+ CLChl CL- 1 0.010709067 3.8362434e-05
+ CLChl CChl 1 0.0046754 7.4813E-6
+ HChl O 1 0.0002920184 5.6465771e-08
+ HChl OM 1 0.0002920184 5.6465771e-08
+ HChl OA 1 0.0002920184 7.377075e-08
+ HChl OW 1 0.0003141224 1.0124626e-07
+ HChl N 1 0.0003030704 8.5311774e-08
+ HChl NT 1 0.0003030704 8.5311774e-08
+ HChl NL 1 0.0003030704 8.5311774e-08
+ HChl NR 1 0.0003030704 8.5311774e-08
+ HChl NZ 1 0.0003030704 8.5311774e-08
+ HChl NE 1 0.0003030704 8.5311774e-08
+ HChl C 1 0.0002970532 1.2045944e-07
+ HChl CH1 1 0.0003774872 2.211811e-07
+ HChl CH2 1 0.0005175406 3.329192e-07
+ HChl CH3 1 0.0006114212 3.7993576e-07
+ HChl CH4 1 0.000704872 3.8439479e-07
+ HChl CR1 1 0.000455895 2.5495171e-07
+ HChl HC 1 5.6488e-05 8.065602e-09
+ HChl H 1 0 0
+ HChl DUM 1 0 0
+ HChl S 1 0.0006135088 2.3711558e-07
+ HChl CU1+ 1 0.000125563 4.6944427e-09
+ HChl CU2+ 1 0.000125563 4.6944427e-09
+ HChl FE 1 0 0
+ HChl ZN2+ 1 0.000125563 6.3711698e-09
+ HChl MG2+ 1 4.96112e-05 3.8282101e-09
+ HChl CA2+ 1 0.000194638 4.6275572e-08
+ HChl P 1 0.000745396 3.0891911e-07
+ HChl AR 1 0.000485981 2.0577121e-07
+ HChl F 1 0.0002107248 5.7193643e-08
+ HChl CL 1 0.0005748268 2.5645991e-07
+ HChl BR 1 0.0002108476 5.3062481e-07
+ HChl CMet 1 0.0005784494 2.9944367e-07
+ HChl OMet 1 0.0002920184 7.377075e-08
+ HChl NA+ 1 5.212246e-05 9.50823e-09
+ HChl CL- 1 0.00072145 6.7803516e-07
+ HChl CChl 1 0.0003622 0.1745E-6
+ HChl CLChl 1 0.0006493 0.3266E-6
+ SDmso O 1 0.0048877412 3.9925763e-06
+ SDmso OM 1 0.0048877412 3.9925763e-06
+ SDmso OA 1 0.0048877412 5.216175e-06
+ SDmso OW 1 0.0052577132 7.1589104e-06
+ SDmso N 1 0.0050727272 6.0322166e-06
+ SDmso NT 1 0.0050727272 6.0322166e-06
+ SDmso NL 1 0.0050727272 6.0322166e-06
+ SDmso NR 1 0.0050727272 6.0322166e-06
+ SDmso NZ 1 0.0050727272 6.0322166e-06
+ SDmso NE 1 0.0050727272 6.0322166e-06
+ SDmso C 1 0.0049720126 8.5174342e-06
+ SDmso CH1 1 0.0063182996 1.5639252e-05
+ SDmso CH2 1 0.0086624833 2.3540018e-05
+ SDmso CH3 1 0.010233837 2.686446e-05
+ SDmso CH4 1 0.011797996 2.7179749e-05
+ SDmso CR1 1 0.0076306725 1.8027101e-05
+ SDmso HC 1 0.000945484 5.703018e-07
+ SDmso H 1 0 0
+ SDmso DUM 1 0 0
+ SDmso S 1 0.010268778 1.6765946e-05
+ SDmso CU1+ 1 0.0021016465 3.3193419e-07
+ SDmso CU2+ 1 0.0021016465 3.3193419e-07
+ SDmso FE 1 0 0
+ SDmso ZN2+ 1 0.0021016465 4.5049206e-07
+ SDmso MG2+ 1 0.0008303816 2.7068471e-07
+ SDmso CA2+ 1 0.003257809 3.2720486e-06
+ SDmso P 1 0.012476278 2.1843023e-05
+ SDmso AR 1 0.0081342455 1.4549651e-05
+ SDmso F 1 0.0035270664 4.0440425e-06
+ SDmso CL 1 0.0096213274 1.8133743e-05
+ SDmso BR 1 0.0035291218 3.7519367e-05
+ SDmso CMet 1 0.0096819617 2.1173034e-05
+ SDmso OMet 1 0.0048877412 5.216175e-06
+ SDmso NA+ 1 0.00087241453 6.72307e-07
+ SDmso CL- 1 0.012075475 4.7942444e-05
+ SDmso CChl 1 0.0052712788 9.3473856e-06
+ SDmso CLChl 1 0.0093665606 1.720225e-05
+ SDmso HChl 1 0.0006310078 3.0404041e-07
+ CDmso O 1 0.0045248108 4.016601e-06
+ CDmso OM 1 0.0045248108 4.016601e-06
+ CDmso OA 1 0.0045248108 5.2475625e-06
+ CDmso OW 1 0.0048673112 7.201988e-06
+ CDmso N 1 0.004696061 6.0685145e-06
+ CDmso NT 1 0.004696061 6.0685145e-06
+ CDmso NL 1 0.004696061 6.0685145e-06
+ CDmso NR 1 0.004696061 6.0685145e-06
+ CDmso NZ 1 0.004696061 6.0685145e-06
+ CDmso NE 1 0.004696061 6.0685145e-06
+ CDmso C 1 0.0046028248 8.5686865e-06
+ CDmso CH1 1 0.0058491457 1.5733359e-05
+ CDmso CH2 1 0.0080192663 2.3681667e-05
+ CDmso CH3 1 0.0094739416 2.7026113e-05
+ CDmso CH4 1 0.010921957 2.7343299e-05
+ CDmso CR1 1 0.0070640708 1.8135576e-05
+ CDmso HC 1 0.0008752788 5.737335e-07
+ CDmso H 1 0 0
+ CDmso DUM 1 0 0
+ CDmso S 1 0.0095062889 1.6866832e-05
+ CDmso CU1+ 1 0.0019455925 3.3393156e-07
+ CDmso CU2+ 1 0.0019455925 3.3393156e-07
+ CDmso FE 1 0 0
+ CDmso ZN2+ 1 0.0019455925 4.5320282e-07
+ CDmso MG2+ 1 0.00076872312 2.7231351e-07
+ CDmso CA2+ 1 0.0030159063 3.2917377e-06
+ CDmso P 1 0.011549875 2.197446e-05
+ CDmso AR 1 0.0075302519 1.4637201e-05
+ CDmso F 1 0.0032651705 4.0683769e-06
+ CDmso CL 1 0.0089069132 1.824286e-05
+ CDmso BR 1 0.0032670733 3.7745134e-05
+ CDmso CMet 1 0.0089630452 2.1300439e-05
+ CDmso OMet 1 0.0045248108 5.2475625e-06
+ CDmso NA+ 1 0.00080763497 6.763525e-07
+ CDmso CL- 1 0.011178832 4.823093e-05
+ CDmso CChl 1 0.0048798696 9.403632e-06
+ CDmso CLChl 1 0.0086710636 1.7305761e-05
+ CDmso HChl 1 0.00058415346 3.0586992e-07
+ CDmso SDmso 1 0.0097827 21.6523E-6
+ ODmso O 1 0.0022663291 7.4645315e-07
+ ODmso OM 1 0.0022663291 7.4645315e-07
+ ODmso OA 1 0.0022663291 1.380375e-06
+ ODmso OW 1 0.0024378763 1.825875e-06
+ ODmso N 1 0.0023521027 2.185875e-06
+ ODmso NT 1 0.0023521027 2.53125e-06
+ ODmso NL 1 0.0023521027 3.4515e-06
+ ODmso NR 1 0.0023521027 2.071125e-06
+ ODmso NZ 1 0.0023521027 2.4165e-06
+ ODmso NE 1 0.0023521027 2.232e-06
+ ODmso C 1 0.0023054038 1.5924218e-06
+ ODmso CH1 1 0.002929645 2.9239188e-06
+ ODmso CH2 1 0.0040165871 4.4010482e-06
+ ODmso CH3 1 0.0047451862 5.0225868e-06
+ ODmso CH4 1 0.0054704496 5.0815333e-06
+ ODmso CR1 1 0.003538161 3.3703517e-06
+ ODmso HC 1 0.0004383984 1.0662378e-07
+ ODmso H 1 0 0
+ ODmso DUM 1 0 0
+ ODmso S 1 0.0047613878 3.1345658e-06
+ ODmso CU1+ 1 0.0009744834 2.53125e-07
+ ODmso CU2+ 1 0.0009744834 4.602375e-07
+ ODmso FE 1 0 0
+ ODmso ZN2+ 1 0.0009744834 1.09305e-07
+ ODmso MG2+ 1 0.00038502816 6.56775e-08
+ ODmso CA2+ 1 0.0015105684 7.939125e-07
+ ODmso P 1 0.0057849528 5.299875e-06
+ ODmso AR 1 0.0037716558 2.7202067e-06
+ ODmso F 1 0.0016354166 7.5607529e-07
+ ODmso CL 1 0.0044611802 3.3902895e-06
+ ODmso BR 1 0.0016363697 7.0146311e-06
+ ODmso CMet 1 0.0044892949 3.9585162e-06
+ ODmso OMet 1 0.0022663291 1.380375e-06
+ ODmso NA+ 1 0.00040451783 1.63125e-07
+ ODmso CL- 1 0.00559911 8.9633324e-06
+ ODmso CChl 1 0.0024441664 1.7475898e-06
+ ODmso CLChl 1 0.0043430509 3.2161373e-06
+ ODmso HChl 1 0.00029258328 5.6843478e-08
+ ODmso SDmso 1 0.0052442 4.6094E-6
+ ODmso CDmso 1 0.0049187 4.7597E-6
+ CCl4 O 1 0.0024394475 2.3738805e-06
+ CCl4 OM 1 0.0024394475 2.3738805e-06
+ CCl4 OA 1 0.0024394475 3.1014e-06
+ CCl4 OW 1 0.0026240987 4.2564992e-06
+ CCl4 N 1 0.0025317731 3.5865968e-06
+ CCl4 NT 1 0.0025317731 3.5865968e-06
+ CCl4 NL 1 0.0025317731 3.5865968e-06
+ CCl4 NR 1 0.0025317731 3.5865968e-06
+ CCl4 NZ 1 0.0025317731 3.5865968e-06
+ CCl4 NE 1 0.0025317731 3.5865968e-06
+ CCl4 C 1 0.002481507 5.0642416e-06
+ CCl4 CH1 1 0.0031534322 9.2986864e-06
+ CCl4 CH2 1 0.0043234027 1.3996274e-05
+ CCl4 CH3 1 0.0051076574 1.5972899e-05
+ CCl4 CH4 1 0.0058883216 1.6160362e-05
+ CCl4 CR1 1 0.003808431 1.0718438e-05
+ CCl4 HC 1 0.0004718864 3.390864e-07
+ CCl4 H 1 0 0
+ CCl4 DUM 1 0 0
+ CCl4 S 1 0.0051250966 9.9685888e-06
+ CCl4 CU1+ 1 0.0010489214 1.9735931e-07
+ CCl4 CU2+ 1 0.0010489214 1.9735931e-07
+ CCl4 FE 1 0 0
+ CCl4 ZN2+ 1 0.0010489214 2.6785069e-07
+ CCl4 MG2+ 1 0.00041443936 1.6094198e-07
+ CCl4 CA2+ 1 0.0016259564 1.9454738e-06
+ CCl4 P 1 0.0062268488 1.2987285e-05
+ CCl4 AR 1 0.0040597618 8.6508384e-06
+ CCl4 F 1 0.0017603414 2.404481e-06
+ CCl4 CL 1 0.004801957 1.0781845e-05
+ CCl4 BR 1 0.0017613673 2.2308026e-05
+ CCl4 CMet 1 0.0048322193 1.2588927e-05
+ CCl4 OMet 1 0.0024394475 3.1014e-06
+ CCl4 NA+ 1 0.00043541779 3.99736e-07
+ CCl4 CL- 1 0.00602681 2.8505312e-05
+ CCl4 CChl 1 0.0026308693 5.5577088e-06
+ CCl4 CLChl 1 0.0046748042 1.0228004e-05
+ CCl4 HChl 1 0.00031493288 1.807744e-07
+ CCl4 SDmso 1 0.0052712788 1.2782179e-05
+ CCl4 CDmso 1 0.0048798696 1.2859094e-05
+ CCl4 ODmso 1 0.0024441664 2.3897596e-06
+ CLCl4 O 1 0.0041472796 3.0768825e-06
+ CLCl4 OM 1 0.0041472796 3.0768825e-06
+ CLCl4 OA 1 0.0041472796 4.01985e-06
+ CLCl4 OW 1 0.0044612032 5.5170208e-06
+ CLCl4 N 1 0.0043042414 4.6487332e-06
+ CLCl4 NT 1 0.0043042414 4.6487332e-06
+ CLCl4 NL 1 0.0043042414 4.6487332e-06
+ CLCl4 NR 1 0.0043042414 4.6487332e-06
+ CLCl4 NZ 1 0.0043042414 4.6487332e-06
+ CLCl4 NE 1 0.0043042414 4.6487332e-06
+ CLCl4 C 1 0.0042187844 6.5639684e-06
+ CLCl4 CH1 1 0.0053611175 1.2052404e-05
+ CLCl4 CH2 1 0.0073501723 1.8141136e-05
+ CLCl4 CH3 1 0.0086834756 2.0703121e-05
+ CLCl4 CH4 1 0.010010675 2.0946098e-05
+ CLCl4 CR1 1 0.0064746742 1.3892602e-05
+ CLCl4 HC 1 0.0008022492 4.395036e-07
+ CLCl4 H 1 0 0
+ CLCl4 DUM 1 0 0
+ CLCl4 S 1 0.0087131239 1.2920691e-05
+ CLCl4 CU1+ 1 0.0017832604 2.5580539e-07
+ CLCl4 CU2+ 1 0.0017832604 2.5580539e-07
+ CLCl4 FE 1 0 0
+ CLCl4 ZN2+ 1 0.0017832604 3.4717211e-07
+ CLCl4 MG2+ 1 0.00070458408 2.0860342e-07
+ CLCl4 CA2+ 1 0.0027642717 2.5216072e-06
+ CLCl4 P 1 0.010586201 1.6833345e-05
+ CLCl4 AR 1 0.0069019592 1.1212702e-05
+ CLCl4 F 1 0.0029927383 3.116545e-06
+ CLCl4 CL 1 0.0081637576 1.3974785e-05
+ CLCl4 BR 1 0.0029944823 2.8914334e-05
+ CLCl4 CMet 1 0.0082152062 1.6317018e-05
+ CLCl4 OMet 1 0.0041472796 4.01985e-06
+ CLCl4 NA+ 1 0.00074024929 5.18114e-07
+ CLCl4 CL- 1 0.010246117 3.6946888e-05
+ CLCl4 CChl 1 0.0044727137 7.2035712e-06
+ CLCl4 CLChl 1 0.0079475863 1.3256929e-05
+ CLCl4 HChl 1 0.00053541414 2.3430902e-07
+ CLCl4 SDmso 1 0.0089616468 1.6567499e-05
+ CLCl4 CDmso 1 0.0082962159 1.6667191e-05
+ CLCl4 ODmso 1 0.0041553021 3.0974642e-06
+ CLCl4 CCl4 1 0.0044727137 9.8505978e-06
SI O 1 0.005773784 5.299875e-06
SI OM 1 0.005773784 1.4453348e-05
SI OA 1 0.005773784 5.780397e-06
SI F 1 0.004166448 5.780397e-06
SI CL 1 0.011365468 1.8424721e-05
SI BR 1 0.004168876 3.8121412e-05
- SI CMET 1 0.011437094 2.1512782e-05
- SI OMET 1 0.005773784 5.780397e-06
+ SI CMet 1 0.011437094 2.1512782e-05
+ SI OMet 1 0.005773784 5.780397e-06
SI NA+ 1 0.0010305646 6.83095e-07
SI CL- 1 0.0142645 4.871174e-05
- SI CCHL 1 0.0062268488 9.497376e-06
- SI CLCHL 1 0.011064517 1.7478281e-05
- SI HCHL 1 0.000745396 3.0891911e-07
- SI SDMSO 1 0.012476278 2.1843023e-05
- SI CDMSO 1 0.011549875 2.197446e-05
- SI ODMSO 1 0.0057849528 5.299875e-06
- SI CCL4 1 0.0062268488 1.2987285e-05
- SI CLCL4 1 0.010586201 1.6833345e-05
+ SI CChl 1 0.0062268488 9.497376e-06
+ SI CLChl 1 0.011064517 1.7478281e-05
+ SI HChl 1 0.000745396 3.0891911e-07
+ SI SDmso 1 0.012476278 2.1843023e-05
+ SI CDmso 1 0.011549875 2.197446e-05
+ SI ODmso 1 0.0057849528 5.299875e-06
+ SI CCl4 1 0.0062268488 1.2987285e-05
+ SI CLCl4 1 0.010586201 1.6833345e-05
[ pairtypes ]
; i j func c6 c12
BR F 1 0.0011785488 7.0578424e-06
BR CL 1 0.0032149108 3.1647812e-05
BR BR 1 0.0011792356 6.5480464e-05
- CMET O 1 0.0044806276 3.9322131e-06
- CMET OM 1 0.0044806276 3.9322131e-06
- CMET OA 1 0.0044806276 5.1373125e-06
- CMET OW 1 0.0048197836 7.050676e-06
- CMET N 1 0.0046502056 5.9410165e-06
- CMET NT 1 0.0046502056 5.9410165e-06
- CMET NL 1 0.0046502056 5.9410165e-06
- CMET NR 1 0.0046502056 5.9410165e-06
- CMET NZ 1 0.0046502056 5.9410165e-06
- CMET NE 1 0.0046502056 5.9410165e-06
- CMET C 1 0.0045578798 8.3886605e-06
- CMET CH1 1 0.0050835716 8.8270445e-06
- CMET CH2 1 0.0064750533 1.2178856e-05
- CMET CH3 1 0.0077987038 1.5859455e-05
- CMET CH4 1 0.010815308 2.6768823e-05
- CMET CR1 1 0.0070045135 1.3178919e-05
- CMET HC 1 0.000866732 5.616795e-07
- CMET H 1 0 0
- CMET DUM 1 0 0
- CMET S 1 0.0094134632 1.6512464e-05
- CMET CU1+ 1 0.0019265945 3.2691574e-07
- CMET CU2+ 1 0.0019265945 3.2691574e-07
- CMET FE 1 0 0
- CMET ZN2+ 1 0.0019265945 4.4368114e-07
- CMET MG2+ 1 0.0007612168 2.6659227e-07
- CMET CA2+ 1 0.002986457 3.222579e-06
- CMET P 1 0.011437094 2.1512782e-05
- CMET AR 1 0.0074567215 1.4329677e-05
- CMET F 1 0.0032332872 3.9829013e-06
- CMET CL 1 0.0088199402 1.7859582e-05
- CMET BR 1 0.0032351714 3.6952118e-05
- CMET CMET 1 0.0088755241 2.0852922e-05
- OMET O 1 0.0022619536 9.687375e-07
- OMET OM 1 0.0022619536 9.687375e-07
- OMET OA 1 0.0022619536 1.265625e-06
- OMET OW 1 0.0024331696 1.737e-06
- OMET N 1 0.0023475616 1.463625e-06
- OMET NT 1 0.0023475616 1.463625e-06
- OMET NL 1 0.0023475616 1.463625e-06
- OMET NR 1 0.0023475616 1.463625e-06
- OMET NZ 1 0.0023475616 1.463625e-06
- OMET NE 1 0.0023475616 1.463625e-06
- OMET C 1 0.0023009528 2.066625e-06
- OMET CH1 1 0.0025663376 2.174625e-06
- OMET CH2 1 0.0032687988 3.000375e-06
- OMET CH3 1 0.0039370168 3.907125e-06
- OMET CH4 1 0.005459888 6.59475e-06
- OMET CR1 1 0.003536086 3.24675e-06
- OMET HC 1 0.000437552 1.38375e-07
- OMET H 1 0 0
- OMET DUM 1 0 0
- OMET S 1 0.0047521952 4.068e-06
- OMET CU1+ 1 0.000972602 8.053875e-08
- OMET CU2+ 1 0.000972602 8.053875e-08
- OMET FE 1 0 0
- OMET ZN2+ 1 0.000972602 1.09305e-07
- OMET MG2+ 1 0.0003842848 6.56775e-08
- OMET CA2+ 1 0.001507652 7.939125e-07
- OMET P 1 0.005773784 5.299875e-06
- OMET AR 1 0.003764374 3.53025e-06
- OMET F 1 0.0016322592 9.81225e-07
- OMET CL 1 0.0044525672 4.399875e-06
- OMET BR 1 0.0016332104 9.1035e-06
- OMET CMET 1 0.0044806276 5.1373125e-06
- OMET OMET 1 0.0022619536 1.265625e-06
+ CMet O 1 0.0044806276 3.9322131e-06
+ CMet OM 1 0.0044806276 3.9322131e-06
+ CMet OA 1 0.0044806276 5.1373125e-06
+ CMet OW 1 0.0048197836 7.050676e-06
+ CMet N 1 0.0046502056 5.9410165e-06
+ CMet NT 1 0.0046502056 5.9410165e-06
+ CMet NL 1 0.0046502056 5.9410165e-06
+ CMet NR 1 0.0046502056 5.9410165e-06
+ CMet NZ 1 0.0046502056 5.9410165e-06
+ CMet NE 1 0.0046502056 5.9410165e-06
+ CMet C 1 0.0045578798 8.3886605e-06
+ CMet CH1 1 0.0050835716 8.8270445e-06
+ CMet CH2 1 0.0064750533 1.2178856e-05
+ CMet CH3 1 0.0077987038 1.5859455e-05
+ CMet CH4 1 0.010815308 2.6768823e-05
+ CMet CR1 1 0.0070045135 1.3178919e-05
+ CMet HC 1 0.000866732 5.616795e-07
+ CMet H 1 0 0
+ CMet DUM 1 0 0
+ CMet S 1 0.0094134632 1.6512464e-05
+ CMet CU1+ 1 0.0019265945 3.2691574e-07
+ CMet CU2+ 1 0.0019265945 3.2691574e-07
+ CMet FE 1 0 0
+ CMet ZN2+ 1 0.0019265945 4.4368114e-07
+ CMet MG2+ 1 0.0007612168 2.6659227e-07
+ CMet CA2+ 1 0.002986457 3.222579e-06
+ CMet P 1 0.011437094 2.1512782e-05
+ CMet AR 1 0.0074567215 1.4329677e-05
+ CMet F 1 0.0032332872 3.9829013e-06
+ CMet CL 1 0.0088199402 1.7859582e-05
+ CMet BR 1 0.0032351714 3.6952118e-05
+ CMet CMet 1 0.0088755241 2.0852922e-05
+ OMet O 1 0.0022619536 9.687375e-07
+ OMet OM 1 0.0022619536 9.687375e-07
+ OMet OA 1 0.0022619536 1.265625e-06
+ OMet OW 1 0.0024331696 1.737e-06
+ OMet N 1 0.0023475616 1.463625e-06
+ OMet NT 1 0.0023475616 1.463625e-06
+ OMet NL 1 0.0023475616 1.463625e-06
+ OMet NR 1 0.0023475616 1.463625e-06
+ OMet NZ 1 0.0023475616 1.463625e-06
+ OMet NE 1 0.0023475616 1.463625e-06
+ OMet C 1 0.0023009528 2.066625e-06
+ OMet CH1 1 0.0025663376 2.174625e-06
+ OMet CH2 1 0.0032687988 3.000375e-06
+ OMet CH3 1 0.0039370168 3.907125e-06
+ OMet CH4 1 0.005459888 6.59475e-06
+ OMet CR1 1 0.003536086 3.24675e-06
+ OMet HC 1 0.000437552 1.38375e-07
+ OMet H 1 0 0
+ OMet DUM 1 0 0
+ OMet S 1 0.0047521952 4.068e-06
+ OMet CU1+ 1 0.000972602 8.053875e-08
+ OMet CU2+ 1 0.000972602 8.053875e-08
+ OMet FE 1 0 0
+ OMet ZN2+ 1 0.000972602 1.09305e-07
+ OMet MG2+ 1 0.0003842848 6.56775e-08
+ OMet CA2+ 1 0.001507652 7.939125e-07
+ OMet P 1 0.005773784 5.299875e-06
+ OMet AR 1 0.003764374 3.53025e-06
+ OMet F 1 0.0016322592 9.81225e-07
+ OMet CL 1 0.0044525672 4.399875e-06
+ OMet BR 1 0.0016332104 9.1035e-06
+ OMet CMet 1 0.0044806276 5.1373125e-06
+ OMet OMet 1 0.0022619536 1.265625e-06
NA+ O 1 0.00040373684 1.248595e-07
NA+ OM 1 0.00040373684 1.248595e-07
NA+ OA 1 0.00040373684 1.63125e-07
NA+ F 1 0.00029134248 1.26469e-07
NA+ CL 1 0.00079474018 5.67095e-07
NA+ BR 1 0.00029151226 1.17334e-06
- NA+ CMET 1 0.00079974869 6.621425e-07
- NA+ OMET 1 0.00040373684 1.63125e-07
+ NA+ CMet 1 0.00079974869 6.621425e-07
+ NA+ OMet 1 0.00040373684 1.63125e-07
NA+ NA+ 1 7.2063121e-05 2.1025e-08
CL- O 1 0.0055883 8.903774e-06
CL- OM 1 0.0055883 8.903774e-06
CL- F 1 0.0040326 9.018548e-06
CL- CL 1 0.01100035 4.043974e-05
CL- BR 1 0.00403495 8.367128e-05
- CL- CMET 1 0.011069675 4.721761e-05
- CL- OMET 1 0.0055883 1.16325e-05
+ CL- CMet 1 0.011069675 4.721761e-05
+ CL- OMet 1 0.0055883 1.16325e-05
CL- NA+ 1 0.0009974575 1.4993e-06
CL- CL- 1 0.01380625 0.0001069156
- CCHL O 1 0.0024394475 1.7359776e-06
- CCHL OM 1 0.0024394475 1.7359776e-06
- CCHL OA 1 0.0024394475 2.268e-06
- CCHL OW 1 0.0026240987 3.112704e-06
- CCHL N 1 0.0025317731 2.622816e-06
- CCHL NT 1 0.0025317731 2.622816e-06
- CCHL NL 1 0.0025317731 2.622816e-06
- CCHL NR 1 0.0025317731 2.622816e-06
- CCHL NZ 1 0.0025317731 2.622816e-06
- CCHL NE 1 0.0025317731 2.622816e-06
- CCHL C 1 0.002481507 3.703392e-06
- CCHL CH1 1 0.0027677163 3.896928e-06
- CCHL CH2 1 0.0035252992 5.376672e-06
- CCHL CH3 1 0.0042459518 7.001568e-06
- CCHL CH4 1 0.0058883216 1.1817792e-05
- CCHL CR1 1 0.0038135602 5.818176e-06
- CCHL HC 1 0.0004718864 2.47968e-07
- CCHL H 1 0 0
- CCHL DUM 1 0 0
- CCHL S 1 0.0051250966 7.289856e-06
- CCHL CU1+ 1 0.0010489214 1.4432544e-07
- CCHL CU2+ 1 0.0010489214 1.4432544e-07
- CCHL FE 1 0 0
- CCHL ZN2+ 1 0.0010489214 1.9587456e-07
- CCHL MG2+ 1 0.00041443936 1.1769408e-07
- CCHL CA2+ 1 0.0016259564 1.4226912e-06
- CCHL P 1 0.0062268488 9.497376e-06
- CCHL AR 1 0.0040597618 6.326208e-06
- CCHL F 1 0.0017603414 1.7583552e-06
- CCHL CL 1 0.004801957 7.884576e-06
- CCHL BR 1 0.0017613673 1.6313472e-05
- CCHL CMET 1 0.0048322193 9.206064e-06
- CCHL OMET 1 0.0024394475 2.268e-06
- CCHL NA+ 1 0.00043541779 2.9232e-07
- CCHL CL- 1 0.00602681 2.084544e-05
- CCHL CCHL 1 0.0026308693 4.064256e-06
- CLCHL O 1 0.004334666 3.1947671e-06
- CLCHL OM 1 0.004334666 3.1947671e-06
- CLCHL OA 1 0.004334666 4.1738625e-06
- CLCHL OW 1 0.0046627736 5.7283944e-06
- CLCHL N 1 0.0044987198 4.8268401e-06
- CLCHL NT 1 0.0044987198 4.8268401e-06
- CLCHL NL 1 0.0044987198 4.8268401e-06
- CLCHL NR 1 0.0044987198 4.8268401e-06
- CLCHL NZ 1 0.0044987198 4.8268401e-06
- CLCHL NE 1 0.0044987198 4.8268401e-06
- CLCHL C 1 0.0044094016 6.8154537e-06
- CLCHL CH1 1 0.0049179684 7.1716233e-06
- CLCHL CH2 1 0.0062641209 9.8948367e-06
- CLCHL CH3 1 0.007544652 1.2885177e-05
- CLCHL CH4 1 0.010462987 2.1748606e-05
- CLCHL CR1 1 0.0067763334 1.0707349e-05
- CLCHL HC 1 0.0008384972 4.563423e-07
- CLCHL H 1 0 0
- CLCHL DUM 1 0 0
- CLCHL S 1 0.0091068087 1.3415722e-05
- CLCHL CU1+ 1 0.0018638335 2.6560606e-07
- CLCHL CU2+ 1 0.0018638335 2.6560606e-07
- CLCHL FE 1 0 0
- CLCHL ZN2+ 1 0.0018638335 3.6047332e-07
- CLCHL MG2+ 1 0.00073641928 2.1659564e-07
- CLCHL CA2+ 1 0.0028891697 2.6182176e-06
- CLCHL P 1 0.011064517 1.7478281e-05
- CLCHL AR 1 0.0072138101 1.1642294e-05
- CLCHL F 1 0.0031279591 3.2359492e-06
- CLCHL CL 1 0.0085326204 1.4510201e-05
- CLCHL BR 1 0.0031297819 3.0022129e-05
- CLCHL CMET 1 0.0085863936 1.6942172e-05
- CLCHL OMET 1 0.004334666 4.1738625e-06
- CLCHL NA+ 1 0.00077369595 5.379645e-07
- CLCHL CL- 1 0.010709067 3.8362434e-05
- CLCHL CCHL 1 0.0046754 7.4813E-6
- CLCHL CLCHL 1 0.0083066819 1.3764842e-05
- HCHL O 1 0.0002920184 5.6465771e-08
- HCHL OM 1 0.0002920184 5.6465771e-08
- HCHL OA 1 0.0002920184 7.377075e-08
- HCHL OW 1 0.0003141224 1.0124626e-07
- HCHL N 1 0.0003030704 8.5311774e-08
- HCHL NT 1 0.0003030704 8.5311774e-08
- HCHL NL 1 0.0003030704 8.5311774e-08
- HCHL NR 1 0.0003030704 8.5311774e-08
- HCHL NZ 1 0.0003030704 8.5311774e-08
- HCHL NE 1 0.0003030704 8.5311774e-08
- HCHL C 1 0.0002970532 1.2045944e-07
- HCHL CH1 1 0.0003313144 1.2675454e-07
- HCHL CH2 1 0.0004220022 1.7488586e-07
- HCHL CH3 1 0.0005082692 2.277385e-07
- HCHL CH4 1 0.000704872 3.8439479e-07
- HCHL CR1 1 0.000456509 1.8924656e-07
- HCHL HC 1 5.6488e-05 8.065602e-09
- HCHL H 1 0 0
- HCHL DUM 1 0 0
- HCHL S 1 0.0006135088 2.3711558e-07
- HCHL CU1+ 1 0.000125563 4.6944427e-09
- HCHL CU2+ 1 0.000125563 4.6944427e-09
- HCHL FE 1 0 0
- HCHL ZN2+ 1 0.000125563 6.3711698e-09
- HCHL MG2+ 1 4.96112e-05 3.8282101e-09
- HCHL CA2+ 1 0.000194638 4.6275572e-08
- HCHL P 1 0.000745396 3.0891911e-07
- HCHL AR 1 0.000485981 2.0577121e-07
- HCHL F 1 0.0002107248 5.7193643e-08
- HCHL CL 1 0.0005748268 2.5645991e-07
- HCHL BR 1 0.0002108476 5.3062481e-07
- HCHL CMET 1 0.0005784494 2.9944367e-07
- HCHL OMET 1 0.0002920184 7.377075e-08
- HCHL NA+ 1 5.212246e-05 9.50823e-09
- HCHL CL- 1 0.00072145 6.7803516e-07
- HCHL CCHL 1 0.0003622 0.1745E-6
- HCHL CLCHL 1 0.0006493 0.3266E-6
- HCHL HCHL 1 3.76996e-05 4.2999495e-09
- SDMSO O 1 0.0048877412 3.9925763e-06
- SDMSO OM 1 0.0048877412 3.9925763e-06
- SDMSO OA 1 0.0048877412 5.216175e-06
- SDMSO OW 1 0.0052577132 7.1589104e-06
- SDMSO N 1 0.0050727272 6.0322166e-06
- SDMSO NT 1 0.0050727272 6.0322166e-06
- SDMSO NL 1 0.0050727272 6.0322166e-06
- SDMSO NR 1 0.0050727272 6.0322166e-06
- SDMSO NZ 1 0.0050727272 6.0322166e-06
- SDMSO NE 1 0.0050727272 6.0322166e-06
- SDMSO C 1 0.0049720126 8.5174342e-06
- SDMSO CH1 1 0.0055454692 8.9625478e-06
- SDMSO CH2 1 0.0070633821 1.2365812e-05
- SDMSO CH3 1 0.0085073006 1.6102912e-05
- SDMSO CH4 1 0.011797996 2.7179749e-05
- SDMSO CR1 1 0.0076409495 1.3381228e-05
- SDMSO HC 1 0.000945484 5.703018e-07
- SDMSO H 1 0 0
- SDMSO DUM 1 0 0
- SDMSO S 1 0.010268778 1.6765946e-05
- SDMSO CU1+ 1 0.0021016465 3.3193419e-07
- SDMSO CU2+ 1 0.0021016465 3.3193419e-07
- SDMSO FE 1 0 0
- SDMSO ZN2+ 1 0.0021016465 4.5049206e-07
- SDMSO MG2+ 1 0.0008303816 2.7068471e-07
- SDMSO CA2+ 1 0.003257809 3.2720486e-06
- SDMSO P 1 0.012476278 2.1843023e-05
- SDMSO AR 1 0.0081342455 1.4549651e-05
- SDMSO F 1 0.0035270664 4.0440425e-06
- SDMSO CL 1 0.0096213274 1.8133743e-05
- SDMSO BR 1 0.0035291218 3.7519367e-05
- SDMSO CMET 1 0.0096819617 2.1173034e-05
- SDMSO OMET 1 0.0048877412 5.216175e-06
- SDMSO NA+ 1 0.00087241453 6.72307e-07
- SDMSO CL- 1 0.012075475 4.7942444e-05
- SDMSO CCHL 1 0.0052712788 9.3473856e-06
- SDMSO CLCHL 1 0.0093665606 1.720225e-05
- SDMSO HCHL 1 0.0006310078 3.0404041e-07
- SDMSO SDMSO 1 0.010561673 2.149806e-05
- CDMSO O 1 0.0045248108 4.016601e-06
- CDMSO OM 1 0.0045248108 4.016601e-06
- CDMSO OA 1 0.0045248108 5.2475625e-06
- CDMSO OW 1 0.0048673112 7.201988e-06
- CDMSO N 1 0.004696061 6.0685145e-06
- CDMSO NT 1 0.004696061 6.0685145e-06
- CDMSO NL 1 0.004696061 6.0685145e-06
- CDMSO NR 1 0.004696061 6.0685145e-06
- CDMSO NZ 1 0.004696061 6.0685145e-06
- CDMSO NE 1 0.004696061 6.0685145e-06
- CDMSO C 1 0.0046028248 8.5686865e-06
- CDMSO CH1 1 0.0051337004 9.0164785e-06
- CDMSO CH2 1 0.0065389035 1.2440222e-05
- CDMSO CH3 1 0.0078756064 1.6199809e-05
- CDMSO CH4 1 0.010921957 2.7343299e-05
- CDMSO CR1 1 0.0070735846 1.3461747e-05
- CDMSO HC 1 0.0008752788 5.737335e-07
- CDMSO H 1 0 0
- CDMSO DUM 1 0 0
- CDMSO S 1 0.0095062889 1.6866832e-05
- CDMSO CU1+ 1 0.0019455925 3.3393156e-07
- CDMSO CU2+ 1 0.0019455925 3.3393156e-07
- CDMSO FE 1 0 0
- CDMSO ZN2+ 1 0.0019455925 4.5320282e-07
- CDMSO MG2+ 1 0.00076872312 2.7231351e-07
- CDMSO CA2+ 1 0.0030159063 3.2917377e-06
- CDMSO P 1 0.011549875 2.197446e-05
- CDMSO AR 1 0.0075302519 1.4637201e-05
- CDMSO F 1 0.0032651705 4.0683769e-06
- CDMSO CL 1 0.0089069132 1.824286e-05
- CDMSO BR 1 0.0032670733 3.7745134e-05
- CDMSO CMET 1 0.0089630452 2.1300439e-05
- CDMSO OMET 1 0.0045248108 5.2475625e-06
- CDMSO NA+ 1 0.00080763497 6.763525e-07
- CDMSO CL- 1 0.011178832 4.823093e-05
- CDMSO CCHL 1 0.0048798696 9.403632e-06
- CDMSO CLCHL 1 0.0086710636 1.7305761e-05
- CDMSO HCHL 1 0.00058415346 3.0586992e-07
- CDMSO SDMSO 1 0.0097827 21.6523E-6
- CDMSO CDMSO 1 0.0090514293 2.175756e-05
- ODMSO O 1 0.0022663291 7.4645315e-07
- ODMSO OM 1 0.0022663291 7.4645315e-07
- ODMSO OA 1 0.0022663291 9.752175e-07
- ODMSO OW 1 0.0024378763 1.3384318e-06
- ODMSO N 1 0.0023521027 1.1277849e-06
- ODMSO NT 1 0.0023521027 1.1277849e-06
- ODMSO NL 1 0.0023521027 1.1277849e-06
- ODMSO NR 1 0.0023521027 1.1277849e-06
- ODMSO NZ 1 0.0023521027 1.1277849e-06
- ODMSO NE 1 0.0023521027 1.1277849e-06
- ODMSO C 1 0.0023054038 1.5924218e-06
- ODMSO CH1 1 0.0025713019 1.6756404e-06
- ODMSO CH2 1 0.003275122 2.3119156e-06
- ODMSO CH3 1 0.0039446326 3.0106048e-06
- ODMSO CH4 1 0.0054704496 5.0815333e-06
- ODMSO CR1 1 0.0035429262 2.501758e-06
- ODMSO HC 1 0.0004383984 1.0662378e-07
- ODMSO H 1 0 0
- ODMSO DUM 1 0 0
- ODMSO S 1 0.0047613878 3.1345658e-06
- ODMSO CU1+ 1 0.0009744834 6.2058507e-08
- ODMSO CU2+ 1 0.0009744834 6.2058507e-08
- ODMSO FE 1 0 0
- ODMSO ZN2+ 1 0.0009744834 8.4224118e-08
- ODMSO MG2+ 1 0.00038502816 5.0607287e-08
- ODMSO CA2+ 1 0.0015105684 6.117431e-07
- ODMSO P 1 0.0057849528 4.0837775e-06
- ODMSO AR 1 0.0037716558 2.7202067e-06
- ODMSO F 1 0.0016354166 7.5607529e-07
- ODMSO CL 1 0.0044611802 3.3902895e-06
- ODMSO BR 1 0.0016363697 7.0146311e-06
- ODMSO CMET 1 0.0044892949 3.9585162e-06
- ODMSO OMET 1 0.0022663291 9.752175e-07
- ODMSO NA+ 1 0.00040451783 1.256947e-07
- ODMSO CL- 1 0.00559911 8.9633324e-06
- ODMSO CCHL 1 0.0024441664 1.7475898e-06
- ODMSO CLCHL 1 0.0043430509 3.2161373e-06
- ODMSO HCHL 1 0.00029258328 5.6843478e-08
- ODMSO SDMSO 1 0.0052442 4.6094E-6
- ODMSO CDMSO 1 0.0049187 4.7597E-6
- ODMSO ODMSO 1 0.0022707131 7.5144626e-07
- CCL4 O 1 0.0024394475 2.3738805e-06
- CCL4 OM 1 0.0024394475 2.3738805e-06
- CCL4 OA 1 0.0024394475 3.1014e-06
- CCL4 OW 1 0.0026240987 4.2564992e-06
- CCL4 N 1 0.0025317731 3.5865968e-06
- CCL4 NT 1 0.0025317731 3.5865968e-06
- CCL4 NL 1 0.0025317731 3.5865968e-06
- CCL4 NR 1 0.0025317731 3.5865968e-06
- CCL4 NZ 1 0.0025317731 3.5865968e-06
- CCL4 NE 1 0.0025317731 3.5865968e-06
- CCL4 C 1 0.002481507 5.0642416e-06
- CCL4 CH1 1 0.0027677163 5.3288944e-06
- CCL4 CH2 1 0.0035252992 7.3523856e-06
- CCL4 CH3 1 0.0042459518 9.5743664e-06
- CCL4 CH4 1 0.0058883216 1.6160362e-05
- CCL4 CR1 1 0.0038135602 7.9561248e-06
- CCL4 HC 1 0.0004718864 3.390864e-07
- CCL4 H 1 0 0
- CCL4 DUM 1 0 0
- CCL4 S 1 0.0051250966 9.9685888e-06
- CCL4 CU1+ 1 0.0010489214 1.9735931e-07
- CCL4 CU2+ 1 0.0010489214 1.9735931e-07
- CCL4 FE 1 0 0
- CCL4 ZN2+ 1 0.0010489214 2.6785069e-07
- CCL4 MG2+ 1 0.00041443936 1.6094198e-07
- CCL4 CA2+ 1 0.0016259564 1.9454738e-06
- CCL4 P 1 0.0062268488 1.2987285e-05
- CCL4 AR 1 0.0040597618 8.6508384e-06
- CCL4 F 1 0.0017603414 2.404481e-06
- CCL4 CL 1 0.004801957 1.0781845e-05
- CCL4 BR 1 0.0017613673 2.2308026e-05
- CCL4 CMET 1 0.0048322193 1.2588927e-05
- CCL4 OMET 1 0.0024394475 3.1014e-06
- CCL4 NA+ 1 0.00043541779 3.99736e-07
- CCL4 CL- 1 0.00602681 2.8505312e-05
- CCL4 CCHL 1 0.0026308693 5.5577088e-06
- CCL4 CLCHL 1 0.0046748042 1.0228004e-05
- CCL4 HCHL 1 0.00031493288 1.807744e-07
- CCL4 SDMSO 1 0.0052712788 1.2782179e-05
- CCL4 CDMSO 1 0.0048798696 1.2859094e-05
- CCL4 ODMSO 1 0.0024441664 2.3897596e-06
- CCL4 CCL4 1 0.0026308693 7.5999462e-06
- CLCL4 O 1 0.0041472796 3.0768825e-06
- CLCL4 OM 1 0.0041472796 3.0768825e-06
- CLCL4 OA 1 0.0041472796 4.01985e-06
- CLCL4 OW 1 0.0044612032 5.5170208e-06
- CLCL4 N 1 0.0043042414 4.6487332e-06
- CLCL4 NT 1 0.0043042414 4.6487332e-06
- CLCL4 NL 1 0.0043042414 4.6487332e-06
- CLCL4 NR 1 0.0043042414 4.6487332e-06
- CLCL4 NZ 1 0.0043042414 4.6487332e-06
- CLCL4 NE 1 0.0043042414 4.6487332e-06
- CLCL4 C 1 0.0042187844 6.5639684e-06
- CLCL4 CH1 1 0.004705366 6.9069956e-06
- CLCL4 CH2 1 0.0059933247 9.5297244e-06
- CLCL4 CH3 1 0.0072184988 1.2409724e-05
- CLCL4 CH4 1 0.010010675 2.0946098e-05
- CLCL4 CR1 1 0.0064833944 1.0312255e-05
- CLCL4 HC 1 0.0008022492 4.395036e-07
- CLCL4 H 1 0 0
- CLCL4 DUM 1 0 0
- CLCL4 S 1 0.0087131239 1.2920691e-05
- CLCL4 CU1+ 1 0.0017832604 2.5580539e-07
- CLCL4 CU2+ 1 0.0017832604 2.5580539e-07
- CLCL4 FE 1 0 0
- CLCL4 ZN2+ 1 0.0017832604 3.4717211e-07
- CLCL4 MG2+ 1 0.00070458408 2.0860342e-07
- CLCL4 CA2+ 1 0.0027642717 2.5216072e-06
- CLCL4 P 1 0.010586201 1.6833345e-05
- CLCL4 AR 1 0.0069019592 1.1212702e-05
- CLCL4 F 1 0.0029927383 3.116545e-06
- CLCL4 CL 1 0.0081637576 1.3974785e-05
- CLCL4 BR 1 0.0029944823 2.8914334e-05
- CLCL4 CMET 1 0.0082152062 1.6317018e-05
- CLCL4 OMET 1 0.0041472796 4.01985e-06
- CLCL4 NA+ 1 0.00074024929 5.18114e-07
- CLCL4 CL- 1 0.010246117 3.6946888e-05
- CLCL4 CCHL 1 0.0044727137 7.2035712e-06
- CLCL4 CLCHL 1 0.0079475863 1.3256929e-05
- CLCL4 HCHL 1 0.00053541414 2.3430902e-07
- CLCL4 SDMSO 1 0.0089616468 1.6567499e-05
- CLCL4 CDMSO 1 0.0082962159 1.6667191e-05
- CLCL4 ODMSO 1 0.0041553021 3.0974642e-06
- CLCL4 CCL4 1 0.0044727137 9.8505978e-06
- CLCL4 CLCL4 1 0.0076040144 1.2767758e-05
+ CChl O 1 0.0024394475 1.7359776e-06
+ CChl OM 1 0.0024394475 1.7359776e-06
+ CChl OA 1 0.0024394475 2.268e-06
+ CChl OW 1 0.0026240987 3.112704e-06
+ CChl N 1 0.0025317731 2.622816e-06
+ CChl NT 1 0.0025317731 2.622816e-06
+ CChl NL 1 0.0025317731 2.622816e-06
+ CChl NR 1 0.0025317731 2.622816e-06
+ CChl NZ 1 0.0025317731 2.622816e-06
+ CChl NE 1 0.0025317731 2.622816e-06
+ CChl C 1 0.002481507 3.703392e-06
+ CChl CH1 1 0.0027677163 3.896928e-06
+ CChl CH2 1 0.0035252992 5.376672e-06
+ CChl CH3 1 0.0042459518 7.001568e-06
+ CChl CH4 1 0.0058883216 1.1817792e-05
+ CChl CR1 1 0.0038135602 5.818176e-06
+ CChl HC 1 0.0004718864 2.47968e-07
+ CChl H 1 0 0
+ CChl DUM 1 0 0
+ CChl S 1 0.0051250966 7.289856e-06
+ CChl CU1+ 1 0.0010489214 1.4432544e-07
+ CChl CU2+ 1 0.0010489214 1.4432544e-07
+ CChl FE 1 0 0
+ CChl ZN2+ 1 0.0010489214 1.9587456e-07
+ CChl MG2+ 1 0.00041443936 1.1769408e-07
+ CChl CA2+ 1 0.0016259564 1.4226912e-06
+ CChl P 1 0.0062268488 9.497376e-06
+ CChl AR 1 0.0040597618 6.326208e-06
+ CChl F 1 0.0017603414 1.7583552e-06
+ CChl CL 1 0.004801957 7.884576e-06
+ CChl BR 1 0.0017613673 1.6313472e-05
+ CChl CMet 1 0.0048322193 9.206064e-06
+ CChl OMet 1 0.0024394475 2.268e-06
+ CChl NA+ 1 0.00043541779 2.9232e-07
+ CChl CL- 1 0.00602681 2.084544e-05
+ CChl CChl 1 0.0026308693 4.064256e-06
+ CLChl O 1 0.004334666 3.1947671e-06
+ CLChl OM 1 0.004334666 3.1947671e-06
+ CLChl OA 1 0.004334666 4.1738625e-06
+ CLChl OW 1 0.0046627736 5.7283944e-06
+ CLChl N 1 0.0044987198 4.8268401e-06
+ CLChl NT 1 0.0044987198 4.8268401e-06
+ CLChl NL 1 0.0044987198 4.8268401e-06
+ CLChl NR 1 0.0044987198 4.8268401e-06
+ CLChl NZ 1 0.0044987198 4.8268401e-06
+ CLChl NE 1 0.0044987198 4.8268401e-06
+ CLChl C 1 0.0044094016 6.8154537e-06
+ CLChl CH1 1 0.0049179684 7.1716233e-06
+ CLChl CH2 1 0.0062641209 9.8948367e-06
+ CLChl CH3 1 0.007544652 1.2885177e-05
+ CLChl CH4 1 0.010462987 2.1748606e-05
+ CLChl CR1 1 0.0067763334 1.0707349e-05
+ CLChl HC 1 0.0008384972 4.563423e-07
+ CLChl H 1 0 0
+ CLChl DUM 1 0 0
+ CLChl S 1 0.0091068087 1.3415722e-05
+ CLChl CU1+ 1 0.0018638335 2.6560606e-07
+ CLChl CU2+ 1 0.0018638335 2.6560606e-07
+ CLChl FE 1 0 0
+ CLChl ZN2+ 1 0.0018638335 3.6047332e-07
+ CLChl MG2+ 1 0.00073641928 2.1659564e-07
+ CLChl CA2+ 1 0.0028891697 2.6182176e-06
+ CLChl P 1 0.011064517 1.7478281e-05
+ CLChl AR 1 0.0072138101 1.1642294e-05
+ CLChl F 1 0.0031279591 3.2359492e-06
+ CLChl CL 1 0.0085326204 1.4510201e-05
+ CLChl BR 1 0.0031297819 3.0022129e-05
+ CLChl CMet 1 0.0085863936 1.6942172e-05
+ CLChl OMet 1 0.004334666 4.1738625e-06
+ CLChl NA+ 1 0.00077369595 5.379645e-07
+ CLChl CL- 1 0.010709067 3.8362434e-05
+ CLChl CChl 1 0.0046754 7.4813E-6
+ CLChl CLChl 1 0.0083066819 1.3764842e-05
+ HChl O 1 0.0002920184 5.6465771e-08
+ HChl OM 1 0.0002920184 5.6465771e-08
+ HChl OA 1 0.0002920184 7.377075e-08
+ HChl OW 1 0.0003141224 1.0124626e-07
+ HChl N 1 0.0003030704 8.5311774e-08
+ HChl NT 1 0.0003030704 8.5311774e-08
+ HChl NL 1 0.0003030704 8.5311774e-08
+ HChl NR 1 0.0003030704 8.5311774e-08
+ HChl NZ 1 0.0003030704 8.5311774e-08
+ HChl NE 1 0.0003030704 8.5311774e-08
+ HChl C 1 0.0002970532 1.2045944e-07
+ HChl CH1 1 0.0003313144 1.2675454e-07
+ HChl CH2 1 0.0004220022 1.7488586e-07
+ HChl CH3 1 0.0005082692 2.277385e-07
+ HChl CH4 1 0.000704872 3.8439479e-07
+ HChl CR1 1 0.000456509 1.8924656e-07
+ HChl HC 1 5.6488e-05 8.065602e-09
+ HChl H 1 0 0
+ HChl DUM 1 0 0
+ HChl S 1 0.0006135088 2.3711558e-07
+ HChl CU1+ 1 0.000125563 4.6944427e-09
+ HChl CU2+ 1 0.000125563 4.6944427e-09
+ HChl FE 1 0 0
+ HChl ZN2+ 1 0.000125563 6.3711698e-09
+ HChl MG2+ 1 4.96112e-05 3.8282101e-09
+ HChl CA2+ 1 0.000194638 4.6275572e-08
+ HChl P 1 0.000745396 3.0891911e-07
+ HChl AR 1 0.000485981 2.0577121e-07
+ HChl F 1 0.0002107248 5.7193643e-08
+ HChl CL 1 0.0005748268 2.5645991e-07
+ HChl BR 1 0.0002108476 5.3062481e-07
+ HChl CMet 1 0.0005784494 2.9944367e-07
+ HChl OMet 1 0.0002920184 7.377075e-08
+ HChl NA+ 1 5.212246e-05 9.50823e-09
+ HChl CL- 1 0.00072145 6.7803516e-07
+ HChl CChl 1 0.0003622 0.1745E-6
+ HChl CLChl 1 0.0006493 0.3266E-6
+ HChl HChl 1 3.76996e-05 4.2999495e-09
+ SDmso O 1 0.0048877412 3.9925763e-06
+ SDmso OM 1 0.0048877412 3.9925763e-06
+ SDmso OA 1 0.0048877412 5.216175e-06
+ SDmso OW 1 0.0052577132 7.1589104e-06
+ SDmso N 1 0.0050727272 6.0322166e-06
+ SDmso NT 1 0.0050727272 6.0322166e-06
+ SDmso NL 1 0.0050727272 6.0322166e-06
+ SDmso NR 1 0.0050727272 6.0322166e-06
+ SDmso NZ 1 0.0050727272 6.0322166e-06
+ SDmso NE 1 0.0050727272 6.0322166e-06
+ SDmso C 1 0.0049720126 8.5174342e-06
+ SDmso CH1 1 0.0055454692 8.9625478e-06
+ SDmso CH2 1 0.0070633821 1.2365812e-05
+ SDmso CH3 1 0.0085073006 1.6102912e-05
+ SDmso CH4 1 0.011797996 2.7179749e-05
+ SDmso CR1 1 0.0076409495 1.3381228e-05
+ SDmso HC 1 0.000945484 5.703018e-07
+ SDmso H 1 0 0
+ SDmso DUM 1 0 0
+ SDmso S 1 0.010268778 1.6765946e-05
+ SDmso CU1+ 1 0.0021016465 3.3193419e-07
+ SDmso CU2+ 1 0.0021016465 3.3193419e-07
+ SDmso FE 1 0 0
+ SDmso ZN2+ 1 0.0021016465 4.5049206e-07
+ SDmso MG2+ 1 0.0008303816 2.7068471e-07
+ SDmso CA2+ 1 0.003257809 3.2720486e-06
+ SDmso P 1 0.012476278 2.1843023e-05
+ SDmso AR 1 0.0081342455 1.4549651e-05
+ SDmso F 1 0.0035270664 4.0440425e-06
+ SDmso CL 1 0.0096213274 1.8133743e-05
+ SDmso BR 1 0.0035291218 3.7519367e-05
+ SDmso CMet 1 0.0096819617 2.1173034e-05
+ SDmso OMet 1 0.0048877412 5.216175e-06
+ SDmso NA+ 1 0.00087241453 6.72307e-07
+ SDmso CL- 1 0.012075475 4.7942444e-05
+ SDmso CChl 1 0.0052712788 9.3473856e-06
+ SDmso CLChl 1 0.0093665606 1.720225e-05
+ SDmso HChl 1 0.0006310078 3.0404041e-07
+ SDmso SDmso 1 0.010561673 2.149806e-05
+ CDmso O 1 0.0045248108 4.016601e-06
+ CDmso OM 1 0.0045248108 4.016601e-06
+ CDmso OA 1 0.0045248108 5.2475625e-06
+ CDmso OW 1 0.0048673112 7.201988e-06
+ CDmso N 1 0.004696061 6.0685145e-06
+ CDmso NT 1 0.004696061 6.0685145e-06
+ CDmso NL 1 0.004696061 6.0685145e-06
+ CDmso NR 1 0.004696061 6.0685145e-06
+ CDmso NZ 1 0.004696061 6.0685145e-06
+ CDmso NE 1 0.004696061 6.0685145e-06
+ CDmso C 1 0.0046028248 8.5686865e-06
+ CDmso CH1 1 0.0051337004 9.0164785e-06
+ CDmso CH2 1 0.0065389035 1.2440222e-05
+ CDmso CH3 1 0.0078756064 1.6199809e-05
+ CDmso CH4 1 0.010921957 2.7343299e-05
+ CDmso CR1 1 0.0070735846 1.3461747e-05
+ CDmso HC 1 0.0008752788 5.737335e-07
+ CDmso H 1 0 0
+ CDmso DUM 1 0 0
+ CDmso S 1 0.0095062889 1.6866832e-05
+ CDmso CU1+ 1 0.0019455925 3.3393156e-07
+ CDmso CU2+ 1 0.0019455925 3.3393156e-07
+ CDmso FE 1 0 0
+ CDmso ZN2+ 1 0.0019455925 4.5320282e-07
+ CDmso MG2+ 1 0.00076872312 2.7231351e-07
+ CDmso CA2+ 1 0.0030159063 3.2917377e-06
+ CDmso P 1 0.011549875 2.197446e-05
+ CDmso AR 1 0.0075302519 1.4637201e-05
+ CDmso F 1 0.0032651705 4.0683769e-06
+ CDmso CL 1 0.0089069132 1.824286e-05
+ CDmso BR 1 0.0032670733 3.7745134e-05
+ CDmso CMet 1 0.0089630452 2.1300439e-05
+ CDmso OMet 1 0.0045248108 5.2475625e-06
+ CDmso NA+ 1 0.00080763497 6.763525e-07
+ CDmso CL- 1 0.011178832 4.823093e-05
+ CDmso CChl 1 0.0048798696 9.403632e-06
+ CDmso CLChl 1 0.0086710636 1.7305761e-05
+ CDmso HChl 1 0.00058415346 3.0586992e-07
+ CDmso SDmso 1 0.0097827 21.6523E-6
+ CDmso CDmso 1 0.0090514293 2.175756e-05
+ ODmso O 1 0.0022663291 7.4645315e-07
+ ODmso OM 1 0.0022663291 7.4645315e-07
+ ODmso OA 1 0.0022663291 9.752175e-07
+ ODmso OW 1 0.0024378763 1.3384318e-06
+ ODmso N 1 0.0023521027 1.1277849e-06
+ ODmso NT 1 0.0023521027 1.1277849e-06
+ ODmso NL 1 0.0023521027 1.1277849e-06
+ ODmso NR 1 0.0023521027 1.1277849e-06
+ ODmso NZ 1 0.0023521027 1.1277849e-06
+ ODmso NE 1 0.0023521027 1.1277849e-06
+ ODmso C 1 0.0023054038 1.5924218e-06
+ ODmso CH1 1 0.0025713019 1.6756404e-06
+ ODmso CH2 1 0.003275122 2.3119156e-06
+ ODmso CH3 1 0.0039446326 3.0106048e-06
+ ODmso CH4 1 0.0054704496 5.0815333e-06
+ ODmso CR1 1 0.0035429262 2.501758e-06
+ ODmso HC 1 0.0004383984 1.0662378e-07
+ ODmso H 1 0 0
+ ODmso DUM 1 0 0
+ ODmso S 1 0.0047613878 3.1345658e-06
+ ODmso CU1+ 1 0.0009744834 6.2058507e-08
+ ODmso CU2+ 1 0.0009744834 6.2058507e-08
+ ODmso FE 1 0 0
+ ODmso ZN2+ 1 0.0009744834 8.4224118e-08
+ ODmso MG2+ 1 0.00038502816 5.0607287e-08
+ ODmso CA2+ 1 0.0015105684 6.117431e-07
+ ODmso P 1 0.0057849528 4.0837775e-06
+ ODmso AR 1 0.0037716558 2.7202067e-06
+ ODmso F 1 0.0016354166 7.5607529e-07
+ ODmso CL 1 0.0044611802 3.3902895e-06
+ ODmso BR 1 0.0016363697 7.0146311e-06
+ ODmso CMet 1 0.0044892949 3.9585162e-06
+ ODmso OMet 1 0.0022663291 9.752175e-07
+ ODmso NA+ 1 0.00040451783 1.256947e-07
+ ODmso CL- 1 0.00559911 8.9633324e-06
+ ODmso CChl 1 0.0024441664 1.7475898e-06
+ ODmso CLChl 1 0.0043430509 3.2161373e-06
+ ODmso HChl 1 0.00029258328 5.6843478e-08
+ ODmso SDmso 1 0.0052442 4.6094E-6
+ ODmso CDmso 1 0.0049187 4.7597E-6
+ ODmso ODmso 1 0.0022707131 7.5144626e-07
+ CCl4 O 1 0.0024394475 2.3738805e-06
+ CCl4 OM 1 0.0024394475 2.3738805e-06
+ CCl4 OA 1 0.0024394475 3.1014e-06
+ CCl4 OW 1 0.0026240987 4.2564992e-06
+ CCl4 N 1 0.0025317731 3.5865968e-06
+ CCl4 NT 1 0.0025317731 3.5865968e-06
+ CCl4 NL 1 0.0025317731 3.5865968e-06
+ CCl4 NR 1 0.0025317731 3.5865968e-06
+ CCl4 NZ 1 0.0025317731 3.5865968e-06
+ CCl4 NE 1 0.0025317731 3.5865968e-06
+ CCl4 C 1 0.002481507 5.0642416e-06
+ CCl4 CH1 1 0.0027677163 5.3288944e-06
+ CCl4 CH2 1 0.0035252992 7.3523856e-06
+ CCl4 CH3 1 0.0042459518 9.5743664e-06
+ CCl4 CH4 1 0.0058883216 1.6160362e-05
+ CCl4 CR1 1 0.0038135602 7.9561248e-06
+ CCl4 HC 1 0.0004718864 3.390864e-07
+ CCl4 H 1 0 0
+ CCl4 DUM 1 0 0
+ CCl4 S 1 0.0051250966 9.9685888e-06
+ CCl4 CU1+ 1 0.0010489214 1.9735931e-07
+ CCl4 CU2+ 1 0.0010489214 1.9735931e-07
+ CCl4 FE 1 0 0
+ CCl4 ZN2+ 1 0.0010489214 2.6785069e-07
+ CCl4 MG2+ 1 0.00041443936 1.6094198e-07
+ CCl4 CA2+ 1 0.0016259564 1.9454738e-06
+ CCl4 P 1 0.0062268488 1.2987285e-05
+ CCl4 AR 1 0.0040597618 8.6508384e-06
+ CCl4 F 1 0.0017603414 2.404481e-06
+ CCl4 CL 1 0.004801957 1.0781845e-05
+ CCl4 BR 1 0.0017613673 2.2308026e-05
+ CCl4 CMet 1 0.0048322193 1.2588927e-05
+ CCl4 OMet 1 0.0024394475 3.1014e-06
+ CCl4 NA+ 1 0.00043541779 3.99736e-07
+ CCl4 CL- 1 0.00602681 2.8505312e-05
+ CCl4 CChl 1 0.0026308693 5.5577088e-06
+ CCl4 CLChl 1 0.0046748042 1.0228004e-05
+ CCl4 HChl 1 0.00031493288 1.807744e-07
+ CCl4 SDmso 1 0.0052712788 1.2782179e-05
+ CCl4 CDmso 1 0.0048798696 1.2859094e-05
+ CCl4 ODmso 1 0.0024441664 2.3897596e-06
+ CCl4 CCl4 1 0.0026308693 7.5999462e-06
+ CLCl4 O 1 0.0041472796 3.0768825e-06
+ CLCl4 OM 1 0.0041472796 3.0768825e-06
+ CLCl4 OA 1 0.0041472796 4.01985e-06
+ CLCl4 OW 1 0.0044612032 5.5170208e-06
+ CLCl4 N 1 0.0043042414 4.6487332e-06
+ CLCl4 NT 1 0.0043042414 4.6487332e-06
+ CLCl4 NL 1 0.0043042414 4.6487332e-06
+ CLCl4 NR 1 0.0043042414 4.6487332e-06
+ CLCl4 NZ 1 0.0043042414 4.6487332e-06
+ CLCl4 NE 1 0.0043042414 4.6487332e-06
+ CLCl4 C 1 0.0042187844 6.5639684e-06
+ CLCl4 CH1 1 0.004705366 6.9069956e-06
+ CLCl4 CH2 1 0.0059933247 9.5297244e-06
+ CLCl4 CH3 1 0.0072184988 1.2409724e-05
+ CLCl4 CH4 1 0.010010675 2.0946098e-05
+ CLCl4 CR1 1 0.0064833944 1.0312255e-05
+ CLCl4 HC 1 0.0008022492 4.395036e-07
+ CLCl4 H 1 0 0
+ CLCl4 DUM 1 0 0
+ CLCl4 S 1 0.0087131239 1.2920691e-05
+ CLCl4 CU1+ 1 0.0017832604 2.5580539e-07
+ CLCl4 CU2+ 1 0.0017832604 2.5580539e-07
+ CLCl4 FE 1 0 0
+ CLCl4 ZN2+ 1 0.0017832604 3.4717211e-07
+ CLCl4 MG2+ 1 0.00070458408 2.0860342e-07
+ CLCl4 CA2+ 1 0.0027642717 2.5216072e-06
+ CLCl4 P 1 0.010586201 1.6833345e-05
+ CLCl4 AR 1 0.0069019592 1.1212702e-05
+ CLCl4 F 1 0.0029927383 3.116545e-06
+ CLCl4 CL 1 0.0081637576 1.3974785e-05
+ CLCl4 BR 1 0.0029944823 2.8914334e-05
+ CLCl4 CMet 1 0.0082152062 1.6317018e-05
+ CLCl4 OMet 1 0.0041472796 4.01985e-06
+ CLCl4 NA+ 1 0.00074024929 5.18114e-07
+ CLCl4 CL- 1 0.010246117 3.6946888e-05
+ CLCl4 CChl 1 0.0044727137 7.2035712e-06
+ CLCl4 CLChl 1 0.0079475863 1.3256929e-05
+ CLCl4 HChl 1 0.00053541414 2.3430902e-07
+ CLCl4 SDmso 1 0.0089616468 1.6567499e-05
+ CLCl4 CDmso 1 0.0082962159 1.6667191e-05
+ CLCl4 ODmso 1 0.0041553021 3.0974642e-06
+ CLCl4 CCl4 1 0.0044727137 9.8505978e-06
+ CLCl4 CLCl4 1 0.0076040144 1.2767758e-05
SI O 1 0 0
SI OM 1 0 0
SI OA 1 0 0
SI F 1 0 0
SI CL 1 0 0
SI BR 1 0 0
- SI CMET 1 0 0
- SI OMET 1 0 0
+ SI CMet 1 0 0
+ SI OMet 1 0 0
SI NA+ 1 0 0
SI CL- 1 0 0
- SI CCHL 1 0 0
- SI CLCHL 1 0 0
- SI HCHL 1 0 0
- SI SDMSO 1 0 0
- SI CDMSO 1 0 0
- SI ODMSO 1 0 0
- SI CCL4 1 0 0
- SI CLCL4 1 0 0
+ SI CChl 1 0 0
+ SI CLChl 1 0 0
+ SI HChl 1 0 0
+ SI SDmso 1 0 0
+ SI CDmso 1 0 0
+ SI ODmso 1 0 0
+ SI CCl4 1 0 0
+ SI CLCl4 1 0 0
SI SI 1 0 0
--- /dev/null
+spc SPC simple point charge, recommended
+spce SPC/E extended simple point charge
aminoacids.hdb ffbonded.itp spc.itp \
aminoacids.n.tdb ffnonbonded.itp spce.itp \
aminoacids.rtp forcefield.doc tip3p.itp \
-aminoacids.vsd forcefield.itp tip4p.itp
+aminoacids.vsd forcefield.itp tip4p.itp \
+aminoacids.r2b watermodels.dat
EXTRA_DIST = ${topol_DATA}
--- /dev/null
+; rtp residue to rtp building block table
+;GMX Force-field
+CYS CYSH
+HISD HISA
+HISE HISB
+LYS LYSH
+LYSN LYS
C O gb_4
C +N gb_9
[ angles ]
+ CA C O ga_30
CA C +N ga_18
O C +N ga_32
[ impropers ]
OW OWT4 0.0 0
HW1 H 0.52 0
HW2 H 0.52 0
- HW3 IW -1.04 0
+ MW IW -1.04 0
[ bonds ]
OW HW1 gb_35
OW HW2 gb_35
- OW HW3 gb_35
[ angles ]
; ai aj ak gromos type
[ impropers ]
[ CHCL3 ]
[ atoms ]
- CChl CCHL 0.17900 0
- HChl HCHL 0.08200 0
-CLCh1 CLCHL -0.08700 0
-CLCh2 CLCHL -0.08700 0
-CLCh3 CLCHL -0.08700 0
+ CChl CChl 0.17900 0
+ HChl HChl 0.08200 0
+CLCh1 CLChl -0.08700 0
+CLCh2 CLChl -0.08700 0
+CLCh3 CLChl -0.08700 0
[ bonds ]
CChl CLCh1 gb_37
CChl CLCh2 gb_37
[ DMSO ]
[ atoms ]
-SDmso SDMSO 0.13900 0
-ODmso ODMSO -0.45900 0
-CDms1 CDMSO 0.16000 0
-CDms2 CDMSO 0.16000 0
+SDmso SDmso 0.13900 0
+ODmso ODmso -0.45900 0
+CDms1 CDmso 0.16000 0
+CDms2 CDmso 0.16000 0
[ bonds ]
SDmso ODmso gb_38
SDmso CDms1 gb_39
[ CH3OH ]
[ atoms ]
- Omet OMET -0.57400 0
+ Omet OMet -0.57400 0
HMet H 0.39800 0
- CMet CMET 0.17600 0
+ CMet CMet 0.17600 0
[ bonds ]
Omet HMet gb_1
Omet CMet gb_17
[ CCL4 ]
[ atoms ]
- CCl4 CCL4 0.00000 0
-CLCl1 CLCL4 0.00000 0
-CLCl2 CLCL4 0.00000 0
-CLCl3 CLCL4 0.00000 0
-CLCl4 CLCL4 0.00000 0
+ CCl4 CCl4 0.00000 0
+CLCl1 CLCl4 0.00000 0
+CLCl2 CLCl4 0.00000 0
+CLCl3 CLCl4 0.00000 0
+CLCl4 CLCl4 0.00000 0
[ bonds ]
CCl4 CLCl1 gb_40
CCl4 CLCl2 gb_40
F 18.99840 ; fluor (non-ionic)
CL 35.45300 ; chlorine (non-ionic)
BR 79.90400 ; bromine (non-ionic)
- CMET 15.035 ; CH3-group in methanol (solvent)
- OMET 15.9994 ; oxygen in methanol (solvent)
+ CMet 15.035 ; CH3-group in methanol (solvent)
+ OMet 15.9994 ; oxygen in methanol (solvent)
NA+ 22.9898 ; sodium (charge 1+)
CL- 35.45300 ; chlorine (charge 1-)
- CCHL 12.011 ; carbon in chloroform (solvent)
-CLCHL 35.453 ; chloride in chloroform (solvent)
- HCHL 1.008 ; hydrogen in chloroform (solvent)
-SDMSO 32.06000 ; DMSO Sulphur (solvent)
-CDMSO 15.03500 ; DMSO Carbon (solvent)
-ODMSO 15.99940 ; DMSO Oxygen (solvent)
- CCL4 12.011 ; carbon in carbontetrachloride (solvent)
-CLCL4 35.453 ; chloride in carbontetrachloride (solvent)
+ CChl 12.011 ; carbon in chloroform (solvent)
+CLChl 35.453 ; chloride in chloroform (solvent)
+ HChl 1.008 ; hydrogen in chloroform (solvent)
+SDmso 32.06000 ; DMSO Sulphur (solvent)
+CDmso 15.03500 ; DMSO Carbon (solvent)
+ODmso 15.99940 ; DMSO Oxygen (solvent)
+ CCl4 12.011 ; carbon in carbontetrachloride (solvent)
+CLCl4 35.453 ; chloride in carbontetrachloride (solvent)
SI 28.08 ; silicon
MNH3 0 ; Dummy mass in rigid tetraedrical NH3 group
MW 0 ; Dummy mass in rigid tyrosine rings
F 9 0.000 0.000 A 0.0011778624 7.6073284e-07
CL 17 0.000 0.000 A 0.0087647044 1.5295921e-05
BR 35 0.000 0.000 A 0.0011792356 6.5480464e-05
- CMET 6 0.000 0.000 A 0.0088755241 2.0852922e-05
- OMET 8 0.000 0.000 A 0.0022619536 1.505529e-06
+ CMet 6 0.000 0.000 A 0.0088755241 2.0852922e-05
+ OMet 8 0.000 0.000 A 0.0022619536 1.505529e-06
NA+ 11 0.000 0.000 A 7.2063121e-05 2.1025e-08
CL- 17 0.000 0.000 A 0.01380625 0.0001069156
- CCHL 6 0.000 0.000 A 0.0026308693 4.064256e-06
-CLCHL 17 0.000 0.000 A 0.0083066819 1.3764842e-05
- HCHL 1 0.000 0.000 A 3.76996e-05 4.2999495e-09
-SDMSO 16 0.000 0.000 A 0.010561673 2.149806e-05
-CDMSO 6 0.000 0.000 A 0.0090514293 2.175756e-05
-ODMSO 8 0.000 0.000 A 0.0022707131 7.5144626e-07
- CCL4 6 0.000 0.000 A 0.0026308693 7.5999462e-06
-CLCL4 17 0.000 0.000 A 0.0076040144 1.2767758e-05
+ CChl 6 0.000 0.000 A 0.0026308693 4.064256e-06
+CLChl 17 0.000 0.000 A 0.0083066819 1.3764842e-05
+ HChl 1 0.000 0.000 A 3.76996e-05 4.2999495e-09
+SDmso 16 0.000 0.000 A 0.010561673 2.149806e-05
+CDmso 6 0.000 0.000 A 0.0090514293 2.175756e-05
+ODmso 8 0.000 0.000 A 0.0022707131 7.5144626e-07
+ CCl4 6 0.000 0.000 A 0.0026308693 7.5999462e-06
+CLCl4 17 0.000 0.000 A 0.0076040144 1.2767758e-05
SI 14 0.000 0.000 A 0.01473796 2.2193521e-05
MNH3 0 0.000 0.000 A 0.0 0.0
OWT3 8 15.9994 0.000 A 0.24889E-02 0.24352E-05
BR AR 1 0.002718011 2.5392696e-05
BR F 1 0.0011785488 7.0578424e-06
BR CL 1 0.0032149108 3.1647812e-05
- CMET O 1 0.0044806276 3.9322131e-06
- CMET OM 1 0.0044806276 3.9322131e-06
- CMET OA 1 0.0044806276 5.1373125e-06
- CMET OW 1 0.0048197836 7.050676e-06
- CMET N 1 0.0046502056 5.9410165e-06
- CMET NT 1 0.0046502056 5.9410165e-06
- CMET NL 1 0.0046502056 5.9410165e-06
- CMET NR 1 0.0046502056 5.9410165e-06
- CMET NZ 1 0.0046502056 5.9410165e-06
- CMET NE 1 0.0046502056 5.9410165e-06
- CMET C 1 0.0045578798 8.3886605e-06
- CMET CH1 1 0.0057920308 1.5402804e-05
- CMET CH2 1 0.0079409609 2.318412e-05
- CMET CH3 1 0.0093814318 2.6458301e-05
- CMET CH4 1 0.010815308 2.6768823e-05
- CMET CR1 1 0.0069950925 1.7754552e-05
- CMET HC 1 0.000866732 5.616795e-07
- CMET H 1 0 0
- CMET DUM 1 0 0
- CMET S 1 0.0094134632 1.6512464e-05
- CMET CU1+ 1 0.0019265945 3.2691574e-07
- CMET CU2+ 1 0.0019265945 3.2691574e-07
- CMET FE 1 0 0
- CMET ZN2+ 1 0.0019265945 4.4368114e-07
- CMET MG2+ 1 0.0007612168 2.6659227e-07
- CMET CA2+ 1 0.002986457 3.222579e-06
- CMET P 1 0.011437094 2.1512782e-05
- CMET AR 1 0.0074567215 1.4329677e-05
- CMET F 1 0.0032332872 3.9829013e-06
- CMET CL 1 0.0088199402 1.7859582e-05
- CMET BR 1 0.0032351714 3.6952118e-05
- OMET O 1 0.0022619536 1.380375e-06
- OMET OM 1 0.0022619536 2.258907e-06
- OMET OA 1 0.0022619536 1.505529e-06
- OMET OW 1 0.0024331696 1.991421e-06
- OMET N 1 0.0023475616 2.384061e-06
- OMET NT 1 0.0023475616 2.76075e-06
- OMET NL 1 0.0023475616 3.764436e-06
- OMET NR 1 0.0023475616 2.258907e-06
- OMET NZ 1 0.0023475616 2.635596e-06
- OMET NE 1 0.0023475616 2.434368e-06
- OMET C 1 0.0023009528 2.066625e-06
- OMET CH1 1 0.0029239888 3.794625e-06
- OMET CH2 1 0.0040088324 5.711625e-06
- OMET CH3 1 0.0047360248 6.51825e-06
- OMET CH4 1 0.005459888 6.59475e-06
- OMET CR1 1 0.00353133 4.374e-06
- OMET HC 1 0.000437552 1.38375e-07
- OMET H 1 0 0
- OMET DUM 1 0 0
- OMET S 1 0.0047521952 4.068e-06
- OMET CU1+ 1 0.000972602 2.76075e-07
- OMET CU2+ 1 0.000972602 5.019657e-07
- OMET FE 1 0 0
- OMET ZN2+ 1 0.000972602 1.1921532e-07
- OMET MG2+ 1 0.0003842848 7.163226e-08
- OMET CA2+ 1 0.001507652 8.658939e-07
- OMET P 1 0.005773784 5.780397e-06
- OMET AR 1 0.003764374 3.53025e-06
- OMET F 1 0.0016322592 1.505529e-06
- OMET CL 1 0.0044525672 4.798797e-06
- OMET BR 1 0.0016332104 9.928884e-06
- OMET CMET 1 0.0044806276 5.1373125e-06
+ CMet O 1 0.0044806276 3.9322131e-06
+ CMet OM 1 0.0044806276 3.9322131e-06
+ CMet OA 1 0.0044806276 5.1373125e-06
+ CMet OW 1 0.0048197836 7.050676e-06
+ CMet N 1 0.0046502056 5.9410165e-06
+ CMet NT 1 0.0046502056 5.9410165e-06
+ CMet NL 1 0.0046502056 5.9410165e-06
+ CMet NR 1 0.0046502056 5.9410165e-06
+ CMet NZ 1 0.0046502056 5.9410165e-06
+ CMet NE 1 0.0046502056 5.9410165e-06
+ CMet C 1 0.0045578798 8.3886605e-06
+ CMet CH1 1 0.0057920308 1.5402804e-05
+ CMet CH2 1 0.0079409609 2.318412e-05
+ CMet CH3 1 0.0093814318 2.6458301e-05
+ CMet CH4 1 0.010815308 2.6768823e-05
+ CMet CR1 1 0.0069950925 1.7754552e-05
+ CMet HC 1 0.000866732 5.616795e-07
+ CMet H 1 0 0
+ CMet DUM 1 0 0
+ CMet S 1 0.0094134632 1.6512464e-05
+ CMet CU1+ 1 0.0019265945 3.2691574e-07
+ CMet CU2+ 1 0.0019265945 3.2691574e-07
+ CMet FE 1 0 0
+ CMet ZN2+ 1 0.0019265945 4.4368114e-07
+ CMet MG2+ 1 0.0007612168 2.6659227e-07
+ CMet CA2+ 1 0.002986457 3.222579e-06
+ CMet P 1 0.011437094 2.1512782e-05
+ CMet AR 1 0.0074567215 1.4329677e-05
+ CMet F 1 0.0032332872 3.9829013e-06
+ CMet CL 1 0.0088199402 1.7859582e-05
+ CMet BR 1 0.0032351714 3.6952118e-05
+ OMet O 1 0.0022619536 1.380375e-06
+ OMet OM 1 0.0022619536 2.258907e-06
+ OMet OA 1 0.0022619536 1.505529e-06
+ OMet OW 1 0.0024331696 1.991421e-06
+ OMet N 1 0.0023475616 2.384061e-06
+ OMet NT 1 0.0023475616 2.76075e-06
+ OMet NL 1 0.0023475616 3.764436e-06
+ OMet NR 1 0.0023475616 2.258907e-06
+ OMet NZ 1 0.0023475616 2.635596e-06
+ OMet NE 1 0.0023475616 2.434368e-06
+ OMet C 1 0.0023009528 2.066625e-06
+ OMet CH1 1 0.0029239888 3.794625e-06
+ OMet CH2 1 0.0040088324 5.711625e-06
+ OMet CH3 1 0.0047360248 6.51825e-06
+ OMet CH4 1 0.005459888 6.59475e-06
+ OMet CR1 1 0.00353133 4.374e-06
+ OMet HC 1 0.000437552 1.38375e-07
+ OMet H 1 0 0
+ OMet DUM 1 0 0
+ OMet S 1 0.0047521952 4.068e-06
+ OMet CU1+ 1 0.000972602 2.76075e-07
+ OMet CU2+ 1 0.000972602 5.019657e-07
+ OMet FE 1 0 0
+ OMet ZN2+ 1 0.000972602 1.1921532e-07
+ OMet MG2+ 1 0.0003842848 7.163226e-08
+ OMet CA2+ 1 0.001507652 8.658939e-07
+ OMet P 1 0.005773784 5.780397e-06
+ OMet AR 1 0.003764374 3.53025e-06
+ OMet F 1 0.0016322592 1.505529e-06
+ OMet CL 1 0.0044525672 4.798797e-06
+ OMet BR 1 0.0016332104 9.928884e-06
+ OMet CMet 1 0.0044806276 5.1373125e-06
NA+ O 1 0.00040373684 1.63125e-07
NA+ OM 1 0.00040373684 4.4486e-07
NA+ OA 1 0.00040373684 1.77915e-07
NA+ F 1 0.00029134248 1.77915e-07
NA+ CL 1 0.00079474018 5.67095e-07
NA+ BR 1 0.00029151226 1.17334e-06
- NA+ CMET 1 0.00079974869 6.621425e-07
- NA+ OMET 1 0.00040373684 1.77915e-07
+ NA+ CMet 1 0.00079974869 6.621425e-07
+ NA+ OMet 1 0.00040373684 1.77915e-07
CL- O 1 0.0055883 8.903774e-06
CL- OM 1 0.0055883 8.903774e-06
CL- OA 1 0.0055883 1.268718e-05
CL- F 1 0.0040326 9.018548e-06
CL- CL 1 0.01100035 4.043974e-05
CL- BR 1 0.00403495 8.367128e-05
- CL- CMET 1 0.011069675 4.721761e-05
- CL- OMET 1 0.0055883 1.268718e-05
+ CL- CMet 1 0.011069675 4.721761e-05
+ CL- OMet 1 0.0055883 1.268718e-05
CL- NA+ 1 0.0009974575 1.4993e-06
- CCHL O 1 0.0024394475 1.7359776e-06
- CCHL OM 1 0.0024394475 1.7359776e-06
- CCHL OA 1 0.0024394475 2.268e-06
- CCHL OW 1 0.0026240987 3.112704e-06
- CCHL N 1 0.0025317731 2.622816e-06
- CCHL NT 1 0.0025317731 2.622816e-06
- CCHL NL 1 0.0025317731 2.622816e-06
- CCHL NR 1 0.0025317731 2.622816e-06
- CCHL NZ 1 0.0025317731 2.622816e-06
- CCHL NE 1 0.0025317731 2.622816e-06
- CCHL C 1 0.002481507 3.703392e-06
- CCHL CH1 1 0.0031534322 6.799968e-06
- CCHL CH2 1 0.0043234027 1.0235232e-05
- CCHL CH3 1 0.0051076574 1.1680704e-05
- CCHL CH4 1 0.0058883216 1.1817792e-05
- CCHL CR1 1 0.003808431 7.838208e-06
- CCHL HC 1 0.0004718864 2.47968e-07
- CCHL H 1 0 0
- CCHL DUM 1 0 0
- CCHL S 1 0.0051250966 7.289856e-06
- CCHL CU1+ 1 0.0010489214 1.4432544e-07
- CCHL CU2+ 1 0.0010489214 1.4432544e-07
- CCHL FE 1 0 0
- CCHL ZN2+ 1 0.0010489214 1.9587456e-07
- CCHL MG2+ 1 0.00041443936 1.1769408e-07
- CCHL CA2+ 1 0.0016259564 1.4226912e-06
- CCHL P 1 0.0062268488 9.497376e-06
- CCHL AR 1 0.0040597618 6.326208e-06
- CCHL F 1 0.0017603414 1.7583552e-06
- CCHL CL 1 0.004801957 7.884576e-06
- CCHL BR 1 0.0017613673 1.6313472e-05
- CCHL CMET 1 0.0048322193 9.206064e-06
- CCHL OMET 1 0.0024394475 2.268e-06
- CCHL NA+ 1 0.00043541779 2.9232e-07
- CCHL CL- 1 0.00602681 2.084544e-05
- CLCHL O 1 0.004334666 3.1947671e-06
- CLCHL OM 1 0.004334666 3.1947671e-06
- CLCHL OA 1 0.004334666 4.1738625e-06
- CLCHL OW 1 0.0046627736 5.7283944e-06
- CLCHL N 1 0.0044987198 4.8268401e-06
- CLCHL NT 1 0.0044987198 4.8268401e-06
- CLCHL NL 1 0.0044987198 4.8268401e-06
- CLCHL NR 1 0.0044987198 4.8268401e-06
- CLCHL NZ 1 0.0044987198 4.8268401e-06
- CLCHL NE 1 0.0044987198 4.8268401e-06
- CLCHL C 1 0.0044094016 6.8154537e-06
- CLCHL CH1 1 0.0056033487 1.2514167e-05
- CLCHL CH2 1 0.0076822749 1.8836178e-05
- CLCHL CH3 1 0.0090758208 2.1496319e-05
- CLCHL CH4 1 0.010462987 2.1748606e-05
- CLCHL CR1 1 0.0067672192 1.4424869e-05
- CLCHL HC 1 0.0008384972 4.563423e-07
- CLCHL H 1 0 0
- CLCHL DUM 1 0 0
- CLCHL S 1 0.0091068087 1.3415722e-05
- CLCHL CU1+ 1 0.0018638335 2.6560606e-07
- CLCHL CU2+ 1 0.0018638335 2.6560606e-07
- CLCHL FE 1 0 0
- CLCHL ZN2+ 1 0.0018638335 3.6047332e-07
- CLCHL MG2+ 1 0.00073641928 2.1659564e-07
- CLCHL CA2+ 1 0.0028891697 2.6182176e-06
- CLCHL P 1 0.011064517 1.7478281e-05
- CLCHL AR 1 0.0072138101 1.1642294e-05
- CLCHL F 1 0.0031279591 3.2359492e-06
- CLCHL CL 1 0.0085326204 1.4510201e-05
- CLCHL BR 1 0.0031297819 3.0022129e-05
- CLCHL CMET 1 0.0085863936 1.6942172e-05
- CLCHL OMET 1 0.004334666 4.1738625e-06
- CLCHL NA+ 1 0.00077369595 5.379645e-07
- CLCHL CL- 1 0.010709067 3.8362434e-05
- CLCHL CCHL 1 0.0046754 7.4813E-6
- HCHL O 1 0.0002920184 5.6465771e-08
- HCHL OM 1 0.0002920184 5.6465771e-08
- HCHL OA 1 0.0002920184 7.377075e-08
- HCHL OW 1 0.0003141224 1.0124626e-07
- HCHL N 1 0.0003030704 8.5311774e-08
- HCHL NT 1 0.0003030704 8.5311774e-08
- HCHL NL 1 0.0003030704 8.5311774e-08
- HCHL NR 1 0.0003030704 8.5311774e-08
- HCHL NZ 1 0.0003030704 8.5311774e-08
- HCHL NE 1 0.0003030704 8.5311774e-08
- HCHL C 1 0.0002970532 1.2045944e-07
- HCHL CH1 1 0.0003774872 2.211811e-07
- HCHL CH2 1 0.0005175406 3.329192e-07
- HCHL CH3 1 0.0006114212 3.7993576e-07
- HCHL CH4 1 0.000704872 3.8439479e-07
- HCHL CR1 1 0.000455895 2.5495171e-07
- HCHL HC 1 5.6488e-05 8.065602e-09
- HCHL H 1 0 0
- HCHL DUM 1 0 0
- HCHL S 1 0.0006135088 2.3711558e-07
- HCHL CU1+ 1 0.000125563 4.6944427e-09
- HCHL CU2+ 1 0.000125563 4.6944427e-09
- HCHL FE 1 0 0
- HCHL ZN2+ 1 0.000125563 6.3711698e-09
- HCHL MG2+ 1 4.96112e-05 3.8282101e-09
- HCHL CA2+ 1 0.000194638 4.6275572e-08
- HCHL P 1 0.000745396 3.0891911e-07
- HCHL AR 1 0.000485981 2.0577121e-07
- HCHL F 1 0.0002107248 5.7193643e-08
- HCHL CL 1 0.0005748268 2.5645991e-07
- HCHL BR 1 0.0002108476 5.3062481e-07
- HCHL CMET 1 0.0005784494 2.9944367e-07
- HCHL OMET 1 0.0002920184 7.377075e-08
- HCHL NA+ 1 5.212246e-05 9.50823e-09
- HCHL CL- 1 0.00072145 6.7803516e-07
- HCHL CCHL 1 0.0003622 0.1745E-6
- HCHL CLCHL 1 0.0006493 0.3266E-6
- SDMSO O 1 0.0048877412 3.9925763e-06
- SDMSO OM 1 0.0048877412 3.9925763e-06
- SDMSO OA 1 0.0048877412 5.216175e-06
- SDMSO OW 1 0.0052577132 7.1589104e-06
- SDMSO N 1 0.0050727272 6.0322166e-06
- SDMSO NT 1 0.0050727272 6.0322166e-06
- SDMSO NL 1 0.0050727272 6.0322166e-06
- SDMSO NR 1 0.0050727272 6.0322166e-06
- SDMSO NZ 1 0.0050727272 6.0322166e-06
- SDMSO NE 1 0.0050727272 6.0322166e-06
- SDMSO C 1 0.0049720126 8.5174342e-06
- SDMSO CH1 1 0.0063182996 1.5639252e-05
- SDMSO CH2 1 0.0086624833 2.3540018e-05
- SDMSO CH3 1 0.010233837 2.686446e-05
- SDMSO CH4 1 0.011797996 2.7179749e-05
- SDMSO CR1 1 0.0076306725 1.8027101e-05
- SDMSO HC 1 0.000945484 5.703018e-07
- SDMSO H 1 0 0
- SDMSO DUM 1 0 0
- SDMSO S 1 0.010268778 1.6765946e-05
- SDMSO CU1+ 1 0.0021016465 3.3193419e-07
- SDMSO CU2+ 1 0.0021016465 3.3193419e-07
- SDMSO FE 1 0 0
- SDMSO ZN2+ 1 0.0021016465 4.5049206e-07
- SDMSO MG2+ 1 0.0008303816 2.7068471e-07
- SDMSO CA2+ 1 0.003257809 3.2720486e-06
- SDMSO P 1 0.012476278 2.1843023e-05
- SDMSO AR 1 0.0081342455 1.4549651e-05
- SDMSO F 1 0.0035270664 4.0440425e-06
- SDMSO CL 1 0.0096213274 1.8133743e-05
- SDMSO BR 1 0.0035291218 3.7519367e-05
- SDMSO CMET 1 0.0096819617 2.1173034e-05
- SDMSO OMET 1 0.0048877412 5.216175e-06
- SDMSO NA+ 1 0.00087241453 6.72307e-07
- SDMSO CL- 1 0.012075475 4.7942444e-05
- SDMSO CCHL 1 0.0052712788 9.3473856e-06
- SDMSO CLCHL 1 0.0093665606 1.720225e-05
- SDMSO HCHL 1 0.0006310078 3.0404041e-07
- CDMSO O 1 0.0045248108 4.016601e-06
- CDMSO OM 1 0.0045248108 4.016601e-06
- CDMSO OA 1 0.0045248108 5.2475625e-06
- CDMSO OW 1 0.0048673112 7.201988e-06
- CDMSO N 1 0.004696061 6.0685145e-06
- CDMSO NT 1 0.004696061 6.0685145e-06
- CDMSO NL 1 0.004696061 6.0685145e-06
- CDMSO NR 1 0.004696061 6.0685145e-06
- CDMSO NZ 1 0.004696061 6.0685145e-06
- CDMSO NE 1 0.004696061 6.0685145e-06
- CDMSO C 1 0.0046028248 8.5686865e-06
- CDMSO CH1 1 0.0058491457 1.5733359e-05
- CDMSO CH2 1 0.0080192663 2.3681667e-05
- CDMSO CH3 1 0.0094739416 2.7026113e-05
- CDMSO CH4 1 0.010921957 2.7343299e-05
- CDMSO CR1 1 0.0070640708 1.8135576e-05
- CDMSO HC 1 0.0008752788 5.737335e-07
- CDMSO H 1 0 0
- CDMSO DUM 1 0 0
- CDMSO S 1 0.0095062889 1.6866832e-05
- CDMSO CU1+ 1 0.0019455925 3.3393156e-07
- CDMSO CU2+ 1 0.0019455925 3.3393156e-07
- CDMSO FE 1 0 0
- CDMSO ZN2+ 1 0.0019455925 4.5320282e-07
- CDMSO MG2+ 1 0.00076872312 2.7231351e-07
- CDMSO CA2+ 1 0.0030159063 3.2917377e-06
- CDMSO P 1 0.011549875 2.197446e-05
- CDMSO AR 1 0.0075302519 1.4637201e-05
- CDMSO F 1 0.0032651705 4.0683769e-06
- CDMSO CL 1 0.0089069132 1.824286e-05
- CDMSO BR 1 0.0032670733 3.7745134e-05
- CDMSO CMET 1 0.0089630452 2.1300439e-05
- CDMSO OMET 1 0.0045248108 5.2475625e-06
- CDMSO NA+ 1 0.00080763497 6.763525e-07
- CDMSO CL- 1 0.011178832 4.823093e-05
- CDMSO CCHL 1 0.0048798696 9.403632e-06
- CDMSO CLCHL 1 0.0086710636 1.7305761e-05
- CDMSO HCHL 1 0.00058415346 3.0586992e-07
- CDMSO SDMSO 1 0.0097827 21.6523E-6
- ODMSO O 1 0.0022663291 7.4645315e-07
- ODMSO OM 1 0.0022663291 7.4645315e-07
- ODMSO OA 1 0.0022663291 1.380375e-06
- ODMSO OW 1 0.0024378763 1.825875e-06
- ODMSO N 1 0.0023521027 2.185875e-06
- ODMSO NT 1 0.0023521027 2.53125e-06
- ODMSO NL 1 0.0023521027 3.4515e-06
- ODMSO NR 1 0.0023521027 2.071125e-06
- ODMSO NZ 1 0.0023521027 2.4165e-06
- ODMSO NE 1 0.0023521027 2.232e-06
- ODMSO C 1 0.0023054038 1.5924218e-06
- ODMSO CH1 1 0.002929645 2.9239188e-06
- ODMSO CH2 1 0.0040165871 4.4010482e-06
- ODMSO CH3 1 0.0047451862 5.0225868e-06
- ODMSO CH4 1 0.0054704496 5.0815333e-06
- ODMSO CR1 1 0.003538161 3.3703517e-06
- ODMSO HC 1 0.0004383984 1.0662378e-07
- ODMSO H 1 0 0
- ODMSO DUM 1 0 0
- ODMSO S 1 0.0047613878 3.1345658e-06
- ODMSO CU1+ 1 0.0009744834 2.53125e-07
- ODMSO CU2+ 1 0.0009744834 4.602375e-07
- ODMSO FE 1 0 0
- ODMSO ZN2+ 1 0.0009744834 1.09305e-07
- ODMSO MG2+ 1 0.00038502816 6.56775e-08
- ODMSO CA2+ 1 0.0015105684 7.939125e-07
- ODMSO P 1 0.0057849528 5.299875e-06
- ODMSO AR 1 0.0037716558 2.7202067e-06
- ODMSO F 1 0.0016354166 7.5607529e-07
- ODMSO CL 1 0.0044611802 3.3902895e-06
- ODMSO BR 1 0.0016363697 7.0146311e-06
- ODMSO CMET 1 0.0044892949 3.9585162e-06
- ODMSO OMET 1 0.0022663291 1.380375e-06
- ODMSO NA+ 1 0.00040451783 1.63125e-07
- ODMSO CL- 1 0.00559911 8.9633324e-06
- ODMSO CCHL 1 0.0024441664 1.7475898e-06
- ODMSO CLCHL 1 0.0043430509 3.2161373e-06
- ODMSO HCHL 1 0.00029258328 5.6843478e-08
- ODMSO SDMSO 1 0.0052442 4.6094E-6
- ODMSO CDMSO 1 0.0049187 4.7597E-6
- CCL4 O 1 0.0024394475 2.3738805e-06
- CCL4 OM 1 0.0024394475 2.3738805e-06
- CCL4 OA 1 0.0024394475 3.1014e-06
- CCL4 OW 1 0.0026240987 4.2564992e-06
- CCL4 N 1 0.0025317731 3.5865968e-06
- CCL4 NT 1 0.0025317731 3.5865968e-06
- CCL4 NL 1 0.0025317731 3.5865968e-06
- CCL4 NR 1 0.0025317731 3.5865968e-06
- CCL4 NZ 1 0.0025317731 3.5865968e-06
- CCL4 NE 1 0.0025317731 3.5865968e-06
- CCL4 C 1 0.002481507 5.0642416e-06
- CCL4 CH1 1 0.0031534322 9.2986864e-06
- CCL4 CH2 1 0.0043234027 1.3996274e-05
- CCL4 CH3 1 0.0051076574 1.5972899e-05
- CCL4 CH4 1 0.0058883216 1.6160362e-05
- CCL4 CR1 1 0.003808431 1.0718438e-05
- CCL4 HC 1 0.0004718864 3.390864e-07
- CCL4 H 1 0 0
- CCL4 DUM 1 0 0
- CCL4 S 1 0.0051250966 9.9685888e-06
- CCL4 CU1+ 1 0.0010489214 1.9735931e-07
- CCL4 CU2+ 1 0.0010489214 1.9735931e-07
- CCL4 FE 1 0 0
- CCL4 ZN2+ 1 0.0010489214 2.6785069e-07
- CCL4 MG2+ 1 0.00041443936 1.6094198e-07
- CCL4 CA2+ 1 0.0016259564 1.9454738e-06
- CCL4 P 1 0.0062268488 1.2987285e-05
- CCL4 AR 1 0.0040597618 8.6508384e-06
- CCL4 F 1 0.0017603414 2.404481e-06
- CCL4 CL 1 0.004801957 1.0781845e-05
- CCL4 BR 1 0.0017613673 2.2308026e-05
- CCL4 CMET 1 0.0048322193 1.2588927e-05
- CCL4 OMET 1 0.0024394475 3.1014e-06
- CCL4 NA+ 1 0.00043541779 3.99736e-07
- CCL4 CL- 1 0.00602681 2.8505312e-05
- CCL4 CCHL 1 0.0026308693 5.5577088e-06
- CCL4 CLCHL 1 0.0046748042 1.0228004e-05
- CCL4 HCHL 1 0.00031493288 1.807744e-07
- CCL4 SDMSO 1 0.0052712788 1.2782179e-05
- CCL4 CDMSO 1 0.0048798696 1.2859094e-05
- CCL4 ODMSO 1 0.0024441664 2.3897596e-06
- CLCL4 O 1 0.0041472796 3.0768825e-06
- CLCL4 OM 1 0.0041472796 3.0768825e-06
- CLCL4 OA 1 0.0041472796 4.01985e-06
- CLCL4 OW 1 0.0044612032 5.5170208e-06
- CLCL4 N 1 0.0043042414 4.6487332e-06
- CLCL4 NT 1 0.0043042414 4.6487332e-06
- CLCL4 NL 1 0.0043042414 4.6487332e-06
- CLCL4 NR 1 0.0043042414 4.6487332e-06
- CLCL4 NZ 1 0.0043042414 4.6487332e-06
- CLCL4 NE 1 0.0043042414 4.6487332e-06
- CLCL4 C 1 0.0042187844 6.5639684e-06
- CLCL4 CH1 1 0.0053611175 1.2052404e-05
- CLCL4 CH2 1 0.0073501723 1.8141136e-05
- CLCL4 CH3 1 0.0086834756 2.0703121e-05
- CLCL4 CH4 1 0.010010675 2.0946098e-05
- CLCL4 CR1 1 0.0064746742 1.3892602e-05
- CLCL4 HC 1 0.0008022492 4.395036e-07
- CLCL4 H 1 0 0
- CLCL4 DUM 1 0 0
- CLCL4 S 1 0.0087131239 1.2920691e-05
- CLCL4 CU1+ 1 0.0017832604 2.5580539e-07
- CLCL4 CU2+ 1 0.0017832604 2.5580539e-07
- CLCL4 FE 1 0 0
- CLCL4 ZN2+ 1 0.0017832604 3.4717211e-07
- CLCL4 MG2+ 1 0.00070458408 2.0860342e-07
- CLCL4 CA2+ 1 0.0027642717 2.5216072e-06
- CLCL4 P 1 0.010586201 1.6833345e-05
- CLCL4 AR 1 0.0069019592 1.1212702e-05
- CLCL4 F 1 0.0029927383 3.116545e-06
- CLCL4 CL 1 0.0081637576 1.3974785e-05
- CLCL4 BR 1 0.0029944823 2.8914334e-05
- CLCL4 CMET 1 0.0082152062 1.6317018e-05
- CLCL4 OMET 1 0.0041472796 4.01985e-06
- CLCL4 NA+ 1 0.00074024929 5.18114e-07
- CLCL4 CL- 1 0.010246117 3.6946888e-05
- CLCL4 CCHL 1 0.0044727137 7.2035712e-06
- CLCL4 CLCHL 1 0.0079475863 1.3256929e-05
- CLCL4 HCHL 1 0.00053541414 2.3430902e-07
- CLCL4 SDMSO 1 0.0089616468 1.6567499e-05
- CLCL4 CDMSO 1 0.0082962159 1.6667191e-05
- CLCL4 ODMSO 1 0.0041553021 3.0974642e-06
- CLCL4 CCL4 1 0.0044727137 9.8505978e-06
+ CChl O 1 0.0024394475 1.7359776e-06
+ CChl OM 1 0.0024394475 1.7359776e-06
+ CChl OA 1 0.0024394475 2.268e-06
+ CChl OW 1 0.0026240987 3.112704e-06
+ CChl N 1 0.0025317731 2.622816e-06
+ CChl NT 1 0.0025317731 2.622816e-06
+ CChl NL 1 0.0025317731 2.622816e-06
+ CChl NR 1 0.0025317731 2.622816e-06
+ CChl NZ 1 0.0025317731 2.622816e-06
+ CChl NE 1 0.0025317731 2.622816e-06
+ CChl C 1 0.002481507 3.703392e-06
+ CChl CH1 1 0.0031534322 6.799968e-06
+ CChl CH2 1 0.0043234027 1.0235232e-05
+ CChl CH3 1 0.0051076574 1.1680704e-05
+ CChl CH4 1 0.0058883216 1.1817792e-05
+ CChl CR1 1 0.003808431 7.838208e-06
+ CChl HC 1 0.0004718864 2.47968e-07
+ CChl H 1 0 0
+ CChl DUM 1 0 0
+ CChl S 1 0.0051250966 7.289856e-06
+ CChl CU1+ 1 0.0010489214 1.4432544e-07
+ CChl CU2+ 1 0.0010489214 1.4432544e-07
+ CChl FE 1 0 0
+ CChl ZN2+ 1 0.0010489214 1.9587456e-07
+ CChl MG2+ 1 0.00041443936 1.1769408e-07
+ CChl CA2+ 1 0.0016259564 1.4226912e-06
+ CChl P 1 0.0062268488 9.497376e-06
+ CChl AR 1 0.0040597618 6.326208e-06
+ CChl F 1 0.0017603414 1.7583552e-06
+ CChl CL 1 0.004801957 7.884576e-06
+ CChl BR 1 0.0017613673 1.6313472e-05
+ CChl CMet 1 0.0048322193 9.206064e-06
+ CChl OMet 1 0.0024394475 2.268e-06
+ CChl NA+ 1 0.00043541779 2.9232e-07
+ CChl CL- 1 0.00602681 2.084544e-05
+ CLChl O 1 0.004334666 3.1947671e-06
+ CLChl OM 1 0.004334666 3.1947671e-06
+ CLChl OA 1 0.004334666 4.1738625e-06
+ CLChl OW 1 0.0046627736 5.7283944e-06
+ CLChl N 1 0.0044987198 4.8268401e-06
+ CLChl NT 1 0.0044987198 4.8268401e-06
+ CLChl NL 1 0.0044987198 4.8268401e-06
+ CLChl NR 1 0.0044987198 4.8268401e-06
+ CLChl NZ 1 0.0044987198 4.8268401e-06
+ CLChl NE 1 0.0044987198 4.8268401e-06
+ CLChl C 1 0.0044094016 6.8154537e-06
+ CLChl CH1 1 0.0056033487 1.2514167e-05
+ CLChl CH2 1 0.0076822749 1.8836178e-05
+ CLChl CH3 1 0.0090758208 2.1496319e-05
+ CLChl CH4 1 0.010462987 2.1748606e-05
+ CLChl CR1 1 0.0067672192 1.4424869e-05
+ CLChl HC 1 0.0008384972 4.563423e-07
+ CLChl H 1 0 0
+ CLChl DUM 1 0 0
+ CLChl S 1 0.0091068087 1.3415722e-05
+ CLChl CU1+ 1 0.0018638335 2.6560606e-07
+ CLChl CU2+ 1 0.0018638335 2.6560606e-07
+ CLChl FE 1 0 0
+ CLChl ZN2+ 1 0.0018638335 3.6047332e-07
+ CLChl MG2+ 1 0.00073641928 2.1659564e-07
+ CLChl CA2+ 1 0.0028891697 2.6182176e-06
+ CLChl P 1 0.011064517 1.7478281e-05
+ CLChl AR 1 0.0072138101 1.1642294e-05
+ CLChl F 1 0.0031279591 3.2359492e-06
+ CLChl CL 1 0.0085326204 1.4510201e-05
+ CLChl BR 1 0.0031297819 3.0022129e-05
+ CLChl CMet 1 0.0085863936 1.6942172e-05
+ CLChl OMet 1 0.004334666 4.1738625e-06
+ CLChl NA+ 1 0.00077369595 5.379645e-07
+ CLChl CL- 1 0.010709067 3.8362434e-05
+ CLChl CChl 1 0.0046754 7.4813E-6
+ HChl O 1 0.0002920184 5.6465771e-08
+ HChl OM 1 0.0002920184 5.6465771e-08
+ HChl OA 1 0.0002920184 7.377075e-08
+ HChl OW 1 0.0003141224 1.0124626e-07
+ HChl N 1 0.0003030704 8.5311774e-08
+ HChl NT 1 0.0003030704 8.5311774e-08
+ HChl NL 1 0.0003030704 8.5311774e-08
+ HChl NR 1 0.0003030704 8.5311774e-08
+ HChl NZ 1 0.0003030704 8.5311774e-08
+ HChl NE 1 0.0003030704 8.5311774e-08
+ HChl C 1 0.0002970532 1.2045944e-07
+ HChl CH1 1 0.0003774872 2.211811e-07
+ HChl CH2 1 0.0005175406 3.329192e-07
+ HChl CH3 1 0.0006114212 3.7993576e-07
+ HChl CH4 1 0.000704872 3.8439479e-07
+ HChl CR1 1 0.000455895 2.5495171e-07
+ HChl HC 1 5.6488e-05 8.065602e-09
+ HChl H 1 0 0
+ HChl DUM 1 0 0
+ HChl S 1 0.0006135088 2.3711558e-07
+ HChl CU1+ 1 0.000125563 4.6944427e-09
+ HChl CU2+ 1 0.000125563 4.6944427e-09
+ HChl FE 1 0 0
+ HChl ZN2+ 1 0.000125563 6.3711698e-09
+ HChl MG2+ 1 4.96112e-05 3.8282101e-09
+ HChl CA2+ 1 0.000194638 4.6275572e-08
+ HChl P 1 0.000745396 3.0891911e-07
+ HChl AR 1 0.000485981 2.0577121e-07
+ HChl F 1 0.0002107248 5.7193643e-08
+ HChl CL 1 0.0005748268 2.5645991e-07
+ HChl BR 1 0.0002108476 5.3062481e-07
+ HChl CMet 1 0.0005784494 2.9944367e-07
+ HChl OMet 1 0.0002920184 7.377075e-08
+ HChl NA+ 1 5.212246e-05 9.50823e-09
+ HChl CL- 1 0.00072145 6.7803516e-07
+ HChl CChl 1 0.0003622 0.1745E-6
+ HChl CLChl 1 0.0006493 0.3266E-6
+ SDmso O 1 0.0048877412 3.9925763e-06
+ SDmso OM 1 0.0048877412 3.9925763e-06
+ SDmso OA 1 0.0048877412 5.216175e-06
+ SDmso OW 1 0.0052577132 7.1589104e-06
+ SDmso N 1 0.0050727272 6.0322166e-06
+ SDmso NT 1 0.0050727272 6.0322166e-06
+ SDmso NL 1 0.0050727272 6.0322166e-06
+ SDmso NR 1 0.0050727272 6.0322166e-06
+ SDmso NZ 1 0.0050727272 6.0322166e-06
+ SDmso NE 1 0.0050727272 6.0322166e-06
+ SDmso C 1 0.0049720126 8.5174342e-06
+ SDmso CH1 1 0.0063182996 1.5639252e-05
+ SDmso CH2 1 0.0086624833 2.3540018e-05
+ SDmso CH3 1 0.010233837 2.686446e-05
+ SDmso CH4 1 0.011797996 2.7179749e-05
+ SDmso CR1 1 0.0076306725 1.8027101e-05
+ SDmso HC 1 0.000945484 5.703018e-07
+ SDmso H 1 0 0
+ SDmso DUM 1 0 0
+ SDmso S 1 0.010268778 1.6765946e-05
+ SDmso CU1+ 1 0.0021016465 3.3193419e-07
+ SDmso CU2+ 1 0.0021016465 3.3193419e-07
+ SDmso FE 1 0 0
+ SDmso ZN2+ 1 0.0021016465 4.5049206e-07
+ SDmso MG2+ 1 0.0008303816 2.7068471e-07
+ SDmso CA2+ 1 0.003257809 3.2720486e-06
+ SDmso P 1 0.012476278 2.1843023e-05
+ SDmso AR 1 0.0081342455 1.4549651e-05
+ SDmso F 1 0.0035270664 4.0440425e-06
+ SDmso CL 1 0.0096213274 1.8133743e-05
+ SDmso BR 1 0.0035291218 3.7519367e-05
+ SDmso CMet 1 0.0096819617 2.1173034e-05
+ SDmso OMet 1 0.0048877412 5.216175e-06
+ SDmso NA+ 1 0.00087241453 6.72307e-07
+ SDmso CL- 1 0.012075475 4.7942444e-05
+ SDmso CChl 1 0.0052712788 9.3473856e-06
+ SDmso CLChl 1 0.0093665606 1.720225e-05
+ SDmso HChl 1 0.0006310078 3.0404041e-07
+ CDmso O 1 0.0045248108 4.016601e-06
+ CDmso OM 1 0.0045248108 4.016601e-06
+ CDmso OA 1 0.0045248108 5.2475625e-06
+ CDmso OW 1 0.0048673112 7.201988e-06
+ CDmso N 1 0.004696061 6.0685145e-06
+ CDmso NT 1 0.004696061 6.0685145e-06
+ CDmso NL 1 0.004696061 6.0685145e-06
+ CDmso NR 1 0.004696061 6.0685145e-06
+ CDmso NZ 1 0.004696061 6.0685145e-06
+ CDmso NE 1 0.004696061 6.0685145e-06
+ CDmso C 1 0.0046028248 8.5686865e-06
+ CDmso CH1 1 0.0058491457 1.5733359e-05
+ CDmso CH2 1 0.0080192663 2.3681667e-05
+ CDmso CH3 1 0.0094739416 2.7026113e-05
+ CDmso CH4 1 0.010921957 2.7343299e-05
+ CDmso CR1 1 0.0070640708 1.8135576e-05
+ CDmso HC 1 0.0008752788 5.737335e-07
+ CDmso H 1 0 0
+ CDmso DUM 1 0 0
+ CDmso S 1 0.0095062889 1.6866832e-05
+ CDmso CU1+ 1 0.0019455925 3.3393156e-07
+ CDmso CU2+ 1 0.0019455925 3.3393156e-07
+ CDmso FE 1 0 0
+ CDmso ZN2+ 1 0.0019455925 4.5320282e-07
+ CDmso MG2+ 1 0.00076872312 2.7231351e-07
+ CDmso CA2+ 1 0.0030159063 3.2917377e-06
+ CDmso P 1 0.011549875 2.197446e-05
+ CDmso AR 1 0.0075302519 1.4637201e-05
+ CDmso F 1 0.0032651705 4.0683769e-06
+ CDmso CL 1 0.0089069132 1.824286e-05
+ CDmso BR 1 0.0032670733 3.7745134e-05
+ CDmso CMet 1 0.0089630452 2.1300439e-05
+ CDmso OMet 1 0.0045248108 5.2475625e-06
+ CDmso NA+ 1 0.00080763497 6.763525e-07
+ CDmso CL- 1 0.011178832 4.823093e-05
+ CDmso CChl 1 0.0048798696 9.403632e-06
+ CDmso CLChl 1 0.0086710636 1.7305761e-05
+ CDmso HChl 1 0.00058415346 3.0586992e-07
+ CDmso SDmso 1 0.0097827 21.6523E-6
+ ODmso O 1 0.0022663291 7.4645315e-07
+ ODmso OM 1 0.0022663291 7.4645315e-07
+ ODmso OA 1 0.0022663291 1.380375e-06
+ ODmso OW 1 0.0024378763 1.825875e-06
+ ODmso N 1 0.0023521027 2.185875e-06
+ ODmso NT 1 0.0023521027 2.53125e-06
+ ODmso NL 1 0.0023521027 3.4515e-06
+ ODmso NR 1 0.0023521027 2.071125e-06
+ ODmso NZ 1 0.0023521027 2.4165e-06
+ ODmso NE 1 0.0023521027 2.232e-06
+ ODmso C 1 0.0023054038 1.5924218e-06
+ ODmso CH1 1 0.002929645 2.9239188e-06
+ ODmso CH2 1 0.0040165871 4.4010482e-06
+ ODmso CH3 1 0.0047451862 5.0225868e-06
+ ODmso CH4 1 0.0054704496 5.0815333e-06
+ ODmso CR1 1 0.003538161 3.3703517e-06
+ ODmso HC 1 0.0004383984 1.0662378e-07
+ ODmso H 1 0 0
+ ODmso DUM 1 0 0
+ ODmso S 1 0.0047613878 3.1345658e-06
+ ODmso CU1+ 1 0.0009744834 2.53125e-07
+ ODmso CU2+ 1 0.0009744834 4.602375e-07
+ ODmso FE 1 0 0
+ ODmso ZN2+ 1 0.0009744834 1.09305e-07
+ ODmso MG2+ 1 0.00038502816 6.56775e-08
+ ODmso CA2+ 1 0.0015105684 7.939125e-07
+ ODmso P 1 0.0057849528 5.299875e-06
+ ODmso AR 1 0.0037716558 2.7202067e-06
+ ODmso F 1 0.0016354166 7.5607529e-07
+ ODmso CL 1 0.0044611802 3.3902895e-06
+ ODmso BR 1 0.0016363697 7.0146311e-06
+ ODmso CMet 1 0.0044892949 3.9585162e-06
+ ODmso OMet 1 0.0022663291 1.380375e-06
+ ODmso NA+ 1 0.00040451783 1.63125e-07
+ ODmso CL- 1 0.00559911 8.9633324e-06
+ ODmso CChl 1 0.0024441664 1.7475898e-06
+ ODmso CLChl 1 0.0043430509 3.2161373e-06
+ ODmso HChl 1 0.00029258328 5.6843478e-08
+ ODmso SDmso 1 0.0052442 4.6094E-6
+ ODmso CDmso 1 0.0049187 4.7597E-6
+ CCl4 O 1 0.0024394475 2.3738805e-06
+ CCl4 OM 1 0.0024394475 2.3738805e-06
+ CCl4 OA 1 0.0024394475 3.1014e-06
+ CCl4 OW 1 0.0026240987 4.2564992e-06
+ CCl4 N 1 0.0025317731 3.5865968e-06
+ CCl4 NT 1 0.0025317731 3.5865968e-06
+ CCl4 NL 1 0.0025317731 3.5865968e-06
+ CCl4 NR 1 0.0025317731 3.5865968e-06
+ CCl4 NZ 1 0.0025317731 3.5865968e-06
+ CCl4 NE 1 0.0025317731 3.5865968e-06
+ CCl4 C 1 0.002481507 5.0642416e-06
+ CCl4 CH1 1 0.0031534322 9.2986864e-06
+ CCl4 CH2 1 0.0043234027 1.3996274e-05
+ CCl4 CH3 1 0.0051076574 1.5972899e-05
+ CCl4 CH4 1 0.0058883216 1.6160362e-05
+ CCl4 CR1 1 0.003808431 1.0718438e-05
+ CCl4 HC 1 0.0004718864 3.390864e-07
+ CCl4 H 1 0 0
+ CCl4 DUM 1 0 0
+ CCl4 S 1 0.0051250966 9.9685888e-06
+ CCl4 CU1+ 1 0.0010489214 1.9735931e-07
+ CCl4 CU2+ 1 0.0010489214 1.9735931e-07
+ CCl4 FE 1 0 0
+ CCl4 ZN2+ 1 0.0010489214 2.6785069e-07
+ CCl4 MG2+ 1 0.00041443936 1.6094198e-07
+ CCl4 CA2+ 1 0.0016259564 1.9454738e-06
+ CCl4 P 1 0.0062268488 1.2987285e-05
+ CCl4 AR 1 0.0040597618 8.6508384e-06
+ CCl4 F 1 0.0017603414 2.404481e-06
+ CCl4 CL 1 0.004801957 1.0781845e-05
+ CCl4 BR 1 0.0017613673 2.2308026e-05
+ CCl4 CMet 1 0.0048322193 1.2588927e-05
+ CCl4 OMet 1 0.0024394475 3.1014e-06
+ CCl4 NA+ 1 0.00043541779 3.99736e-07
+ CCl4 CL- 1 0.00602681 2.8505312e-05
+ CCl4 CChl 1 0.0026308693 5.5577088e-06
+ CCl4 CLChl 1 0.0046748042 1.0228004e-05
+ CCl4 HChl 1 0.00031493288 1.807744e-07
+ CCl4 SDmso 1 0.0052712788 1.2782179e-05
+ CCl4 CDmso 1 0.0048798696 1.2859094e-05
+ CCl4 ODmso 1 0.0024441664 2.3897596e-06
+ CLCl4 O 1 0.0041472796 3.0768825e-06
+ CLCl4 OM 1 0.0041472796 3.0768825e-06
+ CLCl4 OA 1 0.0041472796 4.01985e-06
+ CLCl4 OW 1 0.0044612032 5.5170208e-06
+ CLCl4 N 1 0.0043042414 4.6487332e-06
+ CLCl4 NT 1 0.0043042414 4.6487332e-06
+ CLCl4 NL 1 0.0043042414 4.6487332e-06
+ CLCl4 NR 1 0.0043042414 4.6487332e-06
+ CLCl4 NZ 1 0.0043042414 4.6487332e-06
+ CLCl4 NE 1 0.0043042414 4.6487332e-06
+ CLCl4 C 1 0.0042187844 6.5639684e-06
+ CLCl4 CH1 1 0.0053611175 1.2052404e-05
+ CLCl4 CH2 1 0.0073501723 1.8141136e-05
+ CLCl4 CH3 1 0.0086834756 2.0703121e-05
+ CLCl4 CH4 1 0.010010675 2.0946098e-05
+ CLCl4 CR1 1 0.0064746742 1.3892602e-05
+ CLCl4 HC 1 0.0008022492 4.395036e-07
+ CLCl4 H 1 0 0
+ CLCl4 DUM 1 0 0
+ CLCl4 S 1 0.0087131239 1.2920691e-05
+ CLCl4 CU1+ 1 0.0017832604 2.5580539e-07
+ CLCl4 CU2+ 1 0.0017832604 2.5580539e-07
+ CLCl4 FE 1 0 0
+ CLCl4 ZN2+ 1 0.0017832604 3.4717211e-07
+ CLCl4 MG2+ 1 0.00070458408 2.0860342e-07
+ CLCl4 CA2+ 1 0.0027642717 2.5216072e-06
+ CLCl4 P 1 0.010586201 1.6833345e-05
+ CLCl4 AR 1 0.0069019592 1.1212702e-05
+ CLCl4 F 1 0.0029927383 3.116545e-06
+ CLCl4 CL 1 0.0081637576 1.3974785e-05
+ CLCl4 BR 1 0.0029944823 2.8914334e-05
+ CLCl4 CMet 1 0.0082152062 1.6317018e-05
+ CLCl4 OMet 1 0.0041472796 4.01985e-06
+ CLCl4 NA+ 1 0.00074024929 5.18114e-07
+ CLCl4 CL- 1 0.010246117 3.6946888e-05
+ CLCl4 CChl 1 0.0044727137 7.2035712e-06
+ CLCl4 CLChl 1 0.0079475863 1.3256929e-05
+ CLCl4 HChl 1 0.00053541414 2.3430902e-07
+ CLCl4 SDmso 1 0.0089616468 1.6567499e-05
+ CLCl4 CDmso 1 0.0082962159 1.6667191e-05
+ CLCl4 ODmso 1 0.0041553021 3.0974642e-06
+ CLCl4 CCl4 1 0.0044727137 9.8505978e-06
SI O 1 0.005773784 5.299875e-06
SI OM 1 0.005773784 1.4453348e-05
SI OA 1 0.005773784 5.780397e-06
SI F 1 0.004166448 5.780397e-06
SI CL 1 0.011365468 1.8424721e-05
SI BR 1 0.004168876 3.8121412e-05
- SI CMET 1 0.011437094 2.1512782e-05
- SI OMET 1 0.005773784 5.780397e-06
+ SI CMet 1 0.011437094 2.1512782e-05
+ SI OMet 1 0.005773784 5.780397e-06
SI NA+ 1 0.0010305646 6.83095e-07
SI CL- 1 0.0142645 4.871174e-05
- SI CCHL 1 0.0062268488 9.497376e-06
- SI CLCHL 1 0.011064517 1.7478281e-05
- SI HCHL 1 0.000745396 3.0891911e-07
- SI SDMSO 1 0.012476278 2.1843023e-05
- SI CDMSO 1 0.011549875 2.197446e-05
- SI ODMSO 1 0.0057849528 5.299875e-06
- SI CCL4 1 0.0062268488 1.2987285e-05
- SI CLCL4 1 0.010586201 1.6833345e-05
+ SI CChl 1 0.0062268488 9.497376e-06
+ SI CLChl 1 0.011064517 1.7478281e-05
+ SI HChl 1 0.000745396 3.0891911e-07
+ SI SDmso 1 0.012476278 2.1843023e-05
+ SI CDmso 1 0.011549875 2.197446e-05
+ SI ODmso 1 0.0057849528 5.299875e-06
+ SI CCl4 1 0.0062268488 1.2987285e-05
+ SI CLCl4 1 0.010586201 1.6833345e-05
[ pairtypes ]
; i j func c6 c12
BR F 1 0.0011785488 7.0578424e-06
BR CL 1 0.0032149108 3.1647812e-05
BR BR 1 0.0011792356 6.5480464e-05
- CMET O 1 0.0044806276 3.9322131e-06
- CMET OM 1 0.0044806276 3.9322131e-06
- CMET OA 1 0.0044806276 5.1373125e-06
- CMET OW 1 0.0048197836 7.050676e-06
- CMET N 1 0.0046502056 5.9410165e-06
- CMET NT 1 0.0046502056 5.9410165e-06
- CMET NL 1 0.0046502056 5.9410165e-06
- CMET NR 1 0.0046502056 5.9410165e-06
- CMET NZ 1 0.0046502056 5.9410165e-06
- CMET NE 1 0.0046502056 5.9410165e-06
- CMET C 1 0.0045578798 8.3886605e-06
- CMET CH1 1 0.0050835716 8.8270445e-06
- CMET CH2 1 0.0064750533 9.943994e-06
- CMET CH3 1 0.0077987038 1.1214329e-05
- CMET CH4 1 0.010815308 2.6768823e-05
- CMET CR1 1 0.0070045135 1.3178919e-05
- CMET HC 1 0.000866732 5.616795e-07
- CMET H 1 0 0
- CMET DUM 1 0 0
- CMET S 1 0.0094134632 1.6512464e-05
- CMET CU1+ 1 0.0019265945 3.2691574e-07
- CMET CU2+ 1 0.0019265945 3.2691574e-07
- CMET FE 1 0 0
- CMET ZN2+ 1 0.0019265945 4.4368114e-07
- CMET MG2+ 1 0.0007612168 2.6659227e-07
- CMET CA2+ 1 0.002986457 3.222579e-06
- CMET P 1 0.011437094 2.1512782e-05
- CMET AR 1 0.0074567215 1.4329677e-05
- CMET F 1 0.0032332872 3.9829013e-06
- CMET CL 1 0.0088199402 1.7859582e-05
- CMET BR 1 0.0032351714 3.6952118e-05
- CMET CMET 1 0.0088755241 2.0852922e-05
- OMET O 1 0.0022619536 9.687375e-07
- OMET OM 1 0.0022619536 9.687375e-07
- OMET OA 1 0.0022619536 1.265625e-06
- OMET OW 1 0.0024331696 1.737e-06
- OMET N 1 0.0023475616 1.463625e-06
- OMET NT 1 0.0023475616 1.463625e-06
- OMET NL 1 0.0023475616 1.463625e-06
- OMET NR 1 0.0023475616 1.463625e-06
- OMET NZ 1 0.0023475616 1.463625e-06
- OMET NE 1 0.0023475616 1.463625e-06
- OMET C 1 0.0023009528 2.066625e-06
- OMET CH1 1 0.0025663376 2.174625e-06
- OMET CH2 1 0.0032687988 2.4497959e-06
- OMET CH3 1 0.0039370168 2.7627548e-06
- OMET CH4 1 0.005459888 6.59475e-06
- OMET CR1 1 0.003536086 3.24675e-06
- OMET HC 1 0.000437552 1.38375e-07
- OMET H 1 0 0
- OMET DUM 1 0 0
- OMET S 1 0.0047521952 4.068e-06
- OMET CU1+ 1 0.000972602 8.053875e-08
- OMET CU2+ 1 0.000972602 8.053875e-08
- OMET FE 1 0 0
- OMET ZN2+ 1 0.000972602 1.09305e-07
- OMET MG2+ 1 0.0003842848 6.56775e-08
- OMET CA2+ 1 0.001507652 7.939125e-07
- OMET P 1 0.005773784 5.299875e-06
- OMET AR 1 0.003764374 3.53025e-06
- OMET F 1 0.0016322592 9.81225e-07
- OMET CL 1 0.0044525672 4.399875e-06
- OMET BR 1 0.0016332104 9.1035e-06
- OMET CMET 1 0.0044806276 5.1373125e-06
- OMET OMET 1 0.0022619536 1.265625e-06
+ CMet O 1 0.0044806276 3.9322131e-06
+ CMet OM 1 0.0044806276 3.9322131e-06
+ CMet OA 1 0.0044806276 5.1373125e-06
+ CMet OW 1 0.0048197836 7.050676e-06
+ CMet N 1 0.0046502056 5.9410165e-06
+ CMet NT 1 0.0046502056 5.9410165e-06
+ CMet NL 1 0.0046502056 5.9410165e-06
+ CMet NR 1 0.0046502056 5.9410165e-06
+ CMet NZ 1 0.0046502056 5.9410165e-06
+ CMet NE 1 0.0046502056 5.9410165e-06
+ CMet C 1 0.0045578798 8.3886605e-06
+ CMet CH1 1 0.0050835716 8.8270445e-06
+ CMet CH2 1 0.0064750533 9.943994e-06
+ CMet CH3 1 0.0077987038 1.1214329e-05
+ CMet CH4 1 0.010815308 2.6768823e-05
+ CMet CR1 1 0.0070045135 1.3178919e-05
+ CMet HC 1 0.000866732 5.616795e-07
+ CMet H 1 0 0
+ CMet DUM 1 0 0
+ CMet S 1 0.0094134632 1.6512464e-05
+ CMet CU1+ 1 0.0019265945 3.2691574e-07
+ CMet CU2+ 1 0.0019265945 3.2691574e-07
+ CMet FE 1 0 0
+ CMet ZN2+ 1 0.0019265945 4.4368114e-07
+ CMet MG2+ 1 0.0007612168 2.6659227e-07
+ CMet CA2+ 1 0.002986457 3.222579e-06
+ CMet P 1 0.011437094 2.1512782e-05
+ CMet AR 1 0.0074567215 1.4329677e-05
+ CMet F 1 0.0032332872 3.9829013e-06
+ CMet CL 1 0.0088199402 1.7859582e-05
+ CMet BR 1 0.0032351714 3.6952118e-05
+ CMet CMet 1 0.0088755241 2.0852922e-05
+ OMet O 1 0.0022619536 9.687375e-07
+ OMet OM 1 0.0022619536 9.687375e-07
+ OMet OA 1 0.0022619536 1.265625e-06
+ OMet OW 1 0.0024331696 1.737e-06
+ OMet N 1 0.0023475616 1.463625e-06
+ OMet NT 1 0.0023475616 1.463625e-06
+ OMet NL 1 0.0023475616 1.463625e-06
+ OMet NR 1 0.0023475616 1.463625e-06
+ OMet NZ 1 0.0023475616 1.463625e-06
+ OMet NE 1 0.0023475616 1.463625e-06
+ OMet C 1 0.0023009528 2.066625e-06
+ OMet CH1 1 0.0025663376 2.174625e-06
+ OMet CH2 1 0.0032687988 2.4497959e-06
+ OMet CH3 1 0.0039370168 2.7627548e-06
+ OMet CH4 1 0.005459888 6.59475e-06
+ OMet CR1 1 0.003536086 3.24675e-06
+ OMet HC 1 0.000437552 1.38375e-07
+ OMet H 1 0 0
+ OMet DUM 1 0 0
+ OMet S 1 0.0047521952 4.068e-06
+ OMet CU1+ 1 0.000972602 8.053875e-08
+ OMet CU2+ 1 0.000972602 8.053875e-08
+ OMet FE 1 0 0
+ OMet ZN2+ 1 0.000972602 1.09305e-07
+ OMet MG2+ 1 0.0003842848 6.56775e-08
+ OMet CA2+ 1 0.001507652 7.939125e-07
+ OMet P 1 0.005773784 5.299875e-06
+ OMet AR 1 0.003764374 3.53025e-06
+ OMet F 1 0.0016322592 9.81225e-07
+ OMet CL 1 0.0044525672 4.399875e-06
+ OMet BR 1 0.0016332104 9.1035e-06
+ OMet CMet 1 0.0044806276 5.1373125e-06
+ OMet OMet 1 0.0022619536 1.265625e-06
NA+ O 1 0.00040373684 1.248595e-07
NA+ OM 1 0.00040373684 1.248595e-07
NA+ OA 1 0.00040373684 1.63125e-07
NA+ F 1 0.00029134248 1.26469e-07
NA+ CL 1 0.00079474018 5.67095e-07
NA+ BR 1 0.00029151226 1.17334e-06
- NA+ CMET 1 0.00079974869 6.621425e-07
- NA+ OMET 1 0.00040373684 1.63125e-07
+ NA+ CMet 1 0.00079974869 6.621425e-07
+ NA+ OMet 1 0.00040373684 1.63125e-07
NA+ NA+ 1 7.2063121e-05 2.1025e-08
CL- O 1 0.0055883 8.903774e-06
CL- OM 1 0.0055883 8.903774e-06
CL- F 1 0.0040326 9.018548e-06
CL- CL 1 0.01100035 4.043974e-05
CL- BR 1 0.00403495 8.367128e-05
- CL- CMET 1 0.011069675 4.721761e-05
- CL- OMET 1 0.0055883 1.16325e-05
+ CL- CMet 1 0.011069675 4.721761e-05
+ CL- OMet 1 0.0055883 1.16325e-05
CL- NA+ 1 0.0009974575 1.4993e-06
CL- CL- 1 0.01380625 0.0001069156
- CCHL O 1 0.0024394475 1.7359776e-06
- CCHL OM 1 0.0024394475 1.7359776e-06
- CCHL OA 1 0.0024394475 2.268e-06
- CCHL OW 1 0.0026240987 3.112704e-06
- CCHL N 1 0.0025317731 2.622816e-06
- CCHL NT 1 0.0025317731 2.622816e-06
- CCHL NL 1 0.0025317731 2.622816e-06
- CCHL NR 1 0.0025317731 2.622816e-06
- CCHL NZ 1 0.0025317731 2.622816e-06
- CCHL NE 1 0.0025317731 2.622816e-06
- CCHL C 1 0.002481507 3.703392e-06
- CCHL CH1 1 0.0027677163 3.896928e-06
- CCHL CH2 1 0.0035252992 4.3900343e-06
- CCHL CH3 1 0.0042459518 4.9508565e-06
- CCHL CH4 1 0.0058883216 1.1817792e-05
- CCHL CR1 1 0.0038135602 5.818176e-06
- CCHL HC 1 0.0004718864 2.47968e-07
- CCHL H 1 0 0
- CCHL DUM 1 0 0
- CCHL S 1 0.0051250966 7.289856e-06
- CCHL CU1+ 1 0.0010489214 1.4432544e-07
- CCHL CU2+ 1 0.0010489214 1.4432544e-07
- CCHL FE 1 0 0
- CCHL ZN2+ 1 0.0010489214 1.9587456e-07
- CCHL MG2+ 1 0.00041443936 1.1769408e-07
- CCHL CA2+ 1 0.0016259564 1.4226912e-06
- CCHL P 1 0.0062268488 9.497376e-06
- CCHL AR 1 0.0040597618 6.326208e-06
- CCHL F 1 0.0017603414 1.7583552e-06
- CCHL CL 1 0.004801957 7.884576e-06
- CCHL BR 1 0.0017613673 1.6313472e-05
- CCHL CMET 1 0.0048322193 9.206064e-06
- CCHL OMET 1 0.0024394475 2.268e-06
- CCHL NA+ 1 0.00043541779 2.9232e-07
- CCHL CL- 1 0.00602681 2.084544e-05
- CCHL CCHL 1 0.0026308693 4.064256e-06
- CLCHL O 1 0.004334666 3.1947671e-06
- CLCHL OM 1 0.004334666 3.1947671e-06
- CLCHL OA 1 0.004334666 4.1738625e-06
- CLCHL OW 1 0.0046627736 5.7283944e-06
- CLCHL N 1 0.0044987198 4.8268401e-06
- CLCHL NT 1 0.0044987198 4.8268401e-06
- CLCHL NL 1 0.0044987198 4.8268401e-06
- CLCHL NR 1 0.0044987198 4.8268401e-06
- CLCHL NZ 1 0.0044987198 4.8268401e-06
- CLCHL NE 1 0.0044987198 4.8268401e-06
- CLCHL C 1 0.0044094016 6.8154537e-06
- CLCHL CH1 1 0.0049179684 7.1716233e-06
- CLCHL CH2 1 0.0062641209 8.0791004e-06
- CLCHL CH3 1 0.007544652 9.1111968e-06
- CLCHL CH4 1 0.010462987 2.1748606e-05
- CLCHL CR1 1 0.0067763334 1.0707349e-05
- CLCHL HC 1 0.0008384972 4.563423e-07
- CLCHL H 1 0 0
- CLCHL DUM 1 0 0
- CLCHL S 1 0.0091068087 1.3415722e-05
- CLCHL CU1+ 1 0.0018638335 2.6560606e-07
- CLCHL CU2+ 1 0.0018638335 2.6560606e-07
- CLCHL FE 1 0 0
- CLCHL ZN2+ 1 0.0018638335 3.6047332e-07
- CLCHL MG2+ 1 0.00073641928 2.1659564e-07
- CLCHL CA2+ 1 0.0028891697 2.6182176e-06
- CLCHL P 1 0.011064517 1.7478281e-05
- CLCHL AR 1 0.0072138101 1.1642294e-05
- CLCHL F 1 0.0031279591 3.2359492e-06
- CLCHL CL 1 0.0085326204 1.4510201e-05
- CLCHL BR 1 0.0031297819 3.0022129e-05
- CLCHL CMET 1 0.0085863936 1.6942172e-05
- CLCHL OMET 1 0.004334666 4.1738625e-06
- CLCHL NA+ 1 0.00077369595 5.379645e-07
- CLCHL CL- 1 0.010709067 3.8362434e-05
- CLCHL CCHL 1 0.0046754 7.4813E-6
- CLCHL CLCHL 1 0.0083066819 1.3764842e-05
- HCHL O 1 0.0002920184 5.6465771e-08
- HCHL OM 1 0.0002920184 5.6465771e-08
- HCHL OA 1 0.0002920184 7.377075e-08
- HCHL OW 1 0.0003141224 1.0124626e-07
- HCHL N 1 0.0003030704 8.5311774e-08
- HCHL NT 1 0.0003030704 8.5311774e-08
- HCHL NL 1 0.0003030704 8.5311774e-08
- HCHL NR 1 0.0003030704 8.5311774e-08
- HCHL NZ 1 0.0003030704 8.5311774e-08
- HCHL NE 1 0.0003030704 8.5311774e-08
- HCHL C 1 0.0002970532 1.2045944e-07
- HCHL CH1 1 0.0003313144 1.2675454e-07
- HCHL CH2 1 0.0004220022 1.4279371e-07
- HCHL CH3 1 0.0005082692 1.6103545e-07
- HCHL CH4 1 0.000704872 3.8439479e-07
- HCHL CR1 1 0.000456509 1.8924656e-07
- HCHL HC 1 5.6488e-05 8.065602e-09
- HCHL H 1 0 0
- HCHL DUM 1 0 0
- HCHL S 1 0.0006135088 2.3711558e-07
- HCHL CU1+ 1 0.000125563 4.6944427e-09
- HCHL CU2+ 1 0.000125563 4.6944427e-09
- HCHL FE 1 0 0
- HCHL ZN2+ 1 0.000125563 6.3711698e-09
- HCHL MG2+ 1 4.96112e-05 3.8282101e-09
- HCHL CA2+ 1 0.000194638 4.6275572e-08
- HCHL P 1 0.000745396 3.0891911e-07
- HCHL AR 1 0.000485981 2.0577121e-07
- HCHL F 1 0.0002107248 5.7193643e-08
- HCHL CL 1 0.0005748268 2.5645991e-07
- HCHL BR 1 0.0002108476 5.3062481e-07
- HCHL CMET 1 0.0005784494 2.9944367e-07
- HCHL OMET 1 0.0002920184 7.377075e-08
- HCHL NA+ 1 5.212246e-05 9.50823e-09
- HCHL CL- 1 0.00072145 6.7803516e-07
- HCHL CCHL 1 0.0003622 0.1745E-6
- HCHL CLCHL 1 0.0006493 0.3266E-6
- HCHL HCHL 1 3.76996e-05 4.2999495e-09
- SDMSO O 1 0.0048877412 3.9925763e-06
- SDMSO OM 1 0.0048877412 3.9925763e-06
- SDMSO OA 1 0.0048877412 5.216175e-06
- SDMSO OW 1 0.0052577132 7.1589104e-06
- SDMSO N 1 0.0050727272 6.0322166e-06
- SDMSO NT 1 0.0050727272 6.0322166e-06
- SDMSO NL 1 0.0050727272 6.0322166e-06
- SDMSO NR 1 0.0050727272 6.0322166e-06
- SDMSO NZ 1 0.0050727272 6.0322166e-06
- SDMSO NE 1 0.0050727272 6.0322166e-06
- SDMSO C 1 0.0049720126 8.5174342e-06
- SDMSO CH1 1 0.0055454692 8.9625478e-06
- SDMSO CH2 1 0.0070633821 1.0096643e-05
- SDMSO CH3 1 0.0085073006 1.1386479e-05
- SDMSO CH4 1 0.011797996 2.7179749e-05
- SDMSO CR1 1 0.0076409495 1.3381228e-05
- SDMSO HC 1 0.000945484 5.703018e-07
- SDMSO H 1 0 0
- SDMSO DUM 1 0 0
- SDMSO S 1 0.010268778 1.6765946e-05
- SDMSO CU1+ 1 0.0021016465 3.3193419e-07
- SDMSO CU2+ 1 0.0021016465 3.3193419e-07
- SDMSO FE 1 0 0
- SDMSO ZN2+ 1 0.0021016465 4.5049206e-07
- SDMSO MG2+ 1 0.0008303816 2.7068471e-07
- SDMSO CA2+ 1 0.003257809 3.2720486e-06
- SDMSO P 1 0.012476278 2.1843023e-05
- SDMSO AR 1 0.0081342455 1.4549651e-05
- SDMSO F 1 0.0035270664 4.0440425e-06
- SDMSO CL 1 0.0096213274 1.8133743e-05
- SDMSO BR 1 0.0035291218 3.7519367e-05
- SDMSO CMET 1 0.0096819617 2.1173034e-05
- SDMSO OMET 1 0.0048877412 5.216175e-06
- SDMSO NA+ 1 0.00087241453 6.72307e-07
- SDMSO CL- 1 0.012075475 4.7942444e-05
- SDMSO CCHL 1 0.0052712788 9.3473856e-06
- SDMSO CLCHL 1 0.0093665606 1.720225e-05
- SDMSO HCHL 1 0.0006310078 3.0404041e-07
- SDMSO SDMSO 1 0.010561673 2.149806e-05
- CDMSO O 1 0.0045248108 4.016601e-06
- CDMSO OM 1 0.0045248108 4.016601e-06
- CDMSO OA 1 0.0045248108 5.2475625e-06
- CDMSO OW 1 0.0048673112 7.201988e-06
- CDMSO N 1 0.004696061 6.0685145e-06
- CDMSO NT 1 0.004696061 6.0685145e-06
- CDMSO NL 1 0.004696061 6.0685145e-06
- CDMSO NR 1 0.004696061 6.0685145e-06
- CDMSO NZ 1 0.004696061 6.0685145e-06
- CDMSO NE 1 0.004696061 6.0685145e-06
- CDMSO C 1 0.0046028248 8.5686865e-06
- CDMSO CH1 1 0.0051337004 9.0164785e-06
- CDMSO CH2 1 0.0065389035 1.0157398e-05
- CDMSO CH3 1 0.0078756064 1.1454995e-05
- CDMSO CH4 1 0.010921957 2.7343299e-05
- CDMSO CR1 1 0.0070735846 1.3461747e-05
- CDMSO HC 1 0.0008752788 5.737335e-07
- CDMSO H 1 0 0
- CDMSO DUM 1 0 0
- CDMSO S 1 0.0095062889 1.6866832e-05
- CDMSO CU1+ 1 0.0019455925 3.3393156e-07
- CDMSO CU2+ 1 0.0019455925 3.3393156e-07
- CDMSO FE 1 0 0
- CDMSO ZN2+ 1 0.0019455925 4.5320282e-07
- CDMSO MG2+ 1 0.00076872312 2.7231351e-07
- CDMSO CA2+ 1 0.0030159063 3.2917377e-06
- CDMSO P 1 0.011549875 2.197446e-05
- CDMSO AR 1 0.0075302519 1.4637201e-05
- CDMSO F 1 0.0032651705 4.0683769e-06
- CDMSO CL 1 0.0089069132 1.824286e-05
- CDMSO BR 1 0.0032670733 3.7745134e-05
- CDMSO CMET 1 0.0089630452 2.1300439e-05
- CDMSO OMET 1 0.0045248108 5.2475625e-06
- CDMSO NA+ 1 0.00080763497 6.763525e-07
- CDMSO CL- 1 0.011178832 4.823093e-05
- CDMSO CCHL 1 0.0048798696 9.403632e-06
- CDMSO CLCHL 1 0.0086710636 1.7305761e-05
- CDMSO HCHL 1 0.00058415346 3.0586992e-07
- CDMSO SDMSO 1 0.0097827 21.6523E-6
- CDMSO CDMSO 1 0.0090514293 2.175756e-05
- ODMSO O 1 0.0022663291 7.4645315e-07
- ODMSO OM 1 0.0022663291 7.4645315e-07
- ODMSO OA 1 0.0022663291 9.752175e-07
- ODMSO OW 1 0.0024378763 1.3384318e-06
- ODMSO N 1 0.0023521027 1.1277849e-06
- ODMSO NT 1 0.0023521027 1.1277849e-06
- ODMSO NL 1 0.0023521027 1.1277849e-06
- ODMSO NR 1 0.0023521027 1.1277849e-06
- ODMSO NZ 1 0.0023521027 1.1277849e-06
- ODMSO NE 1 0.0023521027 1.1277849e-06
- ODMSO C 1 0.0023054038 1.5924218e-06
- ODMSO CH1 1 0.0025713019 1.6756404e-06
- ODMSO CH2 1 0.003275122 1.8876712e-06
- ODMSO CH3 1 0.0039446326 2.1288192e-06
- ODMSO CH4 1 0.0054704496 5.0815333e-06
- ODMSO CR1 1 0.0035429262 2.501758e-06
- ODMSO HC 1 0.0004383984 1.0662378e-07
- ODMSO H 1 0 0
- ODMSO DUM 1 0 0
- ODMSO S 1 0.0047613878 3.1345658e-06
- ODMSO CU1+ 1 0.0009744834 6.2058507e-08
- ODMSO CU2+ 1 0.0009744834 6.2058507e-08
- ODMSO FE 1 0 0
- ODMSO ZN2+ 1 0.0009744834 8.4224118e-08
- ODMSO MG2+ 1 0.00038502816 5.0607287e-08
- ODMSO CA2+ 1 0.0015105684 6.117431e-07
- ODMSO P 1 0.0057849528 4.0837775e-06
- ODMSO AR 1 0.0037716558 2.7202067e-06
- ODMSO F 1 0.0016354166 7.5607529e-07
- ODMSO CL 1 0.0044611802 3.3902895e-06
- ODMSO BR 1 0.0016363697 7.0146311e-06
- ODMSO CMET 1 0.0044892949 3.9585162e-06
- ODMSO OMET 1 0.0022663291 9.752175e-07
- ODMSO NA+ 1 0.00040451783 1.256947e-07
- ODMSO CL- 1 0.00559911 8.9633324e-06
- ODMSO CCHL 1 0.0024441664 1.7475898e-06
- ODMSO CLCHL 1 0.0043430509 3.2161373e-06
- ODMSO HCHL 1 0.00029258328 5.6843478e-08
- ODMSO SDMSO 1 0.0052442 4.6094E-6
- ODMSO CDMSO 1 0.0049187 4.7597E-6
- ODMSO ODMSO 1 0.0022707131 7.5144626e-07
- CCL4 O 1 0.0024394475 2.3738805e-06
- CCL4 OM 1 0.0024394475 2.3738805e-06
- CCL4 OA 1 0.0024394475 3.1014e-06
- CCL4 OW 1 0.0026240987 4.2564992e-06
- CCL4 N 1 0.0025317731 3.5865968e-06
- CCL4 NT 1 0.0025317731 3.5865968e-06
- CCL4 NL 1 0.0025317731 3.5865968e-06
- CCL4 NR 1 0.0025317731 3.5865968e-06
- CCL4 NZ 1 0.0025317731 3.5865968e-06
- CCL4 NE 1 0.0025317731 3.5865968e-06
- CCL4 C 1 0.002481507 5.0642416e-06
- CCL4 CH1 1 0.0027677163 5.3288944e-06
- CCL4 CH2 1 0.0035252992 6.0031978e-06
- CCL4 CH3 1 0.0042459518 6.7700998e-06
- CCL4 CH4 1 0.0058883216 1.6160362e-05
- CCL4 CR1 1 0.0038135602 7.9561248e-06
- CCL4 HC 1 0.0004718864 3.390864e-07
- CCL4 H 1 0 0
- CCL4 DUM 1 0 0
- CCL4 S 1 0.0051250966 9.9685888e-06
- CCL4 CU1+ 1 0.0010489214 1.9735931e-07
- CCL4 CU2+ 1 0.0010489214 1.9735931e-07
- CCL4 FE 1 0 0
- CCL4 ZN2+ 1 0.0010489214 2.6785069e-07
- CCL4 MG2+ 1 0.00041443936 1.6094198e-07
- CCL4 CA2+ 1 0.0016259564 1.9454738e-06
- CCL4 P 1 0.0062268488 1.2987285e-05
- CCL4 AR 1 0.0040597618 8.6508384e-06
- CCL4 F 1 0.0017603414 2.404481e-06
- CCL4 CL 1 0.004801957 1.0781845e-05
- CCL4 BR 1 0.0017613673 2.2308026e-05
- CCL4 CMET 1 0.0048322193 1.2588927e-05
- CCL4 OMET 1 0.0024394475 3.1014e-06
- CCL4 NA+ 1 0.00043541779 3.99736e-07
- CCL4 CL- 1 0.00602681 2.8505312e-05
- CCL4 CCHL 1 0.0026308693 5.5577088e-06
- CCL4 CLCHL 1 0.0046748042 1.0228004e-05
- CCL4 HCHL 1 0.00031493288 1.807744e-07
- CCL4 SDMSO 1 0.0052712788 1.2782179e-05
- CCL4 CDMSO 1 0.0048798696 1.2859094e-05
- CCL4 ODMSO 1 0.0024441664 2.3897596e-06
- CCL4 CCL4 1 0.0026308693 7.5999462e-06
- CLCL4 O 1 0.0041472796 3.0768825e-06
- CLCL4 OM 1 0.0041472796 3.0768825e-06
- CLCL4 OA 1 0.0041472796 4.01985e-06
- CLCL4 OW 1 0.0044612032 5.5170208e-06
- CLCL4 N 1 0.0043042414 4.6487332e-06
- CLCL4 NT 1 0.0043042414 4.6487332e-06
- CLCL4 NL 1 0.0043042414 4.6487332e-06
- CLCL4 NR 1 0.0043042414 4.6487332e-06
- CLCL4 NZ 1 0.0043042414 4.6487332e-06
- CLCL4 NE 1 0.0043042414 4.6487332e-06
- CLCL4 C 1 0.0042187844 6.5639684e-06
- CLCL4 CH1 1 0.004705366 6.9069956e-06
- CLCL4 CH2 1 0.0059933247 7.7809875e-06
- CLCL4 CH3 1 0.0072184988 8.7750002e-06
- CLCL4 CH4 1 0.010010675 2.0946098e-05
- CLCL4 CR1 1 0.0064833944 1.0312255e-05
- CLCL4 HC 1 0.0008022492 4.395036e-07
- CLCL4 H 1 0 0
- CLCL4 DUM 1 0 0
- CLCL4 S 1 0.0087131239 1.2920691e-05
- CLCL4 CU1+ 1 0.0017832604 2.5580539e-07
- CLCL4 CU2+ 1 0.0017832604 2.5580539e-07
- CLCL4 FE 1 0 0
- CLCL4 ZN2+ 1 0.0017832604 3.4717211e-07
- CLCL4 MG2+ 1 0.00070458408 2.0860342e-07
- CLCL4 CA2+ 1 0.0027642717 2.5216072e-06
- CLCL4 P 1 0.010586201 1.6833345e-05
- CLCL4 AR 1 0.0069019592 1.1212702e-05
- CLCL4 F 1 0.0029927383 3.116545e-06
- CLCL4 CL 1 0.0081637576 1.3974785e-05
- CLCL4 BR 1 0.0029944823 2.8914334e-05
- CLCL4 CMET 1 0.0082152062 1.6317018e-05
- CLCL4 OMET 1 0.0041472796 4.01985e-06
- CLCL4 NA+ 1 0.00074024929 5.18114e-07
- CLCL4 CL- 1 0.010246117 3.6946888e-05
- CLCL4 CCHL 1 0.0044727137 7.2035712e-06
- CLCL4 CLCHL 1 0.0079475863 1.3256929e-05
- CLCL4 HCHL 1 0.00053541414 2.3430902e-07
- CLCL4 SDMSO 1 0.0089616468 1.6567499e-05
- CLCL4 CDMSO 1 0.0082962159 1.6667191e-05
- CLCL4 ODMSO 1 0.0041553021 3.0974642e-06
- CLCL4 CCL4 1 0.0044727137 9.8505978e-06
- CLCL4 CLCL4 1 0.0076040144 1.2767758e-05
+ CChl O 1 0.0024394475 1.7359776e-06
+ CChl OM 1 0.0024394475 1.7359776e-06
+ CChl OA 1 0.0024394475 2.268e-06
+ CChl OW 1 0.0026240987 3.112704e-06
+ CChl N 1 0.0025317731 2.622816e-06
+ CChl NT 1 0.0025317731 2.622816e-06
+ CChl NL 1 0.0025317731 2.622816e-06
+ CChl NR 1 0.0025317731 2.622816e-06
+ CChl NZ 1 0.0025317731 2.622816e-06
+ CChl NE 1 0.0025317731 2.622816e-06
+ CChl C 1 0.002481507 3.703392e-06
+ CChl CH1 1 0.0027677163 3.896928e-06
+ CChl CH2 1 0.0035252992 4.3900343e-06
+ CChl CH3 1 0.0042459518 4.9508565e-06
+ CChl CH4 1 0.0058883216 1.1817792e-05
+ CChl CR1 1 0.0038135602 5.818176e-06
+ CChl HC 1 0.0004718864 2.47968e-07
+ CChl H 1 0 0
+ CChl DUM 1 0 0
+ CChl S 1 0.0051250966 7.289856e-06
+ CChl CU1+ 1 0.0010489214 1.4432544e-07
+ CChl CU2+ 1 0.0010489214 1.4432544e-07
+ CChl FE 1 0 0
+ CChl ZN2+ 1 0.0010489214 1.9587456e-07
+ CChl MG2+ 1 0.00041443936 1.1769408e-07
+ CChl CA2+ 1 0.0016259564 1.4226912e-06
+ CChl P 1 0.0062268488 9.497376e-06
+ CChl AR 1 0.0040597618 6.326208e-06
+ CChl F 1 0.0017603414 1.7583552e-06
+ CChl CL 1 0.004801957 7.884576e-06
+ CChl BR 1 0.0017613673 1.6313472e-05
+ CChl CMet 1 0.0048322193 9.206064e-06
+ CChl OMet 1 0.0024394475 2.268e-06
+ CChl NA+ 1 0.00043541779 2.9232e-07
+ CChl CL- 1 0.00602681 2.084544e-05
+ CChl CChl 1 0.0026308693 4.064256e-06
+ CLChl O 1 0.004334666 3.1947671e-06
+ CLChl OM 1 0.004334666 3.1947671e-06
+ CLChl OA 1 0.004334666 4.1738625e-06
+ CLChl OW 1 0.0046627736 5.7283944e-06
+ CLChl N 1 0.0044987198 4.8268401e-06
+ CLChl NT 1 0.0044987198 4.8268401e-06
+ CLChl NL 1 0.0044987198 4.8268401e-06
+ CLChl NR 1 0.0044987198 4.8268401e-06
+ CLChl NZ 1 0.0044987198 4.8268401e-06
+ CLChl NE 1 0.0044987198 4.8268401e-06
+ CLChl C 1 0.0044094016 6.8154537e-06
+ CLChl CH1 1 0.0049179684 7.1716233e-06
+ CLChl CH2 1 0.0062641209 8.0791004e-06
+ CLChl CH3 1 0.007544652 9.1111968e-06
+ CLChl CH4 1 0.010462987 2.1748606e-05
+ CLChl CR1 1 0.0067763334 1.0707349e-05
+ CLChl HC 1 0.0008384972 4.563423e-07
+ CLChl H 1 0 0
+ CLChl DUM 1 0 0
+ CLChl S 1 0.0091068087 1.3415722e-05
+ CLChl CU1+ 1 0.0018638335 2.6560606e-07
+ CLChl CU2+ 1 0.0018638335 2.6560606e-07
+ CLChl FE 1 0 0
+ CLChl ZN2+ 1 0.0018638335 3.6047332e-07
+ CLChl MG2+ 1 0.00073641928 2.1659564e-07
+ CLChl CA2+ 1 0.0028891697 2.6182176e-06
+ CLChl P 1 0.011064517 1.7478281e-05
+ CLChl AR 1 0.0072138101 1.1642294e-05
+ CLChl F 1 0.0031279591 3.2359492e-06
+ CLChl CL 1 0.0085326204 1.4510201e-05
+ CLChl BR 1 0.0031297819 3.0022129e-05
+ CLChl CMet 1 0.0085863936 1.6942172e-05
+ CLChl OMet 1 0.004334666 4.1738625e-06
+ CLChl NA+ 1 0.00077369595 5.379645e-07
+ CLChl CL- 1 0.010709067 3.8362434e-05
+ CLChl CChl 1 0.0046754 7.4813E-6
+ CLChl CLChl 1 0.0083066819 1.3764842e-05
+ HChl O 1 0.0002920184 5.6465771e-08
+ HChl OM 1 0.0002920184 5.6465771e-08
+ HChl OA 1 0.0002920184 7.377075e-08
+ HChl OW 1 0.0003141224 1.0124626e-07
+ HChl N 1 0.0003030704 8.5311774e-08
+ HChl NT 1 0.0003030704 8.5311774e-08
+ HChl NL 1 0.0003030704 8.5311774e-08
+ HChl NR 1 0.0003030704 8.5311774e-08
+ HChl NZ 1 0.0003030704 8.5311774e-08
+ HChl NE 1 0.0003030704 8.5311774e-08
+ HChl C 1 0.0002970532 1.2045944e-07
+ HChl CH1 1 0.0003313144 1.2675454e-07
+ HChl CH2 1 0.0004220022 1.4279371e-07
+ HChl CH3 1 0.0005082692 1.6103545e-07
+ HChl CH4 1 0.000704872 3.8439479e-07
+ HChl CR1 1 0.000456509 1.8924656e-07
+ HChl HC 1 5.6488e-05 8.065602e-09
+ HChl H 1 0 0
+ HChl DUM 1 0 0
+ HChl S 1 0.0006135088 2.3711558e-07
+ HChl CU1+ 1 0.000125563 4.6944427e-09
+ HChl CU2+ 1 0.000125563 4.6944427e-09
+ HChl FE 1 0 0
+ HChl ZN2+ 1 0.000125563 6.3711698e-09
+ HChl MG2+ 1 4.96112e-05 3.8282101e-09
+ HChl CA2+ 1 0.000194638 4.6275572e-08
+ HChl P 1 0.000745396 3.0891911e-07
+ HChl AR 1 0.000485981 2.0577121e-07
+ HChl F 1 0.0002107248 5.7193643e-08
+ HChl CL 1 0.0005748268 2.5645991e-07
+ HChl BR 1 0.0002108476 5.3062481e-07
+ HChl CMet 1 0.0005784494 2.9944367e-07
+ HChl OMet 1 0.0002920184 7.377075e-08
+ HChl NA+ 1 5.212246e-05 9.50823e-09
+ HChl CL- 1 0.00072145 6.7803516e-07
+ HChl CChl 1 0.0003622 0.1745E-6
+ HChl CLChl 1 0.0006493 0.3266E-6
+ HChl HChl 1 3.76996e-05 4.2999495e-09
+ SDmso O 1 0.0048877412 3.9925763e-06
+ SDmso OM 1 0.0048877412 3.9925763e-06
+ SDmso OA 1 0.0048877412 5.216175e-06
+ SDmso OW 1 0.0052577132 7.1589104e-06
+ SDmso N 1 0.0050727272 6.0322166e-06
+ SDmso NT 1 0.0050727272 6.0322166e-06
+ SDmso NL 1 0.0050727272 6.0322166e-06
+ SDmso NR 1 0.0050727272 6.0322166e-06
+ SDmso NZ 1 0.0050727272 6.0322166e-06
+ SDmso NE 1 0.0050727272 6.0322166e-06
+ SDmso C 1 0.0049720126 8.5174342e-06
+ SDmso CH1 1 0.0055454692 8.9625478e-06
+ SDmso CH2 1 0.0070633821 1.0096643e-05
+ SDmso CH3 1 0.0085073006 1.1386479e-05
+ SDmso CH4 1 0.011797996 2.7179749e-05
+ SDmso CR1 1 0.0076409495 1.3381228e-05
+ SDmso HC 1 0.000945484 5.703018e-07
+ SDmso H 1 0 0
+ SDmso DUM 1 0 0
+ SDmso S 1 0.010268778 1.6765946e-05
+ SDmso CU1+ 1 0.0021016465 3.3193419e-07
+ SDmso CU2+ 1 0.0021016465 3.3193419e-07
+ SDmso FE 1 0 0
+ SDmso ZN2+ 1 0.0021016465 4.5049206e-07
+ SDmso MG2+ 1 0.0008303816 2.7068471e-07
+ SDmso CA2+ 1 0.003257809 3.2720486e-06
+ SDmso P 1 0.012476278 2.1843023e-05
+ SDmso AR 1 0.0081342455 1.4549651e-05
+ SDmso F 1 0.0035270664 4.0440425e-06
+ SDmso CL 1 0.0096213274 1.8133743e-05
+ SDmso BR 1 0.0035291218 3.7519367e-05
+ SDmso CMet 1 0.0096819617 2.1173034e-05
+ SDmso OMet 1 0.0048877412 5.216175e-06
+ SDmso NA+ 1 0.00087241453 6.72307e-07
+ SDmso CL- 1 0.012075475 4.7942444e-05
+ SDmso CChl 1 0.0052712788 9.3473856e-06
+ SDmso CLChl 1 0.0093665606 1.720225e-05
+ SDmso HChl 1 0.0006310078 3.0404041e-07
+ SDmso SDmso 1 0.010561673 2.149806e-05
+ CDmso O 1 0.0045248108 4.016601e-06
+ CDmso OM 1 0.0045248108 4.016601e-06
+ CDmso OA 1 0.0045248108 5.2475625e-06
+ CDmso OW 1 0.0048673112 7.201988e-06
+ CDmso N 1 0.004696061 6.0685145e-06
+ CDmso NT 1 0.004696061 6.0685145e-06
+ CDmso NL 1 0.004696061 6.0685145e-06
+ CDmso NR 1 0.004696061 6.0685145e-06
+ CDmso NZ 1 0.004696061 6.0685145e-06
+ CDmso NE 1 0.004696061 6.0685145e-06
+ CDmso C 1 0.0046028248 8.5686865e-06
+ CDmso CH1 1 0.0051337004 9.0164785e-06
+ CDmso CH2 1 0.0065389035 1.0157398e-05
+ CDmso CH3 1 0.0078756064 1.1454995e-05
+ CDmso CH4 1 0.010921957 2.7343299e-05
+ CDmso CR1 1 0.0070735846 1.3461747e-05
+ CDmso HC 1 0.0008752788 5.737335e-07
+ CDmso H 1 0 0
+ CDmso DUM 1 0 0
+ CDmso S 1 0.0095062889 1.6866832e-05
+ CDmso CU1+ 1 0.0019455925 3.3393156e-07
+ CDmso CU2+ 1 0.0019455925 3.3393156e-07
+ CDmso FE 1 0 0
+ CDmso ZN2+ 1 0.0019455925 4.5320282e-07
+ CDmso MG2+ 1 0.00076872312 2.7231351e-07
+ CDmso CA2+ 1 0.0030159063 3.2917377e-06
+ CDmso P 1 0.011549875 2.197446e-05
+ CDmso AR 1 0.0075302519 1.4637201e-05
+ CDmso F 1 0.0032651705 4.0683769e-06
+ CDmso CL 1 0.0089069132 1.824286e-05
+ CDmso BR 1 0.0032670733 3.7745134e-05
+ CDmso CMet 1 0.0089630452 2.1300439e-05
+ CDmso OMet 1 0.0045248108 5.2475625e-06
+ CDmso NA+ 1 0.00080763497 6.763525e-07
+ CDmso CL- 1 0.011178832 4.823093e-05
+ CDmso CChl 1 0.0048798696 9.403632e-06
+ CDmso CLChl 1 0.0086710636 1.7305761e-05
+ CDmso HChl 1 0.00058415346 3.0586992e-07
+ CDmso SDmso 1 0.0097827 21.6523E-6
+ CDmso CDmso 1 0.0090514293 2.175756e-05
+ ODmso O 1 0.0022663291 7.4645315e-07
+ ODmso OM 1 0.0022663291 7.4645315e-07
+ ODmso OA 1 0.0022663291 9.752175e-07
+ ODmso OW 1 0.0024378763 1.3384318e-06
+ ODmso N 1 0.0023521027 1.1277849e-06
+ ODmso NT 1 0.0023521027 1.1277849e-06
+ ODmso NL 1 0.0023521027 1.1277849e-06
+ ODmso NR 1 0.0023521027 1.1277849e-06
+ ODmso NZ 1 0.0023521027 1.1277849e-06
+ ODmso NE 1 0.0023521027 1.1277849e-06
+ ODmso C 1 0.0023054038 1.5924218e-06
+ ODmso CH1 1 0.0025713019 1.6756404e-06
+ ODmso CH2 1 0.003275122 1.8876712e-06
+ ODmso CH3 1 0.0039446326 2.1288192e-06
+ ODmso CH4 1 0.0054704496 5.0815333e-06
+ ODmso CR1 1 0.0035429262 2.501758e-06
+ ODmso HC 1 0.0004383984 1.0662378e-07
+ ODmso H 1 0 0
+ ODmso DUM 1 0 0
+ ODmso S 1 0.0047613878 3.1345658e-06
+ ODmso CU1+ 1 0.0009744834 6.2058507e-08
+ ODmso CU2+ 1 0.0009744834 6.2058507e-08
+ ODmso FE 1 0 0
+ ODmso ZN2+ 1 0.0009744834 8.4224118e-08
+ ODmso MG2+ 1 0.00038502816 5.0607287e-08
+ ODmso CA2+ 1 0.0015105684 6.117431e-07
+ ODmso P 1 0.0057849528 4.0837775e-06
+ ODmso AR 1 0.0037716558 2.7202067e-06
+ ODmso F 1 0.0016354166 7.5607529e-07
+ ODmso CL 1 0.0044611802 3.3902895e-06
+ ODmso BR 1 0.0016363697 7.0146311e-06
+ ODmso CMet 1 0.0044892949 3.9585162e-06
+ ODmso OMet 1 0.0022663291 9.752175e-07
+ ODmso NA+ 1 0.00040451783 1.256947e-07
+ ODmso CL- 1 0.00559911 8.9633324e-06
+ ODmso CChl 1 0.0024441664 1.7475898e-06
+ ODmso CLChl 1 0.0043430509 3.2161373e-06
+ ODmso HChl 1 0.00029258328 5.6843478e-08
+ ODmso SDmso 1 0.0052442 4.6094E-6
+ ODmso CDmso 1 0.0049187 4.7597E-6
+ ODmso ODmso 1 0.0022707131 7.5144626e-07
+ CCl4 O 1 0.0024394475 2.3738805e-06
+ CCl4 OM 1 0.0024394475 2.3738805e-06
+ CCl4 OA 1 0.0024394475 3.1014e-06
+ CCl4 OW 1 0.0026240987 4.2564992e-06
+ CCl4 N 1 0.0025317731 3.5865968e-06
+ CCl4 NT 1 0.0025317731 3.5865968e-06
+ CCl4 NL 1 0.0025317731 3.5865968e-06
+ CCl4 NR 1 0.0025317731 3.5865968e-06
+ CCl4 NZ 1 0.0025317731 3.5865968e-06
+ CCl4 NE 1 0.0025317731 3.5865968e-06
+ CCl4 C 1 0.002481507 5.0642416e-06
+ CCl4 CH1 1 0.0027677163 5.3288944e-06
+ CCl4 CH2 1 0.0035252992 6.0031978e-06
+ CCl4 CH3 1 0.0042459518 6.7700998e-06
+ CCl4 CH4 1 0.0058883216 1.6160362e-05
+ CCl4 CR1 1 0.0038135602 7.9561248e-06
+ CCl4 HC 1 0.0004718864 3.390864e-07
+ CCl4 H 1 0 0
+ CCl4 DUM 1 0 0
+ CCl4 S 1 0.0051250966 9.9685888e-06
+ CCl4 CU1+ 1 0.0010489214 1.9735931e-07
+ CCl4 CU2+ 1 0.0010489214 1.9735931e-07
+ CCl4 FE 1 0 0
+ CCl4 ZN2+ 1 0.0010489214 2.6785069e-07
+ CCl4 MG2+ 1 0.00041443936 1.6094198e-07
+ CCl4 CA2+ 1 0.0016259564 1.9454738e-06
+ CCl4 P 1 0.0062268488 1.2987285e-05
+ CCl4 AR 1 0.0040597618 8.6508384e-06
+ CCl4 F 1 0.0017603414 2.404481e-06
+ CCl4 CL 1 0.004801957 1.0781845e-05
+ CCl4 BR 1 0.0017613673 2.2308026e-05
+ CCl4 CMet 1 0.0048322193 1.2588927e-05
+ CCl4 OMet 1 0.0024394475 3.1014e-06
+ CCl4 NA+ 1 0.00043541779 3.99736e-07
+ CCl4 CL- 1 0.00602681 2.8505312e-05
+ CCl4 CChl 1 0.0026308693 5.5577088e-06
+ CCl4 CLChl 1 0.0046748042 1.0228004e-05
+ CCl4 HChl 1 0.00031493288 1.807744e-07
+ CCl4 SDmso 1 0.0052712788 1.2782179e-05
+ CCl4 CDmso 1 0.0048798696 1.2859094e-05
+ CCl4 ODmso 1 0.0024441664 2.3897596e-06
+ CCl4 CCl4 1 0.0026308693 7.5999462e-06
+ CLCl4 O 1 0.0041472796 3.0768825e-06
+ CLCl4 OM 1 0.0041472796 3.0768825e-06
+ CLCl4 OA 1 0.0041472796 4.01985e-06
+ CLCl4 OW 1 0.0044612032 5.5170208e-06
+ CLCl4 N 1 0.0043042414 4.6487332e-06
+ CLCl4 NT 1 0.0043042414 4.6487332e-06
+ CLCl4 NL 1 0.0043042414 4.6487332e-06
+ CLCl4 NR 1 0.0043042414 4.6487332e-06
+ CLCl4 NZ 1 0.0043042414 4.6487332e-06
+ CLCl4 NE 1 0.0043042414 4.6487332e-06
+ CLCl4 C 1 0.0042187844 6.5639684e-06
+ CLCl4 CH1 1 0.004705366 6.9069956e-06
+ CLCl4 CH2 1 0.0059933247 7.7809875e-06
+ CLCl4 CH3 1 0.0072184988 8.7750002e-06
+ CLCl4 CH4 1 0.010010675 2.0946098e-05
+ CLCl4 CR1 1 0.0064833944 1.0312255e-05
+ CLCl4 HC 1 0.0008022492 4.395036e-07
+ CLCl4 H 1 0 0
+ CLCl4 DUM 1 0 0
+ CLCl4 S 1 0.0087131239 1.2920691e-05
+ CLCl4 CU1+ 1 0.0017832604 2.5580539e-07
+ CLCl4 CU2+ 1 0.0017832604 2.5580539e-07
+ CLCl4 FE 1 0 0
+ CLCl4 ZN2+ 1 0.0017832604 3.4717211e-07
+ CLCl4 MG2+ 1 0.00070458408 2.0860342e-07
+ CLCl4 CA2+ 1 0.0027642717 2.5216072e-06
+ CLCl4 P 1 0.010586201 1.6833345e-05
+ CLCl4 AR 1 0.0069019592 1.1212702e-05
+ CLCl4 F 1 0.0029927383 3.116545e-06
+ CLCl4 CL 1 0.0081637576 1.3974785e-05
+ CLCl4 BR 1 0.0029944823 2.8914334e-05
+ CLCl4 CMet 1 0.0082152062 1.6317018e-05
+ CLCl4 OMet 1 0.0041472796 4.01985e-06
+ CLCl4 NA+ 1 0.00074024929 5.18114e-07
+ CLCl4 CL- 1 0.010246117 3.6946888e-05
+ CLCl4 CChl 1 0.0044727137 7.2035712e-06
+ CLCl4 CLChl 1 0.0079475863 1.3256929e-05
+ CLCl4 HChl 1 0.00053541414 2.3430902e-07
+ CLCl4 SDmso 1 0.0089616468 1.6567499e-05
+ CLCl4 CDmso 1 0.0082962159 1.6667191e-05
+ CLCl4 ODmso 1 0.0041553021 3.0974642e-06
+ CLCl4 CCl4 1 0.0044727137 9.8505978e-06
+ CLCl4 CLCl4 1 0.0076040144 1.2767758e-05
SI O 1 0 0
SI OM 1 0 0
SI OA 1 0 0
SI F 1 0 0
SI CL 1 0 0
SI BR 1 0 0
- SI CMET 1 0 0
- SI OMET 1 0 0
+ SI CMet 1 0 0
+ SI OMet 1 0 0
SI NA+ 1 0 0
SI CL- 1 0 0
- SI CCHL 1 0 0
- SI CLCHL 1 0 0
- SI HCHL 1 0 0
- SI SDMSO 1 0 0
- SI CDMSO 1 0 0
- SI ODMSO 1 0 0
- SI CCL4 1 0 0
- SI CLCL4 1 0 0
+ SI CChl 1 0 0
+ SI CLChl 1 0 0
+ SI HChl 1 0 0
+ SI SDmso 1 0 0
+ SI CDmso 1 0 0
+ SI ODmso 1 0 0
+ SI CCl4 1 0 0
+ SI CLCl4 1 0 0
SI SI 1 0 0
--- /dev/null
+spc SPC simple point charge, recommended
+spce SPC/E extended simple point charge
aminoacids.hdb ffbonded.itp spc.itp \
aminoacids.n.tdb ffnonbonded.itp spce.itp \
aminoacids.rtp forcefield.doc tip3p.itp \
-aminoacids.vsd forcefield.itp tip4p.itp
+aminoacids.vsd forcefield.itp tip4p.itp \
+aminoacids.r2b watermodels.dat
EXTRA_DIST = ${topol_DATA}
--- /dev/null
+; rtp residue to rtp building block table
+;GMX Force-field
+CYS CYSH
+HISD HISA
+HISE HISB
+LYS LYSH
+LYSN LYS
C O gb_4
C +N gb_9
[ angles ]
+ CA C O ga_30
CA C +N ga_18
O C +N ga_32
[ impropers ]
[ CHCL3 ]
[ atoms ]
- CChl CCHL 0.17900 0
- HChl HCHL 0.08200 0
-CLCh1 CLCHL -0.08700 0
-CLCh2 CLCHL -0.08700 0
-CLCh3 CLCHL -0.08700 0
+ CChl CChl 0.17900 0
+ HChl HChl 0.08200 0
+CLCh1 CLChl -0.08700 0
+CLCh2 CLChl -0.08700 0
+CLCh3 CLChl -0.08700 0
[ bonds ]
CChl CLCh1 gb_37
CChl CLCh2 gb_37
[ DMSO ]
[ atoms ]
-SDmso SDMSO 0.13900 0
-ODmso ODMSO -0.45900 0
-CDms1 CDMSO 0.16000 0
-CDms2 CDMSO 0.16000 0
+SDmso SDmso 0.13900 0
+ODmso ODmso -0.45900 0
+CDms1 CDmso 0.16000 0
+CDms2 CDmso 0.16000 0
[ bonds ]
SDmso ODmso gb_38
SDmso CDms1 gb_39
[ CH3OH ]
[ atoms ]
- Omet OMET -0.57400 0
+ Omet OMet -0.57400 0
HMet H 0.39800 0
- CMet CMET 0.17600 0
+ CMet CMet 0.17600 0
[ bonds ]
Omet HMet gb_1
Omet CMet gb_17
[ CCL4 ]
[ atoms ]
- CCl4 CCL4 0.00000 0
-CLCl1 CLCL4 0.00000 0
-CLCl2 CLCL4 0.00000 0
-CLCl3 CLCL4 0.00000 0
-CLCl4 CLCL4 0.00000 0
+ CCl4 CCl4 0.00000 0
+CLCl1 CLCl4 0.00000 0
+CLCl2 CLCl4 0.00000 0
+CLCl3 CLCl4 0.00000 0
+CLCl4 CLCl4 0.00000 0
[ bonds ]
CCl4 CLCl1 gb_40
CCl4 CLCl2 gb_40
F 18.99840 ; fluor (non-ionic)
CL 35.45300 ; chlorine (non-ionic)
BR 79.90400 ; bromine (non-ionic)
- CMET 15.035 ; CH3-group in methanol (solvent)
- OMET 15.9994 ; oxygen in methanol (solvent)
+ CMet 15.035 ; CH3-group in methanol (solvent)
+ OMet 15.9994 ; oxygen in methanol (solvent)
NA+ 22.9898 ; sodium (charge 1+)
CL- 35.45300 ; chlorine (charge 1-)
- CCHL 12.011 ; carbon in chloroform (solvent)
-CLCHL 35.453 ; chloride in chloroform (solvent)
- HCHL 1.008 ; hydrogen in chloroform (solvent)
-SDMSO 32.06000 ; DMSO Sulphur (solvent)
-CDMSO 15.03500 ; DMSO Carbon (solvent)
-ODMSO 15.99940 ; DMSO Oxygen (solvent)
- CCL4 12.011 ; carbon in carbontetrachloride (solvent)
-CLCL4 35.453 ; chloride in carbontetrachloride (solvent)
+ CChl 12.011 ; carbon in chloroform (solvent)
+CLChl 35.453 ; chloride in chloroform (solvent)
+ HChl 1.008 ; hydrogen in chloroform (solvent)
+SDmso 32.06000 ; DMSO Sulphur (solvent)
+CDmso 15.03500 ; DMSO Carbon (solvent)
+ODmso 15.99940 ; DMSO Oxygen (solvent)
+ CCl4 12.011 ; carbon in carbontetrachloride (solvent)
+CLCl4 35.453 ; chloride in carbontetrachloride (solvent)
SI 28.08 ; silicon
MNH3 0 ; Dummy mass in rigid tetraedrical NH3 group
MW 0 ; Dummy mass in rigid tyrosine rings
F 9 0.000 0.000 A 0.0011778624 7.6073284e-07
CL 17 0.000 0.000 A 0.0087647044 1.5295921e-05
BR 35 0.000 0.000 A 0.0011792356 6.5480464e-05
- CMET 5 0.000 0.000 A 0.0088755241 2.0852922e-05
- OMET 8 0.000 0.000 A 0.0022619536 1.505529e-06
+ CMet 5 0.000 0.000 A 0.0088755241 2.0852922e-05
+ OMet 8 0.000 0.000 A 0.0022619536 1.505529e-06
NA+ 11 0.000 0.000 A 7.2063121e-05 2.1025e-08
CL- 17 0.000 0.000 A 0.01380625 0.0001069156
- CCHL 6 0.000 0.000 A 0.0026308693 4.064256e-06
-CLCHL 17 0.000 0.000 A 0.0083066819 1.3764842e-05
- HCHL 1 0.000 0.000 A 3.76996e-05 4.2999495e-09
-SDMSO 16 0.000 0.000 A 0.010561673 2.149806e-05
-CDMSO 6 0.000 0.000 A 0.0090514293 2.175756e-05
-ODMSO 8 0.000 0.000 A 0.0022707131 7.5144626e-07
- CCL4 6 0.000 0.000 A 0.0026308693 7.5999462e-06
-CLCL4 17 0.000 0.000 A 0.0076040144 1.2767758e-05
+ CChl 6 0.000 0.000 A 0.0026308693 4.064256e-06
+CLChl 17 0.000 0.000 A 0.0083066819 1.3764842e-05
+ HChl 1 0.000 0.000 A 3.76996e-05 4.2999495e-09
+SDmso 16 0.000 0.000 A 0.010561673 2.149806e-05
+CDmso 6 0.000 0.000 A 0.0090514293 2.175756e-05
+ODmso 8 0.000 0.000 A 0.0022707131 7.5144626e-07
+ CCl4 6 0.000 0.000 A 0.0026308693 7.5999462e-06
+CLCl4 17 0.000 0.000 A 0.0076040144 1.2767758e-05
CH2r 6 0.000 0.000 A 0.0073342096 2.8058209e-05
CH0 6 0.000 0.000 A 0.0023970816 0.0002053489
SI 14 0.000 0.000 A 0.01473796 2.2193521e-05
BR AR 1 0.002718011 2.5392696e-05
BR F 1 0.0011785488 7.0578424e-06
BR CL 1 0.0032149108 3.1647812e-05
- CMET O 1 0.0044806276 3.9322131e-06
- CMET OM 1 0.0044806276 3.9322131e-06
- CMET OA 1 0.0044806276 5.1373125e-06
- CMET OW 1 0.0048197836 7.4114295e-06
- CMET N 1 0.0046502056 5.9410165e-06
- CMET NT 1 0.0046502056 5.9410165e-06
- CMET NL 1 0.0046502056 5.9410165e-06
- CMET NR 1 0.0046502056 5.9410165e-06
- CMET NZ 1 0.0046502056 5.9410165e-06
- CMET NE 1 0.0046502056 5.9410165e-06
- CMET C 1 0.0045578798 8.3886605e-06
- CMET CH1 1 0.007338959 4.4980025e-05
- CMET CH2 1 0.0081416282 2.6613562e-05
- CMET CH3 1 0.0092372905 2.3572273e-05
- CMET CH4 1 0.010815308 2.6768823e-05
- CMET CR1 1 0.0069950925 1.7754552e-05
- CMET HC 1 0.000866732 5.616795e-07
- CMET H 1 0 0
- CMET DUM 1 0 0
- CMET S 1 0.0094134632 1.6512464e-05
- CMET CU1+ 1 0.0019265945 3.2691574e-07
- CMET CU2+ 1 0.0019265945 3.2691574e-07
- CMET FE 1 0 0
- CMET ZN2+ 1 0.0019265945 4.4368114e-07
- CMET MG2+ 1 0.0007612168 2.6659227e-07
- CMET CA2+ 1 0.002986457 3.222579e-06
- CMET P 1 0.011437094 2.1512782e-05
- CMET AR 1 0.0074567215 1.4329677e-05
- CMET F 1 0.0032332872 3.9829013e-06
- CMET CL 1 0.0088199402 1.7859582e-05
- CMET BR 1 0.0032351714 3.6952118e-05
- OMET O 1 0.0022619536 1.380375e-06
- OMET OM 1 0.0022619536 2.258907e-06
- OMET OA 1 0.0022619536 1.505529e-06
- OMET OW 1 0.0024331696 1.991421e-06
- OMET N 1 0.0023475616 2.384061e-06
- OMET NT 1 0.0023475616 2.76075e-06
- OMET NL 1 0.0023475616 3.764436e-06
- OMET NR 1 0.0023475616 2.258907e-06
- OMET NZ 1 0.0023475616 2.635596e-06
- OMET NE 1 0.0023475616 2.434368e-06
- OMET C 1 0.0023009528 2.066625e-06
- OMET CH1 1 0.003704924 1.108125e-05
- OMET CH2 1 0.0041101352 6.5565e-06
- OMET CH3 1 0.004663258 5.80725e-06
- OMET CH4 1 0.005459888 6.59475e-06
- OMET CR1 1 0.00353133 4.374e-06
- OMET HC 1 0.000437552 1.38375e-07
- OMET H 1 0 0
- OMET DUM 1 0 0
- OMET S 1 0.0047521952 4.068e-06
- OMET CU1+ 1 0.000972602 2.76075e-07
- OMET CU2+ 1 0.000972602 5.019657e-07
- OMET FE 1 0 0
- OMET ZN2+ 1 0.000972602 1.1921532e-07
- OMET MG2+ 1 0.0003842848 7.163226e-08
- OMET CA2+ 1 0.001507652 8.658939e-07
- OMET P 1 0.005773784 5.780397e-06
- OMET AR 1 0.003764374 3.53025e-06
- OMET F 1 0.0016322592 1.505529e-06
- OMET CL 1 0.0044525672 4.798797e-06
- OMET BR 1 0.0016332104 9.928884e-06
- OMET CMET 1 0.0044806276 5.1373125e-06
+ CMet O 1 0.0044806276 3.9322131e-06
+ CMet OM 1 0.0044806276 3.9322131e-06
+ CMet OA 1 0.0044806276 5.1373125e-06
+ CMet OW 1 0.0048197836 7.4114295e-06
+ CMet N 1 0.0046502056 5.9410165e-06
+ CMet NT 1 0.0046502056 5.9410165e-06
+ CMet NL 1 0.0046502056 5.9410165e-06
+ CMet NR 1 0.0046502056 5.9410165e-06
+ CMet NZ 1 0.0046502056 5.9410165e-06
+ CMet NE 1 0.0046502056 5.9410165e-06
+ CMet C 1 0.0045578798 8.3886605e-06
+ CMet CH1 1 0.007338959 4.4980025e-05
+ CMet CH2 1 0.0081416282 2.6613562e-05
+ CMet CH3 1 0.0092372905 2.3572273e-05
+ CMet CH4 1 0.010815308 2.6768823e-05
+ CMet CR1 1 0.0069950925 1.7754552e-05
+ CMet HC 1 0.000866732 5.616795e-07
+ CMet H 1 0 0
+ CMet DUM 1 0 0
+ CMet S 1 0.0094134632 1.6512464e-05
+ CMet CU1+ 1 0.0019265945 3.2691574e-07
+ CMet CU2+ 1 0.0019265945 3.2691574e-07
+ CMet FE 1 0 0
+ CMet ZN2+ 1 0.0019265945 4.4368114e-07
+ CMet MG2+ 1 0.0007612168 2.6659227e-07
+ CMet CA2+ 1 0.002986457 3.222579e-06
+ CMet P 1 0.011437094 2.1512782e-05
+ CMet AR 1 0.0074567215 1.4329677e-05
+ CMet F 1 0.0032332872 3.9829013e-06
+ CMet CL 1 0.0088199402 1.7859582e-05
+ CMet BR 1 0.0032351714 3.6952118e-05
+ OMet O 1 0.0022619536 1.380375e-06
+ OMet OM 1 0.0022619536 2.258907e-06
+ OMet OA 1 0.0022619536 1.505529e-06
+ OMet OW 1 0.0024331696 1.991421e-06
+ OMet N 1 0.0023475616 2.384061e-06
+ OMet NT 1 0.0023475616 2.76075e-06
+ OMet NL 1 0.0023475616 3.764436e-06
+ OMet NR 1 0.0023475616 2.258907e-06
+ OMet NZ 1 0.0023475616 2.635596e-06
+ OMet NE 1 0.0023475616 2.434368e-06
+ OMet C 1 0.0023009528 2.066625e-06
+ OMet CH1 1 0.003704924 1.108125e-05
+ OMet CH2 1 0.0041101352 6.5565e-06
+ OMet CH3 1 0.004663258 5.80725e-06
+ OMet CH4 1 0.005459888 6.59475e-06
+ OMet CR1 1 0.00353133 4.374e-06
+ OMet HC 1 0.000437552 1.38375e-07
+ OMet H 1 0 0
+ OMet DUM 1 0 0
+ OMet S 1 0.0047521952 4.068e-06
+ OMet CU1+ 1 0.000972602 2.76075e-07
+ OMet CU2+ 1 0.000972602 5.019657e-07
+ OMet FE 1 0 0
+ OMet ZN2+ 1 0.000972602 1.1921532e-07
+ OMet MG2+ 1 0.0003842848 7.163226e-08
+ OMet CA2+ 1 0.001507652 8.658939e-07
+ OMet P 1 0.005773784 5.780397e-06
+ OMet AR 1 0.003764374 3.53025e-06
+ OMet F 1 0.0016322592 1.505529e-06
+ OMet CL 1 0.0044525672 4.798797e-06
+ OMet BR 1 0.0016332104 9.928884e-06
+ OMet CMet 1 0.0044806276 5.1373125e-06
NA+ O 1 0.00040373684 1.63125e-07
NA+ OM 1 0.00040373684 4.4486e-07
NA+ OA 1 0.00040373684 1.77915e-07
NA+ F 1 0.00029134248 1.77915e-07
NA+ CL 1 0.00079474018 5.67095e-07
NA+ BR 1 0.00029151226 1.17334e-06
- NA+ CMET 1 0.00079974869 6.621425e-07
- NA+ OMET 1 0.00040373684 1.77915e-07
+ NA+ CMet 1 0.00079974869 6.621425e-07
+ NA+ OMet 1 0.00040373684 1.77915e-07
CL- O 1 0.0055883 8.903774e-06
CL- OM 1 0.0055883 8.903774e-06
CL- OA 1 0.0055883 1.268718e-05
CL- F 1 0.0040326 9.018548e-06
CL- CL 1 0.01100035 4.043974e-05
CL- BR 1 0.00403495 8.367128e-05
- CL- CMET 1 0.011069675 4.721761e-05
- CL- OMET 1 0.0055883 1.268718e-05
+ CL- CMet 1 0.011069675 4.721761e-05
+ CL- OMet 1 0.0055883 1.268718e-05
CL- NA+ 1 0.0009974575 1.4993e-06
- CCHL O 1 0.0024394475 1.7359776e-06
- CCHL OM 1 0.0024394475 1.7359776e-06
- CCHL OA 1 0.0024394475 2.268e-06
- CCHL OW 1 0.0026240987 3.271968e-06
- CCHL N 1 0.0025317731 2.622816e-06
- CCHL NT 1 0.0025317731 2.622816e-06
- CCHL NL 1 0.0025317731 2.622816e-06
- CCHL NR 1 0.0025317731 2.622816e-06
- CCHL NZ 1 0.0025317731 2.622816e-06
- CCHL NE 1 0.0025317731 2.622816e-06
- CCHL C 1 0.002481507 3.703392e-06
- CCHL CH1 1 0.0039956468 1.98576e-05
- CCHL CH2 1 0.0044326546 1.1749248e-05
- CCHL CH3 1 0.0050291806 1.0406592e-05
- CCHL CH4 1 0.0058883216 1.1817792e-05
- CCHL CR1 1 0.003808431 7.838208e-06
- CCHL HC 1 0.0004718864 2.47968e-07
- CCHL H 1 0 0
- CCHL DUM 1 0 0
- CCHL S 1 0.0051250966 7.289856e-06
- CCHL CU1+ 1 0.0010489214 1.4432544e-07
- CCHL CU2+ 1 0.0010489214 1.4432544e-07
- CCHL FE 1 0 0
- CCHL ZN2+ 1 0.0010489214 1.9587456e-07
- CCHL MG2+ 1 0.00041443936 1.1769408e-07
- CCHL CA2+ 1 0.0016259564 1.4226912e-06
- CCHL P 1 0.0062268488 9.497376e-06
- CCHL AR 1 0.0040597618 6.326208e-06
- CCHL F 1 0.0017603414 1.7583552e-06
- CCHL CL 1 0.004801957 7.884576e-06
- CCHL BR 1 0.0017613673 1.6313472e-05
- CCHL CMET 1 0.0048322193 9.206064e-06
- CCHL OMET 1 0.0024394475 2.268e-06
- CCHL NA+ 1 0.00043541779 2.9232e-07
- CCHL CL- 1 0.00602681 2.084544e-05
- CLCHL O 1 0.004334666 3.1947671e-06
- CLCHL OM 1 0.004334666 3.1947671e-06
- CLCHL OA 1 0.004334666 4.1738625e-06
- CLCHL OW 1 0.0046627736 6.0214923e-06
- CLCHL N 1 0.0044987198 4.8268401e-06
- CLCHL NT 1 0.0044987198 4.8268401e-06
- CLCHL NL 1 0.0044987198 4.8268401e-06
- CLCHL NR 1 0.0044987198 4.8268401e-06
- CLCHL NZ 1 0.0044987198 4.8268401e-06
- CLCHL NE 1 0.0044987198 4.8268401e-06
- CLCHL C 1 0.0044094016 6.8154537e-06
- CLCHL CH1 1 0.0070998839 3.6544485e-05
- CLCHL CH2 1 0.0078764052 2.1622463e-05
- CLCHL CH3 1 0.0089363751 1.9151536e-05
- CLCHL CH4 1 0.010462987 2.1748606e-05
- CLCHL CR1 1 0.0067672192 1.4424869e-05
- CLCHL HC 1 0.0008384972 4.563423e-07
- CLCHL H 1 0 0
- CLCHL DUM 1 0 0
- CLCHL S 1 0.0091068087 1.3415722e-05
- CLCHL CU1+ 1 0.0018638335 2.6560606e-07
- CLCHL CU2+ 1 0.0018638335 2.6560606e-07
- CLCHL FE 1 0 0
- CLCHL ZN2+ 1 0.0018638335 3.6047332e-07
- CLCHL MG2+ 1 0.00073641928 2.1659564e-07
- CLCHL CA2+ 1 0.0028891697 2.6182176e-06
- CLCHL P 1 0.011064517 1.7478281e-05
- CLCHL AR 1 0.0072138101 1.1642294e-05
- CLCHL F 1 0.0031279591 3.2359492e-06
- CLCHL CL 1 0.0085326204 1.4510201e-05
- CLCHL BR 1 0.0031297819 3.0022129e-05
- CLCHL CMET 1 0.0085863936 1.6942172e-05
- CLCHL OMET 1 0.004334666 4.1738625e-06
- CLCHL NA+ 1 0.00077369595 5.379645e-07
- CLCHL CL- 1 0.010709067 3.8362434e-05
- CLCHL CCHL 1 0.0046748042 7.4795616e-06
- HCHL O 1 0.0002920184 5.6465771e-08
- HCHL OM 1 0.0002920184 5.6465771e-08
- HCHL OA 1 0.0002920184 7.377075e-08
- HCHL OW 1 0.0003141224 1.064266e-07
- HCHL N 1 0.0003030704 8.5311774e-08
- HCHL NT 1 0.0003030704 8.5311774e-08
- HCHL NL 1 0.0003030704 8.5311774e-08
- HCHL NR 1 0.0003030704 8.5311774e-08
- HCHL NZ 1 0.0003030704 8.5311774e-08
- HCHL NE 1 0.0003030704 8.5311774e-08
- HCHL C 1 0.0002970532 1.2045944e-07
- HCHL CH1 1 0.000478306 6.459039e-07
- HCHL CH2 1 0.0005306188 3.8216527e-07
- HCHL CH3 1 0.000602027 3.3849299e-07
- HCHL CH4 1 0.000704872 3.8439479e-07
- HCHL CR1 1 0.000455895 2.5495171e-07
- HCHL HC 1 5.6488e-05 8.065602e-09
- HCHL H 1 0 0
- HCHL DUM 1 0 0
- HCHL S 1 0.0006135088 2.3711558e-07
- HCHL CU1+ 1 0.000125563 4.6944427e-09
- HCHL CU2+ 1 0.000125563 4.6944427e-09
- HCHL FE 1 0 0
- HCHL ZN2+ 1 0.000125563 6.3711698e-09
- HCHL MG2+ 1 4.96112e-05 3.8282101e-09
- HCHL CA2+ 1 0.000194638 4.6275572e-08
- HCHL P 1 0.000745396 3.0891911e-07
- HCHL AR 1 0.000485981 2.0577121e-07
- HCHL F 1 0.0002107248 5.7193643e-08
- HCHL CL 1 0.0005748268 2.5645991e-07
- HCHL BR 1 0.0002108476 5.3062481e-07
- HCHL CMET 1 0.0005784494 2.9944367e-07
- HCHL OMET 1 0.0002920184 7.377075e-08
- HCHL NA+ 1 5.212246e-05 9.50823e-09
- HCHL CL- 1 0.00072145 6.7803516e-07
- HCHL CCHL 1 0.00031493288 1.3219718e-07
- HCHL CLCHL 1 0.00055960574 2.432861e-07
- SDMSO O 1 0.0048877412 3.9925763e-06
- SDMSO OM 1 0.0048877412 3.9925763e-06
- SDMSO OA 1 0.0048877412 5.216175e-06
- SDMSO OW 1 0.0052577132 7.5252018e-06
- SDMSO N 1 0.0050727272 6.0322166e-06
- SDMSO NT 1 0.0050727272 6.0322166e-06
- SDMSO NL 1 0.0050727272 6.0322166e-06
- SDMSO NR 1 0.0050727272 6.0322166e-06
- SDMSO NZ 1 0.0050727272 6.0322166e-06
- SDMSO NE 1 0.0050727272 6.0322166e-06
- SDMSO C 1 0.0049720126 8.5174342e-06
- SDMSO CH1 1 0.008005783 4.567051e-05
- SDMSO CH2 1 0.0088813834 2.7022105e-05
- SDMSO CH3 1 0.010076599 2.3934129e-05
- SDMSO CH4 1 0.011797996 2.7179749e-05
- SDMSO CR1 1 0.0076306725 1.8027101e-05
- SDMSO HC 1 0.000945484 5.703018e-07
- SDMSO H 1 0 0
- SDMSO DUM 1 0 0
- SDMSO S 1 0.010268778 1.6765946e-05
- SDMSO CU1+ 1 0.0021016465 3.3193419e-07
- SDMSO CU2+ 1 0.0021016465 3.3193419e-07
- SDMSO FE 1 0 0
- SDMSO ZN2+ 1 0.0021016465 4.5049206e-07
- SDMSO MG2+ 1 0.0008303816 2.7068471e-07
- SDMSO CA2+ 1 0.003257809 3.2720486e-06
- SDMSO P 1 0.012476278 2.1843023e-05
- SDMSO AR 1 0.0081342455 1.4549651e-05
- SDMSO F 1 0.0035270664 4.0440425e-06
- SDMSO CL 1 0.0096213274 1.8133743e-05
- SDMSO BR 1 0.0035291218 3.7519367e-05
- SDMSO CMET 1 0.0096819617 2.1173034e-05
- SDMSO OMET 1 0.0048877412 5.216175e-06
- SDMSO NA+ 1 0.00087241453 6.72307e-07
- SDMSO CL- 1 0.012075475 4.7942444e-05
- SDMSO CCHL 1 0.0052712788 9.3473856e-06
- SDMSO CLCHL 1 0.0093665606 1.720225e-05
- SDMSO HCHL 1 0.0006310078 3.0404041e-07
- CDMSO O 1 0.0045248108 4.016601e-06
- CDMSO OM 1 0.0045248108 4.016601e-06
- CDMSO OA 1 0.0045248108 5.2475625e-06
- CDMSO OW 1 0.0048673112 7.5704835e-06
- CDMSO N 1 0.004696061 6.0685145e-06
- CDMSO NT 1 0.004696061 6.0685145e-06
- CDMSO NL 1 0.004696061 6.0685145e-06
- CDMSO NR 1 0.004696061 6.0685145e-06
- CDMSO NZ 1 0.004696061 6.0685145e-06
- CDMSO NE 1 0.004696061 6.0685145e-06
- CDMSO C 1 0.0046028248 8.5686865e-06
- CDMSO CH1 1 0.0074113281 4.5945325e-05
- CDMSO CH2 1 0.0082219124 2.7184706e-05
- CDMSO CH3 1 0.009328379 2.4078149e-05
- CDMSO CH4 1 0.010921957 2.7343299e-05
- CDMSO CR1 1 0.0070640708 1.8135576e-05
- CDMSO HC 1 0.0008752788 5.737335e-07
- CDMSO H 1 0 0
- CDMSO DUM 1 0 0
- CDMSO S 1 0.0095062889 1.6866832e-05
- CDMSO CU1+ 1 0.0019455925 3.3393156e-07
- CDMSO CU2+ 1 0.0019455925 3.3393156e-07
- CDMSO FE 1 0 0
- CDMSO ZN2+ 1 0.0019455925 4.5320282e-07
- CDMSO MG2+ 1 0.00076872312 2.7231351e-07
- CDMSO CA2+ 1 0.0030159063 3.2917377e-06
- CDMSO P 1 0.011549875 2.197446e-05
- CDMSO AR 1 0.0075302519 1.4637201e-05
- CDMSO F 1 0.0032651705 4.0683769e-06
- CDMSO CL 1 0.0089069132 1.824286e-05
- CDMSO BR 1 0.0032670733 3.7745134e-05
- CDMSO CMET 1 0.0089630452 2.1300439e-05
- CDMSO OMET 1 0.0045248108 5.2475625e-06
- CDMSO NA+ 1 0.00080763497 6.763525e-07
- CDMSO CL- 1 0.011178832 4.823093e-05
- CDMSO CCHL 1 0.0048798696 9.403632e-06
- CDMSO CLCHL 1 0.0086710636 1.7305761e-05
- CDMSO HCHL 1 0.00058415346 3.0586992e-07
- CDMSO SDMSO 1 0.009777435 2.1627421e-05
- ODMSO O 1 0.0022663291 7.4645315e-07
- ODMSO OM 1 0.0022663291 7.4645315e-07
- ODMSO OA 1 0.0022663291 1.380375e-06
- ODMSO OW 1 0.0024378763 1.825875e-06
- ODMSO N 1 0.0023521027 2.185875e-06
- ODMSO NT 1 0.0023521027 2.53125e-06
- ODMSO NL 1 0.0023521027 3.4515e-06
- ODMSO NR 1 0.0023521027 2.071125e-06
- ODMSO NZ 1 0.0023521027 2.4165e-06
- ODMSO NE 1 0.0023521027 2.232e-06
- ODMSO C 1 0.0023054038 1.5924218e-06
- ODMSO CH1 1 0.0037120908 8.538571e-06
- ODMSO CH2 1 0.0041180858 5.0520601e-06
- ODMSO CH3 1 0.0046722786 4.4747313e-06
- ODMSO CH4 1 0.0054704496 5.0815333e-06
- ODMSO CR1 1 0.003538161 3.3703517e-06
- ODMSO HC 1 0.0004383984 1.0662378e-07
- ODMSO H 1 0 0
- ODMSO DUM 1 0 0
- ODMSO S 1 0.0047613878 3.1345658e-06
- ODMSO CU1+ 1 0.0009744834 2.53125e-07
- ODMSO CU2+ 1 0.0009744834 4.602375e-07
- ODMSO FE 1 0 0
- ODMSO ZN2+ 1 0.0009744834 1.09305e-07
- ODMSO MG2+ 1 0.00038502816 6.56775e-08
- ODMSO CA2+ 1 0.0015105684 7.939125e-07
- ODMSO P 1 0.0057849528 5.299875e-06
- ODMSO AR 1 0.0037716558 2.7202067e-06
- ODMSO F 1 0.0016354166 7.5607529e-07
- ODMSO CL 1 0.0044611802 3.3902895e-06
- ODMSO BR 1 0.0016363697 7.0146311e-06
- ODMSO CMET 1 0.0044892949 3.9585162e-06
- ODMSO OMET 1 0.0022663291 1.380375e-06
- ODMSO NA+ 1 0.00040451783 1.63125e-07
- ODMSO CL- 1 0.00559911 8.9633324e-06
- ODMSO CCHL 1 0.0024441664 1.7475898e-06
- ODMSO CLCHL 1 0.0043430509 3.2161373e-06
- ODMSO HCHL 1 0.00029258328 5.6843478e-08
- ODMSO SDMSO 1 0.004897196 4.0192831e-06
- ODMSO CDMSO 1 0.0045335636 4.0434685e-06
- CCL4 O 1 0.0024394475 2.3738805e-06
- CCL4 OM 1 0.0024394475 2.3738805e-06
- CCL4 OA 1 0.0024394475 3.1014e-06
- CCL4 OW 1 0.0026240987 4.4742864e-06
- CCL4 N 1 0.0025317731 3.5865968e-06
- CCL4 NT 1 0.0025317731 3.5865968e-06
- CCL4 NL 1 0.0025317731 3.5865968e-06
- CCL4 NR 1 0.0025317731 3.5865968e-06
- CCL4 NZ 1 0.0025317731 3.5865968e-06
- CCL4 NE 1 0.0025317731 3.5865968e-06
- CCL4 C 1 0.002481507 5.0642416e-06
- CCL4 CH1 1 0.0039956468 2.715448e-05
- CCL4 CH2 1 0.0044326546 1.606663e-05
- CCL4 CH3 1 0.0050291806 1.4230602e-05
- CCL4 CH4 1 0.0058883216 1.6160362e-05
- CCL4 CR1 1 0.003808431 1.0718438e-05
- CCL4 HC 1 0.0004718864 3.390864e-07
- CCL4 H 1 0 0
- CCL4 DUM 1 0 0
- CCL4 S 1 0.0051250966 9.9685888e-06
- CCL4 CU1+ 1 0.0010489214 1.9735931e-07
- CCL4 CU2+ 1 0.0010489214 1.9735931e-07
- CCL4 FE 1 0 0
- CCL4 ZN2+ 1 0.0010489214 2.6785069e-07
- CCL4 MG2+ 1 0.00041443936 1.6094198e-07
- CCL4 CA2+ 1 0.0016259564 1.9454738e-06
- CCL4 P 1 0.0062268488 1.2987285e-05
- CCL4 AR 1 0.0040597618 8.6508384e-06
- CCL4 F 1 0.0017603414 2.404481e-06
- CCL4 CL 1 0.004801957 1.0781845e-05
- CCL4 BR 1 0.0017613673 2.2308026e-05
- CCL4 CMET 1 0.0048322193 1.2588927e-05
- CCL4 OMET 1 0.0024394475 3.1014e-06
- CCL4 NA+ 1 0.00043541779 3.99736e-07
- CCL4 CL- 1 0.00602681 2.8505312e-05
- CCL4 CCHL 1 0.0026308693 5.5577088e-06
- CCL4 CLCHL 1 0.0046748042 1.0228004e-05
- CCL4 HCHL 1 0.00031493288 1.807744e-07
- CCL4 SDMSO 1 0.0052712788 1.2782179e-05
- CCL4 CDMSO 1 0.0048798696 1.2859094e-05
- CCL4 ODMSO 1 0.0024441664 2.3897596e-06
- CLCL4 O 1 0.0041472796 3.0768825e-06
- CLCL4 OM 1 0.0041472796 3.0768825e-06
- CLCL4 OA 1 0.0041472796 4.01985e-06
- CLCL4 OW 1 0.0044612032 5.7993036e-06
- CLCL4 N 1 0.0043042414 4.6487332e-06
- CLCL4 NT 1 0.0043042414 4.6487332e-06
- CLCL4 NL 1 0.0043042414 4.6487332e-06
- CLCL4 NR 1 0.0043042414 4.6487332e-06
- CLCL4 NZ 1 0.0043042414 4.6487332e-06
- CLCL4 NE 1 0.0043042414 4.6487332e-06
- CLCL4 C 1 0.0042187844 6.5639684e-06
- CLCL4 CH1 1 0.0067929579 3.519602e-05
- CLCL4 CH2 1 0.0075359104 2.082461e-05
- CLCL4 CH3 1 0.008550058 1.8444858e-05
- CLCL4 CH4 1 0.010010675 2.0946098e-05
- CLCL4 CR1 1 0.0064746742 1.3892602e-05
- CLCL4 HC 1 0.0008022492 4.395036e-07
- CLCL4 H 1 0 0
- CLCL4 DUM 1 0 0
- CLCL4 S 1 0.0087131239 1.2920691e-05
- CLCL4 CU1+ 1 0.0017832604 2.5580539e-07
- CLCL4 CU2+ 1 0.0017832604 2.5580539e-07
- CLCL4 FE 1 0 0
- CLCL4 ZN2+ 1 0.0017832604 3.4717211e-07
- CLCL4 MG2+ 1 0.00070458408 2.0860342e-07
- CLCL4 CA2+ 1 0.0027642717 2.5216072e-06
- CLCL4 P 1 0.010586201 1.6833345e-05
- CLCL4 AR 1 0.0069019592 1.1212702e-05
- CLCL4 F 1 0.0029927383 3.116545e-06
- CLCL4 CL 1 0.0081637576 1.3974785e-05
- CLCL4 BR 1 0.0029944823 2.8914334e-05
- CLCL4 CMET 1 0.0082152062 1.6317018e-05
- CLCL4 OMET 1 0.0041472796 4.01985e-06
- CLCL4 NA+ 1 0.00074024929 5.18114e-07
- CLCL4 CL- 1 0.010246117 3.6946888e-05
- CLCL4 CCHL 1 0.0044727137 7.2035712e-06
- CLCL4 CLCHL 1 0.0079475863 1.3256929e-05
- CLCL4 HCHL 1 0.00053541414 2.3430902e-07
- CLCL4 SDMSO 1 0.0089616468 1.6567499e-05
- CLCL4 CDMSO 1 0.0082962159 1.6667191e-05
- CLCL4 ODMSO 1 0.0041553021 3.0974642e-06
- CLCL4 CCL4 1 0.0044727137 9.8505978e-06
+ CChl O 1 0.0024394475 1.7359776e-06
+ CChl OM 1 0.0024394475 1.7359776e-06
+ CChl OA 1 0.0024394475 2.268e-06
+ CChl OW 1 0.0026240987 3.271968e-06
+ CChl N 1 0.0025317731 2.622816e-06
+ CChl NT 1 0.0025317731 2.622816e-06
+ CChl NL 1 0.0025317731 2.622816e-06
+ CChl NR 1 0.0025317731 2.622816e-06
+ CChl NZ 1 0.0025317731 2.622816e-06
+ CChl NE 1 0.0025317731 2.622816e-06
+ CChl C 1 0.002481507 3.703392e-06
+ CChl CH1 1 0.0039956468 1.98576e-05
+ CChl CH2 1 0.0044326546 1.1749248e-05
+ CChl CH3 1 0.0050291806 1.0406592e-05
+ CChl CH4 1 0.0058883216 1.1817792e-05
+ CChl CR1 1 0.003808431 7.838208e-06
+ CChl HC 1 0.0004718864 2.47968e-07
+ CChl H 1 0 0
+ CChl DUM 1 0 0
+ CChl S 1 0.0051250966 7.289856e-06
+ CChl CU1+ 1 0.0010489214 1.4432544e-07
+ CChl CU2+ 1 0.0010489214 1.4432544e-07
+ CChl FE 1 0 0
+ CChl ZN2+ 1 0.0010489214 1.9587456e-07
+ CChl MG2+ 1 0.00041443936 1.1769408e-07
+ CChl CA2+ 1 0.0016259564 1.4226912e-06
+ CChl P 1 0.0062268488 9.497376e-06
+ CChl AR 1 0.0040597618 6.326208e-06
+ CChl F 1 0.0017603414 1.7583552e-06
+ CChl CL 1 0.004801957 7.884576e-06
+ CChl BR 1 0.0017613673 1.6313472e-05
+ CChl CMet 1 0.0048322193 9.206064e-06
+ CChl OMet 1 0.0024394475 2.268e-06
+ CChl NA+ 1 0.00043541779 2.9232e-07
+ CChl CL- 1 0.00602681 2.084544e-05
+ CLChl O 1 0.004334666 3.1947671e-06
+ CLChl OM 1 0.004334666 3.1947671e-06
+ CLChl OA 1 0.004334666 4.1738625e-06
+ CLChl OW 1 0.0046627736 6.0214923e-06
+ CLChl N 1 0.0044987198 4.8268401e-06
+ CLChl NT 1 0.0044987198 4.8268401e-06
+ CLChl NL 1 0.0044987198 4.8268401e-06
+ CLChl NR 1 0.0044987198 4.8268401e-06
+ CLChl NZ 1 0.0044987198 4.8268401e-06
+ CLChl NE 1 0.0044987198 4.8268401e-06
+ CLChl C 1 0.0044094016 6.8154537e-06
+ CLChl CH1 1 0.0070998839 3.6544485e-05
+ CLChl CH2 1 0.0078764052 2.1622463e-05
+ CLChl CH3 1 0.0089363751 1.9151536e-05
+ CLChl CH4 1 0.010462987 2.1748606e-05
+ CLChl CR1 1 0.0067672192 1.4424869e-05
+ CLChl HC 1 0.0008384972 4.563423e-07
+ CLChl H 1 0 0
+ CLChl DUM 1 0 0
+ CLChl S 1 0.0091068087 1.3415722e-05
+ CLChl CU1+ 1 0.0018638335 2.6560606e-07
+ CLChl CU2+ 1 0.0018638335 2.6560606e-07
+ CLChl FE 1 0 0
+ CLChl ZN2+ 1 0.0018638335 3.6047332e-07
+ CLChl MG2+ 1 0.00073641928 2.1659564e-07
+ CLChl CA2+ 1 0.0028891697 2.6182176e-06
+ CLChl P 1 0.011064517 1.7478281e-05
+ CLChl AR 1 0.0072138101 1.1642294e-05
+ CLChl F 1 0.0031279591 3.2359492e-06
+ CLChl CL 1 0.0085326204 1.4510201e-05
+ CLChl BR 1 0.0031297819 3.0022129e-05
+ CLChl CMet 1 0.0085863936 1.6942172e-05
+ CLChl OMet 1 0.004334666 4.1738625e-06
+ CLChl NA+ 1 0.00077369595 5.379645e-07
+ CLChl CL- 1 0.010709067 3.8362434e-05
+ CLChl CChl 1 0.0046748042 7.4795616e-06
+ HChl O 1 0.0002920184 5.6465771e-08
+ HChl OM 1 0.0002920184 5.6465771e-08
+ HChl OA 1 0.0002920184 7.377075e-08
+ HChl OW 1 0.0003141224 1.064266e-07
+ HChl N 1 0.0003030704 8.5311774e-08
+ HChl NT 1 0.0003030704 8.5311774e-08
+ HChl NL 1 0.0003030704 8.5311774e-08
+ HChl NR 1 0.0003030704 8.5311774e-08
+ HChl NZ 1 0.0003030704 8.5311774e-08
+ HChl NE 1 0.0003030704 8.5311774e-08
+ HChl C 1 0.0002970532 1.2045944e-07
+ HChl CH1 1 0.000478306 6.459039e-07
+ HChl CH2 1 0.0005306188 3.8216527e-07
+ HChl CH3 1 0.000602027 3.3849299e-07
+ HChl CH4 1 0.000704872 3.8439479e-07
+ HChl CR1 1 0.000455895 2.5495171e-07
+ HChl HC 1 5.6488e-05 8.065602e-09
+ HChl H 1 0 0
+ HChl DUM 1 0 0
+ HChl S 1 0.0006135088 2.3711558e-07
+ HChl CU1+ 1 0.000125563 4.6944427e-09
+ HChl CU2+ 1 0.000125563 4.6944427e-09
+ HChl FE 1 0 0
+ HChl ZN2+ 1 0.000125563 6.3711698e-09
+ HChl MG2+ 1 4.96112e-05 3.8282101e-09
+ HChl CA2+ 1 0.000194638 4.6275572e-08
+ HChl P 1 0.000745396 3.0891911e-07
+ HChl AR 1 0.000485981 2.0577121e-07
+ HChl F 1 0.0002107248 5.7193643e-08
+ HChl CL 1 0.0005748268 2.5645991e-07
+ HChl BR 1 0.0002108476 5.3062481e-07
+ HChl CMet 1 0.0005784494 2.9944367e-07
+ HChl OMet 1 0.0002920184 7.377075e-08
+ HChl NA+ 1 5.212246e-05 9.50823e-09
+ HChl CL- 1 0.00072145 6.7803516e-07
+ HChl CChl 1 0.00031493288 1.3219718e-07
+ HChl CLChl 1 0.00055960574 2.432861e-07
+ SDmso O 1 0.0048877412 3.9925763e-06
+ SDmso OM 1 0.0048877412 3.9925763e-06
+ SDmso OA 1 0.0048877412 5.216175e-06
+ SDmso OW 1 0.0052577132 7.5252018e-06
+ SDmso N 1 0.0050727272 6.0322166e-06
+ SDmso NT 1 0.0050727272 6.0322166e-06
+ SDmso NL 1 0.0050727272 6.0322166e-06
+ SDmso NR 1 0.0050727272 6.0322166e-06
+ SDmso NZ 1 0.0050727272 6.0322166e-06
+ SDmso NE 1 0.0050727272 6.0322166e-06
+ SDmso C 1 0.0049720126 8.5174342e-06
+ SDmso CH1 1 0.008005783 4.567051e-05
+ SDmso CH2 1 0.0088813834 2.7022105e-05
+ SDmso CH3 1 0.010076599 2.3934129e-05
+ SDmso CH4 1 0.011797996 2.7179749e-05
+ SDmso CR1 1 0.0076306725 1.8027101e-05
+ SDmso HC 1 0.000945484 5.703018e-07
+ SDmso H 1 0 0
+ SDmso DUM 1 0 0
+ SDmso S 1 0.010268778 1.6765946e-05
+ SDmso CU1+ 1 0.0021016465 3.3193419e-07
+ SDmso CU2+ 1 0.0021016465 3.3193419e-07
+ SDmso FE 1 0 0
+ SDmso ZN2+ 1 0.0021016465 4.5049206e-07
+ SDmso MG2+ 1 0.0008303816 2.7068471e-07
+ SDmso CA2+ 1 0.003257809 3.2720486e-06
+ SDmso P 1 0.012476278 2.1843023e-05
+ SDmso AR 1 0.0081342455 1.4549651e-05
+ SDmso F 1 0.0035270664 4.0440425e-06
+ SDmso CL 1 0.0096213274 1.8133743e-05
+ SDmso BR 1 0.0035291218 3.7519367e-05
+ SDmso CMet 1 0.0096819617 2.1173034e-05
+ SDmso OMet 1 0.0048877412 5.216175e-06
+ SDmso NA+ 1 0.00087241453 6.72307e-07
+ SDmso CL- 1 0.012075475 4.7942444e-05
+ SDmso CChl 1 0.0052712788 9.3473856e-06
+ SDmso CLChl 1 0.0093665606 1.720225e-05
+ SDmso HChl 1 0.0006310078 3.0404041e-07
+ CDmso O 1 0.0045248108 4.016601e-06
+ CDmso OM 1 0.0045248108 4.016601e-06
+ CDmso OA 1 0.0045248108 5.2475625e-06
+ CDmso OW 1 0.0048673112 7.5704835e-06
+ CDmso N 1 0.004696061 6.0685145e-06
+ CDmso NT 1 0.004696061 6.0685145e-06
+ CDmso NL 1 0.004696061 6.0685145e-06
+ CDmso NR 1 0.004696061 6.0685145e-06
+ CDmso NZ 1 0.004696061 6.0685145e-06
+ CDmso NE 1 0.004696061 6.0685145e-06
+ CDmso C 1 0.0046028248 8.5686865e-06
+ CDmso CH1 1 0.0074113281 4.5945325e-05
+ CDmso CH2 1 0.0082219124 2.7184706e-05
+ CDmso CH3 1 0.009328379 2.4078149e-05
+ CDmso CH4 1 0.010921957 2.7343299e-05
+ CDmso CR1 1 0.0070640708 1.8135576e-05
+ CDmso HC 1 0.0008752788 5.737335e-07
+ CDmso H 1 0 0
+ CDmso DUM 1 0 0
+ CDmso S 1 0.0095062889 1.6866832e-05
+ CDmso CU1+ 1 0.0019455925 3.3393156e-07
+ CDmso CU2+ 1 0.0019455925 3.3393156e-07
+ CDmso FE 1 0 0
+ CDmso ZN2+ 1 0.0019455925 4.5320282e-07
+ CDmso MG2+ 1 0.00076872312 2.7231351e-07
+ CDmso CA2+ 1 0.0030159063 3.2917377e-06
+ CDmso P 1 0.011549875 2.197446e-05
+ CDmso AR 1 0.0075302519 1.4637201e-05
+ CDmso F 1 0.0032651705 4.0683769e-06
+ CDmso CL 1 0.0089069132 1.824286e-05
+ CDmso BR 1 0.0032670733 3.7745134e-05
+ CDmso CMet 1 0.0089630452 2.1300439e-05
+ CDmso OMet 1 0.0045248108 5.2475625e-06
+ CDmso NA+ 1 0.00080763497 6.763525e-07
+ CDmso CL- 1 0.011178832 4.823093e-05
+ CDmso CChl 1 0.0048798696 9.403632e-06
+ CDmso CLChl 1 0.0086710636 1.7305761e-05
+ CDmso HChl 1 0.00058415346 3.0586992e-07
+ CDmso SDmso 1 0.009777435 2.1627421e-05
+ ODmso O 1 0.0022663291 7.4645315e-07
+ ODmso OM 1 0.0022663291 7.4645315e-07
+ ODmso OA 1 0.0022663291 1.380375e-06
+ ODmso OW 1 0.0024378763 1.825875e-06
+ ODmso N 1 0.0023521027 2.185875e-06
+ ODmso NT 1 0.0023521027 2.53125e-06
+ ODmso NL 1 0.0023521027 3.4515e-06
+ ODmso NR 1 0.0023521027 2.071125e-06
+ ODmso NZ 1 0.0023521027 2.4165e-06
+ ODmso NE 1 0.0023521027 2.232e-06
+ ODmso C 1 0.0023054038 1.5924218e-06
+ ODmso CH1 1 0.0037120908 8.538571e-06
+ ODmso CH2 1 0.0041180858 5.0520601e-06
+ ODmso CH3 1 0.0046722786 4.4747313e-06
+ ODmso CH4 1 0.0054704496 5.0815333e-06
+ ODmso CR1 1 0.003538161 3.3703517e-06
+ ODmso HC 1 0.0004383984 1.0662378e-07
+ ODmso H 1 0 0
+ ODmso DUM 1 0 0
+ ODmso S 1 0.0047613878 3.1345658e-06
+ ODmso CU1+ 1 0.0009744834 2.53125e-07
+ ODmso CU2+ 1 0.0009744834 4.602375e-07
+ ODmso FE 1 0 0
+ ODmso ZN2+ 1 0.0009744834 1.09305e-07
+ ODmso MG2+ 1 0.00038502816 6.56775e-08
+ ODmso CA2+ 1 0.0015105684 7.939125e-07
+ ODmso P 1 0.0057849528 5.299875e-06
+ ODmso AR 1 0.0037716558 2.7202067e-06
+ ODmso F 1 0.0016354166 7.5607529e-07
+ ODmso CL 1 0.0044611802 3.3902895e-06
+ ODmso BR 1 0.0016363697 7.0146311e-06
+ ODmso CMet 1 0.0044892949 3.9585162e-06
+ ODmso OMet 1 0.0022663291 1.380375e-06
+ ODmso NA+ 1 0.00040451783 1.63125e-07
+ ODmso CL- 1 0.00559911 8.9633324e-06
+ ODmso CChl 1 0.0024441664 1.7475898e-06
+ ODmso CLChl 1 0.0043430509 3.2161373e-06
+ ODmso HChl 1 0.00029258328 5.6843478e-08
+ ODmso SDmso 1 0.004897196 4.0192831e-06
+ ODmso CDmso 1 0.0045335636 4.0434685e-06
+ CCl4 O 1 0.0024394475 2.3738805e-06
+ CCl4 OM 1 0.0024394475 2.3738805e-06
+ CCl4 OA 1 0.0024394475 3.1014e-06
+ CCl4 OW 1 0.0026240987 4.4742864e-06
+ CCl4 N 1 0.0025317731 3.5865968e-06
+ CCl4 NT 1 0.0025317731 3.5865968e-06
+ CCl4 NL 1 0.0025317731 3.5865968e-06
+ CCl4 NR 1 0.0025317731 3.5865968e-06
+ CCl4 NZ 1 0.0025317731 3.5865968e-06
+ CCl4 NE 1 0.0025317731 3.5865968e-06
+ CCl4 C 1 0.002481507 5.0642416e-06
+ CCl4 CH1 1 0.0039956468 2.715448e-05
+ CCl4 CH2 1 0.0044326546 1.606663e-05
+ CCl4 CH3 1 0.0050291806 1.4230602e-05
+ CCl4 CH4 1 0.0058883216 1.6160362e-05
+ CCl4 CR1 1 0.003808431 1.0718438e-05
+ CCl4 HC 1 0.0004718864 3.390864e-07
+ CCl4 H 1 0 0
+ CCl4 DUM 1 0 0
+ CCl4 S 1 0.0051250966 9.9685888e-06
+ CCl4 CU1+ 1 0.0010489214 1.9735931e-07
+ CCl4 CU2+ 1 0.0010489214 1.9735931e-07
+ CCl4 FE 1 0 0
+ CCl4 ZN2+ 1 0.0010489214 2.6785069e-07
+ CCl4 MG2+ 1 0.00041443936 1.6094198e-07
+ CCl4 CA2+ 1 0.0016259564 1.9454738e-06
+ CCl4 P 1 0.0062268488 1.2987285e-05
+ CCl4 AR 1 0.0040597618 8.6508384e-06
+ CCl4 F 1 0.0017603414 2.404481e-06
+ CCl4 CL 1 0.004801957 1.0781845e-05
+ CCl4 BR 1 0.0017613673 2.2308026e-05
+ CCl4 CMet 1 0.0048322193 1.2588927e-05
+ CCl4 OMet 1 0.0024394475 3.1014e-06
+ CCl4 NA+ 1 0.00043541779 3.99736e-07
+ CCl4 CL- 1 0.00602681 2.8505312e-05
+ CCl4 CChl 1 0.0026308693 5.5577088e-06
+ CCl4 CLChl 1 0.0046748042 1.0228004e-05
+ CCl4 HChl 1 0.00031493288 1.807744e-07
+ CCl4 SDmso 1 0.0052712788 1.2782179e-05
+ CCl4 CDmso 1 0.0048798696 1.2859094e-05
+ CCl4 ODmso 1 0.0024441664 2.3897596e-06
+ CLCl4 O 1 0.0041472796 3.0768825e-06
+ CLCl4 OM 1 0.0041472796 3.0768825e-06
+ CLCl4 OA 1 0.0041472796 4.01985e-06
+ CLCl4 OW 1 0.0044612032 5.7993036e-06
+ CLCl4 N 1 0.0043042414 4.6487332e-06
+ CLCl4 NT 1 0.0043042414 4.6487332e-06
+ CLCl4 NL 1 0.0043042414 4.6487332e-06
+ CLCl4 NR 1 0.0043042414 4.6487332e-06
+ CLCl4 NZ 1 0.0043042414 4.6487332e-06
+ CLCl4 NE 1 0.0043042414 4.6487332e-06
+ CLCl4 C 1 0.0042187844 6.5639684e-06
+ CLCl4 CH1 1 0.0067929579 3.519602e-05
+ CLCl4 CH2 1 0.0075359104 2.082461e-05
+ CLCl4 CH3 1 0.008550058 1.8444858e-05
+ CLCl4 CH4 1 0.010010675 2.0946098e-05
+ CLCl4 CR1 1 0.0064746742 1.3892602e-05
+ CLCl4 HC 1 0.0008022492 4.395036e-07
+ CLCl4 H 1 0 0
+ CLCl4 DUM 1 0 0
+ CLCl4 S 1 0.0087131239 1.2920691e-05
+ CLCl4 CU1+ 1 0.0017832604 2.5580539e-07
+ CLCl4 CU2+ 1 0.0017832604 2.5580539e-07
+ CLCl4 FE 1 0 0
+ CLCl4 ZN2+ 1 0.0017832604 3.4717211e-07
+ CLCl4 MG2+ 1 0.00070458408 2.0860342e-07
+ CLCl4 CA2+ 1 0.0027642717 2.5216072e-06
+ CLCl4 P 1 0.010586201 1.6833345e-05
+ CLCl4 AR 1 0.0069019592 1.1212702e-05
+ CLCl4 F 1 0.0029927383 3.116545e-06
+ CLCl4 CL 1 0.0081637576 1.3974785e-05
+ CLCl4 BR 1 0.0029944823 2.8914334e-05
+ CLCl4 CMet 1 0.0082152062 1.6317018e-05
+ CLCl4 OMet 1 0.0041472796 4.01985e-06
+ CLCl4 NA+ 1 0.00074024929 5.18114e-07
+ CLCl4 CL- 1 0.010246117 3.6946888e-05
+ CLCl4 CChl 1 0.0044727137 7.2035712e-06
+ CLCl4 CLChl 1 0.0079475863 1.3256929e-05
+ CLCl4 HChl 1 0.00053541414 2.3430902e-07
+ CLCl4 SDmso 1 0.0089616468 1.6567499e-05
+ CLCl4 CDmso 1 0.0082962159 1.6667191e-05
+ CLCl4 ODmso 1 0.0041553021 3.0974642e-06
+ CLCl4 CCl4 1 0.0044727137 9.8505978e-06
CH2r O 1 0.0040730384 4.5612467e-06
CH2r OM 1 0.0040730384 4.5612467e-06
CH2r OA 1 0.0040730384 5.959125e-06
CH2r F 1 0.0029391648 4.6200434e-06
CH2r CL 1 0.0080176168 2.0716567e-05
CH2r BR 1 0.0029408776 4.2863324e-05
- CH2r CMET 1 0.0080681444 2.418875e-05
- CH2r OMET 1 0.0040730384 5.959125e-06
+ CH2r CMet 1 0.0080681444 2.418875e-05
+ CH2r OMet 1 0.0040730384 5.959125e-06
CH2r NA+ 1 0.00072699796 7.68065e-07
CH2r CL- 1 0.0100627 5.477098e-05
- CH2r CCHL 1 0.0043926469 1.0678752e-05
- CH2r CLCHL 1 0.0078053152 1.96524e-05
- CH2r HCHL 1 0.0005258296 3.4734548e-07
- CH2r SDMSO 1 0.0088012228 2.456007e-05
- CH2r CDMSO 1 0.008147704 2.4707856e-05
- CH2r ODMSO 1 0.0040809173 4.5917574e-06
- CH2r CCL4 1 0.0043926469 1.460277e-05
- CH2r CLCL4 1 0.0074678936 1.892724e-05
+ CH2r CChl 1 0.0043926469 1.0678752e-05
+ CH2r CLChl 1 0.0078053152 1.96524e-05
+ CH2r HChl 1 0.0005258296 3.4734548e-07
+ CH2r SDmso 1 0.0088012228 2.456007e-05
+ CH2r CDmso 1 0.008147704 2.4707856e-05
+ CH2r ODmso 1 0.0040809173 4.5917574e-06
+ CH2r CCl4 1 0.0043926469 1.460277e-05
+ CH2r CLCl4 1 0.0074678936 1.892724e-05
CH0 O 1 0.0023285376 1.2339563e-05
CH0 OM 1 0.0023285376 1.2339563e-05
CH0 OA 1 0.0023285376 1.612125e-05
CH0 F 1 0.0016803072 1.2498626e-05
CH0 CL 1 0.0045836352 5.604463e-05
CH0 BR 1 0.0016812864 0.00011595836
- CH0 CMET 1 0.0046125216 6.5437945e-05
- CH0 OMET 1 0.0023285376 1.612125e-05
+ CH0 CMet 1 0.0046125216 6.5437945e-05
+ CH0 OMet 1 0.0023285376 1.612125e-05
CH0 NA+ 1 0.00041562144 2.07785e-06
CH0 CL- 1 0.0057528 0.0001481722
- CH0 CCHL 1 0.0025112563 2.888928e-05
- CH0 CLCHL 1 0.0044622634 5.3165733e-05
- CH0 HCHL 1 0.0003006144 9.3967542e-07
- CH0 SDMSO 1 0.0050316192 6.6442478e-05
- CH0 CDMSO 1 0.0046580054 6.6842285e-05
- CH0 ODMSO 1 0.0023330419 1.2422104e-05
- CH0 CCL4 1 0.0025112563 3.9504944e-05
- CH0 CLCL4 1 0.004269361 5.1203956e-05
+ CH0 CChl 1 0.0025112563 2.888928e-05
+ CH0 CLChl 1 0.0044622634 5.3165733e-05
+ CH0 HChl 1 0.0003006144 9.3967542e-07
+ CH0 SDmso 1 0.0050316192 6.6442478e-05
+ CH0 CDmso 1 0.0046580054 6.6842285e-05
+ CH0 ODmso 1 0.0023330419 1.2422104e-05
+ CH0 CCl4 1 0.0025112563 3.9504944e-05
+ CH0 CLCl4 1 0.004269361 5.1203956e-05
CH0 CH2r 1 0.0041929344 7.590601e-05
SI O 1 0.005773784 5.299875e-06
SI OM 1 0.005773784 1.4453348e-05
SI F 1 0.004166448 5.780397e-06
SI CL 1 0.011365468 1.8424721e-05
SI BR 1 0.004168876 3.8121412e-05
- SI CMET 1 0.011437094 2.1512782e-05
- SI OMET 1 0.005773784 5.780397e-06
+ SI CMet 1 0.011437094 2.1512782e-05
+ SI OMet 1 0.005773784 5.780397e-06
SI NA+ 1 0.0010305646 6.83095e-07
SI CL- 1 0.0142645 4.871174e-05
- SI CCHL 1 0.0062268488 9.497376e-06
- SI CLCHL 1 0.011064517 1.7478281e-05
- SI HCHL 1 0.000745396 3.0891911e-07
- SI SDMSO 1 0.012476278 2.1843023e-05
- SI CDMSO 1 0.011549875 2.197446e-05
- SI ODMSO 1 0.0057849528 5.299875e-06
- SI CCL4 1 0.0062268488 1.2987285e-05
- SI CLCL4 1 0.010586201 1.6833345e-05
+ SI CChl 1 0.0062268488 9.497376e-06
+ SI CLChl 1 0.011064517 1.7478281e-05
+ SI HChl 1 0.000745396 3.0891911e-07
+ SI SDmso 1 0.012476278 2.1843023e-05
+ SI CDmso 1 0.011549875 2.197446e-05
+ SI ODmso 1 0.0057849528 5.299875e-06
+ SI CCl4 1 0.0062268488 1.2987285e-05
+ SI CLCl4 1 0.010586201 1.6833345e-05
SI CH2r 1 0.010396696 2.4954167e-05
SI CH0 1 0.005943744 6.750863e-05
BR F 1 0.0011785488 7.0578424e-06
BR CL 1 0.0032149108 3.1647812e-05
BR BR 1 0.0011792356 6.5480464e-05
- CMET O 1 0.0044806276 3.9322131e-06
- CMET OM 1 0.0044806276 3.9322131e-06
- CMET OA 1 0.0044806276 5.1373125e-06
- CMET OW 1 0.0048197836 7.4114295e-06
- CMET N 1 0.0046502056 5.9410165e-06
- CMET NT 1 0.0046502056 5.9410165e-06
- CMET NL 1 0.0046502056 5.9410165e-06
- CMET NR 1 0.0046502056 5.9410165e-06
- CMET NZ 1 0.0046502056 5.9410165e-06
- CMET NE 1 0.0046502056 5.9410165e-06
- CMET C 1 0.0045578798 8.3886605e-06
- CMET CH1 1 0.0050835716 8.8270445e-06
- CMET CH2 1 0.0064750533 9.943994e-06
- CMET CH3 1 0.0077987038 1.1214329e-05
- CMET CH4 1 0.010815308 2.6768823e-05
- CMET CR1 1 0.0070045135 1.3178919e-05
- CMET HC 1 0.000866732 5.616795e-07
- CMET H 1 0 0
- CMET DUM 1 0 0
- CMET S 1 0.0094134632 1.6512464e-05
- CMET CU1+ 1 0.0019265945 3.2691574e-07
- CMET CU2+ 1 0.0019265945 3.2691574e-07
- CMET FE 1 0 0
- CMET ZN2+ 1 0.0019265945 4.4368114e-07
- CMET MG2+ 1 0.0007612168 2.6659227e-07
- CMET CA2+ 1 0.002986457 3.222579e-06
- CMET P 1 0.011437094 2.1512782e-05
- CMET AR 1 0.0074567215 1.4329677e-05
- CMET F 1 0.0032332872 3.9829013e-06
- CMET CL 1 0.0088199402 1.7859582e-05
- CMET BR 1 0.0032351714 3.6952118e-05
- CMET CMET 1 0.0088755241 2.0852922e-05
- OMET O 1 0.0022619536 9.687375e-07
- OMET OM 1 0.0022619536 9.687375e-07
- OMET OA 1 0.0022619536 1.265625e-06
- OMET OW 1 0.0024331696 1.825875e-06
- OMET N 1 0.0023475616 1.463625e-06
- OMET NT 1 0.0023475616 1.463625e-06
- OMET NL 1 0.0023475616 1.463625e-06
- OMET NR 1 0.0023475616 1.463625e-06
- OMET NZ 1 0.0023475616 1.463625e-06
- OMET NE 1 0.0023475616 1.463625e-06
- OMET C 1 0.0023009528 2.066625e-06
- OMET CH1 1 0.0025663376 2.174625e-06
- OMET CH2 1 0.0032687988 2.4497959e-06
- OMET CH3 1 0.0039370168 2.7627548e-06
- OMET CH4 1 0.005459888 6.59475e-06
- OMET CR1 1 0.003536086 3.24675e-06
- OMET HC 1 0.000437552 1.38375e-07
- OMET H 1 0 0
- OMET DUM 1 0 0
- OMET S 1 0.0047521952 4.068e-06
- OMET CU1+ 1 0.000972602 8.053875e-08
- OMET CU2+ 1 0.000972602 8.053875e-08
- OMET FE 1 0 0
- OMET ZN2+ 1 0.000972602 1.09305e-07
- OMET MG2+ 1 0.0003842848 6.56775e-08
- OMET CA2+ 1 0.001507652 7.939125e-07
- OMET P 1 0.005773784 5.299875e-06
- OMET AR 1 0.003764374 3.53025e-06
- OMET F 1 0.0016322592 9.81225e-07
- OMET CL 1 0.0044525672 4.399875e-06
- OMET BR 1 0.0016332104 9.1035e-06
- OMET CMET 1 0.0044806276 5.1373125e-06
- OMET OMET 1 0.0022619536 1.265625e-06
+ CMet O 1 0.0044806276 3.9322131e-06
+ CMet OM 1 0.0044806276 3.9322131e-06
+ CMet OA 1 0.0044806276 5.1373125e-06
+ CMet OW 1 0.0048197836 7.4114295e-06
+ CMet N 1 0.0046502056 5.9410165e-06
+ CMet NT 1 0.0046502056 5.9410165e-06
+ CMet NL 1 0.0046502056 5.9410165e-06
+ CMet NR 1 0.0046502056 5.9410165e-06
+ CMet NZ 1 0.0046502056 5.9410165e-06
+ CMet NE 1 0.0046502056 5.9410165e-06
+ CMet C 1 0.0045578798 8.3886605e-06
+ CMet CH1 1 0.0050835716 8.8270445e-06
+ CMet CH2 1 0.0064750533 9.943994e-06
+ CMet CH3 1 0.0077987038 1.1214329e-05
+ CMet CH4 1 0.010815308 2.6768823e-05
+ CMet CR1 1 0.0070045135 1.3178919e-05
+ CMet HC 1 0.000866732 5.616795e-07
+ CMet H 1 0 0
+ CMet DUM 1 0 0
+ CMet S 1 0.0094134632 1.6512464e-05
+ CMet CU1+ 1 0.0019265945 3.2691574e-07
+ CMet CU2+ 1 0.0019265945 3.2691574e-07
+ CMet FE 1 0 0
+ CMet ZN2+ 1 0.0019265945 4.4368114e-07
+ CMet MG2+ 1 0.0007612168 2.6659227e-07
+ CMet CA2+ 1 0.002986457 3.222579e-06
+ CMet P 1 0.011437094 2.1512782e-05
+ CMet AR 1 0.0074567215 1.4329677e-05
+ CMet F 1 0.0032332872 3.9829013e-06
+ CMet CL 1 0.0088199402 1.7859582e-05
+ CMet BR 1 0.0032351714 3.6952118e-05
+ CMet CMet 1 0.0088755241 2.0852922e-05
+ OMet O 1 0.0022619536 9.687375e-07
+ OMet OM 1 0.0022619536 9.687375e-07
+ OMet OA 1 0.0022619536 1.265625e-06
+ OMet OW 1 0.0024331696 1.825875e-06
+ OMet N 1 0.0023475616 1.463625e-06
+ OMet NT 1 0.0023475616 1.463625e-06
+ OMet NL 1 0.0023475616 1.463625e-06
+ OMet NR 1 0.0023475616 1.463625e-06
+ OMet NZ 1 0.0023475616 1.463625e-06
+ OMet NE 1 0.0023475616 1.463625e-06
+ OMet C 1 0.0023009528 2.066625e-06
+ OMet CH1 1 0.0025663376 2.174625e-06
+ OMet CH2 1 0.0032687988 2.4497959e-06
+ OMet CH3 1 0.0039370168 2.7627548e-06
+ OMet CH4 1 0.005459888 6.59475e-06
+ OMet CR1 1 0.003536086 3.24675e-06
+ OMet HC 1 0.000437552 1.38375e-07
+ OMet H 1 0 0
+ OMet DUM 1 0 0
+ OMet S 1 0.0047521952 4.068e-06
+ OMet CU1+ 1 0.000972602 8.053875e-08
+ OMet CU2+ 1 0.000972602 8.053875e-08
+ OMet FE 1 0 0
+ OMet ZN2+ 1 0.000972602 1.09305e-07
+ OMet MG2+ 1 0.0003842848 6.56775e-08
+ OMet CA2+ 1 0.001507652 7.939125e-07
+ OMet P 1 0.005773784 5.299875e-06
+ OMet AR 1 0.003764374 3.53025e-06
+ OMet F 1 0.0016322592 9.81225e-07
+ OMet CL 1 0.0044525672 4.399875e-06
+ OMet BR 1 0.0016332104 9.1035e-06
+ OMet CMet 1 0.0044806276 5.1373125e-06
+ OMet OMet 1 0.0022619536 1.265625e-06
NA+ O 1 0.00040373684 1.248595e-07
NA+ OM 1 0.00040373684 1.248595e-07
NA+ OA 1 0.00040373684 1.63125e-07
NA+ F 1 0.00029134248 1.26469e-07
NA+ CL 1 0.00079474018 5.67095e-07
NA+ BR 1 0.00029151226 1.17334e-06
- NA+ CMET 1 0.00079974869 6.621425e-07
- NA+ OMET 1 0.00040373684 1.63125e-07
+ NA+ CMet 1 0.00079974869 6.621425e-07
+ NA+ OMet 1 0.00040373684 1.63125e-07
NA+ NA+ 1 7.2063121e-05 2.1025e-08
CL- O 1 0.0055883 8.903774e-06
CL- OM 1 0.0055883 8.903774e-06
CL- F 1 0.0040326 9.018548e-06
CL- CL 1 0.01100035 4.043974e-05
CL- BR 1 0.00403495 8.367128e-05
- CL- CMET 1 0.011069675 4.721761e-05
- CL- OMET 1 0.0055883 1.16325e-05
+ CL- CMet 1 0.011069675 4.721761e-05
+ CL- OMet 1 0.0055883 1.16325e-05
CL- NA+ 1 0.0009974575 1.4993e-06
CL- CL- 1 0.01380625 0.0001069156
- CCHL O 1 0.0024394475 1.7359776e-06
- CCHL OM 1 0.0024394475 1.7359776e-06
- CCHL OA 1 0.0024394475 2.268e-06
- CCHL OW 1 0.0026240987 3.271968e-06
- CCHL N 1 0.0025317731 2.622816e-06
- CCHL NT 1 0.0025317731 2.622816e-06
- CCHL NL 1 0.0025317731 2.622816e-06
- CCHL NR 1 0.0025317731 2.622816e-06
- CCHL NZ 1 0.0025317731 2.622816e-06
- CCHL NE 1 0.0025317731 2.622816e-06
- CCHL C 1 0.002481507 3.703392e-06
- CCHL CH1 1 0.0027677163 3.896928e-06
- CCHL CH2 1 0.0035252992 4.3900343e-06
- CCHL CH3 1 0.0042459518 4.9508565e-06
- CCHL CH4 1 0.0058883216 1.1817792e-05
- CCHL CR1 1 0.0038135602 5.818176e-06
- CCHL HC 1 0.0004718864 2.47968e-07
- CCHL H 1 0 0
- CCHL DUM 1 0 0
- CCHL S 1 0.0051250966 7.289856e-06
- CCHL CU1+ 1 0.0010489214 1.4432544e-07
- CCHL CU2+ 1 0.0010489214 1.4432544e-07
- CCHL FE 1 0 0
- CCHL ZN2+ 1 0.0010489214 1.9587456e-07
- CCHL MG2+ 1 0.00041443936 1.1769408e-07
- CCHL CA2+ 1 0.0016259564 1.4226912e-06
- CCHL P 1 0.0062268488 9.497376e-06
- CCHL AR 1 0.0040597618 6.326208e-06
- CCHL F 1 0.0017603414 1.7583552e-06
- CCHL CL 1 0.004801957 7.884576e-06
- CCHL BR 1 0.0017613673 1.6313472e-05
- CCHL CMET 1 0.0048322193 9.206064e-06
- CCHL OMET 1 0.0024394475 2.268e-06
- CCHL NA+ 1 0.00043541779 2.9232e-07
- CCHL CL- 1 0.00602681 2.084544e-05
- CCHL CCHL 1 0.0026308693 4.064256e-06
- CLCHL O 1 0.004334666 3.1947671e-06
- CLCHL OM 1 0.004334666 3.1947671e-06
- CLCHL OA 1 0.004334666 4.1738625e-06
- CLCHL OW 1 0.0046627736 6.0214923e-06
- CLCHL N 1 0.0044987198 4.8268401e-06
- CLCHL NT 1 0.0044987198 4.8268401e-06
- CLCHL NL 1 0.0044987198 4.8268401e-06
- CLCHL NR 1 0.0044987198 4.8268401e-06
- CLCHL NZ 1 0.0044987198 4.8268401e-06
- CLCHL NE 1 0.0044987198 4.8268401e-06
- CLCHL C 1 0.0044094016 6.8154537e-06
- CLCHL CH1 1 0.0049179684 7.1716233e-06
- CLCHL CH2 1 0.0062641209 8.0791004e-06
- CLCHL CH3 1 0.007544652 9.1111968e-06
- CLCHL CH4 1 0.010462987 2.1748606e-05
- CLCHL CR1 1 0.0067763334 1.0707349e-05
- CLCHL HC 1 0.0008384972 4.563423e-07
- CLCHL H 1 0 0
- CLCHL DUM 1 0 0
- CLCHL S 1 0.0091068087 1.3415722e-05
- CLCHL CU1+ 1 0.0018638335 2.6560606e-07
- CLCHL CU2+ 1 0.0018638335 2.6560606e-07
- CLCHL FE 1 0 0
- CLCHL ZN2+ 1 0.0018638335 3.6047332e-07
- CLCHL MG2+ 1 0.00073641928 2.1659564e-07
- CLCHL CA2+ 1 0.0028891697 2.6182176e-06
- CLCHL P 1 0.011064517 1.7478281e-05
- CLCHL AR 1 0.0072138101 1.1642294e-05
- CLCHL F 1 0.0031279591 3.2359492e-06
- CLCHL CL 1 0.0085326204 1.4510201e-05
- CLCHL BR 1 0.0031297819 3.0022129e-05
- CLCHL CMET 1 0.0085863936 1.6942172e-05
- CLCHL OMET 1 0.004334666 4.1738625e-06
- CLCHL NA+ 1 0.00077369595 5.379645e-07
- CLCHL CL- 1 0.010709067 3.8362434e-05
- CLCHL CCHL 1 0.0046748042 7.4795616e-06
- CLCHL CLCHL 1 0.0083066819 1.3764842e-05
- HCHL O 1 0.0002920184 5.6465771e-08
- HCHL OM 1 0.0002920184 5.6465771e-08
- HCHL OA 1 0.0002920184 7.377075e-08
- HCHL OW 1 0.0003141224 1.064266e-07
- HCHL N 1 0.0003030704 8.5311774e-08
- HCHL NT 1 0.0003030704 8.5311774e-08
- HCHL NL 1 0.0003030704 8.5311774e-08
- HCHL NR 1 0.0003030704 8.5311774e-08
- HCHL NZ 1 0.0003030704 8.5311774e-08
- HCHL NE 1 0.0003030704 8.5311774e-08
- HCHL C 1 0.0002970532 1.2045944e-07
- HCHL CH1 1 0.0003313144 1.2675454e-07
- HCHL CH2 1 0.0004220022 1.4279371e-07
- HCHL CH3 1 0.0005082692 1.6103545e-07
- HCHL CH4 1 0.000704872 3.8439479e-07
- HCHL CR1 1 0.000456509 1.8924656e-07
- HCHL HC 1 5.6488e-05 8.065602e-09
- HCHL H 1 0 0
- HCHL DUM 1 0 0
- HCHL S 1 0.0006135088 2.3711558e-07
- HCHL CU1+ 1 0.000125563 4.6944427e-09
- HCHL CU2+ 1 0.000125563 4.6944427e-09
- HCHL FE 1 0 0
- HCHL ZN2+ 1 0.000125563 6.3711698e-09
- HCHL MG2+ 1 4.96112e-05 3.8282101e-09
- HCHL CA2+ 1 0.000194638 4.6275572e-08
- HCHL P 1 0.000745396 3.0891911e-07
- HCHL AR 1 0.000485981 2.0577121e-07
- HCHL F 1 0.0002107248 5.7193643e-08
- HCHL CL 1 0.0005748268 2.5645991e-07
- HCHL BR 1 0.0002108476 5.3062481e-07
- HCHL CMET 1 0.0005784494 2.9944367e-07
- HCHL OMET 1 0.0002920184 7.377075e-08
- HCHL NA+ 1 5.212246e-05 9.50823e-09
- HCHL CL- 1 0.00072145 6.7803516e-07
- HCHL CCHL 1 0.00031493288 1.3219718e-07
- HCHL CLCHL 1 0.00055960574 2.432861e-07
- HCHL HCHL 1 3.76996e-05 4.2999495e-09
- SDMSO O 1 0.0048877412 3.9925763e-06
- SDMSO OM 1 0.0048877412 3.9925763e-06
- SDMSO OA 1 0.0048877412 5.216175e-06
- SDMSO OW 1 0.0052577132 7.5252018e-06
- SDMSO N 1 0.0050727272 6.0322166e-06
- SDMSO NT 1 0.0050727272 6.0322166e-06
- SDMSO NL 1 0.0050727272 6.0322166e-06
- SDMSO NR 1 0.0050727272 6.0322166e-06
- SDMSO NZ 1 0.0050727272 6.0322166e-06
- SDMSO NE 1 0.0050727272 6.0322166e-06
- SDMSO C 1 0.0049720126 8.5174342e-06
- SDMSO CH1 1 0.0055454692 8.9625478e-06
- SDMSO CH2 1 0.0070633821 1.0096643e-05
- SDMSO CH3 1 0.0085073006 1.1386479e-05
- SDMSO CH4 1 0.011797996 2.7179749e-05
- SDMSO CR1 1 0.0076409495 1.3381228e-05
- SDMSO HC 1 0.000945484 5.703018e-07
- SDMSO H 1 0 0
- SDMSO DUM 1 0 0
- SDMSO S 1 0.010268778 1.6765946e-05
- SDMSO CU1+ 1 0.0021016465 3.3193419e-07
- SDMSO CU2+ 1 0.0021016465 3.3193419e-07
- SDMSO FE 1 0 0
- SDMSO ZN2+ 1 0.0021016465 4.5049206e-07
- SDMSO MG2+ 1 0.0008303816 2.7068471e-07
- SDMSO CA2+ 1 0.003257809 3.2720486e-06
- SDMSO P 1 0.012476278 2.1843023e-05
- SDMSO AR 1 0.0081342455 1.4549651e-05
- SDMSO F 1 0.0035270664 4.0440425e-06
- SDMSO CL 1 0.0096213274 1.8133743e-05
- SDMSO BR 1 0.0035291218 3.7519367e-05
- SDMSO CMET 1 0.0096819617 2.1173034e-05
- SDMSO OMET 1 0.0048877412 5.216175e-06
- SDMSO NA+ 1 0.00087241453 6.72307e-07
- SDMSO CL- 1 0.012075475 4.7942444e-05
- SDMSO CCHL 1 0.0052712788 9.3473856e-06
- SDMSO CLCHL 1 0.0093665606 1.720225e-05
- SDMSO HCHL 1 0.0006310078 3.0404041e-07
- SDMSO SDMSO 1 0.010561673 2.149806e-05
- CDMSO O 1 0.0045248108 4.016601e-06
- CDMSO OM 1 0.0045248108 4.016601e-06
- CDMSO OA 1 0.0045248108 5.2475625e-06
- CDMSO OW 1 0.0048673112 7.5704835e-06
- CDMSO N 1 0.004696061 6.0685145e-06
- CDMSO NT 1 0.004696061 6.0685145e-06
- CDMSO NL 1 0.004696061 6.0685145e-06
- CDMSO NR 1 0.004696061 6.0685145e-06
- CDMSO NZ 1 0.004696061 6.0685145e-06
- CDMSO NE 1 0.004696061 6.0685145e-06
- CDMSO C 1 0.0046028248 8.5686865e-06
- CDMSO CH1 1 0.0051337004 9.0164785e-06
- CDMSO CH2 1 0.0065389035 1.0157398e-05
- CDMSO CH3 1 0.0078756064 1.1454995e-05
- CDMSO CH4 1 0.010921957 2.7343299e-05
- CDMSO CR1 1 0.0070735846 1.3461747e-05
- CDMSO HC 1 0.0008752788 5.737335e-07
- CDMSO H 1 0 0
- CDMSO DUM 1 0 0
- CDMSO S 1 0.0095062889 1.6866832e-05
- CDMSO CU1+ 1 0.0019455925 3.3393156e-07
- CDMSO CU2+ 1 0.0019455925 3.3393156e-07
- CDMSO FE 1 0 0
- CDMSO ZN2+ 1 0.0019455925 4.5320282e-07
- CDMSO MG2+ 1 0.00076872312 2.7231351e-07
- CDMSO CA2+ 1 0.0030159063 3.2917377e-06
- CDMSO P 1 0.011549875 2.197446e-05
- CDMSO AR 1 0.0075302519 1.4637201e-05
- CDMSO F 1 0.0032651705 4.0683769e-06
- CDMSO CL 1 0.0089069132 1.824286e-05
- CDMSO BR 1 0.0032670733 3.7745134e-05
- CDMSO CMET 1 0.0089630452 2.1300439e-05
- CDMSO OMET 1 0.0045248108 5.2475625e-06
- CDMSO NA+ 1 0.00080763497 6.763525e-07
- CDMSO CL- 1 0.011178832 4.823093e-05
- CDMSO CCHL 1 0.0048798696 9.403632e-06
- CDMSO CLCHL 1 0.0086710636 1.7305761e-05
- CDMSO HCHL 1 0.00058415346 3.0586992e-07
- CDMSO SDMSO 1 0.009777435 2.1627421e-05
- CDMSO CDMSO 1 0.0090514293 2.175756e-05
- ODMSO O 1 0.0022663291 7.4645315e-07
- ODMSO OM 1 0.0022663291 7.4645315e-07
- ODMSO OA 1 0.0022663291 9.752175e-07
- ODMSO OW 1 0.0024378763 1.4069138e-06
- ODMSO N 1 0.0023521027 1.1277849e-06
- ODMSO NT 1 0.0023521027 1.1277849e-06
- ODMSO NL 1 0.0023521027 1.1277849e-06
- ODMSO NR 1 0.0023521027 1.1277849e-06
- ODMSO NZ 1 0.0023521027 1.1277849e-06
- ODMSO NE 1 0.0023521027 1.1277849e-06
- ODMSO C 1 0.0023054038 1.5924218e-06
- ODMSO CH1 1 0.0025713019 1.6756404e-06
- ODMSO CH2 1 0.003275122 1.8876712e-06
- ODMSO CH3 1 0.0039446326 2.1288192e-06
- ODMSO CH4 1 0.0054704496 5.0815333e-06
- ODMSO CR1 1 0.0035429262 2.501758e-06
- ODMSO HC 1 0.0004383984 1.0662378e-07
- ODMSO H 1 0 0
- ODMSO DUM 1 0 0
- ODMSO S 1 0.0047613878 3.1345658e-06
- ODMSO CU1+ 1 0.0009744834 6.2058507e-08
- ODMSO CU2+ 1 0.0009744834 6.2058507e-08
- ODMSO FE 1 0 0
- ODMSO ZN2+ 1 0.0009744834 8.4224118e-08
- ODMSO MG2+ 1 0.00038502816 5.0607287e-08
- ODMSO CA2+ 1 0.0015105684 6.117431e-07
- ODMSO P 1 0.0057849528 4.0837775e-06
- ODMSO AR 1 0.0037716558 2.7202067e-06
- ODMSO F 1 0.0016354166 7.5607529e-07
- ODMSO CL 1 0.0044611802 3.3902895e-06
- ODMSO BR 1 0.0016363697 7.0146311e-06
- ODMSO CMET 1 0.0044892949 3.9585162e-06
- ODMSO OMET 1 0.0022663291 9.752175e-07
- ODMSO NA+ 1 0.00040451783 1.256947e-07
- ODMSO CL- 1 0.00559911 8.9633324e-06
- ODMSO CCHL 1 0.0024441664 1.7475898e-06
- ODMSO CLCHL 1 0.0043430509 3.2161373e-06
- ODMSO HCHL 1 0.00029258328 5.6843478e-08
- ODMSO SDMSO 1 0.004897196 4.0192831e-06
- ODMSO CDMSO 1 0.0045335636 4.0434685e-06
- ODMSO ODMSO 1 0.0022707131 7.5144626e-07
- CCL4 O 1 0.0024394475 2.3738805e-06
- CCL4 OM 1 0.0024394475 2.3738805e-06
- CCL4 OA 1 0.0024394475 3.1014e-06
- CCL4 OW 1 0.0026240987 4.4742864e-06
- CCL4 N 1 0.0025317731 3.5865968e-06
- CCL4 NT 1 0.0025317731 3.5865968e-06
- CCL4 NL 1 0.0025317731 3.5865968e-06
- CCL4 NR 1 0.0025317731 3.5865968e-06
- CCL4 NZ 1 0.0025317731 3.5865968e-06
- CCL4 NE 1 0.0025317731 3.5865968e-06
- CCL4 C 1 0.002481507 5.0642416e-06
- CCL4 CH1 1 0.0027677163 5.3288944e-06
- CCL4 CH2 1 0.0035252992 6.0031978e-06
- CCL4 CH3 1 0.0042459518 6.7700998e-06
- CCL4 CH4 1 0.0058883216 1.6160362e-05
- CCL4 CR1 1 0.0038135602 7.9561248e-06
- CCL4 HC 1 0.0004718864 3.390864e-07
- CCL4 H 1 0 0
- CCL4 DUM 1 0 0
- CCL4 S 1 0.0051250966 9.9685888e-06
- CCL4 CU1+ 1 0.0010489214 1.9735931e-07
- CCL4 CU2+ 1 0.0010489214 1.9735931e-07
- CCL4 FE 1 0 0
- CCL4 ZN2+ 1 0.0010489214 2.6785069e-07
- CCL4 MG2+ 1 0.00041443936 1.6094198e-07
- CCL4 CA2+ 1 0.0016259564 1.9454738e-06
- CCL4 P 1 0.0062268488 1.2987285e-05
- CCL4 AR 1 0.0040597618 8.6508384e-06
- CCL4 F 1 0.0017603414 2.404481e-06
- CCL4 CL 1 0.004801957 1.0781845e-05
- CCL4 BR 1 0.0017613673 2.2308026e-05
- CCL4 CMET 1 0.0048322193 1.2588927e-05
- CCL4 OMET 1 0.0024394475 3.1014e-06
- CCL4 NA+ 1 0.00043541779 3.99736e-07
- CCL4 CL- 1 0.00602681 2.8505312e-05
- CCL4 CCHL 1 0.0026308693 5.5577088e-06
- CCL4 CLCHL 1 0.0046748042 1.0228004e-05
- CCL4 HCHL 1 0.00031493288 1.807744e-07
- CCL4 SDMSO 1 0.0052712788 1.2782179e-05
- CCL4 CDMSO 1 0.0048798696 1.2859094e-05
- CCL4 ODMSO 1 0.0024441664 2.3897596e-06
- CCL4 CCL4 1 0.0026308693 7.5999462e-06
- CLCL4 O 1 0.0041472796 3.0768825e-06
- CLCL4 OM 1 0.0041472796 3.0768825e-06
- CLCL4 OA 1 0.0041472796 4.01985e-06
- CLCL4 OW 1 0.0044612032 5.7993036e-06
- CLCL4 N 1 0.0043042414 4.6487332e-06
- CLCL4 NT 1 0.0043042414 4.6487332e-06
- CLCL4 NL 1 0.0043042414 4.6487332e-06
- CLCL4 NR 1 0.0043042414 4.6487332e-06
- CLCL4 NZ 1 0.0043042414 4.6487332e-06
- CLCL4 NE 1 0.0043042414 4.6487332e-06
- CLCL4 C 1 0.0042187844 6.5639684e-06
- CLCL4 CH1 1 0.004705366 6.9069956e-06
- CLCL4 CH2 1 0.0059933247 7.7809875e-06
- CLCL4 CH3 1 0.0072184988 8.7750002e-06
- CLCL4 CH4 1 0.010010675 2.0946098e-05
- CLCL4 CR1 1 0.0064833944 1.0312255e-05
- CLCL4 HC 1 0.0008022492 4.395036e-07
- CLCL4 H 1 0 0
- CLCL4 DUM 1 0 0
- CLCL4 S 1 0.0087131239 1.2920691e-05
- CLCL4 CU1+ 1 0.0017832604 2.5580539e-07
- CLCL4 CU2+ 1 0.0017832604 2.5580539e-07
- CLCL4 FE 1 0 0
- CLCL4 ZN2+ 1 0.0017832604 3.4717211e-07
- CLCL4 MG2+ 1 0.00070458408 2.0860342e-07
- CLCL4 CA2+ 1 0.0027642717 2.5216072e-06
- CLCL4 P 1 0.010586201 1.6833345e-05
- CLCL4 AR 1 0.0069019592 1.1212702e-05
- CLCL4 F 1 0.0029927383 3.116545e-06
- CLCL4 CL 1 0.0081637576 1.3974785e-05
- CLCL4 BR 1 0.0029944823 2.8914334e-05
- CLCL4 CMET 1 0.0082152062 1.6317018e-05
- CLCL4 OMET 1 0.0041472796 4.01985e-06
- CLCL4 NA+ 1 0.00074024929 5.18114e-07
- CLCL4 CL- 1 0.010246117 3.6946888e-05
- CLCL4 CCHL 1 0.0044727137 7.2035712e-06
- CLCL4 CLCHL 1 0.0079475863 1.3256929e-05
- CLCL4 HCHL 1 0.00053541414 2.3430902e-07
- CLCL4 SDMSO 1 0.0089616468 1.6567499e-05
- CLCL4 CDMSO 1 0.0082962159 1.6667191e-05
- CLCL4 ODMSO 1 0.0041553021 3.0974642e-06
- CLCL4 CCL4 1 0.0044727137 9.8505978e-06
- CLCL4 CLCL4 1 0.0076040144 1.2767758e-05
+ CChl O 1 0.0024394475 1.7359776e-06
+ CChl OM 1 0.0024394475 1.7359776e-06
+ CChl OA 1 0.0024394475 2.268e-06
+ CChl OW 1 0.0026240987 3.271968e-06
+ CChl N 1 0.0025317731 2.622816e-06
+ CChl NT 1 0.0025317731 2.622816e-06
+ CChl NL 1 0.0025317731 2.622816e-06
+ CChl NR 1 0.0025317731 2.622816e-06
+ CChl NZ 1 0.0025317731 2.622816e-06
+ CChl NE 1 0.0025317731 2.622816e-06
+ CChl C 1 0.002481507 3.703392e-06
+ CChl CH1 1 0.0027677163 3.896928e-06
+ CChl CH2 1 0.0035252992 4.3900343e-06
+ CChl CH3 1 0.0042459518 4.9508565e-06
+ CChl CH4 1 0.0058883216 1.1817792e-05
+ CChl CR1 1 0.0038135602 5.818176e-06
+ CChl HC 1 0.0004718864 2.47968e-07
+ CChl H 1 0 0
+ CChl DUM 1 0 0
+ CChl S 1 0.0051250966 7.289856e-06
+ CChl CU1+ 1 0.0010489214 1.4432544e-07
+ CChl CU2+ 1 0.0010489214 1.4432544e-07
+ CChl FE 1 0 0
+ CChl ZN2+ 1 0.0010489214 1.9587456e-07
+ CChl MG2+ 1 0.00041443936 1.1769408e-07
+ CChl CA2+ 1 0.0016259564 1.4226912e-06
+ CChl P 1 0.0062268488 9.497376e-06
+ CChl AR 1 0.0040597618 6.326208e-06
+ CChl F 1 0.0017603414 1.7583552e-06
+ CChl CL 1 0.004801957 7.884576e-06
+ CChl BR 1 0.0017613673 1.6313472e-05
+ CChl CMet 1 0.0048322193 9.206064e-06
+ CChl OMet 1 0.0024394475 2.268e-06
+ CChl NA+ 1 0.00043541779 2.9232e-07
+ CChl CL- 1 0.00602681 2.084544e-05
+ CChl CChl 1 0.0026308693 4.064256e-06
+ CLChl O 1 0.004334666 3.1947671e-06
+ CLChl OM 1 0.004334666 3.1947671e-06
+ CLChl OA 1 0.004334666 4.1738625e-06
+ CLChl OW 1 0.0046627736 6.0214923e-06
+ CLChl N 1 0.0044987198 4.8268401e-06
+ CLChl NT 1 0.0044987198 4.8268401e-06
+ CLChl NL 1 0.0044987198 4.8268401e-06
+ CLChl NR 1 0.0044987198 4.8268401e-06
+ CLChl NZ 1 0.0044987198 4.8268401e-06
+ CLChl NE 1 0.0044987198 4.8268401e-06
+ CLChl C 1 0.0044094016 6.8154537e-06
+ CLChl CH1 1 0.0049179684 7.1716233e-06
+ CLChl CH2 1 0.0062641209 8.0791004e-06
+ CLChl CH3 1 0.007544652 9.1111968e-06
+ CLChl CH4 1 0.010462987 2.1748606e-05
+ CLChl CR1 1 0.0067763334 1.0707349e-05
+ CLChl HC 1 0.0008384972 4.563423e-07
+ CLChl H 1 0 0
+ CLChl DUM 1 0 0
+ CLChl S 1 0.0091068087 1.3415722e-05
+ CLChl CU1+ 1 0.0018638335 2.6560606e-07
+ CLChl CU2+ 1 0.0018638335 2.6560606e-07
+ CLChl FE 1 0 0
+ CLChl ZN2+ 1 0.0018638335 3.6047332e-07
+ CLChl MG2+ 1 0.00073641928 2.1659564e-07
+ CLChl CA2+ 1 0.0028891697 2.6182176e-06
+ CLChl P 1 0.011064517 1.7478281e-05
+ CLChl AR 1 0.0072138101 1.1642294e-05
+ CLChl F 1 0.0031279591 3.2359492e-06
+ CLChl CL 1 0.0085326204 1.4510201e-05
+ CLChl BR 1 0.0031297819 3.0022129e-05
+ CLChl CMet 1 0.0085863936 1.6942172e-05
+ CLChl OMet 1 0.004334666 4.1738625e-06
+ CLChl NA+ 1 0.00077369595 5.379645e-07
+ CLChl CL- 1 0.010709067 3.8362434e-05
+ CLChl CChl 1 0.0046748042 7.4795616e-06
+ CLChl CLChl 1 0.0083066819 1.3764842e-05
+ HChl O 1 0.0002920184 5.6465771e-08
+ HChl OM 1 0.0002920184 5.6465771e-08
+ HChl OA 1 0.0002920184 7.377075e-08
+ HChl OW 1 0.0003141224 1.064266e-07
+ HChl N 1 0.0003030704 8.5311774e-08
+ HChl NT 1 0.0003030704 8.5311774e-08
+ HChl NL 1 0.0003030704 8.5311774e-08
+ HChl NR 1 0.0003030704 8.5311774e-08
+ HChl NZ 1 0.0003030704 8.5311774e-08
+ HChl NE 1 0.0003030704 8.5311774e-08
+ HChl C 1 0.0002970532 1.2045944e-07
+ HChl CH1 1 0.0003313144 1.2675454e-07
+ HChl CH2 1 0.0004220022 1.4279371e-07
+ HChl CH3 1 0.0005082692 1.6103545e-07
+ HChl CH4 1 0.000704872 3.8439479e-07
+ HChl CR1 1 0.000456509 1.8924656e-07
+ HChl HC 1 5.6488e-05 8.065602e-09
+ HChl H 1 0 0
+ HChl DUM 1 0 0
+ HChl S 1 0.0006135088 2.3711558e-07
+ HChl CU1+ 1 0.000125563 4.6944427e-09
+ HChl CU2+ 1 0.000125563 4.6944427e-09
+ HChl FE 1 0 0
+ HChl ZN2+ 1 0.000125563 6.3711698e-09
+ HChl MG2+ 1 4.96112e-05 3.8282101e-09
+ HChl CA2+ 1 0.000194638 4.6275572e-08
+ HChl P 1 0.000745396 3.0891911e-07
+ HChl AR 1 0.000485981 2.0577121e-07
+ HChl F 1 0.0002107248 5.7193643e-08
+ HChl CL 1 0.0005748268 2.5645991e-07
+ HChl BR 1 0.0002108476 5.3062481e-07
+ HChl CMet 1 0.0005784494 2.9944367e-07
+ HChl OMet 1 0.0002920184 7.377075e-08
+ HChl NA+ 1 5.212246e-05 9.50823e-09
+ HChl CL- 1 0.00072145 6.7803516e-07
+ HChl CChl 1 0.00031493288 1.3219718e-07
+ HChl CLChl 1 0.00055960574 2.432861e-07
+ HChl HChl 1 3.76996e-05 4.2999495e-09
+ SDmso O 1 0.0048877412 3.9925763e-06
+ SDmso OM 1 0.0048877412 3.9925763e-06
+ SDmso OA 1 0.0048877412 5.216175e-06
+ SDmso OW 1 0.0052577132 7.5252018e-06
+ SDmso N 1 0.0050727272 6.0322166e-06
+ SDmso NT 1 0.0050727272 6.0322166e-06
+ SDmso NL 1 0.0050727272 6.0322166e-06
+ SDmso NR 1 0.0050727272 6.0322166e-06
+ SDmso NZ 1 0.0050727272 6.0322166e-06
+ SDmso NE 1 0.0050727272 6.0322166e-06
+ SDmso C 1 0.0049720126 8.5174342e-06
+ SDmso CH1 1 0.0055454692 8.9625478e-06
+ SDmso CH2 1 0.0070633821 1.0096643e-05
+ SDmso CH3 1 0.0085073006 1.1386479e-05
+ SDmso CH4 1 0.011797996 2.7179749e-05
+ SDmso CR1 1 0.0076409495 1.3381228e-05
+ SDmso HC 1 0.000945484 5.703018e-07
+ SDmso H 1 0 0
+ SDmso DUM 1 0 0
+ SDmso S 1 0.010268778 1.6765946e-05
+ SDmso CU1+ 1 0.0021016465 3.3193419e-07
+ SDmso CU2+ 1 0.0021016465 3.3193419e-07
+ SDmso FE 1 0 0
+ SDmso ZN2+ 1 0.0021016465 4.5049206e-07
+ SDmso MG2+ 1 0.0008303816 2.7068471e-07
+ SDmso CA2+ 1 0.003257809 3.2720486e-06
+ SDmso P 1 0.012476278 2.1843023e-05
+ SDmso AR 1 0.0081342455 1.4549651e-05
+ SDmso F 1 0.0035270664 4.0440425e-06
+ SDmso CL 1 0.0096213274 1.8133743e-05
+ SDmso BR 1 0.0035291218 3.7519367e-05
+ SDmso CMet 1 0.0096819617 2.1173034e-05
+ SDmso OMet 1 0.0048877412 5.216175e-06
+ SDmso NA+ 1 0.00087241453 6.72307e-07
+ SDmso CL- 1 0.012075475 4.7942444e-05
+ SDmso CChl 1 0.0052712788 9.3473856e-06
+ SDmso CLChl 1 0.0093665606 1.720225e-05
+ SDmso HChl 1 0.0006310078 3.0404041e-07
+ SDmso SDmso 1 0.010561673 2.149806e-05
+ CDmso O 1 0.0045248108 4.016601e-06
+ CDmso OM 1 0.0045248108 4.016601e-06
+ CDmso OA 1 0.0045248108 5.2475625e-06
+ CDmso OW 1 0.0048673112 7.5704835e-06
+ CDmso N 1 0.004696061 6.0685145e-06
+ CDmso NT 1 0.004696061 6.0685145e-06
+ CDmso NL 1 0.004696061 6.0685145e-06
+ CDmso NR 1 0.004696061 6.0685145e-06
+ CDmso NZ 1 0.004696061 6.0685145e-06
+ CDmso NE 1 0.004696061 6.0685145e-06
+ CDmso C 1 0.0046028248 8.5686865e-06
+ CDmso CH1 1 0.0051337004 9.0164785e-06
+ CDmso CH2 1 0.0065389035 1.0157398e-05
+ CDmso CH3 1 0.0078756064 1.1454995e-05
+ CDmso CH4 1 0.010921957 2.7343299e-05
+ CDmso CR1 1 0.0070735846 1.3461747e-05
+ CDmso HC 1 0.0008752788 5.737335e-07
+ CDmso H 1 0 0
+ CDmso DUM 1 0 0
+ CDmso S 1 0.0095062889 1.6866832e-05
+ CDmso CU1+ 1 0.0019455925 3.3393156e-07
+ CDmso CU2+ 1 0.0019455925 3.3393156e-07
+ CDmso FE 1 0 0
+ CDmso ZN2+ 1 0.0019455925 4.5320282e-07
+ CDmso MG2+ 1 0.00076872312 2.7231351e-07
+ CDmso CA2+ 1 0.0030159063 3.2917377e-06
+ CDmso P 1 0.011549875 2.197446e-05
+ CDmso AR 1 0.0075302519 1.4637201e-05
+ CDmso F 1 0.0032651705 4.0683769e-06
+ CDmso CL 1 0.0089069132 1.824286e-05
+ CDmso BR 1 0.0032670733 3.7745134e-05
+ CDmso CMet 1 0.0089630452 2.1300439e-05
+ CDmso OMet 1 0.0045248108 5.2475625e-06
+ CDmso NA+ 1 0.00080763497 6.763525e-07
+ CDmso CL- 1 0.011178832 4.823093e-05
+ CDmso CChl 1 0.0048798696 9.403632e-06
+ CDmso CLChl 1 0.0086710636 1.7305761e-05
+ CDmso HChl 1 0.00058415346 3.0586992e-07
+ CDmso SDmso 1 0.009777435 2.1627421e-05
+ CDmso CDmso 1 0.0090514293 2.175756e-05
+ ODmso O 1 0.0022663291 7.4645315e-07
+ ODmso OM 1 0.0022663291 7.4645315e-07
+ ODmso OA 1 0.0022663291 9.752175e-07
+ ODmso OW 1 0.0024378763 1.4069138e-06
+ ODmso N 1 0.0023521027 1.1277849e-06
+ ODmso NT 1 0.0023521027 1.1277849e-06
+ ODmso NL 1 0.0023521027 1.1277849e-06
+ ODmso NR 1 0.0023521027 1.1277849e-06
+ ODmso NZ 1 0.0023521027 1.1277849e-06
+ ODmso NE 1 0.0023521027 1.1277849e-06
+ ODmso C 1 0.0023054038 1.5924218e-06
+ ODmso CH1 1 0.0025713019 1.6756404e-06
+ ODmso CH2 1 0.003275122 1.8876712e-06
+ ODmso CH3 1 0.0039446326 2.1288192e-06
+ ODmso CH4 1 0.0054704496 5.0815333e-06
+ ODmso CR1 1 0.0035429262 2.501758e-06
+ ODmso HC 1 0.0004383984 1.0662378e-07
+ ODmso H 1 0 0
+ ODmso DUM 1 0 0
+ ODmso S 1 0.0047613878 3.1345658e-06
+ ODmso CU1+ 1 0.0009744834 6.2058507e-08
+ ODmso CU2+ 1 0.0009744834 6.2058507e-08
+ ODmso FE 1 0 0
+ ODmso ZN2+ 1 0.0009744834 8.4224118e-08
+ ODmso MG2+ 1 0.00038502816 5.0607287e-08
+ ODmso CA2+ 1 0.0015105684 6.117431e-07
+ ODmso P 1 0.0057849528 4.0837775e-06
+ ODmso AR 1 0.0037716558 2.7202067e-06
+ ODmso F 1 0.0016354166 7.5607529e-07
+ ODmso CL 1 0.0044611802 3.3902895e-06
+ ODmso BR 1 0.0016363697 7.0146311e-06
+ ODmso CMet 1 0.0044892949 3.9585162e-06
+ ODmso OMet 1 0.0022663291 9.752175e-07
+ ODmso NA+ 1 0.00040451783 1.256947e-07
+ ODmso CL- 1 0.00559911 8.9633324e-06
+ ODmso CChl 1 0.0024441664 1.7475898e-06
+ ODmso CLChl 1 0.0043430509 3.2161373e-06
+ ODmso HChl 1 0.00029258328 5.6843478e-08
+ ODmso SDmso 1 0.004897196 4.0192831e-06
+ ODmso CDmso 1 0.0045335636 4.0434685e-06
+ ODmso ODmso 1 0.0022707131 7.5144626e-07
+ CCl4 O 1 0.0024394475 2.3738805e-06
+ CCl4 OM 1 0.0024394475 2.3738805e-06
+ CCl4 OA 1 0.0024394475 3.1014e-06
+ CCl4 OW 1 0.0026240987 4.4742864e-06
+ CCl4 N 1 0.0025317731 3.5865968e-06
+ CCl4 NT 1 0.0025317731 3.5865968e-06
+ CCl4 NL 1 0.0025317731 3.5865968e-06
+ CCl4 NR 1 0.0025317731 3.5865968e-06
+ CCl4 NZ 1 0.0025317731 3.5865968e-06
+ CCl4 NE 1 0.0025317731 3.5865968e-06
+ CCl4 C 1 0.002481507 5.0642416e-06
+ CCl4 CH1 1 0.0027677163 5.3288944e-06
+ CCl4 CH2 1 0.0035252992 6.0031978e-06
+ CCl4 CH3 1 0.0042459518 6.7700998e-06
+ CCl4 CH4 1 0.0058883216 1.6160362e-05
+ CCl4 CR1 1 0.0038135602 7.9561248e-06
+ CCl4 HC 1 0.0004718864 3.390864e-07
+ CCl4 H 1 0 0
+ CCl4 DUM 1 0 0
+ CCl4 S 1 0.0051250966 9.9685888e-06
+ CCl4 CU1+ 1 0.0010489214 1.9735931e-07
+ CCl4 CU2+ 1 0.0010489214 1.9735931e-07
+ CCl4 FE 1 0 0
+ CCl4 ZN2+ 1 0.0010489214 2.6785069e-07
+ CCl4 MG2+ 1 0.00041443936 1.6094198e-07
+ CCl4 CA2+ 1 0.0016259564 1.9454738e-06
+ CCl4 P 1 0.0062268488 1.2987285e-05
+ CCl4 AR 1 0.0040597618 8.6508384e-06
+ CCl4 F 1 0.0017603414 2.404481e-06
+ CCl4 CL 1 0.004801957 1.0781845e-05
+ CCl4 BR 1 0.0017613673 2.2308026e-05
+ CCl4 CMet 1 0.0048322193 1.2588927e-05
+ CCl4 OMet 1 0.0024394475 3.1014e-06
+ CCl4 NA+ 1 0.00043541779 3.99736e-07
+ CCl4 CL- 1 0.00602681 2.8505312e-05
+ CCl4 CChl 1 0.0026308693 5.5577088e-06
+ CCl4 CLChl 1 0.0046748042 1.0228004e-05
+ CCl4 HChl 1 0.00031493288 1.807744e-07
+ CCl4 SDmso 1 0.0052712788 1.2782179e-05
+ CCl4 CDmso 1 0.0048798696 1.2859094e-05
+ CCl4 ODmso 1 0.0024441664 2.3897596e-06
+ CCl4 CCl4 1 0.0026308693 7.5999462e-06
+ CLCl4 O 1 0.0041472796 3.0768825e-06
+ CLCl4 OM 1 0.0041472796 3.0768825e-06
+ CLCl4 OA 1 0.0041472796 4.01985e-06
+ CLCl4 OW 1 0.0044612032 5.7993036e-06
+ CLCl4 N 1 0.0043042414 4.6487332e-06
+ CLCl4 NT 1 0.0043042414 4.6487332e-06
+ CLCl4 NL 1 0.0043042414 4.6487332e-06
+ CLCl4 NR 1 0.0043042414 4.6487332e-06
+ CLCl4 NZ 1 0.0043042414 4.6487332e-06
+ CLCl4 NE 1 0.0043042414 4.6487332e-06
+ CLCl4 C 1 0.0042187844 6.5639684e-06
+ CLCl4 CH1 1 0.004705366 6.9069956e-06
+ CLCl4 CH2 1 0.0059933247 7.7809875e-06
+ CLCl4 CH3 1 0.0072184988 8.7750002e-06
+ CLCl4 CH4 1 0.010010675 2.0946098e-05
+ CLCl4 CR1 1 0.0064833944 1.0312255e-05
+ CLCl4 HC 1 0.0008022492 4.395036e-07
+ CLCl4 H 1 0 0
+ CLCl4 DUM 1 0 0
+ CLCl4 S 1 0.0087131239 1.2920691e-05
+ CLCl4 CU1+ 1 0.0017832604 2.5580539e-07
+ CLCl4 CU2+ 1 0.0017832604 2.5580539e-07
+ CLCl4 FE 1 0 0
+ CLCl4 ZN2+ 1 0.0017832604 3.4717211e-07
+ CLCl4 MG2+ 1 0.00070458408 2.0860342e-07
+ CLCl4 CA2+ 1 0.0027642717 2.5216072e-06
+ CLCl4 P 1 0.010586201 1.6833345e-05
+ CLCl4 AR 1 0.0069019592 1.1212702e-05
+ CLCl4 F 1 0.0029927383 3.116545e-06
+ CLCl4 CL 1 0.0081637576 1.3974785e-05
+ CLCl4 BR 1 0.0029944823 2.8914334e-05
+ CLCl4 CMet 1 0.0082152062 1.6317018e-05
+ CLCl4 OMet 1 0.0041472796 4.01985e-06
+ CLCl4 NA+ 1 0.00074024929 5.18114e-07
+ CLCl4 CL- 1 0.010246117 3.6946888e-05
+ CLCl4 CChl 1 0.0044727137 7.2035712e-06
+ CLCl4 CLChl 1 0.0079475863 1.3256929e-05
+ CLCl4 HChl 1 0.00053541414 2.3430902e-07
+ CLCl4 SDmso 1 0.0089616468 1.6567499e-05
+ CLCl4 CDmso 1 0.0082962159 1.6667191e-05
+ CLCl4 ODmso 1 0.0041553021 3.0974642e-06
+ CLCl4 CCl4 1 0.0044727137 9.8505978e-06
+ CLCl4 CLCl4 1 0.0076040144 1.2767758e-05
CH2r O 1 0.0032687988 1.8751283e-06
CH2r OM 1 0.0032687988 1.8751283e-06
CH2r OA 1 0.0032687988 2.4497959e-06
CH2r F 1 0.0023588136 1.8992996e-06
CH2r CL 1 0.0064345026 8.5165795e-06
CH2r BR 1 0.0023601882 1.762111e-05
- CH2r CMET 1 0.0064750533 9.943994e-06
- CH2r OMET 1 0.0032687988 2.4497959e-06
+ CH2r CMet 1 0.0064750533 9.943994e-06
+ CH2r OMet 1 0.0032687988 2.4497959e-06
CH2r NA+ 1 0.00058344897 3.1575148e-07
CH2r CL- 1 0.008075775 2.2516347e-05
- CH2r CCHL 1 0.0035252992 4.3900343e-06
- CH2r CLCHL 1 0.0062641209 8.0791004e-06
- CH2r HCHL 1 0.0004220022 1.4279371e-07
- CH2r SDMSO 1 0.0070633821 1.0096643e-05
- CH2r CDMSO 1 0.0065389035 1.0157398e-05
- CH2r ODMSO 1 0.003275122 1.8876712e-06
- CH2r CCL4 1 0.0035252992 6.0031978e-06
- CH2r CLCL4 1 0.0059933247 7.7809875e-06
+ CH2r CChl 1 0.0035252992 4.3900343e-06
+ CH2r CLChl 1 0.0062641209 8.0791004e-06
+ CH2r HChl 1 0.0004220022 1.4279371e-07
+ CH2r SDmso 1 0.0070633821 1.0096643e-05
+ CH2r CDmso 1 0.0065389035 1.0157398e-05
+ CH2r ODmso 1 0.003275122 1.8876712e-06
+ CH2r CCl4 1 0.0035252992 6.0031978e-06
+ CH2r CLCl4 1 0.0059933247 7.7809875e-06
CH2r CH2r 1 0.0047238129 4.7419261e-06
CH0 O 1 0.0023009528 1.5818407e-06
CH0 OM 1 0.0023009528 1.5818407e-06
CH0 F 1 0.0016604016 1.6022314e-06
CH0 CL 1 0.0045293356 7.184507e-06
CH0 BR 1 0.0016613692 1.4865004e-05
- CH0 CMET 1 0.0045578798 8.3886605e-06
- CH0 OMET 1 0.0023009528 2.066625e-06
+ CH0 CMet 1 0.0045578798 8.3886605e-06
+ CH0 OMet 1 0.0023009528 2.066625e-06
CH0 NA+ 1 0.00041069782 2.66365e-07
CH0 CL- 1 0.00568465 1.899458e-05
- CH0 CCHL 1 0.002481507 3.703392e-06
- CH0 CLCHL 1 0.0044094016 6.8154537e-06
- CH0 HCHL 1 0.0002970532 1.2045944e-07
- CH0 SDMSO 1 0.0049720126 8.5174342e-06
- CH0 CDMSO 1 0.0046028248 8.5686865e-06
- CH0 ODMSO 1 0.0023054038 1.5924218e-06
- CH0 CCL4 1 0.002481507 5.0642416e-06
- CH0 CLCL4 1 0.0042187844 6.5639684e-06
+ CH0 CChl 1 0.002481507 3.703392e-06
+ CH0 CLChl 1 0.0044094016 6.8154537e-06
+ CH0 HChl 1 0.0002970532 1.2045944e-07
+ CH0 SDmso 1 0.0049720126 8.5174342e-06
+ CH0 CDmso 1 0.0046028248 8.5686865e-06
+ CH0 ODmso 1 0.0023054038 1.5924218e-06
+ CH0 CCl4 1 0.002481507 5.0642416e-06
+ CH0 CLCl4 1 0.0042187844 6.5639684e-06
CH0 CH2r 1 0.0033251574 4.0002446e-06
CH0 CH0 1 0.0023406244 3.374569e-06
SI O 1 0.005773784 4.0566421e-06
SI F 1 0.004166448 4.1089342e-06
SI CL 1 0.011365468 1.8424721e-05
SI BR 1 0.004168876 3.8121412e-05
- SI CMET 1 0.011437094 2.1512782e-05
- SI OMET 1 0.005773784 5.299875e-06
+ SI CMet 1 0.011437094 2.1512782e-05
+ SI OMet 1 0.005773784 5.299875e-06
SI NA+ 1 0.0010305646 6.83095e-07
SI CL- 1 0.0142645 4.871174e-05
- SI CCHL 1 0.0062268488 9.497376e-06
- SI CLCHL 1 0.011064517 1.7478281e-05
- SI HCHL 1 0.000745396 3.0891911e-07
- SI SDMSO 1 0.012476278 2.1843023e-05
- SI CDMSO 1 0.011549875 2.197446e-05
- SI ODMSO 1 0.0057849528 4.0837775e-06
- SI CCL4 1 0.0062268488 1.2987285e-05
- SI CLCL4 1 0.010586201 1.6833345e-05
+ SI CChl 1 0.0062268488 9.497376e-06
+ SI CLChl 1 0.011064517 1.7478281e-05
+ SI HChl 1 0.000745396 3.0891911e-07
+ SI SDmso 1 0.012476278 2.1843023e-05
+ SI CDmso 1 0.011549875 2.197446e-05
+ SI ODmso 1 0.0057849528 4.0837775e-06
+ SI CCl4 1 0.0062268488 1.2987285e-05
+ SI CLCl4 1 0.010586201 1.6833345e-05
SI CH2r 1 0.008343822 1.0258657e-05
SI CH0 1 0.005873332 8.654107e-06
SI SI 1 0.01473796 2.2193521e-05
--- /dev/null
+spc SPC simple point charge, recommended
+spce SPC/E extended simple point charge
aminoacids.hdb ffbonded.itp spc.itp \
aminoacids.n.tdb ffnonbonded.itp spce.itp \
aminoacids.rtp forcefield.doc tip3p.itp \
-aminoacids.vsd forcefield.itp tip4p.itp
+aminoacids.vsd forcefield.itp tip4p.itp \
+aminoacids.r2b atomname2type.n2t watermodels.dat
EXTRA_DIST = ${topol_DATA}
ASPH 2
1 1 H N -C CA
1 2 HD2 OD2 CG CB
+ATP 4
+2 3 AH6 AN6 AC6 AC5
+1 2 AH2* AO2* AC2* AC3*
+1 2 AH3* AO3* AC3* AC2*
+1 2 AH3G AO3G APG AO2G
BEN 7
1 1 H2 C2 C1 C3
1 1 H3 C3 C2 C4
CYSH 2
1 1 H N -C CA
1 2 HG SG CB CA
+DADE 3
+1 1 H2 C2 N1 N3
+1 1 H8 C8 N7 N9
+2 3 H6 N6 C6 C5
+DTHY 2
+1 1 H3 N3 C2 C4
+1 1 H6 C6 C5 N1
FAD 7
2 3 HN6 AN6 AC6 AC5
1 2 HO2* AO2* AC2* AC1*
[ replace ]
N NT 14.0067 0.128
CA CH1 13.019 0.188
-CD CH2R 14.027 0.188
+CD CH2r 14.027 0.188
[ add ]
2 4 H N CA C
H 1.008 0.248
--- /dev/null
+; rtp residue to rtp building block table
+;GMX Force-field
+CYS CYSH
+HISD HISA
+HISE HISB
+LYS LYSH
+LYSN LYS
[ atoms ]
N N 0.00000 0
CA CH1 0.00000 1
- CB CH2R 0.00000 1
+ CB CH2r 0.00000 1
CG CH1 0.20800 2
OD1 OA -0.61100 2
HD1 H 0.40300 2
- CD2 CH2R 0.00000 3
+ CD2 CH2r 0.00000 3
C C 0.450 4
O O -0.450 4
[ bonds ]
[ atoms ]
N N 0.00000 0
CA CH1 0.00000 1
- CB CH2R 0.00000 1
- CG CH2R 0.00000 2
- CD CH2R 0.00000 2
+ CB CH2r 0.00000 1
+ CG CH2r 0.00000 2
+ CD CH2r 0.00000 2
C C 0.450 3
O O -0.450 3
[ bonds ]
N7 NR -0.54000 7
C8 C 0.44000 7
H8 HC 0.10000 7
- C2* CH2R 0.00000 8
+ C2* CH2r 0.00000 8
C3* CH1 0.000 8
O3* OA -0.360 9
[ bonds ]
N7 NR -0.54000 8
C8 C 0.44000 8
H8 HC 0.10000 8
- C2* CH2R 0.00000 9
+ C2* CH2r 0.00000 9
C3* CH1 0.000 9
O3* OA -0.360 10
[ bonds ]
H42 H 0.41500 6
C5 C -0.10000 7
H5 HC 0.10000 7
- C2* CH2R 0.00000 8
+ C2* CH2r 0.00000 8
C3* CH1 0.000 8
O3* OA -0.360 9
[ bonds ]
O4 O -0.45000 6
C5 C 0.00000 7
C5M CH3 0.00000 7
- C2* CH2R 0.00000 8
+ C2* CH2r 0.00000 8
C3* CH1 0.000 8
O3* OA -0.360 9
[ bonds ]
OSI OA -0.36000 8
SI2 P 0.54000 8
O5* OA -0.36000 8
- C5* CH2R 0.00000 9
+ C5* CH2r 0.00000 9
C11 CH1 0.00000 10
C111 CH3 0.00000 10
C112 CH3 0.00000 10
AC5* CH2 0.00000 8
AO5* OA -0.36000 9
APA P 0.70500 9
-AO1PA OM -0.63500 9
-AO2PA OM -0.63500 9
-AO3PA OA -0.36000 10
+AO1A OM -0.63500 9
+AO2A OM -0.63500 9
+AO3A OA -0.36000 10
APB P 0.70500 10
-AO1PB OM -0.63500 10
-AO2PB OM -0.63500 10
-AO3PB OA -0.36000 11
+AO1B OM -0.63500 10
+AO2B OM -0.63500 10
+AO3B OA -0.36000 11
APG P 0.63000 11
-AO1PG OM -0.63500 11
-AO2PG OM -0.63500 11
-AO3PG OA -0.54800 11
-AH3PG H 0.39800 11
+AO1G OM -0.63500 11
+AO2G OM -0.63500 11
+AO3G OA -0.54800 11
+AH3G H 0.39800 11
[ bonds ]
AN9 AC4 gb_10
AN9 AC8 gb_10
AO3* AH3* gb_1
AC5* AO5* gb_20
AO5* APA gb_28
- APA AO1PA gb_24
- APA AO2PA gb_24
- APA AO3PA gb_28
-AO3PA APB gb_28
- APB AO1PB gb_24
- APB AO2PB gb_24
- APB AO3PB gb_28
-AO3PB APG gb_28
- APG AO1PG gb_24
- APG AO2PG gb_24
- APG AO3PG gb_28
-AO3PG AH3PG gb_1
+ APA AO1A gb_24
+ APA AO2A gb_24
+ APA AO3A gb_28
+AO3A APB gb_28
+ APB AO1B gb_24
+ APB AO2B gb_24
+ APB AO3B gb_28
+AO3B APG gb_28
+ APG AO1G gb_24
+ APG AO2G gb_24
+ APG AO3G gb_28
+AO3G AH3G gb_1
[ exclusions ]
; ai aj
AN9 AC2
AC6 AC8
AC5 AC1*
AN7 AC1*
-AO3PB AH3PG
-AO1PG AH3PG
-AO2PG AH3PG
+AO3B AH3G
+AO1G AH3G
+AO2G AH3G
[ angles ]
; ai aj ak gromos type
AC4 AN9 AC8 ga_7
AC3* AO3* AH3* ga_12
AC4* AC5* AO5* ga_9
AC5* AO5* APA ga_26
- AO5* APA AO1PA ga_14
- AO5* APA AO2PA ga_14
- AO5* APA AO3PA ga_5
-AO1PA APA AO2PA ga_29
-AO1PA APA AO3PA ga_14
-AO2PA APA AO3PA ga_14
- APA AO3PA APB ga_26
-AO3PA APB AO1PB ga_14
-AO3PA APB AO2PB ga_14
-AO3PA APB AO3PB ga_5
-AO1PB APB AO2PB ga_29
-AO1PB APB AO3PB ga_14
-AO2PB APB AO3PB ga_14
- APB AO3PB APG ga_26
-AO3PB APG AO1PG ga_14
-AO3PB APG AO2PG ga_14
-AO3PB APG AO3PG ga_5
-AO1PG APG AO2PG ga_29
-AO1PG APG AO3PG ga_14
-AO2PG APG AO3PG ga_14
- APG AO3PG AH3PG ga_12
+ AO5* APA AO1A ga_14
+ AO5* APA AO2A ga_14
+ AO5* APA AO3A ga_5
+AO1A APA AO2A ga_29
+AO1A APA AO3A ga_14
+AO2A APA AO3A ga_14
+ APA AO3A APB ga_26
+AO3A APB AO1B ga_14
+AO3A APB AO2B ga_14
+AO3A APB AO3B ga_5
+AO1B APB AO2B ga_29
+AO1B APB AO3B ga_14
+AO2B APB AO3B ga_14
+ APB AO3B APG ga_26
+AO3B APG AO1G ga_14
+AO3B APG AO2G ga_14
+AO3B APG AO3G ga_5
+AO1G APG AO2G ga_29
+AO1G APG AO3G ga_14
+AO2G APG AO3G ga_14
+ APG AO3G AH3G ga_12
[ impropers ]
; ai aj ak al gromos type
AN9 AC4 AC5 AN7 gi_1
AO2* AC2* AC3* AO3* gd_18
AC4* AC3* AO3* AH3* gd_23
AC4* AC5* AO5* APA gd_29
- AC5* AO5* APA AO3PA gd_19
- AC5* AO5* APA AO3PA gd_22
- AO5* APA AO3PA APB gd_19
- AO5* APA AO3PA APB gd_22
- APA AO3PA APB AO3PB gd_19
- APA AO3PA APB AO3PB gd_22
-AO3PA APB AO3PB APG gd_19
-AO3PA APB AO3PB APG gd_22
- APB AO3PB APG AO3PG gd_19
- APB AO3PB APG AO3PG gd_22
-AO3PB APG AO3PG AH3PG gd_19
-AO3PB APG AO3PG AH3PG gd_22
+ AC5* AO5* APA AO3A gd_19
+ AC5* AO5* APA AO3A gd_22
+ AO5* APA AO3A APB gd_19
+ AO5* APA AO3A APB gd_22
+ APA AO3A APB AO3B gd_19
+ APA AO3A APB AO3B gd_22
+AO3A APB AO3B APG gd_19
+AO3A APB AO3B APG gd_22
+ APB AO3B APG AO3G gd_19
+ APB AO3B APG AO3G gd_22
+AO3B APG AO3G AH3G gd_19
+AO3B APG AO3G AH3G gd_22
[ PMB ]
[ atoms ]
C18 CH3 0.00000 0
C17 CH3 0.00000 0
C1 CH0 0.00000 0
- C2 CH2R 0.00000 1
- C3 CH2R 0.00000 1
- C4 CH2R 0.00000 1
+ C2 CH2r 0.00000 1
+ C3 CH2r 0.00000 1
+ C4 CH2r 0.00000 1
C5 C 0.00000 2
C16 CH3 0.00000 2
C6 C 0.00000 2
[ CHCL3 ]
[ atoms ]
- CChl CCHL 0.17900 0
- HChl HCHL 0.08200 0
-CLCh1 CLCHL -0.08700 0
-CLCh2 CLCHL -0.08700 0
-CLCh3 CLCHL -0.08700 0
+ CChl CChl 0.17900 0
+ HChl HChl 0.08200 0
+CLCh1 CLChl -0.08700 0
+CLCh2 CLChl -0.08700 0
+CLCh3 CLChl -0.08700 0
[ bonds ]
CChl CLCh1 gb_40
CChl CLCh2 gb_40
[ DMSO ]
[ atoms ]
-SDmso SDMSO 0.12753 0
-ODmso ODMSO -0.44753 0
-CDms1 CDMSO 0.16000 0
-CDms2 CDMSO 0.16000 0
+SDmso SDmso 0.12753 0
+ODmso ODmso -0.44753 0
+CDms1 CDmso 0.16000 0
+CDms2 CDmso 0.16000 0
[ bonds ]
SDmso ODmso gb_41
SDmso CDms1 gb_42
[ CH3OH ]
[ atoms ]
- Omet OMET -0.67400 0
+ Omet OMet -0.67400 0
HMet H 0.40800 0
- CMet CMET 0.26600 0
+ CMet CMet 0.26600 0
[ bonds ]
Omet HMet gb_1
Omet CMet gb_27
[ CCL4 ]
[ atoms ]
- CCl4 CCL4 0.00000 0
-CLCl1 CLCL4 0.00000 0
-CLCl2 CLCL4 0.00000 0
-CLCl3 CLCL4 0.00000 0
-CLCl4 CLCL4 0.00000 0
+ CCl4 CCl4 0.00000 0
+CLCl1 CLCl4 0.00000 0
+CLCl2 CLCl4 0.00000 0
+CLCl3 CLCl4 0.00000 0
+CLCl4 CLCl4 0.00000 0
[ bonds ]
CCl4 CLCl1 gb_43
CCl4 CLCl2 gb_43
[ UREA ]
[ atoms ]
- OU OUREA -0.39000 0
- CU CUREA 0.14200 0
- N1U NUREA -0.54200 0
+ OU OUrea -0.39000 0
+ CU CUrea 0.14200 0
+ N1U NUrea -0.54200 0
H11U H 0.33300 0
H12U H 0.33300 0
- N2U NUREA -0.54200 0
+ N2U NUrea -0.54200 0
H21U H 0.33300 0
H22U H 0.33300 0
[ bonds ]
; ai aj ak al gromos type
OU CU N1U H11U gd_15
OU CU N2U H21U gd_15
-
-
-
-
CH2 14.02700 ; aliphatic or sugar CH2-group
CH3 15.03500 ; aliphatic CH3-group
CH4 16.04300 ; methane
- CH2R 14.02700 ; CH2-group in a ring
+ CH2r 14.02700 ; CH2-group in a ring
CR1 13.01900 ; aromatic CH-group
HC 1.00800 ; hydrogen bound to carbon
H 1.00800 ; hydrogen not bound to carbon
F 18.99840 ; fluor (non-ionic)
CL 35.45300 ; chlorine (non-ionic)
BR 79.90400 ; bromine (non-ionic)
- CMET 15.035 ; CH3-group in methanol (solvent)
- OMET 15.9994 ; oxygen in methanol (solvent)
+ CMet 15.035 ; CH3-group in methanol (solvent)
+ OMet 15.9994 ; oxygen in methanol (solvent)
NA+ 22.9898 ; sodium (charge 1+)
CL- 35.45300 ; chlorine (charge 1-)
- CCHL 12.011 ; carbon in chloroform (solvent)
-CLCHL 35.453 ; chloride in chloroform (solvent)
- HCHL 1.008 ; hydrogen in chloroform (solvent)
-SDMSO 32.06000 ; DMSO Sulphur (solvent)
-CDMSO 15.03500 ; DMSO Carbon (solvent)
-ODMSO 15.99940 ; DMSO Oxygen (solvent)
- CCL4 12.011 ; carbon in carbontetrachloride (solvent)
-CLCL4 35.453 ; chloride in carbontetrachloride (solvent)
+ CChl 12.011 ; carbon in chloroform (solvent)
+CLChl 35.453 ; chloride in chloroform (solvent)
+ HChl 1.008 ; hydrogen in chloroform (solvent)
+SDmso 32.06000 ; DMSO Sulphur (solvent)
+CDmso 15.03500 ; DMSO Carbon (solvent)
+ODmso 15.99940 ; DMSO Oxygen (solvent)
+ CCl4 12.011 ; carbon in carbontetrachloride (solvent)
+CLCl4 35.453 ; chloride in carbontetrachloride (solvent)
FTFE 18.99840 ; fluor in trifluoroethanol
CTFE 12.01100 ; carbon in trifluoroethanol
CHTFE 14.0270 ; CH2-group in trifluoroethanol
OTFE 15.99940 ; oxygen in trifluoroethanol
-CUREA 12.01100 ; carbon in urea
-OUREA 15.99940 ; oxygen in urea
-NUREA 14.00670 ; nitrogen in urea
+CUrea 12.01100 ; carbon in urea
+OUrea 15.99940 ; oxygen in urea
+NUrea 14.00670 ; nitrogen in urea
SI 28.08 ; silicon
MNH3 0 ; Dummy mass in rigid tetraedrical NH3 group
MW 0 ; Dummy mass in rigid tyrosine rings
--- /dev/null
+spc SPC simple point charge, recommended
+spce SPC/E extended simple point charge
aminoacids.hdb ffbonded.itp spc.itp \
aminoacids.n.tdb ffnonbonded.itp spce.itp \
aminoacids.rtp forcefield.doc tip3p.itp \
-aminoacids.vsd forcefield.itp tip4p.itp
+aminoacids.vsd forcefield.itp tip4p.itp \
+aminoacids.r2b watermodels.dat
EXTRA_DIST = ${topol_DATA}
ASPH 2
1 1 H N -C CA
1 2 HD2 OD2 CG CB
+ATP 4
+2 3 AH6 AN6 AC6 AC5
+1 2 AH2* AO2* AC2* AC3*
+1 2 AH3* AO3* AC3* AC2*
+1 2 AH3G AO3G APG AO2G
BEN 7
1 1 H2 C2 C1 C3
1 1 H3 C3 C2 C4
CYSH 2
1 1 H N -C CA
1 2 HG SG CB CA
+DADE 3
+1 1 H2 C2 N1 N3
+1 1 H8 C8 N7 N9
+2 3 H6 N6 C6 C5
+DTHY 2
+1 1 H3 N3 C2 C4
+1 1 H6 C6 C5 N1
FAD 7
2 3 HN6 AN6 AC6 AC5
1 2 HO2* AO2* AC2* AC1*
[ replace ]
N NT 14.0067 0.128
CA CH1 13.019 0.188
-CD CH2R 14.027 0.188
+CD CH2r 14.027 0.188
[ add ]
2 4 H N CA C
H 1.008 0.248
--- /dev/null
+; rtp residue to rtp building block table
+;GMX Force-field
+CYS CYSH
+HISD HISA
+HISE HISB
+LYS LYSH
+LYSN LYS
[ atoms ]
N N 0.00000 0
CA CH1 0.00000 1
- CB CH2R 0.00000 1
+ CB CH2r 0.00000 1
CG CH1 0.26600 2
OD1 OA -0.67400 2
HD1 H 0.40800 2
- CD2 CH2R 0.00000 3
+ CD2 CH2r 0.00000 3
C C 0.450 4
O O -0.450 4
[ bonds ]
[ atoms ]
N N 0.00000 0
CA CH1 0.00000 1
- CB CH2R 0.00000 1
- CG CH2R 0.00000 2
- CD CH2R 0.00000 2
+ CB CH2r 0.00000 1
+ CG CH2r 0.00000 2
+ CD CH2r 0.00000 2
C C 0.450 3
O O -0.450 3
[ bonds ]
N7 NR -0.54000 7
C8 C 0.44000 7
H8 HC 0.10000 7
- C2* CH2R 0.00000 8
+ C2* CH2r 0.00000 8
C3* CH1 0.000 8
O3* OA -0.360 9
[ bonds ]
N7 NR -0.54000 8
C8 C 0.44000 8
H8 HC 0.10000 8
- C2* CH2R 0.00000 9
+ C2* CH2r 0.00000 9
C3* CH1 0.000 9
O3* OA -0.360 10
[ bonds ]
H42 H 0.41500 6
C5 C -0.10000 7
H5 HC 0.10000 7
- C2* CH2R 0.00000 8
+ C2* CH2r 0.00000 8
C3* CH1 0.000 8
O3* OA -0.360 9
[ bonds ]
O4 O -0.45000 6
C5 C 0.00000 7
C5M CH3 0.00000 7
- C2* CH2R 0.00000 8
+ C2* CH2r 0.00000 8
C3* CH1 0.000 8
O3* OA -0.360 9
[ bonds ]
OSI OA -0.36000 8
SI2 P 0.54000 8
O5* OA -0.36000 8
- C5* CH2R 0.00000 9
+ C5* CH2r 0.00000 9
C11 CH1 0.00000 10
C111 CH3 0.00000 10
C112 CH3 0.00000 10
AC5* CH2 0.00000 8
AO5* OA -0.36000 9
APA P 0.70500 9
-AO1PA OM -0.63500 9
-AO2PA OM -0.63500 9
-AO3PA OA -0.36000 10
+AO1A OM -0.63500 9
+AO2A OM -0.63500 9
+AO3A OA -0.36000 10
APB P 0.70500 10
-AO1PB OM -0.63500 10
-AO2PB OM -0.63500 10
-AO3PB OA -0.36000 11
+AO1B OM -0.63500 10
+AO2B OM -0.63500 10
+AO3B OA -0.36000 11
APG P 0.63000 11
-AO1PG OM -0.63500 11
-AO2PG OM -0.63500 11
-AO3PG OA -0.54800 11
-AH3PG H 0.39800 11
+AO1G OM -0.63500 11
+AO2G OM -0.63500 11
+AO3G OA -0.54800 11
+AH3G H 0.39800 11
[ bonds ]
AN9 AC4 gb_10
AN9 AC8 gb_10
AO3* AH3* gb_1
AC5* AO5* gb_20
AO5* APA gb_28
- APA AO1PA gb_24
- APA AO2PA gb_24
- APA AO3PA gb_28
-AO3PA APB gb_28
- APB AO1PB gb_24
- APB AO2PB gb_24
- APB AO3PB gb_28
-AO3PB APG gb_28
- APG AO1PG gb_24
- APG AO2PG gb_24
- APG AO3PG gb_28
-AO3PG AH3PG gb_1
+ APA AO1A gb_24
+ APA AO2A gb_24
+ APA AO3A gb_28
+AO3A APB gb_28
+ APB AO1B gb_24
+ APB AO2B gb_24
+ APB AO3B gb_28
+AO3B APG gb_28
+ APG AO1G gb_24
+ APG AO2G gb_24
+ APG AO3G gb_28
+AO3G AH3G gb_1
[ exclusions ]
; ai aj
AN9 AC2
AC6 AC8
AC5 AC1*
AN7 AC1*
-AO3PB AH3PG
-AO1PG AH3PG
-AO2PG AH3PG
+AO3B AH3G
+AO1G AH3G
+AO2G AH3G
[ angles ]
; ai aj ak gromos type
AC4 AN9 AC8 ga_7
AC3* AO3* AH3* ga_12
AC4* AC5* AO5* ga_9
AC5* AO5* APA ga_26
- AO5* APA AO1PA ga_14
- AO5* APA AO2PA ga_14
- AO5* APA AO3PA ga_5
-AO1PA APA AO2PA ga_29
-AO1PA APA AO3PA ga_14
-AO2PA APA AO3PA ga_14
- APA AO3PA APB ga_26
-AO3PA APB AO1PB ga_14
-AO3PA APB AO2PB ga_14
-AO3PA APB AO3PB ga_5
-AO1PB APB AO2PB ga_29
-AO1PB APB AO3PB ga_14
-AO2PB APB AO3PB ga_14
- APB AO3PB APG ga_26
-AO3PB APG AO1PG ga_14
-AO3PB APG AO2PG ga_14
-AO3PB APG AO3PG ga_5
-AO1PG APG AO2PG ga_29
-AO1PG APG AO3PG ga_14
-AO2PG APG AO3PG ga_14
- APG AO3PG AH3PG ga_12
+ AO5* APA AO1A ga_14
+ AO5* APA AO2A ga_14
+ AO5* APA AO3A ga_5
+AO1A APA AO2A ga_29
+AO1A APA AO3A ga_14
+AO2A APA AO3A ga_14
+ APA AO3A APB ga_26
+AO3A APB AO1B ga_14
+AO3A APB AO2B ga_14
+AO3A APB AO3B ga_5
+AO1B APB AO2B ga_29
+AO1B APB AO3B ga_14
+AO2B APB AO3B ga_14
+ APB AO3B APG ga_26
+AO3B APG AO1G ga_14
+AO3B APG AO2G ga_14
+AO3B APG AO3G ga_5
+AO1G APG AO2G ga_29
+AO1G APG AO3G ga_14
+AO2G APG AO3G ga_14
+ APG AO3G AH3G ga_12
[ impropers ]
; ai aj ak al gromos type
AN9 AC4 AC5 AN7 gi_1
AO2* AC2* AC3* AO3* gd_18
AC4* AC3* AO3* AH3* gd_23
AC4* AC5* AO5* APA gd_29
- AC5* AO5* APA AO3PA gd_19
- AC5* AO5* APA AO3PA gd_22
- AO5* APA AO3PA APB gd_19
- AO5* APA AO3PA APB gd_22
- APA AO3PA APB AO3PB gd_19
- APA AO3PA APB AO3PB gd_22
-AO3PA APB AO3PB APG gd_19
-AO3PA APB AO3PB APG gd_22
- APB AO3PB APG AO3PG gd_19
- APB AO3PB APG AO3PG gd_22
-AO3PB APG AO3PG AH3PG gd_19
-AO3PB APG AO3PG AH3PG gd_22
+ AC5* AO5* APA AO3A gd_19
+ AC5* AO5* APA AO3A gd_22
+ AO5* APA AO3A APB gd_19
+ AO5* APA AO3A APB gd_22
+ APA AO3A APB AO3B gd_19
+ APA AO3A APB AO3B gd_22
+AO3A APB AO3B APG gd_19
+AO3A APB AO3B APG gd_22
+ APB AO3B APG AO3G gd_19
+ APB AO3B APG AO3G gd_22
+AO3B APG AO3G AH3G gd_19
+AO3B APG AO3G AH3G gd_22
[ PMB ]
[ atoms ]
C18 CH3 0.00000 0
C17 CH3 0.00000 0
C1 CH0 0.00000 0
- C2 CH2R 0.00000 1
- C3 CH2R 0.00000 1
- C4 CH2R 0.00000 1
+ C2 CH2r 0.00000 1
+ C3 CH2r 0.00000 1
+ C4 CH2r 0.00000 1
C5 C 0.00000 2
C16 CH3 0.00000 2
C6 C 0.00000 2
[ CHCL3 ]
[ atoms ]
- CChl CCHL 0.17900 0
- HChl HCHL 0.08200 0
-CLCh1 CLCHL -0.08700 0
-CLCh2 CLCHL -0.08700 0
-CLCh3 CLCHL -0.08700 0
+ CChl CChl 0.17900 0
+ HChl HChl 0.08200 0
+CLCh1 CLChl -0.08700 0
+CLCh2 CLChl -0.08700 0
+CLCh3 CLChl -0.08700 0
[ bonds ]
CChl CLCh1 gb_40
CChl CLCh2 gb_40
[ DMSO ]
[ atoms ]
-SDmso SDMSO 0.12753 0
-ODmso ODMSO -0.44753 0
-CDms1 CDMSO 0.16000 0
-CDms2 CDMSO 0.16000 0
+SDmso SDmso 0.12753 0
+ODmso ODmso -0.44753 0
+CDms1 CDmso 0.16000 0
+CDms2 CDmso 0.16000 0
[ bonds ]
SDmso ODmso gb_41
SDmso CDms1 gb_42
[ CH3OH ]
[ atoms ]
- Omet OMET -0.67400 0
+ Omet OMet -0.67400 0
HMet H 0.40800 0
- CMet CMET 0.26600 0
+ CMet CMet 0.26600 0
[ bonds ]
Omet HMet gb_1
Omet CMet gb_27
[ CCL4 ]
[ atoms ]
- CCl4 CCL4 0.00000 0
-CLCl1 CLCL4 0.00000 0
-CLCl2 CLCL4 0.00000 0
-CLCl3 CLCL4 0.00000 0
-CLCl4 CLCL4 0.00000 0
+ CCl4 CCl4 0.00000 0
+CLCl1 CLCl4 0.00000 0
+CLCl2 CLCl4 0.00000 0
+CLCl3 CLCl4 0.00000 0
+CLCl4 CLCl4 0.00000 0
[ bonds ]
CCl4 CLCl1 gb_43
CCl4 CLCl2 gb_43
[ UREA ]
[ atoms ]
- OU OUREA -0.39000 0
- CU CUREA 0.14200 0
- N1U NUREA -0.54200 0
+ OU OUrea -0.39000 0
+ CU CUrea 0.14200 0
+ N1U NUrea -0.54200 0
H11U H 0.33300 0
H12U H 0.33300 0
- N2U NUREA -0.54200 0
+ N2U NUrea -0.54200 0
H21U H 0.33300 0
H22U H 0.33300 0
[ bonds ]
; ai aj ak al gromos type
OU CU N1U H11U gd_15
OU CU N2U H21U gd_15
-
CH2 14.02700 ; aliphatic or sugar CH2-group
CH3 15.03500 ; aliphatic CH3-group
CH4 16.04300 ; methane
- CH2R 14.02700 ; CH2-group in a ring
+ CH2r 14.02700 ; CH2-group in a ring
CR1 13.01900 ; aromatic CH-group
HC 1.00800 ; hydrogen bound to carbon
H 1.00800 ; hydrogen not bound to carbon
F 18.99840 ; fluor (non-ionic)
CL 35.45300 ; chlorine (non-ionic)
BR 79.90400 ; bromine (non-ionic)
- CMET 15.035 ; CH3-group in methanol (solvent)
- OMET 15.9994 ; oxygen in methanol (solvent)
+ CMet 15.035 ; CH3-group in methanol (solvent)
+ OMet 15.9994 ; oxygen in methanol (solvent)
NA+ 22.9898 ; sodium (charge 1+)
CL- 35.45300 ; chlorine (charge 1-)
- CCHL 12.011 ; carbon in chloroform (solvent)
-CLCHL 35.453 ; chloride in chloroform (solvent)
- HCHL 1.008 ; hydrogen in chloroform (solvent)
-SDMSO 32.06000 ; DMSO Sulphur (solvent)
-CDMSO 15.03500 ; DMSO Carbon (solvent)
-ODMSO 15.99940 ; DMSO Oxygen (solvent)
- CCL4 12.011 ; carbon in carbontetrachloride (solvent)
-CLCL4 35.453 ; chloride in carbontetrachloride (solvent)
+ CChl 12.011 ; carbon in chloroform (solvent)
+CLChl 35.453 ; chloride in chloroform (solvent)
+ HChl 1.008 ; hydrogen in chloroform (solvent)
+SDmso 32.06000 ; DMSO Sulphur (solvent)
+CDmso 15.03500 ; DMSO Carbon (solvent)
+ODmso 15.99940 ; DMSO Oxygen (solvent)
+ CCl4 12.011 ; carbon in carbontetrachloride (solvent)
+CLCl4 35.453 ; chloride in carbontetrachloride (solvent)
FTFE 18.99840 ; fluor in trifluoroethanol
CTFE 12.01100 ; carbon in trifluoroethanol
CHTFE 14.0270 ; CH2-group in trifluoroethanol
OTFE 15.99940 ; oxygen in trifluoroethanol
-CUREA 12.01100 ; carbon in urea
-OUREA 15.99940 ; oxygen in urea
-NUREA 14.00670 ; nitrogen in urea
+CUrea 12.01100 ; carbon in urea
+OUrea 15.99940 ; oxygen in urea
+NUrea 14.00670 ; nitrogen in urea
SI 28.08 ; silicon
MNH3 0 ; Dummy mass in rigid tetraedrical NH3 group
MW 0 ; Dummy mass in rigid tyrosine rings
--- /dev/null
+spc SPC simple point charge, recommended
+spce SPC/E extended simple point charge
-357
+363
��ߦ��ߨ���߬�����������ߦ��߷���ߋ��߶�ߦ�����������������߶��
�߳���ߋ��߳���߫���ߨ���߫������������
�����߽����߲�߷������ײ��������
�������������ߖ�ߞ��ߋ���ߘ����������ߥ�����
�߳���ߦ���߶ߨ���ߴ���ߦ��߳��������ߖ�߹��������
������߶ߌ���ߑ�����ߜ������߈���ߚ����������ײ�����߽�����
+����ߖ�ߞߗ����������ߗ��ߒ�����ߖ�ߞߘ������߭�������
+���ߖ�،ߙ�����߈���ߗ�������ߞ��ߗ�������ߐ�ߜ���������ײ�������
+��ߖ�߈����؋ߙ��ߝ��ߓ����߈�؛ߗ���ߑ�ߓ���ߞ�ߞ�����ߪ��������
+�����،ߑ�߈��߆��ߜ��ߍ���ߐ�ߞ�ߚ���������������߸��������
+�ߓ���ߋ�߈����ߋ���߶ߙ���ߓ���߶ߛ�ߌ�������������������
+���߶ߗ���ߚ���������ߓ�����ߋ���ߚ���������ߚ�������߯������
aminoacids.n.tdb ffnonbonded.itp spce.itp \
aminoacids.rtp forcefield.doc tip3p.itp \
aminoacids.vsd forcefield.itp tip4p.itp \
-tip5p.itp
+aminoacids.r2b tip5p.itp \
+methanol.itp ethanol.itp 1propanol.itp \
+atomname2type.n2t watermodels.dat
EXTRA_DIST = ${topol_DATA}
--- /dev/null
+; rtp residue to rtp building block table
+;GMX Force-field
+CYS CYSH
+HISD HISA
+HISE HISB
+LYS LYSH
+LYSN LYS
OW HW2
[ HO4 ]
-; TIP4P For software reasons, the MW particle should be called HW as well
+; TIP4P
[ atoms ]
OW opls_113 0.00 0
HW1 opls_114 0.52 0
HW2 opls_114 0.52 0
- HW3 opls_115 -1.04 0
+ MW opls_115 -1.04 0
[ bonds ]
OW HW1
OW HW2
-; Superfluous bonds are necessary to make pdb2gmx happy
- OW HW3
[ HO5 ]
-; TIP5P. For software reasons, the lone pairs should be called HW as well
+; TIP5P
[ atoms ]
+ OW opls_118 0.00 0
HW1 opls_119 0.248 0
HW2 opls_119 0.248 0
- HW3 opls_120 -0.248 0
- HW4 opls_120 -0.248 0
- OW opls_118 0.00 0
+ LP1 opls_120 -0.248 0
+ LP2 opls_120 -0.248 0
[ bonds ]
OW HW1
OW HW2
-; Superfluous bonds are necessary to make pdb2gmx happy
- OW HW3
- OW HW4
[ ILE ]
[ atoms ]
;[ atoms ]
; id at type res nr residu name at name cg nr charge mass
-;1 CU1+ 1 CU1+ CU1+ 1 1 63.54600
+;1 Cu1+ 1 CU1+ CU1+ 1 1 63.54600
[ moleculetype ]
; molname nrexcl
[ atoms ]
; id at type res nr residu name at name cg nr charge mass
-1 CU2+ 1 CU2+ CU 1 2 63.54600
+1 Cu2+ 1 CU2+ CU 1 2 63.54600
[ moleculetype ]
; molname nrexcl
[ atoms ]
; id at type res nr residu name at name cg nr charge mass
-1 ZN2+ 1 ZN2+ ZN 1 2 65.37000
+1 Zn2+ 1 ZN2+ ZN 1 2 65.37000
[ moleculetype ]
; molname nrexcl
--- /dev/null
+tip4p TIP4P TIP 4-point, recommended
+tip3p TIP3P TIP 3-point
+tip5p TIP5P TIP 5-point
+spc SPC simple point charge
+spce SPC/E extended simple point charge
--- /dev/null
+; atom protons mass a1 ... a4 b1 ... b4 c
+H 1 1 0.489918 0.262003 0.196767 0.049879 20.6593 7.74039 49.5519 2.20159 0.001305
+C 6 12 2.26069 1.56165 1.05075 0.839259 22.6907 0.656665 9.75618 55.5949 0.286977
+N 7 14 12.2126 3.13220 2.01250 1.16630 0.005700 9.89330 28.9975 0.582600 -11.529
+O 8 16 3.04850 2.28680 1.54630 0.867000 13.2771 5.70110 0.323900 32.9089 0.250800
+; Na+
+Na 11 23 3.25650 3.93620 1.39980 1.00320 2.66710 6.11530 0.200100 14.0390 0.404000
-7
+8
CYS SG 1 CYS SG 1 0.2 CYS2 CYS2
-CYS SG 1 HEME FE 2 0.25 CYS2 HEME
-CYS SG 1 HEME CAB 1 0.18 CYS2 HEME
-CYS SG 1 HEME CAC 1 0.18 CYS2 HEME
-HIS NE2 1 HEME FE 1 0.2 HIS1 HEME
-MET SD 1 HEME FE 1 0.24 MET HEME
+CYS SG 1 HEM FE 2 0.25 CYS2 HEME
+CYS SG 1 HEM CAB 1 0.18 CYS2 HEME
+CYS SG 1 HEM CAC 1 0.18 CYS2 HEME
+HIS NE2 1 HEM FE 1 0.2 HIS1 HEME
+MET SD 1 HEM FE 1 0.24 MET HEME
+CO C 1 HEME FE 1 0.19 CO HEME
CYM SG 1 CYM SG 1 0.2 CYS2 CYS2
+++ /dev/null
-Urea in Water
- 1359
- 1UREA C1 1 2.064 2.162 0.280 -0.4650 0.0606 0.2278
- 1UREA O2 2 2.163 2.120 0.339 -0.2571 0.2847 0.0448
- 1UREA N3 3 2.055 2.285 0.229 -0.4005 0.0556 0.2068
- 1UREA H4 4 1.965 2.301 0.188 -0.8661 -2.6785 -0.2199
- 1UREA H5 5 2.136 2.342 0.212 -0.3718 -0.2607 -0.8675
- 1UREA N6 6 1.951 2.093 0.285 -0.3042 -0.1600 0.7702
- 1UREA H7 7 1.866 2.125 0.244 -0.6232 -1.5225 0.2764
- 1UREA H8 8 1.958 1.999 0.320 0.3294 -1.7268 -2.7089
- 2UREA C1 9 0.167 0.191 0.530 0.0983 -0.1688 0.0345
- 2UREA O2 10 0.159 0.146 0.416 0.5368 -0.4096 0.1001
- 2UREA N3 11 0.062 0.195 0.612 -0.5603 0.4575 -0.7968
- 2UREA H4 12 0.069 0.227 0.707 0.2921 0.7131 -0.9302
- 2UREA H5 13 -0.016 0.143 0.580 -0.3093 -1.5769 1.3454
- 2UREA N6 14 0.277 0.242 0.583 0.0141 0.0396 0.0062
- 2UREA H7 15 0.277 0.268 0.680 -0.0828 -0.3800 0.1180
- 2UREA H8 16 0.366 0.253 0.539 -0.1339 1.0311 -0.0945
- 3UREA C1 17 0.401 0.363 1.599 0.0438 -0.4272 -0.6386
- 3UREA O2 18 0.376 0.471 1.654 0.1157 -0.6359 -0.1975
- 3UREA N3 19 0.495 0.274 1.629 -0.5239 -0.6346 0.6527
- 3UREA H4 20 0.505 0.187 1.581 -0.5933 -1.2504 1.7041
- 3UREA H5 21 0.555 0.308 1.701 -0.0123 -1.0919 0.4514
- 3UREA N6 22 0.324 0.328 1.496 0.2039 0.1564 -0.9623
- 3UREA H7 23 0.346 0.245 1.445 2.6996 0.2525 -0.2885
- 3UREA H8 24 0.249 0.389 1.471 0.9474 2.6180 1.6525
- 4UREA C1 25 0.218 1.264 0.022 -0.2106 0.0426 0.4113
- 4UREA O2 26 0.256 1.374 -0.018 0.1956 -0.2117 0.0906
- 4UREA N3 27 0.155 1.246 0.137 -0.2782 0.2926 0.4134
- 4UREA H4 28 0.126 1.156 0.170 -0.6101 -0.0633 -0.7796
- 4UREA H5 29 0.141 1.331 0.190 -3.6948 -0.5115 1.3318
- 4UREA N6 30 0.229 1.148 -0.042 0.1029 0.2261 0.1346
- 4UREA H7 31 0.205 1.069 0.013 0.3946 1.0280 1.5092
- 4UREA H8 32 0.274 1.143 -0.132 -1.6874 0.2737 -0.8433
- 5UREA C1 33 2.034 1.257 1.120 -0.1680 -0.1874 -0.0922
- 5UREA O2 34 2.061 1.280 1.237 -0.6452 -0.3566 0.0490
- 5UREA N3 35 2.008 1.355 1.033 0.0869 0.1603 0.2214
- 5UREA H4 36 1.995 1.328 0.938 0.6695 -1.9052 0.6197
- 5UREA H5 37 1.997 1.450 1.062 -0.2994 0.0623 0.3918
- 5UREA N6 38 2.049 1.143 1.053 0.1157 -0.4936 0.4833
- 5UREA H7 39 2.039 1.134 0.954 2.7407 2.4361 -0.3746
- 5UREA H8 40 2.074 1.056 1.095 -0.9621 -1.4199 -0.6256
- 6UREA C1 41 1.989 1.236 2.099 0.0429 0.3060 -0.1219
- 6UREA O2 42 1.877 1.227 2.050 -0.0277 -0.5495 0.1701
- 6UREA N3 43 2.098 1.239 2.022 0.2637 -0.0759 0.1747
- 6UREA H4 44 2.187 1.231 2.066 -0.2713 0.3313 1.3962
- 6UREA H5 45 2.090 1.233 1.922 3.3377 -1.5648 -0.1985
- 6UREA N6 46 2.016 1.238 2.229 -0.1897 -0.4980 -0.0472
- 6UREA H7 47 2.109 1.245 2.267 -0.4690 2.5818 0.6047
- 6UREA H8 48 1.943 1.227 2.295 1.3030 -1.1995 1.6554
- 7UREA C1 49 0.348 2.034 1.498 0.2413 -0.0896 -0.3558
- 7UREA O2 50 0.247 2.099 1.471 0.1987 0.0591 0.1642
- 7UREA N3 51 0.469 2.087 1.505 0.2687 -0.1864 -0.1161
- 7UREA H4 52 0.545 2.025 1.524 0.3918 -0.5757 -1.6391
- 7UREA H5 53 0.485 2.185 1.492 1.1916 -0.0741 1.4450
- 7UREA N6 54 0.351 1.903 1.521 -0.0363 -0.0224 0.0794
- 7UREA H7 55 0.439 1.856 1.526 0.4840 0.8435 -0.4435
- 7UREA H8 56 0.267 1.851 1.507 0.3409 -0.2119 -2.4760
- 8UREA C1 57 0.205 0.249 0.875 0.3450 0.1296 -0.2939
- 8UREA O2 58 0.275 0.151 0.898 0.1974 0.0884 -0.0311
- 8UREA N3 59 0.262 0.366 0.849 -0.1763 0.4807 0.1098
- 8UREA H4 60 0.212 0.451 0.834 -0.8074 -0.1014 -1.6341
- 8UREA H5 61 0.361 0.368 0.862 -0.2868 2.5315 1.4500
- 8UREA N6 62 0.073 0.264 0.880 0.2063 -0.8997 -0.4616
- 8UREA H7 63 0.034 0.356 0.869 1.3777 -0.1582 0.9508
- 8UREA H8 64 0.006 0.192 0.901 -1.3853 0.9596 1.9008
- 9UREA C1 65 0.099 0.270 1.223 0.2068 -0.5778 -0.2992
- 9UREA O2 66 0.062 0.208 1.323 -0.5278 0.0380 -0.1778
- 9UREA N3 67 0.016 0.341 1.147 -0.0125 0.1579 0.5901
- 9UREA H4 68 0.053 0.379 1.063 2.6711 1.0516 1.9574
- 9UREA H5 69 -0.077 0.357 1.179 0.7286 0.8750 2.7265
- 9UREA N6 70 0.222 0.262 1.173 0.4045 0.7461 -0.0794
- 9UREA H7 71 0.239 0.313 1.088 0.4322 -0.5091 -0.8692
- 9UREA H8 72 0.289 0.202 1.217 -0.3249 1.0049 1.5188
- 10UREA C1 73 1.118 0.017 0.342 0.5081 0.2347 0.4064
- 10UREA O2 74 1.116 -0.103 0.371 -0.6670 0.2135 0.3519
- 10UREA N3 75 1.153 0.111 0.429 0.9963 -0.0251 0.4908
- 10UREA H4 76 1.139 0.206 0.401 1.3134 -0.1232 -0.0202
- 10UREA H5 77 1.181 0.088 0.523 1.2712 1.6107 0.8608
- 10UREA N6 78 1.078 0.072 0.228 0.3354 -0.5199 0.0906
- 10UREA H7 79 1.080 0.172 0.224 -3.4543 -0.0769 1.4901
- 10UREA H8 80 1.036 0.016 0.157 0.4889 0.9607 -1.3159
- 11UREA C1 81 0.555 0.298 0.690 -0.0695 -0.2672 0.6581
- 11UREA O2 82 0.549 0.412 0.736 -0.8313 -0.2064 0.4314
- 11UREA N3 83 0.563 0.186 0.761 0.0289 -0.5415 0.2218
- 11UREA H4 84 0.576 0.101 0.711 -0.2934 -0.5958 0.2299
- 11UREA H5 85 0.562 0.186 0.861 0.1100 -0.2916 0.2226
- 11UREA N6 86 0.555 0.257 0.564 0.7632 -0.4538 0.7114
- 11UREA H7 87 0.562 0.158 0.546 -0.4278 -0.6991 1.3735
- 11UREA H8 88 0.550 0.337 0.505 -2.3069 0.4940 1.8783
- 12UREA C1 89 1.440 0.502 2.032 0.5946 -0.0894 -0.0316
- 12UREA O2 90 1.413 0.621 2.049 0.6755 -0.1381 0.4560
- 12UREA N3 91 1.537 0.439 2.098 0.5566 0.7615 0.8774
- 12UREA H4 92 1.553 0.341 2.093 0.2406 0.7369 0.1021
- 12UREA H5 93 1.601 0.494 2.153 0.4968 0.4427 1.2707
- 12UREA N6 94 1.376 0.425 1.946 0.1510 0.0857 0.1386
- 12UREA H7 95 1.408 0.333 1.925 -1.1785 -0.3339 -0.2617
- 12UREA H8 96 1.301 0.458 1.888 -0.0991 -1.4242 -0.5026
- 13UREA C1 97 0.082 1.477 0.314 -0.5786 0.1348 0.7407
- 13UREA O2 98 0.184 1.532 0.355 -0.4595 0.1711 0.3880
- 13UREA N3 99 0.011 1.502 0.204 0.4205 0.7252 0.2052
- 13UREA H4 100 -0.074 1.453 0.184 -0.1520 1.9096 -0.4902
- 13UREA H5 101 0.052 1.574 0.148 2.2960 -0.5806 -0.2978
- 13UREA N6 102 0.023 1.375 0.375 0.1201 -0.4880 0.4035
- 13UREA H7 103 -0.060 1.336 0.333 -0.9967 1.6940 0.2923
- 13UREA H8 104 0.057 1.347 0.464 1.1155 1.5920 0.7861
- 14UREA C1 105 0.273 1.146 1.109 -0.5012 1.1106 0.1718
- 14UREA O2 106 0.391 1.117 1.095 -0.7096 0.1478 0.2466
- 14UREA N3 107 0.208 1.210 1.013 -0.7813 -0.1478 -0.5189
- 14UREA H4 108 0.111 1.226 1.031 -1.0566 -0.6962 -1.3970
- 14UREA H5 109 0.252 1.231 0.926 -0.5105 -1.0271 -0.6098
- 14UREA N6 110 0.198 1.115 1.214 -0.3501 0.4732 0.0963
- 14UREA H7 111 0.104 1.151 1.214 0.3195 2.7519 -2.1684
- 14UREA H8 112 0.226 1.046 1.282 -1.9315 -0.6326 -0.2415
- 15UREA C1 113 0.176 0.952 0.165 -0.0183 -0.2643 -0.0280
- 15UREA O2 114 0.274 0.951 0.240 0.1793 -0.0663 -0.2858
- 15UREA N3 115 0.058 1.002 0.203 -0.0326 -0.0486 -0.3607
- 15UREA H4 116 -0.014 0.998 0.134 -1.4965 -0.1565 1.0770
- 15UREA H5 117 0.043 1.026 0.299 1.4645 -1.5387 0.3562
- 15UREA N6 118 0.174 0.912 0.039 -0.1581 0.1921 -0.1712
- 15UREA H7 119 0.085 0.915 -0.008 -0.3640 1.5833 0.2421
- 15UREA H8 120 0.258 0.872 0.001 0.0202 -1.7285 1.8591
- 16UREA C1 121 0.388 0.050 1.428 -0.0281 -0.4258 -0.0360
- 16UREA O2 122 0.371 0.051 1.306 0.5764 -1.4654 -0.1524
- 16UREA N3 123 0.505 0.020 1.482 -0.2057 -0.4693 0.3187
- 16UREA H4 124 0.521 0.012 1.581 1.0287 2.0535 0.4795
- 16UREA H5 125 0.580 -0.005 1.421 -0.8996 -0.1185 -0.7194
- 16UREA N6 126 0.283 0.061 1.509 -0.1120 -0.2418 -0.1742
- 16UREA H7 127 0.296 0.046 1.607 -0.1843 -0.0627 -0.1376
- 16UREA H8 128 0.196 0.079 1.465 -1.4646 1.6291 2.6349
- 17UREA C1 129 0.538 0.408 1.225 0.2909 0.2067 0.1129
- 17UREA O2 130 0.602 0.306 1.251 -0.2862 -0.3064 -0.4372
- 17UREA N3 131 0.428 0.444 1.290 0.2432 0.9291 -0.3434
- 17UREA H4 132 0.365 0.515 1.259 -1.8819 -1.2772 -1.8642
- 17UREA H5 133 0.397 0.391 1.369 0.1444 0.3373 -0.7677
- 17UREA N6 134 0.567 0.484 1.120 -0.1428 -0.1387 -0.2668
- 17UREA H7 135 0.513 0.564 1.094 2.2287 2.0974 0.6590
- 17UREA H8 136 0.644 0.454 1.063 -0.2267 -0.9354 0.0222
- 18UREA C1 137 0.583 1.835 1.334 0.1384 -0.6704 -0.2682
- 18UREA O2 138 0.513 1.849 1.235 0.1027 0.1719 -0.1368
- 18UREA N3 139 0.670 1.926 1.378 -0.5293 -0.1591 0.0257
- 18UREA H4 140 0.710 1.906 1.467 -2.5556 -1.0981 0.8381
- 18UREA H5 141 0.698 2.009 1.330 1.2855 -0.8668 -0.3127
- 18UREA N6 142 0.582 1.739 1.426 -0.2007 -0.2148 0.2123
- 18UREA H7 143 0.636 1.741 1.510 0.1350 1.7098 0.0378
- 18UREA H8 144 0.510 1.670 1.414 -0.4262 -0.2113 1.3099
- 19UREA C1 145 1.458 0.079 0.017 -0.2251 -0.1139 0.0351
- 19UREA O2 146 1.524 -0.018 -0.021 0.4561 0.2979 0.1351
- 19UREA N3 147 1.325 0.084 0.019 -0.2213 -0.1803 0.1315
- 19UREA H4 148 1.279 0.167 0.052 -0.2967 -0.1262 -0.1077
- 19UREA H5 149 1.270 0.010 -0.018 1.5078 -0.6488 -1.8657
- 19UREA N6 150 1.513 0.189 0.066 0.4248 -0.3584 -0.1309
- 19UREA H7 151 1.460 0.268 0.096 0.2108 -0.1797 -0.9333
- 19UREA H8 152 1.612 0.198 0.078 0.2026 0.7291 1.4927
- 20UREA C1 153 1.399 2.106 0.175 -0.1416 -0.3775 -0.0524
- 20UREA O2 154 1.448 1.996 0.148 0.4884 -0.1421 0.1294
- 20UREA N3 155 1.283 2.156 0.133 -0.2464 -0.4447 0.1591
- 20UREA H4 156 1.256 2.246 0.168 -1.1025 0.7361 -2.9494
- 20UREA H5 157 1.228 2.111 0.063 -0.0438 -1.8789 0.8520
- 20UREA N6 158 1.449 2.178 0.275 -0.2684 -0.4113 0.0334
- 20UREA H7 159 1.411 2.267 0.302 1.7028 0.4066 0.4202
- 20UREA H8 160 1.528 2.141 0.323 0.3079 -2.4204 -2.1370
- 21UREA C1 161 1.490 0.100 0.396 0.3276 0.3532 -0.0637
- 21UREA O2 162 1.466 0.122 0.515 -0.6284 -0.2335 -0.1207
- 21UREA N3 163 1.609 0.080 0.341 0.2239 -0.7119 0.0541
- 21UREA H4 164 1.607 0.058 0.244 -0.0124 -0.1108 -0.0859
- 21UREA H5 165 1.691 0.087 0.398 -0.6948 0.8593 1.3690
- 21UREA N6 166 1.391 0.077 0.309 0.1306 -0.4338 0.3570
- 21UREA H7 167 1.416 0.064 0.213 0.5914 1.7255 0.0858
- 21UREA H8 168 1.297 0.092 0.339 0.3225 0.2939 0.6227
- 22UREA C1 169 0.713 1.373 1.278 -0.0643 0.3239 0.3268
- 22UREA O2 170 0.830 1.354 1.244 -0.0851 0.6551 0.0584
- 22UREA N3 171 0.665 1.325 1.392 -0.5575 0.0089 -0.0116
- 22UREA H4 172 0.570 1.332 1.423 -0.8158 1.4311 -0.9603
- 22UREA H5 173 0.732 1.278 1.449 -0.7796 0.7326 0.8886
- 22UREA N6 174 0.625 1.432 1.197 0.1775 0.3224 0.0620
- 22UREA H7 175 0.534 1.436 1.239 0.6484 0.2133 1.1480
- 22UREA H8 176 0.646 1.458 1.103 -3.0616 -1.3798 -1.4787
- 23UREA C1 177 0.338 1.443 1.298 0.1045 -0.0176 -0.1666
- 23UREA O2 178 0.361 1.546 1.361 -0.2015 -0.0400 -0.0195
- 23UREA N3 179 0.367 1.424 1.169 0.9974 -0.4045 0.0775
- 23UREA H4 180 0.342 1.336 1.128 -1.7944 0.1097 0.2402
- 23UREA H5 181 0.395 1.501 1.111 0.7723 -0.7302 -0.4760
- 23UREA N6 182 0.303 1.327 1.353 -0.7390 0.1130 -0.3981
- 23UREA H7 183 0.298 1.243 1.300 2.1458 0.1505 -1.0642
- 23UREA H8 184 0.286 1.326 1.452 -0.1028 -1.2467 -0.2617
- 24UREA C1 185 1.285 0.377 0.163 -0.4787 -0.2963 0.1334
- 24UREA O2 186 1.224 0.342 0.264 0.1287 -0.3070 0.5057
- 24UREA N3 187 1.409 0.424 0.150 -0.5721 -0.2675 -0.7214
- 24UREA H4 188 1.442 0.444 0.058 -0.8303 1.2360 -0.5328
- 24UREA H5 189 1.473 0.438 0.226 0.2558 -0.2812 -1.3971
- 24UREA N6 190 1.243 0.352 0.040 -0.0288 -0.3923 -0.0009
- 24UREA H7 191 1.301 0.360 -0.042 1.3183 -0.7497 0.8625
- 24UREA H8 192 1.147 0.326 0.031 0.1965 -1.3027 0.0102
- 25UREA C1 193 1.376 1.648 2.255 -0.6907 -0.4421 -0.7514
- 25UREA O2 194 1.403 1.535 2.297 0.0921 -0.0933 -0.2763
- 25UREA N3 195 1.438 1.707 2.154 0.3416 0.0015 0.1005
- 25UREA H4 196 1.394 1.795 2.134 -2.9647 -1.6544 -1.5488
- 25UREA H5 197 1.513 1.673 2.098 0.1185 1.9069 -1.6034
- 25UREA N6 198 1.284 1.731 2.304 0.0279 -0.0491 -0.0210
- 25UREA H7 199 1.291 1.823 2.266 -0.9542 0.7545 1.5598
- 25UREA H8 200 1.215 1.701 2.370 -1.7648 0.3428 -1.5492
- 26UREA C1 201 0.859 1.550 1.635 -0.5593 0.2451 -0.2114
- 26UREA O2 202 0.822 1.505 1.743 0.0306 0.1169 -0.0605
- 26UREA N3 203 0.795 1.530 1.520 -1.0750 -0.4070 0.1807
- 26UREA H4 204 0.828 1.588 1.445 -0.8907 2.4922 2.1675
- 26UREA H5 205 0.714 1.471 1.513 -0.4582 -1.5175 1.5399
- 26UREA N6 206 0.960 1.631 1.605 -0.3275 0.0530 0.0636
- 26UREA H7 207 0.982 1.650 1.510 0.7139 -0.5561 0.1518
- 26UREA H8 208 1.019 1.668 1.678 -0.8031 -0.8196 0.9389
- 27UREA C1 209 0.692 1.868 1.656 -0.0551 -0.0375 -0.3605
- 27UREA O2 210 0.621 1.776 1.696 -0.1985 0.2444 0.0195
- 27UREA N3 211 0.810 1.853 1.597 0.0932 -0.1518 -0.0378
- 27UREA H4 212 0.865 1.932 1.569 -1.2599 1.3391 1.1276
- 27UREA H5 213 0.843 1.759 1.600 0.4398 -0.0209 1.1842
- 27UREA N6 214 0.665 1.997 1.675 0.0013 -0.1211 0.3388
- 27UREA H7 215 0.737 2.060 1.645 0.3102 -0.7814 -0.3964
- 27UREA H8 216 0.588 2.029 1.730 1.4019 1.5887 1.5104
- 28UREA C1 217 1.813 0.194 2.277 -0.8408 -0.2550 -0.1465
- 28UREA O2 218 1.813 0.073 2.301 -0.3760 -0.0594 0.9275
- 28UREA N3 219 1.832 0.254 2.160 0.1502 -0.4181 -0.0871
- 28UREA H4 220 1.839 0.354 2.169 0.3852 -0.4432 0.0011
- 28UREA H5 221 1.849 0.205 2.075 1.6456 0.9279 -0.6616
- 28UREA N6 222 1.806 0.286 2.373 -0.1819 0.1118 -0.4358
- 28UREA H7 223 1.812 0.384 2.357 0.5354 0.1103 -0.2060
- 28UREA H8 224 1.793 0.245 2.464 0.1703 -0.8162 -0.7780
- 29UREA C1 225 2.119 0.576 0.852 0.0619 -0.0750 0.3217
- 29UREA O2 226 2.216 0.644 0.884 -0.2779 0.5126 0.1315
- 29UREA N3 227 2.096 0.548 0.724 -0.0374 -0.1307 0.3541
- 29UREA H4 228 2.022 0.491 0.688 0.4829 -0.2711 -0.5429
- 29UREA H5 229 2.159 0.583 0.655 -1.7691 1.5190 -0.5997
- 29UREA N6 230 2.027 0.527 0.935 -0.3471 0.4707 0.1945
- 29UREA H7 231 1.951 0.475 0.896 0.5739 0.7644 -2.3635
- 29UREA H8 232 2.020 0.553 1.031 -0.6526 0.0312 0.3004
- 30UREA C1 233 1.871 2.422 0.497 0.0733 0.1212 0.2477
- 30UREA O2 234 1.798 2.483 0.575 0.4038 0.1728 0.5130
- 30UREA N3 235 1.854 2.292 0.472 -0.7050 0.2915 -0.1604
- 30UREA H4 236 1.917 2.237 0.417 -1.1849 -0.7880 0.3225
- 30UREA H5 237 1.782 2.246 0.524 -0.2046 0.4489 0.7074
- 30UREA N6 238 1.963 2.470 0.414 0.0230 -0.4127 -0.1244
- 30UREA H7 239 2.000 2.406 0.346 -0.2719 1.0844 -1.8590
- 30UREA H8 240 2.001 2.562 0.423 1.5041 -1.0422 0.7618
- 31UREA C1 241 1.602 1.646 1.932 0.2359 -0.8253 -0.7757
- 31UREA O2 242 1.652 1.730 1.857 0.3008 -0.4832 -0.3511
- 31UREA N3 243 1.492 1.575 1.908 -0.2758 -0.3384 0.0501
- 31UREA H4 244 1.466 1.501 1.970 -1.7057 -1.2389 -1.4706
- 31UREA H5 245 1.440 1.579 1.823 -1.1696 -1.0037 0.5388
- 31UREA N6 246 1.646 1.598 2.048 0.0741 0.0541 -0.3368
- 31UREA H7 247 1.602 1.523 2.097 2.4627 -1.6243 -0.4067
- 31UREA H8 248 1.734 1.632 2.082 0.8369 -1.2316 -0.8742
- 32UREA C1 249 2.012 1.235 0.746 0.4389 -0.0053 -0.3284
- 32UREA O2 250 2.122 1.274 0.708 0.4715 -0.2622 -0.4864
- 32UREA N3 251 1.989 1.115 0.799 -0.1305 0.1034 -0.3245
- 32UREA H4 252 1.898 1.086 0.829 0.6402 -2.9182 -0.2379
- 32UREA H5 253 2.061 1.046 0.807 -1.3798 -1.1500 1.4260
- 32UREA N6 254 1.902 1.309 0.750 0.4299 -0.0402 0.1964
- 32UREA H7 255 1.823 1.254 0.775 1.6014 -2.9159 -1.3724
- 32UREA H8 256 1.891 1.403 0.718 -0.7665 -0.0687 0.4331
- 33UREA C1 257 1.699 1.119 0.897 -0.0659 0.2408 -0.3564
- 33UREA O2 258 1.657 1.068 0.793 -0.1955 -0.1364 -0.1179
- 33UREA N3 259 1.779 1.063 0.988 -0.2076 0.1924 -0.2680
- 33UREA H4 260 1.811 1.120 1.064 -3.6030 3.7815 -0.8789
- 33UREA H5 261 1.801 0.967 0.972 -2.5911 -0.5105 -0.1194
- 33UREA N6 262 1.680 1.248 0.925 -0.2439 0.1166 0.1183
- 33UREA H7 263 1.727 1.288 1.003 0.2559 -0.2234 -0.0052
- 33UREA H8 264 1.623 1.308 0.869 -0.8899 1.1235 1.7191
- 34UREA C1 265 0.408 2.105 1.832 -0.3120 -0.3477 0.4870
- 34UREA O2 266 0.458 2.127 1.942 -0.1389 -0.0323 0.3445
- 34UREA N3 267 0.413 1.985 1.775 0.0798 -0.1921 0.1899
- 34UREA H4 268 0.363 1.967 1.690 -1.2837 -1.7554 1.1984
- 34UREA H5 269 0.458 1.907 1.817 0.0783 -1.1999 -1.4948
- 34UREA N6 270 0.331 2.198 1.776 0.4552 0.2939 0.4669
- 34UREA H7 271 0.288 2.183 1.687 -0.7269 2.0682 0.6273
- 34UREA H8 272 0.323 2.284 1.827 1.3287 -0.5485 2.1844
- 35UREA C1 273 0.932 1.699 1.302 0.1059 -0.1106 0.2001
- 35UREA O2 274 1.032 1.627 1.301 -0.1649 -0.4919 -0.5403
- 35UREA N3 275 0.926 1.831 1.322 0.2087 -0.0989 0.1419
- 35UREA H4 276 0.838 1.877 1.312 -0.3922 -1.2579 -0.3006
- 35UREA H5 277 1.005 1.888 1.345 -0.3880 0.8261 -0.0348
- 35UREA N6 278 0.809 1.656 1.280 0.1034 0.2423 -0.4757
- 35UREA H7 279 0.731 1.719 1.278 0.9377 1.3297 -0.3655
- 35UREA H8 280 0.801 1.559 1.256 1.4904 0.4401 -2.0915
- 36UREA C1 281 0.222 0.140 1.795 0.1610 0.3188 0.6518
- 36UREA O2 282 0.179 0.071 1.888 -0.4847 -0.2438 -0.0306
- 36UREA N3 283 0.158 0.222 1.711 -0.0812 -0.0915 0.4367
- 36UREA H4 284 0.220 0.265 1.646 -0.0213 -0.3257 0.3413
- 36UREA H5 285 0.060 0.236 1.725 -0.0183 0.4559 0.3246
- 36UREA N6 286 0.352 0.138 1.772 0.1435 0.6162 0.5479
- 36UREA H7 287 0.393 0.205 1.709 1.2107 -0.5493 -0.0808
- 36UREA H8 288 0.407 0.081 1.833 -0.3036 -0.9673 -0.4106
- 37SOL OW1 289 1.136 2.323 1.304 0.2852 -0.1304 0.0570
- 37SOL HW2 290 1.060 2.294 1.246 0.1913 -1.2496 0.6873
- 37SOL HW3 291 1.216 2.342 1.246 -0.5225 1.4410 -0.6434
- 38SOL OW1 292 1.279 0.655 1.176 0.4893 -0.4584 -0.2208
- 38SOL HW2 293 1.370 0.680 1.209 0.3788 1.4105 -1.0905
- 38SOL HW3 294 1.215 0.652 1.253 1.1825 -1.5270 0.3609
- 39SOL OW1 295 0.543 1.032 0.553 0.8937 -0.7904 0.8949
- 39SOL HW2 296 0.614 1.101 0.544 -0.5228 0.6580 -0.4457
- 39SOL HW3 297 0.481 1.038 0.475 -0.4963 -2.2289 1.7724
- 40SOL OW1 298 1.217 2.050 0.538 0.0832 0.0469 -0.3454
- 40SOL HW2 299 1.158 1.987 0.588 -0.2242 1.8167 1.8503
- 40SOL HW3 300 1.165 2.130 0.511 1.0529 0.7934 -0.1150
- 41SOL OW1 301 0.688 0.538 1.456 0.4113 -0.3396 0.8565
- 41SOL HW2 302 0.629 0.498 1.386 0.3574 -0.5495 1.0247
- 41SOL HW3 303 0.650 0.627 1.484 -0.9163 -1.2591 2.3074
- 42SOL OW1 304 0.201 2.097 0.941 0.2877 -0.1872 0.5003
- 42SOL HW2 305 0.152 2.012 0.924 2.8847 -1.6217 -1.0097
- 42SOL HW3 306 0.271 2.081 1.011 0.8365 0.7174 0.1789
- 43SOL OW1 307 0.648 1.255 0.806 0.3362 0.3229 0.0646
- 43SOL HW2 308 0.708 1.248 0.885 -0.5740 -1.8875 0.7044
- 43SOL HW3 309 0.631 1.352 0.785 0.6408 1.0421 2.5416
- 44SOL OW1 310 1.693 0.340 1.825 0.3183 0.4511 -0.6230
- 44SOL HW2 311 1.766 0.395 1.867 1.1778 -0.7657 -0.4089
- 44SOL HW3 312 1.661 0.272 1.890 0.9468 -0.7973 -1.5403
- 45SOL OW1 313 0.045 0.532 1.727 -0.1219 0.2634 -0.0246
- 45SOL HW2 314 0.056 0.454 1.665 0.9923 0.0810 0.3757
- 45SOL HW3 315 0.007 0.500 1.814 -3.3184 0.7235 -0.9784
- 46SOL OW1 316 0.901 1.456 0.347 0.0768 -0.2592 0.1823
- 46SOL HW2 317 0.903 1.513 0.429 2.4089 -1.5030 1.1868
- 46SOL HW3 318 0.946 1.369 0.366 0.6032 -0.7108 -2.3848
- 47SOL OW1 319 1.896 1.940 1.100 -0.0326 0.0491 -0.1439
- 47SOL HW2 320 1.942 2.029 1.092 3.1787 -1.2245 0.9262
- 47SOL HW3 321 1.834 1.942 1.179 0.0103 1.2886 -0.0943
- 48SOL OW1 322 0.923 0.703 1.433 0.0107 0.5393 0.0515
- 48SOL HW2 323 0.854 0.634 1.409 -1.5172 1.8332 0.4146
- 48SOL HW3 324 0.939 0.762 1.354 1.9175 -0.5499 -0.5280
- 49SOL OW1 325 1.205 1.647 0.408 -0.6089 -0.3297 -0.5753
- 49SOL HW2 326 1.218 1.614 0.501 0.4658 -0.5659 -0.7919
- 49SOL HW3 327 1.263 1.727 0.393 -0.2170 -0.7238 -1.2472
- 50SOL OW1 328 0.467 0.782 1.801 0.4096 0.2902 -0.0173
- 50SOL HW2 329 0.515 0.697 1.782 0.8423 0.1732 1.3581
- 50SOL HW3 330 0.532 0.858 1.801 0.1874 0.4803 -0.3396
- 51SOL OW1 331 1.306 2.093 1.188 -0.6197 0.5462 0.3714
- 51SOL HW2 332 1.252 2.013 1.164 0.9211 -1.2484 2.1510
- 51SOL HW3 333 1.341 2.137 1.105 -1.6843 -0.4767 -0.6860
- 52SOL OW1 334 1.348 1.320 1.728 0.0665 0.8787 0.8488
- 52SOL HW2 335 1.264 1.367 1.755 -0.2613 0.4745 0.5424
- 52SOL HW3 336 1.339 1.287 1.634 0.1759 -0.0250 1.1409
- 53SOL OW1 337 0.601 1.152 0.206 0.1153 -0.4701 -0.3625
- 53SOL HW2 338 0.559 1.139 0.116 0.2079 -1.9711 -0.2417
- 53SOL HW3 339 0.529 1.153 0.276 0.0772 0.2762 -0.4008
- 54SOL OW1 340 0.404 1.902 0.971 -0.5022 -0.0578 0.1164
- 54SOL HW2 341 0.458 1.881 1.053 -0.0405 -1.3755 -0.4525
- 54SOL HW3 342 0.364 1.817 0.935 -1.6317 0.6496 -0.4065
- 55SOL OW1 343 0.929 0.697 1.699 0.1497 -0.2624 -0.0693
- 55SOL HW2 344 0.939 0.790 1.732 -1.7633 -0.4624 1.4718
- 55SOL HW3 345 0.924 0.697 1.599 -0.4661 1.4132 -0.1009
- 56SOL OW1 346 0.355 2.118 1.192 -0.3272 -0.0244 -0.5704
- 56SOL HW2 347 0.409 2.054 1.245 -1.8039 -1.0670 -0.2191
- 56SOL HW3 348 0.343 2.203 1.243 0.4024 -0.0293 -0.3825
- 57SOL OW1 349 0.009 1.476 1.832 -0.1854 0.0519 -0.2116
- 57SOL HW2 350 -0.070 1.535 1.812 -0.5299 0.6623 2.2750
- 57SOL HW3 351 0.019 1.467 1.931 1.5958 -1.8401 -0.4377
- 58SOL OW1 352 1.134 1.091 1.824 -0.0734 -0.0629 -0.0441
- 58SOL HW2 353 1.165 1.035 1.901 -0.5898 -2.3558 -1.3287
- 58SOL HW3 354 1.070 1.161 1.857 0.4756 -0.2723 1.6762
- 59SOL OW1 355 1.699 0.638 0.430 -0.1132 0.4388 -0.7596
- 59SOL HW2 356 1.662 0.657 0.521 -0.7402 -1.1923 -0.6195
- 59SOL HW3 357 1.798 0.645 0.432 -0.1647 1.3611 -0.2245
- 60SOL OW1 358 1.376 2.113 1.696 -0.5818 0.0101 0.3984
- 60SOL HW2 359 1.459 2.164 1.674 -0.7394 0.7839 1.4313
- 60SOL HW3 360 1.396 2.043 1.764 -0.4207 -1.2366 -0.8326
- 61SOL OW1 361 1.208 0.760 1.814 -0.0553 -0.3885 0.3323
- 61SOL HW2 362 1.115 0.786 1.842 0.4481 0.1673 1.6820
- 61SOL HW3 363 1.215 0.660 1.808 -0.3840 -0.5425 1.8021
- 62SOL OW1 364 1.192 1.196 0.439 0.9122 -0.0313 -0.3822
- 62SOL HW2 365 1.259 1.122 0.438 0.2801 -0.6438 -1.7278
- 62SOL HW3 366 1.221 1.267 0.374 -0.4253 -1.0871 -2.3528
- 63SOL OW1 367 1.516 0.309 1.185 -0.3898 0.8760 -0.1257
- 63SOL HW2 368 1.480 0.360 1.107 0.6799 1.3744 -0.3119
- 63SOL HW3 369 1.550 0.372 1.254 -0.5582 0.4226 0.3892
- 64SOL OW1 370 1.033 1.287 1.489 -0.0249 0.2306 0.7473
- 64SOL HW2 371 1.060 1.200 1.529 1.0482 0.2191 0.0786
- 64SOL HW3 372 1.114 1.340 1.467 -0.5268 0.3893 -1.0206
- 65SOL OW1 373 1.738 1.000 1.911 -0.1312 -0.1774 0.0370
- 65SOL HW2 374 1.651 1.050 1.908 0.5773 1.1947 0.4243
- 65SOL HW3 375 1.809 1.055 1.866 0.9007 -0.3743 1.3003
- 66SOL OW1 376 1.133 0.677 0.588 0.3763 0.1991 -0.2947
- 66SOL HW2 377 1.076 0.652 0.510 -0.3388 1.5659 -0.2579
- 66SOL HW3 378 1.099 0.632 0.670 0.2804 -0.1577 -0.5291
- 67SOL OW1 379 1.671 1.986 0.398 -0.0629 -0.2553 -0.3510
- 67SOL HW2 380 1.689 1.900 0.352 -0.5491 -0.3315 -0.4045
- 67SOL HW3 381 1.735 1.998 0.474 -0.8091 -1.3140 0.5071
- 68SOL OW1 382 1.098 1.114 0.968 0.2296 0.3056 -0.0984
- 68SOL HW2 383 1.056 1.076 0.885 0.0947 -1.2135 0.6155
- 68SOL HW3 384 1.076 1.056 1.046 2.0704 0.5151 0.6519
- 69SOL OW1 385 1.388 2.229 0.930 -0.4170 0.3929 -0.1630
- 69SOL HW2 386 1.332 2.165 0.878 -2.0355 1.5280 0.0322
- 69SOL HW3 387 1.482 2.194 0.936 -1.2514 -2.1860 0.3904
- 70SOL OW1 388 0.340 0.728 1.494 -0.3584 0.2725 0.0880
- 70SOL HW2 389 0.428 0.686 1.473 -0.3132 -0.0415 0.8393
- 70SOL HW3 390 0.266 0.675 1.453 -0.1987 0.7439 -0.8557
- 71SOL OW1 391 0.143 2.330 1.109 -0.1806 -0.0610 0.0267
- 71SOL HW2 392 0.150 2.428 1.127 -0.1789 0.1907 -1.1654
- 71SOL HW3 393 0.159 2.313 1.012 0.1806 -1.2961 0.2695
- 72SOL OW1 394 1.388 1.068 0.675 0.0979 0.9826 -0.4781
- 72SOL HW2 395 1.437 1.016 0.605 1.9188 -0.6478 1.7117
- 72SOL HW3 396 1.289 1.052 0.666 0.4382 -1.8462 -0.8594
- 73SOL OW1 397 0.400 1.005 0.782 0.6828 -0.0037 -0.3761
- 73SOL HW2 398 0.455 1.020 0.864 -0.0446 1.1738 -0.0571
- 73SOL HW3 399 0.449 1.037 0.701 0.6024 0.8055 -0.1209
- 74SOL OW1 400 0.655 2.126 1.122 -0.1484 0.0100 0.4334
- 74SOL HW2 401 0.556 2.133 1.108 -0.2797 -0.1070 1.2197
- 74SOL HW3 402 0.687 2.206 1.172 0.4386 0.8074 -1.0980
- 75SOL OW1 403 1.261 1.685 0.686 0.9478 -0.0452 -0.2167
- 75SOL HW2 404 1.260 1.585 0.679 -0.1131 -0.0829 0.1553
- 75SOL HW3 405 1.317 1.712 0.764 2.0297 -0.2691 -0.8743
- 76SOL OW1 406 0.137 1.782 1.714 -0.8370 0.4849 0.0414
- 76SOL HW2 407 0.101 1.751 1.626 -0.4785 -0.4963 0.2221
- 76SOL HW3 408 0.107 1.876 1.731 -1.6185 0.3980 -0.7329
- 77SOL OW1 409 1.740 0.494 0.938 -0.0261 0.4504 0.2175
- 77SOL HW2 410 1.756 0.484 0.840 -1.5662 -0.3010 -0.0257
- 77SOL HW3 411 1.645 0.519 0.954 -0.2195 -0.8201 1.5289
- 78SOL OW1 412 0.940 0.201 1.027 0.6233 0.6970 -0.3180
- 78SOL HW2 413 0.950 0.250 1.113 -0.2948 0.9349 -0.3301
- 78SOL HW3 414 0.997 0.119 1.028 -0.9453 -0.5645 1.4685
- 79SOL OW1 415 1.052 1.041 0.682 0.3380 -0.4574 -0.3096
- 79SOL HW2 416 0.977 0.975 0.690 -1.5081 1.2352 -1.6186
- 79SOL HW3 417 1.072 1.057 0.586 -0.6621 2.0477 -0.2716
- 80SOL OW1 418 2.027 0.675 1.196 -0.5905 -0.8219 -0.3636
- 80SOL HW2 419 1.957 0.700 1.128 -0.9854 -0.0162 0.3035
- 80SOL HW3 420 1.984 0.625 1.271 -0.9505 1.2143 0.9712
- 81SOL OW1 421 0.977 0.314 0.008 -0.8585 -0.3282 0.0532
- 81SOL HW2 422 1.001 0.275 -0.081 2.7404 -2.6490 1.5980
- 81SOL HW3 423 0.936 0.404 -0.006 -2.0059 -1.0456 -3.8075
- 82SOL OW1 424 1.199 0.665 0.215 0.5635 0.0376 0.0445
- 82SOL HW2 425 1.277 0.608 0.239 -1.6912 -3.6087 0.3920
- 82SOL HW3 426 1.127 0.653 0.283 -1.1287 1.0835 -1.3868
- 83SOL OW1 427 0.978 1.806 2.091 0.0463 0.0392 0.0319
- 83SOL HW2 428 0.926 1.781 2.172 0.8820 -1.3259 0.2121
- 83SOL HW3 429 1.030 1.727 2.059 -0.8704 0.2296 -2.3565
- 84SOL OW1 430 0.482 1.093 1.536 0.1634 0.3943 -0.1332
- 84SOL HW2 431 0.411 1.135 1.593 -0.5340 0.8577 -1.2851
- 84SOL HW3 432 0.554 1.056 1.595 -0.4865 0.8802 1.0329
- 85SOL OW1 433 0.840 2.006 1.949 0.2471 -0.3957 0.1918
- 85SOL HW2 434 0.809 1.958 2.032 0.8465 -1.6771 -0.2660
- 85SOL HW3 435 0.902 1.946 1.898 1.3027 1.0197 -0.3047
- 86SOL OW1 436 1.926 0.136 0.903 -0.0629 0.3100 -0.5335
- 86SOL HW2 437 1.917 0.051 0.851 1.7082 -1.4419 1.6066
- 86SOL HW3 438 1.842 0.152 0.955 -1.1735 1.1430 -2.3708
- 87SOL OW1 439 0.709 1.682 0.009 0.1085 -0.0412 -0.1992
- 87SOL HW2 440 0.714 1.691 -0.090 -2.3892 -0.3615 -0.4814
- 87SOL HW3 441 0.771 1.610 0.039 1.8354 0.8637 -1.2672
- 88SOL OW1 442 1.227 2.334 1.567 0.4275 0.0392 -0.2805
- 88SOL HW2 443 1.179 2.304 1.484 0.4090 -1.5305 0.2379
- 88SOL HW3 444 1.309 2.278 1.579 -0.3833 -0.9087 1.5383
- 89SOL OW1 445 2.091 0.753 1.557 -0.4029 -0.4395 0.2535
- 89SOL HW2 446 2.117 0.671 1.608 2.4658 -0.4839 -0.8823
- 89SOL HW3 447 2.163 0.822 1.568 -0.3322 0.1060 -2.4041
- 90SOL OW1 448 0.826 1.253 1.638 0.0780 -0.2117 0.3012
- 90SOL HW2 449 0.911 1.274 1.589 0.2874 0.2151 0.8341
- 90SOL HW3 450 0.772 1.336 1.648 -0.7071 -0.5929 -0.5648
- 91SOL OW1 451 1.732 1.190 0.502 -0.3850 0.2543 -0.2455
- 91SOL HW2 452 1.647 1.242 0.507 -0.4100 0.2043 -0.1871
- 91SOL HW3 453 1.713 1.093 0.510 -0.2593 0.2818 0.5556
- 92SOL OW1 454 1.589 0.408 0.368 -0.0289 0.5768 0.0586
- 92SOL HW2 455 1.626 0.345 0.436 2.3402 0.3968 -1.1661
- 92SOL HW3 456 1.630 0.499 0.381 1.0059 0.3901 -1.3442
- 93SOL OW1 457 0.434 1.727 1.888 -0.4139 0.4027 0.6709
- 93SOL HW2 458 0.437 1.647 1.949 0.0183 -0.5331 -0.4929
- 93SOL HW3 459 0.425 1.696 1.793 -1.4520 1.8077 0.2500
- 94SOL OW1 460 0.117 0.952 0.818 0.3802 -0.3300 -0.2416
- 94SOL HW2 461 0.215 0.960 0.802 0.5260 -1.0043 0.2051
- 94SOL HW3 462 0.102 0.915 0.910 -0.3007 0.0226 -0.2033
- 95SOL OW1 463 1.745 0.872 1.299 0.2360 0.2454 0.2302
- 95SOL HW2 464 1.800 0.953 1.319 0.9130 -0.3560 0.9305
- 95SOL HW3 465 1.743 0.857 1.200 1.1832 0.4069 0.1642
- 96SOL OW1 466 0.969 1.631 0.126 0.2485 0.2280 0.0868
- 96SOL HW2 467 0.941 1.578 0.206 1.2333 0.2168 0.4467
- 96SOL HW3 468 1.017 1.570 0.062 -2.8046 -0.4916 -1.9320
- 97SOL OW1 469 1.606 2.235 1.807 -0.2479 -0.2295 0.3422
- 97SOL HW2 470 1.658 2.168 1.755 1.4497 0.8729 0.4719
- 97SOL HW3 471 1.565 2.190 1.887 1.0330 -1.0970 0.5764
- 98SOL OW1 472 0.868 0.099 1.839 -0.4913 -0.1475 0.3648
- 98SOL HW2 473 0.807 0.097 1.918 -3.3226 1.6097 -1.4183
- 98SOL HW3 474 0.925 0.181 1.842 -0.8614 0.1080 0.4576
- 99SOL OW1 475 0.103 0.686 0.279 -0.1883 -0.1939 -0.5779
- 99SOL HW2 476 0.127 0.624 0.354 -3.5269 -0.3742 0.6934
- 99SOL HW3 477 0.074 0.774 0.317 -1.4352 -0.0878 -1.6727
- 100SOL OW1 478 1.834 1.993 0.608 -0.2685 -0.1676 -0.2770
- 100SOL HW2 479 1.929 1.971 0.589 0.4409 2.1449 -0.0633
- 100SOL HW3 480 1.807 1.951 0.695 0.1483 -1.6956 -0.8263
- 101SOL OW1 481 1.899 1.670 0.003 -0.0441 -0.5134 0.0147
- 101SOL HW2 482 1.961 1.722 0.061 -0.4384 -0.4639 0.3974
- 101SOL HW3 483 1.948 1.635 -0.076 0.1118 0.8932 -0.5487
- 102SOL OW1 484 0.636 0.867 0.138 0.2646 0.1758 -0.0169
- 102SOL HW2 485 0.629 0.959 0.099 1.9946 0.5852 0.4478
- 102SOL HW3 486 0.548 0.821 0.132 -0.0784 0.8316 -2.7463
- 103SOL OW1 487 0.541 0.315 0.142 0.0964 0.7028 -0.0473
- 103SOL HW2 488 0.620 0.287 0.197 -0.2978 0.3988 0.3800
- 103SOL HW3 489 0.459 0.268 0.176 -0.1150 0.2897 -1.0796
- 104SOL OW1 490 1.076 0.027 2.052 0.2989 -0.3802 0.3914
- 104SOL HW2 491 1.140 -0.028 1.998 1.8610 -0.2656 1.9810
- 104SOL HW3 492 1.050 0.108 2.000 1.3656 -0.4924 -0.3771
- 105SOL OW1 493 0.750 0.390 0.935 0.6192 0.4486 -0.1025
- 105SOL HW2 494 0.820 0.319 0.945 0.7898 -0.0293 -2.9244
- 105SOL HW3 495 0.677 0.356 0.875 -1.4485 1.4118 1.6289
- 106SOL OW1 496 1.694 1.540 1.111 -0.4080 -0.2525 -0.0177
- 106SOL HW2 497 1.739 1.592 1.184 0.4869 -1.2645 0.2206
- 106SOL HW3 498 1.668 1.601 1.037 1.5190 0.4597 -0.2222
- 107SOL OW1 499 1.589 0.373 0.675 0.0431 -0.2324 -0.3412
- 107SOL HW2 500 1.524 0.346 0.605 1.1474 -1.9280 -0.8147
- 107SOL HW3 501 1.582 0.311 0.754 -0.4761 1.0199 0.6715
- 108SOL OW1 502 0.281 1.693 0.025 -0.0806 0.3256 -0.0739
- 108SOL HW2 503 0.251 1.767 -0.034 0.1403 1.3766 1.0549
- 108SOL HW3 504 0.335 1.628 -0.028 0.3225 1.3368 -0.9687
- 109SOL OW1 505 2.041 0.405 0.398 -0.6164 0.2991 -0.0624
- 109SOL HW2 506 2.139 0.424 0.410 -0.0768 -2.2881 0.6908
- 109SOL HW3 507 1.991 0.492 0.399 1.4759 1.6866 1.1017
- 110SOL OW1 508 0.892 0.835 0.932 -0.0875 0.0867 0.3771
- 110SOL HW2 509 0.893 0.750 0.880 -1.6158 -0.5569 1.2592
- 110SOL HW3 510 0.830 0.900 0.889 1.1151 0.8480 -0.3194
- 111SOL OW1 511 0.934 1.138 0.372 0.1781 -0.1319 -0.2100
- 111SOL HW2 512 0.865 1.167 0.438 0.6108 -1.1676 0.7707
- 111SOL HW3 513 1.025 1.161 0.407 0.4165 -0.7609 -0.4099
- 112SOL OW1 514 0.782 1.793 0.680 0.0927 0.3788 -0.3424
- 112SOL HW2 515 0.805 1.717 0.618 -0.5805 -0.5298 0.4629
- 112SOL HW3 516 0.712 1.850 0.637 -2.4495 -1.7474 0.3840
- 113SOL OW1 517 1.209 1.346 1.175 0.0055 0.7532 0.1240
- 113SOL HW2 518 1.213 1.249 1.201 -0.8872 0.3338 -1.1045
- 113SOL HW3 519 1.299 1.375 1.143 0.3634 0.4498 0.8093
- 114SOL OW1 520 1.471 2.085 0.591 0.0062 0.1481 -0.6743
- 114SOL HW2 521 1.372 2.080 0.598 0.0651 0.1128 0.4044
- 114SOL HW3 522 1.504 2.018 0.524 -0.6322 -0.4540 -0.3957
- 115SOL OW1 523 0.675 0.621 1.777 -0.0413 -0.1256 -0.5737
- 115SOL HW2 524 0.714 0.660 1.860 -0.3032 -0.1058 -0.4575
- 115SOL HW3 525 0.743 0.622 1.704 0.9365 -2.0406 0.1692
- 116SOL OW1 526 1.910 2.205 0.798 0.2704 -0.5038 -0.0757
- 116SOL HW2 527 1.871 2.141 0.732 1.4127 -0.3892 -0.9105
- 116SOL HW3 528 2.001 2.233 0.768 -0.4821 2.2762 -0.3314
- 117SOL OW1 529 1.626 1.343 1.679 -0.4152 -0.0794 -0.2261
- 117SOL HW2 530 1.643 1.263 1.622 -0.7488 -0.3894 0.1011
- 117SOL HW3 531 1.532 1.341 1.713 -1.1148 1.4544 -1.7719
- 118SOL OW1 532 0.300 1.483 0.597 -0.8682 0.4686 -0.6379
- 118SOL HW2 533 0.334 1.574 0.621 -0.3277 0.6091 -1.8228
- 118SOL HW3 534 0.301 1.472 0.498 -0.7581 -0.8909 -0.5202
- 119SOL OW1 535 1.424 1.887 1.829 -0.5741 -1.0007 0.3895
- 119SOL HW2 536 1.367 1.873 1.910 -0.3831 1.3658 1.0782
- 119SOL HW3 537 1.503 1.826 1.833 -0.6660 -1.0922 1.9170
- 120SOL OW1 538 2.002 1.848 0.403 0.2073 -0.0724 -0.1044
- 120SOL HW2 539 1.960 1.803 0.482 1.2483 -1.1583 -0.1086
- 120SOL HW3 540 2.097 1.870 0.425 0.1158 0.9183 -0.6028
- 121SOL OW1 541 1.640 0.991 0.298 0.5609 0.4945 -0.1885
- 121SOL HW2 542 1.657 1.012 0.202 -0.8550 -1.3743 -0.9846
- 121SOL HW3 543 1.579 1.059 0.337 -1.6821 -0.3570 -1.7878
- 122SOL OW1 544 1.850 0.668 1.479 0.2522 0.1197 -0.2780
- 122SOL HW2 545 1.941 0.703 1.500 -0.6236 2.1573 0.6611
- 122SOL HW3 546 1.798 0.738 1.430 -0.8633 -0.9380 -0.6969
- 123SOL OW1 547 0.811 0.348 1.617 0.2784 -0.4820 0.5339
- 123SOL HW2 548 0.778 0.353 1.712 0.1123 -0.8340 0.4974
- 123SOL HW3 549 0.764 0.417 1.562 -0.8530 -1.3356 0.3660
- 124SOL OW1 550 0.152 0.565 1.416 0.5757 0.5408 -0.0173
- 124SOL HW2 551 0.082 0.518 1.470 -0.3704 2.0741 0.2246
- 124SOL HW3 552 0.121 0.575 1.322 0.4026 1.2961 0.1099
- 125SOL OW1 553 1.566 1.800 1.096 -0.0052 0.2192 -0.5025
- 125SOL HW2 554 1.519 1.788 1.184 -0.0623 -0.6806 -0.6380
- 125SOL HW3 555 1.507 1.768 1.022 1.1469 -2.2110 -0.5843
- 126SOL OW1 556 0.414 0.470 1.928 0.2116 0.1795 0.1069
- 126SOL HW2 557 0.357 0.401 1.972 -0.9264 0.7937 -0.3207
- 126SOL HW3 558 0.406 0.462 1.829 -0.0213 0.9591 0.0495
- 127SOL OW1 559 0.090 1.791 0.967 0.3167 -0.4991 -0.1999
- 127SOL HW2 560 0.172 1.780 1.023 0.5117 -0.8389 -0.5445
- 127SOL HW3 561 0.019 1.730 1.000 -0.7651 1.4973 1.7336
- 128SOL OW1 562 0.057 0.339 0.161 -0.0525 -0.1842 -0.1555
- 128SOL HW2 563 0.034 0.420 0.107 0.0223 0.0439 0.1489
- 128SOL HW3 564 0.012 0.345 0.250 -0.2806 -0.6235 -0.2385
- 129SOL OW1 565 0.348 0.855 1.050 -0.0623 -0.1359 0.3582
- 129SOL HW2 566 0.433 0.843 0.999 -0.6392 0.0342 -0.7024
- 129SOL HW3 567 0.363 0.917 1.127 0.4242 1.2778 -0.7963
- 130SOL OW1 568 0.421 2.041 0.331 -0.4444 0.2754 0.0853
- 130SOL HW2 569 0.452 2.127 0.290 -0.4246 -0.2667 -1.1317
- 130SOL HW3 570 0.335 2.013 0.289 0.1732 -0.8984 -0.4933
- 131SOL OW1 571 1.497 1.149 1.899 -0.1127 0.0895 -0.3529
- 131SOL HW2 572 1.464 1.054 1.904 1.1609 -0.3773 -0.0086
- 131SOL HW3 573 1.446 1.198 1.829 -1.6025 -0.4887 0.2258
- 132SOL OW1 574 1.090 2.324 1.016 0.4978 -0.5111 0.5508
- 132SOL HW2 575 1.061 2.234 0.985 -1.4229 -0.9019 2.8779
- 132SOL HW3 576 1.174 2.350 0.969 0.8327 -3.1972 -0.7093
- 133SOL OW1 577 0.303 1.272 1.675 -0.1953 -0.0608 0.1099
- 133SOL HW2 578 0.214 1.262 1.631 -0.1178 3.9176 -1.8159
- 133SOL HW3 579 0.297 1.338 1.750 1.0813 0.1111 0.1104
- 134SOL OW1 580 1.750 2.011 1.733 -0.2233 0.0235 0.2833
- 134SOL HW2 581 1.801 1.987 1.816 -0.2438 -0.2268 0.2252
- 134SOL HW3 582 1.666 1.957 1.729 -0.9149 0.9933 0.7904
- 135SOL OW1 583 0.041 0.139 2.156 -0.4666 -0.1268 0.3831
- 135SOL HW2 584 -0.049 0.122 2.116 0.2879 1.9772 -3.0628
- 135SOL HW3 585 0.030 0.191 2.241 -2.5085 0.3559 -0.0648
- 136SOL OW1 586 1.347 1.885 0.372 0.1242 -0.2856 0.6527
- 136SOL HW2 587 1.280 1.949 0.411 0.6183 0.3217 0.5346
- 136SOL HW3 588 1.361 1.907 0.276 -0.1169 -0.9490 0.4574
- 137SOL OW1 589 1.256 1.550 1.422 -0.0091 -0.5712 -0.1766
- 137SOL HW2 590 1.281 1.453 1.425 -0.3430 -0.6465 0.8035
- 137SOL HW3 591 1.170 1.561 1.372 0.1971 -0.7307 -0.5721
- 138SOL OW1 592 1.250 1.008 2.049 0.0330 0.3953 -0.5330
- 138SOL HW2 593 1.266 1.106 2.044 -2.3054 1.0843 1.6849
- 138SOL HW3 594 1.328 0.964 2.094 0.1081 1.7358 0.7927
- 139SOL OW1 595 1.507 0.730 1.325 -0.4714 0.4185 0.0916
- 139SOL HW2 596 1.461 0.771 1.404 -3.4623 1.4345 -1.8530
- 139SOL HW3 597 1.578 0.793 1.291 2.1870 -0.7512 2.5830
- 140SOL OW1 598 0.455 1.742 0.595 -0.2740 -0.0007 0.3909
- 140SOL HW2 599 0.439 1.828 0.644 -0.8287 1.1949 -1.6590
- 140SOL HW3 600 0.535 1.752 0.535 1.1935 -1.8441 1.7970
- 141SOL OW1 601 1.687 1.793 0.188 0.3177 -0.2593 0.3674
- 141SOL HW2 602 1.626 1.836 0.122 -0.0786 0.1012 0.9539
- 141SOL HW3 603 1.779 1.788 0.149 0.3912 1.1539 0.2679
- 142SOL OW1 604 1.563 0.705 0.186 0.0140 -0.6182 -0.4736
- 142SOL HW2 605 1.488 0.679 0.246 -0.2847 0.7640 -0.1706
- 142SOL HW3 606 1.639 0.739 0.241 -0.0116 0.0414 -0.8248
- 143SOL OW1 607 1.702 1.714 0.587 -0.0871 -0.2563 0.4727
- 143SOL HW2 608 1.782 1.654 0.576 0.9125 1.0929 -0.2485
- 143SOL HW3 609 1.640 1.700 0.510 0.6633 0.3203 -0.2690
- 144SOL OW1 610 0.862 2.145 1.489 0.2455 0.3150 0.6359
- 144SOL HW2 611 0.902 2.148 1.398 -1.1372 1.4585 -0.0183
- 144SOL HW3 612 0.904 2.215 1.546 0.1404 0.5704 0.4006
- 145SOL OW1 613 1.535 1.682 0.377 0.1536 -0.0681 0.2072
- 145SOL HW2 614 1.467 1.751 0.400 2.2292 2.0656 0.7481
- 145SOL HW3 615 1.582 1.708 0.293 0.8093 -1.0077 0.2535
- 146SOL OW1 616 0.032 2.169 1.546 -0.0211 0.2842 0.0823
- 146SOL HW2 617 0.122 2.143 1.513 0.4822 0.3521 1.3116
- 146SOL HW3 618 -0.029 2.186 1.468 0.9170 -0.0888 -0.7646
- 147SOL OW1 619 1.957 0.710 0.477 -0.1785 0.7365 -0.1392
- 147SOL HW2 620 1.932 0.759 0.393 -0.3855 -0.5145 -0.8684
- 147SOL HW3 621 2.036 0.753 0.519 -0.0169 1.3543 -1.0270
- 148SOL OW1 622 1.861 1.304 0.273 0.2402 -0.0094 -0.1325
- 148SOL HW2 623 1.824 1.242 0.342 0.2556 -0.8393 -0.8274
- 148SOL HW3 624 1.788 1.363 0.239 -0.0474 -0.4021 -0.2198
- 149SOL OW1 625 0.653 1.698 0.396 -0.4847 0.2238 0.2685
- 149SOL HW2 626 0.732 1.745 0.356 -0.5963 0.8343 0.7422
- 149SOL HW3 627 0.571 1.719 0.344 -0.2981 -0.7145 -0.4488
- 150SOL OW1 628 0.787 1.019 1.472 -0.2957 -0.7313 -0.0828
- 150SOL HW2 629 0.845 1.041 1.393 -0.8605 -0.6963 -0.4969
- 150SOL HW3 630 0.814 1.076 1.549 -0.8463 0.5272 -0.7556
- 151SOL OW1 631 1.495 0.925 0.003 -0.2499 0.0732 -0.5895
- 151SOL HW2 632 1.590 0.958 0.004 -0.5942 1.1442 -0.8220
- 151SOL HW3 633 1.492 0.833 0.042 0.9301 -0.1292 -0.8873
- 152SOL OW1 634 0.178 1.724 0.708 -0.4638 -0.0788 0.4209
- 152SOL HW2 635 0.156 1.659 0.781 -1.8781 0.6958 0.7567
- 152SOL HW3 636 0.245 1.790 0.742 -0.7482 -0.0126 0.8716
- 153SOL OW1 637 1.470 0.875 1.857 0.2012 -0.2387 -0.1237
- 153SOL HW2 638 1.375 0.845 1.856 0.3837 -0.8347 -0.1678
- 153SOL HW3 639 1.525 0.814 1.800 0.6956 -0.2024 0.3052
- 154SOL OW1 640 1.467 1.222 0.382 0.3389 0.6624 0.1653
- 154SOL HW2 641 1.526 1.302 0.395 0.9722 0.1175 0.7419
- 154SOL HW3 642 1.432 1.222 0.288 0.9168 1.2266 -0.0668
- 155SOL OW1 643 0.384 1.134 0.372 -0.4800 -0.1530 -0.3919
- 155SOL HW2 644 0.323 1.169 0.443 -1.1248 -2.4534 0.3793
- 155SOL HW3 645 0.334 1.069 0.315 1.0597 -1.9167 0.0669
- 156SOL OW1 646 0.803 0.902 0.352 -0.0019 0.5576 -0.1973
- 156SOL HW2 647 0.741 0.891 0.274 -0.6208 2.9318 -0.2066
- 156SOL HW3 648 0.849 0.991 0.344 4.0522 -1.1474 -0.5164
- 157SOL OW1 649 1.173 0.623 1.415 0.0266 -0.5275 -0.2205
- 157SOL HW2 650 1.077 0.612 1.443 0.0724 -1.9214 -0.4759
- 157SOL HW3 651 1.224 0.540 1.438 1.6931 0.8330 1.6444
- 158SOL OW1 652 1.021 1.433 0.975 -0.4489 0.4447 0.0545
- 158SOL HW2 653 1.082 1.403 1.048 0.5266 1.3794 -0.3371
- 158SOL HW3 654 0.933 1.386 0.985 0.4164 -1.2907 0.3992
- 159SOL OW1 655 0.403 0.655 0.806 -0.0401 0.3305 0.1337
- 159SOL HW2 656 0.452 0.710 0.874 0.0340 0.0125 0.3387
- 159SOL HW3 657 0.469 0.603 0.752 -0.1153 0.4120 -0.0279
- 160SOL OW1 658 1.846 0.436 1.593 -0.3048 0.2915 0.1266
- 160SOL HW2 659 1.827 0.524 1.548 -1.5172 -0.2518 -0.5401
- 160SOL HW3 660 1.846 0.449 1.692 -1.3792 0.9370 0.0808
- 161SOL OW1 661 0.437 0.781 2.083 0.0095 -1.2060 0.2252
- 161SOL HW2 662 0.426 0.686 2.113 0.2122 -1.8353 -1.4770
- 161SOL HW3 663 0.453 0.783 1.984 0.0920 0.6180 0.2134
- 162SOL OW1 664 0.452 2.222 0.916 -0.6120 0.1469 0.1860
- 162SOL HW2 665 0.361 2.190 0.942 -1.0830 -0.4433 -1.8996
- 162SOL HW3 666 0.449 2.266 0.827 1.2079 -0.2943 -0.1825
- 163SOL OW1 667 0.935 1.123 0.095 -0.2401 0.3174 -0.4180
- 163SOL HW2 668 0.993 1.042 0.105 1.7893 1.6069 -0.5265
- 163SOL HW3 669 0.907 1.156 0.185 0.4230 0.4200 -0.2380
- 164SOL OW1 670 0.769 1.993 0.041 -0.0495 -0.3257 0.1228
- 164SOL HW2 671 0.806 1.973 0.131 -0.5785 0.3032 0.4992
- 164SOL HW3 672 0.670 2.005 0.048 -0.0127 0.3706 -0.4192
- 165SOL OW1 673 0.217 1.153 0.565 -0.0990 -0.3276 -0.1299
- 165SOL HW2 674 0.183 1.222 0.629 2.4918 0.3714 0.7391
- 165SOL HW3 675 0.224 1.064 0.611 2.8380 0.3944 1.3269
- 166SOL OW1 676 1.869 0.588 1.876 -0.3023 -0.2309 0.2519
- 166SOL HW2 677 1.804 0.633 1.937 0.1743 1.6052 -0.4750
- 166SOL HW3 678 1.886 0.645 1.796 1.6203 -0.9528 0.0218
- 167SOL OW1 679 1.422 1.015 1.473 -0.0075 0.1342 -0.5369
- 167SOL HW2 680 1.395 0.936 1.529 -0.0798 0.7241 0.2938
- 167SOL HW3 681 1.521 1.023 1.473 0.3572 -1.7278 -3.1789
- 168SOL OW1 682 1.607 0.650 0.700 0.2782 1.0724 0.1966
- 168SOL HW2 683 1.518 0.690 0.724 -0.1831 -0.1319 0.6430
- 168SOL HW3 684 1.599 0.550 0.697 1.6644 0.9210 0.3875
- 169SOL OW1 685 1.178 0.403 1.108 0.5986 -0.5871 0.1392
- 169SOL HW2 686 1.098 0.455 1.078 0.7783 -1.8790 -3.4652
- 169SOL HW3 687 1.258 0.463 1.111 0.2804 -0.0749 -0.8886
- 170SOL OW1 688 0.220 1.770 1.221 -0.2924 -0.0368 0.2000
- 170SOL HW2 689 0.212 1.671 1.213 -1.9547 0.0426 0.1832
- 170SOL HW3 690 0.310 1.793 1.258 0.7961 -1.4174 -1.3069
- 171SOL OW1 691 0.866 0.337 1.231 0.3183 -0.4266 -0.2301
- 171SOL HW2 692 0.877 0.292 1.319 -0.0839 2.3873 1.5149
- 171SOL HW3 693 0.768 0.341 1.208 -0.2658 2.4013 1.7002
- 172SOL OW1 694 1.311 0.361 0.549 -0.3189 -0.2118 0.0566
- 172SOL HW2 695 1.212 0.365 0.539 -0.3338 -1.5399 -0.8133
- 172SOL HW3 696 1.347 0.281 0.500 1.1329 -0.0823 0.7921
- 173SOL OW1 697 1.369 1.126 0.940 0.0703 -0.1074 -0.0104
- 173SOL HW2 698 1.398 1.092 0.850 -1.6292 0.7576 -0.9813
- 173SOL HW3 699 1.270 1.118 0.948 -0.0663 1.6173 0.9684
- 174SOL OW1 700 0.490 1.531 2.101 -0.3142 -0.2034 -0.0218
- 174SOL HW2 701 0.532 1.573 2.181 0.1668 0.8101 -0.7578
- 174SOL HW3 702 0.545 1.452 2.073 -0.7854 -0.8985 0.9184
- 175SOL OW1 703 0.409 1.150 1.927 -0.4094 0.0594 0.2832
- 175SOL HW2 704 0.446 1.105 2.009 0.3173 2.0924 1.2063
- 175SOL HW3 705 0.483 1.193 1.877 -0.7977 -1.3774 -1.7446
- 176SOL OW1 706 1.553 0.319 1.596 1.0173 0.6704 0.6473
- 176SOL HW2 707 1.622 0.343 1.664 -0.2749 -0.0704 2.3291
- 176SOL HW3 708 1.566 0.224 1.567 -0.0467 0.0138 2.0999
- 177SOL OW1 709 0.037 1.562 1.300 -0.1944 0.2660 -0.2755
- 177SOL HW2 710 0.077 1.590 1.387 1.4003 0.6788 -1.0633
- 177SOL HW3 711 0.072 1.472 1.274 0.5610 0.7744 -1.1404
- 178SOL OW1 712 1.912 1.557 1.478 -0.1816 0.0966 -0.3601
- 178SOL HW2 713 1.984 1.545 1.410 1.1640 1.6529 0.6310
- 178SOL HW3 714 1.839 1.613 1.439 0.1750 0.2880 -0.7820
- 179SOL OW1 715 0.594 0.786 0.966 -0.1755 -0.2980 -0.0467
- 179SOL HW2 716 0.623 0.795 1.062 -0.3751 -1.9217 0.2209
- 179SOL HW3 717 0.641 0.855 0.911 -0.4262 1.0221 1.2627
- 180SOL OW1 718 1.061 1.373 0.077 0.2085 0.3349 -0.0397
- 180SOL HW2 719 1.096 1.375 0.171 -1.4745 0.5354 0.6623
- 180SOL HW3 720 0.987 1.305 0.071 1.2854 -0.8419 -1.6848
- 181SOL OW1 721 0.280 1.428 1.894 -0.4383 -0.1926 0.0340
- 181SOL HW2 722 0.296 1.407 1.991 -1.2069 -2.0656 -0.1646
- 181SOL HW3 723 0.188 1.465 1.882 0.4019 2.3055 0.1863
- 182SOL OW1 724 1.551 0.057 1.541 0.6365 -0.1158 -0.1718
- 182SOL HW2 725 1.482 0.047 1.469 -0.7483 1.2134 0.8578
- 182SOL HW3 726 1.616 -0.019 1.535 -0.5573 -1.1409 -1.5682
- 183SOL OW1 727 1.959 1.867 1.885 -0.0742 -0.4716 0.5309
- 183SOL HW2 728 2.013 1.937 1.839 -2.0839 1.1694 0.3402
- 183SOL HW3 729 1.966 1.781 1.835 0.4568 0.3251 -0.8702
- 184SOL OW1 730 1.667 1.932 2.073 -0.0409 0.7001 -0.1997
- 184SOL HW2 731 1.651 1.862 2.003 0.0770 1.9545 -1.5861
- 184SOL HW3 732 1.764 1.932 2.099 -0.2911 -0.5783 0.9833
- 185SOL OW1 733 1.325 0.406 1.488 0.5195 0.1676 -0.3890
- 185SOL HW2 734 1.277 0.331 1.442 0.0256 1.7667 -2.9259
- 185SOL HW3 735 1.413 0.373 1.522 0.7108 -1.4512 -2.0854
- 186SOL OW1 736 0.574 0.779 0.492 0.2239 0.5640 0.0222
- 186SOL HW2 737 0.565 0.867 0.539 -1.7082 -0.1004 1.1098
- 186SOL HW3 738 0.566 0.793 0.393 -0.7699 1.5840 0.2103
- 187SOL OW1 739 1.157 0.248 1.340 -0.1217 -0.3071 -0.5183
- 187SOL HW2 740 1.193 0.155 1.331 0.2450 -0.3768 1.1698
- 187SOL HW3 741 1.175 0.298 1.255 2.1698 -0.9637 -0.5707
- 188SOL OW1 742 0.161 1.794 0.446 -0.8110 0.0841 0.3138
- 188SOL HW2 743 0.188 1.803 0.542 -2.3818 -0.4592 0.8767
- 188SOL HW3 744 0.165 1.698 0.418 -1.8121 0.0080 0.3627
- 189SOL OW1 745 0.349 1.639 1.629 0.0392 -0.1262 -0.1540
- 189SOL HW2 746 0.274 1.672 1.685 -1.7873 0.8696 -2.8050
- 189SOL HW3 747 0.315 1.573 1.561 2.3917 -2.6787 0.7377
- 190SOL OW1 748 1.342 1.284 1.440 -0.2950 0.0562 0.3305
- 190SOL HW2 749 1.348 1.184 1.438 -0.3939 -0.0530 2.1054
- 190SOL HW3 750 1.428 1.323 1.406 0.7217 -0.7497 1.7540
- 191SOL OW1 751 1.406 0.811 0.778 0.6720 0.5929 -0.3196
- 191SOL HW2 752 1.428 0.904 0.750 -0.4232 0.9320 -0.1214
- 191SOL HW3 753 1.327 0.812 0.839 0.5703 -0.4798 -0.4004
- 192SOL OW1 754 0.700 0.994 0.813 1.1074 -0.5002 -0.0158
- 192SOL HW2 755 0.683 1.092 0.801 1.6522 0.0292 2.4064
- 192SOL HW3 756 0.732 0.954 0.727 -1.4648 0.7945 -1.8249
- 193SOL OW1 757 0.782 1.057 2.057 0.0264 0.4447 0.0530
- 193SOL HW2 758 0.835 1.089 1.978 -1.7843 0.6596 -1.1826
- 193SOL HW3 759 0.838 1.065 2.140 1.7809 0.8963 -1.0727
- 194SOL OW1 760 0.479 0.103 2.025 -0.5797 0.6887 -0.2586
- 194SOL HW2 761 0.462 0.026 2.085 -1.8118 1.1639 0.0553
- 194SOL HW3 762 0.565 0.148 2.052 -0.5221 0.2113 0.3846
- 195SOL OW1 763 0.483 2.156 0.036 -0.7147 -0.3670 0.7713
- 195SOL HW2 764 0.451 2.062 0.042 -1.8879 0.0453 3.3508
- 195SOL HW3 765 0.405 2.219 0.039 0.0530 0.7570 -0.5180
- 196SOL OW1 766 1.270 2.306 1.879 -0.5172 0.0068 0.1912
- 196SOL HW2 767 1.273 2.404 1.862 1.8605 0.0045 -0.0624
- 196SOL HW3 768 1.290 2.256 1.795 -0.0143 -0.5746 0.6314
- 197SOL OW1 769 2.012 1.085 0.463 0.8652 0.0841 0.1395
- 197SOL HW2 770 1.953 1.154 0.504 0.1023 -0.7188 0.4400
- 197SOL HW3 771 2.069 1.044 0.535 0.9856 0.0826 0.0405
- 198SOL OW1 772 1.573 0.603 1.741 0.4222 -0.1978 -0.4899
- 198SOL HW2 773 1.477 0.575 1.743 -0.6547 2.7477 -0.8728
- 198SOL HW3 774 1.628 0.539 1.795 -2.2080 -0.6903 2.1344
- 199SOL OW1 775 0.306 0.556 0.033 -0.2636 0.1231 -0.2672
- 199SOL HW2 776 0.219 0.582 -0.008 -0.8636 -1.4908 -0.1772
- 199SOL HW3 777 0.323 0.459 0.016 -0.5286 -0.7489 3.0715
- 200SOL OW1 778 1.548 0.752 1.015 -0.3507 0.0468 0.5606
- 200SOL HW2 779 1.537 0.845 1.049 -1.2341 1.7778 -3.3248
- 200SOL HW3 780 1.518 0.748 0.919 3.1604 -3.3148 -0.9129
- 201SOL OW1 781 1.891 0.353 0.747 -0.0313 0.1405 0.0081
- 201SOL HW2 782 1.851 0.308 0.667 -0.6769 -0.4122 0.6093
- 201SOL HW3 783 1.917 0.283 0.815 1.6864 0.5065 -0.2055
- 202SOL OW1 784 0.821 0.007 0.837 0.0137 0.2150 -0.0930
- 202SOL HW2 785 0.838 0.071 0.912 -1.1353 0.4274 0.0132
- 202SOL HW3 786 0.749 -0.058 0.863 1.0818 -1.1099 -0.2309
- 203SOL OW1 787 0.681 0.330 1.850 0.3431 0.3624 -0.8161
- 203SOL HW2 788 0.718 0.300 1.938 2.1497 0.6528 -1.3927
- 203SOL HW3 789 0.670 0.429 1.850 0.2084 0.3459 -0.8702
- 204SOL OW1 790 0.673 2.091 0.806 0.2248 -0.2273 -0.5970
- 204SOL HW2 791 0.590 2.121 0.853 -0.7719 -2.4140 -0.7221
- 204SOL HW3 792 0.650 2.056 0.716 1.9138 2.5751 -2.4408
- 205SOL OW1 793 1.862 0.180 1.515 -0.4790 0.1718 -0.4126
- 205SOL HW2 794 1.851 0.274 1.545 -1.7644 -0.4605 1.4924
- 205SOL HW3 795 1.845 0.118 1.592 2.7467 -1.6806 -0.8542
- 206SOL OW1 796 0.951 0.668 0.372 -0.1340 -0.4240 0.0408
- 206SOL HW2 797 0.883 0.741 0.374 -0.5862 -0.8339 0.9180
- 206SOL HW3 798 0.915 0.590 0.321 0.8056 0.3079 -1.9539
- 207SOL OW1 799 1.855 0.465 1.185 -0.1366 0.1802 0.1627
- 207SOL HW2 800 1.797 0.478 1.265 1.2033 2.4143 0.9498
- 207SOL HW3 801 1.801 0.480 1.102 -0.7696 3.0255 0.8675
- 208SOL OW1 802 1.025 0.291 0.780 -0.4427 0.0834 -0.0165
- 208SOL HW2 803 1.123 0.291 0.801 -0.1719 -0.5314 -1.1052
- 208SOL HW3 804 0.976 0.239 0.850 0.5462 -2.7610 -1.1074
- 209SOL OW1 805 0.075 0.869 1.068 -0.4918 0.1182 -0.4621
- 209SOL HW2 806 0.174 0.862 1.079 -0.5615 0.4953 0.5608
- 209SOL HW3 807 0.031 0.789 1.109 -0.7440 1.5214 2.4824
- 210SOL OW1 808 0.973 2.083 0.945 -0.2425 -0.0130 -0.2203
- 210SOL HW2 809 1.007 2.086 0.852 -1.4809 1.0332 -0.6997
- 210SOL HW3 810 0.876 2.058 0.944 -0.6952 1.4488 0.5869
- 211SOL OW1 811 0.071 0.866 0.577 0.0309 0.2476 -0.2138
- 211SOL HW2 812 0.061 0.891 0.673 0.1544 0.8086 -0.3413
- 211SOL HW3 813 0.155 0.813 0.565 0.6085 1.1184 -0.1728
- 212SOL OW1 814 1.254 1.404 0.609 -0.1379 0.3185 0.4844
- 212SOL HW2 815 1.342 1.390 0.656 0.2736 2.7504 0.6997
- 212SOL HW3 816 1.240 1.331 0.543 2.9310 0.5347 -0.7532
- 213SOL OW1 817 0.171 0.519 0.496 -0.5668 -0.0275 -0.1699
- 213SOL HW2 818 0.245 0.586 0.504 -0.6710 -0.0120 0.9302
- 213SOL HW3 819 0.203 0.430 0.526 -0.6857 -0.2829 -0.7839
- 214SOL OW1 820 0.054 0.419 1.992 -0.2565 0.6495 0.4681
- 214SOL HW2 821 0.132 0.362 2.018 -0.8265 -0.2158 0.3569
- 214SOL HW3 822 0.036 0.486 2.064 1.0840 1.4419 0.1290
- 215SOL OW1 823 1.875 1.101 1.344 -0.1734 0.1442 -0.3170
- 215SOL HW2 824 1.896 1.188 1.390 1.5403 0.2351 -1.1023
- 215SOL HW3 825 1.960 1.058 1.315 -0.9986 -1.6428 -0.3130
- 216SOL OW1 826 1.980 0.286 1.822 0.1199 -0.6894 0.2519
- 216SOL HW2 827 2.037 0.335 1.888 1.1110 -1.4020 -0.0213
- 216SOL HW3 828 1.950 0.199 1.862 -1.1443 -0.1610 0.5285
- 217SOL OW1 829 1.035 0.421 0.541 -0.2447 -0.4423 0.2604
- 217SOL HW2 830 0.948 0.410 0.492 0.2421 -0.1260 -0.7443
- 217SOL HW3 831 1.020 0.416 0.639 -1.3084 -0.9486 0.0905
- 218SOL OW1 832 0.636 2.313 1.715 0.6696 0.0992 -0.3801
- 218SOL HW2 833 0.726 2.356 1.728 0.3719 1.0585 -1.1632
- 218SOL HW3 834 0.599 2.285 1.803 1.2241 0.8029 0.1065
- 219SOL OW1 835 0.662 1.557 0.956 0.1848 -0.3105 0.1038
- 219SOL HW2 836 0.660 1.565 0.856 -1.6341 -1.8911 -0.0878
- 219SOL HW3 837 0.674 1.648 0.996 -1.4103 0.7798 -1.5685
- 220SOL OW1 838 0.924 1.580 0.595 0.1161 -0.1201 0.0291
- 220SOL HW2 839 0.917 1.640 0.675 1.9956 0.3666 -0.0738
- 220SOL HW3 840 0.945 1.487 0.624 0.2213 -0.0692 0.1083
- 221SOL OW1 841 0.670 0.808 1.217 -0.4153 -0.5267 0.4481
- 221SOL HW2 842 0.625 0.773 1.299 -0.0833 0.4069 1.0660
- 221SOL HW3 843 0.697 0.904 1.232 0.8835 -0.7403 -0.2501
- 222SOL OW1 844 0.290 2.336 0.032 -0.1051 0.1941 -0.0143
- 222SOL HW2 845 0.213 2.358 -0.028 -0.3537 0.5040 0.4109
- 222SOL HW3 846 0.306 2.412 0.095 0.3015 -0.0309 0.1571
- 223SOL OW1 847 1.204 1.866 1.069 -0.2716 0.2936 -0.1189
- 223SOL HW2 848 1.268 1.795 1.041 1.6314 0.6822 2.4322
- 223SOL HW3 849 1.113 1.844 1.037 0.2868 -2.9379 -0.1334
- 224SOL OW1 850 0.082 1.210 1.527 -0.2478 0.0411 0.5473
- 224SOL HW2 851 0.111 1.115 1.536 -0.6224 -0.4289 -1.7677
- 224SOL HW3 852 -0.014 1.213 1.500 0.3096 0.7544 -1.8928
- 225SOL OW1 853 1.716 2.156 0.107 0.0955 -0.2612 0.2071
- 225SOL HW2 854 1.737 2.071 0.059 0.6789 -0.4693 0.8011
- 225SOL HW3 855 1.628 2.146 0.153 -0.7544 0.1397 -1.2163
- 226SOL OW1 856 1.728 2.204 1.480 0.6707 0.9221 -0.6426
- 226SOL HW2 857 1.798 2.140 1.450 -1.4256 -2.0479 -0.0090
- 226SOL HW3 858 1.643 2.186 1.432 -1.3714 -0.3787 2.7435
- 227SOL OW1 859 1.288 1.630 0.984 0.2912 0.7037 0.3714
- 227SOL HW2 860 1.339 1.573 1.048 0.4474 -0.3381 -0.6182
- 227SOL HW3 861 1.196 1.591 0.971 0.7734 -0.0892 -1.1703
- 228SOL OW1 862 1.888 1.521 0.509 0.3686 -0.4818 0.7969
- 228SOL HW2 863 1.946 1.593 0.546 0.4245 -0.8561 1.4505
- 228SOL HW3 864 1.942 1.462 0.448 -0.0598 1.0559 -1.2976
- 229SOL OW1 865 1.028 2.242 0.706 0.0044 0.1051 1.1540
- 229SOL HW2 866 0.965 2.304 0.753 0.8757 1.2016 0.9504
- 229SOL HW3 867 1.121 2.280 0.709 0.2929 -0.3330 -0.4763
- 230SOL OW1 868 1.312 0.799 1.575 -0.1011 -0.0488 0.2992
- 230SOL HW2 869 1.254 0.749 1.511 0.3609 -0.1725 -0.0320
- 230SOL HW3 870 1.276 0.790 1.668 -0.3965 -0.4381 0.1474
- 231SOL OW1 871 1.746 0.569 0.062 0.4210 -0.1202 0.0070
- 231SOL HW2 872 1.805 0.636 0.016 -1.4151 0.5003 -1.6923
- 231SOL HW3 873 1.679 0.617 0.119 -0.2112 -0.5618 -0.3518
- 232SOL OW1 874 2.073 0.782 1.995 0.0843 0.0517 -0.1017
- 232SOL HW2 875 1.991 0.738 1.959 -0.3056 1.9441 -1.8699
- 232SOL HW3 876 2.148 0.774 1.929 0.7683 -0.0164 0.6422
- 233SOL OW1 877 0.145 1.795 1.990 0.0074 -0.7360 -0.1482
- 233SOL HW2 878 0.189 1.883 2.004 2.2483 -1.7433 0.0662
- 233SOL HW3 879 0.149 1.771 1.893 -0.3146 -0.7461 -0.1601
- 234SOL OW1 880 0.306 0.740 0.560 -0.7314 -0.3855 -0.1185
- 234SOL HW2 881 0.396 0.771 0.532 -1.1278 0.3944 -0.5830
- 234SOL HW3 882 0.309 0.708 0.655 0.2000 -1.1864 -0.3855
- 235SOL OW1 883 1.691 1.974 1.258 -0.1993 -0.5744 0.4667
- 235SOL HW2 884 1.670 2.072 1.255 0.4307 -0.4199 0.8810
- 235SOL HW3 885 1.638 1.926 1.189 0.9434 0.3275 -1.1500
- 236SOL OW1 886 0.768 1.417 2.026 -0.3987 -0.3774 0.1575
- 236SOL HW2 887 0.765 1.515 2.004 1.8007 0.1508 1.5372
- 236SOL HW3 888 0.752 1.404 2.124 -0.9178 -1.4810 -0.0406
- 237SOL OW1 889 1.132 2.031 1.679 -0.1771 0.1142 0.4719
- 237SOL HW2 890 1.071 2.110 1.685 1.2946 1.5635 -1.2060
- 237SOL HW3 891 1.227 2.062 1.678 0.4766 -1.4880 -1.3818
- 238SOL OW1 892 1.575 1.419 1.385 0.2252 -0.1345 -0.5253
- 238SOL HW2 893 1.595 1.459 1.475 -1.0329 -0.9650 0.1845
- 238SOL HW3 894 1.625 1.469 1.315 -0.1451 1.7640 0.4296
- 239SOL OW1 895 0.187 1.030 1.804 0.5710 0.0737 0.3446
- 239SOL HW2 896 0.196 0.938 1.844 3.7927 -0.2552 -0.5535
- 239SOL HW3 897 0.262 1.087 1.836 -0.3818 1.9029 -0.4304
- 240SOL OW1 898 1.367 1.145 0.130 0.3495 0.1779 0.5064
- 240SOL HW2 899 1.424 1.067 0.102 -0.1970 -0.1735 0.3571
- 240SOL HW3 900 1.272 1.115 0.139 0.0773 0.9017 0.1382
- 241SOL OW1 901 0.849 0.869 0.627 -0.1383 0.1409 -0.1084
- 241SOL HW2 902 0.815 0.843 0.537 -0.8143 -0.4992 0.3196
- 241SOL HW3 903 0.918 0.804 0.657 0.6518 0.7761 -0.4582
- 242SOL OW1 904 1.148 0.629 2.129 0.4786 0.0085 -0.4960
- 242SOL HW2 905 1.168 0.619 2.227 -0.4466 2.4357 0.0761
- 242SOL HW3 906 1.234 0.639 2.079 1.1018 -2.8530 -0.3584
- 243SOL OW1 907 0.952 1.112 1.286 -0.4415 -0.0059 0.1264
- 243SOL HW2 908 1.042 1.128 1.327 -0.6071 -0.1923 0.5738
- 243SOL HW3 909 0.907 1.200 1.269 -0.2001 0.0836 -0.0399
- 244SOL OW1 910 0.281 0.290 2.104 0.0501 0.3815 -0.1521
- 244SOL HW2 911 0.194 0.239 2.104 -1.1389 2.0368 -2.3656
- 244SOL HW3 912 0.357 0.226 2.090 -1.1216 -0.9652 -0.8991
- 245SOL OW1 913 1.217 0.909 0.461 0.3312 0.5867 0.2410
- 245SOL HW2 914 1.312 0.881 0.446 -0.1797 -0.8132 -0.7712
- 245SOL HW3 915 1.171 0.842 0.520 -0.6846 -0.3719 -1.4855
- 246SOL OW1 916 0.898 0.960 1.780 -0.5373 -0.3096 0.5417
- 246SOL HW2 917 0.938 0.901 1.850 1.8625 0.5291 0.0831
- 246SOL HW3 918 0.964 1.032 1.756 -2.4532 1.3284 -0.4047
- 247SOL OW1 919 1.525 1.923 1.515 0.0699 0.1041 -0.2481
- 247SOL HW2 920 1.465 1.883 1.585 1.4862 -1.6207 0.1276
- 247SOL HW3 921 1.513 1.874 1.429 -0.3507 0.9938 -0.7101
- 248SOL OW1 922 0.270 0.617 1.118 -0.3647 -1.1497 0.2467
- 248SOL HW2 923 0.214 0.594 1.039 -0.7250 -0.8062 0.3991
- 248SOL HW3 924 0.299 0.713 1.112 -1.0109 -0.8966 0.8855
- 249SOL OW1 925 1.180 0.774 0.944 0.1336 -0.0263 -0.2162
- 249SOL HW2 926 1.216 0.734 1.028 0.0027 1.3557 0.5630
- 249SOL HW3 927 1.082 0.791 0.954 0.2877 0.9889 -0.2536
- 250SOL OW1 928 0.956 0.605 0.786 0.1068 0.1774 -0.0797
- 250SOL HW2 929 0.893 0.579 0.713 2.7508 -1.1156 -2.3083
- 250SOL HW3 930 0.937 0.552 0.868 -0.1445 -2.3430 -1.5557
- 251SOL OW1 931 1.015 0.857 2.015 0.2381 0.3067 0.0365
- 251SOL HW2 932 1.111 0.886 2.012 0.3099 0.0505 -0.9465
- 251SOL HW3 933 0.988 0.839 2.109 1.1194 0.4981 0.3437
- 252SOL OW1 934 1.332 1.631 1.675 0.5109 0.1798 -0.1515
- 252SOL HW2 935 1.260 1.689 1.713 -0.2704 1.1089 -2.6244
- 252SOL HW3 936 1.306 1.602 1.583 1.9034 -2.3392 0.0916
- 253SOL OW1 937 0.755 1.229 0.545 0.1632 0.3442 -0.0762
- 253SOL HW2 938 0.729 1.304 0.485 0.6018 0.9426 0.4554
- 253SOL HW3 939 0.723 1.247 0.638 1.0571 0.3399 0.2595
- 254SOL OW1 940 1.717 1.138 0.057 -0.4038 -0.2375 0.6024
- 254SOL HW2 941 1.643 1.203 0.040 0.0313 0.1766 0.2458
- 254SOL HW3 942 1.787 1.147 -0.015 1.1147 0.9823 2.0727
- 255SOL OW1 943 1.009 0.851 1.176 0.2001 -0.2090 0.5317
- 255SOL HW2 944 0.949 0.846 1.097 0.2459 -0.9283 0.5300
- 255SOL HW3 945 1.032 0.947 1.194 -2.1474 0.3118 1.4502
- 256SOL OW1 946 1.814 0.776 1.037 0.6002 0.0790 0.3822
- 256SOL HW2 947 1.851 0.764 0.945 0.0460 -1.9432 0.3141
- 256SOL HW3 948 1.714 0.771 1.034 0.3496 2.4510 0.9071
- 257SOL OW1 949 0.858 0.172 0.615 -0.0079 -0.5948 -0.5931
- 257SOL HW2 950 0.838 0.116 0.696 -0.5116 -0.8031 -0.8554
- 257SOL HW3 951 0.944 0.220 0.629 0.1991 -1.0708 -0.1686
- 258SOL OW1 952 2.030 1.032 1.701 0.4107 0.0500 -0.1015
- 258SOL HW2 953 1.985 1.119 1.720 0.9095 0.3886 -0.4316
- 258SOL HW3 954 2.126 1.036 1.729 0.9627 0.2973 -1.7729
- 259SOL OW1 955 1.892 2.216 2.085 0.1296 -0.3379 -0.1510
- 259SOL HW2 956 1.811 2.228 2.143 0.0083 -0.0105 -0.3835
- 259SOL HW3 957 1.925 2.122 2.093 -0.3881 -0.5293 -0.2002
- 260SOL OW1 958 1.785 0.924 0.562 -0.2890 -0.3779 0.5556
- 260SOL HW2 959 1.843 0.853 0.602 -0.5468 -2.1529 -1.8082
- 260SOL HW3 960 1.690 0.910 0.591 -0.0634 0.7309 2.0991
- 261SOL OW1 961 1.921 2.304 1.685 0.1364 0.1818 0.4606
- 261SOL HW2 962 1.999 2.262 1.638 -0.7556 1.4247 -2.6679
- 261SOL HW3 963 1.837 2.256 1.659 -0.4812 1.3711 0.1019
- 262SOL OW1 964 1.614 1.565 0.832 0.3797 -0.1073 -0.1023
- 262SOL HW2 965 1.545 1.505 0.791 -1.1622 -1.4172 3.5048
- 262SOL HW3 966 1.579 1.658 0.837 1.1102 0.3990 -2.3274
- 263SOL OW1 967 1.497 1.353 0.704 0.1611 -0.1069 0.2288
- 263SOL HW2 968 1.481 1.255 0.710 -2.6445 0.1620 -0.3910
- 263SOL HW3 969 1.562 1.372 0.631 -0.0032 -1.4578 -0.3207
- 264SOL OW1 970 1.875 1.644 0.849 -0.0714 -0.2426 0.0902
- 264SOL HW2 971 1.906 1.657 0.943 -1.4938 -0.9485 0.7244
- 264SOL HW3 972 1.786 1.598 0.850 -0.2811 0.0158 -1.6070
- 265SOL OW1 973 1.064 2.086 2.142 -0.1044 -0.0325 -0.3753
- 265SOL HW2 974 0.992 2.017 2.135 0.6492 -0.9878 0.6409
- 265SOL HW3 975 1.023 2.177 2.148 -1.3739 -0.6155 1.5909
- 266SOL OW1 976 0.046 2.187 1.980 -0.5149 -0.6850 -0.8837
- 266SOL HW2 977 0.089 2.277 1.969 -1.1191 -0.4309 -1.1820
- 266SOL HW3 978 -0.052 2.198 1.998 -0.4258 -1.2500 0.1065
- 267SOL OW1 979 0.191 0.739 1.808 0.5220 0.2734 -0.0164
- 267SOL HW2 980 0.152 0.663 1.756 -0.0782 0.3818 0.2702
- 267SOL HW3 981 0.290 0.741 1.794 0.4638 -0.1609 -0.5463
- 268SOL OW1 982 0.726 1.673 1.932 0.0207 0.0549 -0.1509
- 268SOL HW2 983 0.769 1.622 1.858 -0.8982 0.1103 -0.7589
- 268SOL HW3 984 0.636 1.705 1.902 -0.9405 -0.9577 1.3718
- 269SOL OW1 985 1.972 2.141 1.330 -0.4534 0.1086 0.0010
- 269SOL HW2 986 2.025 2.077 1.275 -0.8246 -0.3034 0.1138
- 269SOL HW3 987 1.948 2.221 1.275 -0.6252 -0.1976 -0.3688
- 270SOL OW1 988 1.658 1.117 1.528 0.2607 -0.5341 -0.0100
- 270SOL HW2 989 1.730 1.101 1.460 0.4751 -0.3352 0.1681
- 270SOL HW3 990 1.645 1.033 1.582 -0.6765 -1.0626 -0.9830
- 271SOL OW1 991 1.119 1.542 2.054 0.0234 -0.3990 -0.3820
- 271SOL HW2 992 1.210 1.561 2.091 -0.0331 -1.2025 0.2400
- 271SOL HW3 993 1.075 1.471 2.110 -0.2812 -1.3285 -1.7155
- 272SOL OW1 994 1.237 1.275 2.048 -0.5531 0.0225 -0.1349
- 272SOL HW2 995 1.171 1.285 2.123 -1.7612 -1.3556 -0.8992
- 272SOL HW3 996 1.208 1.332 1.971 0.4170 1.0569 0.2158
- 273SOL OW1 997 0.540 0.171 1.038 0.3354 -0.6817 -0.0134
- 273SOL HW2 998 0.520 0.245 1.102 -0.5285 -1.4808 0.6939
- 273SOL HW3 999 0.467 0.103 1.041 0.7022 -1.1941 -1.2252
- 274SOL OW1 1000 0.975 1.311 0.726 0.5964 -0.2290 -0.3184
- 274SOL HW2 1001 1.025 1.358 0.799 -0.2221 0.1840 0.0004
- 274SOL HW3 1002 0.976 1.213 0.743 -2.4172 -0.1446 2.3673
- 275SOL OW1 1003 0.953 0.519 1.954 0.4663 0.0117 0.4285
- 275SOL HW2 1004 1.018 0.584 1.994 1.3126 -0.4641 -0.1157
- 275SOL HW3 1005 0.883 0.570 1.903 1.4991 0.5361 -0.5644
- 276SOL OW1 1006 0.419 0.711 0.228 -0.4438 -0.1473 -0.3698
- 276SOL HW2 1007 0.394 0.651 0.151 -0.2649 0.1585 -0.6684
- 276SOL HW3 1008 0.347 0.778 0.243 -0.5010 -0.2414 -0.2350
- 277SOL OW1 1009 1.116 1.454 1.805 0.1103 0.1292 -0.3284
- 277SOL HW2 1010 1.024 1.448 1.764 -0.4522 0.3372 0.8395
- 277SOL HW3 1011 1.111 1.504 1.891 0.9079 -1.6825 0.8948
- 278SOL OW1 1012 1.584 1.639 1.607 -0.5431 -0.0793 0.1061
- 278SOL HW2 1013 1.622 1.556 1.648 1.0321 0.2578 -0.5482
- 278SOL HW3 1014 1.488 1.649 1.635 -0.7532 -2.0017 0.3451
- 279SOL OW1 1015 0.954 2.046 0.262 0.4970 -0.1102 -0.0130
- 279SOL HW2 1016 0.970 1.953 0.294 1.0066 -0.3130 -0.7977
- 279SOL HW3 1017 1.029 2.105 0.291 -0.3206 0.3302 1.3667
- 280SOL OW1 1018 1.693 0.757 2.013 -0.0274 0.1625 0.1846
- 280SOL HW2 1019 1.595 0.736 2.020 0.0519 -1.0072 -1.2800
- 280SOL HW3 1020 1.706 0.853 1.989 -0.6645 0.8550 2.1968
- 281SOL OW1 1021 0.913 0.814 0.072 0.2924 0.0487 0.6119
- 281SOL HW2 1022 0.976 0.829 0.148 0.2435 2.2686 0.3178
- 281SOL HW3 1023 0.824 0.786 0.108 0.6651 -0.3940 1.2279
- 282SOL OW1 1024 1.917 1.960 2.147 -0.3048 -0.5074 0.0672
- 282SOL HW2 1025 1.968 1.925 2.067 -0.2317 0.6001 -0.4022
- 282SOL HW3 1026 1.958 1.923 2.230 0.6829 -0.4139 -0.3422
- 283SOL OW1 1027 0.933 1.247 1.896 0.7904 -0.1360 0.0571
- 283SOL HW2 1028 0.899 1.240 1.802 1.2532 -0.2693 -0.0993
- 283SOL HW3 1029 0.877 1.312 1.947 0.0390 -0.6455 -0.0867
- 284SOL OW1 1030 1.075 0.276 1.941 -0.0296 0.2682 -0.0047
- 284SOL HW2 1031 1.167 0.267 1.904 0.6220 1.1655 1.2566
- 284SOL HW3 1032 1.044 0.370 1.933 0.8334 0.9939 2.8727
- 285SOL OW1 1033 1.984 1.681 1.095 -0.3031 -0.2150 -0.3904
- 285SOL HW2 1034 1.964 1.778 1.109 0.1490 -0.1971 0.1779
- 285SOL HW3 1035 2.032 1.645 1.175 2.9218 0.0086 -1.9199
- 286SOL OW1 1036 0.416 1.972 0.721 0.0236 -0.8542 0.4856
- 286SOL HW2 1037 0.406 1.990 0.819 1.3393 1.0164 0.3743
- 286SOL HW3 1038 0.367 2.042 0.669 1.2748 -0.3758 -0.1153
- 287SOL OW1 1039 1.455 2.162 1.404 0.0789 -0.3076 -0.2559
- 287SOL HW2 1040 1.405 2.132 1.323 -1.0966 -0.2658 0.4090
- 287SOL HW3 1041 1.473 2.083 1.463 -1.2460 -0.0461 0.5554
- 288SOL OW1 1042 0.259 2.155 0.589 0.1260 0.6444 -0.0772
- 288SOL HW2 1043 0.164 2.123 0.585 0.0568 0.9313 -1.6776
- 288SOL HW3 1044 0.311 2.116 0.514 1.3130 0.4927 0.7763
- 289SOL OW1 1045 1.280 0.215 1.748 1.0047 -0.5879 -0.8177
- 289SOL HW2 1046 1.344 0.215 1.671 0.5260 -0.0547 -1.2353
- 289SOL HW3 1047 1.187 0.229 1.714 0.9365 1.5047 -0.0661
- 290SOL OW1 1048 1.978 2.189 1.060 -0.1456 -0.1797 0.0410
- 290SOL HW2 1049 1.975 2.198 0.961 -1.3919 1.5237 0.1591
- 290SOL HW3 1050 2.055 2.241 1.097 -0.4933 0.3586 0.0212
- 291SOL OW1 1051 1.256 2.020 0.851 -0.0820 0.2327 0.2151
- 291SOL HW2 1052 1.175 1.994 0.797 -0.8015 1.1566 0.8055
- 291SOL HW3 1053 1.257 1.969 0.937 -0.2796 0.5172 0.3853
- 292SOL OW1 1054 1.644 2.238 1.203 0.2588 0.3076 -0.6026
- 292SOL HW2 1055 1.650 2.216 1.105 2.4804 0.2945 -0.5715
- 292SOL HW3 1056 1.679 2.331 1.218 0.1668 0.2244 0.1896
- 293SOL OW1 1057 1.247 0.201 0.937 -0.5878 -0.0681 0.1382
- 293SOL HW2 1058 1.222 0.282 0.989 -0.0725 0.1658 0.0337
- 293SOL HW3 1059 1.347 0.197 0.927 -0.6251 1.4574 -3.1918
- 294SOL OW1 1060 1.140 0.958 0.211 -0.0049 0.3410 0.1559
- 294SOL HW2 1061 1.168 0.956 0.307 2.8205 -0.9272 -0.5224
- 294SOL HW3 1062 1.183 0.884 0.161 0.8471 2.3716 -2.6039
- 295SOL OW1 1063 0.889 2.106 0.513 0.9659 -0.5531 0.6999
- 295SOL HW2 1064 0.936 2.115 0.426 -0.0005 -0.2868 0.1832
- 295SOL HW3 1065 0.942 2.151 0.585 1.4576 -0.2157 0.1344
- 296SOL OW1 1066 0.029 2.026 1.765 -0.4433 -0.5379 0.6112
- 296SOL HW2 1067 0.018 2.077 1.680 -0.8408 -2.1014 -0.3715
- 296SOL HW3 1068 0.045 2.089 1.841 -1.3062 1.0111 -0.3955
- 297SOL OW1 1069 1.267 0.057 0.709 0.9387 -0.3073 -0.4524
- 297SOL HW2 1070 1.362 0.043 0.680 1.1152 2.0742 -1.4971
- 297SOL HW3 1071 1.265 0.124 0.783 0.1184 1.6341 -2.0669
- 298SOL OW1 1072 1.259 1.929 2.044 0.2442 0.1771 0.3725
- 298SOL HW2 1073 1.297 2.021 2.039 -1.0129 0.7674 0.8496
- 298SOL HW3 1074 1.161 1.934 2.065 -0.0393 -1.2573 -0.3601
- 299SOL OW1 1075 2.023 1.721 0.640 0.2865 -0.5265 -0.7926
- 299SOL HW2 1076 2.120 1.705 0.656 0.1931 -3.3458 -1.8557
- 299SOL HW3 1077 1.973 1.717 0.726 1.0495 3.6657 0.2647
- 300SOL OW1 1078 0.380 0.947 1.335 0.8461 0.7453 -0.0901
- 300SOL HW2 1079 0.357 0.870 1.394 -0.4477 -0.4841 -1.9476
- 300SOL HW3 1080 0.427 1.017 1.387 0.8912 -0.7010 2.0392
- 301SOL OW1 1081 1.918 1.646 1.739 -0.0535 0.6170 0.5572
- 301SOL HW2 1082 1.830 1.671 1.778 -0.9732 -1.5312 0.1268
- 301SOL HW3 1083 1.909 1.632 1.640 0.0305 -1.8481 0.7779
- 302SOL OW1 1084 0.048 1.813 1.462 0.0335 0.0653 -0.1951
- 302SOL HW2 1085 0.077 1.861 1.379 -1.0583 1.3938 0.1101
- 302SOL HW3 1086 -0.045 1.842 1.486 0.3382 -0.1826 1.5425
- 303SOL OW1 1087 0.596 1.425 0.458 -0.1987 0.2503 -0.1817
- 303SOL HW2 1088 0.619 1.522 0.444 -1.0996 0.5916 0.5457
- 303SOL HW3 1089 0.558 1.387 0.373 0.0408 0.5640 -0.4296
- 304SOL OW1 1090 1.563 0.140 1.927 0.3645 -0.0913 0.0944
- 304SOL HW2 1091 1.571 0.089 1.841 -1.5264 -1.2190 0.4652
- 304SOL HW3 1092 1.546 0.076 2.002 0.3737 0.9595 1.0419
- 305SOL OW1 1093 0.067 2.267 0.764 -0.0999 0.4859 -0.1641
- 305SOL HW2 1094 0.124 2.219 0.830 0.9073 0.0300 -1.2879
- 305SOL HW3 1095 0.118 2.281 0.679 -1.4279 0.7244 -0.9909
- 306SOL OW1 1096 0.801 0.203 0.190 0.6493 0.1668 0.4170
- 306SOL HW2 1097 0.832 0.108 0.194 -1.1922 -0.6337 -0.9809
- 306SOL HW3 1098 0.869 0.258 0.142 0.5212 -1.2523 -1.6849
- 307SOL OW1 1099 0.533 1.887 2.128 0.0226 0.6627 -0.2580
- 307SOL HW2 1100 0.470 1.852 2.058 -2.4602 -0.7732 2.2595
- 307SOL HW3 1101 0.585 1.812 2.166 -2.3913 0.0245 2.4930
- 308SOL OW1 1102 0.528 1.412 1.632 -0.8352 -0.0469 0.5465
- 308SOL HW2 1103 0.443 1.360 1.624 -1.3150 0.7869 -0.2050
- 308SOL HW3 1104 0.506 1.508 1.653 -0.0500 0.0908 0.8007
- 309SOL OW1 1105 1.381 0.093 1.233 -0.0587 0.1976 0.4752
- 309SOL HW2 1106 1.412 0.001 1.208 -0.7652 0.5636 -2.5755
- 309SOL HW3 1107 1.446 0.161 1.199 -0.2696 0.8705 1.3496
- 310SOL OW1 1108 0.770 0.169 2.070 0.4545 0.5678 0.6666
- 310SOL HW2 1109 0.753 0.071 2.060 -0.4028 0.8212 -1.8942
- 310SOL HW3 1110 0.754 0.196 2.165 0.4253 -1.6691 1.4204
- 311SOL OW1 1111 1.454 1.409 1.046 0.5445 0.2513 -0.0296
- 311SOL HW2 1112 1.469 1.320 1.002 1.2183 1.0000 -1.4346
- 311SOL HW3 1113 1.541 1.445 1.077 0.3879 0.7344 -0.1447
- 312SOL OW1 1114 0.085 2.006 1.239 -0.1167 -0.4359 0.1726
- 312SOL HW2 1115 0.133 1.923 1.211 1.4401 -0.0054 1.2985
- 312SOL HW3 1116 0.140 2.086 1.215 -0.6655 0.1501 0.7875
- 313SOL OW1 1117 1.461 2.105 2.033 -0.1383 0.4784 0.0319
- 313SOL HW2 1118 1.478 2.186 2.089 -0.2246 -0.4473 1.5216
- 313SOL HW3 1119 1.535 2.039 2.047 -0.2618 0.1197 -0.8496
- 314SOL OW1 1120 0.340 1.308 0.799 0.9160 -0.1565 -0.2207
- 314SOL HW2 1121 0.411 1.241 0.777 2.2208 0.4793 1.5386
- 314SOL HW3 1122 0.348 1.387 0.739 1.9791 0.0400 0.1429
- 315SOL OW1 1123 0.929 2.151 1.222 -0.5944 0.1197 0.1351
- 315SOL HW2 1124 0.895 2.230 1.172 0.0852 0.3808 0.0725
- 315SOL HW3 1125 0.964 2.083 1.157 -1.1072 -0.2027 0.1943
- 316SOL OW1 1126 2.100 0.948 1.315 0.4221 0.4586 -0.4373
- 316SOL HW2 1127 2.064 0.871 1.262 -1.7043 1.3522 -0.4889
- 316SOL HW3 1128 2.126 0.916 1.406 0.0188 -0.4015 -0.6065
- 317SOL OW1 1129 1.145 1.038 1.546 -0.1093 0.2955 0.0122
- 317SOL HW2 1130 1.158 1.023 1.644 -2.2044 -2.3553 0.1003
- 317SOL HW3 1131 1.224 1.002 1.496 1.4082 2.4793 0.5554
- 318SOL OW1 1132 1.912 1.296 1.526 0.3522 -0.3134 -0.1810
- 318SOL HW2 1133 1.885 1.282 1.622 -3.2052 -0.1144 -0.8638
- 318SOL HW3 1134 1.911 1.394 1.506 1.9986 -0.2848 -0.3211
- 319SOL OW1 1135 1.384 0.628 0.446 0.4008 -0.0933 -0.1623
- 319SOL HW2 1136 1.420 0.534 0.445 -0.5526 -0.4827 -0.8141
- 319SOL HW3 1137 1.301 0.631 0.502 0.8043 0.5429 0.4324
- 320SOL OW1 1138 0.858 0.558 0.090 -0.0122 0.1778 -0.0083
- 320SOL HW2 1139 0.911 0.635 0.054 -0.1280 -0.5815 -2.0910
- 320SOL HW3 1140 0.781 0.540 0.029 -2.1907 0.5699 2.3116
- 321SOL OW1 1141 1.860 0.831 0.254 0.7899 0.0549 -0.0619
- 321SOL HW2 1142 1.916 0.882 0.189 -0.3759 0.1824 -1.0219
- 321SOL HW3 1143 1.808 0.895 0.311 -0.3971 0.0190 -1.0279
- 322SOL OW1 1144 1.844 1.229 1.776 0.1141 0.0489 0.6993
- 322SOL HW2 1145 1.774 1.287 1.735 1.1835 1.2181 0.4048
- 322SOL HW3 1146 1.848 1.247 1.874 0.2519 0.2844 0.6511
- 323SOL OW1 1147 1.233 1.411 0.296 0.2309 -0.1874 0.3203
- 323SOL HW2 1148 1.299 1.439 0.227 -0.6722 0.2931 -0.3849
- 323SOL HW3 1149 1.221 1.485 0.362 -0.9687 0.5342 -0.6407
- 324SOL OW1 1150 1.129 1.788 1.779 -0.6566 0.2734 -0.6771
- 324SOL HW2 1151 1.123 1.876 1.733 1.2428 0.8152 -0.0582
- 324SOL HW3 1152 1.104 1.799 1.876 1.1301 0.6399 -0.1725
- 325SOL OW1 1153 0.737 0.026 1.221 0.0077 0.0778 -0.5632
- 325SOL HW2 1154 0.673 0.091 1.181 1.6127 2.0068 -0.3141
- 325SOL HW3 1155 0.784 0.069 1.298 2.2379 -0.7853 -1.2836
- 326SOL OW1 1156 1.509 1.796 0.775 -0.2051 0.1182 -0.1425
- 326SOL HW2 1157 1.480 1.891 0.789 -1.8179 0.0203 -2.0527
- 326SOL HW3 1158 1.582 1.793 0.708 0.2218 -0.0019 0.3159
- 327SOL OW1 1159 0.027 0.580 0.031 0.2837 -0.1428 -0.4424
- 327SOL HW2 1160 0.086 0.601 0.109 0.7012 -0.5373 -0.6436
- 327SOL HW3 1161 0.013 0.663 -0.023 2.3162 -0.3566 -1.4869
- 328SOL OW1 1162 1.185 0.507 1.761 0.2547 0.1429 0.4548
- 328SOL HW2 1163 1.221 0.488 1.670 0.7551 4.0340 -0.5010
- 328SOL HW3 1164 1.086 0.494 1.760 0.4541 -2.2470 0.3296
- 329SOL OW1 1165 0.365 1.621 0.943 -0.7039 -0.0471 -0.5873
- 329SOL HW2 1166 0.450 1.575 0.916 0.0127 0.8943 -0.0353
- 329SOL HW3 1167 0.287 1.564 0.915 0.0947 -1.1815 -0.6706
- 330SOL OW1 1168 1.061 1.884 0.681 0.2105 -0.1813 -0.0737
- 330SOL HW2 1169 0.965 1.866 0.702 0.0836 0.4474 -0.0774
- 330SOL HW3 1170 1.118 1.808 0.713 -0.2677 -0.4826 0.0686
- 331SOL OW1 1171 0.243 2.021 2.082 0.2709 -0.1350 0.3389
- 331SOL HW2 1172 0.166 2.083 2.064 -0.1299 -0.3362 1.3095
- 331SOL HW3 1173 0.324 2.054 2.033 -0.2382 0.4884 -0.1123
- 332SOL OW1 1174 1.919 1.937 1.507 0.2408 -0.0323 0.4649
- 332SOL HW2 1175 1.850 1.964 1.575 -1.5352 -1.1953 -0.6733
- 332SOL HW3 1176 1.918 2.001 1.431 -0.4900 -0.6189 -0.0565
- 333SOL OW1 1177 0.933 1.790 0.355 -0.3352 0.0057 -0.0255
- 333SOL HW2 1178 0.957 1.756 0.446 1.0694 1.2429 0.1363
- 333SOL HW3 1179 0.981 1.736 0.286 -0.8918 -0.5180 -0.0161
- 334SOL OW1 1180 0.800 0.372 0.419 0.0355 -0.1714 -0.0748
- 334SOL HW2 1181 0.777 0.317 0.339 -0.3391 -0.3275 0.1383
- 334SOL HW3 1182 0.794 0.315 0.502 0.3118 0.0168 0.0759
- 335SOL OW1 1183 1.512 1.331 2.115 0.0868 0.4288 -0.8723
- 335SOL HW2 1184 1.521 1.271 2.036 0.4469 1.8393 -1.9765
- 335SOL HW3 1185 1.418 1.329 2.148 0.1779 -1.0321 -0.5578
- 336SOL OW1 1186 0.727 1.843 0.989 0.3361 0.5755 -0.0955
- 336SOL HW2 1187 0.719 1.929 1.039 2.1985 2.5596 -2.6490
- 336SOL HW3 1188 0.716 1.861 0.891 4.2448 -1.1747 -1.2396
- 337SOL OW1 1189 1.617 2.308 0.699 0.3564 0.1586 -0.2502
- 337SOL HW2 1190 1.609 2.361 0.615 -2.1644 0.3376 -0.0496
- 337SOL HW3 1191 1.595 2.212 0.680 0.1679 0.1249 0.1341
- 338SOL OW1 1192 0.339 0.164 0.237 0.2883 0.5473 -0.0562
- 338SOL HW2 1193 0.260 0.183 0.295 -1.2717 -1.9668 -1.0349
- 338SOL HW3 1194 0.397 0.095 0.281 -0.2030 -0.4120 -0.8363
- 339SOL OW1 1195 0.631 1.006 1.788 -0.3762 -0.1030 -0.1886
- 339SOL HW2 1196 0.713 0.950 1.788 -0.7522 -1.0567 3.2108
- 339SOL HW3 1197 0.656 1.102 1.802 0.1590 -0.1925 -0.5066
- 340SOL OW1 1198 1.618 1.446 0.483 -0.6540 0.2783 0.2438
- 340SOL HW2 1199 1.714 1.457 0.459 -1.0449 -0.5335 -2.3743
- 340SOL HW3 1200 1.563 1.516 0.436 -1.5434 -1.6326 -2.0173
- 341SOL OW1 1201 1.395 1.785 1.314 -0.6522 -0.0111 -1.1168
- 341SOL HW2 1202 1.323 1.848 1.340 1.6876 2.0763 1.6400
- 341SOL HW3 1203 1.371 1.692 1.344 -1.8450 0.7648 0.6598
- 342SOL OW1 1204 1.964 0.913 0.014 -0.3584 -0.0188 0.4452
- 342SOL HW2 1205 1.867 0.937 0.004 -0.8084 -1.4691 0.9152
- 342SOL HW3 1206 1.995 0.864 -0.068 -0.4902 -0.8971 0.9007
- 343SOL OW1 1207 0.623 1.073 1.228 -0.2576 0.2708 0.0802
- 343SOL HW2 1208 0.532 1.102 1.199 -0.4763 1.7749 1.8722
- 343SOL HW3 1209 0.636 1.095 1.325 2.0537 0.2199 -0.1018
- 344SOL OW1 1210 0.045 1.543 2.087 0.0121 0.4452 0.1073
- 344SOL HW2 1211 0.096 1.484 2.149 0.3859 -0.4229 -0.9643
- 344SOL HW3 1212 0.087 1.634 2.085 1.2304 -0.0871 -0.3117
- 345SOL OW1 1213 2.076 1.812 0.142 0.2289 0.2330 0.1957
- 345SOL HW2 1214 2.051 1.804 0.239 -2.0749 -0.9232 -0.3680
- 345SOL HW3 1215 2.171 1.844 0.135 0.5722 0.2072 2.7961
- 346SOL OW1 1216 0.973 2.308 1.649 -0.0363 0.6628 -0.4252
- 346SOL HW2 1217 1.065 2.346 1.636 1.2491 -1.5838 0.9213
- 346SOL HW3 1218 0.929 2.354 1.726 -0.5261 2.3091 -1.5627
- 347SOL OW1 1219 1.052 0.266 1.596 0.2113 0.4111 -0.0833
- 347SOL HW2 1220 1.085 0.245 1.504 2.7294 1.2937 0.4343
- 347SOL HW3 1221 0.965 0.314 1.591 0.0805 0.0927 -1.9646
- 348SOL OW1 1222 1.489 0.871 0.495 0.1547 -0.3292 0.0575
- 348SOL HW2 1223 1.450 0.779 0.494 0.1465 -0.3234 -0.0264
- 348SOL HW3 1224 1.557 0.879 0.422 1.1807 -0.6952 0.9225
- 349SOL OW1 1225 0.938 0.549 1.101 0.1357 0.1533 0.2190
- 349SOL HW2 1226 0.916 0.624 1.164 -0.0842 0.8688 -0.6756
- 349SOL HW3 1227 0.910 0.463 1.143 -2.5885 0.7789 0.1099
- 350SOL OW1 1228 0.704 0.626 0.668 0.6157 0.1806 0.0715
- 350SOL HW2 1229 0.655 0.539 0.662 2.2438 -0.9351 1.2245
- 350SOL HW3 1230 0.678 0.684 0.591 -1.9246 -0.5093 0.2291
- 351SOL OW1 1231 0.630 1.282 1.829 0.8725 -0.4090 -0.2307
- 351SOL HW2 1232 0.684 1.337 1.893 0.4285 -0.7096 0.4214
- 351SOL HW3 1233 0.595 1.341 1.756 -1.5060 0.7973 1.6184
- 352SOL OW1 1234 1.564 0.161 0.889 -0.3152 0.1492 -0.7084
- 352SOL HW2 1235 1.592 0.076 0.845 2.0832 0.3671 0.0895
- 352SOL HW3 1236 1.630 0.184 0.961 -2.2702 1.3953 0.9036
- 353SOL OW1 1237 0.394 1.720 0.276 0.1173 0.0420 -0.3110
- 353SOL HW2 1238 0.321 1.775 0.316 -0.8055 -1.5132 0.3387
- 353SOL HW3 1239 0.367 1.692 0.183 -0.3823 -0.8813 0.0847
- 354SOL OW1 1240 0.756 2.329 0.436 0.5990 -0.0603 -0.0024
- 354SOL HW2 1241 0.801 2.242 0.458 0.5313 -0.5679 -1.6092
- 354SOL HW3 1242 0.808 2.404 0.476 1.9649 -0.7294 -0.4040
- 355SOL OW1 1243 0.885 2.251 0.085 0.6383 -0.2396 -0.6881
- 355SOL HW2 1244 0.826 2.232 0.008 -0.3880 0.6365 -0.1671
- 355SOL HW3 1245 0.858 2.195 0.163 -0.7030 1.2621 0.0525
- 356SOL OW1 1246 0.197 1.989 0.151 -0.0589 0.3862 -0.4144
- 356SOL HW2 1247 0.141 2.061 0.192 -1.2333 0.6664 -2.2701
- 356SOL HW3 1248 0.204 2.004 0.052 -0.2276 -1.9258 -0.9016
- 357SOL OW1 1249 1.223 1.073 1.234 -0.1838 0.8167 -0.0918
- 357SOL HW2 1250 1.235 1.069 1.135 -0.3070 0.9161 -0.1089
- 357SOL HW3 1251 1.295 1.019 1.278 -0.6642 0.0019 -0.2646
- 358SOL OW1 1252 1.758 0.185 1.103 0.7252 0.3838 0.7167
- 358SOL HW2 1253 1.699 0.243 1.159 -1.3011 -1.3475 0.6155
- 358SOL HW3 1254 1.832 0.148 1.159 0.8983 1.4621 1.2472
- 359SOL OW1 1255 0.138 1.505 0.848 -0.0638 0.1356 -0.1292
- 359SOL HW2 1256 0.152 1.485 0.751 -1.9054 -0.4357 -0.3498
- 359SOL HW3 1257 0.117 1.420 0.897 0.9665 0.3905 0.8413
- 360SOL OW1 1258 0.981 1.709 0.948 -0.1266 0.0977 -0.1316
- 360SOL HW2 1259 0.888 1.742 0.967 0.1471 0.0502 1.6697
- 360SOL HW3 1260 0.986 1.612 0.970 -0.0920 -0.4444 -2.1942
- 361SOL OW1 1261 0.498 0.500 0.414 -0.2412 0.2503 0.1252
- 361SOL HW2 1262 0.589 0.536 0.394 -0.9357 1.6307 -0.8297
- 361SOL HW3 1263 0.432 0.538 0.350 -1.3749 -1.4911 0.1255
- 362SOL OW1 1264 0.800 1.211 1.007 1.2113 -0.5321 0.4601
- 362SOL HW2 1265 0.863 1.230 1.083 0.7992 0.2314 0.6267
- 362SOL HW3 1266 0.729 1.148 1.038 0.0668 1.0413 1.2860
- 363SOL OW1 1267 1.255 0.495 0.829 0.2436 0.2108 -0.5205
- 363SOL HW2 1268 1.208 0.581 0.848 0.2590 0.2289 -0.5742
- 363SOL HW3 1269 1.280 0.491 0.732 -1.3244 -0.5928 -0.9613
- 364SOL OW1 1270 0.437 1.421 0.231 -0.9420 0.0497 0.5702
- 364SOL HW2 1271 0.414 1.513 0.263 -0.0214 1.0948 -1.3975
- 364SOL HW3 1272 0.391 1.403 0.144 0.8339 -0.1955 -0.4199
- 365SOL OW1 1273 1.460 0.494 1.002 0.0155 -0.2857 -0.6445
- 365SOL HW2 1274 1.377 0.489 0.946 -1.6651 -1.6727 1.6206
- 365SOL HW3 1275 1.475 0.589 1.029 -0.6572 0.0437 -1.3404
- 366SOL OW1 1276 1.926 0.063 1.267 0.2483 -0.1883 -0.1945
- 366SOL HW2 1277 2.010 0.107 1.237 0.2736 0.4869 0.8096
- 366SOL HW3 1278 1.902 0.094 1.359 -1.5281 0.2719 -0.7414
- 367SOL OW1 1279 1.617 0.457 1.356 0.4690 0.2356 -0.4113
- 367SOL HW2 1280 1.623 0.423 1.450 -2.9891 -2.7892 -0.8426
- 367SOL HW3 1281 1.564 0.542 1.354 -1.3832 -0.7857 0.4810
- 368SOL OW1 1282 0.598 1.510 0.707 -0.0516 0.5519 0.4414
- 368SOL HW2 1283 0.592 1.453 0.625 -2.2716 -0.8214 1.3958
- 368SOL HW3 1284 0.566 1.602 0.685 -0.7429 0.1708 -0.2256
- 369SOL OW1 1285 1.649 0.851 1.593 -0.0436 0.0262 0.5595
- 369SOL HW2 1286 1.604 0.762 1.605 0.0920 -0.2687 -0.7439
- 369SOL HW3 1287 1.739 0.850 1.636 -0.9417 0.4109 2.6545
- 370SOL OW1 1288 0.523 1.020 2.125 -0.1503 -0.4224 -0.1771
- 370SOL HW2 1289 0.614 1.035 2.086 0.2283 0.0730 0.8203
- 370SOL HW3 1290 0.498 0.924 2.114 1.6699 -1.2915 1.7056
- 371SOL OW1 1291 0.542 2.278 0.279 0.0314 0.1883 -0.1521
- 371SOL HW2 1292 0.632 2.295 0.319 0.2941 -1.4280 0.0663
- 371SOL HW3 1293 0.553 2.231 0.192 -0.5978 -0.2083 -0.0217
- 372SOL OW1 1294 0.110 1.487 1.575 0.0351 -0.7548 -0.3625
- 372SOL HW2 1295 0.105 1.391 1.546 0.9934 -1.2565 0.9413
- 372SOL HW3 1296 0.077 1.495 1.669 -0.3170 0.2761 -0.5496
- 373SOL OW1 1297 1.150 1.993 1.405 -0.5974 0.3356 -0.2624
- 373SOL HW2 1298 1.193 2.069 1.355 0.7441 0.2856 0.7164
- 373SOL HW3 1299 1.145 2.015 1.502 -1.6321 -0.2306 -0.1637
- 374SOL OW1 1300 0.716 2.233 2.024 0.3004 -0.1334 0.0678
- 374SOL HW2 1301 0.771 2.160 1.983 0.8764 0.8194 -0.9512
- 374SOL HW3 1302 0.626 2.198 2.047 1.1929 -1.7222 1.6543
- 375SOL OW1 1303 0.620 0.486 2.129 0.3881 0.5202 0.2084
- 375SOL HW2 1304 0.595 0.414 2.194 0.0033 0.0080 -0.4925
- 375SOL HW3 1305 0.576 0.469 2.041 2.2358 0.2248 -0.7452
- 376SOL OW1 1306 0.738 0.766 2.000 -0.2642 -0.4550 -0.2552
- 376SOL HW2 1307 0.758 0.863 2.013 -0.3771 -0.3098 -1.0841
- 376SOL HW3 1308 0.683 0.733 2.077 0.0931 0.0367 0.2266
- 377SOL OW1 1309 0.642 1.965 0.512 0.2993 -0.0891 0.2094
- 377SOL HW2 1310 0.573 1.982 0.441 -0.8856 0.4081 1.4044
- 377SOL HW3 1311 0.717 2.029 0.500 -1.0243 1.7262 0.7416
- 378SOL OW1 1312 1.872 0.083 1.935 -0.5347 0.2032 0.0159
- 378SOL HW2 1313 1.870 0.009 2.002 0.6811 1.2194 1.2930
- 378SOL HW3 1314 1.880 0.045 1.843 1.2108 -1.3043 0.6806
- 379SOL OW1 1315 0.832 0.155 1.438 0.2556 -0.4593 0.4941
- 379SOL HW2 1316 0.796 0.215 1.509 -0.8868 0.3052 -0.6515
- 379SOL HW3 1317 0.918 0.115 1.469 1.3358 2.0519 1.2105
- 380SOL OW1 1318 1.775 1.909 0.856 -0.4436 -0.4835 0.1120
- 380SOL HW2 1319 1.790 1.816 0.820 0.4624 -0.4765 0.4355
- 380SOL HW3 1320 1.818 1.917 0.946 -0.7355 0.1846 0.1987
- 381SOL OW1 1321 1.868 0.764 0.768 -0.0259 -0.0227 -0.3363
- 381SOL HW2 1322 1.961 0.731 0.786 -0.0120 0.3945 0.4483
- 381SOL HW3 1323 1.810 0.686 0.744 -0.1371 -0.8816 2.0730
- 382SOL OW1 1324 2.081 0.375 1.517 -0.4671 0.6184 0.4154
- 382SOL HW2 1325 1.987 0.402 1.534 -0.7423 -0.6888 1.2676
- 382SOL HW3 1326 2.082 0.293 1.460 0.1717 0.7063 0.2864
- 383SOL OW1 1327 0.177 0.932 1.560 -0.3843 -0.0472 -0.6301
- 383SOL HW2 1328 0.180 0.966 1.654 0.6020 2.4626 -1.4114
- 383SOL HW3 1329 0.230 0.847 1.554 -0.6400 -0.3870 1.0695
- 384SOL OW1 1330 1.650 2.137 0.935 -0.1129 -0.3985 -0.0997
- 384SOL HW2 1331 1.686 2.045 0.916 0.7573 -0.3583 1.1268
- 384SOL HW3 1332 1.717 2.206 0.908 0.2210 -0.2618 0.9869
- 385SOL OW1 1333 0.750 1.403 0.111 -0.6115 -0.1659 -0.2487
- 385SOL HW2 1334 0.671 1.342 0.109 -0.5361 -0.2806 -1.4666
- 385SOL HW3 1335 0.787 1.408 0.204 -0.4625 -2.1811 -0.1244
- 386SOL OW1 1336 0.033 1.988 0.642 -0.0599 0.6337 -0.2454
- 386SOL HW2 1337 0.024 2.036 0.729 -1.0164 0.9044 -0.4709
- 386SOL HW3 1338 0.037 1.889 0.658 1.0552 0.7130 0.1605
- 387SOL OW1 1339 1.707 1.499 0.174 0.1081 0.0095 -0.4323
- 387SOL HW2 1340 1.785 1.562 0.181 0.9811 -1.0574 2.7464
- 387SOL HW3 1341 1.626 1.550 0.145 0.7286 2.7605 1.7946
- 388SOL OW1 1342 1.711 1.717 1.368 0.4610 0.4438 0.8829
- 388SOL HW2 1343 1.737 1.813 1.362 -1.7634 1.1141 -0.4482
- 388SOL HW3 1344 1.651 1.702 1.447 0.3085 0.2985 0.7396
- 389SOL OW1 1345 1.506 0.989 1.132 -0.6062 0.4189 -0.0253
- 389SOL HW2 1346 1.570 1.044 1.185 -0.8636 0.2733 0.4386
- 389SOL HW3 1347 1.465 1.046 1.060 0.2117 0.4484 -0.4855
- 390SOL OW1 1348 1.884 0.813 1.740 -0.1427 -0.1347 -0.0074
- 390SOL HW2 1349 1.823 0.851 1.810 -1.0767 -1.0786 -0.2533
- 390SOL HW3 1350 1.946 0.884 1.707 0.4213 0.3219 1.8382
- 391SOL OW1 1351 1.629 1.231 1.216 -0.3626 0.4568 -0.1572
- 391SOL HW2 1352 1.723 1.206 1.242 -0.2741 0.2659 -0.6372
- 391SOL HW3 1353 1.597 1.305 1.274 -0.0901 0.1964 0.3370
- 392SOL OW1 1354 0.485 2.286 0.583 0.1395 -0.2396 -0.3706
- 392SOL HW2 1355 0.531 2.271 0.496 2.0663 1.0403 0.3082
- 392SOL HW3 1356 0.388 2.263 0.574 0.2612 -0.2494 -2.7869
- 393SOL OW1 1357 0.613 0.789 1.519 -0.4909 -0.1533 -0.2373
- 393SOL HW2 1358 0.554 0.815 1.595 -0.5684 -2.1845 0.5120
- 393SOL HW3 1359 0.684 0.857 1.507 -2.3703 1.9727 -0.6281
- 2.10085 2.34032 2.18488 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
+++ /dev/null
-[ moleculetype ]
-; name nrexcl
-Urea 3
-
-[ atoms ]
-; nr type resnr residu atom cgnr charge
-#ifdef Boek
- 1 C 1 UREA C1 1 0.38
- 2 O 1 UREA O2 1 -0.38
- 3 NT 1 UREA N3 2 -0.83
- 4 H 1 UREA H4 2 0.415
- 5 H 1 UREA H5 2 0.415
- 6 NT 1 UREA N6 3 -0.83
- 7 H 1 UREA H7 3 0.415
- 8 H 1 UREA H8 3 0.415
-#else
- 1 C 1 UREA C1 1 0.683
- 2 O 1 UREA O2 1 -0.683
- 3 NT 1 UREA N3 2 -0.622
- 4 H 1 UREA H4 2 0.346
- 5 H 1 UREA H5 2 0.276
- 6 NT 1 UREA N6 3 -0.622
- 7 H 1 UREA H7 3 0.346
- 8 H 1 UREA H8 3 0.276
-#endif
-
-[ bonds ]
-; ai aj funct c0 c1
- 3 4 1 1.000000e-01 3.744680e+05
- 3 5 1 1.000000e-01 3.744680e+05
- 6 7 1 1.000000e-01 3.744680e+05
- 6 8 1 1.000000e-01 3.744680e+05
- 1 2 1 1.230000e-01 5.020800e+05
- 1 3 1 1.330000e-01 3.765600e+05
- 1 6 1 1.330000e-01 3.765600e+05
-
-[ pairs ]
-; ai aj funct c0 c1
- 2 4 1 0.000000e+00 0.000000e+00
- 2 5 1 0.000000e+00 0.000000e+00
- 2 7 1 0.000000e+00 0.000000e+00
- 2 8 1 0.000000e+00 0.000000e+00
- 3 7 1 0.000000e+00 0.000000e+00
- 3 8 1 0.000000e+00 0.000000e+00
- 4 6 1 0.000000e+00 0.000000e+00
- 5 6 1 0.000000e+00 0.000000e+00
-
-[ angles ]
-; ai aj ak funct c0 c1
- 1 3 4 1 1.200000e+02 2.928800e+02
- 1 3 5 1 1.200000e+02 2.928800e+02
- 4 3 5 1 1.200000e+02 3.347200e+02
- 1 6 7 1 1.200000e+02 2.928800e+02
- 1 6 8 1 1.200000e+02 2.928800e+02
- 7 6 8 1 1.200000e+02 3.347200e+02
- 2 1 3 1 1.215000e+02 5.020800e+02
- 2 1 6 1 1.215000e+02 5.020800e+02
- 3 1 6 1 1.170000e+02 5.020800e+02
-
-[ dihedrals ]
-; ai aj ak al funct c0 c1 c2
- 2 1 3 4 1 1.800000e+02 3.347200e+01 2.000000e+00
- 6 1 3 4 1 1.800000e+02 3.347200e+01 2.000000e+00
- 2 1 3 5 1 1.800000e+02 3.347200e+01 2.000000e+00
- 6 1 3 5 1 1.800000e+02 3.347200e+01 2.000000e+00
- 2 1 6 7 1 1.800000e+02 3.347200e+01 2.000000e+00
- 3 1 6 7 1 1.800000e+02 3.347200e+01 2.000000e+00
- 2 1 6 8 1 1.800000e+02 3.347200e+01 2.000000e+00
- 3 1 6 8 1 1.800000e+02 3.347200e+01 2.000000e+00
-
-[ dihedrals ]
-; ai aj ak al funct c0 c1
- 3 4 5 1 2 0.000000e+00 1.673600e+02
- 6 7 8 1 2 0.000000e+00 1.673600e+02
- 1 3 6 2 2 0.000000e+00 1.673600e+02
-
mdrun:
(cd $(top_builddir)/src/gmxlib && $(MAKE))
(cd $(top_builddir)/src/mdlib && $(MAKE))
- (cd $(top_builddir)/src/kernel && $(MAKE) lib_LTLIBRARIES)
(cd $(top_builddir)/src/kernel && $(MAKE) mdrun)
install-mdrun:
/* Define to 1 if you have the xml2 library (-lxml2). */
#cmakedefine HAVE_LIBXML2
+/* Define to 1 if you have the dl library (-ldl). */
+#cmakedefine HAVE_LIBDL
+
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_SCHED_H
+/* Have copyfile.h */
+#cmakedefine HAVE_COPYFILE_H
+
+/* Have io.h (windows)*/
+#cmakedefine HAVE_IO_H
+
/* Define to 1 if you have the strcasecmp() function. */
#cmakedefine HAVE_STRCASECMP
/* Define to 1 if you have the memcmp() function. */
#cmakedefine HAVE_MEMCMP
+/* Define to 1 if you have the posix_memalign() function. */
+#cmakedefine HAVE_POSIX_MEMALIGN
+
+/* Define to 1 if you have the memalign() function. */
+#cmakedefine HAVE_MEMALIGN
+
+/* Define to 1 if you have the MSVC _aligned_malloc() function. */
+#cmakedefine HAVE__ALIGNED_MALLOC
+
/* Define to 1 if you have the gettimeofday() function. */
#cmakedefine HAVE_GETTIMEOFDAY
+/* Define to 1 if you have the cbrt() function. */
+#cmakedefine HAVE_CBRT
+
/* Define to 1 if you have the isnan() function. */
#cmakedefine HAVE_ISNAN
/* Define to 1 if you have the _isfinite() function. */
#cmakedefine HAVE__ISFINITE
+/* Define to 1 if you have the fsync() function. */
+#cmakedefine HAVE_FSYNC
+
+/* Define to 1 if you have the Windows _commit() function. */
+#cmakedefine HAVE__COMMIT
+
+/* Define to 1 if you have the fileno() function. */
+#cmakedefine HAVE_FILENO
+
+/* Define to 1 if you have the _fileno() function. */
+#cmakedefine HAVE__FILENO
+
+/* Define to 1 if you have the copyfile() function. */
+#cmakedefine HAVE_COPYFILE
+
+/* Define to 1 if you have the Windows CopyFile() function. */
+#cmakedefine HAVE_WIN_COPYFILE
+
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H
# Note: you don't have to list sources for "prog" if it is the single file prog.c
CLEANFILES = *~ \\\#*
-
-
-
-
-
-
-
-
-
-
"[TT]xpm[tt] matrices) and in all time options."
};
+ output_env_t oenv=NULL;
CopyRight(stderr,argv[0]);
parse_common_args(&argc,argv,0,
- 0,NULL,0,NULL,asize(desc),desc,asize(bugs),bugs);
+ 0,NULL,0,NULL,asize(desc),desc,asize(bugs),bugs,&oenv);
thanx(stderr);
add_library(gmx ${GMXLIB_SOURCES} ${BLAS_SOURCES} ${LAPACK_SOURCES} ${GMX_MORESSE_SOURCES} ${GMX_SSE2_SOURCES} ${THREAD_MPI_SRC})
target_link_libraries(gmx ${GMX_EXTRA_LIBRARIES} ${THREAD_LIB})
add_dependencies(gmx gmx_version)
+set_target_properties(gmx PROPERTIES OUTPUT_NAME "gmx${GMX_BINARY_SUFFIX}")
install(TARGETS gmx DESTINATION ${LIB_INSTALL_DIR})
3dview.c atomprop.c bondfree.c \
calcgrid.c calch.c chargegroup.c checkpoint.c \
confio.c copyrite.c disre.c do_fit.c \
- enxio.c ewald_util.c gmx_fatal.c ffscanf.c \
- filenm.c futil.c gbutil.c gmxcpp.c \
+ enxio.c ewald_util.c ffscanf.c \
+ filenm.c futil.c gbutil.c gmx_fatal.c \
+ gmx_sort.c gmxcpp.c \
gmxfio.c ifunc.c index.c cinvsqrtdata.c \
invblock.c macros.c orires.c sparsematrix.c \
main.c maths.c matio.c mshift.c \
pargs.c pbc.c pdbio.c princ.c \
rando.c random.c gmx_random.c rbin.c \
readinp.c replace.c rmpbc.c shift_util.c \
- sortwater.c smalloc.c statutil.c \
+ sortwater.c smalloc.c statutil.c sfactor.c \
strdb.c string2.c symtab.c \
topsort.c tpxio.c \
trnio.c trxio.c txtdump.c typedefs.c \
viewit.c warninp.c \
wgms.c wman.c writeps.c \
xdrd.c xtcio.c xvgr.c replace.h \
- libxdrf.c gmx_arpack.c \
+ libxdrf.c gmx_arpack.c gmx_matrix.c \
dihres.c gmx_random_gausstable.h \
tcontrol.c splitter.c gmx_cyclecounter.c \
gmx_system_xdr.c md5.c vmdio.c vmddlopen.c sighandler.c \
- oenv.c version.c
+ oenv.c gmxfio_rw.c gmxfio_asc.c gmxfio_bin.c \
+ gmxfio_xdr.c
pkgconfigdir = ${libdir}/pkgconfig
pkgconfig_DATA = libgmx@LIBSUFFIX@.pc
# clean all libtool libraries, since the target names might have changed
-CLEANFILES = *.la *~ \\\#* innerc.c innerf.f mkinl version.c
+CLEANFILES = *.la *~ \\\#* innerc.c innerf.f mkinl
-#version.c contains git version information or version defined in VERSION
-#The empty target FORCE forces make to run the commands every time. But
+if USE_VERSION_H
+#version.c contains generated git version information
+libgmx@LIBSUFFIX@_la_SOURCES += version.c
+CLEANFILES += version.c
+#The empty target FORCE forces make to run the command every time. But
#version.c is only changed if the version actually has changed, and hence
#rebuilds are only triggered when they are needed.
version.c: FORCE
$(top_srcdir)/src/gmxlib/genversion.sh @VERSION@ $(top_srcdir)
FORCE:
-
+endif
if (debug) {
fprintf(debug,"searching residue: %4s atom: %4s\n",resnm,atomnm);
if (j == NOTFOUND)
- fprintf(debug," not succesful\n");
+ fprintf(debug," not successful\n");
else
fprintf(debug," match: %4s %4s\n",ap->resnm[j],ap->atomnm[j]);
}
-/*
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
*
* This source code is part of
*
#include "gmx_fatal.h"
#include "calcgrid.h"
-#define facNR 6
-int factor[facNR] = {2,3,5,7,11,13};
-int decomp[facNR];
-int ng,ng_max,*list,n_list,n_list_alloc;
+#define facNR 4
+const int factor[facNR] = {2,3,5,7};
-static void make_list(int start_fac)
+static void make_list(int start_fac,int *ng,int ng_max,int *n_list,int **list)
{
- int i;
+ int i,fac;
- if (ng < ng_max) {
- if (n_list >= n_list_alloc) {
- n_list_alloc += 100;
- srenew(list,n_list_alloc);
+ if (*ng < ng_max)
+ {
+ if (*n_list % 100 == 0)
+ {
+ srenew(*list,*n_list+100);
+ }
+ (*list)[*n_list] = *ng;
+ (*n_list)++;
+
+ for(i=start_fac; i<facNR; i++)
+ {
+ fac = factor[i];
+ /* The choice of grid size is based on benchmarks of fftw
+ * and the need for a lot of factors for nice DD decomposition.
+ * The base criterion is that a grid size is not included
+ * when there is a larger grid size that produces a faster 3D FFT.
+ * Allow any power for 2, two for 3 and 5, but only one for 7.
+ * Three for 3 are ok when there is also a factor of 2.
+ * Two factors of 5 are not allowed with a factor of 3 or 7.
+ * A factor of 7 does not go with a factor of 5, 7 or 9.
+ */
+ if ((fac == 2) ||
+ (fac == 3 && (*ng % 9 != 0 ||
+ (*ng % 2 == 0 && *ng % 27 != 0))) ||
+ (fac == 5 && *ng % 15 && *ng % 25 != 0) ||
+ (fac == 7 && *ng % 5 != 0 && *ng % 7 != 0 && *ng % 9 != 0))
+ {
+ *ng *= fac;
+ make_list(i,ng,ng_max,n_list,list);
+ *ng /= fac;
+ }
+ }
}
- list[n_list] = ng;
- n_list++;
-
- for(i=start_fac; i<facNR; i++) {
- /* allow any power of 2, 3, 5 and 7, but only one of 11 or 13 */
- if (i<4 || (decomp[4]+decomp[5]==0)) {
- ng*=factor[i];
- decomp[i]++;
- make_list(i);
- ng/=factor[i];
- decomp[i]--;
- }
- }
- }
}
static int list_comp(const void *a,const void *b)
}
real calc_grid(FILE *fp,matrix box,real gr_sp,
- int *nx,int *ny,int *nz,int nnodes)
+ int *nx,int *ny,int *nz)
{
- int d,n[DIM];
- int i,j,nmin[DIM];
- rvec box_size,spacing;
- real max_spacing;
- real tmp[3];
-
- if (gr_sp <= 0)
- gmx_fatal(FARGS,"invalid fourier grid spacing: %g",gr_sp);
+ int d,n[DIM];
+ int i,j,nmin[DIM];
+ rvec box_size,spacing;
+ real max_spacing;
+ int ng_max,ng;
+ int n_list,*list;
- /* New grid calculation setup:
- *
- * To maintain similar accuracy for triclinic PME grids as for rectangular
- * ones, the max grid spacing should set along the box vectors rather than
- * cartesian X/Y/Z directions. This will lead to slightly larger grids, but
- * it is much better than having to go to pme_order=6.
- *
- * Thus, instead of just extracting the diagonal elements to box_size[d], we
- * now calculate the cartesian length of the vectors.
- *
- * /Erik Lindahl, 20060402.
- */
- for(d=0; d<DIM; d++)
- {
- box_size[d] = 0;
- for(i=0;i<DIM;i++)
- {
- box_size[d] += box[d][i]*box[d][i];
- }
- box_size[d] = sqrt(box_size[d]);
- }
-
-
- n[XX] = *nx;
- n[YY] = *ny;
- n[ZZ] = *nz;
-
- ng = 1;
- ng_max = 1;
- for(d=0; d<DIM; d++) {
- nmin[d] = (int)(box_size[d]/gr_sp + 0.999);
- if (2*nmin[d] > ng_max)
- ng_max = 2*nmin[d];
- }
- n_list=0;
- n_list_alloc=0;
- list=NULL;
- for(i=0; i<facNR; i++)
- decomp[i]=0;
- make_list(0);
-
- if ((*nx<=0) || (*ny<=0) || (*nz<=0))
- fprintf(fp,"Calculating fourier grid dimensions for%s%s%s\n",
- *nx > 0 ? "":" X",*ny > 0 ? "":" Y",*nz > 0 ? "":" Z");
+ if (gr_sp <= 0)
+ {
+ gmx_fatal(FARGS,"invalid fourier grid spacing: %g",gr_sp);
+ }
- qsort(list,n_list,sizeof(list[0]),list_comp);
- if (debug)
- for(i=0; i<n_list; i++)
- fprintf(debug,"grid: %d\n",list[i]);
-
- if (((*nx>0) && (*nx != nnodes*(*nx/nnodes))) ||
- ((*ny>0) && (*ny != nnodes*(*ny/nnodes))))
- gmx_fatal(FARGS,"the x or y grid spacing (nx %d, ny %d) is not divisible by the number of nodes (%d)",*nx,*ny,nnodes);
-
- for(d=0; d<DIM; d++) {
- for(i=0; (i<n_list) && (n[d]<=0); i++)
- if ((list[i] >= nmin[d]) &&
- ((d == ZZ) || (list[i] == nnodes*(list[i]/nnodes))))
- n[d] = list[i];
- if (n[d] <= 0)
- gmx_fatal(FARGS ,"could not find a grid spacing with nx and ny divisible by the number of nodes (%d)",nnodes);
- }
-
- max_spacing = 0;
- for(d=0; d<DIM; d++) {
- spacing[d] = box_size[d]/n[d];
- if (spacing[d] > max_spacing)
- max_spacing = spacing[d];
- }
- *nx = n[XX];
- *ny = n[YY];
- *nz = n[ZZ];
- fprintf(fp,"Using a fourier grid of %dx%dx%d, spacing %.3f %.3f %.3f\n",
- *nx,*ny,*nz,spacing[XX],spacing[YY],spacing[ZZ]);
+ /* New grid calculation setup:
+ *
+ * To maintain similar accuracy for triclinic PME grids as for rectangular
+ * ones, the max grid spacing should set along the box vectors rather than
+ * cartesian X/Y/Z directions. This will lead to slightly larger grids, but
+ * it is much better than having to go to pme_order=6.
+ *
+ * Thus, instead of just extracting the diagonal elements to box_size[d], we
+ * now calculate the cartesian length of the vectors.
+ *
+ * /Erik Lindahl, 20060402.
+ */
+ for(d=0; d<DIM; d++)
+ {
+ box_size[d] = 0;
+ for(i=0;i<DIM;i++)
+ {
+ box_size[d] += box[d][i]*box[d][i];
+ }
+ box_size[d] = sqrt(box_size[d]);
+ }
+
+ n[XX] = *nx;
+ n[YY] = *ny;
+ n[ZZ] = *nz;
+
+ ng = 1;
+ ng_max = 1;
+ for(d=0; d<DIM; d++)
+ {
+ nmin[d] = (int)(box_size[d]/gr_sp + 0.999);
+ if (2*nmin[d] > ng_max)
+ {
+ ng_max = 2*nmin[d];
+ }
+ }
+ n_list=0;
+ list=NULL;
+ make_list(0,&ng,ng_max,&n_list,&list);
+
+ if ((*nx<=0) || (*ny<=0) || (*nz<=0))
+ {
+ fprintf(fp,"Calculating fourier grid dimensions for%s%s%s\n",
+ *nx > 0 ? "":" X",*ny > 0 ? "":" Y",*nz > 0 ? "":" Z");
+ }
+
+ qsort(list,n_list,sizeof(list[0]),list_comp);
+ if (debug)
+ {
+ for(i=0; i<n_list; i++)
+ fprintf(debug,"grid: %d\n",list[i]);
+ }
+
+ for(d=0; d<DIM; d++)
+ {
+ for(i=0; (i<n_list) && (n[d]<=0); i++)
+ {
+ if (list[i] >= nmin[d])
+ {
+ n[d] = list[i];
+ }
+ }
+ }
+
+ sfree(list);
+
+ max_spacing = 0;
+ for(d=0; d<DIM; d++)
+ {
+ spacing[d] = box_size[d]/n[d];
+ if (spacing[d] > max_spacing)
+ {
+ max_spacing = spacing[d];
+ }
+ }
+ *nx = n[XX];
+ *ny = n[YY];
+ *nz = n[ZZ];
+ fprintf(fp,"Using a fourier grid of %dx%dx%d, spacing %.3f %.3f %.3f\n",
+ *nx,*ny,*nz,spacing[XX],spacing[YY],spacing[ZZ]);
- return max_spacing;
+ return max_spacing;
}
#undef AA
#undef BB
#undef CC
- /*static int l=0; removed due to thread-safety issues*/
int m;
rvec kkk;
gmx_file_position_t **p_outputfiles, int *nfiles,
FILE *list, int file_version)
{
- int i,j;
- off_t offset;
- off_t mask = 0xFFFFFFFFL;
- int offset_high,offset_low;
- char *buf;
- gmx_file_position_t *outputfiles;
-
+ int i,j;
+ off_t offset;
+ off_t mask = 0xFFFFFFFFL;
+ int offset_high,offset_low;
+ char *buf;
+ gmx_file_position_t *outputfiles;
+
if (do_cpt_int(xd,"number of output files",nfiles,list) != 0)
- {
- return -1;
- }
+ {
+ return -1;
+ }
- if(bRead)
- {
- snew(*p_outputfiles,*nfiles);
- }
-
- outputfiles = *p_outputfiles;
-
- for(i=0;i<*nfiles;i++)
- {
- /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
- if(bRead)
- {
- do_cpt_string_err(xd,bRead,"output filename",&buf,list);
- strncpy(outputfiles[i].filename,buf,CPTSTRLEN-1);
- if(list==NULL)
- {
- sfree(buf);
- }
-
- if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
- {
- return -1;
- }
- if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
- {
- return -1;
- }
+ if(bRead)
+ {
+ snew(*p_outputfiles,*nfiles);
+ }
+
+ outputfiles = *p_outputfiles;
+
+ for(i=0;i<*nfiles;i++)
+ {
+ /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
+ if(bRead)
+ {
+ do_cpt_string_err(xd,bRead,"output filename",&buf,list);
+ strncpy(outputfiles[i].filename,buf,CPTSTRLEN-1);
+ if(list==NULL)
+ {
+ sfree(buf);
+ }
+
+ if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
+ {
+ return -1;
+ }
+ if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
+ {
+ return -1;
+ }
#if (SIZEOF_OFF_T > 4)
- outputfiles[i].offset = ( ((off_t) offset_high) << 32 ) | ( (off_t) offset_low & mask );
+ outputfiles[i].offset = ( ((off_t) offset_high) << 32 ) | ( (off_t) offset_low & mask );
#else
- outputfiles[i].offset = offset_low;
+ outputfiles[i].offset = offset_low;
#endif
- }
- else
- {
- buf = outputfiles[i].filename;
- do_cpt_string_err(xd,bRead,"output filename",&buf,list);
- /* writing */
- offset = outputfiles[i].offset;
+ }
+ else
+ {
+ buf = outputfiles[i].filename;
+ do_cpt_string_err(xd,bRead,"output filename",&buf,list);
+ /* writing */
+ offset = outputfiles[i].offset;
if (offset == -1)
{
offset_low = -1;
offset_high = 0;
#endif
}
- if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
- {
- return -1;
- }
- if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
- {
- return -1;
- }
- }
- if (file_version >= 8)
- {
+ if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
+ {
+ return -1;
+ }
+ if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
+ {
+ return -1;
+ }
+ }
+ if (file_version >= 8)
+ {
if (do_cpt_int(xd,"file_checksum_size",&(outputfiles[i].chksum_size),
list) != 0)
{
{
return -1;
}
- }
- else
- {
- outputfiles[i].chksum_size = -1;
- }
- }
- return 0;
+ }
+ else
+ {
+ outputfiles[i].chksum_size = -1;
+ }
+ }
+ return 0;
}
-void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
+void write_checkpoint(const char *fn,bool bNumberAndKeep,
+ FILE *fplog,t_commrec *cr,
int eIntegrator,int simulation_part,
gmx_large_int_t step,double t,t_state *state)
{
- int fp;
+ t_fileio *fp;
int file_version;
char *version;
char *btime;
char *bmach;
char *fprog;
char *ftime;
+ char *fntemp; /* the temporary checkpoint file name */
time_t now;
int nppnodes,npmenodes,flag_64bit;
- char buf[1024];
- gmx_file_position_t *outputfiles;
- int noutputfiles;
+ char buf[1024],suffix[5+STEPSTRSIZE],sbuf[STEPSTRSIZE];
+ gmx_file_position_t *outputfiles;
+ int noutputfiles;
int flags_eks,flags_enh,i;
+ t_fileio *ret;
if (PAR(cr))
{
nppnodes = 1;
npmenodes = 0;
}
-
- if (gmx_fexist(fn))
- {
- /* Rename the previous checkpoint file */
- strcpy(buf,fn);
- buf[strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
- strcat(buf,"_prev");
- strcat(buf,fn+strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1);
- (void)remove(buf); /* Unix will overwrite buf if it exists, but for windows we need to remove first */
- if(rename(fn,buf) != 0)
- {
- gmx_file("Cannot rename checkpoint file; maybe you are out of quota?");
- }
- }
-
+
+ /* make the new temporary filename */
+ snew(fntemp, strlen(fn)+5+STEPSTRSIZE);
+ strcpy(fntemp,fn);
+ fntemp[strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
+ sprintf(suffix,"_%s%s","step",gmx_step_str(step,sbuf));
+ strcat(fntemp,suffix);
+ strcat(fntemp,fn+strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1);
+
now = time(NULL);
ftime = strdup(ctime(&now));
ftime[strlen(ftime)-1] = '\0';
- /* No need to pollute stderr every time we write a checkpoint file */
+ /* No need to pollute stderr every time we write a checkpoint file */
/* fprintf(stderr,"\nWriting checkpoint, step %d at %s\n",step,ftime); */
if (fplog)
{
}
/* Get offsets for open files */
- gmx_fio_get_output_file_positions(&outputfiles, &noutputfiles);
+ gmx_fio_get_output_file_positions(&outputfiles, &noutputfiles);
- fp = gmx_fio_open(fn,"w");
+ fp = gmx_fio_open(fntemp,"w");
if (state->ekinstate.bUpToDate)
{
flags_eks =
- ((1<<eeksEKIN_N) | (1<<eeksEKINH) | (1<<eeksEKINF) | (1<<eeksEKINO) |
- (1<<eeksEKINSCALEF) | (1<<eeksEKINSCALEH) | (1<<eeksVSCALE) | (1<<eeksDEKINDL) | (1<<eeksMVCOS));
+ ((1<<eeksEKIN_N) | (1<<eeksEKINH) | (1<<eeksEKINF) |
+ (1<<eeksEKINO) | (1<<eeksEKINSCALEF) | (1<<eeksEKINSCALEH) |
+ (1<<eeksVSCALE) | (1<<eeksDEKINDL) | (1<<eeksMVCOS));
}
else
{
&version,&btime,&buser,&bmach,&fprog,&ftime,
&eIntegrator,&simulation_part,&step,&t,&nppnodes,
DOMAINDECOMP(cr) ? cr->dd->nc : NULL,&npmenodes,
- &state->natoms,&state->ngtc,&state->nnhpres,&state->nhchainlength,
- &state->flags,&flags_eks,&flags_enh,NULL);
+ &state->natoms,&state->ngtc,&state->nnhpres,
+ &state->nhchainlength, &state->flags,&flags_eks,&flags_enh,
+ NULL);
sfree(version);
sfree(btime);
sfree(bmach);
sfree(fprog);
- if( (do_cpt_state(gmx_fio_getxdr(fp),FALSE,state->flags,state,TRUE,NULL) < 0) ||
- (do_cpt_ekinstate(gmx_fio_getxdr(fp),FALSE,flags_eks,&state->ekinstate,NULL) < 0) ||
- (do_cpt_enerhist(gmx_fio_getxdr(fp),FALSE,flags_enh,&state->enerhist,NULL) < 0) ||
- (do_cpt_files(gmx_fio_getxdr(fp),FALSE,&outputfiles,&noutputfiles,NULL,file_version) < 0))
- {
- gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of quota?");
- }
+ if((do_cpt_state(gmx_fio_getxdr(fp),FALSE,state->flags,state,TRUE,NULL) < 0) ||
+ (do_cpt_ekinstate(gmx_fio_getxdr(fp),FALSE,flags_eks,&state->ekinstate,NULL) < 0)||
+ (do_cpt_enerhist(gmx_fio_getxdr(fp),FALSE,flags_enh,&state->enerhist,NULL) < 0) ||
+ (do_cpt_files(gmx_fio_getxdr(fp),FALSE,&outputfiles,&noutputfiles,NULL,
+ file_version) < 0))
+ {
+ gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of quota?");
+ }
do_cpt_footer(gmx_fio_getxdr(fp),FALSE,file_version);
+ /* we really, REALLY, want the checkpoint file and all files it depends
+ on to be physically written out do disk: */
+ ret=gmx_fio_all_output_fsync();
+ if (ret)
+ {
+ char buf[STRLEN];
+ sprintf(buf,
+ "Cannot fsync '%s'; maybe you are out of disk space or quota?",
+ gmx_fio_getname(ret));
+
+ if (getenv(GMX_IGNORE_FSYNC_FAILURE_ENV)==NULL)
+ {
+ gmx_file(buf);
+ }
+ else
+ {
+ gmx_warning(buf);
+ }
+ }
+
if( gmx_fio_close(fp) != 0)
- {
- gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of quota?");
- }
-
+ {
+ gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of quota?");
+ }
+
+ /* we don't move the checkpoint if the user specified they didn't want it,
+ or if the fsyncs failed */
+ if (!bNumberAndKeep && !ret)
+ {
+ if (gmx_fexist(fn))
+ {
+ /* Rename the previous checkpoint file */
+ strcpy(buf,fn);
+ buf[strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
+ strcat(buf,"_prev");
+ strcat(buf,fn+strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1);
+#ifndef GMX_FAHCORE
+ /* we copy here so that if something goes wrong between now and
+ * the rename below, there's always a state.cpt.
+ * If renames are atomic (such as in POSIX systems),
+ * this copying should be unneccesary.
+ */
+ gmx_file_copy(fn, buf, FALSE);
+ /* We don't really care if this fails:
+ * there's already a new checkpoint.
+ */
+#else
+ gmx_file_rename(fn, buf);
+#endif
+ }
+ if (gmx_file_rename(fntemp, fn) != 0)
+ {
+ gmx_file("Cannot rename checkpoint file; maybe you are out of quota?");
+ }
+ }
+
sfree(ftime);
- sfree(outputfiles);
- #ifdef GMX_FAHCORE
- /*code for alternate checkpointing scheme. moved from top of loop over steps */
- fcRequestCheckPoint();
- if ( fcCheckPointParallel( cr->nodeid, NULL,0) == 0 ) {
- gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", step );
- }
- #endif /* end FAHCORE block */
+ sfree(outputfiles);
+ sfree(fntemp);
+#ifdef GMX_FAHCORE
+ /*code for alternate checkpointing scheme. moved from top of loop over
+ steps */
+ fcRequestCheckPoint();
+ if ( fcCheckPointParallel( cr->nodeid, NULL,0) == 0 ) {
+ gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", step );
+ }
+#endif /* end GMX_FAHCORE block */
}
static void print_flag_mismatch(FILE *fplog,int sflags,int fflags)
t_state *state,bool *bReadRNG,bool *bReadEkin,
int *simulation_part,bool bAppendOutputFiles)
{
- int fp,i,j,rc;
+ t_fileio *fp;
+ int i,j,rc;
int file_version;
char *version,*btime,*buser,*bmach,*fprog,*ftime;
char filename[STRLEN],buf[STEPSTRSIZE];
int ret;
gmx_file_position_t *outputfiles;
int nfiles;
- int chksum_file;
+ t_fileio *chksum_file;
FILE* fplog = *pfplog;
unsigned char digest[16];
#if !((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
- struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, 0 };
+ struct flock fl = { 0, SEEK_SET, 0, F_WRLCK, 0 };
#endif
const char *int_warn=
" offsets. Can not append. Run mdrun without -append",
outputfiles[i].filename);
}
-#ifdef FAHCORE
+#ifdef GMX_FAHCORE
chksum_file=gmx_fio_open(outputfiles[i].filename,"a");
#else
{
gmx_fio_close(chksum_file);
}
-#ifndef FAHCORE
+#ifndef GMX_FAHCORE
/* compare md5 chksum */
if (outputfiles[i].chksum_size != -1 &&
memcmp(digest,outputfiles[i].chksum,16)!=0)
gmx_bcast(sizeof(*bReadEkin),bReadEkin,cr);
}
ir->bContinuation = TRUE;
- ir->nsteps += ir->init_step - step;
+ if (ir->nsteps >= 0)
+ {
+ ir->nsteps += ir->init_step - step;
+ }
ir->init_step = step;
ir->simulation_part += 1;
}
-static void read_checkpoint_data(int fp,int *simulation_part,
+static void read_checkpoint_data(t_fileio *fp,int *simulation_part,
gmx_large_int_t *step,double *t,t_state *state,
bool bReadRNG,
int *nfiles,gmx_file_position_t **outputfiles)
read_checkpoint_state(const char *fn,int *simulation_part,
gmx_large_int_t *step,double *t,t_state *state)
{
- int fp;
+ t_fileio *fp;
fp = gmx_fio_open(fn,"r");
read_checkpoint_data(fp,simulation_part,step,t,state,TRUE,NULL,NULL);
}
}
-void read_checkpoint_trxframe(int fp,t_trxframe *fr)
+void read_checkpoint_trxframe(t_fileio *fp,t_trxframe *fr)
{
t_state state;
int simulation_part;
void list_checkpoint(const char *fn,FILE *out)
{
- int fp;
+ t_fileio *fp;
int file_version;
char *version,*btime,*buser,*bmach,*fprog,*ftime;
int eIntegrator,simulation_part,nppnodes,npme;
bool bAppendReq,
const char *part_suffix,bool *bAddPart)
{
- int fp;
+ t_fileio *fp;
gmx_large_int_t step=0;
double t;
t_state state;
bAppend = FALSE;
if (SIMMASTER(cr)) {
- if(!gmx_fexist(filename) || ( (fp = gmx_fio_open(filename,"r")) < 0 ))
+ if(!gmx_fexist(filename) || (!(fp = gmx_fio_open(filename,"r")) ))
{
*simulation_part = 0;
}
int read_g96_conf(FILE *fp,const char *infile,t_trxframe *fr)
{
- static t_symtab *symtab=NULL;
- static char line[STRLEN+1]; /* VERY DIRTY, you can not read two *
- * Gromos96 trajectories at the same time */
+ t_symtab *symtab=NULL;
+ char line[STRLEN+1];
bool bAtStart,bTime,bAtoms,bPos,bVel,bBox,bEnd,bFinished;
int natoms,nbp;
double db1,db2,db3,db4,db5,db6,db7,db8,db9;
}
} while (!bFinished && fgets2(line,STRLEN,fp));
- close_symtab(symtab);
+ free_symtab(symtab);
fr->natoms = natoms;
static void read_espresso_conf(const char *infile,
t_atoms *atoms,rvec x[],rvec *v,matrix box)
{
- static t_symtab *symtab=NULL;
+ t_symtab *symtab=NULL;
FILE *fp;
char word[STRLEN],buf[STRLEN];
int natoms,level,npar,r,nprop,p,i,m,molnr;
static bool get_w_conf(FILE *in,const char *infile,char *title,
t_atoms *atoms, int *ndec, rvec x[],rvec *v, matrix box)
{
- static t_symtab *symtab=NULL;
+ t_symtab *symtab=NULL;
char name[6];
char line[STRLEN+1],*ptr;
char buf[256];
tpx_make_chain_identifiers(atoms,&top.mols);
sfree(mtop);
+ /* The strings in the symtab are still in use in the returned t_atoms
+ * structure, so we should not free them. But there is no place to put the
+ * symbols; the only choice is to leak the memory...
+ * So we clear the symbol table before freeing the topology structure. */
+ open_symtab(&top.symtab);
done_top(&top);
break;
"J. S. Hub and B. L. de Groot",
"Mechanism of selectivity in aquaporins and aquaglyceroporins",
"PNAS",
- 105, 2008, "1198-1203" }
+ 105, 2008, "1198-1203" },
+ { "Engin2010",
+ "O. Engin, A. Villa, M. Sayar and B. Hess",
+ "Driving Forces for Adsorption of Amphiphilic Peptides to Air-Water Interface",
+ "J. Phys. Chem. B",
+ 0, 2010, "???" }
};
#define NSTR (int)asize(citedb)
*/
snew(dd->Rt_6,2*dd->nres);
dd->Rtav_6 = &(dd->Rt_6[dd->nres]);
- if (cr->ms)
+
+ ptr = getenv("GMX_DISRE_ENSEMBLE_SIZE");
+ if (cr->ms != NULL && ptr != NULL)
{
- ptr = getenv("GMX_DISRE_ENSEMBLE_SIZE");
#ifdef GMX_MPI
- if (ptr == NULL)
+ dd->nsystems = 0;
+ sscanf(ptr,"%d",&dd->nsystems);
+ if (fplog)
{
- dd->nsystems = cr->ms->nsim;
- dd->mpi_comm_ensemble = cr->ms->mpi_comm_masters;
- if (fplog)
- {
- fprintf(fplog,"Will apply ensemble averaging over %d systems\n",
- dd->nsystems);
- }
+ fprintf(fplog,"Found GMX_DISRE_ENSEMBLE_SIZE set to %d systems per ensemble\n",dd->nsystems);
}
- else
+ check_multi_int(fplog,cr->ms,dd->nsystems,
+ "the number of systems per ensemble");
+ if (dd->nsystems <= 0 || cr->ms->nsim % dd->nsystems != 0)
{
- dd->nsystems = 0;
- sscanf(ptr,"%d",&dd->nsystems);
- if (fplog)
- {
- fprintf(fplog,"Found GMX_DISRE_ENSEMBLE_SIZE set to %d systems per ensemble\n",dd->nsystems);
- }
- check_multi_int(fplog,cr->ms,dd->nsystems,
- "the number of systems per ensemble");
- if (dd->nsystems <= 0 || cr->ms->nsim % dd->nsystems != 0)
+ gmx_fatal(FARGS,"The number of systems %d is not divisible by the number of systems per ensemble %d\n",cr->ms->nsim,dd->nsystems);
+ }
+ /* Split the inter-master communicator into different ensembles */
+ MPI_Comm_split(cr->ms->mpi_comm_masters,
+ cr->ms->sim/dd->nsystems,
+ cr->ms->sim,
+ &dd->mpi_comm_ensemble);
+ if (fplog)
+ {
+ fprintf(fplog,"Our ensemble consists of systems:");
+ for(i=0; i<dd->nsystems; i++)
{
- gmx_fatal(FARGS,"The number of systems %d is not divisible by the number of systems per ensemble %d\n",cr->ms->nsim,dd->nsystems);
+ fprintf(fplog," %d",
+ (cr->ms->sim/dd->nsystems)*dd->nsystems+i);
}
- /* Split the inter-master communicator into different ensembles */
- MPI_Comm_split(cr->ms->mpi_comm_masters,
- cr->ms->sim/dd->nsystems,
- cr->ms->sim,
- &dd->mpi_comm_ensemble);
- if (fplog)
- {
- fprintf(fplog,"Our ensemble consists of systems:");
- for(i=0; i<dd->nsystems; i++)
- {
- fprintf(fplog," %d",
- (cr->ms->sim/dd->nsystems)*dd->nsystems+i);
- }
- fprintf(fplog,"\n");
+ fprintf(fplog,"\n");
}
- }
snew(dd->Rtl_6,dd->nres);
#endif
}
struct ener_file
{
ener_old_t eo;
- int fp;
+ t_fileio *fio;
int framenr;
real frametime;
};
{
int magic=-55555;
XDR *xdr;
- bool bRead = gmx_fio_getread(ef->fp);
+ bool bRead = gmx_fio_getread(ef->fio);
int file_version;
int i;
-
- gmx_fio_select(ef->fp);
+
+ gmx_fio_checktype(ef->fio);
- xdr = gmx_fio_getxdr(ef->fp);
+ xdr = gmx_fio_getxdr(ef->fio);
if (!xdr_int(xdr,&magic))
{
xdr_int(xdr,&file_version);
if (file_version > enx_version)
{
- gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fp),file_version,enx_version);
+ gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fio),file_version,enx_version);
}
xdr_int(xdr,nre);
}
int magic=-7777777;
real r;
int block,i,zero=0,dum=0;
- bool bRead = gmx_fio_getread(ef->fp);
+ bool bRead = gmx_fio_getread(ef->fio);
int tempfix_nr=0;
if (nre_test >= 0)
* number of blocks, where this number is read before).
*/
r = -2e10;
- if (!do_real(r))
+ if (!gmx_fio_do_real(ef->fio, r))
{
return FALSE;
}
/* Assume we are reading an old format */
*file_version = 1;
fr->t = r;
- if (!do_int(dum)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, dum)) *bOK = FALSE;
fr->step = dum;
}
else
{
- if (!do_int(magic)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, magic)) *bOK = FALSE;
if (magic != -7777777)
{
gmx_fatal(FARGS,"Energy header magic number mismatch, this is not a GROMACS edr file");
}
*file_version = enx_version;
- if (!do_int (*file_version)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, *file_version)) *bOK = FALSE;
if (*bOK && *file_version > enx_version)
{
- gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fp),file_version,enx_version);
+ gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fio),file_version,enx_version);
}
- if (!do_double(fr->t)) *bOK = FALSE;
- if (!do_gmx_large_int(fr->step)) *bOK = FALSE;
+ if (!gmx_fio_do_double(ef->fio, fr->t)) *bOK = FALSE;
+ if (!gmx_fio_do_gmx_large_int(ef->fio, fr->step)) *bOK = FALSE;
if (!bRead && fr->nsum == 1) {
/* Do not store sums of length 1,
* since this does not add information.
*/
- if (!do_int (zero)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, zero)) *bOK = FALSE;
} else {
- if (!do_int (fr->nsum)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, fr->nsum)) *bOK = FALSE;
}
if (*file_version >= 3)
{
- do_gmx_large_int(fr->nsteps);
+ gmx_fio_do_gmx_large_int(ef->fio, fr->nsteps);
}
else
{
fr->nsteps = max(1,fr->nsum);
}
}
- if (!do_int (fr->nre)) *bOK = FALSE;
- if (!do_int (fr->ndisre)) *bOK = FALSE;
- if (!do_int (fr->nblock)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, fr->nre)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, fr->ndisre)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, fr->nblock)) *bOK = FALSE;
/* Frames could have nre=0, so we can not rely only on the fr->nre check */
if (bRead && nre_test >= 0 &&
}
for(block=0; block<fr->nblock; block++)
{
- if (!do_int (fr->nr[block]))
+ if (!gmx_fio_do_int(ef->fio, fr->nr[block]))
{
*bOK = FALSE;
}
}
- if (!do_int (fr->e_size)) *bOK = FALSE;
- if (!do_int (fr->d_size)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, fr->e_size)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, fr->d_size)) *bOK = FALSE;
/* Do a dummy int to keep the format compatible with the old code */
- if (!do_int (dum)) *bOK = FALSE;
+ if (!gmx_fio_do_int(ef->fio, dum)) *bOK = FALSE;
if (*bOK && *file_version == 1 && nre_test < 0)
{
void close_enx(ener_file_t ef)
{
- if(gmx_fio_close(ef->fp) != 0)
+ if(gmx_fio_close(ef->fio) != 0)
{
gmx_file("Cannot close energy file; it might be corrupt, or maybe you are out of quota?");
}
snew(ef,1);
if (mode[0]=='r') {
- ef->fp=gmx_fio_open(fn,mode);
- gmx_fio_select(ef->fp);
- gmx_fio_setprecision(ef->fp,FALSE);
+ ef->fio=gmx_fio_open(fn,mode);
+ gmx_fio_checktype(ef->fio);
+ gmx_fio_setprecision(ef->fio,FALSE);
do_enxnms(ef,&nre,&nms);
snew(fr,1);
do_eheader(ef,&file_version,fr,nre,&bWrongPrecision,&bDum);
}
else
{
- gmx_fio_rewind(ef->fp);
- gmx_fio_select(ef->fp);
- gmx_fio_setprecision(ef->fp,TRUE);
+ gmx_fio_rewind(ef->fio);
+ gmx_fio_checktype(ef->fio);
+ gmx_fio_setprecision(ef->fio,TRUE);
do_enxnms(ef,&nre,&nms);
do_eheader(ef,&file_version,fr,nre,&bWrongPrecision,&bDum);
if(!bDum)
}
free_enxframe(fr);
sfree(fr);
- gmx_fio_rewind(ef->fp);
+ gmx_fio_rewind(ef->fio);
}
else
- ef->fp = gmx_fio_open(fn,mode);
+ ef->fio = gmx_fio_open(fn,mode);
ef->framenr=0;
ef->frametime=0;
return ef;
}
-int enx_file_pointer(const ener_file_t ef)
+t_fileio *enx_file_pointer(const ener_file_t ef)
{
- return ef->fp;
+ return ef->fio;
}
static void convert_full_sums(ener_old_t *ener_old,t_enxframe *fr)
char buf[22];
bOK = TRUE;
- bRead = gmx_fio_getread(ef->fp);
+ bRead = gmx_fio_getread(ef->fio);
if (!bRead)
{
fr->e_size = fr->nre*sizeof(fr->ener[0].e)*4;
fr->d_size = fr->ndisre*(sizeof(fr->disre_rm3tav[0]) +
sizeof(fr->disre_rt[0]));
}
- gmx_fio_select(ef->fp);
-
+ gmx_fio_checktype(ef->fio);
+
if (!do_eheader(ef,&file_version,fr,-1,NULL,&bOK))
{
if (bRead)
if (!((fr->step >= 0) && bSane))
{
fprintf(stderr,"\nWARNING: there may be something wrong with energy file %s\n",
- gmx_fio_getname(ef->fp));
+ gmx_fio_getname(ef->fio));
fprintf(stderr,"Found: step=%s, nre=%d, ndisre=%d, nblock=%d, time=%g.\n"
"Trying to skip frame expect a crash though\n",
gmx_step_str(fr->step,buf),fr->nre,fr->ndisre,fr->nblock,fr->t);
for(i=0; i<fr->nre; i++)
{
- bOK = bOK && do_real(fr->ener[i].e);
+ bOK = bOK && gmx_fio_do_real(ef->fio, fr->ener[i].e);
/* Do not store sums of length 1,
* since this does not add information.
(bRead && fr->nsum > 0) || fr->nsum > 1)
{
tmp1 = fr->ener[i].eav;
- bOK = bOK && do_real(tmp1);
+ bOK = bOK && gmx_fio_do_real(ef->fio, tmp1);
if (bRead)
fr->ener[i].eav = tmp1;
/* This is to save only in single precision (unless compiled in DP) */
tmp2 = fr->ener[i].esum;
- bOK = bOK && do_real(tmp2);
+ bOK = bOK && gmx_fio_do_real(ef->fio, tmp2);
if (bRead)
fr->ener[i].esum = tmp2;
{
/* Old, unused real */
rdum = 0;
- bOK = bOK && do_real(rdum);
+ bOK = bOK && gmx_fio_do_real(ef->fio, rdum);
}
}
}
srenew(fr->disre_rt,fr->ndisre);
fr->d_alloc = fr->ndisre;
}
- ndo_real(fr->disre_rm3tav,fr->ndisre,bOK1);
+ bOK1=gmx_fio_ndo_real(ef->fio, fr->disre_rm3tav,fr->ndisre);
bOK = bOK && bOK1;
- ndo_real(fr->disre_rt,fr->ndisre,bOK1);
+ bOK1=gmx_fio_ndo_real(ef->fio, fr->disre_rt,fr->ndisre);
bOK = bOK && bOK1;
}
for(block=0; block<fr->nblock; block++)
srenew(fr->block[block],fr->nr[block]);
fr->b_alloc[block] = fr->nr[block];
}
- ndo_real(fr->block[block],fr->nr[block],bOK1);
+ bOK1=gmx_fio_ndo_real(ef->fio, fr->block[block],fr->nr[block]);
bOK = bOK && bOK1;
}
if(!bRead)
{
- if( gmx_fio_flush(ef->fp) != 0)
+ if( gmx_fio_flush(ef->fio) != 0)
{
gmx_file("Cannot write energy file; maybe you are out of quota?");
}
int nre,nfr,i,j,ni,npcoupl;
char buf[STRLEN];
const char *bufi;
- gmx_enxnm_t *enm;
+ gmx_enxnm_t *enm=NULL;
t_enxframe *fr;
ener_file_t in;
return ret;
}
+void done_filenms(int nf, t_filenm fnm[])
+{
+ int i, j;
+
+ for (i = 0; i < nf; ++i)
+ {
+ for (j = 0; j < fnm[i].nfiles; ++j)
+ {
+ sfree(fnm[i].fns[j]);
+ }
+ sfree(fnm[i].fns);
+ fnm[i].fns = NULL;
+ }
+}
#include <sys/stat.h>
#include <fcntl.h>
+#ifdef HAVE_COPYFILE_H
+/* BSD specific */
+#include <copyfile.h>
+#endif
+
#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
#include <direct.h>
#include <io.h>
#include "smalloc.h"
#include "statutil.h"
+
#ifdef GMX_THREADS
#include "thread_mpi.h"
#endif
if (test == NULL)
return FALSE;
else {
- ffclose(test);
+ fclose(test);
return TRUE;
}
}
}
}
-char *backup_fn(const char *file)
+static char *backup_fn(const char *file,int count_max)
{
/* Use a reasonably low value for countmax; we might
* generate 4-5 files in each round, and we dont
* want to hit directory limits of 1024 or 2048 files.
*/
-#define COUNTMAX 128
+#define COUNTMAX 99
int i,count=1;
char *directory,*fn;
char *buf;
+ if (count_max == -1)
+ {
+ count_max = COUNTMAX;
+ }
+
smalloc(buf, GMX_PATH_MAX);
for(i=strlen(file)-1; ((i > 0) && (file[i] != '/')); i--)
do {
sprintf(buf,"%s/#%s.%d#",directory,fn,count);
count++;
- } while ((count < COUNTMAX) && gmx_fexist(buf));
+ } while ((count <= count_max) && gmx_fexist(buf));
/* Arbitrarily bail out */
- if (count == COUNTMAX)
- gmx_fatal(FARGS,"Won't make more than %d backups of %s for you",
- COUNTMAX,fn);
+ if (count > count_max)
+ gmx_fatal(FARGS,"Won't make more than %d backups of %s for you.\n"
+ "The env.var. GMX_MAXBACKUP controls this maximum, -1 disables backups.",
+ count_max,fn);
sfree(directory);
sfree(fn);
bool make_backup(const char * name)
{
+ char * env;
+ int count_max;
char * backup;
#ifdef GMX_FAHCORE
return FALSE; /* skip making backups */
#else
- if(gmx_fexist(name)) {
- backup = backup_fn(name);
+ if (gmx_fexist(name))
+ {
+ env = getenv("GMX_MAXBACKUP");
+ if (env != NULL)
+ {
+ count_max = 0;
+ sscanf(env,"%d",&count_max);
+ if (count_max == -1)
+ {
+ /* Do not make backups and possibly overwrite old files */
+ return TRUE;
+ }
+ }
+ else
+ {
+ /* Use the default maximum */
+ count_max = -1;
+ }
+ backup = backup_fn(name,count_max);
if(rename(name, backup) == 0) {
fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
name, backup);
/* name in Buf should now be OK */
}
- int
-gmx_truncatefile(char *path, off_t length)
+int gmx_truncatefile(char *path, off_t length)
{
#ifdef _MSC_VER
/* Microsoft visual studio does not have "truncate" */
return truncate(path,length);
#endif
}
+
+
+int gmx_file_rename(const char *oldname, const char *newname)
+{
+#if (!(defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)))
+ /* under unix, rename() is atomic (at least, it should be). */
+ return rename(oldname, newname);
+#else
+ if (MoveFileEx(oldname, newname,
+ MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
+ return 0;
+ else
+ return 1;
+#endif
+}
+
+int gmx_file_copy(const char *oldname, const char *newname, bool copy_if_empty)
+{
+#if defined(HAVE_COPYFILE_H) && !defined(GMX_FAHCORE)
+ /* this is BSD specific, but convenient */
+ return copyfile(oldname, newname, NULL, COPYFILE_DATA);
+#elif defined(HAVE_WIN_COPYFILE) && !defined(GMX_FAHCORE)
+ if (CopyFile(oldname, newname, FALSE))
+ return 0;
+ else
+ return 1;
+#else
+#define FILECOPY_BUFSIZE (1<<16)
+ /* POSIX doesn't support any of the above. */
+ FILE *in=NULL;
+ FILE *out=NULL;
+ char *buf;
+
+ snew(buf, FILECOPY_BUFSIZE);
+
+ in=fopen(oldname, "rb");
+ if (!in)
+ goto error;
+
+ /* If we don't copy when empty, we postpone opening the file
+ until we're actually ready to write. */
+ if (copy_if_empty)
+ {
+ out=fopen(newname, "wb");
+ if (!out)
+ goto error;
+ }
+
+ while(!feof(in))
+ {
+ size_t nread;
+
+ nread=fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
+ if (nread>0)
+ {
+ size_t ret;
+ if (!out)
+ {
+ out=fopen(newname, "wb");
+ if (!out)
+ goto error;
+ }
+ ret=fwrite(buf, sizeof(char), nread, out);
+ if (ret!=nread)
+ {
+ goto error;
+ }
+ }
+ if (ferror(in))
+ goto error;
+ }
+ sfree(buf);
+ fclose(in);
+ fclose(out);
+ return 0;
+error:
+ sfree(buf);
+ if (in)
+ fclose(in);
+ if (out)
+ fclose(out);
+ return 1;
+#undef FILECOPY_BUFSIZE
+#endif
+}
+
+
}
}
+static void low_rotate_conf_indexed(int nindex,atom_id *index,rvec *x,real alfa, real beta,real gamma)
+{
+ int i;
+ rvec x_old;
+
+ for (i=0; i<nindex; i++) {
+ copy_rvec(x[index[i]],x_old);
+ /*calculate new x[index[i]] by rotation alfa around the x-axis*/
+ x[index[i]][XX]= x_old[XX];
+ x[index[i]][YY]= cos(alfa)*x_old[YY] - sin(alfa)*x_old[ZZ];
+ x[index[i]][ZZ]= sin(alfa)*x_old[YY] + cos(alfa)*x_old[ZZ];
+ copy_rvec(x[index[i]],x_old);
+ /*calculate new x[index[i]] by rotation beta around the y-axis*/
+ x[index[i]][XX]= cos(beta)*x_old[XX] + sin(beta)*x_old[ZZ];
+ x[index[i]][YY]= x_old[YY];
+ x[index[i]][ZZ]= - sin(beta)*x_old[XX] + cos(beta)*x_old[ZZ];
+ copy_rvec(x[index[i]],x_old);
+ /*calculate new x[index[i]] by rotation gamma around the z-axis*/
+ x[index[i]][XX]= x_old[XX]*cos(gamma) - x_old[YY]*sin(gamma);
+ x[index[i]][YY]= x_old[XX]*sin(gamma) + x_old[YY]*cos(gamma);
+ x[index[i]][ZZ]= x_old[ZZ];
+ }
+}
+
void rotate_conf(int natom,rvec *x,rvec *v,real alfa, real beta,real gamma)
{
if (x)
low_rotate_conf(natom,v,alfa,beta,gamma);
}
+void rotate_conf_indexed(int nindex,atom_id *index,rvec *x,rvec *v,real alfa, real beta,real gamma)
+{
+ if (x)
+ low_rotate_conf_indexed(nindex,index,x,alfa,beta,gamma);
+ if (v)
+ low_rotate_conf_indexed(nindex,index,v,alfa,beta,gamma);
+}
void orient(int natom,rvec *x,rvec *v, rvec angle,matrix box)
{
#!/bin/sh
# usage: genversion.sh PKGVERSION top_srcdir
+# Requires git 1.5.1 or later
PKGVERSION=$1
SRCDIR=$2
# Get either -dirty or an empty string, depending on whether there are local changes.
dirtystr=`(cd $SRCDIR && git diff-index --quiet HEAD) || echo "-dirty"`
# Get date of the head commit as YYYYMMDD (commit date).
- date=`git --git-dir=$GITDIR rev-list -n1 --pretty=format:%ci HEAD | sed -ne '/commit/!{s/-\| .*$//g;p;}'`
+ # Git before 1.5.3 does not support any sensible date format,
+ # so we need to massage the output.
+ if test "`git --version`" \< "git version 1.5.3" ; then
+ date=`git --git-dir=$GITDIR rev-list -n1 --pretty=format:%cD HEAD | \
+ sed -ne '/commit/!{s/^.*, *\([ 0-9][0-9]\) \([a-zA-Z]*\) \([0-9]*\) .*$/\3\2\1/;y/ /0/;\
+ s/Jan/01/;s/Feb/02/;s/Mar/03/;s/Apr/04/;s/May/05/;s/Jun/06/;
+ s/Jul/07/;s/Aug/08/;s/Sep/09/;s/Oct/10/;s/Nov/11/;s/Dec/12/;
+ p;}'`
+ else
+ date=`git --git-dir=$GITDIR rev-list -n1 --pretty=format:%ci HEAD | sed -ne '/commit/!{s/-\| .*$//g;p;}'`
+ fi
# Get a 7-character hash for the HEAD commit.
shorthash=`git --git-dir=$GITDIR rev-parse --short=7 HEAD 2>/dev/null`
# Get the full hash for the HEAD commit.
#include "smalloc.h"
#include "gmxfio.h"
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
#ifdef GMX_THREADS
-#include "thread_mpi.h"
+#include "tmpi.h"
#endif
static bool bDebug = FALSE;
#ifdef GMX_THREADS
tMPI_Thread_mutex_lock(&debug_mutex);
#endif
- if (!fatal_errno)
+ if (fatal_errno == 0)
{
- if (log_file)
+ if (log_file)
+ {
fprintf(log_file,"%s\n",msg);
+ }
fprintf(stderr,"%s\n",msg);
/* we set it to no-zero because if this function is called, something
has gone wrong */
else
{
if (fatal_errno != -1)
+ {
errno=fatal_errno;
+ }
perror(msg);
}
#ifndef GMX_THREADS
- if (gmx_parallel_env_initialized()) {
+ if (gmx_parallel_env_initialized())
+ {
int nnodes;
int noderank;
#endif
}
+/* The function below should be identical to quit_gmx,
+ * except that is does not actually quit and call gmx_abort.
+ */
+static void quit_gmx_noquit(const char *msg)
+{
+#ifdef GMX_THREADS
+ tMPI_Thread_mutex_lock(&debug_mutex);
+#endif
+ if (!fatal_errno)
+ {
+ if (log_file)
+ fprintf(log_file,"%s\n",msg);
+ fprintf(stderr,"%s\n",msg);
+ /* we set it to no-zero because if this function is called, something
+ has gone wrong */
+ fatal_errno=255;
+ }
+ else
+ {
+ if (fatal_errno != -1)
+ errno=fatal_errno;
+ perror(msg);
+ }
+
+ if (!gmx_parallel_env_initialized())
+ {
+ if (debug)
+ fflush(debug);
+ if (bDebugMode()) {
+ fprintf(stderr,"dump core (y/n):");
+ fflush(stderr);
+ if (toupper(getc(stdin))!='N')
+ (void) abort();
+ }
+ }
+
+#ifdef GMX_THREADS
+ tMPI_Thread_mutex_unlock(&debug_mutex);
+#endif
+}
+
void _set_fatal_tmp_file(const char *fn, const char *file, int line)
{
#ifdef GMX_THREADS
}
void gmx_fatal_collective(int f_errno,const char *file,int line,
- bool bMaster,
+ t_commrec *cr,gmx_domdec_t *dd,
const char *fmt,...)
{
+ bool bFinalize;
va_list ap;
char msg[STRLEN];
-
- if (bMaster)
+#ifdef GMX_MPI
+ int result;
+#endif
+
+ bFinalize = TRUE;
+
+#ifdef GMX_MPI
+ if (gmx_parallel_env_initialized())
+ {
+ /* Check if we are calling on all processes in MPI_COMM_WORLD */
+ if (cr != NULL)
+ {
+ MPI_Comm_compare(cr->mpi_comm_mysim,MPI_COMM_WORLD,&result);
+ }
+ else
+ {
+ MPI_Comm_compare(dd->mpi_comm_all,MPI_COMM_WORLD,&result);
+ }
+ /* Any result except MPI_UNEQUAL allows us to call MPI_Finalize */
+ bFinalize = (result != MPI_UNEQUAL);
+ }
+#endif
+
+ if ((cr != NULL && MASTER(cr) ) ||
+ (dd != NULL && DDMASTER(dd)))
{
va_start(ap,fmt);
tMPI_Thread_mutex_unlock(&debug_mutex);
#endif
+ if (bFinalize)
+ {
+ /* Use an error handler that does not quit */
+ set_gmx_error_handler(quit_gmx_noquit);
+ }
+
_gmx_error("fatal",msg,file,line);
}
#ifdef GMX_MPI
- /* Let all other processes wait till the master has printed
- * the error message and issued MPI_Abort.
- */
- MPI_Barrier(MPI_COMM_WORLD);
+ if (gmx_parallel_env_initialized())
+ {
+ if (bFinalize)
+ {
+ /* Broadcast the fatal error number possibly modified
+ * on the master process, in case the user would like
+ * to use the return status on a non-master process.
+ * The master process in cr and dd always has global rank 0.
+ */
+ MPI_Bcast(&fatal_errno,sizeof(fatal_errno),MPI_BYTE,
+ 0,MPI_COMM_WORLD);
+
+ /* Finalize nicely instead of aborting */
+ MPI_Finalize();
+ }
+ else
+ {
+ /* Let all other processes wait till the master has printed
+ * the error message and issued MPI_Abort.
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+ }
+ }
#endif
+
+ exit(fatal_errno);
}
void _invalid_case(const char *fn,int line)
strerr = gmx_strerror(key);
sprintf(buf,"\n%s\nProgram %s, %s\n"
"Source code file: %s, line: %d\n\n"
- "%s:\n%s\nFor more information and tips for trouble shooting please check the GROMACS website at\n"
- "http://www.gromacs.org/Documentation/Errors\n%s\n\n%s\n",
+ "%s:\n%s\nFor more information and tips for troubleshooting, please check the GROMACS\n"
+ "website at http://www.gromacs.org/Documentation/Errors\n%s\n\n%s\n",
llines,ShortProgram(),GromacsVersion(),file,line,
strerr,msg ? msg : errerrbuf,llines,tmpbuf);
free(strerr);
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ * $Id: gmx_matrix.c,v 1.4 2008/12/02 18:27:57 spoel Exp $
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 4.0.99
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Groningen Machine for Chemical Simulation
+ */
+#include <stdlib.h>
+#include "typedefs.h"
+#include "smalloc.h"
+#include "vec.h"
+#include "gmx_fatal.h"
+#include "gmx_matrix.h"
+#include "gmx_lapack.h"
+
+double **alloc_matrix(int n,int m)
+{
+ double **ptr;
+ int i;
+
+ /* There's always time for more pointer arithmetic! */
+ /* This is necessary in order to be able to work with LAPACK */
+ snew(ptr,n);
+ snew(ptr[0],n*m);
+ for(i=1; (i<n); i++)
+ ptr[i] = ptr[i-1]+m;
+ return ptr;
+}
+
+void free_matrix(double **a,int n)
+{
+ int i;
+
+ sfree(a[0]);
+ sfree(a);
+}
+
+#define DEBUG_MATRIX
+void matrix_multiply(FILE *fp,int n,int m,double **x,double **y,double **z)
+{
+ int i,j,k;
+
+#ifdef DEBUG_MATRIX
+ if (fp)
+ fprintf(fp,"Multiplying %d x %d matrix with a %d x %d matrix\n",
+ n,m,m,n);
+ if (fp)
+ for(i=0; (i<n); i++)
+ {
+ for(j=0; (j<m); j++)
+ fprintf(fp," %7g",x[i][j]);
+ fprintf(fp,"\n");
+ }
+#endif
+ for(i=0; (i<m); i++)
+ {
+ for(j=0; (j<m); j++)
+ {
+ z[i][j] = 0;
+ for(k=0; (k<n); k++)
+ z[i][j] += x[k][i]*y[j][k];
+ }
+ }
+}
+
+static void dump_matrix(FILE *fp,const char *title,int n,double **a)
+{
+ double d=1;
+ int i,j;
+
+ fprintf(fp,"%s\n",title);
+ for(i=0; (i<n); i++)
+ {
+ d = d*a[i][i];
+ for(j=0; (j<n); j++)
+ {
+ fprintf(fp," %8.2f",a[i][j]);
+ }
+ fprintf(fp,"\n");
+ }
+ fprintf(fp,"Prod a[i][i] = %g\n",d);
+}
+
+int matrix_invert(FILE *fp,int n,double **a)
+{
+ int i,j,m,lda,*ipiv,lwork,info;
+ double **test=NULL,**id,*work;
+
+#ifdef DEBUG_MATRIX
+ if (fp)
+ {
+ fprintf(fp,"Inverting %d square matrix\n",n);
+ test = alloc_matrix(n,n);
+ for(i=0; (i<n); i++)
+ {
+ for(j=0; (j<n); j++)
+ {
+ test[i][j] = a[i][j];
+ }
+ }
+ dump_matrix(fp,"before inversion",n,a);
+ }
+#endif
+ snew(ipiv,n);
+ lwork = n*n;
+ snew(work,lwork);
+ m = lda = n;
+ info = 0;
+ F77_FUNC(dgetrf,DGETRF)(&n,&m,a[0],&lda,ipiv,&info);
+#ifdef DEBUG_MATRIX
+ if (fp)
+ dump_matrix(fp,"after dgetrf",n,a);
+#endif
+ if (info != 0)
+ return info;
+ F77_FUNC(dgetri,DGETRI)(&n,a[0],&lda,ipiv,work,&lwork,&info);
+#ifdef DEBUG_MATRIX
+ if (fp)
+ dump_matrix(fp,"after dgetri",n,a);
+#endif
+ if (info != 0)
+ return info;
+
+#ifdef DEBUG_MATRIX
+ if (fp)
+ {
+ id = alloc_matrix(n,n);
+ matrix_multiply(fp,n,n,test,a,id);
+ dump_matrix(fp,"And here is the product of A and Ainv",n,id);
+ free_matrix(id,n);
+ free_matrix(test,n);
+ }
+#endif
+ sfree(ipiv);
+ sfree(work);
+
+ return 0;
+}
+
+double multi_regression(FILE *fp,int nrow,double *y,int ncol,
+ double **xx,double *a0)
+{
+ int row,niter,i,j;
+ double ax,chi2,**a,**at,**ata,*atx;
+
+ a = alloc_matrix(nrow,ncol);
+ at = alloc_matrix(ncol,nrow);
+ ata = alloc_matrix(ncol,ncol);
+ for(i=0; (i<nrow); i++)
+ for(j=0; (j<ncol); j++)
+ at[j][i] = a[i][j] = xx[j][i];
+ matrix_multiply(fp,nrow,ncol,a,at,ata);
+ if ((row = matrix_invert(fp,ncol,ata)) != 0) {
+ gmx_fatal(FARGS,"Matrix inversion failed. Incorrect row = %d.\nThis probably indicates that you do not have sufficient data points, or that some parameters are linearly dependent.",
+ row);
+ }
+ snew(atx,ncol);
+
+ for(i=0; (i<ncol); i++)
+ {
+ atx[i] = 0;
+ for(j=0; (j<nrow); j++)
+ atx[i] += at[i][j]*y[j];
+ }
+ for(i=0; (i<ncol); i++)
+ {
+ a0[i] = 0;
+ for(j=0; (j<ncol); j++)
+ a0[i] += ata[i][j]*atx[j];
+ }
+ chi2 = 0;
+ for(j=0; (j<nrow); j++)
+ {
+ ax = 0;
+ for(i=0; (i<ncol); i++)
+ ax += a0[i]*a[j][i];
+ chi2 += sqr(y[j]-ax);
+ }
+
+ sfree(atx);
+ free_matrix(a,nrow);
+ free_matrix(at,ncol);
+ free_matrix(ata,ncol);
+
+ return chi2;
+}
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This file is part of Gromacs Copyright (c) 1991-2010
+ * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org
+ *
+ * And Hey:
+ * Gnomes, ROck Monsters And Chili Sauce
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include "gmx_sort.h"
+
+
+static void
+qsort_swapfunc(void * a,
+ void * b,
+ size_t n,
+ int swaptype)
+{
+ int * ia;
+ int * ib;
+ int itmp;
+
+ char * ca;
+ char * cb;
+ char ctmp;
+
+ if (swaptype <= 1)
+ {
+ ia = (int *)a;
+ ib = (int *)b;
+ for( ; n > 0; ia += 1, ib += 1, n -= sizeof(int))
+ {
+ itmp = *ia;
+ *ia = *ib;
+ *ib = itmp;
+ }
+ }
+ else
+ {
+ ca = (char *)a;
+ cb = (char *)b;
+ for( ; n > 0; ca += 1, cb += 1, n -= 1)
+ {
+ ctmp = *ca;
+ *ca = *cb;
+ *cb = ctmp;
+ }
+ }
+}
+
+
+static void *
+qsort_med3(void * a,
+ void * b,
+ void * c,
+ int (*compar) (const void *a, const void *b))
+{
+ if(compar(a,b) < 0)
+ {
+ if(compar(b,c) < 0)
+ return b;
+ else if(compar(a,c) < 0)
+ return c;
+ else
+ return a;
+ }
+ else
+ {
+ if(compar(b,c) > 0)
+ return b;
+ else if(compar(a,c) > 0)
+ return c;
+ else
+ return a;
+ }
+}
+
+
+void
+gmx_qsort(void * base,
+ size_t nmemb,
+ size_t size,
+ int (*compar)(const void *, const void *))
+{
+#define QSORT_EXCH(a, b, t) (t = a, a = b, b = t);
+#define QSORT_SWAP(a, b) swaptype != 0 ? qsort_swapfunc(a, b, size, swaptype) : \
+ (void)QSORT_EXCH(*(int *)(a), *(int *)(b), t)
+
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn, *pv, *cbase;
+ int r, swaptype;
+ int t, v;
+ size_t s, st;
+
+ cbase = (char *)base;
+
+ swaptype = (size_t)(cbase - (char *)0) % sizeof(int) || size % sizeof(int) ? 2 : size == sizeof(int)? 0 : 1;
+
+ if (nmemb < 7)
+ {
+ /* Insertion sort on smallest arrays */
+ for (pm = cbase + size; pm < cbase + nmemb*size; pm += size)
+ {
+ for (pl = pm; (pl > cbase) && compar((void *)(pl-size),(void *) pl) > 0; pl -= size)
+ {
+ QSORT_SWAP(pl, pl-size);
+ }
+ }
+ return;
+ }
+
+ /* Small arrays, middle element */
+ pm = cbase + (nmemb/2)*size;
+
+ if (nmemb > 7)
+ {
+ pl = cbase;
+ pn = cbase + (nmemb-1)*size;
+ if (nmemb > 40)
+ {
+ /* Big arrays, pseudomedian of 9 */
+ s = (nmemb/8)*size;
+ pl = (char *)qsort_med3((void *)pl, (void *)((size_t)pl+s), (void *)((size_t)pl+2*s), compar);
+ pm = (char *)qsort_med3((void *)((size_t)pm-s), (void *)pm, (void *)((size_t)pm+s), compar);
+ pn = (char *)qsort_med3((void *)((size_t)pn-2*s), (void *)((size_t)pn-s), (void *)pn, compar);
+ }
+ /* Mid-size, med of 3 */
+ pm = (char *)qsort_med3((void *)pl, (void *)pm, (void *)pn, compar);
+ }
+
+ /* pv points to partition value */
+ if (swaptype != 0)
+ {
+ pv = cbase;
+ QSORT_SWAP(pv, pm);
+ }
+ else
+ {
+ pv = (char*)(void*)&v;
+ v = *(int *)pm;
+ }
+
+ pa = pb = cbase;
+ pc = pd = cbase + (nmemb-1)*size;
+
+ for (;;)
+ {
+ while (pb <= pc && (r = compar((void *)pb,(void *) pv)) <= 0)
+ {
+ if (r == 0)
+ {
+ QSORT_SWAP(pa, pb);
+ pa += size;
+ }
+ pb += size;
+ }
+ while (pc >= pb && (r = compar((void *)pc,(void *) pv)) >= 0)
+ {
+ if (r == 0)
+ {
+ QSORT_SWAP(pc, pd);
+ pd -= size;
+ }
+ pc -= size;
+ }
+ if (pb > pc)
+ {
+ break;
+ }
+ QSORT_SWAP(pb, pc);
+ pb += size;
+ pc -= size;
+ }
+ pn = cbase + nmemb*size;
+
+ s = pa-cbase;
+ st = pb-pa;
+ if(st<s)
+ {
+ s = st;
+ }
+
+ if(s>0)
+ {
+ qsort_swapfunc(cbase, pb-s, s, swaptype);
+ }
+
+ s = pd-pc;
+ st = pn-pd-size;
+ if(st<s)
+ {
+ s = st;
+ }
+
+ if(s>0)
+ {
+ qsort_swapfunc(pb, pn-s, s, swaptype);
+ }
+
+ if ((s = pb-pa) > size)
+ {
+ gmx_qsort(cbase, s/size, size, compar);
+ }
+
+ if ((s = pd-pc) > size)
+ {
+ gmx_qsort(pn-s, s/size, size, compar);
+ }
+
+#undef QSORT_EXCH
+#undef QSORT_SWAP
+
+ return;
+}
+
+
+
/*
* for unit alignment
*/
-static char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
+const static char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
static xdr_uint32_t xdr_swapbytes(xdr_uint32_t x)
{
xdr_opaque (XDR *xdrs, char *cp, unsigned int cnt)
{
unsigned int rndup;
- static char crud[BYTES_PER_XDR_UNIT];
+ char crud[BYTES_PER_XDR_UNIT];
/*
* if no data we are done
/* Windows and some other systems dont define double-precision
* word order in the header files, so unfortunately we have
* to calculate it!
+ *
+ * For thread safety, we calculate it every time: locking this would
+ * be more expensive.
*/
- static int LSW=-1; /* Least significant fp word */
+ /*static int LSW=-1;*/ /* Least significant fp word */
+ int LSW=-1; /* Least significant fp word */
+
+
int *ip;
xdr_int32_t tmp[2];
}
}
-static void add_define(const char *define)
+static void add_define(const char *name, const char *value)
{
int i;
- const char *ptr;
- char name[256];
-
- sscanf(define,"%s%n",name,&i);
- ptr = define + i;
-
- while ((*ptr != '\0') && isspace(*ptr))
- ptr++;
-
+
for(i=0; (i<ndef); i++) {
if (strcmp(defs[i].name,name) == 0) {
break;
fprintf(debug,"Overriding define %s\n",name);
sfree(defs[i].def);
}
- if (strlen(ptr) > 0)
- defs[i].def = strdup(ptr);
+ if (value && strlen(value) > 0)
+ defs[i].def = strdup(value);
else
defs[i].def = NULL;
}
{
gmx_cpp_t cpp;
char *buf,*pdum;
- const char *ptr;
+ char *ptr;
int i;
unsigned int i1;
if (strstr(cppopts[i],"-I") == cppopts[i])
add_include(cppopts[i]+2);
if (strstr(cppopts[i],"-D") == cppopts[i])
- add_define(cppopts[i]+2);
+ {
+ /* If the option contains a =, split it into name and value. */
+ ptr = strchr(cppopts[i], '=');
+ if (ptr)
+ {
+ buf = strndup(cppopts[i] + 2, ptr - cppopts[i] - 2);
+ add_define(buf, ptr + 1);
+ sfree(buf);
+ }
+ else
+ {
+ add_define(cppopts[i] + 2, NULL);
+ }
+ }
i++;
}
}
snew(cpp,1);
*handle = cpp;
- ptr = strrchr(filenm,'/');
- if (NULL == ptr) {
+ cpp->fn = NULL;
+ /* Find the file. First check whether it is in the current directory. */
+ if (gmx_fexist(filenm))
+ {
+ cpp->fn = strdup(filenm);
+ }
+ else
+ {
+ /* If not, check all the paths given with -I. */
+ for (i = 0; i < nincl; ++i)
+ {
+ snew(buf, strlen(incl[i]) + strlen(filenm) + 2);
+ sprintf(buf, "%s%c%s", incl[i], DIR_SEPARATOR, filenm);
+ if (gmx_fexist(buf))
+ {
+ cpp->fn = buf;
+ break;
+ }
+ sfree(buf);
+ }
+ /* If still not found, check the Gromacs library search path. */
+ if (!cpp->fn)
+ {
+ cpp->fn = low_gmxlibfn(filenm, FALSE);
+ }
+ }
+ if (!cpp->fn)
+ {
+ gmx_fatal(FARGS, "Topology include file \"%s\" not found", filenm);
+ }
+ /* If the file name has a path component, we need to change to that
+ * directory. */
+ ptr = strrchr(cpp->fn, DIR_SEPARATOR);
+ if (!ptr)
+ {
cpp->path = NULL;
cpp->cwd = NULL;
- cpp->fn = strdup(filenm);
}
- else {
- buf = strdup(filenm);
- buf[ptr-filenm] = '\0';
+ else
+ {
+ cpp->path = cpp->fn;
+ *ptr = '\0';
cpp->fn = strdup(ptr+1);
snew(cpp->cwd,STRLEN);
- /* Search for the directory in cwd and the GROMACS search path */
- cpp->path = gmxlibfn(buf);
- sfree(buf);
-
#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
pdum=_getcwd(cpp->cwd,STRLEN);
_chdir(cpp->path);
cpp->ifdefs = NULL;
cpp->child = NULL;
cpp->parent = NULL;
- i = 0;
- while (((cpp->fp = fopen(cpp->fn,"r")) == NULL) && (i<nincl)) {
- snew(buf,strlen(incl[i])+strlen(filenm)+2);
- sprintf(buf,"%s/%s",incl[i],filenm);
- sfree(cpp->fn);
- cpp->fn = strdup(buf);
- sfree(buf);
- i++;
- }
if (cpp->fp == NULL) {
- sfree(cpp->fn);
- cpp->fn = strdup(filenm);
- cpp->fp = libopen(filenm);
+ cpp->fp = fopen(cpp->fn, "r");
}
if (cpp->fp == NULL) {
switch(errno) {
int i,i0,len,status;
unsigned int i1;
char *inc_fn,*name;
+ const char *ptr;
int bIfdef,bIfndef;
/* #ifdef or ifndef statement */
/* #define statement */
if (strcmp(dname,"define") == 0) {
- add_define(dval);
+ /* Split it into name and value. */
+ ptr = dval;
+ while ((*ptr != '\0') && !isspace(*ptr))
+ ptr++;
+ name = strndup(dval, ptr - dval);
+
+ while ((*ptr != '\0') && isspace(*ptr))
+ ptr++;
+
+ add_define(name, ptr);
+ sfree(name);
return eCPP_OK;
}
#include <ctype.h>
#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
#include "gmx_fatal.h"
#include "macros.h"
#include "thread_mpi.h"
#endif
-/* The source code in this file should be thread-safe.
- * But some functions are NOT THREADSAFE when multiple threads
- * use the same file pointer.
- * Please keep it that way.
- */
+#include "gmxfio_int.h"
-/* XDR should be available on all platforms now,
- * but we keep the possibility of turning it off...
- */
-#define USE_XDR
+/* This is the new improved and thread safe version of gmxfio. */
+
+
+
+/* the list of open files is a linked list, with a dummy element at its head;
+ it is initialized when the first file is opened. */
+static t_fileio *open_files = NULL;
+
+
+#ifdef GMX_THREADS
+/* this mutex locks the open_files structure so that no two threads can
+ modify it.
+
+ For now, we use this as a coarse grained lock on all file
+ insertion/deletion operations because it makes avoiding deadlocks
+ easier, and adds almost no overhead . */
+static tMPI_Thread_mutex_t open_file_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
+#endif
-typedef struct
-{
- int iFTP;
- bool bOpen, bRead, bDouble, bDebug, bStdio;
- char *fn;
- FILE *fp;
- XDR *xdr;
- bool bLargerThan_off_t, bReadWrite;
-} t_fileio;
/* These simple lists define the I/O type for these files */
static const int ftpXDR[] =
{ efXML};
#endif
-bool in_ftpset(int ftp, int nset, const int set[])
+const char *itemstr[eitemNR] =
+ { "[header]", "[inputrec]", "[box]", "[topology]", "[coordinates]",
+ "[velocities]", "[forces]" };
+
+const char *eioNames[eioNR] =
+ { "REAL", "INT", "GMX_STE_T", "UCHAR", "NUCHAR", "USHORT", "RVEC", "NRVEC",
+ "IVEC", "STRING" };
+
+
+
+/* Comment strings for TPA only */
+const char *comment_str[eitemNR] = {
+"; The header holds information on the number of atoms etc. and on whether\n"
+"; certain items are present in the file or not.\n"
+"; \n"
+"; WARNING\n"
+"; DO NOT EDIT THIS FILE BY HAND\n"
+"; The GROMACS preprocessor performs a lot of checks on your input that\n"
+"; you ignore when editing this. Your simulation may crash because of this\n",
+"; The inputrec holds the parameters for MD such as the number of steps,\n"
+"; the timestep and the cut-offs.\n",
+"; The simulation box in nm.\n",
+"; The topology section describes the topology of the molecules\n"
+"; i.e. bonds, angles and dihedrals etc. and also holds the force field\n"
+"; parameters.\n",
+"; The atomic coordinates in nm\n",
+"; The atomic velocities in nm/ps\n",
+"; The forces on the atoms in nm/ps^2\n" };
+
+
+
+
+/******************************************************************
+ *
+ * Internal functions:
+ *
+ ******************************************************************/
+
+static int gmx_fio_int_flush(t_fileio* fio)
+{
+ int rc = 0;
+
+ if (fio->fp)
+ {
+ rc = fflush(fio->fp);
+ }
+ else if (fio->xdr)
+ {
+ rc = fflush((FILE *) fio->xdr->x_private);
+ }
+
+ return rc;
+}
+
+/* returns TRUE if the file type ftp is in the set set */
+static bool in_ftpset(int ftp, int nset, const int set[])
{
int i;
bool bResult;
return bResult;
}
-static bool do_dummy(void *item, int nitem, int eio, const char *desc,
- const char *srcfile, int line)
-{
- gmx_fatal(FARGS, "gmx_fio_select not called!");
- return FALSE;
-}
-/* Global variables */
-do_func *do_read = do_dummy;
-do_func *do_write = do_dummy;
-const char *itemstr[eitemNR] =
- { "[header]", "[inputrec]", "[box]", "[topology]", "[coordinates]",
- "[velocities]", "[forces]" };
-/* Comment strings for TPA only */
-const char
-*comment_str[eitemNR] =
- {
- "; The header holds information on the number of atoms etc. and on whether\n"
- "; certain items are present in the file or not.\n"
- "; \n"
- "; WARNING\n"
- "; DO NOT EDIT THIS FILE BY HAND\n"
- "; The GROMACS preprocessor performs a lot of checks on your input that\n"
- "; you ignore when editing this. Your simulation may crash because of this\n",
-
- "; The inputrec holds the parameters for MD such as the number of steps,\n"
- "; the timestep and the cut-offs.\n",
- "; The simulation box in nm.\n",
- "; The topology section describes the topology of the molcecules\n"
- "; i.e. bonds, angles and dihedrals etc. and also holds the force field\n"
- "; parameters.\n", "; The atomic coordinates in nm\n",
- "; The atomic velocities in nm/ps\n",
- "; The forces on the atoms in nm/ps^2\n" };
-
-/* Local variables */
-static t_fileio *FIO = NULL;
-static t_fileio *curfio = NULL;
-static int nFIO = 0;
-static const char *eioNames[eioNR] =
- { "REAL", "INT", "GMX_STE_T", "UCHAR", "NUCHAR", "USHORT", "RVEC", "NRVEC",
- "IVEC", "STRING" };
-static char *add_comment = NULL;
+extern void gmx_fio_set_comment(t_fileio *fio, const char *comment)
+{
+ fio->comment=comment;
+}
-#ifdef GMX_THREADS
-static tMPI_Thread_mutex_t fio_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
-/* this mutex locks concurrent access to the FIO and curfio arrays, the
- nFIO counter, and the add_comment string. For now this is
- the easiest way to make this all thread-safe. Because I/O is mostly
- done by the master node, this won't cause any performance issues
- (locking/unlocking mutexes is very cheap as long as no thread get
- scheduled out). */
-#endif
+extern void gmx_fio_unset_comment(t_fileio *fio)
+{
+ fio->comment=NULL;
+}
-/* these functions are all called from functions that lock the fio_mutex
- themselves, and need to make sure that the called function doesn't
- try to lock that mutex again. */
-static int gmx_fio_flush_lock(int fio, bool do_lock);
-static int gmx_fio_close_lock(int fio, bool do_lock);
-static bool do_xdr_lock(void *item, int nitem, int eio, const char *desc,
- const char *srcfile, int line, bool do_lock);
-static const char *dbgstr(const char *desc)
+const char *gmx_fio_dbgstr(t_fileio *fio, const char *desc, char *buf)
{
- static const char *null_str = "";
- static char buf[STRLEN];
-
- if (!curfio->bDebug)
+ if (!fio->bDebug)
{
- return null_str;
+ /* set to empty string */
+ buf[0]=0;
}
else
{
- sprintf(buf, " ; %s %s", add_comment ? add_comment : "", desc);
- return buf;
- }
-}
-
-void set_comment(const char *comment)
-{
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- if (comment)
- add_comment = strdup(comment);
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
+#if (defined( _WIN32 ) || defined( _WIN64 ) )
+ /* windows doesn't do standard C */
+#define snprintf sprintf_s
#endif
+ snprintf(buf, GMX_FIO_BUFLEN, " ; %s %s",
+ fio->comment ? fio->comment : "", desc);
+ }
+ return buf;
}
-void unset_comment(void)
-{
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- if (add_comment)
- sfree(add_comment);
- add_comment = NULL;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-}
-static void _check_nitem(int eio, int nitem, const char *file, int line)
+/* check the number of items given against the type */
+void gmx_fio_check_nitem(t_fileio *fio, int eio, int nitem, const char *file,
+ int line)
{
if ((nitem != 1) && !((eio == eioNRVEC) || (eio == eioNUCHAR)))
- gmx_fatal(FARGS, "nitem (%d) may differ from 1 only for %s or %s, not for %s"
+ gmx_fatal(FARGS,
+ "nitem (%d) may differ from 1 only for %s or %s, not for %s"
"(%s, %d)",nitem,eioNames[eioNUCHAR],eioNames[eioNRVEC],
eioNames[eio],file,line);
}
-#define check_nitem() _check_nitem(eio,nitem,__FILE__,__LINE__)
-static void fe(int eio, const char *desc, const char *srcfile, int line)
+/* output a data type error. */
+void gmx_fio_fe(t_fileio *fio, int eio, const char *desc,
+ const char *srcfile, int line)
{
gmx_fatal(FARGS, "Trying to %s %s type %d (%s), src %s, line %d",
- curfio->bRead ? "read" : "write",desc,eio,
- ((eio >= 0) && (eio < eioNR)) ? eioNames[eio] : "unknown",
- srcfile,line);
+ fio->bRead ? "read" : "write",desc,eio,
+ ((eio >= 0) && (eio < eioNR)) ? eioNames[eio] : "unknown",
+ srcfile,line);
}
-#define FE() fe(eio,desc,__FILE__,__LINE__)
-static void encode_string(int maxlen, char dst[], char src[])
+/* set the reader/writer functions based on the file type */
+static void gmx_fio_set_iotype(t_fileio *fio)
{
- int i;
-
- for (i = 0; (src[i] != '\0') && (i < maxlen - 1); i++)
- if ((src[i] == ' ') || (src[i] == '\t'))
- dst[i] = '_';
- else
- dst[i] = src[i];
- dst[i] = '\0';
-
- if (i == maxlen)
- fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
-}
-
-static void decode_string(int maxlen, char dst[], char src[])
-{
- int i;
-
- for (i = 0; (src[i] != '\0') && (i < maxlen - 1); i++)
+ if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
{
- if (src[i] == '_')
- {
- dst[i] = ' ';
- }
- else
- {
- dst[i] = src[i];
- }
+#ifdef USE_XDR
+ fio->iotp=&xdr_iotype;
+#else
+ gmx_fatal(FARGS,"Sorry, no XDR");
+#endif
}
- dst[i] = '\0';
-
- if (i == maxlen)
+ else if (in_ftpset(fio->iFTP, asize(ftpASC), ftpASC))
+ {
+ fio->iotp=&asc_iotype;
+ }
+ else if (in_ftpset(fio->iFTP, asize(ftpBIN), ftpBIN))
+ {
+ fio->iotp=&bin_iotype;
+ }
+#ifdef HAVE_XMl
+ else if (in_ftpset(fio->iFTP,asize(ftpXML),ftpXML))
{
- fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
+ fio->iotp=&dummy_iotype;
}
+#endif
+ else
+ fio->iotp=&dummy_iotype;
}
-static bool do_ascwrite(void *item, int nitem, int eio, const char *desc,
- const char *srcfile, int line)
-{
- int i;
- int res = 0, *iptr;
- real *ptr;
- char strbuf[256];
- unsigned char *ucptr;
+/* lock the mutex associated with this fio. This needs to be done for every
+ type of access to the fio's elements. */
+void gmx_fio_lock(t_fileio *fio)
+{
#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
+ tMPI_Spinlock_lock(&(fio->mtx));
#endif
- check_nitem();
- switch (eio)
- {
- case eioREAL:
- case eioDOUBLE:
- res = fprintf(curfio->fp, "%18.10e%s\n", *((real *) item), dbgstr(desc));
- break;
- case eioINT:
- res = fprintf(curfio->fp, "%18d%s\n", *((int *) item), dbgstr(desc));
- break;
- case eioGMX_LARGE_INT:
- sprintf(strbuf, "%s%s%s", "%", gmx_large_int_fmt, "\n");
- res = fprintf(curfio->fp, strbuf, *((gmx_large_int_t *) item),
- dbgstr(desc));
- break;
- case eioUCHAR:
- res = fprintf(curfio->fp, "%4d%s\n", *((unsigned char *) item),
- dbgstr(desc));
- break;
- case eioNUCHAR:
- ucptr = (unsigned char *) item;
- for (i = 0; (i < nitem); i++)
- res = fprintf(curfio->fp, "%4d", (int) ucptr[i]);
- fprintf(curfio->fp, "%s\n", dbgstr(desc));
- break;
- case eioUSHORT:
- res = fprintf(curfio->fp, "%18d%s\n", *((unsigned short *) item),
- dbgstr(desc));
- break;
- case eioRVEC:
- ptr = (real *) item;
- res = fprintf(curfio->fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
- ptr[YY], ptr[ZZ], dbgstr(desc));
- break;
- case eioNRVEC:
- for (i = 0; (i < nitem); i++)
- {
- ptr = ((rvec *) item)[i];
- res = fprintf(curfio->fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
- ptr[YY], ptr[ZZ], dbgstr(desc));
- }
- break;
- case eioIVEC:
- iptr = (int *) item;
- res = fprintf(curfio->fp, "%18d%18d%18d%s\n", iptr[XX], iptr[YY],
- iptr[ZZ], dbgstr(desc));
- break;
- case eioSTRING:
- encode_string(256, strbuf, (char *) item);
- res = fprintf(curfio->fp, "%-18s%s\n", strbuf, dbgstr(desc));
- break;
- default:
- FE();
- }
- if ((res <= 0) && curfio->bDebug)
- fprintf(stderr,
- "Error writing %s %s to file %s (source %s, line %d)\n",
- eioNames[eio], desc, curfio->fn, srcfile, line);
+}
+/* unlock the mutex associated with this fio. */
+void gmx_fio_unlock(t_fileio *fio)
+{
#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
+ tMPI_Spinlock_unlock(&(fio->mtx));
#endif
- return (res > 0);
}
-/* This is a global variable that is reset when a file is opened. */
-/*static int nbuf=0;*/
-
-static char *next_item(FILE *fp, char *buf, int buflen)
+/* make a dummy head element, assuming we locked everything. */
+static void gmx_fio_make_dummy(void)
{
- int rd;
- bool in_comment = FALSE;
- bool in_token = FALSE;
- int i = 0;
- /* This routine reads strings from the file fp, strips comment
- * and buffers. For thread-safety reasons, It reads through getc() */
-
- rd = getc(fp);
- if (rd == EOF)
- gmx_file("End of file");
- do
+ if (!open_files)
{
- if (in_comment)
- {
- if (rd == '\n')
- in_comment = FALSE;
- }
- else if (in_token)
- {
- if (isspace(rd) || rd == ';')
- break;
- buf[i++] = (char) rd;
- }
- else
- {
- if (!isspace(rd))
- {
- if (rd == ';')
- in_comment = TRUE;
- else
- {
- in_token = TRUE;
- buf[i++] = (char) (rd);
- }
- }
- }
- if (i >= buflen - 2)
- break;
- } while ((rd = getc(fp)) != EOF);
+ snew(open_files,1);
+ open_files->fp=NULL;
+ open_files->fn=NULL;
+ open_files->next=open_files;
+ open_files->prev=open_files;
+#ifdef GMX_THREADS
+ tMPI_Spinlock_init(&(open_files->mtx));
+#endif
+ }
+}
- fprintf(stderr, "WARNING, ftpASC file type not tested!\n");
- buf[i] = 0;
- return buf;
-}
-static bool do_ascread(void *item, int nitem, int eio, const char *desc,
- const char *srcfile, int line)
-{
- FILE *fp = curfio->fp;
- int i, m, res = 0, *iptr, ix;
- gmx_large_int_t s;
- double d, x;
- real *ptr;
- unsigned char uc, *ucptr;
- char *cptr;
-#define NEXT_ITEM_BUF_LEN 128
- char ni_buf[NEXT_ITEM_BUF_LEN];
-
- check_nitem();
- switch (eio)
- {
- case eioREAL:
- case eioDOUBLE:
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf", &d);
- if (item)
- *((real *) item) = d;
- break;
- case eioINT:
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
- if (item)
- *((int *) item) = i;
- break;
- case eioGMX_LARGE_INT:
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN),
- gmx_large_int_pfmt, &s);
- if (item)
- *((gmx_large_int_t *) item) = s;
- break;
- case eioUCHAR:
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%c", &uc);
- if (item)
- *((unsigned char *) item) = uc;
- break;
- case eioNUCHAR:
- ucptr = (unsigned char *) item;
- for (i = 0; (i < nitem); i++)
- {
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &ix);
- if (item)
- ucptr[i] = ix;
- }
- break;
- case eioUSHORT:
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
- if (item)
- *((unsigned short *) item) = i;
- break;
- case eioRVEC:
- ptr = (real *) item;
- for (m = 0; (m < DIM); m++)
- {
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n", &x);
- ptr[m] = x;
- }
- break;
- case eioNRVEC:
- for (i = 0; (i < nitem); i++)
- {
- ptr = ((rvec *) item)[i];
- for (m = 0; (m < DIM); m++)
- {
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n",
- &x);
- if (item)
- ptr[m] = x;
- }
- }
- break;
- case eioIVEC:
- iptr = (int *) item;
- for (m = 0; (m < DIM); m++)
- {
- res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d\n", &ix);
- if (item)
- iptr[m] = ix;
- }
- break;
- case eioSTRING:
- cptr = next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN);
- if (item)
- {
- decode_string(strlen(cptr) + 1, (char *) item, cptr);
- /* res = sscanf(cptr,"%s",(char *)item);*/
- res = 1;
- }
- break;
- default:
- FE();
- }
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- if ((res <= 0) && curfio->bDebug)
- fprintf(stderr,
- "Error reading %s %s from file %s (source %s, line %d)\n",
- eioNames[eio], desc, curfio->fn, srcfile, line);
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
- return (res > 0);
-}
-static bool do_binwrite(void *item, int nitem, int eio, const char *desc,
- const char *srcfile, int line)
-{
- size_t size = 0, wsize;
- int ssize;
- check_nitem();
- switch (eio)
- {
- case eioREAL:
- size = sizeof(real);
- break;
- case eioDOUBLE:
- size = sizeof(double);
- break;
- case eioINT:
- size = sizeof(int);
- break;
- case eioGMX_LARGE_INT:
- size = sizeof(gmx_large_int_t);
- break;
- case eioUCHAR:
- size = sizeof(unsigned char);
- break;
- case eioNUCHAR:
- size = sizeof(unsigned char);
- break;
- case eioUSHORT:
- size = sizeof(unsigned short);
- break;
- case eioRVEC:
- size = sizeof(rvec);
- break;
- case eioNRVEC:
- size = sizeof(rvec);
- break;
- case eioIVEC:
- size = sizeof(ivec);
- break;
- case eioSTRING:
- size = ssize = strlen((char *) item) + 1;
- do_binwrite(&ssize, 1, eioINT, desc, srcfile, line);
- break;
- default:
- FE();
- }
+/***********************************************************************
+ *
+ * FILE LIST OPERATIONS
+ *
+***********************************************************************/
- wsize = fwrite(item, size, nitem, curfio->fp);
+/* insert a new t_fileio into the list */
+static void gmx_fio_insert(t_fileio *fio)
+{
+ t_fileio *prev;
#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- if ((wsize != nitem) && curfio->bDebug)
+ /* first lock the big open_files mutex. */
+ tMPI_Thread_mutex_lock(&open_file_mutex);
+#endif
+ /* now check whether the dummy element has been allocated,
+ and allocate it if it hasn't */
+ gmx_fio_make_dummy();
+
+ /* and lock the fio we got and the list's head **/
+ gmx_fio_lock(fio);
+ gmx_fio_lock(open_files);
+ prev=open_files->prev;
+ /* lock the element after the current one */
+ if (prev != open_files)
{
- fprintf(stderr,
- "Error writing %s %s to file %s (source %s, line %d)\n",
- eioNames[eio], desc, curfio->fn, srcfile, line);
- fprintf(stderr, "written size %u bytes, source size %u bytes\n",
- (unsigned int) wsize, (unsigned int) size);
+ gmx_fio_lock(prev);
}
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
- return (wsize == nitem);
-}
-static bool do_binread(void *item, int nitem, int eio, const char *desc,
- const char *srcfile, int line)
-{
- size_t size = 0, rsize;
- int ssize;
+ /* now do the actual insertion: */
+ fio->next=open_files;
+ open_files->prev=fio;
+ prev->next=fio;
+ fio->prev=prev;
- check_nitem();
- switch (eio)
+ /* now unlock all our locks */
+ if (prev != open_files)
{
- case eioREAL:
- if (curfio->bDouble)
- size = sizeof(double);
- else
- size = sizeof(float);
- break;
- case eioDOUBLE:
- size = sizeof(double);
- break;
- case eioINT:
- size = sizeof(int);
- break;
- case eioGMX_LARGE_INT:
- size = sizeof(gmx_large_int_t);
- break;
- case eioUCHAR:
- size = sizeof(unsigned char);
- break;
- case eioNUCHAR:
- size = sizeof(unsigned char);
- break;
- case eioUSHORT:
- size = sizeof(unsigned short);
- break;
- case eioRVEC:
- case eioNRVEC:
- if (curfio->bDouble)
- size = sizeof(double) * DIM;
- else
- size = sizeof(float) * DIM;
- break;
- case eioIVEC:
- size = sizeof(ivec);
- break;
- case eioSTRING:
- do_binread(&ssize, 1, eioINT, desc, srcfile, line);
- size = ssize;
- break;
- default:
- FE();
+ gmx_fio_unlock(prev);
}
+ gmx_fio_unlock(open_files);
+ gmx_fio_unlock(fio);
#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
+ /* now unlock the big open_files mutex. */
+ tMPI_Thread_mutex_unlock(&open_file_mutex);
#endif
- if (item)
- rsize = fread(item, size, nitem, curfio->fp);
- else
- {
- /* Skip over it if we have a NULL pointer here */
-#ifdef HAVE_FSEEKO
- fseeko(curfio->fp, (off_t) (size * nitem), SEEK_CUR);
-#else
- fseek(curfio->fp,(size*nitem),SEEK_CUR);
-#endif
- rsize = nitem;
- }
- if ((rsize != nitem) && (curfio->bDebug))
- fprintf(stderr,
- "Error reading %s %s from file %s (source %s, line %d)\n",
- eioNames[eio], desc, curfio->fn, srcfile, line);
+}
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
- return (rsize == nitem);
+/* remove a t_fileio into the list. We assume the fio is locked, and we leave
+ it locked. */
+static void gmx_fio_remove(t_fileio *fio)
+{
+ t_fileio *prev;
+
+ /* this looks a bit complicated because we're trying to avoid a
+ deadlock with threads that are walking through the structure
+ with gmx_fio_get_next(): if they're trying to lock our current structure
+ while we are trying to lock the previous structure, we get a deadlock.
+ */
+ do
+ {
+ /* we remember the prev */
+ prev=fio->prev;
+ /* and unlock it to prevent deadlocks */
+ gmx_fio_unlock(fio);
+ /* lock the prev nbr */
+ gmx_fio_lock(prev);
+ /* now that that one is locked, we can safely lock original one again */
+ gmx_fio_lock(fio);
+
+ /* and normally, we should be able to get out of this loop, but maybe
+ things have changed when we unlocked our original fio */
+ } while((prev->next != fio) || (fio->prev != prev));
+ /* now set the prev's pointer */
+ fio->prev->next=fio->next;
+ gmx_fio_unlock(fio->prev);
+
+ /* with the next ptr, we can simply lock while the original was locked */
+ gmx_fio_lock(fio->next);
+ fio->next->prev=fio->prev;
+ gmx_fio_unlock(fio->next);
+
+ /* and make sure we point nowhere in particular */
+ fio->next=fio->prev=fio;
}
-#ifdef USE_XDR
-/* this is a recursive function that does mutex locking, so
- there is an a function that locks (do_xdr) and the real function
- that calls itself without locking. */
-static bool do_xdr_lock(void *item, int nitem, int eio, const char *desc,
- const char *srcfile, int line, bool do_lock)
+/* get the first open file, or NULL if there is none.
+ Returns a locked fio. */
+static t_fileio *gmx_fio_get_first(void)
{
- unsigned char ucdum, *ucptr;
- bool_t res = 0;
- float fvec[DIM];
- double dvec[DIM];
- int j, m, *iptr, idum;
- gmx_large_int_t sdum;
- real *ptr;
- unsigned short us;
- double d = 0;
- float f = 0;
+ t_fileio *ret;
+ /* first lock the big open_files mutex and the dummy's mutex */
+ gmx_fio_make_dummy();
#ifdef GMX_THREADS
- if (do_lock)
- tMPI_Thread_mutex_lock(&fio_mutex);
+ /* first lock the big open_files mutex. */
+ tMPI_Thread_mutex_lock(&open_file_mutex);
#endif
- check_nitem();
- switch (eio)
- {
- case eioREAL:
- if (curfio->bDouble)
- {
- if (item && !curfio->bRead)
- d = *((real *) item);
- res = xdr_double(curfio->xdr, &d);
- if (item)
- *((real *) item) = d;
- }
- else
- {
- if (item && !curfio->bRead)
- f = *((real *) item);
- res = xdr_float(curfio->xdr, &f);
- if (item)
- *((real *) item) = f;
- }
- break;
- case eioDOUBLE:
- if (item && !curfio->bRead)
- d = *((double *) item);
- res = xdr_double(curfio->xdr, &d);
- if (item)
- *((double *) item) = d;
- break;
- case eioINT:
- if (item && !curfio->bRead)
- idum = *(int *) item;
- res = xdr_int(curfio->xdr, &idum);
- if (item)
- *(int *) item = idum;
- break;
- case eioGMX_LARGE_INT:
- /* do_xdr will not generate a warning when a 64bit gmx_large_int_t
- * value that is out of 32bit range is read into a 32bit gmx_large_int_t.
- */
- if (item && !curfio->bRead)
- sdum = *(gmx_large_int_t *) item;
- res = xdr_gmx_large_int(curfio->xdr, &sdum, NULL);
- if (item)
- *(gmx_large_int_t *) item = sdum;
- break;
- case eioUCHAR:
- if (item && !curfio->bRead)
- ucdum = *(unsigned char *) item;
- res = xdr_u_char(curfio->xdr, &ucdum);
- if (item)
- *(unsigned char *) item = ucdum;
- break;
- case eioNUCHAR:
- ucptr = (unsigned char *) item;
- res = 1;
- for (j = 0; (j < nitem) && res; j++)
- {
- res = xdr_u_char(curfio->xdr, &(ucptr[j]));
- }
- break;
- case eioUSHORT:
- if (item && !curfio->bRead)
- us = *(unsigned short *) item;
- res = xdr_u_short(curfio->xdr, (unsigned short *) &us);
- if (item)
- *(unsigned short *) item = us;
- break;
- case eioRVEC:
- if (curfio->bDouble)
- {
- if (item && !curfio->bRead)
- for (m = 0; (m < DIM); m++)
- dvec[m] = ((real *) item)[m];
- res = xdr_vector(curfio->xdr, (char *) dvec, DIM,
- (unsigned int) sizeof(double),
- (xdrproc_t) xdr_double);
- if (item)
- for (m = 0; (m < DIM); m++)
- ((real *) item)[m] = dvec[m];
- }
- else
- {
- if (item && !curfio->bRead)
- for (m = 0; (m < DIM); m++)
- fvec[m] = ((real *) item)[m];
- res = xdr_vector(curfio->xdr, (char *) fvec, DIM,
- (unsigned int) sizeof(float),
- (xdrproc_t) xdr_float);
- if (item)
- for (m = 0; (m < DIM); m++)
- ((real *) item)[m] = fvec[m];
- }
- break;
- case eioNRVEC:
- ptr = NULL;
- res = 1;
- for (j = 0; (j < nitem) && res; j++)
- {
- if (item)
- ptr = ((rvec *) item)[j];
- res = do_xdr_lock(ptr, 1, eioRVEC, desc, srcfile, line, FALSE);
- }
- break;
- case eioIVEC:
- iptr = (int *) item;
- res = 1;
- for (m = 0; (m < DIM) && res; m++)
- {
- if (item && !curfio->bRead)
- idum = iptr[m];
- res = xdr_int(curfio->xdr, &idum);
- if (item)
- iptr[m] = idum;
- }
- break;
- case eioSTRING:
- {
- char *cptr;
- int slen;
- if (item)
- {
- if (!curfio->bRead)
- slen = strlen((char *) item) + 1;
- else
- slen = 0;
- }
- else
- slen = 0;
+ gmx_fio_lock(open_files);
+ ret=open_files->next;
- if (xdr_int(curfio->xdr, &slen) <= 0)
- gmx_fatal(FARGS, "wrong string length %d for string %s"
- " (source %s, line %d)",slen,desc,srcfile,line);
- if (!item && curfio->bRead)
- snew(cptr,slen);
- else
- cptr=(char *)item;
- if (cptr)
- res = xdr_string(curfio->xdr,&cptr,slen);
- else
- res = 1;
- if (!item && curfio->bRead)
- sfree(cptr);
- break;
+#ifdef GMX_THREADS
+ tMPI_Thread_mutex_unlock(&open_file_mutex);
+#endif
+
+ /* check whether there were any to begin with */
+ if (ret==open_files)
+ {
+ /* after this, the open_file pointer should never change */
+ ret=NULL;
}
- default:
- FE();
+ else
+ {
+ gmx_fio_lock(open_files->next);
}
- if ((res == 0) && (curfio->bDebug))
- fprintf(stderr,"Error in xdr I/O %s %s to file %s (source %s, line %d)\n",
- eioNames[eio],desc,curfio->fn,srcfile,line);
+ gmx_fio_unlock(open_files);
-#ifdef GMX_THREADS
- if (do_lock)
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
- return (res != 0);
+
+ return ret;
}
-static bool do_xdr(void *item, int nitem, int eio, const char *desc,
- const char *srcfile, int line)
+/* get the next open file, or NULL if there is none.
+ Unlocks the previous fio and locks the next one. */
+static t_fileio *gmx_fio_get_next(t_fileio *fio)
{
- /* this is a recursive function that does mutex locking, so
- it needs to be called with locking here, but without locking
- from itself */
- return do_xdr_lock(item, nitem, eio, desc, srcfile, line, TRUE);
+ t_fileio *ret;
+
+ ret=fio->next;
+ /* check if that was the last one */
+ if (fio->next==open_files)
+ {
+ ret=NULL;
+ }
+ else
+ {
+ gmx_fio_lock(ret);
+ }
+ gmx_fio_unlock(fio);
+
+ return ret;
}
-#endif
-#define gmx_fio_check(fio) range_check(fio,0,nFIO)
+
+
/*****************************************************************
*
* EXPORTED SECTION
*
*****************************************************************/
-int gmx_fio_open(const char *fn, const char *mode)
+t_fileio *gmx_fio_open(const char *fn, const char *mode)
{
t_fileio *fio = NULL;
- int i, nfio = 0;
+ int i;
char newmode[5];
bool bRead, bReadWrite;
int xdrid;
}
else
{
+ /* sanitize the mode string */
if (strncmp(mode, "r+", 2) == 0)
{
strcpy(newmode, "r+");
}
}
+ snew(fio, 1);
#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
+ tMPI_Spinlock_init(&(fio->mtx));
#endif
- /* Determine whether we have to make a new one */
- for(i=0; (i<nFIO); i++)
- {
- if (!FIO[i].bOpen)
- {
- fio = &(FIO[i]);
- nfio = i;
- break;
- }
- }
-
- if (i == nFIO)
- {
- nFIO++;
- srenew(FIO,nFIO);
- fio = &(FIO[nFIO-1]);
- nfio = nFIO-1;
- }
-
bRead = (newmode[0]=='r' && newmode[1]!='+');
bReadWrite = (newmode[1]=='+');
fio->fp = NULL;
{
#ifndef GMX_FAHCORE
/* only make backups for normal gromacs */
- if (gmx_fexist(fn))
- {
- char *bf=(char *)backup_fn(fn);
- if (rename(fn,bf) == 0)
- {
- fprintf(stderr,
- "\nBack Off! I just backed up %s to %s\n",
- fn,bf);
- }
- else
- {
- fprintf(stderr,"Sorry, I couldn't backup %s to %s\n",
- fn,bf);
- }
- sfree(bf);
- }
+ make_backup(fn);
#endif
}
else
gmx_open(fn);
}
}
- snew(fio->xdr,1);
- xdrid = xdropen(fio->xdr,fn,newmode);
- if (xdrid == 0)
+ /* Open the file */
+ fio->fp = ffopen(fn,newmode);
+
+ /* determine the XDR direction */
+ if (newmode[0] == 'w' || newmode[0]=='a')
{
- if(newmode[0]=='r' && newmode[1]!='+')
- gmx_fatal(FARGS,"Cannot open file %s for reading\nCheck permissions if it exists.",fn);
- else
- gmx_fatal(FARGS,"Cannot open file %s for writing.\nCheck your permissions, disk space and/or quota.",fn);
+ fio->xdrmode=XDR_ENCODE;
}
- fio->fp = xdr_get_fp(xdrid);
+ else
+ {
+ fio->xdrmode=XDR_DECODE;
+ }
+
+ snew(fio->xdr,1);
+ xdrstdio_create(fio->xdr, fio->fp, fio->xdrmode);
}
else
{
fio->bOpen = TRUE;
fio->bLargerThan_off_t = FALSE;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
- return nfio;
+ /* set the reader/writer functions */
+ gmx_fio_set_iotype(fio);
+
+ /* and now insert this file into the list of open files. */
+ gmx_fio_insert(fio);
+ return fio;
}
-/* this function may be called from a function that locks the fio_mutex,
- which is why it exists in the first place. */
-static int gmx_fio_close_lock(int fio, bool do_lock)
+int gmx_fio_close(t_fileio *fio)
{
int rc = 0;
-#ifdef GMX_THREADS
- if (do_lock)
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
+ gmx_fio_lock(fio);
+ /* first remove it from the list */
+ gmx_fio_remove(fio);
- if (in_ftpset(FIO[fio].iFTP, asize(ftpXDR), ftpXDR))
+ if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
{
- rc = !xdrclose(FIO[fio].xdr); /* xdrclose returns 1 if happy,
- negate it */
- sfree(FIO[fio].xdr);
- }
- else
- {
- /* Don't close stdin and stdout! */
- if (!FIO[fio].bStdio && FIO[fio].fp!=NULL)
- rc = ffclose(FIO[fio].fp); /* fclose returns 0 if happy */
+ xdr_destroy(fio->xdr);
+ sfree(fio->xdr);
}
- sfree(FIO[fio].fn);
- FIO[fio].bOpen = FALSE;
- do_read = do_dummy;
- do_write = do_dummy;
-#ifdef GMX_THREADS
- if (do_lock)
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ /* Don't close stdin and stdout! */
+ if (!fio->bStdio && fio->fp!=NULL)
+ rc = ffclose(fio->fp); /* fclose returns 0 if happy */
- return rc;
-}
+ fio->bOpen = FALSE;
-int gmx_fio_close(int fio)
-{
- return gmx_fio_close_lock(fio, TRUE);
+ gmx_fio_unlock(fio);
+
+ sfree(fio);
+
+ return rc;
}
/* close only fp but keep FIO entry. */
-int gmx_fio_fp_close(int fio)
+int gmx_fio_fp_close(t_fileio *fio)
{
int rc=0;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- if (!in_ftpset(FIO[fio].iFTP,asize(ftpXDR),ftpXDR) && !FIO[fio].bStdio)
+ gmx_fio_lock(fio);
+ if (!in_ftpset(fio->iFTP,asize(ftpXDR),ftpXDR) && !fio->bStdio)
{
- rc = ffclose(FIO[fio].fp); /* fclose returns 0 if happy */
- FIO[fio].fp = NULL;
+ rc = ffclose(fio->fp); /* fclose returns 0 if happy */
+ fio->fp = NULL;
}
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ gmx_fio_unlock(fio);
+
return rc;
}
FILE * gmx_fio_fopen(const char *fn, const char *mode)
{
FILE *fp, *ret;
- int fd;
+ t_fileio *fio;
+
+ fio = gmx_fio_open(fn, mode);
+ gmx_fio_lock(fio);
+ ret = fio->fp;
+ gmx_fio_unlock(fio);
- fd = gmx_fio_open(fn, mode);
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- ret = FIO[fd].fp;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
return ret;
}
int gmx_fio_fclose(FILE *fp)
{
- int i, rc, found;
-
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- found = 0;
- rc = -1;
+ t_fileio *cur;
+ t_fileio *found=NULL;
- for (i = 0; i < nFIO && !found; i++)
+ cur=gmx_fio_get_first();
+ while(cur)
{
- if (fp == FIO[i].fp)
+ if (cur->fp == fp)
{
- rc = gmx_fio_close_lock(i, FALSE);
- found = 1;
+ gmx_fio_unlock(cur);
+ found=cur;
+ /* we let it loop until the end */
}
+ cur=gmx_fio_get_next(cur);
}
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
- return rc;
+
+ if (!found)
+ return -1;
+ return gmx_fio_close(found);
}
-/*
- * fio: file to computer md5 from
- * offset: starting pointer of region to use for md5
- * digest: return array of md5 sum
- * do_lock: whether to lock the fio array
- *
- * this function may be called from a function that locks the fio_mutex,
- which is why it exists in the first place.
- */
-int gmx_fio_get_file_md5_lock(int fio, off_t offset, unsigned char digest[],
- bool do_lock)
+/* internal variant of get_file_md5 that operates on a locked file */
+static int gmx_fio_int_get_file_md5(t_fileio *fio, off_t offset,
+ unsigned char digest[])
{
/*1MB: large size important to catch almost identical files */
#define CPT_CHK_LEN 1048576
-
md5_state_t state;
unsigned char buf[CPT_CHK_LEN];
off_t read_len;
off_t seek_offset;
int ret = -1;
- seek_offset = offset - CPT_CHK_LEN;
+ seek_offset = offset - CPT_CHK_LEN;
if (seek_offset < 0)
{
seek_offset = 0;
}
read_len = offset - seek_offset;
-#ifdef GMX_THREADS
- if (do_lock)
- {
- tMPI_Thread_mutex_lock(&fio_mutex);
- }
-#endif
- gmx_fio_check(fio);
- if (FIO[fio].fp && FIO[fio].bReadWrite)
+ if (fio->fp && fio->bReadWrite)
{
#ifdef HAVE_FSEEKO
- ret = fseeko(FIO[fio].fp, seek_offset, SEEK_SET);
+ ret = fseeko(fio->fp, seek_offset, SEEK_SET);
#else
- ret=fseek(FIO[fio].fp,seek_offset,SEEK_SET);
+ ret=fseek(fio->fp,seek_offset,SEEK_SET);
#endif
if (ret)
{
- fseek(FIO[fio].fp, 0, SEEK_END);
+ fseek(fio->fp, 0, SEEK_END);
}
}
if (ret) /*either no fp, not readwrite, or fseek not successful */
{
-#ifdef GMX_THREADS
- if (do_lock)
- {
- tMPI_Thread_mutex_unlock(&fio_mutex);
- }
-#endif
return -1;
}
/* the read puts the file position back to offset */
- if (fread(buf, 1, read_len, FIO[fio].fp) != read_len)
+ if (fread(buf, 1, read_len, fio->fp) != read_len)
{
/* not fatal: md5sum check to prevent overwriting files
* works (less safe) without
* */
- if (ferror(FIO[fio].fp))
+ if (ferror(fio->fp))
{
- fprintf(stderr, "\nTrying to get md5sum: %s: %s\n", FIO[fio].fn,
+ fprintf(stderr, "\nTrying to get md5sum: %s: %s\n", fio->fn,
strerror(errno));
}
- else if (feof(FIO[fio].fp))
+ else if (feof(fio->fp))
{
- fprintf(stderr, "\nTrying to get md5sum: EOF: %s\n", FIO[fio].fn);
+ fprintf(stderr, "\nTrying to get md5sum: EOF: %s\n", fio->fn);
}
else
{
fprintf(
stderr,
"\nTrying to get md5sum: Unknown reason for short read: %s\n",
- FIO[fio].fn);
+ fio->fn);
}
- fseek(FIO[fio].fp, 0, SEEK_END);
+ fseek(fio->fp, 0, SEEK_END);
ret = -1;
}
- fseek(FIO[fio].fp, 0, SEEK_END); /*is already at end, but under windows
+ fseek(fio->fp, 0, SEEK_END); /*is already at end, but under windows
it gives problems otherwise*/
if (debug)
{
- fprintf(debug, "chksum %s readlen %ld\n", FIO[fio].fn,
- (long int) read_len);
+ fprintf(debug, "chksum %s readlen %ld\n", fio->fn, (long int)read_len);
}
-#ifdef GMX_THREADS
- if (do_lock)
- {
- tMPI_Thread_mutex_unlock(&fio_mutex);
- }
-#endif
if (!ret)
{
}
}
+
/*
- * fio: file to computer md5 from
+ * fio: file to compute md5 for
* offset: starting pointer of region to use for md5
* digest: return array of md5 sum
*/
-int gmx_fio_get_file_md5(int fio, off_t offset, unsigned char digest[])
+int gmx_fio_get_file_md5(t_fileio *fio, off_t offset, unsigned char digest[])
{
- return gmx_fio_get_file_md5_lock(fio, offset, digest, TRUE);
+ int ret;
+
+ gmx_fio_lock(fio);
+ ret=gmx_fio_int_get_file_md5(fio, offset, digest);
+ gmx_fio_unlock(fio);
+
+ return ret;
}
/* The fio_mutex should ALWAYS be locked when this function is called */
-static int gmx_fio_get_file_position(int fio, off_t *offset)
+static int gmx_fio_int_get_file_position(t_fileio *fio, off_t *offset)
{
char buf[STRLEN];
/* Flush the file, so we are sure it is written */
- if (gmx_fio_flush_lock(fio, FALSE))
+ if (gmx_fio_int_flush(fio))
{
char buf[STRLEN];
sprintf(
buf,
"Cannot write file '%s'; maybe you are out of disk space or quota?",
- FIO[fio].fn);
+ fio->fn);
gmx_file(buf);
}
this when exabyte-size output files are common...
*/
#ifdef HAVE_FSEEKO
- *offset = ftello(FIO[fio].fp);
+ *offset = ftello(fio->fp);
#else
- *offset = ftell(FIO[fio].fp);
+ *offset = ftell(fio->fp);
#endif
return 0;
}
-int gmx_fio_check_file_position(int fio)
+int gmx_fio_check_file_position(t_fileio *fio)
{
/* If off_t is 4 bytes we can not store file offset > 2 GB.
* If we do not have ftello, we will play it safe.
#if (SIZEOF_OFF_T == 4 || !defined HAVE_FSEEKO)
off_t offset;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_get_file_position(fio,&offset);
+ gmx_fio_lock(fio);
+ gmx_fio_int_get_file_position(fio,&offset);
/* We have a 4 byte offset,
* make sure that we will detect out of range for all possible cases.
*/
if (offset < 0 || offset > 2147483647)
{
- FIO[fio].bLargerThan_off_t = TRUE;
+ fio->bLargerThan_off_t = TRUE;
}
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ gmx_fio_unlock(fio);
#endif
return 0;
long pos;
gmx_file_position_t * outputfiles;
char buf[STRLEN];
+ t_fileio *cur;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
nfiles = 0;
+ /* pre-allocate 100 files */
nalloc = 100;
snew(outputfiles,nalloc);
- for (i = 0; i < nFIO; i++)
+ cur=gmx_fio_get_first();
+ while(cur)
{
- /* Skip the checkpoint files themselves, since they could be open when we call this routine... */
+ /* Skip the checkpoint files themselves, since they could be open when
+ we call this routine... */
/* also skip debug files (shoud be the only iFTP==efNR) */
- if (FIO[i].bOpen && !FIO[i].bRead && !FIO[i].bStdio && FIO[i].iFTP
- != efCPT && FIO[i].iFTP != efNR)
+ if (cur->bOpen &&
+ !cur->bRead &&
+ !cur->bStdio &&
+ cur->iFTP != efCPT &&
+ cur->iFTP != efNR)
{
int ret;
/* This is an output file currently open for writing, add it */
srenew(outputfiles,nalloc);
}
- strncpy(outputfiles[nfiles].filename, FIO[i].fn, STRLEN - 1);
+ strncpy(outputfiles[nfiles].filename, cur->fn, STRLEN - 1);
/* Get the file position */
- if (FIO[i].bLargerThan_off_t)
+ if (cur->bLargerThan_off_t)
{
/* -1 signals out of range */
outputfiles[nfiles].offset = -1;
}
else
{
- gmx_fio_get_file_position(i, &outputfiles[nfiles].offset);
+ gmx_fio_int_get_file_position(cur, &outputfiles[nfiles].offset);
#ifndef GMX_FAHCORE
outputfiles[nfiles].chksum_size
- = gmx_fio_get_file_md5_lock(i, outputfiles[nfiles].offset,
- outputfiles[nfiles].chksum,
- FALSE);
+ = gmx_fio_int_get_file_md5(cur,
+ outputfiles[nfiles].offset,
+ outputfiles[nfiles].chksum);
#endif
}
nfiles++;
}
+
+ cur=gmx_fio_get_next(cur);
}
*p_nfiles = nfiles;
*p_outputfiles = outputfiles;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
return 0;
}
-void gmx_fio_select(int fio)
-{
-#ifdef DEBUG
- fprintf(stderr,"Select fio called with type %d for file %s\n",
- FIO[fio].iFTP,FIO[fio].fn);
-#endif
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- if (in_ftpset(FIO[fio].iFTP, asize(ftpXDR), ftpXDR))
+void gmx_fio_checktype(t_fileio *fio)
+{
+ if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
{
-#ifdef USE_XDR
- do_read = do_xdr;
- do_write = do_xdr;
-#else
- gmx_fatal(FARGS,"Sorry, no XDR");
-#endif
+ return;
}
- else if (in_ftpset(FIO[fio].iFTP, asize(ftpASC), ftpASC))
+ else if (in_ftpset(fio->iFTP, asize(ftpASC), ftpASC))
{
- do_read = do_ascread;
- do_write = do_ascwrite;
+ return;
}
- else if (in_ftpset(FIO[fio].iFTP, asize(ftpBIN), ftpBIN))
+ else if (in_ftpset(fio->iFTP, asize(ftpBIN), ftpBIN))
{
- do_read = do_binread;
- do_write = do_binwrite;
+ return;
}
#ifdef HAVE_XMl
- else if (in_ftpset(FIO[fio].iFTP,asize(ftpXML),ftpXML))
+ else if (in_ftpset(fio->iFTP,asize(ftpXML),ftpXML))
{
- do_read = do_dummy;
- do_write = do_dummy;
+ return;
}
#endif
else
gmx_fatal(FARGS, "Can not read/write topologies to file type %s",
- ftp2ext(curfio->iFTP));
+ ftp2ext(fio->iFTP));
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
- curfio = &(FIO[fio]);
}
-void gmx_fio_setprecision(int fio, bool bDouble)
+
+void gmx_fio_setprecision(t_fileio *fio, bool bDouble)
{
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- FIO[fio].bDouble = bDouble;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ gmx_fio_lock(fio);
+ fio->bDouble = bDouble;
+ gmx_fio_unlock(fio);
}
-bool gmx_fio_getdebug(int fio)
+bool gmx_fio_getdebug(t_fileio *fio)
{
bool ret;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- ret = FIO[fio].bDebug;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
- return FIO[fio].bDebug;
+
+ gmx_fio_lock(fio);
+ ret = fio->bDebug;
+ gmx_fio_unlock(fio);
+
+ return ret;
}
-void gmx_fio_setdebug(int fio, bool bDebug)
+void gmx_fio_setdebug(t_fileio *fio, bool bDebug)
{
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- FIO[fio].bDebug = bDebug;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ gmx_fio_lock(fio);
+ fio->bDebug = bDebug;
+ gmx_fio_unlock(fio);
}
-char *gmx_fio_getname(int fio)
+char *gmx_fio_getname(t_fileio *fio)
{
char *ret;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- ret = curfio->fn;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ gmx_fio_lock(fio);
+ ret = fio->fn;
+ gmx_fio_unlock(fio);
+
return ret;
}
-void gmx_fio_setftp(int fio, int ftp)
+int gmx_fio_getftp(t_fileio* fio)
{
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- FIO[fio].iFTP = ftp;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ int ret;
+
+ gmx_fio_lock(fio);
+ ret = fio->iFTP;
+ gmx_fio_unlock(fio);
+
+ return ret;
}
-int gmx_fio_getftp(int fio)
+void gmx_fio_rewind(t_fileio* fio)
+{
+ gmx_fio_lock(fio);
+
+ if (fio->xdr)
+ {
+ xdr_destroy(fio->xdr);
+ frewind(fio->fp);
+ xdrstdio_create(fio->xdr, fio->fp, fio->xdrmode);
+ }
+ else
+ {
+ frewind(fio->fp);
+ }
+ gmx_fio_unlock(fio);
+}
+
+
+int gmx_fio_flush(t_fileio* fio)
{
int ret;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- ret = FIO[fio].iFTP;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+
+ gmx_fio_lock(fio);
+ ret=gmx_fio_int_flush(fio);
+ gmx_fio_unlock(fio);
+
return ret;
}
-void gmx_fio_rewind(int fio)
+
+
+static int gmx_fio_int_fsync(t_fileio *fio)
{
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
+ int rc = 0;
+ int filen=-1;
+
+#if ( ( (defined(HAVE_FILENO) || (defined(HAVE__FILENO) ) ) && \
+ (defined(HAVE_FSYNC)) || defined(HAVE__COMMIT) ) || \
+ defined(FAHCORE) )
+ if (fio->fp)
+ {
+#ifdef GMX_FAHCORE
+ /* the fahcore defines its own os-independent fsync */
+ rc=fah_fsync(fio->fp);
+#elif defined(HAVE_FILENO)
+ filen=fileno(fio->fp);
+#elif defined(HAVE__FILENO)
+ filen=_fileno(fio->fp);
#endif
- gmx_fio_check(fio);
- if (FIO[fio].xdr)
+ }
+ else if (fio->xdr)
{
- xdrclose(FIO[fio].xdr);
- /* File is always opened as binary by xdropen */
- xdropen(FIO[fio].xdr, FIO[fio].fn, FIO[fio].bRead ? "r" : "w");
+#ifdef GMX_FAHCORE
+ /* the fahcore defines its own os-independent fsync */
+ rc=fah_fsync((FILE *) fio->xdr->x_private);
+#elif defined(HAVE_FILENO)
+ filen=fileno((FILE *) fio->xdr->x_private);
+#elif defined(HAVE__FILENO)
+ filen=_fileno((FILE *) fio->xdr->x_private);
+#endif
}
- else
- frewind(FIO[fio].fp);
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
+
+#ifndef GMX_FAHCORE
+ if (filen>0)
+ {
+#if (defined(HAVE_FSYNC))
+ /* fahcore also defines HAVE_FSYNC */
+ rc=fsync(filen);
+#elif (defined(HAVE__COMMIT))
+ rc=_commit(filen);
#endif
+ }
+#endif
+
+ /* We check for these error codes this way because POSIX requires them
+ to be defined, and using anything other than macros is unlikely: */
+#ifdef EINTR
+ /* we don't want to report an error just because fsync() caught a signal.
+ For our purposes, we can just ignore this. */
+ if (rc && errno==EINTR)
+ rc=0;
+#endif
+#ifdef EINVAL
+ /* we don't want to report an error just because we tried to fsync()
+ stdout, a socket or a pipe. */
+ if (rc && errno==EINVAL)
+ rc=0;
+#endif
+#endif
+
+ return rc;
}
-static int gmx_fio_flush_lock(int fio, bool do_lock)
+
+int gmx_fio_fsync(t_fileio *fio)
{
- int rc = 0;
+ int rc;
-#ifdef GMX_THREADS
- if (do_lock)
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- if (FIO[fio].fp)
- rc = fflush(FIO[fio].fp);
- else if (FIO[fio].xdr)
- rc = fflush((FILE *) FIO[fio].xdr->x_private);
-#ifdef GMX_THREADS
- if (do_lock)
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ gmx_fio_lock(fio);
+ rc=gmx_fio_int_fsync(fio);
+ gmx_fio_unlock(fio);
return rc;
}
-int gmx_fio_flush(int fio)
+
+
+t_fileio *gmx_fio_all_output_fsync(void)
{
- return gmx_fio_flush_lock(fio, TRUE);
+ t_fileio *ret=NULL;
+ t_fileio *cur;
+
+ cur=gmx_fio_get_first();
+ while(cur)
+ {
+ /* skip debug files (shoud be the only iFTP==efNR) */
+ if (cur->bOpen &&
+ !cur->bRead &&
+ !cur->bStdio &&
+ cur->iFTP != efNR)
+ {
+ /* if any of them fails, return failure code */
+ int rc=gmx_fio_int_fsync(cur);
+ if (rc != 0 && !ret)
+ {
+ ret=cur;
+ }
+ }
+ cur=gmx_fio_get_next(cur);
+ }
+
+ /* in addition, we force these to be written out too, if they're being
+ redirected. We don't check for errors because errors most likely mean
+ that they're not redirected. */
+ fflush(stdout);
+ fflush(stderr);
+#if (defined(HAVE_FSYNC))
+ /* again, fahcore defines HAVE_FSYNC and fsync() */
+ fsync(STDOUT_FILENO);
+ fsync(STDERR_FILENO);
+#endif
+
+ return ret;
}
-off_t gmx_fio_ftell(int fio)
+
+off_t gmx_fio_ftell(t_fileio* fio)
{
off_t ret = 0;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- if (FIO[fio].fp)
- ret = ftell(FIO[fio].fp);
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+
+ gmx_fio_lock(fio);
+ if (fio->fp)
+ ret = ftell(fio->fp);
+ gmx_fio_unlock(fio);
return ret;
}
-int gmx_fio_seek(int fio, off_t fpos)
+int gmx_fio_seek(t_fileio* fio, off_t fpos)
{
int rc;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- if (FIO[fio].fp)
+
+ gmx_fio_lock(fio);
+ if (fio->fp)
{
#ifdef HAVE_FSEEKO
- rc = fseeko(FIO[fio].fp, fpos, SEEK_SET);
+ rc = fseeko(fio->fp, fpos, SEEK_SET);
#else
- rc = fseek(FIO[fio].fp,fpos,SEEK_SET);
+ rc = fseek(fio->fp,fpos,SEEK_SET);
#endif
}
else
{
- gmx_file(FIO[fio].fn);
+ gmx_file(fio->fn);
rc = -1;
}
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ gmx_fio_unlock(fio);
return rc;
}
-FILE *gmx_fio_getfp(int fio)
+FILE *gmx_fio_getfp(t_fileio *fio)
{
FILE *ret = NULL;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- if (FIO[fio].fp)
- ret = FIO[fio].fp;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+
+ gmx_fio_lock(fio);
+ if (fio->fp)
+ ret = fio->fp;
+ gmx_fio_unlock(fio);
return ret;
}
-XDR *gmx_fio_getxdr(int fio)
+XDR *gmx_fio_getxdr(t_fileio* fio)
{
XDR *ret = NULL;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- if (FIO[fio].xdr)
- ret = FIO[fio].xdr;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+ gmx_fio_lock(fio);
+ if (fio->xdr)
+ ret = fio->xdr;
+ gmx_fio_unlock(fio);
+
return ret;
}
-bool gmx_fio_getread(int fio)
+bool gmx_fio_getread(t_fileio* fio)
{
bool ret;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
- gmx_fio_check(fio);
- ret = FIO[fio].bRead;
-#ifdef GMX_THREADS
- tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+
+ gmx_fio_lock(fio);
+ ret = fio->bRead;
+ gmx_fio_unlock(fio);
+
return ret;
}
-int xtc_seek_frame(int frame, int fio, int natoms)
+int xtc_seek_frame(t_fileio *fio, int frame, int natoms)
{
- return xdr_xtc_seek_frame(frame, FIO[fio].fp, FIO[fio].xdr, natoms);
+ int ret;
+
+ gmx_fio_lock(fio);
+ ret=xdr_xtc_seek_frame(frame, fio->fp, fio->xdr, natoms);
+ gmx_fio_unlock(fio);
+
+ return ret;
}
-int xtc_seek_time(real time, int fio, int natoms)
+int xtc_seek_time(t_fileio *fio, real time, int natoms)
{
- return xdr_xtc_seek_time(time, FIO[fio].fp, FIO[fio].xdr, natoms);
+ int ret;
+
+ gmx_fio_lock(fio);
+ ret=xdr_xtc_seek_time(time, fio->fp, fio->xdr, natoms);
+ gmx_fio_unlock(fio);
+
+ return ret;
}
+
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "filenm.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "md5.h"
+
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+#include "gmxfio_int.h"
+
+
+/* This is the part that reads dummy and ascii files. */
+
+
+
+
+/* file type functions */
+static bool do_ascread(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line);
+static bool do_ascwrite(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line);
+static bool do_dummyread(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line);
+static bool do_dummywrite(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line);
+
+
+const t_iotype asc_iotype={do_ascread, do_ascwrite};
+const t_iotype dummy_iotype={do_dummyread, do_dummywrite};
+
+
+
+
+
+
+static bool do_dummyread(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ gmx_fatal(FARGS, "File type not set!");
+ return FALSE;
+}
+
+static bool do_dummywrite(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ gmx_fatal(FARGS, "File type not set!");
+ return FALSE;
+}
+
+
+
+static void encode_string(int maxlen, char dst[], const char src[])
+{
+ int i;
+
+ for (i = 0; (src[i] != '\0') && (i < maxlen - 1); i++)
+ if ((src[i] == ' ') || (src[i] == '\t'))
+ dst[i] = '_';
+ else
+ dst[i] = src[i];
+ dst[i] = '\0';
+
+ if (i == maxlen)
+ fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
+}
+
+static void decode_string(int maxlen, char dst[], const char src[])
+{
+ int i;
+
+ for (i = 0; (src[i] != '\0') && (i < maxlen - 1); i++)
+ {
+ if (src[i] == '_')
+ {
+ dst[i] = ' ';
+ }
+ else
+ {
+ dst[i] = src[i];
+ }
+ }
+ dst[i] = '\0';
+
+ if (i == maxlen)
+ {
+ fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
+ }
+}
+
+static bool do_ascwrite(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ int i;
+ int res = 0, *iptr;
+ real *ptr;
+ char strbuf[256];
+ char buf[GMX_FIO_BUFLEN];
+ unsigned char *ucptr;
+ FILE *fp=fio->fp;
+
+ gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+ switch (eio)
+ {
+ case eioREAL:
+ case eioDOUBLE:
+ res = fprintf(fp, "%18.10e%s\n", *((real *) item),
+ gmx_fio_dbgstr(fio, desc, buf));
+ break;
+ case eioINT:
+ res = fprintf(fp, "%18d%s\n", *((int *) item), gmx_fio_dbgstr(fio,
+ desc,
+ buf));
+ break;
+ case eioGMX_LARGE_INT:
+ sprintf(strbuf, "%s%s%s", "%", gmx_large_int_fmt, "\n");
+ res = fprintf(fp, strbuf, *((gmx_large_int_t *) item),
+ gmx_fio_dbgstr(fio, desc, buf));
+ break;
+ case eioUCHAR:
+ res = fprintf(fp, "%4d%s\n", *((unsigned char *) item),
+ gmx_fio_dbgstr(fio, desc, buf));
+ break;
+ case eioNUCHAR:
+ ucptr = (unsigned char *) item;
+ for (i = 0; (i < nitem); i++)
+ res = fprintf(fp, "%4d", (int) ucptr[i]);
+ fprintf(fio->fp, "%s\n", gmx_fio_dbgstr(fio, desc, buf));
+ break;
+ case eioUSHORT:
+ res = fprintf(fp, "%18d%s\n", *((unsigned short *) item),
+ gmx_fio_dbgstr(fio, desc, buf));
+ break;
+ case eioRVEC:
+ ptr = (real *) item;
+ res = fprintf(fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
+ ptr[YY], ptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
+ break;
+ case eioNRVEC:
+ for (i = 0; (i < nitem); i++)
+ {
+ ptr = ((rvec *) item)[i];
+ res = fprintf(fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
+ ptr[YY], ptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
+ }
+ break;
+ case eioIVEC:
+ iptr = (int *) item;
+ res = fprintf(fp, "%18d%18d%18d%s\n", iptr[XX], iptr[YY],
+ iptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
+ break;
+ case eioSTRING:
+ encode_string(256, strbuf, (char *) item);
+ res = fprintf(fp, "%-18s%s\n", strbuf, gmx_fio_dbgstr(fio, desc, buf));
+ break;
+ default:
+ gmx_fio_fe(fio, eio, desc, srcfile, line);
+ }
+ if ((res <= 0) && fio->bDebug)
+ fprintf(stderr,
+ "Error writing %s %s to file %s (source %s, line %d)\n",
+ eioNames[eio], desc, fio->fn, srcfile, line);
+
+ return (res > 0);
+}
+
+
+static char *next_item(FILE *fp, char *buf, int buflen)
+{
+ int rd;
+ bool in_comment = FALSE;
+ bool in_token = FALSE;
+ int i = 0;
+ /* This routine reads strings from the file fp, strips comment
+ * and buffers. For thread-safety reasons, It reads through getc() */
+
+ rd = getc(fp);
+ if (rd == EOF)
+ gmx_file("End of file");
+ do
+ {
+ if (in_comment)
+ {
+ if (rd == '\n')
+ in_comment = FALSE;
+ }
+ else if (in_token)
+ {
+ if (isspace(rd) || rd == ';')
+ break;
+ buf[i++] = (char) rd;
+ }
+ else
+ {
+ if (!isspace(rd))
+ {
+ if (rd == ';')
+ in_comment = TRUE;
+ else
+ {
+ in_token = TRUE;
+ buf[i++] = (char) (rd);
+ }
+ }
+ }
+ if (i >= buflen - 2)
+ break;
+ } while ((rd = getc(fp)) != EOF);
+
+ fprintf(stderr, "WARNING, ftpASC file type not tested!\n");
+
+ buf[i] = 0;
+
+ return buf;
+}
+
+static bool do_ascread(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ FILE *fp = fio->fp;
+ int i, m, res = 0, *iptr, ix;
+ gmx_large_int_t s;
+ double d, x;
+ real *ptr;
+ unsigned char uc, *ucptr;
+ char *cptr;
+#define NEXT_ITEM_BUF_LEN 128
+ char ni_buf[NEXT_ITEM_BUF_LEN];
+
+ gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+ switch (eio)
+ {
+ case eioREAL:
+ case eioDOUBLE:
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf", &d);
+ if (item)
+ *((real *) item) = d;
+ break;
+ case eioINT:
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
+ if (item)
+ *((int *) item) = i;
+ break;
+ case eioGMX_LARGE_INT:
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN),
+ gmx_large_int_pfmt, &s);
+ if (item)
+ *((gmx_large_int_t *) item) = s;
+ break;
+ case eioUCHAR:
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%c", &uc);
+ if (item)
+ *((unsigned char *) item) = uc;
+ break;
+ case eioNUCHAR:
+ ucptr = (unsigned char *) item;
+ for (i = 0; (i < nitem); i++)
+ {
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &ix);
+ if (item)
+ ucptr[i] = ix;
+ }
+ break;
+ case eioUSHORT:
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
+ if (item)
+ *((unsigned short *) item) = i;
+ break;
+ case eioRVEC:
+ ptr = (real *) item;
+ for (m = 0; (m < DIM); m++)
+ {
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n", &x);
+ ptr[m] = x;
+ }
+ break;
+ case eioNRVEC:
+ for (i = 0; (i < nitem); i++)
+ {
+ ptr = ((rvec *) item)[i];
+ for (m = 0; (m < DIM); m++)
+ {
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n",
+ &x);
+ if (item)
+ ptr[m] = x;
+ }
+ }
+ break;
+ case eioIVEC:
+ iptr = (int *) item;
+ for (m = 0; (m < DIM); m++)
+ {
+ res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d\n", &ix);
+ if (item)
+ iptr[m] = ix;
+ }
+ break;
+ case eioSTRING:
+ cptr = next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN);
+ if (item)
+ {
+ decode_string(strlen(cptr) + 1, (char *) item, cptr);
+ /* res = sscanf(cptr,"%s",(char *)item);*/
+ res = 1;
+ }
+ break;
+ default:
+ gmx_fio_fe(fio, eio, desc, srcfile, line);
+ }
+
+ if ((res <= 0) && fio->bDebug)
+ fprintf(stderr,
+ "Error reading %s %s from file %s (source %s, line %d)\n",
+ eioNames[eio], desc, fio->fn, srcfile, line);
+ return (res > 0);
+}
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "filenm.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "md5.h"
+
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+#include "gmxfio_int.h"
+
+/* This is the part that reads dummy and ascii files. */
+
+
+static bool do_binread(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line);
+static bool do_binwrite(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line);
+
+
+const t_iotype bin_iotype={do_binread, do_binwrite};
+
+
+static bool do_binwrite(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ size_t size = 0, wsize;
+ int ssize;
+
+ gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+ switch (eio)
+ {
+ case eioREAL:
+ size = sizeof(real);
+ break;
+ case eioDOUBLE:
+ size = sizeof(double);
+ break;
+ case eioINT:
+ size = sizeof(int);
+ break;
+ case eioGMX_LARGE_INT:
+ size = sizeof(gmx_large_int_t);
+ break;
+ case eioUCHAR:
+ size = sizeof(unsigned char);
+ break;
+ case eioNUCHAR:
+ size = sizeof(unsigned char);
+ break;
+ case eioUSHORT:
+ size = sizeof(unsigned short);
+ break;
+ case eioRVEC:
+ size = sizeof(rvec);
+ break;
+ case eioNRVEC:
+ size = sizeof(rvec);
+ break;
+ case eioIVEC:
+ size = sizeof(ivec);
+ break;
+ case eioSTRING:
+ size = ssize = strlen((char *) item) + 1;
+ do_binwrite(fio, &ssize, 1, eioINT, desc, srcfile, line);
+ break;
+ default:
+ gmx_fio_fe(fio, eio, desc, srcfile, line);
+ }
+
+ wsize = fwrite(item, size, nitem, fio->fp);
+
+ if ((wsize != nitem) && fio->bDebug)
+ {
+ fprintf(stderr,
+ "Error writing %s %s to file %s (source %s, line %d)\n",
+ eioNames[eio], desc, fio->fn, srcfile, line);
+ fprintf(stderr, "written size %u bytes, source size %u bytes\n",
+ (unsigned int) wsize, (unsigned int) size);
+ }
+ return (wsize == nitem);
+}
+
+static bool do_binread(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ size_t size = 0, rsize;
+ int ssize;
+
+ gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+ switch (eio)
+ {
+ case eioREAL:
+ if (fio->bDouble)
+ size = sizeof(double);
+ else
+ size = sizeof(float);
+ break;
+ case eioDOUBLE:
+ size = sizeof(double);
+ break;
+ case eioINT:
+ size = sizeof(int);
+ break;
+ case eioGMX_LARGE_INT:
+ size = sizeof(gmx_large_int_t);
+ break;
+ case eioUCHAR:
+ size = sizeof(unsigned char);
+ break;
+ case eioNUCHAR:
+ size = sizeof(unsigned char);
+ break;
+ case eioUSHORT:
+ size = sizeof(unsigned short);
+ break;
+ case eioRVEC:
+ case eioNRVEC:
+ if (fio->bDouble)
+ size = sizeof(double) * DIM;
+ else
+ size = sizeof(float) * DIM;
+ break;
+ case eioIVEC:
+ size = sizeof(ivec);
+ break;
+ case eioSTRING:
+ do_binread(fio, &ssize, 1, eioINT, desc, srcfile, line);
+ size = ssize;
+ break;
+ default:
+ gmx_fio_fe(fio, eio, desc, srcfile, line);
+ }
+ if (item)
+ rsize = fread(item, size, nitem, fio->fp);
+ else
+ {
+ /* Skip over it if we have a NULL pointer here */
+#ifdef HAVE_FSEEKO
+ fseeko(fio->fp, (off_t) (size * nitem), SEEK_CUR);
+#else
+ fseek(fio->fp,(size*nitem),SEEK_CUR);
+#endif
+ rsize = nitem;
+ }
+ if ((rsize != nitem) && (fio->bDebug))
+ fprintf(stderr,
+ "Error reading %s %s from file %s (source %s, line %d)\n",
+ eioNames[eio], desc, fio->fn, srcfile, line);
+
+ return (rsize == nitem);
+}
+
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+
+
+
+/* This is the new improved and thread safe version of gmxfio. */
+
+
+/* WARNING WARNING WARNING WARNING
+ The data types used here are PRIVATE to gmxfio routines. DO NOT use them
+ directly in your own code, but use the external functions provided in
+ include/gmxfio.h
+
+ If you don't heed this warning, your code will suddenly stop working
+ at some point in the not-so-distant future.
+
+ WARNING WARNING WARNING WARNING */
+
+
+/* XDR should be available on all platforms now,
+ * but we keep the possibility of turning it off...
+ */
+#define USE_XDR
+
+
+
+/* the reader/writer functions for t_iotype */
+typedef bool read_func(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc,const char *srcfile,int line);
+typedef bool write_func(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc,const char *srcfile,int line);
+
+
+/* these are pointers to the actual reading & writing functions */
+typedef struct
+{
+ read_func *nread;
+ write_func *nwrite;
+} t_iotype;
+
+
+
+struct t_fileio
+{
+ FILE *fp; /* the file pointer */
+ const t_iotype *iotp; /* file type */
+ bool bOpen, /* the file is open */
+ bRead, /* the file is open for reading */
+ bDouble, /* write doubles instead of floats */
+ bDebug, /* the file ops should come with debug info */
+ bStdio, /* the file is actually stdin or stdout */
+ bLargerThan_off_t, /* if the file position is largen than off_t
+ could hold */
+ bReadWrite; /* the file is open for reading and writing */
+ char *fn; /* the file name */
+ XDR *xdr; /* the xdr data pointer */
+ enum xdr_op xdrmode; /* the xdr mode */
+ int iFTP; /* the file type identifier */
+
+ const char *comment; /* a comment string for debugging */
+
+ t_fileio *next, *prev; /* next and previous file pointers in the
+ linked list */
+#ifdef GMX_THREADS
+ tMPI_Spinlock_t mtx; /* content locking mutex. This is a spinlock
+ for performance reasons: in some cases every
+ single byte that gets read/written requires
+ a lock */
+#endif
+};
+
+
+
+extern const t_iotype asc_iotype;
+extern const t_iotype bin_iotype;
+extern const t_iotype xdr_iotype;
+extern const t_iotype dummy_iotype;
+
+extern const char *eioNames[eioNR];
+
+
+
+#define GMX_FIO_BUFLEN 256
+
+/* make a debug string if that is requested in the fio */
+const char *gmx_fio_dbgstr(t_fileio *fio, const char *desc, char *buf);
+/* check the number of items against the allowed number of items */
+void gmx_fio_check_nitem(t_fileio *fio, int eio, int nitem, const char *file,
+ int line);
+/* check the output type against allowed values */
+void gmx_fio_fe(t_fileio *fio, int eio, const char *desc, const char *srcfile,
+ int line);
+
+/* lock/unlock the mutex associated with a fio */
+void gmx_fio_lock(t_fileio *fio);
+void gmx_fio_unlock(t_fileio *fio);
+
+
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "filenm.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "md5.h"
+
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+#include "gmxfio_int.h"
+
+
+/*******************************************************************
+ *
+ * READ/WRITE FUNCTIONS
+ *
+*******************************************************************/
+
+bool gmx_fio_reade_real(t_fileio *fio, real *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioREAL, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_reade_double(t_fileio *fio, double *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioDOUBLE, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_reade_int(t_fileio *fio, int *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioINT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_reade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioGMX_LARGE_INT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_reade_uchar(t_fileio *fio, unsigned char *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioUCHAR, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_reade_ushort(t_fileio *fio, unsigned short *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioUSHORT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_reade_rvec(t_fileio *fio, rvec *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioRVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_reade_ivec(t_fileio *fio, ivec *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioIVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_reade_string(t_fileio *fio, char *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, 1, eioSTRING, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+/* Write */
+
+bool gmx_fio_writee_real(t_fileio *fio, real item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, &item, 1, eioREAL, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_writee_double(t_fileio *fio, double item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, &item, 1, eioDOUBLE, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_writee_int(t_fileio *fio, int item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, &item, 1, eioINT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_writee_gmx_large_int(t_fileio *fio, gmx_large_int_t item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, &item, 1, eioGMX_LARGE_INT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_writee_uchar(t_fileio *fio, unsigned char item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, &item, 1, eioUCHAR, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_writee_ushort(t_fileio *fio, unsigned short item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, &item, 1, eioUSHORT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_writee_rvec(t_fileio *fio, rvec *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, item, 1, eioRVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_writee_ivec(t_fileio *fio, ivec *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, item, 1, eioIVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_writee_string(t_fileio *fio, const char *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, item, 1, eioSTRING, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+/* Read/write functions */
+
+bool gmx_fio_doe_real(t_fileio *fio, real *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioREAL, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioREAL, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_doe_double(t_fileio *fio, double *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioDOUBLE, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioDOUBLE, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_doe_bool(t_fileio *fio, bool *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ int itmp;
+
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ {
+ ret=fio->iotp->nread(fio, &itmp, 1, eioINT, desc, srcfile, line);
+ *item = itmp;
+ }
+ else
+ {
+ itmp = *item;
+ ret=fio->iotp->nwrite(fio, &itmp, 1, eioINT, desc, srcfile, line);
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_doe_int(t_fileio *fio, int *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioINT, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioINT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_doe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioGMX_LARGE_INT, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioGMX_LARGE_INT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_doe_uchar(t_fileio *fio, unsigned char *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioUCHAR, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioUCHAR, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_doe_ushort(t_fileio *fio, unsigned short *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioUSHORT, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioUSHORT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_doe_rvec(t_fileio *fio, rvec *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioRVEC, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioRVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_doe_ivec(t_fileio *fio, ivec *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioIVEC, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioIVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_doe_string(t_fileio *fio, char *item,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ ret=fio->iotp->nread(fio, item, 1, eioSTRING, desc, srcfile, line);
+ else
+ ret=fio->iotp->nwrite(fio, item, 1, eioSTRING, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+
+
+
+
+/* Array reading & writing */
+
+bool gmx_fio_nreade_real(t_fileio *fio, real *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioREAL, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nreade_double(t_fileio *fio, double *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret= ret && fio->iotp->nread(fio, &(item[i]), 1, eioDOUBLE, desc, srcfile,
+ line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nreade_int(t_fileio *fio, int *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioINT, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nreade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioGMX_LARGE_INT, desc,
+ srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_nreade_uchar(t_fileio *fio, unsigned char *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, n, eioNUCHAR, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nreade_ushort(t_fileio *fio, unsigned short *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioUSHORT, desc,
+ srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nreade_rvec(t_fileio *fio, rvec *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nread(fio, item, n, eioNRVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nreade_ivec(t_fileio *fio, ivec *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nread(fio, item[i], 1, eioIVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nreade_string(t_fileio *fio, char *item[], int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nread(fio, item[i], 1, eioSTRING, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+
+/* Array writing */
+
+bool gmx_fio_nwritee_real(t_fileio *fio, const real *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioREAL, desc,
+ srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_nwritee_double(t_fileio *fio, const double *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioDOUBLE, desc,
+ srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_nwritee_int(t_fileio *fio, const int *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioINT, desc, srcfile,
+ line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nwritee_gmx_large_int(t_fileio *fio,
+ const gmx_large_int_t *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioGMX_LARGE_INT,
+ desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nwritee_uchar(t_fileio *fio, const unsigned char *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, item, n, eioNUCHAR, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nwritee_ushort(t_fileio *fio, const unsigned short *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioUSHORT, desc,
+ srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_nwritee_rvec(t_fileio *fio, const rvec *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret;
+ gmx_fio_lock(fio);
+ ret=fio->iotp->nwrite(fio, item, n, eioNRVEC, desc, srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_nwritee_ivec(t_fileio *fio, const ivec *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioIVEC, desc,
+ srcfile, line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+bool gmx_fio_nwritee_string(t_fileio *fio, const char *item[], int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioSTRING, desc, srcfile,
+ line);
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+/* array read/write functions */
+
+bool gmx_fio_ndoe_real(t_fileio *fio, real *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ {
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioREAL, desc,
+ srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioREAL, desc,
+ srcfile, line);
+ }
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+bool gmx_fio_ndoe_double(t_fileio *fio, double *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ {
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioDOUBLE, desc,
+ srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioDOUBLE, desc,
+ srcfile, line);
+ }
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+bool gmx_fio_ndoe_bool(t_fileio *fio, bool *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i,itmp;
+
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ {
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, &itmp, 1, eioINT, desc,
+ srcfile, line);
+ item[i] = itmp;
+ }
+ else
+ {
+ itmp = item[i];
+ ret=ret && fio->iotp->nwrite(fio, &itmp, 1, eioINT, desc,
+ srcfile, line);
+ }
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+bool gmx_fio_ndoe_int(t_fileio *fio, int *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ {
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioINT, desc,
+ srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioINT, desc,
+ srcfile, line);
+ }
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+bool gmx_fio_ndoe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ {
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioGMX_LARGE_INT, desc,
+ srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioGMX_LARGE_INT, desc,
+ srcfile, line);
+ }
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+bool gmx_fio_ndoe_uchar(t_fileio *fio, unsigned char *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, item, n, eioNUCHAR, desc,
+ srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, item, n, eioNUCHAR, desc,
+ srcfile, line);
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+bool gmx_fio_ndoe_ushort(t_fileio *fio, unsigned short *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ {
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioUSHORT, desc,
+ srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioUSHORT, desc,
+ srcfile, line);
+ }
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+bool gmx_fio_ndoe_rvec(t_fileio *fio, rvec *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ gmx_fio_lock(fio);
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, item, n, eioNRVEC, desc, srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, item, n, eioNRVEC, desc, srcfile,
+ line);
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+bool gmx_fio_ndoe_ivec(t_fileio *fio, ivec *item, int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ {
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioIVEC, desc,
+ srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioIVEC, desc,
+ srcfile, line);
+ }
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+bool gmx_fio_ndoe_string(t_fileio *fio, char *item[], int n,
+ const char *desc, const char *srcfile, int line)
+{
+ bool ret=TRUE;
+ int i;
+ gmx_fio_lock(fio);
+ for(i=0;i<n;i++)
+ {
+ if (fio->bRead)
+ {
+ ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioSTRING, desc,
+ srcfile, line);
+ }
+ else
+ {
+ ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioSTRING, desc,
+ srcfile, line);
+ }
+ }
+ gmx_fio_unlock(fio);
+ return ret;
+}
+
+
+
+
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "filenm.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "md5.h"
+
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+#include "gmxfio_int.h"
+
+/* This is the part that reads xdr files. */
+
+
+/* file type functions */
+static bool do_xdrread(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line);
+static bool do_xdrwrite(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line);
+
+
+const t_iotype xdr_iotype={do_xdrread, do_xdrwrite};
+
+
+#ifdef USE_XDR
+
+static bool do_xdr(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ unsigned char ucdum, *ucptr;
+ bool_t res = 0;
+ float fvec[DIM];
+ double dvec[DIM];
+ int j, m, *iptr, idum;
+ gmx_large_int_t sdum;
+ real *ptr;
+ unsigned short us;
+ double d = 0;
+ float f = 0;
+
+ gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+ switch (eio)
+ {
+ case eioREAL:
+ if (fio->bDouble)
+ {
+ if (item && !fio->bRead)
+ d = *((real *) item);
+ res = xdr_double(fio->xdr, &d);
+ if (item)
+ *((real *) item) = d;
+ }
+ else
+ {
+ if (item && !fio->bRead)
+ f = *((real *) item);
+ res = xdr_float(fio->xdr, &f);
+ if (item)
+ *((real *) item) = f;
+ }
+ break;
+ case eioDOUBLE:
+ if (item && !fio->bRead)
+ d = *((double *) item);
+ res = xdr_double(fio->xdr, &d);
+ if (item)
+ *((double *) item) = d;
+ break;
+ case eioINT:
+ if (item && !fio->bRead)
+ idum = *(int *) item;
+ res = xdr_int(fio->xdr, &idum);
+ if (item)
+ *(int *) item = idum;
+ break;
+ case eioGMX_LARGE_INT:
+ /* do_xdr will not generate a warning when a 64bit gmx_large_int_t
+ * value that is out of 32bit range is read into a 32bit gmx_large_int_t.
+ */
+ if (item && !fio->bRead)
+ sdum = *(gmx_large_int_t *) item;
+ res = xdr_gmx_large_int(fio->xdr, &sdum, NULL);
+ if (item)
+ *(gmx_large_int_t *) item = sdum;
+ break;
+ case eioUCHAR:
+ if (item && !fio->bRead)
+ ucdum = *(unsigned char *) item;
+ res = xdr_u_char(fio->xdr, &ucdum);
+ if (item)
+ *(unsigned char *) item = ucdum;
+ break;
+ case eioNUCHAR:
+ ucptr = (unsigned char *) item;
+ res = 1;
+ for (j = 0; (j < nitem) && res; j++)
+ {
+ res = xdr_u_char(fio->xdr, &(ucptr[j]));
+ }
+ break;
+ case eioUSHORT:
+ if (item && !fio->bRead)
+ us = *(unsigned short *) item;
+ res = xdr_u_short(fio->xdr, (unsigned short *) &us);
+ if (item)
+ *(unsigned short *) item = us;
+ break;
+ case eioRVEC:
+ if (fio->bDouble)
+ {
+ if (item && !fio->bRead)
+ for (m = 0; (m < DIM); m++)
+ dvec[m] = ((real *) item)[m];
+ res = xdr_vector(fio->xdr, (char *) dvec, DIM,
+ (unsigned int) sizeof(double),
+ (xdrproc_t) xdr_double);
+ if (item)
+ for (m = 0; (m < DIM); m++)
+ ((real *) item)[m] = dvec[m];
+ }
+ else
+ {
+ if (item && !fio->bRead)
+ for (m = 0; (m < DIM); m++)
+ fvec[m] = ((real *) item)[m];
+ res = xdr_vector(fio->xdr, (char *) fvec, DIM,
+ (unsigned int) sizeof(float),
+ (xdrproc_t) xdr_float);
+ if (item)
+ for (m = 0; (m < DIM); m++)
+ ((real *) item)[m] = fvec[m];
+ }
+ break;
+ case eioNRVEC:
+ ptr = NULL;
+ res = 1;
+ for (j = 0; (j < nitem) && res; j++)
+ {
+ if (item)
+ ptr = ((rvec *) item)[j];
+ res = do_xdr(fio, ptr, 1, eioRVEC, desc, srcfile, line);
+ }
+ break;
+ case eioIVEC:
+ iptr = (int *) item;
+ res = 1;
+ for (m = 0; (m < DIM) && res; m++)
+ {
+ if (item && !fio->bRead)
+ idum = iptr[m];
+ res = xdr_int(fio->xdr, &idum);
+ if (item)
+ iptr[m] = idum;
+ }
+ break;
+ case eioSTRING:
+ {
+ char *cptr;
+ int slen;
+
+ if (item)
+ {
+ if (!fio->bRead)
+ slen = strlen((char *) item) + 1;
+ else
+ slen = 0;
+ }
+ else
+ slen = 0;
+
+ if (xdr_int(fio->xdr, &slen) <= 0)
+ gmx_fatal(FARGS, "wrong string length %d for string %s"
+ " (source %s, line %d)",slen,desc,srcfile,line);
+ if (!item && fio->bRead)
+ snew(cptr,slen);
+ else
+ cptr=(char *)item;
+ if (cptr)
+ res = xdr_string(fio->xdr,&cptr,slen);
+ else
+ res = 1;
+ if (!item && fio->bRead)
+ sfree(cptr);
+ break;
+ }
+ default:
+ gmx_fio_fe(fio, eio, desc, srcfile, line);
+ }
+ if ((res == 0) && (fio->bDebug))
+ fprintf(stderr,"Error in xdr I/O %s %s to file %s (source %s, line %d)\n",
+ eioNames[eio],desc,fio->fn,srcfile,line);
+
+ return (res != 0);
+}
+
+
+static bool do_xdrread(t_fileio *fio, void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ return do_xdr(fio, item, nitem, eio, desc, srcfile, line);
+}
+
+
+static bool do_xdrwrite(t_fileio *fio, const void *item, int nitem, int eio,
+ const char *desc, const char *srcfile, int line)
+{
+ void *it=(void*)item; /* ugh.. */
+ return do_xdr(fio, it, nitem, eio, desc, srcfile, line);
+}
+
+#endif
+
+
#include "txtdump.h"
#include "gmxfio.h"
-typedef enum { etOther, etProt, etDNA, erestNR } eRestp;
-static const char *ResTP[erestNR] = { "OTHER", "PROTEIN", "DNA" };
+typedef enum { etOther, etProt, etDNA, etRNA, erestNR } eRestp;
+static const char *ResTP[erestNR] = { "OTHER", "PROTEIN", "DNA", "RNA" };
-static const char *Sugars[] = { "A", "T", "G", "C", "U" };
-#define NDNA asize(Sugars)
+static const char *DNA[] = { "DA", "DT", "DG", "DC", "DU" };
+#define NDNA asize(DNA)
+
+static const char *RNA[] = { "A", "T", "G", "C", "U" };
+#define NRNA asize(RNA)
static const char *Negate[] = { "SOL" };
#define NNEGATE asize(Negate)
"MCD1", "MCD2", "MCE1", "MCE2", "MNZ1", "MNZ2" };
static const char *calpha[] = { "CA" };
static const char *bb[] = { "N","CA","C" };
- static const char *mc[] = { "N","CA","C","O","O1","O2","OXT" };
- static const char *mcb[] = { "N","CA","CB","C","O","O1","O2","OT","OXT" };
- static const char *mch[] = { "N","CA","C","O","O1","O2","OT","OXT",
+ static const char *mc[] = { "N","CA","C","O","O1","O2","OC1","OC2","OT","OXT" };
+ static const char *mcb[] = { "N","CA","CB","C","O","O1","O2","OC1","OC2","OT","OXT" };
+ static const char *mch[] = { "N","CA","C","O","O1","O2","OC1","OC2","OT","OXT",
"H1","H2","H3","H" };
/* array of arrays of atomnames: */
static const char **chains[] = { NULL,pnoh,calpha,bb,mc,mcb,mch,mch,mch,pnodum };
return aan;
}
+bool is_residue(t_aa_names *aan,char *resnm)
+{
+ /* gives true if resnm occurs in aminoacids.dat */
+ int i;
+
+ for(i=0; i<aan->n; i++) {
+ if (strcasecmp(aan->aa[i],resnm) == 0) {
+ return TRUE;
+ }
+ }
+ for(i=0; i<NDNA; i++) {
+ if (strcasecmp(DNA[i],resnm) == 0) {
+ return TRUE;
+ }
+ }
+ for(i=0; i<NRNA; i++) {
+ if (strcasecmp(RNA[i],resnm) == 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
bool is_protein(t_aa_names *aan,char *resnm)
{
/* gives true if resnm occurs in aminoacids.dat */
resnm = *atoms->resinfo[i].name;
if ((restp[i] == etOther) && is_protein(aan,resnm))
restp[i] = etProt;
- if (restp[i] == etOther)
+ if (restp[i] == etOther) {
for(j=0; (j<NDNA); j++) {
- if (strcasecmp(Sugars[j],resnm) == 0)
+ if (strcasecmp(DNA[j],resnm) == 0)
restp[i] = etDNA;
}
+ for(j=0; (j<NRNA); j++) {
+ if (strcasecmp(RNA[j],resnm) == 0)
+ restp[i] = etRNA;
+ }
+ }
}
p_status(atoms->nres,restp,bVerb);
done_aa_names(&aan);
}
sfree(aid);
+ /* RNA */
+ aid=mk_aid(atoms,restp,etRNA,&nra,TRUE);
+ if (nra > 0) {
+ add_grp(gb,gn,nra,aid,"RNA");
+ analyse_dna(restp,atoms,gb,gn,bASK,bVerb);
+ }
+ sfree(aid);
+
/* Other */
analyse_other(restp,atoms,gb,gn,bASK,bVerb);
#endif
+/* This is just for clarity - it can never be anything but 4! */
+#define XDR_INT_SIZE 4
+
+
+
+#ifndef GMX_THREADS
+
+/* NOTE: DO NOT USE THESE ANYWHERE IN GROMACS ITSELF.
+ These are necessary for the backward-compatile io routines for 3d party
+ tools */
#define MAXID 256
static FILE *xdrfiles[MAXID];
static XDR *xdridptr[MAXID];
static char xdrmodes[MAXID];
static unsigned int cnt;
-/* This is just for clarity - it can never be anything but 4! */
-#define XDR_INT_SIZE 4
+#endif
#ifdef GMX_FORTRAN
+
+/* the open&close prototypes */
+int xdropen(XDR *xdrs, const char *filename, const char *type);
+int xdrclose(XDR *xdrs);
+
typedef void (* F77_FUNC(xdrfproc,XDRFPROC))(int *, void *, int *);
int ftocstr(char *ds, int dl, char *ss, int sl)
}
#endif /* GMX_FORTRAN */
-/*___________________________________________________________________________
- |
- | what follows are the C routines for opening, closing xdr streams
- | and the routine to read/write compressed coordinates together
- | with some routines to assist in this task (those are marked
- | static and cannot be called from user programs)
-*/
-#define MAXABS INT_MAX-2
-
-#ifndef MIN
-#define MIN(x,y) ((x) < (y) ? (x):(y))
-#endif
-#ifndef MAX
-#define MAX(x,y) ((x) > (y) ? (x):(y))
-#endif
-#ifndef SQR
-#define SQR(x) ((x)*(x))
-#endif
-static int magicints[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
- 80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
- 812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
- 8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
- 82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
- 832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042,
- 8388607, 10568983, 13316085, 16777216 };
-
-#define FIRSTIDX 9
-/* note that magicints[FIRSTIDX-1] == 0 */
-#define LASTIDX (sizeof(magicints) / sizeof(*magicints))
-
-
+#ifndef GMX_THREADS
/*__________________________________________________________________________
|
| xdropen - open xdr file
|
| This versions differs from xdrstdio_create, because I need to know
- | the state of the file (read or write) so I can use xdr3dfcoord
- | in eigther read or write mode, and the file descriptor
+ | the state of the file (read or write) and the file descriptor
| so I can close the file (something xdr_destroy doesn't do).
|
+ | NOTE: THIS FUNCTION IS NOW OBSOLETE AND ONLY PROVIDED FOR BACKWARD
+ | COMPATIBILITY OF 3D PARTY TOOLS. IT SHOULD NOT BE USED ANYWHERE
+ | IN GROMACS ITSELF.
*/
int xdropen(XDR *xdrs, const char *filename, const char *type) {
return 0;
}
- /* next test isn't usefull in the case of C language
+ /* next test isn't useful in the case of C language
* but is used for the Fortran interface
* (C users are expected to pass the address of an already allocated
* XDR staructure)
}
return xdrid;
}
-
/*_________________________________________________________________________
|
| xdrclose - close a xdr file
| It also closes the associated file descriptor (this is *not*
| done by xdr_destroy).
|
+ | NOTE: THIS FUNCTION IS NOW OBSOLETE AND ONLY PROVIDED FOR BACKWARD
+ | COMPATIBILITY OF 3D PARTY TOOLS. IT SHOULD NOT BE USED ANYWHERE
+ | IN GROMACS ITSELF.
*/
int xdrclose(XDR *xdrs) {
return 0;
}
-FILE *
-xdr_get_fp(int xdrid)
-{
- return xdrfiles[xdrid];
-}
+#endif
+
+
+/*___________________________________________________________________________
+ |
+ | what follows are the C routine to read/write compressed coordinates together
+ | with some routines to assist in this task (those are marked
+ | static and cannot be called from user programs)
+*/
+#define MAXABS INT_MAX-2
+
+#ifndef MIN
+#define MIN(x,y) ((x) < (y) ? (x):(y))
+#endif
+#ifndef MAX
+#define MAX(x,y) ((x) > (y) ? (x):(y))
+#endif
+#ifndef SQR
+#define SQR(x) ((x)*(x))
+#endif
+static const int magicints[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
+ 80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
+ 812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
+ 8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
+ 82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
+ 832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042,
+ 8388607, 10568983, 13316085, 16777216 };
+
+#define FIRSTIDX 9
+/* note that magicints[FIRSTIDX-1] == 0 */
+#define LASTIDX (sizeof(magicints) / sizeof(*magicints))
/*____________________________________________________________________________
|
*/
-int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision) {
-
-
+int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision, bool bRead)
+{
static int *ip = NULL;
static int oldsize;
static int *buf;
bitsizeint[0] = bitsizeint[1] = bitsizeint[2] = 0;
prevcoord[0] = prevcoord[1] = prevcoord[2] = 0;
-
- /* find out if xdrs is opened for reading or for writing */
- xdrid = 0;
- while (xdridptr[xdrid] != xdrs) {
- xdrid++;
- if (xdrid >= MAXID) {
- fprintf(stderr, "xdr error. no open xdr stream\n");
- exit (1);
- }
- }
- if ((xdrmodes[xdrid] == 'w') || (xdrmodes[xdrid] == 'a')) {
-
+
+ if (!bRead)
+ {
/* xdrs is open for writing */
if (xdr_int(xdrs, size) == 0)
return cr;
}
-t_commrec *init_par_threads(t_commrec *cro)
+t_commrec *init_par_threads(const t_commrec *cro)
{
#ifdef GMX_THREADS
int initialized;
t_commrec *cr;
+ /* make a thread-specific commrec */
snew(cr,1);
/* now copy the whole thing, so settings like the number of PME nodes
get propagated. */
*cr=*cro;
+
/* and we start setting our own thread-specific values for things */
MPI_Initialized(&initialized);
if (!initialized)
#endif
}
-void cancel_par_threads(t_commrec *cr)
-{
-#ifdef GMX_THREADS
- if (MASTERTHREAD(cr))
- {
- fprintf(stderr, "\nCANCELING %d THREADS\n", cr->nthreads-1);
- cr->nnodes = 1;
- cr->nthreads = 1;
- cr->sim_nodeid = 0;
- cr->nodeid = 0;
- cr->threadid = 0;
- cr->duty = (DUTY_PP | DUTY_PME);
- }
- else
- {
- tMPI_Finalize();
- }
-#else
- gmx_incons("cancel_par_threads called without thread support");
-#endif
-}
t_commrec *init_cr_nopar(void)
{
}
}
-char *fgetline(char **line,int llmax,FILE *in)
+static char *fgetline(char **line,int llmax,int *llalloc,FILE *in)
{
- static char *line0=NULL;
- static int linelengthmax=0;
char *fg;
-
- if (llmax > linelengthmax) {
- linelengthmax = llmax;
- srenew(line0,linelengthmax);
+
+ if (!(*line))
+ {
+ snew(*line, llmax);
+ *llalloc=llmax;
}
- fg=fgets(line0,linelengthmax,in);
- *line=line0;
+ else if (llmax > *llalloc)
+ {
+ srenew(*line,llmax);
+ *llalloc=llmax;
+ }
+ fg=fgets(*line,llmax,in);
trim(*line);
-
+
return fg;
}
t_mapping *map;
char *line=NULL,*str,buf[256];
int i,m,col_len,nch,n_axis_x,n_axis_y,llmax;
+ int llalloc=0;
unsigned int r,g,b;
double u;
bool bGetOnWithIt;
llmax = STRLEN;
- while (fgetline(&line,llmax,in) && (strncmp(line,"static",6) != 0)) {
+ while (fgetline(&line,llmax,&llalloc,in) && (strncmp(line,"static",6) != 0)) {
parsestring(line,"title",(mm->title));
parsestring(line,"legend",(mm->legend));
parsestring(line,"x-label",(mm->label_x));
gmx_input("Invalid XPixMap");
/* Read sizes */
bGetOnWithIt=FALSE;
- while (!bGetOnWithIt && fgetline(&line,llmax,in)) {
+ while (!bGetOnWithIt && fgetline(&line,llmax,&llalloc,in)) {
while (( line[0] != '\"' ) && ( line[0] != '\0' ))
line++;
/* Read color map */
snew(map,mm->nmap);
m=0;
- while ((m < mm->nmap) && fgetline(&line,llmax,in)) {
+ while ((m < mm->nmap) && fgetline(&line,llmax,&llalloc,in)) {
line=strchr(line,'\"');
if (line) {
line++;
skipstr(&line);
}
}
- } while ((line[0] != '\"') && fgetline(&line,llmax,in));
+ } while ((line[0] != '\"') && fgetline(&line,llmax,&llalloc,in));
/* Read matrix */
snew(mm->matrix,mm->nx);
}
m--;
}
- } while ((m>=0) && fgetline(&line,llmax,in));
+ } while ((m>=0) && fgetline(&line,llmax,&llalloc,in));
if (m>=0)
gmx_incons("Not enough rows in the matrix");
+
+ sfree(line);
}
int read_xpm_matrix(const char *fnm,t_matrix **matrix)
{
FILE *in;
- char *line;
+ char *line=NULL;
int nmat;
+ int llalloc=0;
in=gmx_fio_fopen(fnm,"r");
nmat=0;
- while (fgetline(&line,STRLEN,in)) {
+ while (fgetline(&line,STRLEN,&llalloc,in)) {
if (strstr(line,"/* XPM */")) {
srenew(*matrix,nmat+1);
read_xpm_entry(in,&(*matrix)[nmat]);
if (nmat==0)
gmx_file("Invalid XPixMap");
+ sfree(line);
+
return nmat;
}
for(j=0; j<g->nedge[i]; j++) {
g->edge[0][n++] = g->edge[i][j];
}
- g->edge[i] = g->edge[0] + n - g->nedge[i];
max_nedge = max(max_nedge,g->nedge[i]);
}
srenew(g->edge[0],n);
+ /* set pointers after srenew because edge[0] might move */
+ for(i=1; i<g->nnodes; i++) {
+ g->edge[i] = g->edge[i-1] + g->nedge[i-1];
+ }
if (fplog) {
fprintf(fplog,"Max number of graph edges per atom is %d\n",
}
}
#undef GCHECK
-
-#ifdef DEBUGMSHIFT
-void main(int argc,char *argv[])
-{
- FILE *out;
- t_args targ;
- t_topology top;
- t_statheader sh;
- rvec *x;
- ivec *mshift;
- matrix box;
-
- t_graph *g;
- int i,idum,pid;
- real rdum;
-
- CopyRight(stderr,argv[0]);
- parse_common_args(&argc,argv,&targ,PCA_NEED_INOUT,NULL);
- if (argc > 1)
- pid=strtol(argv[1], NULL, 10);
- else
- pid=0;
-
- read_status_header(targ.infile,&sh);
- snew(x,sh.natoms);
- snew(mshift,sh.natoms);
-
- fprintf(stderr,"Reading Status %s\n",targ.infile);
- read_status(targ.infile,&idum,&rdum,&rdum,NULL,
- box,NULL,NULL,&idum,x,NULL,NULL,&idum,NULL,&top);
-
- fprintf(stderr,"Making Graph Structure...\n");
- g=mk_graph(&(top.idef),top.atoms.nr,FALSE,FALSE);
-
- out=gmx_fio_fopen(targ.outfile,"w");
-
- fprintf(stderr,"Making Shift...\n");
- mk_mshift(out,g,box,x,mshift);
-
- p_graph(out,"In Den Haag daar woont een graaf...",g);
- gmx_fio_fclose(out);
-}
-#endif
-
gen_local_top(mtop,NULL,FALSE,<op);
- open_symtab(&top.symtab);
-
- open_symtab(&top.symtab);
-
top.name = mtop->name;
top.idef = ltop.idef;
top.atomtypes = ltop.atomtypes;
top.excls = ltop.excls;
top.atoms = gmx_mtop_global_atoms(mtop);
top.mols = mtop->mols;
+ top.symtab = mtop->symtab;
/* We only need to free the moltype and molblock data,
* all other pointers have been copied to top.
+ *
+ * Well, except for the group data, but we can't free those, because they
+ * are used somewhere even after a call to this function.
*/
for(mt=0; mt<mtop->nmoltype; mt++)
{
#include "copyrite.h"
#include "gmx_fatal.h"
#include "mtxio.h"
+#include "gmxfio.h"
/* Just a number to identify our file type */
* Each entry consists of an integer column index and floating-point data value.
*/
-void
-gmx_mtxio_write(const char * filename,
- int nrow,
- int ncol,
- real * full_matrix,
- gmx_sparsematrix_t * sparse_matrix)
+void gmx_mtxio_write(const char * filename,
+ int nrow,
+ int ncol,
+ real * full_matrix,
+ gmx_sparsematrix_t * sparse_matrix)
{
- int fd;
+ t_fileio *fio;
XDR * xd;
int i,j,prec;
bool bDum = TRUE;
gmx_fatal(FARGS,"Both full AND sparse matrix specified to gmx_mtxio_write().\n");
}
- fd = gmx_fio_open(filename,"w");
- gmx_fio_select(fd);
- xd = gmx_fio_getxdr(fd);
+ fio = gmx_fio_open(filename,"w");
+ gmx_fio_checktype(fio);
+ xd = gmx_fio_getxdr(fio);
/* Write magic number */
i = GMX_MTXIO_MAGIC_NUMBER;
- do_int(i);
+ gmx_fio_do_int(fio, i);
/* Write generating Gromacs version */
- do_string(GromacsVersion());
+ gmx_fio_write_string(fio, GromacsVersion());
/* Write 1 for double, 0 for single precision */
if(sizeof(real)==sizeof(double))
prec = 1;
else
prec = 0;
- do_int(prec);
+ gmx_fio_do_int(fio, prec);
- do_int(nrow);
- do_int(ncol);
+ gmx_fio_do_int(fio, nrow);
+ gmx_fio_do_int(fio, ncol);
if(full_matrix!=NULL)
{
/* Full matrix storage format */
i = GMX_MTXIO_FULL_MATRIX;
- do_int(i);
+ gmx_fio_do_int(fio, i);
sz = nrow*ncol;
- ndo_real(full_matrix,sz,bDum);
+ bDum=gmx_fio_ndo_real(fio, full_matrix,sz);
}
else
{
/* Sparse storage */
i = GMX_MTXIO_SPARSE_MATRIX;
- do_int(i);
-
- do_int(sparse_matrix->compressed_symmetric);
- do_int(sparse_matrix->nrow);
+ gmx_fio_do_int(fio, i);
+
+ gmx_fio_do_bool(fio, sparse_matrix->compressed_symmetric);
+ gmx_fio_do_int(fio, sparse_matrix->nrow);
if(sparse_matrix->nrow != nrow)
{
gmx_fatal(FARGS,"Internal inconsistency in sparse matrix.\n");
}
- ndo_int(sparse_matrix->ndata,sparse_matrix->nrow,bDum);
+ bDum=gmx_fio_ndo_int(fio, sparse_matrix->ndata,sparse_matrix->nrow);
for(i=0;i<sparse_matrix->nrow;i++)
{
for(j=0;j<sparse_matrix->ndata[i];j++)
{
- do_int(sparse_matrix->data[i][j].col);
- do_real(sparse_matrix->data[i][j].value);
+ gmx_fio_do_int(fio, sparse_matrix->data[i][j].col);
+ gmx_fio_do_real(fio, sparse_matrix->data[i][j].value);
}
}
}
- gmx_fio_close(fd);
+ gmx_fio_close(fio);
}
real ** full_matrix,
gmx_sparsematrix_t ** sparse_matrix)
{
- int fd;
+ t_fileio *fio;
XDR * xd;
int i,j,prec;
bool bDum = TRUE;
char gmxver[256];
size_t sz;
- fd = gmx_fio_open(filename,"r");
- gmx_fio_select(fd);
- xd = gmx_fio_getxdr(fd);
+ fio = gmx_fio_open(filename,"r");
+ gmx_fio_checktype(fio);
+ xd = gmx_fio_getxdr(fio);
/* Read and check magic number */
i = GMX_MTXIO_MAGIC_NUMBER;
- do_int(i);
+ gmx_fio_do_int(fio, i);
if(i!=GMX_MTXIO_MAGIC_NUMBER)
{
}
/* Read generating Gromacs version */
- do_string(gmxver);
+ gmx_fio_do_string(fio, gmxver);
/* Write 1 for double, 0 for single precision */
if(sizeof(real)==sizeof(double))
prec = 1;
else
prec = 0;
- do_int(prec);
+ gmx_fio_do_int(fio, prec);
fprintf(stderr,"Reading %s precision matrix generated by Gromacs %s\n",
(prec == 1) ? "double" : "single",gmxver);
- do_int(i);
+ gmx_fio_do_int(fio, i);
*nrow=i;
- do_int(i);
+ gmx_fio_do_int(fio, i);
*ncol=i;
- do_int(i);
+ gmx_fio_do_int(fio, i);
if(i==GMX_MTXIO_FULL_MATRIX)
{
sz = (*nrow) * (*ncol);
snew((*full_matrix),sz);
- ndo_real((*full_matrix),sz,bDum);
+ bDum=gmx_fio_ndo_real(fio, (*full_matrix),sz);
}
else
{
printf("Sparse matrix storage format, nrow=%d, ncols=%d\n",*nrow,*ncol);
snew((*sparse_matrix),1);
- do_int((*sparse_matrix)->compressed_symmetric);
- do_int((*sparse_matrix)->nrow);
+ gmx_fio_do_bool(fio, (*sparse_matrix)->compressed_symmetric);
+ gmx_fio_do_int(fio, (*sparse_matrix)->nrow);
if((*sparse_matrix)->nrow != *nrow)
{
gmx_fatal(FARGS,"Internal inconsistency in sparse matrix.\n");
snew((*sparse_matrix)->ndata,(*sparse_matrix)->nrow);
snew((*sparse_matrix)->nalloc,(*sparse_matrix)->nrow);
snew((*sparse_matrix)->data,(*sparse_matrix)->nrow);
- ndo_int((*sparse_matrix)->ndata,(*sparse_matrix)->nrow,bDum);
+ bDum=gmx_fio_ndo_int(fio, (*sparse_matrix)->ndata,
+ (*sparse_matrix)->nrow);
for(i=0;i<(*sparse_matrix)->nrow;i++)
{
for(j=0;j<(*sparse_matrix)->ndata[i];j++)
{
- do_int((*sparse_matrix)->data[i][j].col);
- do_real((*sparse_matrix)->data[i][j].value);
+ gmx_fio_do_int(fio, (*sparse_matrix)->data[i][j].col);
+ gmx_fio_do_real(fio, (*sparse_matrix)->data[i][j].value);
}
}
}
- gmx_fio_close(fd);
+ gmx_fio_close(fio);
}
}
MPE_Init_log();
#endif
-
+
+#ifdef GMX_LIB_MPI
fprintf(stderr,"NNODES=%d, MYRANK=%d, HOSTNAME=%s\n",
mpi_num_nodes,mpi_my_rank,mpi_hostname);
+#endif
*nnodes=mpi_num_nodes;
#else
#ifdef GMX_THREADS
fprintf(stderr,"Halting program %s\n",ShortProgram());
+ thanx(stderr);
exit(1);
#else
if (nnodes > 1)
__m128 vgb,vgbB,fijGB,fijGBB,dvdatmp,dvdatmpB;
__m128 facel,gbtabscale,mask,dvdaj;
- __m128 mask1 = _mm_castsi128_ps( _mm_set_epi32(0, 0, 0, 0xffffffff) );
- __m128 mask2 = _mm_castsi128_ps( _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff) );
- __m128 mask3 = _mm_castsi128_ps( _mm_set_epi32(0, 0xffffffff, 0xffffffff, 0xffffffff) );
+ __m128 mask1 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0, 0, 0xffffffff) );
+ __m128 mask2 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff) );
+ __m128 mask3 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0xffffffff, 0xffffffff, 0xffffffff) );
__m128i n0, nnn;
__m128i n0B, nnnB;
gmx_mm_update_iforce_1atom_ps(fix,fiy,fiz,faction+ii3,fshift+is3);
ggid = gid[n];
- gmx_mm_update_2pot_ps(vctot,vc+ggid,vgbtot,gpol+ggid);
+
+ gmx_mm_update_1pot_ps(vctot,vc+ggid);
+ gmx_mm_update_1pot_ps(vgbtot,gpol+ggid);
gmx_mm_update_1pot_ps(dvdasum,dvda+ii);
}
__m128 rinvsixB,vvdw6B,vvdw12B;
__m128 facel,gbtabscale,mask,dvdaj;
- __m128 mask1 = _mm_castsi128_ps( _mm_set_epi32(0, 0, 0, 0xffffffff) );
- __m128 mask2 = _mm_castsi128_ps( _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff) );
- __m128 mask3 = _mm_castsi128_ps( _mm_set_epi32(0, 0xffffffff, 0xffffffff, 0xffffffff) );
+ __m128 mask1 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0, 0, 0xffffffff) );
+ __m128 mask2 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff) );
+ __m128 mask3 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0xffffffff, 0xffffffff, 0xffffffff) );
__m128i n0, nnn;
__m128i n0B, nnnB;
jz = _mm_setzero_ps();
c6 = _mm_setzero_ps();
c12 = _mm_setzero_ps();
-
+
for(n=0; (n<nri); n++)
{
#include <xmmintrin.h>
#include <emmintrin.h>
-
+#include <gmx_sse2_single.h>
/* get gmx_gbdata_t */
#include "../nb_kerneltype.h"
static inline __m128
my_invrsq_ps(__m128 x)
{
- const __m128 three = (const __m128) {3.0f, 3.0f, 3.0f, 3.0f};
- const __m128 half = (const __m128) {0.5f, 0.5f, 0.5f, 0.5f};
+ const __m128 three = {3.0f, 3.0f, 3.0f, 3.0f};
+ const __m128 half = {0.5f, 0.5f, 0.5f, 0.5f};
__m128 t1 = _mm_rsqrt_ps(x);
- return (__m128) _mm_mul_ps(half,_mm_mul_ps(t1,_mm_sub_ps(three,_mm_mul_ps(x,_mm_mul_ps(t1,t1)))));
+ return gmx_mm_castps_ps128(_mm_mul_ps(half,_mm_mul_ps(t1,_mm_sub_ps(three,_mm_mul_ps(x,_mm_mul_ps(t1,t1))))));
}
void nb_kernel430_ia32_sse(int * p_nri,
gpol = gbdata->gpol;
nri = *p_nri;
- ntype = *p_ntype;
- nthreads = *p_nthreads;
- facel = *p_facel;
+ ntype = *p_ntype;
+ nthreads = *p_nthreads;
+ facel = *p_facel;
scl_gb = (1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent);
- krf = *p_krf;
- crf = *p_crf;
- tabscale = *p_tabscale;
- gbtabscale = *p_gbtabscale;
- nj1 = 0;
+ krf = *p_krf;
+ crf = *p_crf;
+ tabscale = *p_tabscale;
+ gbtabscale = *p_gbtabscale;
+ nj1 = 0;
/* Splat variables */
fac_sse = _mm_load1_ps(&facel);
mask = _mm_set_epi32(0,0xffffffff,0xffffffff,0xffffffff);
}
- jx = _mm_and_ps( (__m128) mask, xmm6);
- jy = _mm_and_ps( (__m128) mask, xmm4);
- jz = _mm_and_ps( (__m128) mask, xmm5);
+ jx = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm6);
+ jy = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm4);
+ jz = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm5);
- c6 = _mm_and_ps( (__m128) mask, c6);
- c12 = _mm_and_ps( (__m128) mask, c12);
- dvdaj = _mm_and_ps( (__m128) mask, dvdaj);
- isaj = _mm_and_ps( (__m128) mask, isaj);
- q = _mm_and_ps( (__m128) mask, q);
+ c6 = _mm_and_ps( gmx_mm_castsi128_ps(mask), c6);
+ c12 = _mm_and_ps( gmx_mm_castsi128_ps(mask), c12);
+ dvdaj = _mm_and_ps( gmx_mm_castsi128_ps(mask), dvdaj);
+ isaj = _mm_and_ps( gmx_mm_castsi128_ps(mask), isaj);
+ q = _mm_and_ps( gmx_mm_castsi128_ps(mask), q);
dx1 = _mm_sub_ps(ix,jx);
dy1 = _mm_sub_ps(iy,jy);
xmm1 = _mm_mul_ps(xmm1,isaj);
dvdaj = _mm_add_ps(dvdaj,xmm1);
- vcoul = _mm_and_ps( (__m128) mask, vcoul);
- vgb = _mm_and_ps( (__m128) mask, vgb);
+ vcoul = _mm_and_ps( gmx_mm_castsi128_ps(mask), vcoul);
+ vgb = _mm_and_ps( gmx_mm_castsi128_ps(mask), vgb);
vctot = _mm_add_ps(vctot,vcoul);
vgbtot = _mm_add_ps(vgbtot,vgb);
_mm_store_ss(faction+j33+2,xmm7);
}
- t1 = _mm_and_ps( (__m128) mask, t1);
- t2 = _mm_and_ps( (__m128) mask, t2);
- t3 = _mm_and_ps( (__m128) mask, t3);
+ t1 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t1);
+ t2 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t2);
+ t3 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t3);
fix = _mm_add_ps(fix,t1);
fiy = _mm_add_ps(fiy,t2);
xmm2 = _mm_unpacklo_ps(fix,fiy); /* fx, fy, - - */
xmm2 = _mm_movelh_ps(xmm2,fiz);
- xmm2 = _mm_and_ps( (__m128) maski, xmm2);
+ xmm2 = _mm_and_ps( gmx_mm_castsi128_ps(maski), xmm2);
/* load, add and store i forces */
xmm4 = _mm_loadl_pi(xmm4, (__m64 *) (faction+ii3));
_mm_store_ss(fshift+is3+2,xmm4);
/* Coulomb potential */
- ggid = gid[n];
+ ggid = gid[n];
vcoul = _mm_movehl_ps(vcoul,vctot);
vctot = _mm_add_ps(vctot,vcoul);
__m128d q,iq,qq,isai,isaj,isaprod,vcoul,gbscale,dvdai,dvdaj;
__m128d Y,F,G,H,Fp,VV,FF,vgb,fijC,dvdatmp,dvdasum,vctot,vgbtot,n0d;
__m128d xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
- __m128d fac,tabscale,gbtabscale;
+ __m128d fac,tabscale,gbtabscale,gbfactor;
__m128i n0,nnn;
const __m128d neg = {-1.0f,-1.0f};
nri = *p_nri;
ntype = *p_ntype;
nthreads = *p_nthreads;
- facel = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));
+ facel = *p_facel;
krf = *p_krf;
crf = *p_crf;
tabscl = *p_tabscale;
fac = _mm_load1_pd(&facel);
tabscale = _mm_load1_pd(&tabscl);
gbtabscale = _mm_load1_pd(&gbtabscl);
+ gbfactor = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
/* Keep compiler happy */
dvdatmp = _mm_setzero_pd();
fscal = _mm_mul_pd(vcoul,rinv);
qq = _mm_mul_pd(isaprod,qq);
qq = _mm_mul_pd(qq,neg);
+ qq = _mm_mul_pd(qq,gbfactor);
gbscale = _mm_mul_pd(isaprod,gbtabscale);
/* Load dvdaj */
fscal = _mm_mul_sd(vcoul,rinv);
qq = _mm_mul_sd(isaprod,qq);
qq = _mm_mul_sd(qq,neg);
+ qq = _mm_mul_sd(qq,gbfactor);
gbscale = _mm_mul_sd(isaprod,gbtabscale);
r = _mm_mul_sd(rsq11,rinv);
__m128d Y,F,G,H,Fp,VV,FF,vgb,fijC,dvdatmp,dvdasum,vctot,vgbtot,n0d;
__m128d xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
__m128d c6,c12,Vvdw6,Vvdw12,Vvdwtmp,Vvdwtot,rinvsq,rinvsix;
- __m128d fac,tabscale,gbtabscale;
+ __m128d fac,tabscale,gbtabscale,gbfactor;
__m128i n0,nnn;
const __m128d neg = {-1.0f,-1.0f};
nri = *p_nri;
ntype = *p_ntype;
nthreads = *p_nthreads;
- facel = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));
+ facel = *p_facel;
krf = *p_krf;
crf = *p_crf;
tabscl = *p_tabscale;
fac = _mm_load1_pd(&facel);
tabscale = _mm_load1_pd(&tabscl);
gbtabscale = _mm_load1_pd(&gbtabscl);
+ gbfactor = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
/* Keep compiler happy */
Vvdwtmp = _mm_setzero_pd();
vcoul = _mm_mul_pd(qq,rinv);
fscal = _mm_mul_pd(vcoul,rinv);
qq = _mm_mul_pd(isaprod,qq);
+ qq = _mm_mul_pd(qq,gbfactor);
qq = _mm_mul_pd(qq,neg);
gbscale = _mm_mul_pd(isaprod,gbtabscale);
vcoul = _mm_mul_sd(qq,rinv);
fscal = _mm_mul_sd(vcoul,rinv);
qq = _mm_mul_sd(isaprod,qq);
+ qq = _mm_mul_sd(qq,gbfactor);
qq = _mm_mul_sd(qq,neg);
gbscale = _mm_mul_sd(isaprod,gbtabscale);
__m128d Y,F,G,H,Fp,VV,FF,vgb,fijC,fijD,fijR,dvdatmp,dvdasum,vctot,n0d;
__m128d xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
__m128d c6,c12,Vvdw6,Vvdw12,Vvdwtmp,Vvdwtot,vgbtot,rinvsq,rinvsix;
- __m128d fac,tabscale,gbtabscale;
+ __m128d fac,tabscale,gbtabscale,gbfactor;
__m128i n0,nnn;
const __m128d neg = {-1.0f,-1.0f};
nri = *p_nri;
ntype = *p_ntype;
nthreads = *p_nthreads;
- facel = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));
+ facel = *p_facel;
krf = *p_krf;
crf = *p_crf;
tabscl = *p_tabscale;
fac = _mm_load1_pd(&facel);
tabscale = _mm_load1_pd(&tabscl);
gbtabscale = _mm_load1_pd(&gbtabscl);
+ gbfactor = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
/* Keep compiler happy */
Vvdwtmp = _mm_setzero_pd();
fscal = _mm_mul_pd(vcoul,rinv);
qq = _mm_mul_pd(isaprod,qq);
qq = _mm_mul_pd(qq,neg);
+ qq = _mm_mul_pd(qq,gbfactor);
gbscale = _mm_mul_pd(isaprod,gbtabscale);
/* Load VdW parameters */
fscal = _mm_mul_sd(vcoul,rinv);
qq = _mm_mul_sd(isaprod,qq);
qq = _mm_mul_sd(qq,neg);
+ qq = _mm_mul_sd(qq,gbfactor);
gbscale = _mm_mul_sd(isaprod,gbtabscale);
/* Load VdW parameters */
gmx_mm_update_iforce_1atom_ps(fix,fiy,fiz,faction+ii3,fshift+is3);
ggid = gid[n];
- gmx_mm_update_2pot_ps(vctot,vc+ggid,vgbtot,gpol+ggid);
+
+ gmx_mm_update_1pot_ps(vctot,vc+ggid);
+ gmx_mm_update_1pot_ps(vgbtot,gpol+ggid);
gmx_mm_update_1pot_ps(dvdasum,dvda+ii);
}
#include <xmmintrin.h>
#include <emmintrin.h>
+#include <gmx_sse2_single.h>
/* get gmx_gbdata_t */
#include "../nb_kerneltype.h"
static inline __m128
my_invrsq_ps(__m128 x)
{
- const __m128 three = (const __m128) {3.0f, 3.0f, 3.0f, 3.0f};
- const __m128 half = (const __m128) {0.5f, 0.5f, 0.5f, 0.5f};
+ const __m128 three = {3.0f, 3.0f, 3.0f, 3.0f};
+ const __m128 half = {0.5f, 0.5f, 0.5f, 0.5f};
__m128 t1 = _mm_rsqrt_ps(x);
- return (__m128) _mm_mul_ps(half,_mm_mul_ps(t1,_mm_sub_ps(three,_mm_mul_ps(x,_mm_mul_ps(t1,t1)))));
+ return gmx_mm_castps_ps128(_mm_mul_ps(half,_mm_mul_ps(t1,_mm_sub_ps(three,_mm_mul_ps(x,_mm_mul_ps(t1,t1))))));
}
void nb_kernel430_sse2_single(int * p_nri,
gpol = gbdata->gpol;
nri = *p_nri;
- ntype = *p_ntype;
- nthreads = *p_nthreads;
- facel = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));
- krf = *p_krf;
- crf = *p_crf;
- tabscale = *p_tabscale;
- gbtabscale = *p_gbtabscale;
- nj1 = 0;
+ ntype = *p_ntype;
+ nthreads = *p_nthreads;
+ facel = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));
+ krf = *p_krf;
+ crf = *p_crf;
+ tabscale = *p_tabscale;
+ gbtabscale = *p_gbtabscale;
+ nj1 = 0;
/* Splat variables */
fac_sse = _mm_load1_ps(&facel);
mask = _mm_set_epi32(0,0xffffffff,0xffffffff,0xffffffff);
}
- jx = _mm_and_ps( (__m128) mask, xmm6);
- jy = _mm_and_ps( (__m128) mask, xmm4);
- jz = _mm_and_ps( (__m128) mask, xmm5);
+ jx = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm6);
+ jy = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm4);
+ jz = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm5);
- c6 = _mm_and_ps( (__m128) mask, c6);
- c12 = _mm_and_ps( (__m128) mask, c12);
- dvdaj = _mm_and_ps( (__m128) mask, dvdaj);
- isaj = _mm_and_ps( (__m128) mask, isaj);
- q = _mm_and_ps( (__m128) mask, q);
+ c6 = _mm_and_ps( gmx_mm_castsi128_ps(mask), c6);
+ c12 = _mm_and_ps( gmx_mm_castsi128_ps(mask), c12);
+ dvdaj = _mm_and_ps( gmx_mm_castsi128_ps(mask), dvdaj);
+ isaj = _mm_and_ps( gmx_mm_castsi128_ps(mask), isaj);
+ q = _mm_and_ps( gmx_mm_castsi128_ps(mask), q);
dx1 = _mm_sub_ps(ix,jx);
dy1 = _mm_sub_ps(iy,jy);
xmm1 = _mm_mul_ps(xmm1,isaj);
dvdaj = _mm_add_ps(dvdaj,xmm1);
- vcoul = _mm_and_ps( (__m128) mask, vcoul);
- vgb = _mm_and_ps( (__m128) mask, vgb);
+ vcoul = _mm_and_ps( gmx_mm_castsi128_ps(mask), vcoul);
+ vgb = _mm_and_ps( gmx_mm_castsi128_ps(mask), vgb);
vctot = _mm_add_ps(vctot,vcoul);
vgbtot = _mm_add_ps(vgbtot,vgb);
_mm_store_ss(faction+j33+2,xmm7);
}
- t1 = _mm_and_ps( (__m128) mask, t1);
- t2 = _mm_and_ps( (__m128) mask, t2);
- t3 = _mm_and_ps( (__m128) mask, t3);
+ t1 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t1);
+ t2 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t2);
+ t3 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t3);
fix = _mm_add_ps(fix,t1);
fiy = _mm_add_ps(fiy,t2);
xmm2 = _mm_unpacklo_ps(fix,fiy); /* fx, fy, - - */
xmm2 = _mm_movelh_ps(xmm2,fiz);
- xmm2 = _mm_and_ps( (__m128) maski, xmm2);
+ xmm2 = _mm_and_ps( gmx_mm_castsi128_ps(maski), xmm2);
/* load i force from memory */
xmm4 = _mm_loadl_pi(xmm4, (__m64 *) (faction+ii3));
xmm4 = _mm_shuffle_ps(xmm4,xmm4,_MM_SHUFFLE(2,2,2,2));
_mm_store_ss(faction+ii3+2,xmm4);
- ggid = gid[n];
+ /* Load, add and store i shift forces */
+ xmm4 = _mm_loadl_pi(xmm4, (__m64 *) (fshift+is3));
+ xmm5 = _mm_load1_ps(fshift+is3+2);
+ xmm4 = _mm_shuffle_ps(xmm4,xmm5,_MM_SHUFFLE(3,2,1,0));
+
+ xmm4 = _mm_add_ps(xmm4,xmm2);
+
+ _mm_storel_pi( (__m64 *) (fshift+is3),xmm4);
+ xmm4 = _mm_shuffle_ps(xmm4,xmm4,_MM_SHUFFLE(2,2,2,2));
+ _mm_store_ss(fshift+is3+2,xmm4);
+
+ /* Coulomb potential */
+ ggid = gid[n];
vcoul = _mm_movehl_ps(vcoul,vctot);
vctot = _mm_add_ps(vctot,vcoul);
gmx_mm_update_iforce_1atom_ps(fix,fiy,fiz,faction+ii3,fshift+is3);
ggid = gid[n];
- gmx_mm_update_2pot_ps(vctot,vc+ggid,vgbtot,gpol+ggid);
+
+ gmx_mm_update_1pot_ps(vctot,vc+ggid);
+ gmx_mm_update_1pot_ps(vgbtot,gpol+ggid);
gmx_mm_update_1pot_ps(dvdasum,dvda+ii);
}
xmm4 = _mm_shuffle_ps(xmm4,xmm4,_MM_SHUFFLE(2,2,2,2));
_mm_store_ss(faction+ii3+2,xmm4);
- ggid = gid[n];
+ /* Load, add and store i shift forces */
+ xmm4 = _mm_loadl_pi(xmm4, (__m64 *) (fshift+is3));
+ xmm5 = _mm_load1_ps(fshift+is3+2);
+ xmm4 = _mm_shuffle_ps(xmm4,xmm5,_MM_SHUFFLE(3,2,1,0));
+
+ xmm4 = _mm_add_ps(xmm4,xmm2);
+
+ _mm_storel_pi( (__m64 *) (fshift+is3),xmm4);
+ xmm4 = _mm_shuffle_ps(xmm4,xmm4,_MM_SHUFFLE(2,2,2,2));
+ _mm_store_ss(fshift+is3+2,xmm4);
+
+ /* Coulomb potential */
+ ggid = gid[n];
vcoul = _mm_movehl_ps(vcoul,vctot);
vctot = _mm_add_ps(vctot,vcoul);
/* get gmx_gbdata_t */
#include "../nb_kerneltype.h"
+#include "nb_kernel400_x86_64_sse2.h"
+
static inline __m128d
my_invrsq_pd(__m128d x)
{
__m128d q,iq,qq,isai,isaj,isaprod,vcoul,gbscale,dvdai,dvdaj;
__m128d Y,F,G,H,Fp,VV,FF,vgb,fijC,dvdatmp,dvdasum,vctot,vgbtot,n0d;
__m128d xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
- __m128d fac,tabscale,gbtabscale;
+ __m128d fac,tabscale,gbtabscale,gbfactor;
__m128i n0,nnn;
const __m128d neg = {-1.0f,-1.0f};
nri = *p_nri;
ntype = *p_ntype;
nthreads = *p_nthreads;
- facel = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));
+ facel = *p_facel;
krf = *p_krf;
crf = *p_crf;
tabscl = *p_tabscale;
fac = _mm_load1_pd(&facel);
tabscale = _mm_load1_pd(&tabscl);
gbtabscale = _mm_load1_pd(&gbtabscl);
+ gbfactor = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
/* Keep compiler happy */
dvdatmp = _mm_setzero_pd();
fscal = _mm_mul_pd(vcoul,rinv);
qq = _mm_mul_pd(isaprod,qq);
qq = _mm_mul_pd(qq,neg);
+ qq = _mm_mul_pd(qq,gbfactor);
gbscale = _mm_mul_pd(isaprod,gbtabscale);
/* Load dvdaj */
/* .. then fz */
_mm_storel_pd(faction+j13+2,xmm7);
- _mm_storel_pd(faction+j23+2,xmm7);
+ _mm_storeh_pd(faction+j23+2,xmm7);
}
/* In double precision, offset can only be either 0 or 1 */
fscal = _mm_mul_sd(vcoul,rinv);
qq = _mm_mul_sd(isaprod,qq);
qq = _mm_mul_sd(qq,neg);
+ qq = _mm_mul_pd(qq,gbfactor);
gbscale = _mm_mul_sd(isaprod,gbtabscale);
r = _mm_mul_sd(rsq11,rinv);
/* get gmx_gbdata_t */
#include "../nb_kerneltype.h"
+#include "nb_kernel410_x86_64_sse2.h"
static inline __m128d
my_invrsq_pd(__m128d x)
__m128d Y,F,G,H,Fp,VV,FF,vgb,fijC,dvdatmp,dvdasum,vctot,vgbtot,n0d;
__m128d xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
__m128d c6,c12,Vvdw6,Vvdw12,Vvdwtmp,Vvdwtot,rinvsq,rinvsix;
- __m128d fac,tabscale,gbtabscale;
+ __m128d fac,tabscale,gbtabscale,gbfactor;
__m128i n0,nnn;
const __m128d neg = {-1.0f,-1.0f};
nri = *p_nri;
ntype = *p_ntype;
nthreads = *p_nthreads;
- facel = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));
+ facel = *p_facel;
krf = *p_krf;
crf = *p_crf;
tabscl = *p_tabscale;
fac = _mm_load1_pd(&facel);
tabscale = _mm_load1_pd(&tabscl);
gbtabscale = _mm_load1_pd(&gbtabscl);
+ gbfactor = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
/* Keep compiler happy */
Vvdwtmp = _mm_setzero_pd();
vcoul = _mm_mul_pd(qq,rinv);
fscal = _mm_mul_pd(vcoul,rinv);
qq = _mm_mul_pd(isaprod,qq);
+ qq = _mm_mul_pd(qq,gbfactor);
qq = _mm_mul_pd(qq,neg);
gbscale = _mm_mul_pd(isaprod,gbtabscale);
/* .. then fz */
_mm_storel_pd(faction+j13+2,xmm7);
- _mm_storel_pd(faction+j23+2,xmm7);
+ _mm_storeh_pd(faction+j23+2,xmm7);
}
/* In double precision, offset can only be either 0 or 1 */
vcoul = _mm_mul_sd(qq,rinv);
fscal = _mm_mul_sd(vcoul,rinv);
qq = _mm_mul_sd(isaprod,qq);
+ qq = _mm_mul_pd(qq,gbfactor);
qq = _mm_mul_sd(qq,neg);
gbscale = _mm_mul_sd(isaprod,gbtabscale);
/* get gmx_gbdata_t */
#include "../nb_kerneltype.h"
+#include "nb_kernel430_x86_64_sse2.h"
static inline __m128d
my_invrsq_pd(__m128d x)
__m128d Y,F,G,H,Fp,VV,FF,vgb,fijC,fijD,fijR,dvdatmp,dvdasum,vctot,n0d;
__m128d xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
__m128d c6,c12,Vvdw6,Vvdw12,Vvdwtmp,Vvdwtot,vgbtot,rinvsq,rinvsix;
- __m128d fac,tabscale,gbtabscale;
+ __m128d fac,tabscale,gbtabscale,gbfactor;
__m128i n0,nnn;
const __m128d neg = {-1.0f,-1.0f};
nri = *p_nri;
ntype = *p_ntype;
nthreads = *p_nthreads;
- facel = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));
+ facel = *p_facel;
krf = *p_krf;
crf = *p_crf;
tabscl = *p_tabscale;
fac = _mm_load1_pd(&facel);
tabscale = _mm_load1_pd(&tabscl);
gbtabscale = _mm_load1_pd(&gbtabscl);
+ gbfactor = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
/* Keep compiler happy */
Vvdwtmp = _mm_setzero_pd();
vcoul = _mm_mul_pd(qq,rinv);
fscal = _mm_mul_pd(vcoul,rinv);
qq = _mm_mul_pd(isaprod,qq);
+ qq = _mm_mul_pd(qq,gbfactor);
qq = _mm_mul_pd(qq,neg);
gbscale = _mm_mul_pd(isaprod,gbtabscale);
fscal = _mm_mul_sd(vcoul,rinv);
qq = _mm_mul_sd(isaprod,qq);
qq = _mm_mul_sd(qq,neg);
+ qq = _mm_mul_sd(qq,gbfactor);
gbscale = _mm_mul_sd(isaprod,gbtabscale);
/* Load VdW parameters */
rvec r_ij,r_kj,r_kl,m,n;
real sign;
t_dih *dd;
-
- rm_pbc(xr->idef,xr->ePBC,xr->natoms,xr->box,xr->x,xr->x);
+ gmx_rmpbc_t gpbc=NULL;
+
+ gpbc = gmx_rmpbc_init(xr->idef,xr->ePBC,xr->natoms,xr->box);
+ gmx_rmpbc(gpbc,xr->box,xr->x,xr->x);
+ gmx_rmpbc_done(gpbc);
for(i=0; (i<xr->ndih); i++) {
dd=&(xr->dih[i]);
{ "Spread Q", 6 },
{ "Spread Q Bspline", 2 },
{ "Gather F", 23 },
- { "Gather F Bspline", 12 },
+ { "Gather F Bspline", 6 },
{ "3D-FFT", 8 },
{ "Convolution", 4 },
{ "Solve PME", 64 },
oenv->program_name=strdup(argvzero);
}
if (oenv->program_name == NULL)
- oenv->program_name="GROMACS";
+ oenv->program_name = strdup("GROMACS");
/* copy command line */
if (argv)
}
+void output_env_done(output_env_t oenv)
+{
+ sfree(oenv->program_name);
+ sfree(oenv->cmd_line);
+ sfree(oenv);
+}
+
+
int output_env_get_verbosity(const output_env_t oenv)
{
pr=ret=oenv->program_name;
if ((pr=strrchr(ret,'/')) != NULL)
ret=pr+1;
- /*else
- ret=ret;*/
+ /* Strip away the libtool prefix if it's still there. */
+ if(strlen(ret) > 3 && !strncmp(ret, "lt-", 3))
+ ret = ret + 3;
return ret;
}
od->nex = 0;
od->S = NULL;
+ od->M=NULL;
+ od->eig=NULL;
+ od->v=NULL;
+
od->nr = gmx_mtop_ftype_count(mtop,F_ORIRES);
if (od->nr == 0)
{
{
int ex,i,j,nrot,ord[DIM],t;
matrix S,TMP;
- static double **M=NULL,*eig,**v;
- if (M == NULL)
+ if (od->M == NULL)
{
- snew(M,DIM);
+ snew(od->M,DIM);
for(i=0; i<DIM; i++)
{
- snew(M[i],DIM);
+ snew(od->M[i],DIM);
}
- snew(eig,DIM);
- snew(v,DIM);
+ snew(od->eig_diag,DIM);
+ snew(od->v,DIM);
for(i=0; i<DIM; i++)
{
- snew(v[i],DIM);
+ snew(od->v[i],DIM);
}
}
{
for(j=0; j<DIM; j++)
{
- M[i][j] = S[i][j];
+ od->M[i][j] = S[i][j];
}
}
- jacobi(M,DIM,eig,v,&nrot);
+ jacobi(od->M,DIM,od->eig_diag,od->v,&nrot);
for(i=0; i<DIM; i++)
{
{
for(j=i+1; j<DIM; j++)
{
- if (sqr(eig[ord[j]]) > sqr(eig[ord[i]]))
+ if (sqr(od->eig_diag[ord[j]]) > sqr(od->eig_diag[ord[i]]))
{
t = ord[i];
ord[i] = ord[j];
for(i=0; i<DIM; i++)
{
- od->eig[ex*12 + i] = eig[ord[i]];
+ od->eig[ex*12 + i] = od->eig_diag[ord[i]];
}
for(i=0; i<DIM; i++)
{
for(j=0; j<DIM; j++)
{
- od->eig[ex*12 + 3 + 3*i + j] = v[j][ord[i]];
+ od->eig[ex*12 + 3 + 3*i + j] = od->v[j][ord[i]];
}
}
}
return min(min_hv2,min_ss*min_ss);
}
+/* this one is mostly harmless... */
static bool bWarnedGuess=FALSE;
int guess_ePBC(matrix box)
int *compact_unitcell_edges()
{
/* this is an index in vert[] (see calc_box_vertices) */
- static int edge[NCUCEDGE*2];
- static int hexcon[24] = { 0,9, 1,19, 2,15, 3,21,
+ /*static int edge[NCUCEDGE*2];*/
+ int *edge;
+ static const int hexcon[24] = { 0,9, 1,19, 2,15, 3,21,
4,17, 5,11, 6,23, 7,13,
8,20, 10,18, 12,16, 14,22 };
int e,i,j;
bool bFirst = TRUE;
+ snew(edge,NCUCEDGE*2);
+
if (bFirst) {
e = 0;
for(i=0; i<6; i++)
"CONECT"
};
+
+/* this is not very good,
+ but these are only used in gmx_trjconv and gmx_editconv */
static bool bTER=FALSE;
static bool bWideFormat=FALSE;
#define REMARK_SIM_BOX "REMARK THIS IS A SIMULATION BOX"
gmx_conect conect)
{
gmx_conect_t *gc = (gmx_conect_t *)conect;
- static t_symtab symtab;
- static bool bFirst=TRUE;
+ t_symtab symtab;
bool bCOMPND;
bool bConnWarn = FALSE;
char line[STRLEN+1];
if (box != NULL)
clear_mat(box);
- if (bFirst) {
- open_symtab(&symtab);
- bFirst=FALSE;
- }
+ open_symtab(&symtab);
bCOMPND=FALSE;
title[0]='\0';
* without identifier or with identical identifiers.
*/
nterread++;
- if (nterread == 2 && atoms->resinfo[0].chain == ' ') {
- set_chainid(atoms,0,nres_ter_prev,chidmax);
- chidmax = 'A';
- }
- if (nterread >= 2 &&
- (atoms->resinfo[nres_ter_prev].chain == ' ' ||
- (nres_ter_prev > 0 &&
- atoms->resinfo[nres_ter_prev-1].chain !=
- atoms->resinfo[nres_ter_prev].chain)) &&
- chidmax < 'Z') {
- chidmax++;
- set_chainid(atoms,nres_ter_prev,atoms->nres,chidmax);
+ if (NULL != atoms->resinfo) {
+ if (nterread == 2 && atoms->resinfo[0].chain == ' ') {
+ set_chainid(atoms,0,nres_ter_prev,chidmax);
+ chidmax = 'A';
+ }
+ if (nterread >= 2 &&
+ (atoms->resinfo[nres_ter_prev].chain == ' ' ||
+ (nres_ter_prev > 0 &&
+ atoms->resinfo[nres_ter_prev-1].chain !=
+ atoms->resinfo[nres_ter_prev].chain)) &&
+ chidmax < 'Z') {
+ chidmax++;
+ set_chainid(atoms,nres_ter_prev,atoms->nres,chidmax);
+ }
+ chidmax = max(chidmax,atoms->resinfo[nres_ter_prev].chain);
+ nres_ter_prev = atoms->nres;
}
- chidmax = max(chidmax,atoms->resinfo[nres_ter_prev].chain);
- nres_ter_prev = atoms->nres;
}
break;
case epdbMODEL:
}
}
+ free_symtab(&symtab);
return natom;
}
#include "warninp.h"
#include "gmx_fatal.h"
-static int inp_count = 1;
-
/* find an entry; return index, or -1 if not found */
static int search_einp(int ninp, const t_inpfile *inp, const char *name);
if (debug)
fprintf(debug,"Reading MDP file %s\n",fn);
- inp_count = 1;
+
if (!cppopts)
cppopts_given=cppopts;
else
{
sprintf(warn_buf, "%s", cpp_error(&in, status));
warning_error(wi,warn_buf);
+ *ninp = 0;
return NULL;
}
nin = lc = 0;
{
sprintf(warn_buf, "%s", cpp_error(&in, status));
warning_error(wi,warn_buf);
- return NULL;
+ *ninp = nin;
+ return inp;
}
else
ptr=0;
{
/* add a new item */
srenew(inp,++nin);
+ inp[nin-1].inp_count = 1;
inp[nin-1].count = 0;
inp[nin-1].bObsolete = FALSE;
inp[nin-1].bSet = FALSE;
} while (ptr);
cpp_close_file(&in);
- if (debug)
+ if (debug) {
fprintf(debug,"Done reading MDP file, there were %d entries in there\n",
nin);
- *ninp=nin;
+ }
+
+ *ninp = nin;
+
return inp;
}
(*inp)[i].name=strdup(name);
(*inp)[i].bSet=TRUE;
}
- (*inp)[i].count = inp_count++;
+ (*inp)[i].count = (*inp)[0].inp_count++;
(*inp)[i].bSet = TRUE;
if (debug)
fprintf(debug,"Inp %d = %s\n",(*inp)[i].count,(*inp)[i].name);
int get_eeenum(int *ninp,t_inpfile **inp,const char *name,const char **defs,
warninp_t wi)
{
- int ii,i,j,n;
+ int ii,i,j;
+ int n=0;
char buf[STRLEN];
ii=get_einp(ninp,inp,name);
break;
if (defs[i] == NULL) {
- n = sprintf(buf,"Invalid enum '%s' for variable %s, using '%s'\n",
+ n += sprintf(buf,"Invalid enum '%s' for variable %s, using '%s'\n",
(*inp)[ii].value,name,defs[0]);
- n = sprintf(buf+n,"Next time use one of:");
+ n += sprintf(buf+n,"Next time use one of:");
j=0;
while (defs[j]) {
- n = sprintf(buf+n," '%s'",defs[j]);
+ n += sprintf(buf+n," '%s'",defs[j]);
j++;
}
if (wi != NULL) {
#include "futil.h"
#include "vec.h"
-typedef struct {
- int natoms;
- t_graph *gr;
-} multi_graph;
+typedef struct gmx_rmpbc {
+ int natoms;
+ int ePBC;
+ t_graph *gr;
+} koeiepoep;
-
-void rm_pbc(t_idef *idef,int ePBC,int natoms,matrix box,rvec x[],rvec x_s[])
+gmx_rmpbc_t gmx_rmpbc_init(t_idef *idef,int ePBC,int natoms,
+ matrix box)
{
- static int ngraph=0;
- static multi_graph *mgraph=NULL;
- static bool bFirst=TRUE;
- rvec sv[SHIFTS];
- int n,i;
- bool bNeedToCopy;
+ gmx_rmpbc_t gpbc;
+
+ snew(gpbc,1);
+
+ gpbc->natoms=natoms;
if (ePBC == -1)
- ePBC = guess_ePBC(box);
+ gpbc->ePBC = guess_ePBC(box);
+ else
+ gpbc->ePBC = ePBC;
+
+ if ((ePBC != epbcNONE) && (idef->ntypes!=-1)) {
+ gpbc->gr = mk_graph(NULL,idef,0,natoms,FALSE,FALSE);
+ }
+ else {
+ fprintf(stderr,
+ "\nWarning: if there are broken molecules in the trajectory file,\n"
+ " they can not be made whole without a run input file\n\n");
+ }
+ return gpbc;
+}
- bNeedToCopy = (x != x_s);
+void gmx_rmpbc_done(gmx_rmpbc_t gpbc)
+{
+ done_graph(gpbc->gr);
+}
- if (ePBC != epbcNONE) {
- if (idef->ntypes!=-1) {
- n=-1;
- for(i=0; i<ngraph; i++)
- if (mgraph[i].natoms==natoms)
- n=i;
- if (n==-1) {
- /* make a new graph if there isn't one with this number of atoms */
- n=ngraph;
- ngraph++;
- srenew(mgraph,ngraph);
- mgraph[n].natoms=natoms;
- mgraph[n].gr=mk_graph(NULL,idef,0,natoms,FALSE,FALSE);
- }
- mk_mshift(stdout,mgraph[n].gr,ePBC,box,x);
- calc_shifts(box,sv);
- shift_x(mgraph[n].gr,box,x,x_s);
- bNeedToCopy=FALSE;
- } else if (bFirst) {
- fprintf(stderr,
- "\nWarning: if there are broken molecules in the trajectory file,\n"
- " they can not be made whole without a run input file\n\n");
- bFirst=FALSE;
- }
- }
- if (bNeedToCopy)
- for (i=0; i<natoms; i++)
+void gmx_rmpbc(gmx_rmpbc_t gpbc,matrix box,rvec x[],rvec x_s[])
+{
+ int i;
+
+ mk_mshift(stdout,gpbc->gr,gpbc->ePBC,box,x);
+ shift_x(gpbc->gr,box,x,x_s);
+ if (x != x_s)
+ for (i=0; i<gpbc->natoms; i++)
copy_rvec(x[i],x_s[i]);
}
libselection_la_SOURCES = \
compiler.c evaluate.c evaluate.h keywords.h \
+ mempool.c mempool.h \
params.c parser.c parser.h parsetree.c \
parsetree.h \
scanner.c scanner.h scanner_flex.h scanner_internal.c \
*
* \todo
* Better error handling and memory management in error situations.
- * For example, memory handling in atom-valued method parameters within common
- * subexpressions may currently result in memory leaks.
- * Also, the main compilation function leaves the selection collection in
+ * At least, the main compilation function leaves the selection collection in
* a bad state if an error occurs.
*
* \todo
- * The memory usage could be optimized.
+ * The memory usage could still be optimized.
+ * Use of memory pooling could still be extended, and a lot of redundant
+ * gmin/gmax data could be eliminated for complex arithmetic expressions.
*/
/*! \internal
* \page selcompiler Selection compilation
* function from evaluate.h.
* -# The compiler data structure is allocated for each element, and
* the fields are initialized, with the exception of the contents of
- * \c gmax and \c gmin fields.
+ * \c gmax and \c gmin fields. In reality, several passes are made
+ * to completely initialize the structure, because some flags are set
+ * recursively based on which elements refer to an element, and these
+ * flags need to be set to initialize other fields.
* .
* -# The evaluation function of all elements is replaced with the
* analyze_static() function to be able to initialize the element before
* To be able to do this for all possible values of dynamical expressions,
* special care needs to be taken with boolean expressions because they
* are short-circuiting. This is done through the
- * \c t_compiler_data::bEvalMax flag, which makes dynamic child expressions
+ * \c SEL_CDATA_EVALMAX flag, which makes dynamic child expressions
* of \c BOOL_OR expressions evaluate to empty groups, while subexpressions
* of \c BOOL_AND are evaluated to largest possible groups.
* Memory is also allocated to store the results of the evaluation.
* one reference to them. These cannot be completely processed during the
* first pass, because it is not known whether later references require
* additional evaluation of static expressions.
+ * -# Unused subexpressions are removed. For efficiency reasons (and to avoid
+ * some checks), this is actually done several times already earlier in
+ * the compilation process.
* -# Most of the processing is now done, and the next pass simply sets the
* evaluation group of root elements to the largest selection as determined
- * in pass 3. Subexpressions that were evaluated to constants are no
- * longer referenced at this time, and are removed.
- * -# The next pass eliminates some unnecessary evaluation calls from
- * subexpressions that are referenced only once, as well as initializing
- * the position calculation data for selection method elements that require
- * it. Compiler data is also freed as it is no longer needed.
+ * in pass 3. For root elements of subexpressions that should not be
+ * evaluated before they are referred to, the evaluation group/function is
+ * cleared. At the same time, position calculation data is initialized for
+ * for selection method elements that require it. Compiler data is also
+ * freed as it is no longer needed.
* -# A final pass initializes the total masses and charges in the
* \c gmx_ana_selection_t data structures.
*
* -# A selection that should be evaluated.
* These elements appear in the same order as the selections in the input.
* For these elements, \ref t_selelem::v has been set to the maximum
- * possible group that the selection can evaluate to, and
- * \ref t_selelem::cgrp has been set to use a NULL group for evaluation.
+ * possible group that the selection can evaluate to (only for dynamic
+ * selections), and \ref t_selelem::cgrp has been set to use a NULL group
+ * for evaluation.
* -# A subexpression that appears in one or more selections.
* Each selection that gives a value for a method parameter is a
* potential subexpression, as is any variable value.
* For these elements, \c t_selelem::cgrp has been set to the group
* that should be used to evaluate the subexpression.
* If \c t_selelem::cgrp is empty, the total evaluation group is not known
- * in advance. If this is the case, \c t_selelem::evaluate is also NULL.
+ * in advance or it is more efficient to evaluate the subexpression only
+ * when it is referenced. If this is the case, \c t_selelem::evaluate is
+ * also NULL.
*
* The children of the \ref SEL_ROOT elements can be used to distinguish
* the two types of root elements from each other; the rules are the same
*
* For \ref SEL_SUBEXPR elements, memory has been allocated for
* \c t_selelem::cgrp to store the group for which the expression has been
- * evaluated during the current frame.
+ * evaluated during the current frame. This is only done if full subexpression
+ * evaluation by _gmx_sel_evaluate_subexpr() is needed; the other evaluation
+ * functions do not require this memory.
*
* \ref SEL_SUBEXPRREF elements are used to describe references to
* subexpressions. They have always a single child, which is the
* \ref SEL_SUBEXPR element being referenced.
*
- * If a subexpression is used only once and can be evaluated statically,
- * the evaluation has been optimized by setting the child of the
- * \ref SEL_SUBEXPR element to evaluate the value of \ref SEL_SUBEXPRREF
- * directly. In this case, the evaluation routines for the \ref SEL_SUBEXPRREF
- * and \ref SEL_SUBEXPR elements only propagate some status information,
- * but do not unnecessarily copy the values.
+ * If a subexpression is used only once, the evaluation has been optimized by
+ * setting the child of the \ref SEL_SUBEXPR element to evaluate the value of
+ * \ref SEL_SUBEXPRREF directly (in the case of memory pooling, this is managed
+ * by the evaluation functions). In such cases, the evaluation routines for the
+ * \ref SEL_SUBEXPRREF and \ref SEL_SUBEXPR elements only propagate some status
+ * information, but do not unnecessarily copy the values.
*
*
* \subsection selcompiler_tree_bool Boolean elements
* The static parts of the expressions have been evaluated, and are placed
* in the first child. These are followed by the dynamic expressions, in the
* order provided by the user.
+ *
+ *
+ * \subsection selcompiler_tree_arith Arithmetic elements
+ *
+ * Constant and static expressions in \ref SEL_ARITHMETIC elements have been
+ * calculated.
+ * Currently, no other processing is done.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include "evaluate.h"
#include "keywords.h"
+#include "mempool.h"
#include "selcollection.h"
#include "selelem.h"
/*! \internal \brief
- * Internal data structure used by the compiler.
+ * Compiler flags.
*/
-typedef struct t_compiler_data
+enum
{
- /** The real evaluation method. */
- sel_evalfunc evaluate;
/*! \brief
- * Whether the element is a method parameter.
+ * Whether a subexpression needs to evaluated for all atoms.
*
* This flag is set for \ref SEL_SUBEXPR elements that are used to
- * evaluate non-atom-valued selection method parameters.
+ * evaluate non-atom-valued selection method parameters, as well as
+ * those that are used directly as values of selections.
*/
- bool bMethodParam;
+ SEL_CDATA_FULLEVAL = 1,
/*! \brief
- * TRUE if the whole subexpression should be treated static.
+ * Whether the whole subexpression should be treated as static.
*
* This flag is always FALSE if \ref SEL_DYNAMIC is set for the element,
* but it is also FALSE for static elements within common subexpressions.
*/
- bool bStatic;
- /** TRUE if the subexpression will always be evaluated with the same group. */
- bool bStaticEval;
- /** TRUE if the compiler evaluation routine should return the maximal selection. */
- bool bEvalMax;
+ SEL_CDATA_STATIC = 2,
+ /** Whether the subexpression will always be evaluated in the same group. */
+ SEL_CDATA_STATICEVAL = 4,
+ /** Whether the compiler evaluation routine should return the maximal selection. */
+ SEL_CDATA_EVALMAX = 8,
+ /** Whether memory has been allocated for \p gmin and \p gmax. */
+ SEL_CDATA_MINMAXALLOC = 16,
+ /** Whether subexpressions use simple pass evaluation functions. */
+ SEL_CDATA_SIMPLESUBEXPR = 32,
+ /** Whether this expressions is a part of a common subexpression. */
+ SEL_CDATA_COMMONSUBEXPR = 64
+};
+
+/*! \internal \brief
+ * Internal data structure used by the compiler.
+ */
+typedef struct t_compiler_data
+{
+ /** The real evaluation method. */
+ sel_evalfunc evaluate;
+ /** Flags for specifying how to treat this element during compilation. */
+ int flags;
/** Smallest selection that can be selected by the subexpression. */
gmx_ana_index_t *gmin;
/** Largest selection that can be selected by the subexpression. */
gmx_ana_index_t *gmax;
- /** TRUE if memory has been allocated for \p gmin and \p gmax. */
- bool bMinMaxAlloc;
} t_compiler_data;
* COMPILER UTILITY FUNCTIONS
********************************************************************/
+static void
+print_group_info(FILE *fp, const char *name, t_selelem *sel, gmx_ana_index_t *g)
+{
+ fprintf(fp, " %s=", name);
+ if (!g)
+ {
+ fprintf(fp, "(null)");
+ }
+ else if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+ {
+ fprintf(fp, "(%d atoms, %p)", g->isize, (void*)g);
+ }
+ else if (sel->v.type == GROUP_VALUE && g == sel->v.u.g)
+ {
+ fprintf(fp, "(static, %p)", (void*)g);
+ }
+ else
+ {
+ fprintf(fp, "%p", (void*)g);
+ }
+}
+
+/*!
+ * \param[in] fp File handle to receive the output.
+ * \param[in] sel Selection element to print.
+ * \param[in] level Indentation level, starting from zero.
+ */
+void
+_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level)
+{
+ if (!sel->cdata)
+ {
+ return;
+ }
+ fprintf(fp, "%*c cdata: flg=", level*2+1, ' ');
+ if (sel->cdata->flags & SEL_CDATA_FULLEVAL)
+ {
+ fprintf(fp, "F");
+ }
+ if (!(sel->cdata->flags & SEL_CDATA_STATIC))
+ {
+ fprintf(fp, "D");
+ }
+ if (sel->cdata->flags & SEL_CDATA_STATICEVAL)
+ {
+ fprintf(fp, "S");
+ }
+ if (sel->cdata->flags & SEL_CDATA_EVALMAX)
+ {
+ fprintf(fp, "M");
+ }
+ if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+ {
+ fprintf(fp, "A");
+ }
+ if (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+ {
+ fprintf(fp, "Ss");
+ }
+ if (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+ {
+ fprintf(fp, "Sc");
+ }
+ if (!sel->cdata->flags)
+ {
+ fprintf(fp, "0");
+ }
+ fprintf(fp, " eval=");
+ _gmx_sel_print_evalfunc_name(fp, sel->cdata->evaluate);
+ print_group_info(fp, "gmin", sel, sel->cdata->gmin);
+ print_group_info(fp, "gmax", sel, sel->cdata->gmax);
+ fprintf(fp, "\n");
+}
+
/*!
* \param sel Selection to free.
*
if (sel->cdata)
{
sel->evaluate = sel->cdata->evaluate;
- if (sel->cdata->bMinMaxAlloc)
+ if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
{
sel->cdata->gmin->name = NULL;
sel->cdata->gmax->name = NULL;
{
int nalloc;
+ if (sel->mempool)
+ {
+ return TRUE;
+ }
/* Find out the number of elements to allocate */
if (sel->flags & SEL_SINGLEVAL)
{
nalloc = 1;
}
/* Allocate memory for sel->v.u if needed */
- if ((sel->flags & SEL_ALLOCVAL)
- || (sel->type == SEL_SUBEXPRREF && sel->u.param
- && (sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL))))
+ if (sel->flags & SEL_ALLOCVAL)
{
_gmx_selvalue_reserve(&sel->v, nalloc);
}
}
}
+
/********************************************************************
- * SUBEXPRESSION EXTRACTION COMPILER PASS
+ * SUBEXPRESSION PROCESSING
********************************************************************/
+/*! \brief
+ * Reverses the chain of selection elements starting at \p root.
+ *
+ * \param root First selection in the whole selection chain.
+ * \returns The new first element for the chain.
+ */
+static t_selelem *
+reverse_selelem_chain(t_selelem *root)
+{
+ t_selelem *item;
+ t_selelem *prev;
+ t_selelem *next;
+
+ prev = NULL;
+ item = root;
+ while (item)
+ {
+ next = item->next;
+ item->next = prev;
+ prev = item;
+ item = next;
+ }
+ return prev;
+}
+
+/*! \brief
+ * Removes subexpressions that don't have any references.
+ *
+ * \param root First selection in the whole selection chain.
+ * \returns The new first element for the chain.
+ *
+ * The elements are processed in reverse order to correctly detect
+ * subexpressions only referred to by other subexpressions.
+ */
+static t_selelem *
+remove_unused_subexpressions(t_selelem *root)
+{
+ t_selelem *item;
+ t_selelem *prev;
+ t_selelem *next;
+
+ root = reverse_selelem_chain(root);
+ while (root->child->type == SEL_SUBEXPR && root->child->refcount == 1)
+ {
+ next = root->next;
+ _gmx_selelem_free(root);
+ root = next;
+ }
+ prev = root;
+ item = root->next;
+ while (item)
+ {
+ next = item->next;
+ if (item->child->type == SEL_SUBEXPR && item->child->refcount == 1)
+ {
+ prev->next = next;
+ _gmx_selelem_free(item);
+ }
+ else
+ {
+ prev = item;
+ }
+ item = next;
+ }
+ return reverse_selelem_chain(root);
+}
+
/*! \brief
* Creates a name with a running number for a subexpression.
*
* Processes and extracts subexpressions from a given selection subtree.
*
* \param sel Root of the subtree to process.
- * \param[in] gall Index group that contains all the input atoms.
- * \param subexprn Pointer to a subexpression counter.
+ * \param subexprn Pointer to a subexpression counter.
* \returns Pointer to a chain of subselections, or NULL if none were found.
*
* This function finds recursively all \ref SEL_SUBEXPRREF elements below
* of these root elements.
*/
static t_selelem *
-extract_item_subselections(t_selelem *sel, gmx_ana_index_t *gall, int *subexprn)
+extract_item_subselections(t_selelem *sel, int *subexprn)
{
t_selelem *root;
t_selelem *subexpr;
{
if (!root)
{
- root = subexpr = extract_item_subselections(child, gall, subexprn);
+ root = subexpr = extract_item_subselections(child, subexprn);
}
else
{
- subexpr->next = extract_item_subselections(child, gall, subexprn);
+ subexpr->next = extract_item_subselections(child, subexprn);
}
while (subexpr && subexpr->next)
{
subexpr = subexpr->next;
}
- /* The latter check excludes variable references */
- if (child->type == SEL_SUBEXPRREF && child->child->type != SEL_SUBEXPR)
+ /* The latter check excludes variable references.
+ * It also excludes subexpression elements that have already been
+ * processed, because they are given a name when they are first
+ * encountered.
+ * TODO: There should be a more robust mechanism (probably a dedicated
+ * flag) for detecting parser-generated subexpressions than relying on
+ * a NULL name field. */
+ if (child->type == SEL_SUBEXPRREF && (child->child->type != SEL_SUBEXPR
+ || child->child->name == NULL))
{
/* Create the root element for the subexpression */
if (!root)
subexpr->next = _gmx_selelem_create(SEL_ROOT);
subexpr = subexpr->next;
}
- /* Set the evaluation group to all atoms */
- if (!(child->flags & SEL_ATOMVAL))
+ /* Create the subexpression element and/or
+ * move the actual subexpression under the created element. */
+ if (child->child->type != SEL_SUBEXPR)
+ {
+ subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
+ _gmx_selelem_set_vtype(subexpr->child, child->v.type);
+ subexpr->child->child = child->child;
+ child->child = subexpr->child;
+ }
+ else
{
- gmx_ana_index_set(&subexpr->u.cgrp, gall->isize, gall->index, NULL, 0);
+ subexpr->child = child->child;
}
- /* Create the subexpression element */
- subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
- _gmx_selelem_set_vtype(subexpr->child, child->v.type);
create_subexpression_name(subexpr->child, ++*subexprn);
- /* Move the actual subexpression under the created element */
- subexpr->child->child = child->child;
- child->child = subexpr->child;
- subexpr->child->refcount = 2;
+ subexpr->child->refcount++;
/* Set the flags for the created elements */
subexpr->flags |= (child->flags & SEL_VALFLAGMASK);
subexpr->child->flags |= (child->flags & SEL_VALFLAGMASK);
* Extracts subexpressions of the selection chain.
*
* \param sel First selection in the whole selection chain.
- * \param[in] gall Index group that contains all the input atoms.
* \returns The new first element for the chain.
*
* Finds all the subexpressions (and their subexpressions) in the
* refer to them.
*/
static t_selelem *
-extract_subexpressions(t_selelem *sel, gmx_ana_index_t *gall)
+extract_subexpressions(t_selelem *sel)
{
t_selelem *root, *item, *next;
int subexprn;
next = sel;
while (next)
{
- item = extract_item_subselections(next, gall, &subexprn);
+ item = extract_item_subselections(next, &subexprn);
if (item)
{
if (!root)
return root;
}
+
/********************************************************************
- * BOOLEAN OPERATION REORDERING COMPILER PASS
+ * BOOLEAN OPERATION REORDERING
********************************************************************/
/*! \brief
}
}
+
/********************************************************************
- * EVALUATION PREPARATION COMPILER PASS
+ * ARITHMETIC EXPRESSION PROCESSING
********************************************************************/
/*! \brief
- * Initializes the evaluation groups for the selections.
+ * Processes arithmetic expressions to simplify and speed up evaluation.
*
- * \param[in,out] sc Selection collection data.
+ * \param sel Root of the selection subtree to process.
*
- * The evaluation group of each \ref SEL_ROOT element corresponding to a
- * selection in \p sc is set to \p gall.
+ * Currently, this function only converts integer constants to reals
+ * within arithmetic expressions.
*/
-static void
-initialize_evalgrps(gmx_ana_selcollection_t *sc)
+static bool
+optimize_arithmetic_expressions(t_selelem *sel)
{
- t_selelem *item;
- int i;
+ t_selelem *child;
+ bool bOk;
- /* Initialize the output */
- for (i = 0; i < sc->nr; ++i)
+ /* Do recursively for children. */
+ if (sel->type != SEL_SUBEXPRREF)
{
- item = sc->sel[i]->selelem;
- /* Set the evaluation group to all atoms */
- gmx_ana_index_set(&item->u.cgrp, sc->gall.isize, sc->gall.index,
- item->u.cgrp.name, 0);
+ child = sel->child;
+ while (child)
+ {
+ bOk = optimize_arithmetic_expressions(child);
+ if (!bOk)
+ {
+ return bOk;
+ }
+ child = child->next;
+ }
}
+
+ if (sel->type != SEL_ARITHMETIC)
+ {
+ return TRUE;
+ }
+
+ /* Convert integer constants to reals. */
+ child = sel->child;
+ while (child)
+ {
+ if (child->v.type == INT_VALUE)
+ {
+ real *r;
+
+ if (child->type != SEL_CONST)
+ {
+ gmx_impl("Non-constant integer expressions not implemented in arithmetic evaluation");
+ return FALSE;
+ }
+ snew(r, 1);
+ r[0] = child->v.u.i[0];
+ sfree(child->v.u.i);
+ child->v.u.r = r;
+ child->v.type = REAL_VALUE;
+ }
+ else if (child->v.type != REAL_VALUE)
+ {
+ gmx_bug("Internal error");
+ return FALSE;
+ }
+ child = child->next;
+ }
+ return TRUE;
}
+
+/********************************************************************
+ * EVALUATION PREPARATION COMPILER
+ ********************************************************************/
+
/*! \brief
- * Prepares the selection (sub)tree for evaluation.
+ * Sets the evaluation functions for the selection (sub)tree.
*
- * \param[in,out] sel Root of the selection subtree to prepare.
+ * \param[in,out] sel Root of the selection subtree to process.
* \returns TRUE on success, FALSE if any subexpression fails.
*
* This function sets the evaluation function (\c t_selelem::evaluate)
* for the selection elements.
- * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
- * structure if required.
*/
static bool
-init_item_evaluation(t_selelem *sel)
+init_item_evalfunc(t_selelem *sel)
{
- t_selelem *child;
-
- /* Process children */
+ /* Process children. */
if (sel->type != SEL_SUBEXPRREF)
{
+ t_selelem *child;
+
child = sel->child;
while (child)
{
- if (!init_item_evaluation(child))
+ if (!init_item_evalfunc(child))
{
return FALSE;
}
}
}
- /* Make sure that the group/position structure is allocated */
- if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
- {
- if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
- {
- _gmx_selvalue_reserve(&sel->v, 1);
- sel->v.nr = 1;
- }
- }
-
/* Set the evaluation function */
switch (sel->type)
{
break;
case SEL_EXPRESSION:
+ if (!(sel->flags & SEL_DYNAMIC) && sel->u.expr.method
+ && sel->u.expr.method->init_frame)
+ {
+ sel->flags |= SEL_INITFRAME;
+ }
sel->evaluate = &_gmx_sel_evaluate_method;
break;
+ case SEL_ARITHMETIC:
+ sel->evaluate = &_gmx_sel_evaluate_arithmetic;
+ break;
+
case SEL_MODIFIER:
if (sel->v.type != NO_VALUE)
{
break;
case SEL_SUBEXPR:
- sel->evaluate = &_gmx_sel_evaluate_subexpr;
+ sel->evaluate = (sel->refcount == 2
+ ? &_gmx_sel_evaluate_subexpr_simple
+ : &_gmx_sel_evaluate_subexpr);
break;
case SEL_SUBEXPRREF:
sel->name = sel->child->name;
- sel->evaluate = &_gmx_sel_evaluate_subexprref;
+ sel->evaluate = (sel->child->refcount == 2
+ ? &_gmx_sel_evaluate_subexprref_simple
+ : &_gmx_sel_evaluate_subexprref);
break;
}
return TRUE;
}
+/*! \brief
+ * Sets the memory pool for selection elements that can use it.
+ *
+ * \param sel Root of the selection subtree to process.
+ * \param[in] mempool Memory pool to use.
+ */
+static void
+setup_memory_pooling(t_selelem *sel, gmx_sel_mempool_t *mempool)
+{
+ if (sel->type != SEL_SUBEXPRREF)
+ {
+ t_selelem *child;
+
+ child = sel->child;
+ while (child)
+ {
+ if ((sel->type == SEL_BOOLEAN && (child->flags & SEL_DYNAMIC))
+ || (sel->type == SEL_ARITHMETIC && child->type != SEL_CONST
+ && !(child->flags & SEL_SINGLEVAL))
+ || (sel->type == SEL_SUBEXPR && sel->refcount > 2))
+ {
+ child->mempool = mempool;
+ if (child->type == SEL_SUBEXPRREF
+ && child->child->refcount == 2)
+ {
+ child->child->child->mempool = mempool;
+ }
+ }
+ setup_memory_pooling(child, mempool);
+ child = child->next;
+ }
+ }
+}
+
+/*! \brief
+ * Prepares the selection (sub)tree for evaluation.
+ *
+ * \param[in,out] sel Root of the selection subtree to prepare.
+ *
+ * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
+ * structure if required.
+ */
+static void
+init_item_evaloutput(t_selelem *sel)
+{
+ /* Process children. */
+ if (sel->type != SEL_SUBEXPRREF)
+ {
+ t_selelem *child;
+
+ child = sel->child;
+ while (child)
+ {
+ init_item_evaloutput(child);
+ child = child->next;
+ }
+ }
+
+ if (sel->type == SEL_SUBEXPR && sel->refcount == 2)
+ {
+ sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+ {
+ _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+ }
+ }
+ else if (sel->type == SEL_SUBEXPR
+ && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
+ {
+ sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
+ sel->cdata->evaluate = sel->evaluate;
+ sel->child->mempool = NULL;
+ sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+ {
+ _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+ }
+ }
+ else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
+ {
+ if (sel->v.u.ptr)
+ {
+ _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+ _gmx_selelem_free_values(sel->child->child);
+ sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ sel->child->child->flags |= (sel->flags & SEL_ALLOCDATA);
+ _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
+ }
+ else if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+ {
+ _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
+ }
+ sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ }
+
+ /* Make sure that the group/position structure is allocated. */
+ if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
+ {
+ if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+ {
+ _gmx_selvalue_reserve(&sel->v, 1);
+ sel->v.nr = 1;
+ }
+ }
+}
+
/********************************************************************
- * COMPILER DATA INITIALIZATION PASS
+ * COMPILER DATA INITIALIZATION
********************************************************************/
/*! \brief
sel->cdata->evaluate = sel->evaluate;
/* Initialize the flags */
- sel->cdata->bMethodParam = FALSE;
- sel->cdata->bStatic = !(sel->flags & SEL_DYNAMIC);
- sel->cdata->bStaticEval = TRUE;
- sel->cdata->bEvalMax = (sel->type == SEL_SUBEXPR ? TRUE : FALSE);
- /* Set the method parameter flag for non-atom-valued parameters */
+ sel->cdata->flags = SEL_CDATA_STATICEVAL;
+ if (!(sel->flags & SEL_DYNAMIC))
+ {
+ sel->cdata->flags |= SEL_CDATA_STATIC;
+ }
+ if (sel->type == SEL_SUBEXPR)
+ {
+ sel->cdata->flags |= SEL_CDATA_EVALMAX;
+ }
+ /* Set the full evaluation flag for subexpressions that require it;
+ * the subexpression has already been initialized, so we can simply
+ * access its compilation flags.*/
if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
{
child = sel->child;
while (child)
{
- if (!(child->flags & SEL_ATOMVAL))
+ if (!(child->flags & SEL_ATOMVAL) && child->child)
{
- child->child->cdata->bMethodParam = TRUE;
+ child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
}
child = child->next;
}
}
+ else if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPRREF)
+ {
+ sel->child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
+ }
/* Initialize children */
if (sel->type != SEL_SUBEXPRREF)
child = sel->child;
while (child)
{
- child->cdata->bEvalMax = bEvalMax;
- if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
+ if (bEvalMax)
+ {
+ child->cdata->flags |= SEL_CDATA_EVALMAX;
+ }
+ else if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
{
- child->child->cdata->bEvalMax = !bEvalMax;
+ child->child->cdata->flags |= SEL_CDATA_EVALMAX;
}
child = child->next;
}
child = sel->child;
while (child)
{
- child->cdata->bEvalMax = TRUE;
+ child->cdata->flags |= SEL_CDATA_EVALMAX;
child = child->next;
}
}
-
- /* Initialize the minimum and maximum evaluation groups */
- sel->cdata->bMinMaxAlloc = FALSE;
- if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
- {
- if (sel->type == SEL_SUBEXPR)
- {
- sel->cdata->gmin = sel->child->cdata->gmin;
- sel->cdata->gmax = sel->child->cdata->gmax;
- }
- else if (sel->v.type == GROUP_VALUE && sel->cdata->bStatic)
- {
- sel->cdata->gmin = sel->v.u.g;
- sel->cdata->gmax = sel->v.u.g;
- }
- else
- {
- sel->cdata->bMinMaxAlloc = TRUE;
- snew(sel->cdata->gmin, 1);
- snew(sel->cdata->gmax, 1);
- }
- }
}
/*! \brief
{
t_selelem *child;
- /* Non-atom-valued method parameters should always have bStaticEval,
+ /* Subexpressions with full evaluation should always have bStaticEval,
* so don't do anything if a reference to them is encountered. */
- if (sel->type == SEL_SUBEXPRREF && sel->child->cdata->bMethodParam)
+ if (sel->type == SEL_SUBEXPRREF
+ && (sel->child->cdata->flags & SEL_CDATA_FULLEVAL))
{
return;
}
/* Propagate the bStaticEval flag to children if it is not set */
- if (!sel->cdata->bStaticEval)
+ if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
{
child = sel->child;
while (child)
if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
|| (child->flags & SEL_ATOMVAL))
{
- if (child->cdata->bStaticEval)
+ if (child->cdata->flags & SEL_CDATA_STATICEVAL)
{
- child->cdata->bStaticEval = FALSE;
+ child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
init_item_staticeval(child);
}
}
}
while (child)
{
- child->cdata->bStaticEval = FALSE;
+ child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
child = child->next;
}
}
}
}
+/*! \brief
+ * Initializes compiler flags for subexpressions.
+ *
+ * \param sel Root of the selection subtree to process.
+ */
+static void
+init_item_subexpr_flags(t_selelem *sel)
+{
+ if (sel->type == SEL_SUBEXPR)
+ {
+ if (sel->refcount == 2)
+ {
+ sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
+ }
+ else if (!(sel->cdata->flags & SEL_CDATA_FULLEVAL))
+ {
+ sel->cdata->flags |= SEL_CDATA_COMMONSUBEXPR;
+ }
+ }
+ else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
+ {
+ sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
+ }
+
+ /* Process children, but only follow subexpression references if the
+ * common subexpression flag needs to be propagated. */
+ if (sel->type != SEL_SUBEXPRREF
+ || ((sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+ && sel->child->refcount > 2))
+ {
+ t_selelem *child = sel->child;
+
+ while (child)
+ {
+ if (!(child->cdata->flags & SEL_CDATA_COMMONSUBEXPR))
+ {
+ if (sel->type != SEL_EXPRESSION || (child->flags & SEL_ATOMVAL))
+ {
+ child->cdata->flags |=
+ (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR);
+ }
+ init_item_subexpr_flags(child);
+ }
+ child = child->next;
+ }
+ }
+}
+
+/*! \brief
+ * Initializes the gmin and gmax fields of the compiler data structure.
+ *
+ * \param sel Root of the selection subtree to process.
+ */
+static void
+init_item_minmax_groups(t_selelem *sel)
+{
+ /* Process children. */
+ if (sel->type != SEL_SUBEXPRREF)
+ {
+ t_selelem *child;
+
+ child = sel->child;
+ while (child)
+ {
+ init_item_minmax_groups(child);
+ child = child->next;
+ }
+ }
+
+ /* Initialize the minimum and maximum evaluation groups. */
+ if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
+ {
+ if (sel->v.type == GROUP_VALUE
+ && (sel->cdata->flags & SEL_CDATA_STATIC))
+ {
+ sel->cdata->gmin = sel->v.u.g;
+ sel->cdata->gmax = sel->v.u.g;
+ }
+ else if (sel->type == SEL_SUBEXPR
+ && ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+ || (sel->cdata->flags & SEL_CDATA_FULLEVAL)))
+ {
+ sel->cdata->gmin = sel->child->cdata->gmin;
+ sel->cdata->gmax = sel->child->cdata->gmax;
+ }
+ else
+ {
+ sel->cdata->flags |= SEL_CDATA_MINMAXALLOC;
+ snew(sel->cdata->gmin, 1);
+ snew(sel->cdata->gmax, 1);
+ }
+ }
+}
+
/********************************************************************
- * STATIC ANALYSIS COMPILER PASS
+ * EVALUATION GROUP INITIALIZATION
+ ********************************************************************/
+
+/*! \brief
+ * Initializes evaluation groups for root items.
+ *
+ * \param[in,out] sc Selection collection data.
+ *
+ * The evaluation group of each \ref SEL_ROOT element corresponding to a
+ * selection in \p sc is set to \p gall. The same is done for \ref SEL_ROOT
+ * elements corresponding to subexpressions that need full evaluation.
+ */
+static void
+initialize_evalgrps(gmx_ana_selcollection_t *sc)
+{
+ t_selelem *root;
+
+ root = sc->root;
+ while (root)
+ {
+ if (root->child->type != SEL_SUBEXPR
+ || (root->child->cdata->flags & SEL_CDATA_FULLEVAL))
+ {
+ gmx_ana_index_set(&root->u.cgrp, sc->gall.isize, sc->gall.index,
+ root->u.cgrp.name, 0);
+ }
+ root = root->next;
+ }
+}
+
+
+/********************************************************************
+ * STATIC ANALYSIS
********************************************************************/
/*! \brief
{
t_selelem *child;
- sel->cdata->bStatic = (!bDynamic && !(sel->flags & SEL_DYNAMIC));
+ if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
+ {
+ sel->cdata->flags |= SEL_CDATA_STATIC;
+ }
+ else
+ {
+ sel->cdata->flags &= ~SEL_CDATA_STATIC;
+ }
child = sel->child;
while (child)
{
if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
|| (child->u.param->flags & SPAR_ATOMVAL))
{
- mark_subexpr_dynamic(child, bDynamic);
+ mark_subexpr_dynamic(child, bDynamic);
+ }
+ child = child->next;
+ }
+}
+
+/*! \brief
+ * Frees memory for subexpressions that are no longer needed.
+ *
+ * \param sel Selection subtree to check.
+ *
+ * Checks whether the subtree rooted at \p sel refers to any \ref SEL_SUBEXPR
+ * elements that are not referred to by anything else except their own root
+ * element. If such elements are found, all memory allocated for them is freed
+ * except the actual element. The element is left because otherwise a dangling
+ * pointer would be left at the root element, which is not traversed by this
+ * function. Later compilation passes remove the stub elements.
+ */
+static void
+release_subexpr_memory(t_selelem *sel)
+{
+ if (sel->type == SEL_SUBEXPR)
+ {
+ if (sel->refcount == 2)
+ {
+ release_subexpr_memory(sel->child);
+ sel->name = NULL;
+ _gmx_selelem_free_chain(sel->child);
+ _gmx_selelem_free_values(sel);
+ _gmx_selelem_free_exprdata(sel);
+ _gmx_selelem_free_compiler_data(sel);
+ sel->child = NULL;
+ }
+ }
+ else
+ {
+ t_selelem *child;
+
+ child = sel->child;
+ while (child)
+ {
+ release_subexpr_memory(child);
+ child = child->next;
}
- child = child->next;
}
}
static void
make_static(t_selelem *sel)
{
+ /* If this is a subexpression reference and the data is stored in the
+ * child, we transfer data ownership before doing anything else. */
+ if (sel->type == SEL_SUBEXPRREF
+ && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
+ {
+ if (sel->child->child->flags & SEL_ALLOCDATA)
+ {
+ sel->flags |= SEL_ALLOCDATA;
+ sel->child->child->flags &= ~SEL_ALLOCDATA;
+ }
+ if (sel->child->child->flags & SEL_ALLOCVAL)
+ {
+ sel->flags |= SEL_ALLOCVAL;
+ sel->v.nalloc = sel->child->child->v.nalloc;
+ sel->child->child->flags &= ~SEL_ALLOCVAL;
+ sel->child->child->v.nalloc = -1;
+ }
+ }
+ /* When we reach here for parameter elements, the value is already
+ * stored in the parent element, so make sure that it is not freed
+ * through this element. */
+ if (sel->type == SEL_SUBEXPRREF && sel->u.param)
+ {
+ sel->u.param->val.nalloc = sel->v.nalloc;
+ sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ sel->v.nalloc = -1;
+ }
+ /* Free the children. */
+ release_subexpr_memory(sel);
+ _gmx_selelem_free_chain(sel->child);
+ sel->child = NULL;
/* Free the expression data as it is no longer needed */
_gmx_selelem_free_exprdata(sel);
/* Make the item static */
sel->type = SEL_CONST;
sel->evaluate = NULL;
sel->cdata->evaluate = NULL;
- /* Free the children */
- _gmx_selelem_free_chain(sel->child);
- sel->child = NULL;
/* Set the group value.
- * None of the elements for which this function may be called uses
- * the cgrp group, so we can simply overwrite the contents without
- * worrying about memory leaks. */
+ * free_exprdata above frees the cgrp group, so we can just override it. */
if (sel->v.type == GROUP_VALUE)
{
gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, NULL, 0);
}
/*! \brief
- * Evaluates a constant expression during analyze_static() and analyze_static2().
+ * Evaluates a constant expression during analyze_static().
*
* \param[in] data Evaluation data.
* \param[in,out] sel Selection to process.
&& (bAtomVal || !(sel->flags & SEL_METHODINIT)))
{
sel->flags |= SEL_METHODINIT;
- /* The allocation flags are cleared first to not to free anything if
- * initialization fails. */
- child = sel->child;
- if (sel->type == SEL_MODIFIER && sel->v.type != NO_VALUE)
- {
- child = child->next;
- }
- while (child)
- {
- child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
- child = child->next;
- }
rc = sel->u.expr.method->init(top, sel->u.expr.method->nparams,
sel->u.expr.method->param, sel->u.expr.mdata);
if (rc != 0)
{
return rc;
}
+ if (sel->v.type != POS_VALUE && sel->v.type != GROUP_VALUE)
+ {
+ alloc_selection_data(sel, isize, TRUE);
+ }
}
else
{
/* Find the last static subexpression */
child = sel->child;
- while (child->next && child->next->cdata->bStatic)
+ while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
{
child = child->next;
}
- if (!child->cdata->bStatic)
+ if (!(child->cdata->flags & SEL_CDATA_STATIC))
{
return 0;
}
_gmx_selvalue_reserve(&child->v, 1);
gmx_ana_index_copy(child->v.u.g, sel->v.u.g, TRUE);
init_item_compilerdata(child);
- child->cdata->bStaticEval = sel->cdata->bStaticEval;
+ init_item_minmax_groups(child);
+ child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
+ child->cdata->flags |= sel->cdata->flags & SEL_CDATA_STATICEVAL;
child->next = next;
sel->child = child;
}
* time copying the group. */
child->evaluate = NULL;
if (sel->u.boolt == BOOL_NOT
- || (sel->cdata->bStaticEval && sel->u.boolt == BOOL_OR))
+ || ((sel->cdata->flags & SEL_CDATA_STATICEVAL)
+ && sel->u.boolt == BOOL_OR))
{
child->cdata->evaluate = NULL;
}
child = child->next;
}
/* Update the static part if other expressions limit it */
- if (sel->child->cdata->bStatic
+ if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
&& sel->child->v.u.g->isize > gmax->isize)
{
gmx_ana_index_copy(sel->child->v.u.g, gmax, FALSE);
}
/* Update the static part if other expressions have static parts
* that are not included. */
- if (sel->child->cdata->bStatic
+ if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
&& sel->child->v.u.g->isize < gmin->isize)
{
gmx_ana_index_reserve(sel->child->v.u.g, gmin->isize);
* expressions have been evaluated.
* The above is exactly true only for elements other than subexpressions:
* another pass is required for subexpressions that are referred to more than
- * once to evaluate the static parts.
- * This second pass is performed by analyze_static2().
- *
- * \see analyze_static2()
+ * once and whose evaluation group is not known in advance.
*/
static int
analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
{
t_selelem *child, *next;
- gmx_ana_index_t gmin, gmax;
- bool bDelayAlloc;
+ bool bDoMinMax;
int rc;
- gmx_ana_index_clear(&gmin);
- gmx_ana_index_clear(&gmax);
- bDelayAlloc = FALSE;
-
if (sel->type != SEL_ROOT && g)
{
- bDelayAlloc = !alloc_selection_data(sel, g->isize, FALSE);
+ alloc_selection_data(sel, g->isize, FALSE);
+ }
+
+ bDoMinMax = (sel->cdata->flags & SEL_CDATA_MINMAXALLOC);
+ if (sel->type != SEL_SUBEXPR && bDoMinMax)
+ {
+ gmx_ana_index_deinit(sel->cdata->gmin);
+ gmx_ana_index_deinit(sel->cdata->gmax);
}
/* TODO: This switch is awfully long... */
if (!(sel->flags & SEL_DYNAMIC))
{
rc = sel->cdata->evaluate(data, sel, g);
- if (rc == 0 && sel->cdata->bStatic)
+ if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
{
make_static(sel);
}
{
rc = sel->cdata->evaluate(data, sel, g);
}
- gmx_ana_index_copy(&gmax, g, TRUE);
+ if (bDoMinMax)
+ {
+ gmx_ana_index_copy(sel->cdata->gmax, g, TRUE);
+ }
}
break;
if (!(sel->flags & SEL_DYNAMIC))
{
rc = sel->cdata->evaluate(data, sel, g);
- if (rc == 0 && sel->cdata->bStatic)
+ if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
{
make_static(sel);
}
}
/* Evaluate minimal and maximal selections */
- evaluate_boolean_minmax_grps(sel, g, &gmin, &gmax);
+ evaluate_boolean_minmax_grps(sel, g, sel->cdata->gmin,
+ sel->cdata->gmax);
+ }
+ break;
+
+ case SEL_ARITHMETIC:
+ rc = sel->cdata->evaluate(data, sel, g);
+ if (rc != 0)
+ {
+ return rc;
+ }
+ if (!(sel->flags & SEL_DYNAMIC))
+ {
+ if (sel->cdata->flags & SEL_CDATA_STATIC)
+ {
+ make_static(sel);
+ }
+ }
+ else if (bDoMinMax)
+ {
+ gmx_ana_index_copy(sel->cdata->gmax, g, TRUE);
}
break;
break;
case SEL_SUBEXPR:
- if (sel->u.cgrp.isize == 0)
+ if (sel->cdata->flags & (SEL_CDATA_SIMPLESUBEXPR | SEL_CDATA_FULLEVAL))
+ {
+ rc = sel->cdata->evaluate(data, sel, g);
+ _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+ }
+ else if (sel->u.cgrp.isize == 0)
{
gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
- if (bDelayAlloc)
- {
- /* We need to evaluate the child before we can allocate the
- * memory. */
- rc = sel->child->evaluate(data, sel->child, g);
- if (rc != 0)
- {
- return rc;
- }
- alloc_selection_data(sel, g->isize, TRUE);
- /* Do not evaluate the child again */
- sel->child->evaluate = NULL;
- rc = sel->cdata->evaluate(data, sel, g);
- sel->child->evaluate = &analyze_static;
- }
- else
+ rc = sel->cdata->evaluate(data, sel, g);
+ if (bDoMinMax)
{
- alloc_selection_data(sel->child, g->isize, FALSE);
- rc = sel->cdata->evaluate(data, sel, g);
+ gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, TRUE);
+ gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, TRUE);
}
}
else
{
isize += sel->u.cgrp.isize;
gmx_ana_index_reserve(&sel->u.cgrp, isize);
- if (sel->v.type == GROUP_VALUE || (sel->flags & SEL_ATOMVAL))
- {
- alloc_selection_data(sel->child, isize, FALSE);
- alloc_selection_data(sel, isize, FALSE);
- }
- rc = sel->cdata->evaluate(data, sel, g);
+ alloc_selection_data(sel, isize, FALSE);
}
- else
+ rc = sel->cdata->evaluate(data, sel, g);
+ if (isize > 0 && bDoMinMax)
{
- rc = sel->cdata->evaluate(data, sel, g);
+ gmx_ana_index_reserve(sel->cdata->gmin,
+ sel->cdata->gmin->isize
+ + sel->child->cdata->gmin->isize);
+ gmx_ana_index_reserve(sel->cdata->gmax,
+ sel->cdata->gmax->isize
+ + sel->child->cdata->gmax->isize);
+ gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin,
+ sel->child->cdata->gmin);
+ gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax,
+ sel->child->cdata->gmax);
}
}
break;
case SEL_SUBEXPRREF:
- /* Evaluate the subexpression if it is not yet evaluated.
- * Can happen when a variable is passed as a parameter or as
- * a selection. */
- if (sel->child->u.cgrp.isize == 0)
- {
- rc = sel->child->evaluate(data, sel->child, g ? g : data->gall);
- if (rc != 0)
- {
- return rc;
- }
- /* Prevent another evaluation of the child. */
- sel->child->evaluate = NULL;
- alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
- }
- if (!g)
+ if (!g && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
{
+ /* The subexpression should have been evaluated if g is NULL
+ * (i.e., this is a method parameter or a direct value of a
+ * selection). */
alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
}
- /* TODO: This is not general enough if/when position references
- * can be evaluated more than once (that is, if there are position
- * methods that do not have SMETH_SINGLEVAL or SMETH_VARNUMVAL). */
- if (sel->v.type == POS_VALUE && !(sel->flags & SEL_OUTINIT))
- {
- gmx_ana_pos_copy(sel->v.u.p, sel->child->child->v.u.p, TRUE);
- sel->flags |= SEL_OUTINIT;
- }
rc = sel->cdata->evaluate(data, sel, g);
- sel->child->evaluate = &analyze_static;
if (rc != 0)
{
return rc;
}
+ if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+ && (sel->child->child->flags & SEL_ALLOCVAL))
+ {
+ _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
+ }
/* Store the parameter value if required */
store_param_val(sel);
if (!(sel->flags & SEL_DYNAMIC))
{
- if (sel->cdata->bStatic)
+ if (sel->cdata->flags & SEL_CDATA_STATIC)
{
make_static(sel);
}
}
- else
+ else if (bDoMinMax)
{
- if (sel->child->refcount <= 2 || !g)
+ if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR) || !g)
{
- gmx_ana_index_copy(&gmin, sel->child->cdata->gmin, TRUE);
- gmx_ana_index_copy(&gmax, sel->child->cdata->gmax, TRUE);
+ gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, TRUE);
+ gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, TRUE);
}
else
{
- gmx_ana_index_reserve(&gmin, min(g->isize, sel->child->cdata->gmin->isize));
- gmx_ana_index_reserve(&gmax, min(g->isize, sel->child->cdata->gmax->isize));
- gmx_ana_index_intersection(&gmin, sel->child->cdata->gmin, g);
- gmx_ana_index_intersection(&gmax, sel->child->cdata->gmax, g);
+ gmx_ana_index_reserve(sel->cdata->gmin,
+ min(g->isize, sel->child->cdata->gmin->isize));
+ gmx_ana_index_reserve(sel->cdata->gmax,
+ min(g->isize, sel->child->cdata->gmax->isize));
+ gmx_ana_index_intersection(sel->cdata->gmin,
+ sel->child->cdata->gmin, g);
+ gmx_ana_index_intersection(sel->cdata->gmax,
+ sel->child->cdata->gmax, g);
}
}
break;
}
/* Update the minimal and maximal evaluation groups */
- if (sel->cdata->bMinMaxAlloc)
- {
- gmx_ana_index_reserve(sel->cdata->gmin, sel->cdata->gmin->isize + gmin.isize);
- gmx_ana_index_reserve(sel->cdata->gmax, sel->cdata->gmax->isize + gmax.isize);
- gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin, &gmin);
- gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax, &gmax);
- }
- /* Replace the result of the evaluation */
- /* This is not necessary for subexpressions or for boolean negations
- * because the evaluation function already has done it properly. */
- if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
- && sel->type != SEL_SUBEXPR
- && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
- {
- if (sel->cdata->bEvalMax)
- {
- gmx_ana_index_copy(sel->v.u.g, &gmax, FALSE);
- }
- else
- {
- gmx_ana_index_copy(sel->v.u.g, &gmin, FALSE);
- }
- }
- gmx_ana_index_deinit(&gmin);
- gmx_ana_index_deinit(&gmax);
-
- /* Make sure that enough data storage has been allocated */
- /* TODO: Constant expressions could be handled here more intelligently */
- if (sel->type != SEL_ROOT && sel->cdata->bStaticEval)
- {
- alloc_selection_data(sel, sel->cdata->gmax->isize, TRUE);
- /* Make sure that the new value pointer is stored if required */
- store_param_val(sel);
- }
-
- return 0;
-}
-
-/*! \brief
- * Evaluates the static parts of \p sel and analyzes the structure.
- *
- * \param[in] data Evaluation data.
- * \param[in,out] sel Selection currently being evaluated.
- * \param[in] g Group for which \p sel should be evaluated.
- * \returns 0 on success, a non-zero error code on error.
- *
- * This function is a simpler version of analyze_static() that is used
- * during a second evaluation round, and can thus use information calculated
- * by analyze_static().
- * It is also used as the replacement for the \c t_selelem::evaluate
- * function pointer.
- * It is used to evaluate the static parts of subexpressions that could not
- * be evaluated during the analyze_static() pass.
- *
- * \see analyze_static()
- */
-static int
-analyze_static2(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
- int rc;
-
- rc = 0;
- switch (sel->type)
- {
- case SEL_CONST:
- rc = process_const(data, sel, g);
- break;
-
- case SEL_EXPRESSION:
- case SEL_BOOLEAN:
- case SEL_SUBEXPRREF:
- if (sel->cdata->bStatic)
- {
- rc = sel->cdata->evaluate(data, sel, g);
- if (rc == 0)
- {
- make_static(sel);
- }
- }
- else if (sel->type == SEL_BOOLEAN)
- {
- rc = evaluate_boolean_static_part(data, sel, g);
- if (rc == 0)
- {
- rc = sel->cdata->evaluate(data, sel, g);
- }
- }
- break;
-
- case SEL_ROOT: /* Roots should not be present here */
- case SEL_MODIFIER: /* Modifiers should not be present here */
- case SEL_SUBEXPR:
- rc = sel->cdata->evaluate(data, sel, g);
- break;
- }
- /* Exit if there was some problem */
- if (rc != 0)
+ if (bDoMinMax)
{
- return rc;
+ gmx_ana_index_squeeze(sel->cdata->gmin);
+ gmx_ana_index_squeeze(sel->cdata->gmax);
+ sfree(sel->cdata->gmin->name);
+ sfree(sel->cdata->gmax->name);
+ sel->cdata->gmin->name = NULL;
+ sel->cdata->gmax->name = NULL;
}
/* Replace the result of the evaluation */
/* This is not necessary for subexpressions or for boolean negations
* because the evaluation function already has done it properly. */
- if (sel->v.type == GROUP_VALUE && !sel->cdata->bStatic
+ if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
&& sel->type != SEL_SUBEXPR
&& !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
{
- if (sel->cdata->bEvalMax)
+ if (sel->cdata->flags & SEL_CDATA_EVALMAX)
{
gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmax, FALSE);
}
/********************************************************************
- * ROOT ITEM INITIALIZATION COMPILER PASS
+ * EVALUATION GROUP INITIALIZATION
********************************************************************/
/*! \brief
- * Initializes a \ref SEL_ROOT element.
+ * Initializes the evaluation group for a \ref SEL_ROOT element.
*
* \param root Root element to initialize.
- * \returns Pointer to the selection element that should replace \p root.
- * Can be \p root itself or NULL if the selection should be removed.
+ * \param[in] gall Group of all atoms.
*
* Checks whether it is necessary to evaluate anything through the root
* element, and either clears the evaluation function or initializes the
* evaluation group.
- *
- * If the function returns NULL, the memory allocated for \p root is
- * automatically freed.
*/
-static t_selelem *
-init_root_item(t_selelem *root)
+static void
+init_root_item(t_selelem *root, gmx_ana_index_t *gall)
{
t_selelem *expr;
char *name;
- /* Process subexpressions */
- if (root->child->type == SEL_SUBEXPR)
+ expr = root->child;
+ /* Subexpressions with non-static evaluation group should not be
+ * evaluated by the root, and neither should be single-reference
+ * subexpressions that don't evaluate for all atoms. */
+ if (expr->type == SEL_SUBEXPR
+ && (!(root->child->cdata->flags & SEL_CDATA_STATICEVAL)
+ || ((root->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+ && !(root->child->cdata->flags & SEL_CDATA_FULLEVAL))))
{
- if (root->child->refcount == 1)
- {
- /* Free subexpressions that are no longer used */
- _gmx_selelem_free(root);
- return NULL;
- }
- else if (root->child->v.type == POS_VALUE)
- {
- /* Position values only need to be evaluated once, by the root */
- }
- else if (!root->child->cdata->bStaticEval)
+ root->evaluate = NULL;
+ if (root->cdata)
{
- /* Subexpressions with non-static evaluation group should not be
- * evaluated by the root. */
- root->evaluate = NULL;
- if (root->cdata)
- {
- root->cdata->evaluate = NULL;
- }
+ root->cdata->evaluate = NULL;
}
}
name = root->u.cgrp.name;
if (root->evaluate)
{
- expr = root->child;
- if (expr->type == SEL_SUBEXPR)
+ /* Non-atom-valued non-group expressions don't care about the group, so
+ * don't allocate any memory for it. */
+ if ((expr->flags & SEL_VARNUMVAL)
+ || ((expr->flags & SEL_SINGLEVAL) && expr->v.type != GROUP_VALUE))
{
- gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, TRUE);
+ gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
+ }
+ else if (expr->cdata->gmax->isize == gall->isize)
+ {
+ /* Save some memory by only referring to the global group. */
+ gmx_ana_index_set(&root->u.cgrp, gall->isize, gall->index, NULL, 0);
}
else
{
- /* expr should evaluate the positions for a selection */
- if (expr->v.u.p->g)
+ gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, TRUE);
+ }
+ /* For selections, store the maximum group for
+ * gmx_ana_selcollection_evaluate_fin() as the value of the root
+ * element (unused otherwise). */
+ if (expr->type != SEL_SUBEXPR && expr->v.u.p->g)
+ {
+ t_selelem *child = expr;
+
+ /* TODO: This code is copied from parsetree.c; it would be better
+ * to have this hardcoded only in one place. */
+ while (child->type == SEL_MODIFIER)
+ {
+ child = child->child;
+ if (child->type == SEL_SUBEXPRREF)
+ {
+ child = child->child->child;
+ }
+ }
+ if (child->type == SEL_SUBEXPRREF)
+ {
+ child = child->child->child;
+ }
+ if (child->child->flags & SEL_DYNAMIC)
{
_gmx_selelem_set_vtype(root, GROUP_VALUE);
root->flags |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
_gmx_selvalue_reserve(&root->v, 1);
gmx_ana_index_copy(root->v.u.g, expr->v.u.p->g, TRUE);
}
- gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
}
}
else
gmx_ana_index_clear(&root->u.cgrp);
}
root->u.cgrp.name = name;
- return root;
-}
-
-/*! \brief
- * Initializes the evaluation groups for \ref SEL_ROOT items.
- *
- * \param root First selection in the whole selection chain.
- * \returns The new first element for the chain.
- *
- * The function also removes static subexpressions that are no longer used.
- */
-static t_selelem *
-process_roots(t_selelem *root)
-{
- t_selelem *item;
- t_selelem *next;
-
- do
- {
- next = root->next;
- root = init_root_item(root);
- if (!root)
- {
- root = next;
- }
- }
- while (root == next);
- item = root;
- while (item && item->next)
- {
- next = item->next->next;
- item->next = init_root_item(item->next);
- if (!item->next)
- {
- item->next = next;
- }
- else
- {
- item = item->next;
- }
- }
- return root;
}
/********************************************************************
- * SUBEXPRESSION OPTIMIZATION PASS
+ * FINAL SUBEXPRESSION OPTIMIZATION
********************************************************************/
/*! \brief
* referenced once.
*/
static void
-optimize_item_subexpressions(t_selelem *sel)
+postprocess_item_subexpressions(t_selelem *sel)
{
- t_selelem *child;
-
- /* Call recursively for all children unless the children have already been processed */
+ /* Process children. */
if (sel->type != SEL_SUBEXPRREF)
{
+ t_selelem *child;
+
child = sel->child;
while (child)
{
- optimize_item_subexpressions(child);
+ postprocess_item_subexpressions(child);
child = child->next;
}
}
- /* Optimize the evaluation of subexpressions that are used only once */
- if (sel->type == SEL_SUBEXPRREF && sel->cdata->bStaticEval && sel->child->refcount == 2)
+ /* Replace the evaluation function of statically evaluated subexpressions
+ * for which the static group was not known in advance. */
+ if (sel->type == SEL_SUBEXPR && sel->refcount > 2
+ && (sel->cdata->flags & SEL_CDATA_STATICEVAL)
+ && !(sel->cdata->flags & SEL_CDATA_FULLEVAL))
{
- /* The evaluation functions are not always needed, and they do some
- * extra work, but it should be neglible compared to other factors
- * in the evaluation, so set them always for simplicity. */
- sel->evaluate = &_gmx_sel_evaluate_subexprref_pass;
+ char *name;
+
+ /* We need to free memory allocated for the group, because it is no
+ * longer needed (and would be lost on next call to the evaluation
+ * function). But we need to preserve the name. */
+ name = sel->u.cgrp.name;
+ gmx_ana_index_deinit(&sel->u.cgrp);
+ sel->u.cgrp.name = name;
+
+ sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
if (sel->cdata)
{
sel->cdata->evaluate = sel->evaluate;
}
- /* Replace the value of the child */
_gmx_selelem_free_values(sel->child);
- sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ sel->child->mempool = NULL;
_gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
- sel->child->evaluate = &_gmx_sel_evaluate_subexpr_pass;
- if (sel->child->cdata)
+ sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ }
+
+ /* Adjust memory allocation flags for subexpressions that are used only
+ * once. This is not strictly necessary, but we do it to have the memory
+ * managed consistently for all types of subexpressions. */
+ if (sel->type == SEL_SUBEXPRREF
+ && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
+ {
+ if (sel->child->child->flags & SEL_ALLOCVAL)
{
- sel->child->cdata->evaluate = sel->child->evaluate;
+ sel->flags |= SEL_ALLOCVAL;
+ sel->flags |= (sel->child->child->flags & SEL_ALLOCDATA);
+ sel->v.nalloc = sel->child->child->v.nalloc;
+ sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ sel->child->child->v.nalloc = -1;
}
- /* Replace the value of the grandchild */
- _gmx_selelem_free_values(sel->child->child);
- sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
- _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
+ }
+
+ /* Do the same for subexpressions that are evaluated at once for all atoms. */
+ if (sel->type == SEL_SUBEXPR
+ && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+ && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
+ {
+ sel->flags |= SEL_ALLOCVAL;
+ sel->flags |= (sel->child->flags & SEL_ALLOCDATA);
+ sel->v.nalloc = sel->child->v.nalloc;
+ sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+ sel->child->v.nalloc = -1;
}
}
/********************************************************************
- * COM CALCULATION COMPILER PASS
+ * COM CALCULATION INITIALIZATION
********************************************************************/
/*! \brief
/* Create a default calculation if one does not yet exist */
int cflags;
cflags = 0;
- if (!sel->cdata->bStaticEval)
+ if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
{
cflags |= POS_DYNAMIC;
}
/********************************************************************
- * FREE COMPILER DATA PASS
+ * COMPILER DATA FREEING
********************************************************************/
/*! \brief
/********************************************************************
- * INFORMATION UPDATE
+ * MASS AND CHARGE CALCULATION
********************************************************************/
/*! \brief
- * Updates the information about the selection.
+ * Initializes total masses and charges for selections.
*
* \param[in] top Topology information.
* \param[in] ngrps Number of elements in the \p sel array.
* \param[in,out] sel Array of selections to update.
* \param[in] bMaskOnly TRUE if the positions will always be calculated
* for all atoms, i.e., the masses/charges do not change.
- *
- * Initializes total masses and charges.
*/
static void
-update_info(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
- bool bMaskOnly)
+calculate_mass_charge(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
+ bool bMaskOnly)
{
int g, b, i;
* MAIN COMPILATION FUNCTION
********************************************************************/
+/*!
+ * \param[in,out] sc Selection collection to debug.
+ * \param[in] bDebug If TRUE, later call to gmx_ana_selcollection_compile()
+ * will print out intermediate selection trees.
+ */
+void
+gmx_ana_selcollection_set_compile_debug(gmx_ana_selcollection_t *sc, bool bDebug)
+{
+ sc->bDebugCompile = bDebug;
+}
+
/*!
* \param[in,out] sc Selection collection to be compiled.
* \returns 0 on successful compilation, a non-zero error code on error.
int flags;
int rc;
- _gmx_sel_evaluate_init(&evaldata, &sc->gall, sc->top, NULL, NULL);
+ rc = _gmx_sel_mempool_create(&sc->mempool);
+ if (rc != 0)
+ {
+ return rc;
+ }
+ _gmx_sel_evaluate_init(&evaldata, sc->mempool, &sc->gall,
+ sc->top, NULL, NULL);
/* Clear the symbol table because it is not possible to parse anything
* after compilation, and variable references in the symbol table can
*/
_gmx_selcollection_clear_symtab(sc);
+ /* Remove any unused variables. */
+ sc->root = remove_unused_subexpressions(sc->root);
/* Extract subexpressions into separate roots */
- sc->root = extract_subexpressions(sc->root, &sc->gall);
+ sc->root = extract_subexpressions(sc->root);
/* Initialize the evaluation callbacks and process the tree structure
* to conform to the expectations of the callback functions. */
item = sc->root;
while (item)
{
- /* Process boolean expressions */
+ /* Process boolean and arithmetic expressions. */
optimize_boolean_expressions(item);
reorder_boolean_static_children(item);
- /* Initialize evaluation */
- if (!init_item_evaluation(item))
+ if (!optimize_arithmetic_expressions(item))
{
/* FIXME: Clean up the collection */
return -1;
}
+ /* Initialize evaluation function. */
+ if (!init_item_evalfunc(item))
+ {
+ /* FIXME: Clean up the collection */
+ return -1;
+ }
+ setup_memory_pooling(item, sc->mempool);
/* Initialize the compiler data */
init_item_compilerdata(item);
init_item_staticeval(item);
item = item->next;
}
+ /* Initialize subexpression flags and evaluation output.
+ * Requires compiler flags for the full tree. */
+ item = sc->root;
+ while (item)
+ {
+ init_item_subexpr_flags(item);
+ init_item_evaloutput(item);
+ item = item->next;
+ }
+ /* Initialize minimum/maximum index groups.
+ * Requires evaluation output for the full tree. */
+ item = sc->root;
+ while (item)
+ {
+ init_item_minmax_groups(item);
+ item = item->next;
+ }
/* Initialize the evaluation index groups */
initialize_evalgrps(sc);
+ if (sc->bDebugCompile)
+ {
+ fprintf(stderr, "\nTree after initial compiler processing:\n");
+ gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
+ }
+
/* Evaluate all static parts of the selection and analyze the tree
* to allocate enough memory to store the value of each dynamic subtree. */
item = sc->root;
while (item)
{
- if (item->child->type == SEL_SUBEXPR && item->child->refcount > 2)
+ if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
{
mark_subexpr_dynamic(item->child, TRUE);
}
item = item->next;
}
+ /* At this point, static subexpressions no longer have references to them,
+ * so they can be removed. */
+ sc->root = remove_unused_subexpressions(sc->root);
+
+ if (sc->bDebugCompile)
+ {
+ fprintf(stderr, "\nTree after first analysis pass:\n");
+ gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
+ }
+
/* Do a second pass to evaluate static parts of common subexpressions */
- /* Note that the refcount check skips constant subexpressions completely
- * since they were already evaluated by analyze_static(). */
item = sc->root;
while (item)
{
- if (item->child->type == SEL_SUBEXPR && item->child->refcount > 2)
+ if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
{
+ bool bMinMax = item->child->cdata->flags & SEL_CDATA_MINMAXALLOC;
+
mark_subexpr_dynamic(item->child, FALSE);
item->child->u.cgrp.isize = 0;
- /* We won't clear item->child->child->v.u.g here, because it may
+ /* We won't clear item->child->v.u.g here, because it may
* be static, and hence actually point to item->child->cdata->gmax,
* which is used below. We could also check whether this is the
* case and only clear the group otherwise, but because the value
* is actually overwritten immediately in the evaluate call, we
* won't, because similar problems may arise if gmax handling ever
- * changes and the check were not updated. */
- set_evaluation_function(item, &analyze_static2);
+ * changes and the check were not updated.
+ * For the same reason, we clear the min/max flag so that the
+ * evaluation group doesn't get messed up. */
+ set_evaluation_function(item, &analyze_static);
+ item->child->cdata->flags &= ~SEL_CDATA_MINMAXALLOC;
rc = item->evaluate(&evaldata, item->child, item->child->cdata->gmax);
+ if (bMinMax)
+ {
+ item->child->cdata->flags |= SEL_CDATA_MINMAXALLOC;
+ }
if (rc != 0)
{
/* FIXME: Clean up the collection */
item = item->next;
}
- /* Initialize evaluation groups and remove unused subexpressions. */
- sc->root = process_roots(sc->root);
+ /* We need a yet another pass of subexpression removal to remove static
+ * subexpressions referred to by common dynamic subexpressions. */
+ sc->root = remove_unused_subexpressions(sc->root);
- /* Initialize position calculations for methods, perform some final
- * optimization and free the memory allocated for the compilation. */
+ if (sc->bDebugCompile)
+ {
+ fprintf(stderr, "\nTree after second analysis pass:\n");
+ gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
+ }
+
+ /* Initialize evaluation groups, position calculations for methods, perform
+ * some final optimization, and free the memory allocated for the
+ * compilation. */
/* By default, use whole residues/molecules. */
flags = POS_COMPLWHOLE;
rc = gmx_ana_poscalc_type_from_enum(sc->rpost, &post, &flags);
item = sc->root;
while (item)
{
- optimize_item_subexpressions(item);
+ init_root_item(item, &sc->gall);
+ postprocess_item_subexpressions(item);
rc = init_item_comg(item, sc->pcc, post, flags);
if (rc != 0)
{
item = item->next;
}
- /* Finish up by updating some information */
- update_info(sc->top, sc->nr, sc->sel, sc->bMaskOnly);
+ /* Allocate memory for the evaluation memory pool. */
+ rc = _gmx_sel_mempool_reserve(sc->mempool, 0);
+ if (rc != 0)
+ {
+ return rc;
+ }
+
+ /* Finish up by calculating total masses and charges. */
+ calculate_mass_charge(sc->top, sc->nr, sc->sel, sc->bMaskOnly);
return 0;
}
#include <selmethod.h>
#include "evaluate.h"
+#include "mempool.h"
#include "selcollection.h"
#include "selelem.h"
+/*!
+ * \param[in] fp File handle to receive the output.
+ * \param[in] evalfunc Function pointer to print.
+ */
+void
+_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc)
+{
+ if (!evalfunc)
+ fprintf(fp, "none");
+ else if (evalfunc == &_gmx_sel_evaluate_root)
+ fprintf(fp, "root");
+ else if (evalfunc == &_gmx_sel_evaluate_static)
+ fprintf(fp, "static");
+ else if (evalfunc == &_gmx_sel_evaluate_subexpr_simple)
+ fprintf(fp, "subexpr_simple");
+ else if (evalfunc == &_gmx_sel_evaluate_subexpr_staticeval)
+ fprintf(fp, "subexpr_staticeval");
+ else if (evalfunc == &_gmx_sel_evaluate_subexpr)
+ fprintf(fp, "subexpr");
+ else if (evalfunc == &_gmx_sel_evaluate_subexprref_simple)
+ fprintf(fp, "ref_simple");
+ else if (evalfunc == &_gmx_sel_evaluate_subexprref)
+ fprintf(fp, "ref");
+ else if (evalfunc == &_gmx_sel_evaluate_method)
+ fprintf(fp, "method");
+ else if (evalfunc == &_gmx_sel_evaluate_modifier)
+ fprintf(fp, "mod");
+ else if (evalfunc == &_gmx_sel_evaluate_not)
+ fprintf(fp, "not");
+ else if (evalfunc == &_gmx_sel_evaluate_and)
+ fprintf(fp, "and");
+ else if (evalfunc == &_gmx_sel_evaluate_or)
+ fprintf(fp, "or");
+ else if (evalfunc == &_gmx_sel_evaluate_arithmetic)
+ fprintf(fp, "arithmetic");
+ else
+ fprintf(fp, "%p", (void*)(evalfunc));
+}
+
/*!
* \param[out] data Evaluation data structure to initialize.
+ * \param[in] mp Memory pool for intermediate evaluation values.
* \param[in] gall Index group with all the atoms.
* \param[in] top Topology structure for evaluation.
* \param[in] fr New frame for evaluation.
* \param[in] pbc New PBC information for evaluation.
*/
void
-_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data, gmx_ana_index_t *gall,
+_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
+ gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
t_topology *top, t_trxframe *fr, t_pbc *pbc)
{
+ data->mp = mp;
data->gall = gall;
data->top = top;
data->fr = fr;
int g, i;
int rc;
- _gmx_sel_evaluate_init(&data, &sc->gall, sc->top, fr, pbc);
+ _gmx_sel_evaluate_init(&data, sc->mempool, &sc->gall, sc->top, fr, pbc);
init_frame_eval(sc->root);
sel = sc->root;
while (sel)
* _gmx_sel_evaluate_subexpr(). */
if (sel->child->v.type == GROUP_VALUE)
{
- sel->child->child->v.u.g->isize = 0;
+ sel->child->v.u.g->isize = 0;
}
}
if (sel->evaluate)
for (g = 0; g < sc->nr; ++g)
{
sel = sc->sel[g]->selelem;
- if (sc->sel[g]->g)
+ if (sc->sel[g]->bDynamic)
{
gmx_ana_index_copy(sc->sel[g]->g, sel->v.u.g, FALSE);
sc->sel[g]->g->name = NULL;
return 0;
}
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g Group for which \p sel should be evaluated.
+ * \returns 0 on success, a non-zero error code on error.
+ *
+ * Evaluates each child of \p sel in \p g.
+ */
+int
+_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel,
+ gmx_ana_index_t *g)
+{
+ t_selelem *child;
+ int rc;
+
+ child = sel->child;
+ while (child)
+ {
+ if (child->evaluate)
+ {
+ rc = child->evaluate(data, child, g);
+ if (rc != 0)
+ {
+ return rc;
+ }
+ }
+ child = child->next;
+ }
+ return 0;
+}
+
/*!
* \param[in] data Data for the current frame.
* \param[in] sel Selection element being evaluated.
* \returns 0 on success, a non-zero error code on error.
*
* Evaluates the child element (there should be exactly one) in \p g.
- * The number of values is copied from the child to \p sel->v.nr, but
- * otherwise the value of \p sel is not touched.
+ * The compiler has taken care that the child actually stores the evaluated
+ * value in the value pointer of this element.
*
* This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
* elements that are used only once, and hence do not need full subexpression
* handling.
*/
int
-_gmx_sel_evaluate_subexpr_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
{
int rc;
return 0;
}
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g Group for which \p sel should be evaluated.
+ * \returns 0 on success, a non-zero error code on error.
+ *
+ * If this is the first call for this frame, evaluates the child element
+ * there should be exactly one in \p g.
+ * The compiler has taken care that the child actually stores the evaluated
+ * value in the value pointer of this element.
+ * Assumes that \p g is persistent for the duration of the whole evaluation.
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
+ * elements that have a static evaluation group, and hence do not need full
+ * subexpression handling.
+ */
+int
+_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+ if (sel->u.cgrp.isize == 0)
+ {
+ int rc;
+
+ rc = sel->child->evaluate(data, sel->child, g);
+ if (rc != 0)
+ {
+ return rc;
+ }
+ sel->v.nr = sel->child->v.nr;
+ gmx_ana_index_set(&sel->u.cgrp, g->isize, g->index, sel->u.cgrp.name, 0);
+ }
+ return 0;
+}
+
/*!
* \param[in] data Data for the current frame.
* \param[in] sel Selection element being evaluated.
* The call to gmx_ana_index_difference() can take quite a lot of unnecessary
* time if the subexpression is evaluated either several times for the same
* group or for completely distinct groups.
+ * However, in the majority of cases, these situations occur when
+ * _gmx_sel_evaluate_subexpr_staticeval() can be used, so this should not be a
+ * major problem.
*/
int
_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
if (sel->u.cgrp.isize == 0)
{
char *name;
- /* We need to check for the presence because the compiler may clear
- * it temporarily. */
- if (sel->child->evaluate)
+ void *old_ptr = sel->child->v.u.ptr;
+ int old_nalloc = sel->child->v.nalloc;
+ _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+ rc = sel->child->evaluate(data, sel->child, g);
+ _gmx_selvalue_setstore_alloc(&sel->child->v, old_ptr, old_nalloc);
+ if (rc != 0)
{
- rc = sel->child->evaluate(data, sel->child, g);
- if (rc != 0)
- {
- return rc;
- }
+ return rc;
}
/* We need to keep the name for the cgrp across the copy to avoid
* problems if g has a name set. */
}
else
{
- if (sel->v.type == GROUP_VALUE)
+ /* We allocate some extra memory here to avoid some computation. */
+ rc = _gmx_sel_mempool_alloc_group(data->mp, &gmiss, g->isize);
+ if (rc != 0)
{
- gmx_ana_index_set(&gmiss, 0, sel->child->v.u.g->index + sel->child->v.u.g->isize, NULL, 0);
+ return rc;
}
- else
+ gmx_ana_index_difference(&gmiss, g, &sel->u.cgrp);
+ if (gmiss.isize == 0)
{
- gmx_ana_index_set(&gmiss, 0, sel->u.cgrp.index + sel->u.cgrp.isize, NULL, 0);
+ _gmx_sel_mempool_free_group(data->mp, &gmiss);
}
- gmx_ana_index_difference(&gmiss, g, &sel->u.cgrp);
}
if (gmiss.isize > 0)
{
- /* We use the value of sel to store the old value of the child before
- * evaluating the missing values. */
- if (sel->v.type == GROUP_VALUE)
- {
- atom_id *tmp = sel->child->v.u.g->index;
- sel->child->v.u.g->index = sel->v.u.g->index;
- sel->v.u.g->index = tmp;
- sel->v.u.g->isize = sel->child->v.u.g->isize;
- sel->child->v.u.g->isize = 0;
- }
- else
+ rc = _gmx_selelem_mempool_reserve(sel->child, gmiss.isize);
+ if (rc != 0)
{
- void *tmp = sel->child->v.u.ptr;
- sel->child->v.u.ptr = sel->v.u.ptr;
- sel->v.u.ptr = tmp;
+ return rc;
}
/* Evaluate the missing values for the child */
rc = sel->child->evaluate(data, sel->child, &gmiss);
/* Merge the missing values to the existing ones. */
if (sel->v.type == GROUP_VALUE)
{
- gmx_ana_index_merge(sel->child->v.u.g, sel->child->v.u.g, sel->v.u.g);
- gmx_ana_index_merge(&sel->u.cgrp, &sel->u.cgrp, &gmiss);
+ gmx_ana_index_merge(sel->v.u.g, sel->child->v.u.g, sel->v.u.g);
}
else
{
{
if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
{
- sel->child->v.u.i[k] = sel->child->v.u.i[j--];
+ sel->v.u.i[k] = sel->v.u.i[j--];
}
else
{
- sel->child->v.u.i[k] = sel->v.u.i[i--];
+ sel->v.u.i[k] = sel->child->v.u.i[i--];
}
}
break;
{
if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
{
- sel->child->v.u.r[k] = sel->child->v.u.r[j--];
+ sel->v.u.r[k] = sel->v.u.r[j--];
}
else
{
- sel->child->v.u.r[k] = sel->v.u.r[i--];
+ sel->v.u.r[k] = sel->child->v.u.r[i--];
}
}
break;
{
if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
{
- sel->child->v.u.s[k] = sel->child->v.u.s[j--];
+ sel->v.u.s[k] = sel->v.u.s[j--];
}
else
{
- sel->child->v.u.s[k] = sel->v.u.s[i--];
+ sel->v.u.s[k] = sel->child->v.u.s[i--];
}
}
break;
gmx_bug("internal error");
return -1;
}
- /* TODO: With some additional storage, we could do a merge here */
- sel->u.cgrp.isize += gmiss.isize;
- gmx_ana_index_sort(&sel->u.cgrp);
}
+ gmx_ana_index_merge(&sel->u.cgrp, &sel->u.cgrp, &gmiss);
+ _gmx_selelem_mempool_release(sel->child);
+ _gmx_sel_mempool_free_group(data->mp, &gmiss);
}
return 0;
}
* \param[in] g Group for which \p sel should be evaluated.
* \returns 0 for success.
*
+ * Sets the value pointers of the child and its child to point to the same
+ * memory as the value pointer of this element to avoid copying, and then
+ * evaluates evaluates the child.
+ *
* This function is used as \c t_selelem:evaluate for \ref SEL_SUBEXPRREF
- * elements for which the actual value is evaluated directly by the
- * subexpression, but for which the number of values needs to be passed
- * forward.
+ * elements for which the \ref SEL_SUBEXPR does not have other references.
*/
int
-_gmx_sel_evaluate_subexprref_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
{
- sel->v.nr = sel->child->child->v.nr;
+ if (g)
+ {
+ int rc;
+
+ _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+ _gmx_selvalue_setstore_alloc(&sel->child->child->v, sel->v.u.ptr,
+ sel->child->child->v.nalloc);
+ rc = sel->child->evaluate(data, sel->child, g);
+ if (rc != 0)
+ {
+ return rc;
+ }
+ }
+ sel->v.nr = sel->child->v.nr;
if (sel->u.param)
{
sel->u.param->val.nr = sel->v.nr;
t_selelem *expr;
int i, j;
- /* We need to check for the presence because the compiler may clear
- * it temporarily. */
- if (g && sel->child->evaluate)
+ if (g)
{
int rc;
return rc;
}
}
- expr = sel->child->child;
+ expr = sel->child;
switch (sel->v.type)
{
case INT_VALUE:
{
int rc;
- rc = sel->child->evaluate(data, sel->child, g);
+ rc = _gmx_selelem_mempool_reserve(sel->child, g->isize);
+ if (rc == 0)
+ {
+ rc = sel->child->evaluate(data, sel->child, g);
+ }
if (rc != 0)
{
return rc;
}
gmx_ana_index_difference(sel->v.u.g, g, sel->child->v.u.g);
+ _gmx_selelem_mempool_release(sel->child);
return 0;
}
{
child = child->next;
}
- rc = child->evaluate(data, child, g);
+ rc = _gmx_selelem_mempool_reserve(child, g->isize);
+ if (rc == 0)
+ {
+ rc = child->evaluate(data, child, g);
+ }
if (rc != 0)
{
return rc;
}
gmx_ana_index_copy(sel->v.u.g, child->v.u.g, FALSE);
+ _gmx_selelem_mempool_release(child);
child = child->next;
while (child && sel->v.u.g->isize > 0)
{
- rc = child->evaluate(data, child, sel->v.u.g);
+ rc = _gmx_selelem_mempool_reserve(child, sel->v.u.g->isize);
+ if (rc == 0)
+ {
+ rc = child->evaluate(data, child, sel->v.u.g);
+ }
if (rc != 0)
{
return rc;
}
gmx_ana_index_intersection(sel->v.u.g, sel->v.u.g, child->v.u.g);
+ _gmx_selelem_mempool_release(child);
child = child->next;
}
return 0;
child = sel->child;
if (child->evaluate)
{
- rc = child->evaluate(data, child, g);
+ rc = _gmx_selelem_mempool_reserve(child, g->isize);
+ if (rc == 0)
+ {
+ rc = child->evaluate(data, child, g);
+ }
if (rc != 0)
{
return rc;
}
+ gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
+ _gmx_selelem_mempool_release(child);
+ }
+ else
+ {
+ gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
}
- gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
child = child->next;
while (child && tmp.isize > 0)
{
tmp.name = NULL;
- rc = child->evaluate(data, child, &tmp);
+ rc = _gmx_selelem_mempool_reserve(child, tmp.isize);
+ if (rc == 0)
+ {
+ rc = child->evaluate(data, child, &tmp);
+ }
if (rc != 0)
{
return rc;
}
gmx_ana_index_partition(&tmp, &tmp2, &tmp, child->v.u.g);
+ _gmx_selelem_mempool_release(child);
sel->v.u.g->isize += tmp.isize;
tmp.isize = tmp2.isize;
tmp.index = tmp2.index;
gmx_ana_index_sort(sel->v.u.g);
return 0;
}
+
+
+/********************************************************************
+ * ARITHMETIC EVALUATION
+ ********************************************************************/
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g Group for which \p sel should be evaluated.
+ * \returns 0 on success, a non-zero error code on error.
+ */
+int
+_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel,
+ gmx_ana_index_t *g)
+{
+ t_selelem *left, *right;
+ int n, i, i1, i2;
+ real lval, rval=0., val=0.;
+ int rc;
+
+ left = sel->child;
+ right = left->next;
+
+ if (left->mempool)
+ {
+ _gmx_selvalue_setstore(&left->v, sel->v.u.ptr);
+ rc = _gmx_selelem_mempool_reserve(right, g->isize);
+ if (rc != 0)
+ {
+ return rc;
+ }
+ }
+ else if (right->mempool)
+ {
+ _gmx_selvalue_setstore(&right->v, sel->v.u.ptr);
+ }
+ rc = _gmx_sel_evaluate_children(data, sel, g);
+
+ n = (sel->flags & SEL_SINGLEVAL) ? 1 : g->isize;
+ sel->v.nr = n;
+ for (i = i1 = i2 = 0; i < n; ++i)
+ {
+ lval = left->v.u.r[i1];
+ if (sel->u.arith.type != ARITH_NEG)
+ {
+ rval = right->v.u.r[i2];
+ }
+ switch (sel->u.arith.type)
+ {
+ case ARITH_PLUS: val = lval + rval; break;
+ case ARITH_MINUS: val = lval - rval; break;
+ case ARITH_NEG: val = -lval; break;
+ case ARITH_MULT: val = lval * rval; break;
+ case ARITH_DIV: val = lval / rval; break;
+ case ARITH_EXP: val = pow(lval, rval); break;
+ }
+ sel->v.u.r[i] = val;
+ if (!(left->flags & SEL_SINGLEVAL))
+ {
+ ++i1;
+ }
+ if (sel->u.arith.type != ARITH_NEG && !(right->flags & SEL_SINGLEVAL))
+ {
+ ++i2;
+ }
+ }
+
+ if (left->mempool)
+ {
+ _gmx_selvalue_setstore(&left->v, NULL);
+ _gmx_selelem_mempool_release(right);
+ }
+ else if (right->mempool)
+ {
+ _gmx_selvalue_setstore(&right->v, NULL);
+ }
+ return 0;
+}
#include "selelem.h"
+struct gmx_sel_mempool_t;
+
/*! \internal \brief
* Data structure for passing information required during evaluation.
*/
typedef struct gmx_sel_evaluate_t
{
+ /** Memory pool for intermediate values. */
+ struct gmx_sel_mempool_t *mp;
/** Index group that contains all the atoms. */
gmx_ana_index_t *gall;
/** Topology information. */
/*@{*/
/** Initializes an evaluation data structure. */
void
-_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data, gmx_ana_index_t *gall,
+_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
+ struct gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
t_topology *top, t_trxframe *fr, t_pbc *pbc);
+/** Evaluates the children of a general selection element. */
+int
+_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
/** Evaluates the children of a \ref SEL_EXPRESSION element. */
int
_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
/** Evaluates a static group selection element. */
int
_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates an arithmetic expression element. */
+int
+_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
/*@}*/
/*! \name Subexpression evaluation functions
*/
/*@{*/
-/** Evaluates a subexpression, only handling the number of values. */
+/** Evaluates a subexpression when there is only one reference. */
+int
+_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a subexpression when the evaluation group is static. */
int
-_gmx_sel_evaluate_subexpr_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
/** Evaluates a subexpression. */
int
_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a subexpression reference, only handling the number of values. */
+/** Evaluates a subexpression reference when there are no other references. */
int
-_gmx_sel_evaluate_subexprref_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
/** Evaluates a subexpression reference. */
int
_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
#ifndef SELECTION_KEYWORDS_H
#define SELECTION_KEYWORDS_H
+struct gmx_ana_selmethod_t;
struct t_selelem;
+struct t_selexpr_param;
/** Selection method data for comparison expression evaluation. */
extern struct gmx_ana_selmethod_t sm_compare;
void
_gmx_selelem_set_kwpos_flags(struct t_selelem *sel, int flags);
+/** Does custom processing for parameters of the \c same selection method. */
+int
+_gmx_selelem_custom_init_same(struct gmx_ana_selmethod_t **method,
+ struct t_selexpr_param *params, void *scanner);
+
+/** Initializes a selection element for evaluating a keyword in a given group. */
+int
+_gmx_sel_init_keyword_evaluator(struct t_selelem **sel,
+ struct gmx_ana_selmethod_t *method,
+ struct t_selexpr_param *param, void *scanner);
+
#endif
--- /dev/null
+/*
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Memory pooling for selection evaluation.
+ *
+ * \todo
+ * Document these functions.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <gmx_fatal.h>
+#include <smalloc.h>
+
+#include <indexutil.h>
+
+#include "mempool.h"
+
+#define ALIGN_STEP 8
+
+typedef struct gmx_sel_mempool_block_t
+{
+ void *ptr;
+ size_t size;
+} gmx_sel_mempool_block_t;
+
+struct gmx_sel_mempool_t
+{
+ size_t currsize;
+ size_t freesize;
+ char *buffer;
+ char *freeptr;
+ int nblocks;
+ gmx_sel_mempool_block_t *blockstack;
+ int blockstack_nalloc;
+ size_t maxsize;
+};
+
+int
+_gmx_sel_mempool_create(gmx_sel_mempool_t **mpp)
+{
+ gmx_sel_mempool_t *mp;
+
+ snew(mp, 1);
+ mp->currsize = 0;
+ mp->freesize = 0;
+ mp->buffer = NULL;
+ mp->freeptr = NULL;
+ mp->nblocks = 0;
+ mp->blockstack = NULL;
+ mp->blockstack_nalloc = 0;
+ mp->maxsize = 0;
+ *mpp = mp;
+ return 0;
+}
+
+void
+_gmx_sel_mempool_destroy(gmx_sel_mempool_t *mp)
+{
+ if (!mp->buffer)
+ {
+ int i;
+
+ for (i = 0; i < mp->nblocks; ++i)
+ {
+ sfree(mp->blockstack[i].ptr);
+ }
+ }
+ sfree(mp->buffer);
+ sfree(mp->blockstack);
+ sfree(mp);
+}
+
+int
+_gmx_sel_mempool_alloc(gmx_sel_mempool_t *mp, void **ptrp, size_t size)
+{
+ void *ptr = NULL;
+ size_t size_walign;
+
+ *ptrp = NULL;
+ size_walign = ((size + ALIGN_STEP - 1) / ALIGN_STEP) * ALIGN_STEP;
+ if (mp->buffer)
+ {
+ if (mp->freesize < size)
+ {
+ gmx_bug("out of memory pool memory");
+ return ENOMEM;
+ }
+ ptr = mp->freeptr;
+ mp->freeptr += size_walign;
+ mp->freesize -= size_walign;
+ mp->currsize += size_walign;
+ }
+ else
+ {
+ ptr = malloc(size);
+ if (!ptr)
+ {
+ gmx_mem("out of memory");
+ return ENOMEM;
+ }
+ mp->currsize += size_walign;
+ if (mp->currsize > mp->maxsize)
+ {
+ mp->maxsize = mp->currsize;
+ }
+ }
+
+ if (mp->nblocks >= mp->blockstack_nalloc)
+ {
+ mp->blockstack_nalloc = mp->nblocks + 10;
+ srenew(mp->blockstack, mp->blockstack_nalloc);
+ }
+ mp->blockstack[mp->nblocks].ptr = ptr;
+ mp->blockstack[mp->nblocks].size = size_walign;
+ mp->nblocks++;
+
+ *ptrp = ptr;
+ return 0;
+}
+
+void
+_gmx_sel_mempool_free(gmx_sel_mempool_t *mp, void *ptr)
+{
+ int size;
+
+ if (ptr == NULL)
+ {
+ return;
+ }
+ assert(mp->nblocks > 0 && mp->blockstack[mp->nblocks - 1].ptr == ptr);
+ mp->nblocks--;
+ size = mp->blockstack[mp->nblocks].size;
+ mp->currsize -= size;
+ if (mp->buffer)
+ {
+ mp->freeptr = (char *)ptr;
+ mp->freesize += size;
+ }
+ else
+ {
+ sfree(ptr);
+ }
+}
+
+int
+_gmx_sel_mempool_reserve(gmx_sel_mempool_t *mp, size_t size)
+{
+ assert(mp->nblocks == 0 && !mp->buffer);
+ if (size == 0)
+ {
+ size = mp->maxsize;
+ }
+ mp->buffer = (char *)malloc(size);
+ if (!mp->buffer)
+ {
+ gmx_mem("out of memory");
+ return ENOMEM;
+ }
+ mp->freesize = size;
+ mp->freeptr = mp->buffer;
+ return 0;
+}
+
+int
+_gmx_sel_mempool_alloc_group(gmx_sel_mempool_t *mp, gmx_ana_index_t *g,
+ int isize)
+{
+ return _gmx_sel_mempool_alloc(mp, (void **)&g->index,
+ sizeof(*g->index)*isize);
+}
+
+void
+_gmx_sel_mempool_free_group(gmx_sel_mempool_t *mp, gmx_ana_index_t *g)
+{
+ _gmx_sel_mempool_free(mp, g->index);
+ g->index = NULL;
+}
--- /dev/null
+/*
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Declarations for memory pooling functions.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ */
+#ifndef GMX_SELECTION_MEMPOOL_H
+#define GMX_SELECTION_MEMPOOL_H
+
+struct gmx_ana_index_t;
+
+typedef struct gmx_sel_mempool_t gmx_sel_mempool_t;
+
+/** Create an empty memory pool. */
+int
+_gmx_sel_mempool_create(gmx_sel_mempool_t **mpp);
+/** Destroy a memory pool. */
+void
+_gmx_sel_mempool_destroy(gmx_sel_mempool_t *mp);
+
+/** Allocate memory from a memory pool. */
+int
+_gmx_sel_mempool_alloc(gmx_sel_mempool_t *mp, void **ptrp, size_t size);
+/** Release memory allocated from a memory pool. */
+void
+_gmx_sel_mempool_free(gmx_sel_mempool_t *mp, void *ptr);
+/** Set the size of a memory pool. */
+int
+_gmx_sel_mempool_reserve(gmx_sel_mempool_t *mp, size_t size);
+
+/** Convenience function for allocating an index group from a memory pool. */
+int
+_gmx_sel_mempool_alloc_group(gmx_sel_mempool_t *mp, struct gmx_ana_index_t *g,
+ int isize);
+/** Convenience function for freeing an index group from a memory pool. */
+void
+_gmx_sel_mempool_free_group(gmx_sel_mempool_t *mp, struct gmx_ana_index_t *g);
+
+#endif
return rc;
}
+/*! \brief
+ * Adds a child element for a parameter, keeping the parameter order.
+ *
+ * \param[in,out] root Root element to which the child is added.
+ * \param[in] child Child to add.
+ * \param[in] param Parameter for which this child is a value.
+ *
+ * Puts \p child in the child list of \p root such that the list remains
+ * in the same order as the corresponding parameters.
+ */
+static void
+place_child(t_selelem *root, t_selelem *child, gmx_ana_selparam_t *param)
+{
+ gmx_ana_selparam_t *ps;
+ int n;
+
+ ps = root->u.expr.method->param;
+ n = param - ps;
+ /* Put the child element in the correct place */
+ if (!root->child || n < root->child->u.param - ps)
+ {
+ child->next = root->child;
+ root->child = child;
+ }
+ else
+ {
+ t_selelem *prev;
+
+ prev = root->child;
+ while (prev->next && prev->next->u.param - ps >= n)
+ {
+ prev = prev->next;
+ }
+ child->next = prev->next;
+ prev->next = child;
+ }
+}
+
/*! \brief
* Comparison function for sorting integer ranges.
*
* \param[in] nval Number of values in \p values.
* \param[in] values Pointer to the list of values.
* \param param Parameter to parse.
+ * \param root Selection element to which child expressions are added.
* \returns TRUE if the values were parsed successfully, FALSE otherwise.
*
* For integer ranges, the sequence of numbers from the first to second value
* is stored, each as a separate value.
*/
static bool
-parse_values_varnum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
+parse_values_varnum(int nval, t_selexpr_value *values,
+ gmx_ana_selparam_t *param, t_selelem *root)
{
t_selexpr_value *value;
int i, j;
*param->nvalptr = param->val.nr;
}
param->nvalptr = NULL;
+ /* Create a dummy child element to store the string values.
+ * This element is responsible for freeing the values, but carries no
+ * other function. */
+ if (param->val.type == STR_VALUE)
+ {
+ t_selelem *child;
+
+ child = _gmx_selelem_create(SEL_CONST);
+ _gmx_selelem_set_vtype(child, STR_VALUE);
+ child->name = param->name;
+ child->flags &= ~SEL_ALLOCVAL;
+ child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA;
+ child->v.nr = param->val.nr;
+ _gmx_selvalue_setstore(&child->v, param->val.u.s);
+ /* Because the child is not group-valued, the u union is not used
+ * for anything, so we can abuse it by storing the parameter value
+ * as place_child() expects, but this is really ugly... */
+ child->u.param = param;
+ place_child(root, child, param);
+ }
return TRUE;
}
static t_selelem *
add_child(t_selelem *root, gmx_ana_selparam_t *param, t_selelem *expr)
{
- gmx_ana_selparam_t *ps;
- int n;
t_selelem *child;
int rc;
gmx_bug("unsupported root element for selection parameter parser");
return NULL;
}
- ps = root->u.expr.method->param;
- n = param - ps;
/* Create a subexpression reference element if necessary */
if (expr->type == SEL_SUBEXPRREF)
{
param->flags &= ~SPAR_DYNAMIC;
}
/* Put the child element in the correct place */
- if (!root->child || n < root->child->u.param - ps)
- {
- child->next = root->child;
- root->child = child;
- }
- else
- {
- t_selelem *prev;
-
- prev = root->child;
- while (prev->next && prev->next->u.param - ps >= n)
- {
- prev = prev->next;
- }
- child->next = prev->next;
- prev->next = child;
- }
+ place_child(root, child, param);
return child;
on_error:
return FALSE;
}
+ child->flags |= SEL_ALLOCVAL;
param->val.nr = -1;
*param->nvalptr = param->val.nr;
/* Rest of the initialization is done during compilation in
gmx_bug("internal error");
return FALSE;
}
+ sel->v.nr = 1;
sel->v.nalloc = -1;
return TRUE;
}
{
return FALSE;
}
+ child->flags |= SEL_ALLOCVAL;
if (child->v.type != GROUP_VALUE && (child->flags & SEL_ATOMVAL))
{
/* Rest of the initialization is done during compilation in
case REAL_VALUE:
val->u.r.r1 = val->u.r.r2 = expr->v.u.r[0];
break;
+ case STR_VALUE:
+ val->u.s = expr->v.u.s[0];
+ break;
case POS_VALUE:
copy_rvec(expr->v.u.p->x[0], val->u.x);
break;
}
else
{
- rc = parse_values_varnum(pparam->nval, pparam->value, oparam);
+ rc = parse_values_varnum(pparam->nval, pparam->value, oparam, root);
}
}
else if (oparam->flags & SPAR_ENUMVAL)
XOR = 285,
OR = 286,
AND = 287,
- NOT = 288
+ NOT = 288,
+ UNARY_NEG = 289
};
#endif
/* Tokens. */
#define OR 286
#define AND 287
#define NOT 288
+#define UNARY_NEG 289
struct t_selexpr_value *val;
struct t_selexpr_param *param;
}
-/* Line 193 of yacc.c. */
-#line 210 "parser.c"
+/* Line 187 of yacc.c. */
+#line 212 "parser.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
/* Line 216 of yacc.c. */
-#line 223 "parser.c"
+#line 225 "parser.c"
#ifdef short
# undef short
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 252
+#define YYLAST 329
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 38
+#define YYNTOKENS 44
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 19
+#define YYNNTS 20
/* YYNRULES -- Number of rules. */
-#define YYNRULES 68
+#define YYNRULES 76
/* YYNRULES -- Number of states. */
-#define YYNSTATES 110
+#define YYNSTATES 125
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 288
+#define YYMAXUTOK 289
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 35, 36, 2, 2, 37, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 34, 2, 2, 2, 2, 2, 2, 2, 2,
+ 41, 42, 36, 34, 43, 35, 2, 37, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 40, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 39, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 38
};
#if YYDEBUG
20, 22, 25, 29, 33, 37, 39, 41, 44, 47,
49, 51, 55, 59, 61, 63, 65, 67, 70, 74,
78, 82, 86, 89, 92, 94, 96, 99, 103, 107,
- 111, 113, 115, 118, 122, 126, 134, 138, 141, 145,
- 147, 149, 151, 153, 156, 157, 160, 163, 164, 166,
- 168, 171, 175, 177, 179, 181, 185, 189, 193
+ 111, 113, 115, 118, 122, 126, 130, 134, 138, 141,
+ 145, 149, 151, 154, 162, 166, 169, 173, 175, 177,
+ 179, 181, 184, 185, 188, 191, 192, 194, 196, 199,
+ 203, 205, 207, 209, 211, 215, 219
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 39, 0, -1, -1, 39, 40, -1, 41, 10, -1,
- 1, 10, -1, -1, 42, -1, 6, -1, 46, -1,
- 44, -1, 46, 44, -1, 9, 34, 47, -1, 9,
- 34, 49, -1, 9, 34, 50, -1, 4, -1, 43,
- -1, 4, 5, -1, 43, 5, -1, 50, -1, 47,
- -1, 35, 44, 36, -1, 44, 23, 51, -1, 6,
- -1, 7, -1, 8, -1, 9, -1, 33, 47, -1,
- 47, 32, 47, -1, 47, 31, 47, -1, 35, 47,
- 36, -1, 49, 28, 49, -1, 11, 46, -1, 11,
- 6, -1, 24, -1, 18, -1, 48, 19, -1, 48,
- 17, 55, -1, 48, 16, 55, -1, 48, 21, 51,
- -1, 6, -1, 7, -1, 48, 16, -1, 48, 20,
- 51, -1, 35, 49, 36, -1, 35, 45, 37, 45,
- 37, 45, 36, -1, 35, 50, 36, -1, 22, 51,
- -1, 18, 27, 47, -1, 14, -1, 13, -1, 15,
- -1, 52, -1, 52, 26, -1, -1, 52, 53, -1,
- 25, 54, -1, -1, 55, -1, 56, -1, 55, 56,
- -1, 55, 37, 56, -1, 47, -1, 50, -1, 49,
+ 45, 0, -1, -1, 45, 46, -1, 47, 10, -1,
+ 1, 10, -1, -1, 48, -1, 6, -1, 52, -1,
+ 50, -1, 52, 50, -1, 9, 40, 53, -1, 9,
+ 40, 55, -1, 9, 40, 57, -1, 4, -1, 49,
+ -1, 4, 5, -1, 49, 5, -1, 57, -1, 53,
+ -1, 41, 50, 42, -1, 50, 23, 58, -1, 6,
+ -1, 7, -1, 8, -1, 9, -1, 33, 53, -1,
+ 53, 32, 53, -1, 53, 31, 53, -1, 41, 53,
+ 42, -1, 55, 28, 55, -1, 11, 52, -1, 11,
+ 6, -1, 24, -1, 18, -1, 54, 19, -1, 54,
+ 17, 62, -1, 54, 16, 62, -1, 54, 21, 58,
+ -1, 6, -1, 7, -1, 54, 16, -1, 54, 20,
+ 58, -1, 55, 34, 55, -1, 55, 35, 55, -1,
+ 55, 36, 55, -1, 55, 37, 55, -1, 35, 55,
+ -1, 55, 39, 55, -1, 41, 55, 42, -1, 52,
+ -1, 54, 17, -1, 41, 51, 43, 51, 43, 51,
+ 42, -1, 41, 57, 42, -1, 22, 58, -1, 18,
+ 27, 53, -1, 14, -1, 13, -1, 15, -1, 59,
+ -1, 59, 26, -1, -1, 59, 60, -1, 25, 61,
+ -1, -1, 62, -1, 63, -1, 62, 63, -1, 62,
+ 43, 63, -1, 53, -1, 57, -1, 55, -1, 56,
-1, 6, 12, 6, -1, 6, 12, 7, -1, 7,
- 12, 45, -1, 46, -1
+ 12, 51, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 166, 166, 167, 176, 177, 197, 201, 202, 211,
- 221, 223, 225, 227, 229, 235, 236, 239, 240, 244,
- 245, 250, 251, 262, 263, 266, 267, 275, 281, 287,
- 299, 303, 311, 317, 325, 326, 330, 335, 340, 348,
- 360, 367, 377, 382, 390, 398, 403, 407, 415, 426,
- 430, 434, 443, 445, 450, 451, 456, 463, 464, 468,
- 469, 471, 475, 477, 479, 481, 486, 491, 496
+ 0, 173, 173, 174, 183, 184, 204, 208, 209, 218,
+ 228, 230, 232, 234, 236, 242, 243, 246, 247, 251,
+ 252, 257, 258, 269, 270, 273, 274, 282, 288, 294,
+ 306, 310, 318, 324, 332, 333, 337, 342, 347, 355,
+ 367, 374, 384, 389, 397, 399, 401, 403, 405, 407,
+ 409, 416, 423, 435, 440, 444, 452, 463, 467, 471,
+ 480, 482, 487, 488, 493, 500, 501, 505, 506, 508,
+ 512, 514, 516, 518, 520, 525, 530
};
#endif
"KEYWORD_STR", "KEYWORD_POS", "KEYWORD_GROUP", "METHOD_NUMERIC",
"METHOD_GROUP", "METHOD_POS", "MODIFIER", "EMPTY_POSMOD", "PARAM",
"END_OF_METHOD", "OF", "CMP_OP", "PARAM_REDUCT", "XOR", "OR", "AND",
- "NOT", "'='", "'('", "')'", "','", "$accept", "commands", "command",
- "cmd_plain", "help_request", "help_topic", "selection", "number",
- "string", "sel_expr", "pos_mod", "num_expr", "pos_expr", "method_params",
- "method_param_list", "method_param", "value_list", "value_list_nonempty",
- "value_item", 0
+ "NOT", "'+'", "'-'", "'*'", "'/'", "UNARY_NEG", "'^'", "'='", "'('",
+ "')'", "','", "$accept", "commands", "command", "cmd_plain",
+ "help_request", "help_topic", "selection", "number", "string",
+ "sel_expr", "pos_mod", "num_expr", "str_expr", "pos_expr",
+ "method_params", "method_param_list", "method_param", "value_list",
+ "value_list_nonempty", "value_item", 0
};
#endif
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
- 285, 286, 287, 288, 61, 40, 41, 44
+ 285, 286, 287, 288, 43, 45, 42, 47, 289, 94,
+ 61, 40, 41, 44
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 38, 39, 39, 40, 40, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 42, 42, 43, 43, 44,
- 44, 44, 44, 45, 45, 46, 46, 47, 47, 47,
- 47, 47, 47, 47, 48, 48, 47, 47, 47, 47,
- 49, 49, 49, 49, 49, 50, 50, 50, 50, 47,
- 49, 50, 51, 51, 52, 52, 53, 54, 54, 55,
- 55, 55, 56, 56, 56, 56, 56, 56, 56
+ 0, 44, 45, 45, 46, 46, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 48, 48, 49, 49, 50,
+ 50, 50, 50, 51, 51, 52, 52, 53, 53, 53,
+ 53, 53, 53, 53, 54, 54, 53, 53, 53, 53,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 56, 56, 57, 57, 57, 57, 53, 55, 57,
+ 58, 58, 59, 59, 60, 61, 61, 62, 62, 62,
+ 63, 63, 63, 63, 63, 63, 63
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
1, 2, 3, 3, 3, 1, 1, 2, 2, 1,
1, 3, 3, 1, 1, 1, 1, 2, 3, 3,
3, 3, 2, 2, 1, 1, 2, 3, 3, 3,
- 1, 1, 2, 3, 3, 7, 3, 2, 3, 1,
- 1, 1, 1, 2, 0, 2, 2, 0, 1, 1,
- 2, 3, 1, 1, 1, 3, 3, 3, 1
+ 1, 1, 2, 3, 3, 3, 3, 3, 2, 3,
+ 3, 1, 2, 7, 3, 2, 3, 1, 1, 1,
+ 1, 2, 0, 2, 2, 0, 1, 1, 2, 3,
+ 1, 1, 1, 1, 3, 3, 3
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 2, 0, 1, 0, 15, 8, 41, 25, 26, 0,
- 50, 49, 51, 35, 54, 34, 0, 0, 3, 0,
- 7, 16, 10, 9, 20, 0, 0, 19, 5, 17,
- 0, 33, 26, 32, 0, 47, 52, 40, 35, 0,
- 27, 40, 41, 0, 0, 20, 0, 19, 4, 18,
- 54, 11, 0, 0, 42, 0, 36, 54, 54, 0,
- 0, 12, 13, 14, 48, 57, 53, 55, 0, 21,
- 0, 30, 44, 46, 22, 29, 28, 40, 41, 68,
- 62, 64, 63, 38, 59, 37, 43, 39, 0, 0,
- 31, 0, 56, 58, 23, 24, 0, 0, 0, 0,
- 60, 0, 42, 0, 65, 66, 67, 61, 0, 45
+ 2, 0, 1, 0, 15, 40, 41, 25, 26, 0,
+ 58, 57, 59, 35, 62, 34, 0, 0, 0, 3,
+ 0, 7, 16, 10, 9, 20, 0, 0, 19, 5,
+ 17, 0, 33, 26, 32, 0, 55, 60, 40, 35,
+ 0, 27, 0, 0, 48, 40, 41, 0, 0, 20,
+ 0, 19, 4, 18, 62, 11, 0, 0, 42, 0,
+ 36, 62, 62, 0, 0, 0, 0, 0, 0, 0,
+ 12, 13, 14, 56, 65, 61, 63, 0, 0, 42,
+ 21, 0, 30, 50, 54, 22, 29, 28, 40, 41,
+ 51, 70, 0, 72, 73, 71, 38, 67, 37, 43,
+ 39, 31, 44, 45, 46, 47, 49, 0, 64, 66,
+ 23, 24, 0, 0, 0, 52, 0, 68, 0, 74,
+ 75, 76, 69, 0, 53
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 1, 18, 19, 20, 21, 22, 44, 79, 80,
- 25, 81, 82, 35, 36, 67, 92, 83, 84
+ -1, 1, 19, 20, 21, 22, 23, 48, 90, 91,
+ 26, 93, 94, 95, 36, 37, 76, 108, 98, 97
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -74
+#define YYPACT_NINF -87
static const yytype_int16 yypact[] =
{
- -74, 64, -74, 13, 4, 14, -74, -74, 16, 40,
- -74, -74, -74, 33, -74, -74, 207, 133, -74, 47,
- -74, 58, 46, 156, -4, 96, 48, -74, -74, -74,
- 170, -74, -74, -74, 207, -74, 30, -74, -74, 207,
- -74, 52, 53, -15, 54, 49, -23, 56, -74, -74,
- -74, 46, 207, 207, 119, 119, -74, -74, -74, 217,
- 193, -4, 48, -74, -4, 119, -74, -74, 49, -74,
- 60, -74, -74, -74, -74, -74, -74, 91, 92, -74,
- -4, -74, -74, 87, -74, 87, -74, -74, 217, -9,
- -74, 56, -74, 87, -74, -74, 69, 77, 60, 119,
- -74, 71, -74, 60, -74, -74, -74, -74, 72, -74
+ -87, 124, -87, -1, 6, 8, -87, -87, 12, 56,
+ -87, -87, -87, 17, -87, -87, 278, 288, 200, -87,
+ 53, -87, 75, 66, 225, 0, 133, 84, -87, -87,
+ -87, 239, -87, -87, -87, 278, -87, 57, -87, -87,
+ 278, -87, 288, -14, 55, 54, 58, -16, 63, -18,
+ 68, 69, -87, -87, -87, 66, 278, 278, 186, 186,
+ -87, -87, -87, 288, 288, 288, 288, 288, 288, 264,
+ 0, 84, -87, 0, 186, -87, -87, -18, 51, -87,
+ -87, 102, -87, -87, -87, -87, 83, -87, 110, 114,
+ -87, 0, 164, 19, -87, -87, 155, -87, 155, -87,
+ -87, 19, 38, 38, 55, 55, 55, 69, -87, 155,
+ -87, -87, 93, 107, 102, 186, 186, -87, 102, -87,
+ -87, -87, -87, 85, -87
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -74, -74, -74, -74, -74, -74, 24, -64, 36, 1,
- -58, -1, 2, -14, -74, -74, -74, -51, -73
+ -87, -87, -87, -87, -87, -87, 15, -78, 28, 60,
+ -17, 3, -87, 4, -46, -87, -87, -87, -57, -86
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -41
+#define YYTABLE_NINF -25
static const yytype_int8 yytable[] =
{
- 26, 89, 24, 27, 85, 59, 96, 102, 50, 29,
- 100, 57, 100, 72, 93, 26, 46, 40, 45, 47,
- 100, 69, 26, 28, 24, 27, 107, 52, 53, 62,
- 89, 61, 63, 26, 106, 64, 74, 23, 46, 108,
- 68, 43, -40, 86, 87, 33, 31, 51, 7, 32,
- 30, 26, 26, 75, 76, 65, 66, 48, 90, 46,
- 34, 68, 91, 49, 2, 3, 94, 95, 4, 50,
- 5, 6, 7, 8, -6, 9, 59, 10, 11, 12,
- 52, 53, 13, 104, 105, 71, 14, 101, 15, -23,
- -24, 70, 73, 77, 78, 7, 32, 16, 9, 17,
- 10, 11, 12, 97, 98, 13, 103, 72, 109, 14,
- 0, 15, 54, 55, 0, 56, 57, 58, 0, 0,
- 16, 0, 60, 0, 99, 77, 78, 7, 32, 0,
- 9, 0, 10, 11, 12, 0, 0, 13, 0, 41,
- 42, 14, 0, 15, 9, 0, 10, 11, 12, 0,
- 0, 13, 16, 0, 60, 14, 0, 15, 0, 0,
- 0, 0, 37, 6, 0, 0, 16, 9, 17, 10,
- 11, 12, 0, 0, 13, 0, 37, 6, 14, 0,
+ 43, 96, 79, 112, 27, 28, 61, 54, 85, 29,
+ 117, 30, 117, 56, 57, 99, 100, 109, -8, 27,
+ 44, 50, 51, 117, 82, 43, 80, 27, 28, 24,
+ 122, 56, 57, 47, 71, 72, 121, 34, 27, 55,
+ 123, 92, 92, 50, 35, 78, 43, 43, 43, 43,
+ 43, 43, 31, 64, 65, 66, 67, 92, 68, 27,
+ 27, 25, 32, 52, 7, 33, 101, 102, 103, 104,
+ 105, 106, 50, 107, 66, 67, 41, 68, 49, 92,
+ 53, 92, 74, 75, 25, 64, 65, 66, 67, 54,
+ 68, 70, 92, 83, 68, 73, 63, -23, 92, 92,
+ 77, -24, 64, 65, 66, 67, 81, 68, 110, 111,
+ 83, 84, 63, 119, 120, 57, 86, 87, 64, 65,
+ 66, 67, 113, 68, 2, 3, 114, 124, 4, 77,
+ 5, 6, 7, 8, -6, 9, 118, 10, 11, 12,
+ 0, 0, 13, 0, 0, 0, 14, 0, 15, 58,
+ 59, 0, 60, 61, 62, 0, 0, 16, 0, 17,
+ 0, 88, 89, 7, 33, 18, 9, 0, 10, 11,
+ 12, 0, 0, 13, 0, 0, 0, 14, 0, 15,
+ 58, 115, 0, 60, 61, 62, 0, 0, 16, 0,
+ 17, 0, 88, 89, 7, 33, 69, 9, 116, 10,
+ 11, 12, 0, 0, 13, 0, 45, 46, 14, 0,
15, 9, 0, 10, 11, 12, 0, 0, 13, 16,
- 0, 17, 14, 0, 15, 0, 0, 0, 0, 41,
- 42, 0, 0, 16, 9, 60, 10, 11, 12, 0,
- 0, 13, 0, 37, 6, 14, 0, 15, 9, 0,
- 10, 11, 0, 37, 6, 38, 16, 0, 60, 0,
- 10, 15, 0, 0, 0, 38, 0, 0, 0, 0,
- 16, 15, 39, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 88
+ 0, 17, 14, 0, 15, 0, 0, 69, 0, 0,
+ 0, 38, 6, 16, 0, 17, 9, 0, 10, 11,
+ 12, 18, 0, 13, 0, 38, 6, 14, 0, 15,
+ 9, 0, 10, 11, 12, 0, 0, 13, 16, 0,
+ 17, 14, 0, 15, 0, 0, 18, 0, 0, 0,
+ 45, 46, 16, 0, 17, 9, 0, 10, 11, 12,
+ 69, 0, 13, 0, 38, 6, 14, 0, 15, 9,
+ 0, 10, 11, 0, 38, 6, 39, 16, 0, 17,
+ 0, 10, 15, 0, 0, 69, 39, 0, 0, 0,
+ 0, 16, 15, 17, 0, 0, 0, 0, 0, 40,
+ 0, 0, 0, 17, 0, 0, 0, 0, 0, 42
};
static const yytype_int8 yycheck[] =
{
- 1, 59, 1, 1, 55, 28, 70, 16, 23, 5,
- 83, 20, 85, 36, 65, 16, 17, 16, 17, 17,
- 93, 36, 23, 10, 23, 23, 99, 31, 32, 30,
- 88, 30, 30, 34, 98, 34, 50, 1, 39, 103,
- 39, 17, 28, 57, 58, 9, 6, 23, 8, 9,
- 34, 52, 53, 52, 53, 25, 26, 10, 59, 60,
- 27, 60, 60, 5, 0, 1, 6, 7, 4, 23,
- 6, 7, 8, 9, 10, 11, 28, 13, 14, 15,
- 31, 32, 18, 6, 7, 36, 22, 88, 24, 37,
- 37, 37, 36, 6, 7, 8, 9, 33, 11, 35,
- 13, 14, 15, 12, 12, 18, 37, 36, 36, 22,
- -1, 24, 16, 17, -1, 19, 20, 21, -1, -1,
- 33, -1, 35, -1, 37, 6, 7, 8, 9, -1,
- 11, -1, 13, 14, 15, -1, -1, 18, -1, 6,
- 7, 22, -1, 24, 11, -1, 13, 14, 15, -1,
- -1, 18, 33, -1, 35, 22, -1, 24, -1, -1,
- -1, -1, 6, 7, -1, -1, 33, 11, 35, 13,
+ 17, 58, 16, 81, 1, 1, 20, 23, 54, 10,
+ 96, 5, 98, 31, 32, 61, 62, 74, 10, 16,
+ 17, 18, 18, 109, 42, 42, 42, 24, 24, 1,
+ 116, 31, 32, 18, 31, 31, 114, 9, 35, 24,
+ 118, 58, 59, 40, 27, 42, 63, 64, 65, 66,
+ 67, 68, 40, 34, 35, 36, 37, 74, 39, 56,
+ 57, 1, 6, 10, 8, 9, 63, 64, 65, 66,
+ 67, 68, 69, 69, 36, 37, 16, 39, 18, 96,
+ 5, 98, 25, 26, 24, 34, 35, 36, 37, 23,
+ 39, 31, 109, 42, 39, 35, 28, 43, 115, 116,
+ 40, 43, 34, 35, 36, 37, 43, 39, 6, 7,
+ 42, 42, 28, 6, 7, 32, 56, 57, 34, 35,
+ 36, 37, 12, 39, 0, 1, 12, 42, 4, 69,
+ 6, 7, 8, 9, 10, 11, 43, 13, 14, 15,
+ -1, -1, 18, -1, -1, -1, 22, -1, 24, 16,
+ 17, -1, 19, 20, 21, -1, -1, 33, -1, 35,
+ -1, 6, 7, 8, 9, 41, 11, -1, 13, 14,
+ 15, -1, -1, 18, -1, -1, -1, 22, -1, 24,
+ 16, 17, -1, 19, 20, 21, -1, -1, 33, -1,
+ 35, -1, 6, 7, 8, 9, 41, 11, 43, 13,
14, 15, -1, -1, 18, -1, 6, 7, 22, -1,
24, 11, -1, 13, 14, 15, -1, -1, 18, 33,
- -1, 35, 22, -1, 24, -1, -1, -1, -1, 6,
- 7, -1, -1, 33, 11, 35, 13, 14, 15, -1,
- -1, 18, -1, 6, 7, 22, -1, 24, 11, -1,
- 13, 14, -1, 6, 7, 18, 33, -1, 35, -1,
- 13, 24, -1, -1, -1, 18, -1, -1, -1, -1,
- 33, 24, 35, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 35
+ -1, 35, 22, -1, 24, -1, -1, 41, -1, -1,
+ -1, 6, 7, 33, -1, 35, 11, -1, 13, 14,
+ 15, 41, -1, 18, -1, 6, 7, 22, -1, 24,
+ 11, -1, 13, 14, 15, -1, -1, 18, 33, -1,
+ 35, 22, -1, 24, -1, -1, 41, -1, -1, -1,
+ 6, 7, 33, -1, 35, 11, -1, 13, 14, 15,
+ 41, -1, 18, -1, 6, 7, 22, -1, 24, 11,
+ -1, 13, 14, -1, 6, 7, 18, 33, -1, 35,
+ -1, 13, 24, -1, -1, 41, 18, -1, -1, -1,
+ -1, 33, 24, 35, -1, -1, -1, -1, -1, 41,
+ -1, -1, -1, 35, -1, -1, -1, -1, -1, 41
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 39, 0, 1, 4, 6, 7, 8, 9, 11,
- 13, 14, 15, 18, 22, 24, 33, 35, 40, 41,
- 42, 43, 44, 46, 47, 48, 49, 50, 10, 5,
- 34, 6, 9, 46, 27, 51, 52, 6, 18, 35,
- 47, 6, 7, 44, 45, 47, 49, 50, 10, 5,
- 23, 44, 31, 32, 16, 17, 19, 20, 21, 28,
- 35, 47, 49, 50, 47, 25, 26, 53, 47, 36,
- 37, 36, 36, 36, 51, 47, 47, 6, 7, 46,
- 47, 49, 50, 55, 56, 55, 51, 51, 35, 48,
- 49, 50, 54, 55, 6, 7, 45, 12, 12, 37,
- 56, 49, 16, 37, 6, 7, 45, 56, 45, 36
+ 0, 45, 0, 1, 4, 6, 7, 8, 9, 11,
+ 13, 14, 15, 18, 22, 24, 33, 35, 41, 46,
+ 47, 48, 49, 50, 52, 53, 54, 55, 57, 10,
+ 5, 40, 6, 9, 52, 27, 58, 59, 6, 18,
+ 41, 53, 41, 54, 55, 6, 7, 50, 51, 53,
+ 55, 57, 10, 5, 23, 50, 31, 32, 16, 17,
+ 19, 20, 21, 28, 34, 35, 36, 37, 39, 41,
+ 53, 55, 57, 53, 25, 26, 60, 53, 55, 16,
+ 42, 43, 42, 42, 42, 58, 53, 53, 6, 7,
+ 52, 53, 54, 55, 56, 57, 62, 63, 62, 58,
+ 58, 55, 55, 55, 55, 55, 55, 57, 61, 62,
+ 6, 7, 51, 12, 12, 17, 43, 63, 43, 6,
+ 7, 51, 63, 51, 42
};
#define yyerrok (yyerrstatus = 0)
we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# if YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
switch (yytype)
{
case 5: /* "HELP_TOPIC" */
-#line 146 "parser.y"
+#line 153 "parser.y"
{ free((yyvaluep->str)); };
-#line 1243 "parser.c"
+#line 1274 "parser.c"
break;
case 8: /* "STR" */
-#line 146 "parser.y"
+#line 153 "parser.y"
{ free((yyvaluep->str)); };
-#line 1248 "parser.c"
+#line 1279 "parser.c"
break;
case 9: /* "IDENTIFIER" */
-#line 146 "parser.y"
+#line 153 "parser.y"
{ free((yyvaluep->str)); };
-#line 1253 "parser.c"
+#line 1284 "parser.c"
break;
case 25: /* "PARAM" */
-#line 147 "parser.y"
+#line 154 "parser.y"
{ if((yyvaluep->str)) free((yyvaluep->str)); };
-#line 1258 "parser.c"
+#line 1289 "parser.c"
+ break;
+ case 28: /* "CMP_OP" */
+#line 153 "parser.y"
+ { free((yyvaluep->str)); };
+#line 1294 "parser.c"
break;
- case 40: /* "command" */
-#line 148 "parser.y"
+ case 46: /* "command" */
+#line 155 "parser.y"
{ if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
-#line 1263 "parser.c"
+#line 1299 "parser.c"
break;
- case 41: /* "cmd_plain" */
-#line 148 "parser.y"
+ case 47: /* "cmd_plain" */
+#line 155 "parser.y"
{ if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
-#line 1268 "parser.c"
+#line 1304 "parser.c"
break;
- case 44: /* "selection" */
-#line 149 "parser.y"
+ case 50: /* "selection" */
+#line 156 "parser.y"
{ _gmx_selelem_free_chain((yyvaluep->sel)); };
-#line 1273 "parser.c"
+#line 1309 "parser.c"
break;
- case 46: /* "string" */
-#line 146 "parser.y"
+ case 52: /* "string" */
+#line 153 "parser.y"
{ free((yyvaluep->str)); };
-#line 1278 "parser.c"
+#line 1314 "parser.c"
break;
- case 47: /* "sel_expr" */
-#line 150 "parser.y"
+ case 53: /* "sel_expr" */
+#line 157 "parser.y"
{ _gmx_selelem_free((yyvaluep->sel)); };
-#line 1283 "parser.c"
+#line 1319 "parser.c"
break;
- case 49: /* "num_expr" */
-#line 150 "parser.y"
+ case 55: /* "num_expr" */
+#line 157 "parser.y"
{ _gmx_selelem_free((yyvaluep->sel)); };
-#line 1288 "parser.c"
+#line 1324 "parser.c"
break;
- case 50: /* "pos_expr" */
-#line 150 "parser.y"
+ case 56: /* "str_expr" */
+#line 157 "parser.y"
{ _gmx_selelem_free((yyvaluep->sel)); };
-#line 1293 "parser.c"
+#line 1329 "parser.c"
break;
- case 51: /* "method_params" */
-#line 151 "parser.y"
+ case 57: /* "pos_expr" */
+#line 157 "parser.y"
+ { _gmx_selelem_free((yyvaluep->sel)); };
+#line 1334 "parser.c"
+ break;
+ case 58: /* "method_params" */
+#line 158 "parser.y"
{ _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1298 "parser.c"
+#line 1339 "parser.c"
break;
- case 52: /* "method_param_list" */
-#line 151 "parser.y"
+ case 59: /* "method_param_list" */
+#line 158 "parser.y"
{ _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1303 "parser.c"
+#line 1344 "parser.c"
break;
- case 53: /* "method_param" */
-#line 151 "parser.y"
+ case 60: /* "method_param" */
+#line 158 "parser.y"
{ _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1308 "parser.c"
+#line 1349 "parser.c"
break;
- case 54: /* "value_list" */
-#line 152 "parser.y"
+ case 61: /* "value_list" */
+#line 159 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1313 "parser.c"
+#line 1354 "parser.c"
break;
- case 55: /* "value_list_nonempty" */
-#line 152 "parser.y"
+ case 62: /* "value_list_nonempty" */
+#line 159 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1318 "parser.c"
+#line 1359 "parser.c"
break;
- case 56: /* "value_item" */
-#line 152 "parser.y"
+ case 63: /* "value_item" */
+#line 159 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1323 "parser.c"
+#line 1364 "parser.c"
break;
default:
switch (yyn)
{
case 2:
-#line 166 "parser.y"
+#line 173 "parser.y"
{ (yyval.sel) = NULL ;}
break;
case 3:
-#line 168 "parser.y"
+#line 175 "parser.y"
{
(yyval.sel) = _gmx_sel_append_selection((yyvsp[(2) - (2)].sel), (yyvsp[(1) - (2)].sel), scanner);
if (_gmx_sel_parser_should_finish(scanner))
break;
case 4:
-#line 176 "parser.y"
+#line 183 "parser.y"
{ (yyval.sel) = (yyvsp[(1) - (2)].sel); ;}
break;
case 5:
-#line 178 "parser.y"
+#line 185 "parser.y"
{
(yyval.sel) = NULL;
_gmx_selparser_error("invalid selection '%s'",
break;
case 6:
-#line 197 "parser.y"
+#line 204 "parser.y"
{
(yyval.sel) = NULL;
_gmx_sel_handle_empty_cmd(scanner);
break;
case 7:
-#line 201 "parser.y"
+#line 208 "parser.y"
{ (yyval.sel) = NULL; ;}
break;
case 8:
-#line 203 "parser.y"
+#line 210 "parser.y"
{
t_selelem *s, *p;
s = _gmx_sel_init_group_by_id((yyvsp[(1) - (1)].i), scanner);
break;
case 9:
-#line 212 "parser.y"
+#line 219 "parser.y"
{
t_selelem *s, *p;
s = _gmx_sel_init_group_by_name((yyvsp[(1) - (1)].str), scanner);
break;
case 10:
-#line 222 "parser.y"
+#line 229 "parser.y"
{ (yyval.sel) = _gmx_sel_init_selection(NULL, (yyvsp[(1) - (1)].sel), scanner); ;}
break;
case 11:
-#line 224 "parser.y"
+#line 231 "parser.y"
{ (yyval.sel) = _gmx_sel_init_selection((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].sel), scanner); ;}
break;
case 12:
-#line 226 "parser.y"
+#line 233 "parser.y"
{ (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner); ;}
break;
case 13:
-#line 228 "parser.y"
+#line 235 "parser.y"
{ (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner); ;}
break;
case 14:
-#line 230 "parser.y"
+#line 237 "parser.y"
{ (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner); ;}
break;
case 15:
-#line 235 "parser.y"
+#line 242 "parser.y"
{ _gmx_sel_handle_help_cmd(NULL, scanner); ;}
break;
case 17:
-#line 239 "parser.y"
+#line 246 "parser.y"
{ _gmx_sel_handle_help_cmd((yyvsp[(2) - (2)].str), scanner); ;}
break;
case 18:
-#line 240 "parser.y"
+#line 247 "parser.y"
{ _gmx_sel_handle_help_cmd((yyvsp[(2) - (2)].str), scanner); ;}
break;
case 19:
-#line 244 "parser.y"
+#line 251 "parser.y"
{ (yyval.sel) = (yyvsp[(1) - (1)].sel); ;}
break;
case 20:
-#line 246 "parser.y"
+#line 253 "parser.y"
{
(yyval.sel) = _gmx_sel_init_position((yyvsp[(1) - (1)].sel), NULL, scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 21:
-#line 250 "parser.y"
+#line 257 "parser.y"
{ (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
break;
case 22:
-#line 252 "parser.y"
+#line 259 "parser.y"
{
(yyval.sel) = _gmx_sel_init_modifier((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].sel), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 23:
-#line 262 "parser.y"
+#line 269 "parser.y"
{ (yyval.r) = (yyvsp[(1) - (1)].i); ;}
break;
case 24:
-#line 263 "parser.y"
+#line 270 "parser.y"
{ (yyval.r) = (yyvsp[(1) - (1)].r); ;}
break;
case 25:
-#line 266 "parser.y"
+#line 273 "parser.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); ;}
break;
case 26:
-#line 267 "parser.y"
+#line 274 "parser.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); ;}
break;
case 27:
-#line 276 "parser.y"
+#line 283 "parser.y"
{
(yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
(yyval.sel)->u.boolt = BOOL_NOT;
break;
case 28:
-#line 282 "parser.y"
+#line 289 "parser.y"
{
(yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
(yyval.sel)->u.boolt = BOOL_AND;
break;
case 29:
-#line 288 "parser.y"
+#line 295 "parser.y"
{
(yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
(yyval.sel)->u.boolt = BOOL_OR;
break;
case 30:
-#line 299 "parser.y"
+#line 306 "parser.y"
{ (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
break;
case 31:
-#line 304 "parser.y"
+#line 311 "parser.y"
{
(yyval.sel) = _gmx_sel_init_comparison((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), (yyvsp[(2) - (3)].str), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 32:
-#line 312 "parser.y"
+#line 319 "parser.y"
{
(yyval.sel) = _gmx_sel_init_group_by_name((yyvsp[(2) - (2)].str), scanner);
free((yyvsp[(2) - (2)].str));
break;
case 33:
-#line 318 "parser.y"
+#line 325 "parser.y"
{
(yyval.sel) = _gmx_sel_init_group_by_id((yyvsp[(2) - (2)].i), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 34:
-#line 325 "parser.y"
+#line 332 "parser.y"
{ (yyval.str) = NULL; ;}
break;
case 35:
-#line 326 "parser.y"
+#line 333 "parser.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); ;}
break;
case 36:
-#line 331 "parser.y"
+#line 338 "parser.y"
{
(yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 37:
-#line 336 "parser.y"
+#line 343 "parser.y"
{
(yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 38:
-#line 341 "parser.y"
+#line 348 "parser.y"
{
(yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 39:
-#line 349 "parser.y"
+#line 356 "parser.y"
{
(yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 40:
-#line 361 "parser.y"
+#line 368 "parser.y"
{
(yyval.sel) = _gmx_selelem_create(SEL_CONST);
_gmx_selelem_set_vtype((yyval.sel), INT_VALUE);
break;
case 41:
-#line 368 "parser.y"
+#line 375 "parser.y"
{
(yyval.sel) = _gmx_selelem_create(SEL_CONST);
_gmx_selelem_set_vtype((yyval.sel), REAL_VALUE);
break;
case 42:
-#line 378 "parser.y"
+#line 385 "parser.y"
{
(yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 43:
-#line 383 "parser.y"
+#line 390 "parser.y"
{
(yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
if ((yyval.sel) == NULL) YYERROR;
break;
case 44:
-#line 390 "parser.y"
- { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+#line 398 "parser.y"
+ { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '+', scanner); ;}
break;
case 45:
-#line 399 "parser.y"
- { (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r)); ;}
+#line 400 "parser.y"
+ { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '-', scanner); ;}
break;
case 46:
-#line 403 "parser.y"
- { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+#line 402 "parser.y"
+ { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '*', scanner); ;}
break;
case 47:
+#line 404 "parser.y"
+ { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '/', scanner); ;}
+ break;
+
+ case 48:
+#line 406 "parser.y"
+ { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(2) - (2)].sel), NULL, '-', scanner); ;}
+ break;
+
+ case 49:
#line 408 "parser.y"
+ { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '^', scanner); ;}
+ break;
+
+ case 50:
+#line 409 "parser.y"
+ { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+ break;
+
+ case 51:
+#line 417 "parser.y"
+ {
+ (yyval.sel) = _gmx_selelem_create(SEL_CONST);
+ _gmx_selelem_set_vtype((yyval.sel), STR_VALUE);
+ _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
+ (yyval.sel)->v.u.s[0] = (yyvsp[(1) - (1)].str);
+ ;}
+ break;
+
+ case 52:
+#line 424 "parser.y"
+ {
+ (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
+ if ((yyval.sel) == NULL) YYERROR;
+ ;}
+ break;
+
+ case 53:
+#line 436 "parser.y"
+ { (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r)); ;}
+ break;
+
+ case 54:
+#line 440 "parser.y"
+ { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+ break;
+
+ case 55:
+#line 445 "parser.y"
{
(yyval.sel) = _gmx_sel_init_method((yyvsp[(1) - (2)].meth), (yyvsp[(2) - (2)].param), NULL, scanner);
if ((yyval.sel) == NULL) YYERROR;
;}
break;
- case 48:
-#line 416 "parser.y"
+ case 56:
+#line 453 "parser.y"
{
(yyval.sel) = _gmx_sel_init_position((yyvsp[(3) - (3)].sel), (yyvsp[(1) - (3)].str), scanner);
if ((yyval.sel) == NULL) YYERROR;
;}
break;
- case 49:
-#line 427 "parser.y"
+ case 57:
+#line 464 "parser.y"
{ (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
break;
- case 50:
-#line 431 "parser.y"
+ case 58:
+#line 468 "parser.y"
{ (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
break;
- case 51:
-#line 435 "parser.y"
+ case 59:
+#line 472 "parser.y"
{ (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
break;
- case 52:
-#line 444 "parser.y"
+ case 60:
+#line 481 "parser.y"
{ (yyval.param) = process_param_list((yyvsp[(1) - (1)].param)); ;}
break;
- case 53:
-#line 446 "parser.y"
+ case 61:
+#line 483 "parser.y"
{ (yyval.param) = process_param_list((yyvsp[(1) - (2)].param)); ;}
break;
- case 54:
-#line 450 "parser.y"
+ case 62:
+#line 487 "parser.y"
{ (yyval.param) = NULL; ;}
break;
- case 55:
-#line 452 "parser.y"
+ case 63:
+#line 489 "parser.y"
{ (yyvsp[(2) - (2)].param)->next = (yyvsp[(1) - (2)].param); (yyval.param) = (yyvsp[(2) - (2)].param); ;}
break;
- case 56:
-#line 457 "parser.y"
+ case 64:
+#line 494 "parser.y"
{
(yyval.param) = _gmx_selexpr_create_param((yyvsp[(1) - (2)].str));
(yyval.param)->value = process_value_list((yyvsp[(2) - (2)].val), &(yyval.param)->nval);
;}
break;
- case 57:
-#line 463 "parser.y"
+ case 65:
+#line 500 "parser.y"
{ (yyval.val) = NULL; ;}
break;
- case 58:
-#line 464 "parser.y"
+ case 66:
+#line 501 "parser.y"
{ (yyval.val) = (yyvsp[(1) - (1)].val); ;}
break;
- case 59:
-#line 468 "parser.y"
+ case 67:
+#line 505 "parser.y"
{ (yyval.val) = (yyvsp[(1) - (1)].val); ;}
break;
- case 60:
-#line 470 "parser.y"
+ case 68:
+#line 507 "parser.y"
{ (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); ;}
break;
- case 61:
-#line 472 "parser.y"
+ case 69:
+#line 509 "parser.y"
{ (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); ;}
break;
- case 62:
-#line 476 "parser.y"
+ case 70:
+#line 513 "parser.y"
{ (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
break;
- case 63:
-#line 478 "parser.y"
+ case 71:
+#line 515 "parser.y"
{ (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
break;
- case 64:
-#line 480 "parser.y"
+ case 72:
+#line 517 "parser.y"
{ (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
break;
- case 65:
-#line 482 "parser.y"
+ case 73:
+#line 519 "parser.y"
+ { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
+ break;
+
+ case 74:
+#line 521 "parser.y"
{
(yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
(yyval.val)->u.i.i1 = (yyvsp[(1) - (3)].i); (yyval.val)->u.i.i2 = (yyvsp[(3) - (3)].i);
;}
break;
- case 66:
-#line 487 "parser.y"
+ case 75:
+#line 526 "parser.y"
{
(yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
(yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].i); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
;}
break;
- case 67:
-#line 492 "parser.y"
+ case 76:
+#line 531 "parser.y"
{
(yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
(yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
;}
break;
- case 68:
-#line 497 "parser.y"
- {
- (yyval.val) = _gmx_selexpr_create_value(STR_VALUE);
- (yyval.val)->u.s = (yyvsp[(1) - (1)].str);
- ;}
- break;
-
/* Line 1267 of yacc.c. */
-#line 2076 "parser.c"
+#line 2162 "parser.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
}
-#line 503 "parser.y"
+#line 537 "parser.y"
static t_selexpr_value *
XOR = 285,
OR = 286,
AND = 287,
- NOT = 288
+ NOT = 288,
+ UNARY_NEG = 289
};
#endif
/* Tokens. */
#define OR 286
#define AND 287
#define NOT 288
+#define UNARY_NEG 289
struct t_selexpr_value *val;
struct t_selexpr_param *param;
}
-/* Line 1529 of yacc.c. */
-#line 127 "parser.h"
+/* Line 1489 of yacc.c. */
+#line 129 "parser.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
%nonassoc <str> CMP_OP
/* A dummy token that determines the precedence of parameter reduction */
%nonassoc PARAM_REDUCT
-/* Operator tokens */
-%left AND OR XOR
+/* Boolean operator tokens */
+%left OR XOR
+%left AND
%left NOT
+/* Arithmetic operator tokens */
+%left '+' '-'
+%left '*' '/'
+%right UNARY_NEG /* Dummy token for unary negation precedence */
+%right '^'
/* Simple non-terminals */
%type <r> number
%type <sel> selection
%type <sel> sel_expr
%type <sel> num_expr
+%type <sel> str_expr
%type <sel> pos_expr
/* Parameter/value non-terminals */
%type <param> method_params method_param_list method_param
%type <val> value_list value_list_nonempty value_item
-%destructor { free($$); } HELP_TOPIC STR IDENTIFIER string
+%destructor { free($$); } HELP_TOPIC STR IDENTIFIER CMP_OP string
%destructor { if($$) free($$); } PARAM
%destructor { if($$) _gmx_selelem_free($$); } command cmd_plain
%destructor { _gmx_selelem_free_chain($$); } selection
-%destructor { _gmx_selelem_free($$); } sel_expr num_expr pos_expr
+%destructor { _gmx_selelem_free($$); } sel_expr num_expr str_expr pos_expr
%destructor { _gmx_selexpr_free_params($$); } method_params method_param_list method_param
%destructor { _gmx_selexpr_free_values($$); } value_list value_list_nonempty value_item
-%expect 72
+%expect 91
%debug
%pure-parser
}
;
-/* Grouping of numeric expressions */
-num_expr: '(' num_expr ')' { $$ = $2; }
+/* Arithmetic evaluation and grouping */
+num_expr: num_expr '+' num_expr
+ { $$ = _gmx_sel_init_arithmetic($1, $3, '+', scanner); }
+ | num_expr '-' num_expr
+ { $$ = _gmx_sel_init_arithmetic($1, $3, '-', scanner); }
+ | num_expr '*' num_expr
+ { $$ = _gmx_sel_init_arithmetic($1, $3, '*', scanner); }
+ | num_expr '/' num_expr
+ { $$ = _gmx_sel_init_arithmetic($1, $3, '/', scanner); }
+ | '-' num_expr %prec UNARY_NEG
+ { $$ = _gmx_sel_init_arithmetic($2, NULL, '-', scanner); }
+ | num_expr '^' num_expr
+ { $$ = _gmx_sel_init_arithmetic($1, $3, '^', scanner); }
+ | '(' num_expr ')' { $$ = $2; }
+;
+
+/********************************************************************
+ * STRING EXPRESSIONS
+ ********************************************************************/
+
+str_expr: string
+ {
+ $$ = _gmx_selelem_create(SEL_CONST);
+ _gmx_selelem_set_vtype($$, STR_VALUE);
+ _gmx_selvalue_reserve(&$$->v, 1);
+ $$->v.u.s[0] = $1;
+ }
+ | pos_mod KEYWORD_STR
+ {
+ $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
+ if ($$ == NULL) YYERROR;
+ }
;
/********************************************************************
{ $$ = _gmx_selexpr_create_value_expr($1); }
| num_expr %prec PARAM_REDUCT
{ $$ = _gmx_selexpr_create_value_expr($1); }
+ | str_expr %prec PARAM_REDUCT
+ { $$ = _gmx_selexpr_create_value_expr($1); }
| TOK_INT TO TOK_INT
{
$$ = _gmx_selexpr_create_value(INT_VALUE);
$$ = _gmx_selexpr_create_value(REAL_VALUE);
$$->u.r.r1 = $1; $$->u.r.r2 = $3;
}
- | string
- {
- $$ = _gmx_selexpr_create_value(STR_VALUE);
- $$->u.s = $1;
- }
;
%%
* which are in the order given in the input.
* The children always have \ref GROUP_VALUE, but different element types
* are possible.
+ *
+ *
+ * \subsection selparser_tree_arith Arithmetic elements
+ *
+ * One \ref SEL_ARITHMETIC element is created for each arithmetic operation in
+ * the input, and the tree structure represents the evaluation order.
+ * The \c t_selelem::optype type gives the name of the operation.
+ * Each element has exactly two children (one for unary negation elements),
+ * which are in the order given in the input.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
{
t_selelem *child;
int rc;
- bool bUseChildType;
+ bool bUseChildType=FALSE;
+ bool bOnlySingleChildren;
/* Return if the flags have already been set */
if (sel->flags & SEL_FLAGSSET)
bUseChildType = FALSE;
break;
+ case SEL_ARITHMETIC:
+ sel->flags |= SEL_ATOMVAL;
+ bUseChildType = FALSE;
+ break;
+
case SEL_MODIFIER:
if (sel->v.type != NO_VALUE)
{
bUseChildType = FALSE;
break;
- default:
+ case SEL_BOOLEAN:
+ case SEL_SUBEXPR:
+ case SEL_SUBEXPRREF:
bUseChildType = TRUE;
break;
}
/* Loop through children to propagate their flags upwards */
+ bOnlySingleChildren = TRUE;
child = sel->child;
while (child)
{
}
sel->flags |= (child->flags & SEL_VALTYPEMASK);
}
+ if (!(child->flags & SEL_SINGLEVAL))
+ {
+ bOnlySingleChildren = FALSE;
+ }
child = child->next;
}
- /* Mark that the flags are set */
- sel->flags |= SEL_FLAGSSET;
+ /* For arithmetic expressions consisting only of single values,
+ * the result is also a single value. */
+ if (sel->type == SEL_ARITHMETIC && bOnlySingleChildren)
+ {
+ sel->flags = (sel->flags & ~SEL_VALTYPEMASK) | SEL_SINGLEVAL;
+ }
/* For root elements, the type should be propagated here, after the
* children have been updated. */
if (sel->type == SEL_ROOT)
{
sel->flags |= (sel->child->flags & SEL_VALTYPEMASK);
}
+ /* Mark that the flags are set */
+ sel->flags |= SEL_FLAGSSET;
return 0;
}
-/*! \brief
- * Initializes the method parameter data of \ref SEL_EXPRESSION and
- * \ref SEL_MODIFIER elements.
- *
- * \param[in] sc Selection collection.
+/*!
* \param[in,out] sel Selection element to initialize.
+ * \param[in] scanner Scanner data structure.
*
* A deep copy of the parameters is made to allow several
* expressions with the same method to coexist peacefully.
* Calls sel_datafunc() if one is specified for the method.
*/
-static void
-init_method_params(gmx_ana_selcollection_t *sc, t_selelem *sel)
+void
+_gmx_selelem_init_method_params(t_selelem *sel, yyscan_t scanner)
{
int nparams;
gmx_ana_selparam_t *orgparam;
}
if (sel->u.expr.method->set_poscoll)
{
+ gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+
sel->u.expr.method->set_poscoll(sc->pcc, mdata);
}
/* Store the values */
sel->u.expr.mdata = mdata;
}
-/*! \brief
- * Initializes the method for a \ref SEL_EXPRESSION selection element.
- *
- * \param[in] sc Selection collection.
+/*!
* \param[in,out] sel Selection element to initialize.
* \param[in] method Selection method to set.
+ * \param[in] scanner Scanner data structure.
*
* Makes a copy of \p method and stores it in \p sel->u.expr.method,
- * and calls init_method_params();
+ * and calls _gmx_selelem_init_method_params();
*/
-static void
-set_method(gmx_ana_selcollection_t *sc, t_selelem *sel,
- gmx_ana_selmethod_t *method)
+void
+_gmx_selelem_set_method(t_selelem *sel, gmx_ana_selmethod_t *method,
+ yyscan_t scanner)
{
int i;
sel->name = method->name;
snew(sel->u.expr.method, 1);
memcpy(sel->u.expr.method, method, sizeof(gmx_ana_selmethod_t));
- init_method_params(sc, sel);
+ _gmx_selelem_init_method_params(sel, scanner);
}
/*! \brief
return rc;
}
+/*!
+ * \param[in] left Selection element for the left hand side.
+ * \param[in] right Selection element for the right hand side.
+ * \param[in] op String representation of the operator.
+ * \param[in] scanner Scanner data structure.
+ * \returns The created selection element.
+ *
+ * This function handles the creation of a \c t_selelem object for
+ * arithmetic expressions.
+ */
+t_selelem *
+_gmx_sel_init_arithmetic(t_selelem *left, t_selelem *right, char op,
+ yyscan_t scanner)
+{
+ t_selelem *sel;
+ char buf[2];
+
+ buf[0] = op;
+ buf[1] = 0;
+ sel = _gmx_selelem_create(SEL_ARITHMETIC);
+ sel->v.type = REAL_VALUE;
+ switch(op)
+ {
+ case '+': sel->u.arith.type = ARITH_PLUS; break;
+ case '-': sel->u.arith.type = (right ? ARITH_MINUS : ARITH_NEG); break;
+ case '*': sel->u.arith.type = ARITH_MULT; break;
+ case '/': sel->u.arith.type = ARITH_DIV; break;
+ case '^': sel->u.arith.type = ARITH_EXP; break;
+ }
+ sel->u.arith.opstr = strdup(buf);
+ sel->name = sel->u.arith.opstr;
+ sel->child = left;
+ sel->child->next = right;
+ return sel;
+}
+
/*!
* \param[in] left Selection element for the left hand side.
* \param[in] right Selection element for the right hand side.
_gmx_sel_init_comparison(t_selelem *left, t_selelem *right, char *cmpop,
yyscan_t scanner)
{
- gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
t_selelem *sel;
t_selexpr_param *params, *param;
const char *name;
int rc;
sel = _gmx_selelem_create(SEL_EXPRESSION);
- set_method(sc, sel, &sm_compare);
+ _gmx_selelem_set_method(sel, &sm_compare, scanner);
/* Create the parameter for the left expression */
name = left->v.type == INT_VALUE ? "int1" : "real1";
params = param = _gmx_selexpr_create_param(strdup(name));
root = _gmx_selelem_create(SEL_EXPRESSION);
child = root;
- set_method(sc, child, method);
+ _gmx_selelem_set_method(child, method, scanner);
/* Initialize the evaluation of keyword matching if values are provided */
if (args)
}
/* Initialize the selection element */
root = _gmx_selelem_create(SEL_EXPRESSION);
- set_method(sc, root, kwmethod);
+ _gmx_selelem_set_method(root, kwmethod, scanner);
params = param = _gmx_selexpr_create_param(NULL);
param->nval = 1;
param->value = _gmx_selexpr_create_value_expr(child);
*
* This function handles the creation of a \c t_selelem object for
* selection methods that take parameters.
+ *
+ * Part of the behavior of the \c same selection keyword is hardcoded into
+ * this function (or rather, into _gmx_selelem_custom_init_same()) to allow the
+ * use of any keyword in \c "same KEYWORD as" without requiring special
+ * handling somewhere else (or sacrificing the simple syntax).
*/
t_selelem *
_gmx_sel_init_method(gmx_ana_selmethod_t *method, t_selexpr_param *params,
int rc;
_gmx_sel_finish_method(scanner);
+ /* The "same" keyword needs some custom massaging of the parameters. */
+ rc = _gmx_selelem_custom_init_same(&method, params, scanner);
+ if (rc != 0)
+ {
+ _gmx_selexpr_free_params(params);
+ return NULL;
+ }
root = _gmx_selelem_create(SEL_EXPRESSION);
- set_method(sc, root, method);
+ _gmx_selelem_set_method(root, method, scanner);
/* Process the parameters */
if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
root->u.expr.method->param, root, scanner))
_gmx_sel_init_modifier(gmx_ana_selmethod_t *method, t_selexpr_param *params,
t_selelem *sel, yyscan_t scanner)
{
- gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
t_selelem *root;
t_selelem *mod;
t_selexpr_param *vparam;
_gmx_sel_finish_method(scanner);
mod = _gmx_selelem_create(SEL_MODIFIER);
- set_method(sc, mod, method);
+ _gmx_selelem_set_method(mod, method, scanner);
if (method->type == NO_VALUE)
{
t_selelem *child;
t_selelem *
_gmx_sel_init_position(t_selelem *expr, const char *type, yyscan_t scanner)
{
- gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
t_selelem *root;
t_selexpr_param *params;
root = _gmx_selelem_create(SEL_EXPRESSION);
- set_method(sc, root, &sm_keyword_pos);
+ _gmx_selelem_set_method(root, &sm_keyword_pos, scanner);
_gmx_selelem_set_kwpos_type(root, type);
/* Create the parameters for the parameter parser. */
params = _gmx_selexpr_create_param(NULL);
int
_gmx_selelem_update_flags(struct t_selelem *sel);
+/** Initializes the method parameter data of \ref SEL_EXPRESSION and
+ * \ref SEL_MODIFIER elements. */
+void
+_gmx_selelem_init_method_params(struct t_selelem *sel, void *scanner);
+/** Initializes the method for a \ref SEL_EXPRESSION selection element. */
+void
+_gmx_selelem_set_method(struct t_selelem *sel,
+ struct gmx_ana_selmethod_t *method, void *scanner);
+
+/** Creates a \c t_selelem for arithmetic expression evaluation. */
+struct t_selelem *
+_gmx_sel_init_arithmetic(struct t_selelem *left, struct t_selelem *right,
+ char op, void *scanner);
/** Creates a \c t_selelem for comparsion expression evaluation. */
struct t_selelem *
_gmx_sel_init_comparison(struct t_selelem *left, struct t_selelem *right,
bool bVelocities;
/** TRUE if forces should be evaluated for output positions. */
bool bForces;
+ /** TRUE if debugging output should be printed during compilation. */
+ bool bDebugCompile;
/** Root of the selection element tree. */
struct t_selelem *root;
struct gmx_ana_index_t gall;
/** Position calculation collection used for selection position evaluation. */
struct gmx_ana_poscalc_coll_t *pcc;
+ /** Memory pool used for selection evaluation. */
+ struct gmx_sel_mempool_t *mempool;
/** Parser symbol table. */
struct gmx_sel_symtab_t *symtab;
};
#include <selection.h>
#include <selmethod.h>
+#include "mempool.h"
#include "selcollection.h"
#include "selelem.h"
#include "symrec.h"
sc->bMaskOnly = FALSE;
sc->bVelocities = FALSE;
sc->bForces = FALSE;
+ sc->bDebugCompile = FALSE;
sc->root = NULL;
sc->nr = 0;
sc->sel = NULL;
sc->top = NULL;
gmx_ana_index_clear(&sc->gall);
sc->pcc = pcc;
+ sc->mempool = NULL;
_gmx_sel_symtab_create(&sc->symtab);
*scp = sc;
return 0;
}
sfree(sc->varstrs);
gmx_ana_index_deinit(&sc->gall);
+ if (sc->mempool)
+ {
+ _gmx_sel_mempool_destroy(sc->mempool);
+ }
_gmx_selcollection_clear_symtab(sc);
sfree(sc);
}
#include <position.h>
#include <selmethod.h>
-#include "evaluate.h"
#include "keywords.h"
+#include "mempool.h"
#include "selelem.h"
/*!
case SEL_CONST: return "CONST";
case SEL_EXPRESSION: return "EXPR";
case SEL_BOOLEAN: return "BOOL";
+ case SEL_ARITHMETIC: return "ARITH";
case SEL_ROOT: return "ROOT";
case SEL_SUBEXPR: return "SUBEXPR";
case SEL_SUBEXPRREF: return "REF";
}
_gmx_selvalue_clear(&sel->v);
sel->evaluate = NULL;
+ sel->mempool = NULL;
sel->child = NULL;
sel->next = NULL;
sel->refcount = 1;
return 0;
}
+/*!
+ * \param[in,out] sel Selection element to reserve.
+ * \param[in] count Number of values to reserve memory for.
+ * \returns 0 on success or if no memory pool, non-zero on error.
+ *
+ * Reserves memory for the values of \p sel from the \p sel->mempool
+ * memory pool. If no memory pool is set, nothing is done.
+ */
+int
+_gmx_selelem_mempool_reserve(t_selelem *sel, int count)
+{
+ int rc = 0;
+
+ if (!sel->mempool)
+ {
+ return 0;
+ }
+ switch (sel->v.type)
+ {
+ case INT_VALUE:
+ rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.i,
+ sizeof(*sel->v.u.i)*count);
+ break;
+
+ case REAL_VALUE:
+ rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.r,
+ sizeof(*sel->v.u.r)*count);
+ break;
+
+ case GROUP_VALUE:
+ rc = _gmx_sel_mempool_alloc_group(sel->mempool, sel->v.u.g, count);
+ break;
+
+ default:
+ gmx_incons("mem pooling not implemented for requested type");
+ return -1;
+ }
+ return rc;
+}
+
+/*!
+ * \param[in,out] sel Selection element to release.
+ *
+ * Releases the memory allocated for the values of \p sel from the
+ * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
+ */
+void
+_gmx_selelem_mempool_release(t_selelem *sel)
+{
+ if (!sel->mempool)
+ {
+ return;
+ }
+ switch (sel->v.type)
+ {
+ case INT_VALUE:
+ case REAL_VALUE:
+ _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
+ _gmx_selvalue_setstore(&sel->v, NULL);
+ break;
+
+ case GROUP_VALUE:
+ if (sel->v.u.g)
+ {
+ _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
+ }
+ break;
+
+ default:
+ gmx_incons("mem pooling not implemented for requested type");
+ break;
+ }
+}
+
/*!
* \param[in] sel Selection to free.
*/
{
int i, n;
+ _gmx_selelem_mempool_release(sel);
if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
{
/* The number of position/group structures is constant, so the
sfree(sel->v.u.ptr);
}
_gmx_selvalue_setstore(&sel->v, NULL);
+ if (sel->type == SEL_SUBEXPRREF && sel->u.param)
+ {
+ sel->u.param->val.u.ptr = NULL;
+ }
}
/*!
- * \param[in] sel Selection to free.
+ * \param[in] method Method to free.
+ * \param[in] mdata Method data to free.
*/
void
-_gmx_selelem_free_exprdata(t_selelem *sel)
+_gmx_selelem_free_method(gmx_ana_selmethod_t *method, void *mdata)
{
- int i;
+ sel_freefunc free_func = NULL;
- if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
+ /* Save the pointer to the free function. */
+ if (method && method->free)
{
- /* Free method data */
- if (sel->u.expr.mdata)
- {
- if (sel->u.expr.method && sel->u.expr.method->free)
- {
- sel->u.expr.method->free(sel->u.expr.mdata);
- }
- sfree(sel->u.expr.mdata);
- sel->u.expr.mdata = NULL;
- }
- /* Free the method itself */
- if (sel->u.expr.method)
+ free_func = method->free;
+ }
+
+ /* Free the method itself.
+ * Has to be done before freeing the method data, because parameter
+ * values are typically stored in the method data, and here we may
+ * access them. */
+ if (method)
+ {
+ int i, j;
+
+ /* Free the memory allocated for the parameters that are not managed
+ * by the selection method itself. */
+ for (i = 0; i < method->nparams; ++i)
{
- /* If the method has not yet been initialized, we must free the
- * memory allocated for parameter values here. */
- if (!(sel->flags & SEL_METHODINIT))
+ gmx_ana_selparam_t *param = &method->param[i];
+
+ if (param->val.u.ptr)
{
- for (i = 0; i < sel->u.expr.method->nparams; ++i)
+ if (param->val.type == GROUP_VALUE)
{
- gmx_ana_selparam_t *param = &sel->u.expr.method->param[i];
-
- if ((param->flags & (SPAR_VARNUM | SPAR_ATOMVAL))
- && param->val.type != GROUP_VALUE
- && param->val.type != POS_VALUE)
+ for (j = 0; j < param->val.nr; ++j)
{
- /* We don't need to check for enum values here, because
- * SPAR_ENUMVAL cannot be combined with the flags
- * required above. If it ever will be, this results
- * in a double free within this function, which should
- * be relatively easy to debug.
- */
- if (param->val.type == STR_VALUE)
- {
- int j;
-
- for (j = 0; j < param->val.nr; ++j)
- {
- sfree(param->val.u.s[j]);
- }
- }
- sfree(param->val.u.ptr);
+ gmx_ana_index_deinit(¶m->val.u.g[j]);
+ }
+ }
+ else if (param->val.type == POS_VALUE)
+ {
+ for (j = 0; j < param->val.nr; ++j)
+ {
+ gmx_ana_pos_deinit(¶m->val.u.p[j]);
}
}
- }
- /* And even if it is, the arrays allocated for enum values need
- * to be freed. */
- for (i = 0; i < sel->u.expr.method->nparams; ++i)
- {
- gmx_ana_selparam_t *param = &sel->u.expr.method->param[i];
- if (param->flags & SPAR_ENUMVAL)
+ if (param->val.nalloc > 0)
{
sfree(param->val.u.ptr);
}
-
}
- sfree(sel->u.expr.method->param);
- sfree(sel->u.expr.method);
- sel->u.expr.method = NULL;
}
+ sfree(method->param);
+ sfree(method);
+ }
+ /* Free method data. */
+ if (mdata)
+ {
+ if (free_func)
+ {
+ free_func(mdata);
+ }
+ sfree(mdata);
+ }
+}
+
+/*!
+ * \param[in] sel Selection to free.
+ */
+void
+_gmx_selelem_free_exprdata(t_selelem *sel)
+{
+ if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
+ {
+ _gmx_selelem_free_method(sel->u.expr.method, sel->u.expr.mdata);
+ sel->u.expr.mdata = NULL;
+ sel->u.expr.method = NULL;
/* Free position data */
if (sel->u.expr.pos)
{
sel->u.expr.pc = NULL;
}
}
+ if (sel->type == SEL_ARITHMETIC)
+ {
+ sfree(sel->u.arith.opstr);
+ sel->u.arith.opstr = NULL;
+ }
+ if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
+ || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
+ {
+ gmx_ana_index_deinit(&sel->u.cgrp);
+ }
}
/*!
void
_gmx_selelem_free(t_selelem *sel)
{
- t_selelem *child, *prev;
-
/* Decrement the reference counter and do nothing if references remain */
sel->refcount--;
if (sel->refcount > 0)
return;
}
- /* Free the children */
- child = sel->child;
- while (child)
- {
- prev = child;
- child = child->next;
- _gmx_selelem_free(prev);
- }
+ /* Free the children.
+ * Must be done before freeing other data, because the children may hold
+ * references to data in this element. */
+ _gmx_selelem_free_chain(sel->child);
/* Free value storage */
_gmx_selelem_free_values(sel);
/* Free other storage */
_gmx_selelem_free_exprdata(sel);
- if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
- || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
- {
- gmx_ana_index_deinit(&sel->u.cgrp);
- }
/* Free temporary compiler data if present */
_gmx_selelem_free_compiler_data(sel);
}
}
-/*! \brief
- * Writes out a human-readable name for the evaluation function.
- *
- * \param[in] fp File handle to receive the output.
- * \param[in] sel Selection element for which the evaluation function is printed.
- */
-static void
-print_evaluation_func(FILE *fp, t_selelem *sel)
-{
- fprintf(fp, " eval=");
- if (!sel->evaluate)
- fprintf(fp, "none");
- else if (sel->evaluate == &_gmx_sel_evaluate_root)
- fprintf(fp, "root");
- else if (sel->evaluate == &_gmx_sel_evaluate_static)
- fprintf(fp, "static");
- else if (sel->evaluate == &_gmx_sel_evaluate_subexpr_pass)
- fprintf(fp, "subexpr_pass");
- else if (sel->evaluate == &_gmx_sel_evaluate_subexpr)
- fprintf(fp, "subexpr");
- else if (sel->evaluate == &_gmx_sel_evaluate_subexprref_pass)
- fprintf(fp, "ref_pass");
- else if (sel->evaluate == &_gmx_sel_evaluate_subexprref)
- fprintf(fp, "ref");
- else if (sel->evaluate == &_gmx_sel_evaluate_method)
- fprintf(fp, "method");
- else if (sel->evaluate == &_gmx_sel_evaluate_modifier)
- fprintf(fp, "mod");
- else if (sel->evaluate == &_gmx_sel_evaluate_not)
- fprintf(fp, "not");
- else if (sel->evaluate == &_gmx_sel_evaluate_and)
- fprintf(fp, "and");
- else if (sel->evaluate == &_gmx_sel_evaluate_or)
- fprintf(fp, "or");
- else
- fprintf(fp, "%p", (void*)(sel->evaluate));
-}
-
/*!
* \param[in] fp File handle to receive the output.
* \param[in] sel Root of the selection subtree to print.
{
fprintf(fp, "0");
}
+ if (sel->mempool)
+ {
+ fprintf(fp, "P");
+ }
if (sel->type == SEL_CONST)
{
if (sel->v.type == INT_VALUE)
}
if (sel->evaluate)
{
- print_evaluation_func(fp, sel);
+ fprintf(fp, " eval=");
+ _gmx_sel_print_evalfunc_name(fp, sel->evaluate);
}
if (sel->refcount > 1)
{
{
g = &sel->u.cgrp;
}
- if (g->isize > 0)
+ if (g->isize < 0)
+ {
+ fprintf(fp, "%*c group: (null)\n", level*2+1, ' ');
+ }
+ else if (g->isize > 0)
{
fprintf(fp, "%*c group:", level*2+1, ' ');
if (g->isize <= 20)
}
}
+ if (sel->cdata)
+ {
+ _gmx_selelem_print_compiler_info(fp, sel, level);
+ }
+
if (bValues && sel->type != SEL_CONST && sel->type != SEL_ROOT && sel->v.u.ptr)
{
fprintf(fp, "%*c value: ", level*2+1, ' ');
struct gmx_ana_selmethod_t;
struct gmx_sel_evaluate_t;
+struct gmx_sel_mempool_t;
struct t_selelem;
/********************************************************************/
SEL_EXPRESSION,
/** Boolean expression. */
SEL_BOOLEAN,
+ /** Arithmetic expression. */
+ SEL_ARITHMETIC,
/** Root node of the evaluation tree. */
SEL_ROOT,
/** Subexpression that may be referenced several times. */
BOOL_XOR /**< Xor (not implemented). */
} e_boolean_t;
+/** Defines the arithmetic operation of \c t_selelem objects with type \ref SEL_ARITHMETIC. */
+typedef enum
+{
+ ARITH_PLUS, /**< + */
+ ARITH_MINUS, /**< - */
+ ARITH_NEG, /**< Unary - */
+ ARITH_MULT, /**< * */
+ ARITH_DIV, /**< / */
+ ARITH_EXP /**< ^ (to power) */
+} e_arithmetic_t;
+
/** Returns a string representation of the type of a \c t_selelem. */
extern const char *
_gmx_selelem_type_str(struct t_selelem *sel);
* a selection.
*
* Even if the flag is set, \p v.u.ptr can be NULL during initialization.
+ *
+ * \todo
+ * This flag overlaps with the function of \p v.nalloc field, and could
+ * probably be removed, making memory management simpler. Currently, the
+ * \p v.nalloc field is not kept up-to-date in all cases when this flag
+ * is changed and is used in places where this flag is not, so this would
+ * require a careful investigation of the selection code.
*/
#define SEL_ALLOCVAL (1<<8)
/*! \brief
} expr;
/** Operation type for \ref SEL_BOOLEAN elements. */
e_boolean_t boolt;
+ /** Operation type for \ref SEL_ARITHMETIC elements. */
+ struct {
+ /** Operation type. */
+ e_arithmetic_t type;
+ /** String representation. */
+ char *opstr;
+ } arith;
/** Associated selection parameter for \ref SEL_SUBEXPRREF elements. */
struct gmx_ana_selparam_t *param;
} u;
+ /** Memory pool to use for values, or NULL if standard memory handling. */
+ struct gmx_sel_mempool_t *mempool;
/** Internal data for the selection compiler. */
struct t_compiler_data *cdata;
int refcount;
} t_selelem;
+/* In evaluate.c */
+/** Writes out a human-readable name for an evaluation function. */
+extern void
+_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc);
+
/** Allocates memory and performs some common initialization for a \c t_selelem. */
extern t_selelem *
_gmx_selelem_create(e_selelem_t type);
/** Sets the value type of a \c t_selelem. */
extern int
_gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype);
+/** Reserves memory for value of a \c t_selelem from a memory pool. */
+extern int
+_gmx_selelem_mempool_reserve(t_selelem *sel, int count);
+/** Releases memory pool used for value of a \c t_selelem. */
+extern void
+_gmx_selelem_mempool_release(t_selelem *sel);
/** Frees the memory allocated for a \c t_selelem structure and all its children. */
extern void
_gmx_selelem_free(t_selelem *sel);
/** Frees the memory allocated for the \c t_selelem::d union. */
extern void
_gmx_selelem_free_values(t_selelem *sel);
-/** Frees the memory allocated for the \c t_selelem::u.expr field. */
+/** Frees the memory allocated for a selection method. */
+extern void
+_gmx_selelem_free_method(struct gmx_ana_selmethod_t *method, void *mdata);
+/** Frees the memory allocated for the \c t_selelem::u field. */
extern void
_gmx_selelem_free_exprdata(t_selelem *sel);
/* In compiler.c */
/** Prints a human-readable version of a selection element subtree. */
extern void
_gmx_selelem_print_tree(FILE *fp, t_selelem *root, bool bValues, int level);
+/* In compile.c */
+/** Prints a human-readable version of the internal compiler data structure. */
+extern void
+_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level);
/** Returns TRUE if the selection element subtree requires topology information for evaluation. */
extern bool
"described under \"syntax\". Available keywords can be found under",
"\"keywords\", and concrete examples under \"examples\".",
"Other subtopics give more details on certain aspects.",
+ "\"help all\" prints the help for all subtopics.",
+};
+
+static const char *help_arithmetic[] = {
+ "ARITHMETIC EXPRESSIONS IN SELECTIONS[PAR]",
+
+ "Basic arithmetic evaluation is supported for numeric expressions.",
+ "Supported operations are addition, subtraction, negation, multiplication,",
+ "division, and exponentiation (using ^).",
+ "Result of a division by zero or other illegal operations is undefined.",
};
static const char *help_cmdline[] = {
static const char *help_limits[] = {
"SELECTION LIMITATIONS[PAR]",
- "Arithmetic expressions are not implemented.[PAR]",
-
"Some analysis programs may require a special structure for the input",
"selections (e.g., [TT]g_angle[tt] requires the index group to be made",
"of groups of three or four atoms).",
"For such programs, it is up to the user to provide a proper selection",
- "expression that always returns such positions.[PAR]",
+ "expression that always returns such positions.",
};
static const char *help_positions[] = {
};
static const t_selection_help_item helpitems[] = {
- {NULL, asize(help_common), help_common},
- {"cmdline", asize(help_cmdline), help_cmdline},
- {"evaluation", asize(help_eval), help_eval},
- {"examples", asize(help_examples), help_examples},
- {"keywords", asize(help_keywords), help_keywords},
- {"limitations", asize(help_limits), help_limits},
- {"positions", asize(help_positions), help_positions},
- {"syntax", asize(help_syntax), help_syntax},
+ {NULL, asize(help_common), help_common},
+ {"cmdline", asize(help_cmdline), help_cmdline},
+ {"syntax", asize(help_syntax), help_syntax},
+ {"positions", asize(help_positions), help_positions},
+ {"arithmetic", asize(help_arithmetic), help_arithmetic},
+ {"keywords", asize(help_keywords), help_keywords},
+ {"evaluation", asize(help_eval), help_eval},
+ {"limitations", asize(help_limits), help_limits},
+ {"examples", asize(help_examples), help_examples},
};
/*! \brief
}
else
{
- fprintf(stderr, "%s\n", method->name);
+ const char *symname = _gmx_sel_sym_name(symbol);
+
+ fprintf(stderr, "%s", symname);
+ if (strcmp(symname, method->name) != 0)
+ {
+ fprintf(stderr, " (synonym for %s)", method->name);
+ }
+ fprintf(stderr, "\n");
}
}
symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
void
_gmx_sel_print_help(struct gmx_ana_selcollection_t *sc, const char *topic)
{
- const t_selection_help_item *item = 0;
- int i;
+ const t_selection_help_item *item = NULL;
+ size_t i;
/* Find the item for the topic */
if (!topic)
{
item = &helpitems[0];
}
+ else if (strcmp(topic, "all") == 0)
+ {
+ for (i = 0; i < asize(helpitems); ++i)
+ {
+ item = &helpitems[i];
+ _gmx_sel_print_help(sc, item->topic);
+ if (i != asize(helpitems) - 1)
+ {
+ fprintf(stderr, "\n\n");
+ }
+ }
+ return;
+ }
else
{
for (i = 1; i < asize(helpitems); ++i)
if (strncmp(helpitems[i].topic, topic, strlen(topic)) == 0)
{
item = &helpitems[i];
+ break;
}
}
}
/* Special handling of certain pages */
if (!topic)
{
+ int len = 0;
+
/* Print the subtopics on the main page */
fprintf(stderr, "\nAvailable subtopics:\n");
for (i = 1; i < asize(helpitems); ++i)
{
+ int len1 = strlen(helpitems[i].topic) + 2;
+
+ len += len1;
+ if (len > 79)
+ {
+ fprintf(stderr, "\n");
+ len = len1;
+ }
fprintf(stderr, " %s", helpitems[i].topic);
}
fprintf(stderr, "\n");
extern gmx_ana_selmethod_t sm_none;
extern gmx_ana_selmethod_t sm_atomnr;
extern gmx_ana_selmethod_t sm_resnr;
-extern gmx_ana_selmethod_t sm_resind;
+extern gmx_ana_selmethod_t sm_resindex;
+extern gmx_ana_selmethod_t sm_molindex;
extern gmx_ana_selmethod_t sm_atomname;
extern gmx_ana_selmethod_t sm_atomtype;
extern gmx_ana_selmethod_t sm_resname;
/* From sm_permute.c */
extern gmx_ana_selmethod_t sm_permute;
+/*! \brief
+ * Helper structure for defining selection methods.
+ */
+typedef struct {
+ /*! \brief
+ * Name to register the method under.
+ *
+ * If NULL, use the actual name of the method.
+ * This field is used for defining synonyms.
+ */
+ const char *name;
+ /** Method data structure to register. */
+ gmx_ana_selmethod_t *method;
+} t_register_method;
+
/** Array of selection methods defined in the library. */
-static gmx_ana_selmethod_t *const smtable_def[] = {
- &sm_cog,
- &sm_com,
+static const t_register_method smtable_def[] = {
+ {NULL, &sm_cog},
+ {NULL, &sm_com},
- &sm_all,
- &sm_none,
- &sm_atomnr,
- &sm_resnr,
- &sm_resind,
- &sm_atomname,
- &sm_atomtype,
- &sm_resname,
- &sm_insertcode,
- &sm_chain,
- &sm_mass,
- &sm_charge,
- &sm_altloc,
- &sm_occupancy,
- &sm_betafactor,
- &sm_x,
- &sm_y,
- &sm_z,
+ {NULL, &sm_all},
+ {NULL, &sm_none},
+ {NULL, &sm_atomnr},
+ {NULL, &sm_resnr},
+ {"resid", &sm_resnr},
+ {NULL, &sm_resindex},
+ {"residue", &sm_resindex},
+ {NULL, &sm_molindex},
+ {"mol", &sm_molindex},
+ {"molecule", &sm_molindex},
+ {NULL, &sm_atomname},
+ {NULL, &sm_atomtype},
+ {NULL, &sm_resname},
+ {NULL, &sm_insertcode},
+ {NULL, &sm_chain},
+ {NULL, &sm_mass},
+ {NULL, &sm_charge},
+ {NULL, &sm_altloc},
+ {NULL, &sm_occupancy},
+ {NULL, &sm_betafactor},
+ {NULL, &sm_x},
+ {NULL, &sm_y},
+ {NULL, &sm_z},
- &sm_distance,
- &sm_mindistance,
- &sm_within,
- &sm_insolidangle,
- &sm_same,
+ {NULL, &sm_distance},
+ {NULL, &sm_mindistance},
+ {NULL, &sm_within},
+ {NULL, &sm_insolidangle},
+ {NULL, &sm_same},
- &sm_merge,
- &sm_plus,
- &sm_permute,
+ {NULL, &sm_merge},
+ {NULL, &sm_plus},
+ {NULL, &sm_permute},
};
/*! \brief
{
bool bOk = TRUE;
bool bNeedInit;
- bool bNeedFree;
int i;
/* Make some checks on init_data and free */
/* Warn of dynamic callbacks in static methods */
if (!(method->flags & SMETH_MODIFIER))
{
- if (method->init_frame && !(method->flags & SMETH_DYNAMIC))
- {
- report_error(fp, method->name, "warning: init_frame not used because the method is static");
- }
if (method->pupdate && !(method->flags & SMETH_DYNAMIC))
{
report_error(fp, method->name, "warning: pupdate not used because the method is static");
/* Loop through the parameters to determine if initialization callbacks
* are needed. */
bNeedInit = FALSE;
- bNeedFree = FALSE;
for (i = 0; i < method->nparams; ++i)
{
- if (method->param[i].val.type == POS_VALUE
- || method->param[i].val.type == GROUP_VALUE)
- {
- bNeedFree = TRUE;
- }
if (method->param[i].val.type != POS_VALUE
&& (method->param[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
{
bNeedInit = TRUE;
- bNeedFree = TRUE;
}
}
/* Check that the callbacks required by the parameters are present */
report_error(fp, method->name, "error: init should be provided");
bOk = FALSE;
}
- if (bNeedFree && !method->free)
- {
- report_error(fp, method->name, "error: free should be provided");
- bOk = FALSE;
- }
return bOk;
}
bOk = TRUE;
for (i = 0; i < asize(smtable_def); ++i)
{
- rc = gmx_ana_selmethod_register(sc, smtable_def[i]->name, smtable_def[i]);
+ gmx_ana_selmethod_t *method = smtable_def[i].method;
+
+ if (smtable_def[i].name == NULL)
+ {
+ rc = gmx_ana_selmethod_register(sc, method->name, method);
+ }
+ else
+ {
+ rc = gmx_ana_selmethod_register(sc, smtable_def[i].name, method);
+ }
if (rc != 0)
{
bOk = FALSE;
CMP_GTR, /**< '>' */
CMP_GEQ, /**< '>=' */
CMP_EQUAL, /**< '==' */
- CMP_NEQ, /**< '!=' */
+ CMP_NEQ /**< '!=' */
} e_comparison_t;
/** The operand has a single value. */
#define CMP_DYNAMICVAL 2
/** The value is real. */
#define CMP_REALVAL 4
+/** The integer array is allocated. */
+#define CMP_ALLOCINT 16
+/** The real array is allocated. */
+#define CMP_ALLOCREAL 32
/*! \internal \brief
* Data structure for comparison expression operand values.
/* Free the previous value if one is present. */
sfree(val->r);
val->r = rv;
- val->flags |= CMP_REALVAL;
+ val->flags |= CMP_REALVAL | CMP_ALLOCREAL;
}
/* \brief
sfree(val->i);
val->i = iv;
val->flags &= ~CMP_REALVAL;
+ val->flags |= CMP_ALLOCINT;
return 0;
}
t_methoddata_compare *d = (t_methoddata_compare *)data;
sfree(d->cmpop);
- sfree(d->left.i);
- sfree(d->left.r);
- sfree(d->right.i);
- sfree(d->right.r);
+ if (d->left.flags & CMP_ALLOCINT)
+ {
+ sfree(d->left.i);
+ }
+ if (d->left.flags & CMP_ALLOCREAL)
+ {
+ sfree(d->left.r);
+ }
+ if (d->right.flags & CMP_ALLOCINT)
+ {
+ sfree(d->right.i);
+ }
+ if (d->right.flags & CMP_ALLOCREAL)
+ {
+ sfree(d->right.r);
+ }
}
/*!
{
t_methoddata_distance *d = (t_methoddata_distance *)data;
- gmx_ana_pos_deinit(&d->p);
gmx_ana_nbsearch_free(d->nb);
}
t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
int i;
- gmx_ana_pos_deinit(&d->center);
- gmx_ana_pos_deinit(&d->span);
if (d->tbin)
{
for (i = 0; i < d->ntbins; ++i)
#define USE_REGEX
#endif
+#include <gmx_fatal.h>
#include <macros.h>
#include <smalloc.h>
#include <string2.h>
#include <selmethod.h>
+#include "keywords.h"
+#include "parsetree.h"
+#include "selelem.h"
+
/** Allocates data for integer keyword evaluation. */
static void *
init_data_kwint(int npar, gmx_ana_selparam_t *param);
/** Initializes data for string keyword evaluation. */
static int
init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Frees the memory allocated for integer keyword evaluation. */
-static void
-free_data_kwint(void *data);
-/** Frees the memory allocated for real keyword evaluation. */
-static void
-free_data_kwreal(void *data);
/** Frees the memory allocated for string keyword evaluation. */
static void
free_data_kwstr(void *data);
NULL,
&init_kwint,
NULL,
- &free_data_kwint,
+ NULL,
NULL,
&evaluate_keyword_int,
NULL,
NULL,
&init_kwreal,
NULL,
- &free_data_kwreal,
+ NULL,
NULL,
&evaluate_keyword_real,
NULL,
{NULL, 0, NULL},
};
+/** Initializes keyword evaluation for an arbitrary group. */
+static int
+init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes output for keyword evaluation in an arbitrary group. */
+static int
+init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data);
+/** Frees the data allocated for keyword evaluation in an arbitrary group. */
+static void
+free_data_kweval(void *data);
+/** Initializes frame evaluation for keyword evaluation in an arbitrary group. */
+static int
+init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates keywords in an arbitrary group. */
+static int
+evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+
+/*! \internal \brief
+ * Data structure for keyword evaluation in arbitrary groups.
+ */
+typedef struct
+{
+ /** Wrapped keyword method for evaluating the values. */
+ gmx_ana_selmethod_t *kwmethod;
+ /** Method data for \p kwmethod. */
+ void *kwmdata;
+ /** Group in which \p kwmethod should be evaluated. */
+ gmx_ana_index_t g;
+} t_methoddata_kweval;
+
+/** Parameters for keyword evaluation in an arbitrary group. */
+static gmx_ana_selparam_t smparams_kweval[] = {
+ {NULL, {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
+};
+
/********************************************************************
* INTEGER KEYWORD EVALUATION
return 0;
}
-/*!
- * \param data Data to free (should point to a \ref t_methoddata_kwint).
- *
- * Frees the memory allocated for t_methoddata_kwint::r.
- */
-static void
-free_data_kwint(void *data)
-{
- t_methoddata_kwint *d = (t_methoddata_kwint *)data;
-
- sfree(d->v);
- sfree(d->r);
-}
-
/*!
* See sel_updatefunc() for description of the parameters.
* \p data should point to a \c t_methoddata_kwint.
return 0;
}
-/*!
- * \param data Data to free (should point to a \ref t_methoddata_kwreal).
- *
- * Frees the memory allocated for t_methoddata_kwreal::r.
- */
-static void
-free_data_kwreal(void *data)
-{
- t_methoddata_kwreal *d = (t_methoddata_kwreal *)data;
-
- sfree(d->v);
- sfree(d->r);
-}
-
/*!
* See sel_updatefunc() for description of the parameters.
* \p data should point to a \c t_methoddata_kwreal.
fprintf(stderr, "WARNING: error in regular expression,\n"
" will match '%s' as a simple string\n", s);
}
- else
- {
- sfree(s);
- }
sfree(buf);
#else
bRegExp = FALSE;
}
d->m[i].bRegExp = bRegExp;
}
- sfree(param[1].val.u.s);
return 0;
}
t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
int i;
- sfree(d->v);
for (i = 0; i < d->n; ++i)
{
if (d->m[i].bRegExp)
regfree(&d->m[i].u.r);
#endif
}
- else
- {
- sfree(d->m[i].u.s);
- }
}
sfree(d->m);
}
}
return 0;
}
+
+
+/********************************************************************
+ * KEYWORD EVALUATION FOR ARBITRARY GROUPS
+ ********************************************************************/
+
+/*!
+ * \param[in] top Not used.
+ * \param[in] npar Not used.
+ * \param[in] param Not used.
+ * \param[in] data Should point to \ref t_methoddata_kweval.
+ * \returns 0 on success, a non-zero error code on return.
+ *
+ * Calls the initialization method of the wrapped keyword.
+ */
+static int
+init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+ t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+ return d->kwmethod->init(top, 0, NULL, d->kwmdata);
+}
+
+/*!
+ * \param[in] top Not used.
+ * \param[in,out] out Pointer to output data structure.
+ * \param[in,out] data Should point to \c t_methoddata_kweval.
+ * \returns 0 for success.
+ */
+static int
+init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data)
+{
+ t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+ out->nr = d->g.isize;
+ return 0;
+}
+
+/*!
+ * \param data Data to free (should point to a \c t_methoddata_kweval).
+ *
+ * Frees the memory allocated for all the members of \c t_methoddata_kweval.
+ */
+static void
+free_data_kweval(void *data)
+{
+ t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+ _gmx_selelem_free_method(d->kwmethod, d->kwmdata);
+}
+
+/*!
+ * \param[in] top Topology.
+ * \param[in] fr Current frame.
+ * \param[in] pbc PBC structure.
+ * \param data Should point to a \ref t_methoddata_kweval.
+ * \returns 0 on success, a non-zero error code on error.
+ *
+ * Creates a lookup structure that enables fast queries of whether a point
+ * is within the solid angle or not.
+ */
+static int
+init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+ t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+ return d->kwmethod->init_frame(top, fr, pbc, d->kwmdata);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_kweval.
+ *
+ * Calls the evaluation function of the wrapped keyword with the given
+ * parameters, with the exception of using \c t_methoddata_kweval::g for the
+ * evaluation group.
+ */
+static int
+evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+ t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+ return d->kwmethod->update(top, fr, pbc, &d->g, out, d->kwmdata);
+}
+
+/*!
+ * \param[out] selp Pointer to receive a pointer to the created selection
+ * element (set to NULL on error).
+ * \param[in] method Keyword selection method to evaluate.
+ * \param[in] param Parameter that gives the group to evaluate \p method in.
+ * \param[in] scanner Scanner data structure.
+ * \returns 0 on success, non-zero error code on error.
+ *
+ * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp)
+ * that evaluates the keyword method given by \p method in the group given by
+ * \p param.
+ */
+int
+_gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method,
+ t_selexpr_param *param, void *scanner)
+{
+ t_selelem *sel;
+ t_methoddata_kweval *data;
+
+ if ((method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
+ || method->outinit || method->pupdate)
+ {
+ _gmx_selexpr_free_params(param);
+ gmx_incons("unsupported keyword method for arbitrary group evaluation");
+ return -1;
+ }
+
+ *selp = NULL;
+ sel = _gmx_selelem_create(SEL_EXPRESSION);
+ _gmx_selelem_set_method(sel, method, scanner);
+
+ snew(data, 1);
+ data->kwmethod = sel->u.expr.method;
+ data->kwmdata = sel->u.expr.mdata;
+ gmx_ana_index_clear(&data->g);
+
+ snew(sel->u.expr.method, 1);
+ memcpy(sel->u.expr.method, data->kwmethod, sizeof(gmx_ana_selmethod_t));
+ sel->u.expr.method->flags |= SMETH_VARNUMVAL;
+ sel->u.expr.method->init_data = NULL;
+ sel->u.expr.method->set_poscoll = NULL;
+ sel->u.expr.method->init = method->init ? &init_kweval : NULL;
+ sel->u.expr.method->outinit = &init_output_kweval;
+ sel->u.expr.method->free = &free_data_kweval;
+ sel->u.expr.method->init_frame = method->init_frame ? &init_frame_kweval : NULL;
+ sel->u.expr.method->update = &evaluate_kweval;
+ sel->u.expr.method->pupdate = NULL;
+ sel->u.expr.method->nparams = asize(smparams_kweval);
+ sel->u.expr.method->param = smparams_kweval;
+ _gmx_selelem_init_method_params(sel, scanner);
+ sel->u.expr.mdata = data;
+
+ sel->u.expr.method->param[0].val.u.g = &data->g;
+
+ sfree(param->name);
+ param->name = NULL;
+ if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams,
+ sel->u.expr.method->param, sel, scanner))
+ {
+ _gmx_selelem_free(sel);
+ return -1;
+ }
+ *selp = sel;
+ return 0;
+}
{
t_methoddata_merge *d = (t_methoddata_merge *)data;
- gmx_ana_pos_deinit(&d->p1);
- gmx_ana_pos_deinit(&d->p2);
gmx_ana_index_deinit(&d->g);
}
{
t_methoddata_permute *d = (t_methoddata_permute *)data;
- gmx_ana_pos_deinit(&d->p);
gmx_ana_index_deinit(&d->g);
- sfree(d->perm);
sfree(d->rperm);
}
t_methoddata_pos *d = (t_methoddata_pos *)data;
sfree(d->type);
- gmx_ana_index_deinit(&d->g);
gmx_ana_poscalc_free(d->pc);
}
#include <config.h>
#endif
+#include <stdlib.h>
+
#include <macros.h>
#include <smalloc.h>
+#include <string2.h>
-#include <indexutil.h>
#include <selmethod.h>
+#include "keywords.h"
+#include "parsetree.h"
+#include "selelem.h"
+
/*! \internal \brief
* Data structure for the \p same selection method.
*
- * All angle values are in the units of radians.
+ * To avoid duplicate initialization code, the same data structure is used
+ * for matching both integer and string keywords; hence the unions.
*/
typedef struct
{
- /*! \brief Input group. */
- gmx_ana_index_t g;
+ /** Value for each atom to match. */
+ union
+ {
+ int *i;
+ char **s;
+ void *ptr;
+ } val;
+ /*! \brief
+ * Number of values in the \p as array.
+ *
+ * For string values, this is actually the number of values in the
+ * \p as_s_sorted array.
+ */
+ int nas;
+ /** Values to match against. */
+ union
+ {
+ int *i;
+ char **s;
+ void *ptr;
+ } as;
+ /*! \brief
+ * Separate array for sorted \p as.s array.
+ *
+ * The array of strings returned as the output value of a parameter should
+ * not be messed with to avoid memory corruption (the pointers in the array
+ * may be reused for several evaluations), so we keep our own copy for
+ * modifications.
+ */
+ char **as_s_sorted;
+ /** Whether simple matching can be used. */
+ bool bSorted;
} t_methoddata_same;
-/*! \brief Allocates data for the \p same selection method. */
+/** Allocates data for the \p same selection method. */
static void *
init_data_same(int npar, gmx_ana_selparam_t *param);
-/*! \brief Initializes the \p same selection method. */
+/** Initializes the \p same selection method. */
static int
init_same(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/*! \brief Frees the data allocated for the \p same selection method. */
+/** Frees the data allocated for the \p same selection method. */
static void
free_data_same(void *data);
-/*! \brief Initializes the evaluation of the \p same selection method for a frame. */
+/** Initializes the evaluation of the \p same selection method for a frame. */
+static int
+init_frame_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates the \p same selection method. */
static int
-init_frame_same(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
-/*! \brief Evaluates the \p same selection method. */
+evaluate_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Initializes the evaluation of the \p same selection method for a frame. */
static int
-evaluate_same(t_topology *top, t_trxframe *fr, t_pbc *pbc,
- gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+init_frame_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates the \p same selection method. */
+static int
+evaluate_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/*! \brief Enum array for the \p same selection method. */
-static char *same_enum[] = { NULL, "residue", NULL };
+/** Parameters for the \p same selection method. */
+static gmx_ana_selparam_t smparams_same_int[] = {
+ {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_ATOMVAL},
+ {"as", {INT_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+};
-/*! \brief Parameters for the \p same selection method. */
-static gmx_ana_selparam_t smparams_same[] = {
- {NULL, {STR_VALUE, 1, {same_enum}}, NULL, SPAR_ENUMVAL},
- {"as", {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
+/** Parameters for the \p same selection method. */
+static gmx_ana_selparam_t smparams_same_str[] = {
+ {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_ATOMVAL},
+ {"as", {STR_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+};
+
+/** Help text for the \p same selection method. */
+static const char *help_same[] = {
+ "EXTENDING SELECTIONS[PAR]",
+
+ "[TT]same KEYWORD as ATOM_EXPR[tt][PAR]",
+
+ "The keyword [TT]same[tt] can be used to select all atoms for which",
+ "the given [TT]KEYWORD[tt] matches any of the atoms in [TT]ATOM_EXPR[tt].",
+ "Keywords that evaluate to integer or string values are supported.",
};
/*! \internal \brief Selection method data for the \p same method. */
gmx_ana_selmethod_t sm_same = {
- "same", GROUP_VALUE, SMETH_REQTOP,
- asize(smparams_same), smparams_same,
+ "same", GROUP_VALUE, 0,
+ asize(smparams_same_int), smparams_same_int,
&init_data_same,
NULL,
- NULL,
+ &init_same,
NULL,
&free_data_same,
+ &init_frame_same_int,
+ &evaluate_same_int,
+ NULL,
+ {"same KEYWORD as ATOM_EXPR", asize(help_same), help_same},
+};
+
+/*! \brief
+ * Selection method data for the \p same method.
+ *
+ * This selection method is used for matching string keywords. The parser
+ * never sees this method; _gmx_selelem_custom_init_same() replaces sm_same
+ * with this method in cases where it is required.
+ */
+static gmx_ana_selmethod_t sm_same_str = {
+ "same", GROUP_VALUE, SMETH_SINGLEVAL,
+ asize(smparams_same_str), smparams_same_str,
+ &init_data_same,
+ NULL,
+ &init_same,
NULL,
- &evaluate_same,
+ &free_data_same,
+ &init_frame_same_str,
+ &evaluate_same_str,
NULL,
- {"same residue as ATOM_EXPR", 0, NULL},
+ {"same KEYWORD as ATOM_EXPR", asize(help_same), help_same},
};
/*!
t_methoddata_same *data;
snew(data, 1);
- gmx_ana_index_clear(&data->g);
- param[1].val.u.g = &data->g;
+ data->as_s_sorted = NULL;
+ param[1].nvalptr = &data->nas;
return data;
}
+/*!
+ * \param[in,out] method The method to initialize.
+ * \param[in,out] params Pointer to the first parameter.
+ * \param[in] scanner Scanner data structure.
+ * \returns 0 on success, a non-zero error code on error.
+ *
+ * If \p *method is not a \c same method, this function returns zero
+ * immediately.
+ */
+int
+_gmx_selelem_custom_init_same(gmx_ana_selmethod_t **method,
+ t_selexpr_param *params,
+ void *scanner)
+{
+ gmx_ana_selmethod_t *kwmethod;
+ t_selelem *kwelem;
+ t_selexpr_param *param;
+ char *pname;
+ int rc;
+
+ /* Do nothing if this is not a same method. */
+ if (!*method || (*method)->name != sm_same.name)
+ {
+ return 0;
+ }
+
+ if (params->nval != 1 || !params->value->bExpr
+ || params->value->u.expr->type != SEL_EXPRESSION)
+ {
+ _gmx_selparser_error("error: 'same' should be followed by a single keyword");
+ return -1;
+ }
+ kwmethod = params->value->u.expr->u.expr.method;
+
+ if (kwmethod->type == STR_VALUE)
+ {
+ *method = &sm_same_str;
+ }
+
+ /* We do custom processing with the second parameter, so remove it from
+ * the params list, but save the name for later. */
+ param = params->next;
+ params->next = NULL;
+ pname = param->name;
+ param->name = NULL;
+ /* Create a second keyword evaluation element for the keyword given as
+ * the first parameter, evaluating the keyword in the group given by the
+ * second parameter. */
+ rc = _gmx_sel_init_keyword_evaluator(&kwelem, kwmethod, param, scanner);
+ if (rc != 0)
+ {
+ sfree(pname);
+ return rc;
+ }
+ /* Replace the second parameter with one with a value from \p kwelem. */
+ param = _gmx_selexpr_create_param(pname);
+ param->nval = 1;
+ param->value = _gmx_selexpr_create_value_expr(kwelem);
+ params->next = param;
+ return 0;
+}
+
+/*!
+ * \param top Not used.
+ * \param npar Not used (should be 2).
+ * \param param Initialized method parameters (should point to a copy of
+ * \ref smparams_same).
+ * \param data Pointer to \ref t_methoddata_same to initialize.
+ * \returns 0 on success, -1 on failure.
+ */
+static int
+init_same(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+ t_methoddata_same *d = (t_methoddata_same *)data;
+
+ d->val.ptr = param[0].val.u.ptr;
+ d->as.ptr = param[1].val.u.ptr;
+ if (param[1].val.type == STR_VALUE)
+ {
+ snew(d->as_s_sorted, d->nas);
+ }
+ if (!(param[0].flags & SPAR_ATOMVAL))
+ {
+ fprintf(stderr, "ERROR: the same selection keyword combined with a "
+ "non-keyword does not make sense\n");
+ return -1;
+ }
+ return 0;
+}
+
/*!
* \param data Data to free (should point to a \ref t_methoddata_same).
*/
{
t_methoddata_same *d = (t_methoddata_same *)data;
- gmx_ana_index_deinit(&d->g);
+ sfree(d->as_s_sorted);
+}
+
+/*! \brief
+ * Helper function for comparison of two integers.
+ */
+static int
+cmp_int(const void *a, const void *b)
+{
+ if (*(int *)a < *(int *)b)
+ {
+ return -1;
+ }
+ if (*(int *)a > *(int *)b)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*!
+ * \param[in] top Not used.
+ * \param[in] fr Current frame.
+ * \param[in] pbc PBC structure.
+ * \param data Should point to a \ref t_methoddata_same.
+ * \returns 0 on success, a non-zero error code on error.
+ *
+ * Sorts the \c data->as.i array and removes identical values for faster and
+ * simpler lookup.
+ */
+static int
+init_frame_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+ t_methoddata_same *d = (t_methoddata_same *)data;
+ int i, j;
+
+ /* Collapse adjacent values, and check whether the array is sorted. */
+ d->bSorted = TRUE;
+ for (i = 1, j = 0; i < d->nas; ++i)
+ {
+ if (d->as.i[i] != d->as.i[j])
+ {
+ if (d->as.i[i] < d->as.i[j])
+ {
+ d->bSorted = FALSE;
+ }
+ ++j;
+ d->as.i[j] = d->as.i[i];
+ }
+ }
+ d->nas = j + 1;
+
+ if (!d->bSorted)
+ {
+ qsort(d->as.i, d->nas, sizeof(d->as.i[0]), &cmp_int);
+ /* More identical values may become adjacent after sorting. */
+ for (i = 1, j = 0; i < d->nas; ++i)
+ {
+ if (d->as.i[i] != d->as.i[j])
+ {
+ ++j;
+ d->as.i[j] = d->as.i[i];
+ }
+ }
+ d->nas = j + 1;
+ }
+ return 0;
}
/*!
* See sel_updatefunc() for description of the parameters.
* \p data should point to a \c t_methoddata_same.
*
- * Calculates which atoms in \p g are in the same residues as the atoms in
- * \c t_methoddata_same::g.
+ * Calculates which values in \c data->val.i can be found in \c data->as.i
+ * (assumed sorted), and writes the corresponding atoms to output.
+ * If \c data->val is sorted, uses a linear scan of both arrays, otherwise a
+ * binary search of \c data->as is performed for each block of values in
+ * \c data->val.
*/
static int
-evaluate_same(t_topology *top, t_trxframe *fr, t_pbc *pbc,
- gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+evaluate_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
{
t_methoddata_same *d = (t_methoddata_same *)data;
- int i, j, resind;
+ int i, j;
out->u.g->isize = 0;
i = j = 0;
- while (i < d->g.isize)
+ while (j < g->isize)
+ {
+ if (d->bSorted)
+ {
+ /* If we are sorted, we can do a simple linear scan. */
+ while (i < d->nas && d->as.i[i] < d->val.i[j]) ++i;
+ }
+ else
+ {
+ /* If not, we must do a binary search of all the values. */
+ int i1, i2;
+
+ i1 = 0;
+ i2 = d->nas;
+ while (i2 - i1 > 1)
+ {
+ int itry = (i1 + i2) / 2;
+ if (d->as.i[itry] <= d->val.i[j])
+ {
+ i1 = itry;
+ }
+ else
+ {
+ i2 = itry;
+ }
+ }
+ i = (d->as.i[i1] == d->val.i[j] ? i1 : d->nas);
+ }
+ /* Check whether the value was found in the as list. */
+ if (i == d->nas || d->as.i[i] != d->val.i[j])
+ {
+ /* If not, skip all atoms with the same value. */
+ int tmpval = d->val.i[j];
+ ++j;
+ while (j < g->isize && d->val.i[j] == tmpval) ++j;
+ }
+ else
+ {
+ /* Copy all the atoms with this value to the output. */
+ while (j < g->isize && d->val.i[j] == d->as.i[i])
+ {
+ out->u.g->index[out->u.g->isize++] = g->index[j];
+ ++j;
+ }
+ }
+ if (j < g->isize && d->val.i[j] < d->val.i[j - 1])
+ {
+ d->bSorted = FALSE;
+ }
+ }
+ return 0;
+}
+
+/*! \brief
+ * Helper function for comparison of two strings.
+ */
+static int
+cmp_str(const void *a, const void *b)
+{
+ return strcmp(*(char **)a, *(char **)b);
+}
+
+/*!
+ * \param[in] top Not used.
+ * \param[in] fr Current frame.
+ * \param[in] pbc PBC structure.
+ * \param data Should point to a \ref t_methoddata_same.
+ * \returns 0 on success, a non-zero error code on error.
+ *
+ * Sorts the \c data->as.s array and removes identical values for faster and
+ * simpler lookup.
+ */
+static int
+init_frame_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+ t_methoddata_same *d = (t_methoddata_same *)data;
+ int i, j;
+
+ /* Collapse adjacent values.
+ * For strings, it's unlikely that the values would be sorted originally,
+ * so set bSorted always to FALSE. */
+ d->bSorted = FALSE;
+ d->as_s_sorted[0] = d->as.s[0];
+ for (i = 1, j = 0; i < d->nas; ++i)
{
- resind = top->atoms.atom[d->g.index[i]].resind;
- /* Find the first atom in the current residue */
- while (top->atoms.atom[g->index[j]].resind < resind) ++j;
- /* Copy all the atoms in the residue to the output */
- while (j < g->isize && top->atoms.atom[g->index[j]].resind == resind)
+ if (strcmp(d->as.s[i], d->as_s_sorted[j]) != 0)
{
- out->u.g->index[out->u.g->isize++] = g->index[j];
++j;
+ d->as_s_sorted[j] = d->as.s[i];
}
- /* Skip the rest of the atoms in the residue */
- ++i;
- while (i < d->g.isize && top->atoms.atom[d->g.index[i]].resind == resind) ++i;
}
+ d->nas = j + 1;
+
+ qsort(d->as_s_sorted, d->nas, sizeof(d->as_s_sorted[0]), &cmp_str);
+ /* More identical values may become adjacent after sorting. */
+ for (i = 1, j = 0; i < d->nas; ++i)
+ {
+ if (strcmp(d->as_s_sorted[i], d->as_s_sorted[j]) != 0)
+ {
+ ++j;
+ d->as_s_sorted[j] = d->as_s_sorted[i];
+ }
+ }
+ d->nas = j + 1;
return 0;
}
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_same.
+ *
+ * Calculates which strings in \c data->val.s can be found in \c data->as.s
+ * (assumed sorted), and writes the corresponding atoms to output.
+ * A binary search of \c data->as is performed for each block of values in
+ * \c data->val.
+ */
+static int
+evaluate_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+ t_methoddata_same *d = (t_methoddata_same *)data;
+ int i, j;
+
+ out->u.g->isize = 0;
+ j = 0;
+ while (j < g->isize)
+ {
+ /* Do a binary search of the strings. */
+ void *ptr;
+ ptr = bsearch(&d->val.s[j], d->as_s_sorted, d->nas,
+ sizeof(d->as_s_sorted[0]), &cmp_str);
+ /* Check whether the value was found in the as list. */
+ if (ptr == NULL)
+ {
+ /* If not, skip all atoms with the same value. */
+ const char *tmpval = d->val.s[j];
+ ++j;
+ while (j < g->isize && strcmp(d->val.s[j], tmpval) == 0) ++j;
+ }
+ else
+ {
+ const char *tmpval = d->val.s[j];
+ /* Copy all the atoms with this value to the output. */
+ while (j < g->isize && strcmp(d->val.s[j], tmpval) == 0)
+ {
+ out->u.g->index[out->u.g->isize++] = g->index[j];
+ ++j;
+ }
+ }
+ }
+ return 0;
+}
static int
evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p resind selection keyword. */
+/** Evaluates the \p resindex selection keyword. */
static int
-evaluate_resind(t_topology *top, t_trxframe *fr, t_pbc *pbc,
- gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Checks whether molecule information is present in the topology. */
+static int
+check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Evaluates the \p molindex selection keyword. */
+static int
+evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
/** Evaluates the \p name selection keyword. */
static int
evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
NULL,
};
-/** \internal Selection method data for \p resind selection keyword. */
-gmx_ana_selmethod_t sm_resind = {
- "resind", INT_VALUE, SMETH_REQTOP,
+/** \internal Selection method data for \p resindex selection keyword. */
+gmx_ana_selmethod_t sm_resindex = {
+ "resindex", INT_VALUE, SMETH_REQTOP,
0, NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
- &evaluate_resind,
+ &evaluate_resindex,
+ NULL,
+};
+
+/** \internal Selection method data for \p molindex selection keyword. */
+gmx_ana_selmethod_t sm_molindex = {
+ "molindex", INT_VALUE, SMETH_REQTOP,
+ 0, NULL,
+ NULL,
+ NULL,
+ &check_molecules,
+ NULL,
+ NULL,
+ NULL,
+ &evaluate_molindex,
NULL,
};
* Returns the residue indices for each atom in \p out->u.i.
*/
static int
-evaluate_resind(t_topology *top, t_trxframe *fr, t_pbc *pbc,
- gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
{
int i;
return 0;
}
+/*!
+ * \param[in] top Topology structure.
+ * \param npar Not used.
+ * \param param Not used.
+ * \param data Not used.
+ * \returns 0 if molecule info is present in the topology, -1 otherwise.
+ *
+ * If molecule information is not found, also prints an error message.
+ */
+static int
+check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+ bool bOk;
+
+ bOk = (top != NULL && top->mols.nr > 0);
+ if (!bOk)
+ {
+ fprintf(stderr, "Molecule information not available in topology!\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the molecule indices for each atom in \p out->u.i.
+ */
+static int
+evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+ int i, j;
+
+ out->nr = g->isize;
+ for (i = j = 0; i < g->isize; ++i)
+ {
+ while (top->mols.index[j + 1] <= g->index[i]) ++j;
+ out->u.i[i] = j + 1;
+ }
+ return 0;
+}
+
/*!
* See sel_updatefunc() for description of the parameters.
* \p data is not used.
SYMBOL_RESERVED, /**< The symbol is a reserved keyword. */
SYMBOL_VARIABLE, /**< The symbol is a variable. */
SYMBOL_METHOD, /**< The symbol is a selection method. */
- SYMBOL_POS, /**< The symbol is a position keyword. */
+ SYMBOL_POS /**< The symbol is a position keyword. */
} e_symbol_t;
/** Symbol table for the selection parser. */
bool bMaskOnly = FALSE;
bool bFrameTree = FALSE;
+ bool bDebugCompile = FALSE;
int nref = 0;
int nmaxind = 20;
t_pargs pa[] = {
{"-mask", FALSE, etBOOL, {&bMaskOnly},
"Test position mask functionality"},
+ {"-compdebug", FALSE, etBOOL, {&bDebugCompile},
+ "Print intermediate trees during compilation"},
{"-frtree", FALSE, etBOOL, {&bFrameTree},
"Print the whole evaluation tree for each frame"},
{"-nref", FALSE, etINT, {&nref},
gmx_ana_add_flags(trj, ANA_USE_POSMASK);
gmx_ana_selcollection_set_outpostype(d.sc, NULL, TRUE);
}
+ gmx_ana_selcollection_set_compile_debug(d.sc, bDebugCompile);
gmx_ana_set_nrefgrps(trj, nref);
gmx_ana_init_selections(trj);
gmx_ana_get_ngrps(trj, &ngrps);
print_selections(ngrps, sel, d.nmaxind);
gmx_ana_traj_free(trj);
+ done_filenms(NFILE, fnm);
return 0;
}
--- /dev/null
+/*
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include "sysstuff.h"
+#include "smalloc.h"
+#include "string2.h"
+#include "futil.h"
+#include "maths.h"
+#include "gmx_fatal.h"
+#include "vec.h"
+#include "macros.h"
+#include "index.h"
+#include "strdb.h"
+#include "copyrite.h"
+#include "tpxio.h"
+#include "typedefs.h"
+#include "statutil.h"
+#include "oenv.h"
+#include "gmxfio.h"
+#include "xvgr.h"
+#include "matio.h"
+#include "gmx_ana.h"
+#include "names.h"
+#include "sfactor.h"
+
+
+typedef struct gmx_structurefactors {
+ int nratoms;
+ int *p; /* proton number */
+ int *n; /* neutron number */
+ /* Parameters for the Cromer Mann fit */
+ real **a; /* parameter a */
+ real **b; /* parameter b */
+ real *c; /* parameter c */
+ char **atomnm; /* atomname */
+
+} gmx_structurefactors;
+
+typedef struct reduced_atom{
+ rvec x;
+ int t;
+} reduced_atom;
+
+
+typedef struct structure_factor
+{
+ int n_angles;
+ int n_groups;
+ double lambda;
+ double energy;
+ double momentum;
+ double ref_k;
+ double **F;
+ int nSteps;
+ int total_n_atoms;
+} structure_factor;
+
+
+extern int * create_indexed_atom_type (reduced_atom_t * atm, int size)
+{
+/*
+ * create an index of the atom types found in a group
+ * i.e.: for water index_atp[0]=type_number_of_O and
+ * index_atp[1]=type_number_of_H
+ *
+ * the last element is set to 0
+ */
+ int *index_atp, i, i_tmp, j;
+
+ reduced_atom *att=(reduced_atom *)atm;
+
+ snew (index_atp, 1);
+ i_tmp = 1;
+ index_atp[0] = att[0].t;
+ for (i = 1; i < size; i++) {
+ for (j = 0; j < i_tmp; j++)
+ if (att[i].t == index_atp[j])
+ break;
+ if (j == i_tmp) { /* i.e. no indexed atom type is == to atm[i].t */
+ i_tmp++;
+ srenew (index_atp, i_tmp * sizeof (int));
+ index_atp[i_tmp - 1] = att[i].t;
+ }
+ }
+ i_tmp++;
+ srenew (index_atp, i_tmp * sizeof (int));
+ index_atp[i_tmp - 1] = 0;
+ return index_atp;
+}
+
+
+
+extern t_complex *** rc_tensor_allocation(int x, int y, int z)
+{
+ t_complex ***t;
+ int i,j;
+
+ snew(t,x);
+ t = (t_complex ***)calloc(x,sizeof(t_complex**));
+ if(!t) exit(fprintf(stderr,"\nallocation error"));
+ t[0] = (t_complex **)calloc(x*y,sizeof(t_complex*));
+ if(!t[0]) exit(fprintf(stderr,"\nallocation error"));
+ t[0][0] = (t_complex *)calloc(x*y*z,sizeof(t_complex));
+ if(!t[0][0]) exit(fprintf(stderr,"\nallocation error"));
+
+ for( j = 1 ; j < y ; j++)
+ t[0][j] = t[0][j-1] + z;
+ for( i = 1 ; i < x ; i++) {
+ t[i] = t[i-1] + y;
+ t[i][0] = t[i-1][0] + y*z;
+ for( j = 1 ; j < y ; j++)
+ t[i][j] = t[i][j-1] + z;
+ }
+ return t;
+}
+
+
+extern void compute_structure_factor (structure_factor_t * sft, matrix box,
+ reduced_atom_t * red, int isize, real start_q,
+ real end_q, int group,real **sf_table)
+{
+ structure_factor *sf=(structure_factor *)sft;
+ reduced_atom *redt=(reduced_atom *)red;
+
+ t_complex ***tmpSF;
+ rvec k_factor;
+ real kdotx, asf, kx, ky, kz, krr;
+ int kr, maxkx, maxky, maxkz, i, j, k, p, *counter;
+
+
+ k_factor[XX] = 2 * M_PI / box[XX][XX];
+ k_factor[YY] = 2 * M_PI / box[YY][YY];
+ k_factor[ZZ] = 2 * M_PI / box[ZZ][ZZ];
+
+ maxkx = (int) (end_q / k_factor[XX] + 0.5);
+ maxky = (int) (end_q / k_factor[YY] + 0.5);
+ maxkz = (int) (end_q / k_factor[ZZ] + 0.5);
+
+ snew (counter, sf->n_angles);
+
+ tmpSF = rc_tensor_allocation(maxkx,maxky,maxkz);
+/*
+ * The big loop...
+ * compute real and imaginary part of the structure factor for every
+ * (kx,ky,kz))
+ */
+ fprintf(stderr,"\n");
+ for (i = 0; i < maxkx; i++) {
+ fprintf (stderr,"\rdone %3.1f%% ", (double)(100.0*(i+1))/maxkx);
+ kx = i * k_factor[XX];
+ for (j = 0; j < maxky; j++) {
+ ky = j * k_factor[YY];
+ for (k = 0; k < maxkz; k++)
+ if (i != 0 || j != 0 || k != 0) {
+ kz = k * k_factor[ZZ];
+ krr = sqrt (sqr (kx) + sqr (ky) + sqr (kz));
+ if (krr >= start_q && krr <= end_q) {
+ kr = (int) (krr/sf->ref_k + 0.5);
+ if (kr < sf->n_angles) {
+ counter[kr]++; /* will be used for the copmutation
+ of the average*/
+ for (p = 0; p < isize; p++) {
+ asf = sf_table[redt[p].t][kr];
+
+ kdotx = kx * redt[p].x[XX] +
+ ky * redt[p].x[YY] + kz * redt[p].x[ZZ];
+
+ tmpSF[i][j][k].re += cos (kdotx) * asf;
+ tmpSF[i][j][k].im += sin (kdotx) * asf;
+ }
+ }
+ }
+ }
+ }
+ } /* end loop on i */
+/*
+ * compute the square modulus of the structure factor, averaging on the surface
+ * kx*kx + ky*ky + kz*kz = krr*krr
+ * note that this is correct only for a (on the macroscopic scale)
+ * isotropic system.
+ */
+ for (i = 0; i < maxkx; i++) {
+ kx = i * k_factor[XX]; for (j = 0; j < maxky; j++) {
+ ky = j * k_factor[YY]; for (k = 0; k < maxkz; k++) {
+ kz = k * k_factor[ZZ]; krr = sqrt (sqr (kx) + sqr (ky)
+ + sqr (kz)); if (krr >= start_q && krr <= end_q) {
+ kr = (int) (krr / sf->ref_k + 0.5);
+ if (kr < sf->n_angles && counter[kr] != 0)
+ sf->F[group][kr] +=
+ (sqr (tmpSF[i][j][k].re) +
+ sqr (tmpSF[i][j][k].im))/ counter[kr];
+ }
+ }
+ }
+ } sfree (counter); free(tmpSF[0][0]); free(tmpSF[0]); free(tmpSF);
+}
+
+
+extern gmx_structurefactors_t *gmx_structurefactors_init(const char *datfn) {
+
+ /* Read the database for the structure factor of the different atoms */
+
+ FILE *fp;
+ char line[STRLEN];
+ gmx_structurefactors *gsf;
+ double a1,a2,a3,a4,b1,b2,b3,b4,c;
+ int n,p;
+ int i;
+ int nralloc=10;
+ int line_no;
+ char atomn[32];
+ fp=libopen(datfn);
+ line_no = 0;
+
+ snew(gsf,1);
+
+ snew(gsf->atomnm,nralloc);
+ snew(gsf->a,nralloc);
+ snew(gsf->b,nralloc);
+ snew(gsf->c,nralloc);
+ snew(gsf->n,nralloc);
+ snew(gsf->p,nralloc);
+ gsf->nratoms=line_no;
+ while(get_a_line(fp,line,STRLEN)) {
+ i=line_no;
+ if (sscanf(line,"%s %d %d %lf %lf %lf %lf %lf %lf %lf %lf %lf",
+ atomn,&p,&n,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&c) == 12) {
+ gsf->atomnm[i]=strdup(atomn);
+ gsf->n[i]=n;
+ gsf->p[i]=p;
+ snew(gsf->a[i],4);
+ snew(gsf->b[i],4);
+ gsf->a[i][0]=a1;
+ gsf->a[i][1]=a2;
+ gsf->a[i][2]=a3;
+ gsf->a[i][3]=a4;
+ gsf->b[i][0]=b1;
+ gsf->b[i][1]=b2;
+ gsf->b[i][2]=b3;
+ gsf->b[i][3]=b4;
+ gsf->c[i]=c;
+ line_no++;
+ gsf->nratoms=line_no;
+ if (line_no==nralloc){
+ nralloc+=10;
+ srenew(gsf->atomnm,nralloc);
+ srenew(gsf->a,nralloc);
+ srenew(gsf->b,nralloc);
+ srenew(gsf->c,nralloc);
+ srenew(gsf->n,nralloc);
+ srenew(gsf->p,nralloc);
+ }
+ }
+ else
+ fprintf(stderr,"WARNING: Error in file %s at line %d ignored\n",
+ datfn,line_no);
+ }
+
+ srenew(gsf->atomnm,gsf->nratoms);
+ srenew(gsf->a,gsf->nratoms);
+ srenew(gsf->b,gsf->nratoms);
+ srenew(gsf->c,gsf->nratoms);
+ srenew(gsf->n,gsf->nratoms);
+ srenew(gsf->p,gsf->nratoms);
+
+ fclose(fp);
+
+ return (gmx_structurefactors_t *) gsf;
+
+}
+
+
+extern void rearrange_atoms (reduced_atom_t * positions, t_trxframe *fr, atom_id * index,
+ int isize, t_topology * top, bool flag,gmx_structurefactors_t *gsf)
+/* given the group's index, return the (continuous) array of atoms */
+{
+ int i;
+
+ reduced_atom *pos=(reduced_atom *)positions;
+
+ if (flag)
+ for (i = 0; i < isize; i++)
+ pos[i].t =
+ return_atom_type (*(top->atoms.atomname[index[i]]),gsf);
+ for (i = 0; i < isize; i++)
+ copy_rvec (fr->x[index[i]], pos[i].x);
+
+ positions=(reduced_atom_t *)pos;
+}
+
+
+extern int return_atom_type (const char *name,gmx_structurefactors_t *gsf)
+{
+ typedef struct {
+ const char *name;
+ int nh;
+ } t_united_h;
+ t_united_h uh[] = {
+ { "CH1", 1 }, { "CH2", 2 }, { "CH3", 3 },
+ { "CS1", 1 }, { "CS2", 2 }, { "CS3", 3 },
+ { "CP1", 1 }, { "CP2", 2 }, { "CP3", 3 }
+ };
+ int i,cnt=0;
+ int *tndx;
+ int nrc;
+ int fndx=0;
+ int NCMT;
+
+ gmx_structurefactors *gsft=(gmx_structurefactors *)gsf;
+
+ NCMT=gsft->nratoms;
+
+ snew(tndx,NCMT);
+
+ for(i=0; (i<asize(uh)); i++)
+ if (strcmp(name,uh[i].name) == 0)
+ return NCMT-1+uh[i].nh;
+
+ for(i=0; (i<NCMT); i++){
+ if (strncmp (name, gsft->atomnm[i],strlen(gsft->atomnm[i])) == 0){
+ tndx[cnt]=i;
+ cnt++;
+ }
+ }
+
+ if (cnt==0)
+ gmx_fatal(FARGS,"\nError: atom (%s) not in list (%d types checked)!\n",
+ name,i);
+ else{
+ nrc=0;
+ for(i=0;i<cnt;i++){
+ if(strlen(gsft->atomnm[tndx[i]])>(size_t)nrc){
+ nrc=strlen(gsft->atomnm[tndx[i]]);
+ fndx=tndx[i];
+ }
+ }
+
+ return fndx;
+ }
+
+ return 0;
+}
+
+extern int gmx_structurefactors_get_sf(gmx_structurefactors_t *gsf, int elem, real a[4], real b[4], real *c){
+
+ int success;
+ int i;
+ gmx_structurefactors *gsft=(gmx_structurefactors *)gsf;
+ success=0;
+
+ for(i=0;i<4;i++){
+ a[i]=gsft->a[elem][i];
+ b[i]=gsft->b[elem][i];
+ *c=gsft->c[elem];
+ }
+
+ success+=1;
+ return success;
+}
+
+int atp_size (int *index_atp)
+{
+ int i = 0;
+
+ while (index_atp[i])
+ i++;
+ return i;
+}
+
+
+extern int do_scattering_intensity (const char* fnTPS, const char* fnNDX,
+ const char* fnXVG, const char *fnTRX,
+ const char* fnDAT,
+ real start_q,real end_q,
+ real energy,int ng,const output_env_t oenv)
+{
+ int i,*isize,flags = TRX_READ_X,**index_atp;
+ t_trxstatus *status;
+ char **grpname,title[STRLEN];
+ atom_id **index;
+ t_topology top;
+ int ePBC;
+ t_trxframe fr;
+ reduced_atom_t **red;
+ structure_factor *sf;
+ rvec *xtop;
+ real **sf_table;
+ int nsftable;
+ matrix box;
+ double r_tmp;
+
+ gmx_structurefactors_t *gmx_sf;
+ real *a,*b,c;
+ int success;
+
+ snew(a,4);
+ snew(b,4);
+
+
+ gmx_sf=gmx_structurefactors_init(fnDAT);
+
+ success=gmx_structurefactors_get_sf(gmx_sf,0, a, b, &c);
+
+ snew (sf, 1);
+ sf->energy = energy;
+
+ /* Read the topology informations */
+ read_tps_conf (fnTPS, title, &top, &ePBC, &xtop, NULL, box, TRUE);
+ sfree (xtop);
+
+ /* groups stuff... */
+ snew (isize, ng);
+ snew (index, ng);
+ snew (grpname, ng);
+
+ fprintf (stderr, "\nSelect %d group%s\n", ng,
+ ng == 1 ? "" : "s");
+ if (fnTPS)
+ get_index (&top.atoms, fnNDX, ng, isize, index, grpname);
+ else
+ rd_index (fnNDX, ng, isize, index, grpname);
+
+ /* The first time we read data is a little special */
+ read_first_frame (oenv,&status, fnTRX, &fr, flags);
+
+ sf->total_n_atoms = fr.natoms;
+
+ snew (red, ng);
+ snew (index_atp, ng);
+
+ r_tmp = max (box[XX][XX], box[YY][YY]);
+ r_tmp = (double) max (box[ZZ][ZZ], r_tmp);
+
+ sf->ref_k = (2.0 * M_PI) / (r_tmp);
+ /* ref_k will be the reference momentum unit */
+ sf->n_angles = (int) (end_q / sf->ref_k + 0.5);
+
+ snew (sf->F, ng);
+ for (i = 0; i < ng; i++)
+ snew (sf->F[i], sf->n_angles);
+ for (i = 0; i < ng; i++) {
+ snew (red[i], isize[i]);
+ rearrange_atoms (red[i], &fr, index[i], isize[i], &top, TRUE,gmx_sf);
+ index_atp[i] = create_indexed_atom_type (red[i], isize[i]);
+ }
+
+ sf_table = compute_scattering_factor_table (gmx_sf,(structure_factor_t *)sf,&nsftable);
+
+
+ /* This is the main loop over frames */
+
+ do {
+ sf->nSteps++;
+ for (i = 0; i < ng; i++) {
+ rearrange_atoms (red[i], &fr, index[i], isize[i], &top,FALSE,gmx_sf);
+
+ compute_structure_factor ((structure_factor_t *)sf, box, red[i], isize[i],
+ start_q, end_q, i, sf_table);
+ }
+ }
+
+ while (read_next_frame (oenv,status, &fr));
+
+ save_data ((structure_factor_t *)sf, fnXVG, ng, start_q, end_q,oenv);
+
+
+ sfree(a);
+ sfree(b);
+
+ gmx_structurefactors_done(gmx_sf);
+
+ return 0;
+}
+
+
+extern void save_data (structure_factor_t *sft, const char *file, int ngrps,
+ real start_q, real end_q, const output_env_t oenv)
+{
+
+ FILE *fp;
+ int i, g = 0;
+ double *tmp, polarization_factor, A;
+
+ structure_factor *sf=(structure_factor *)sft;
+
+ fp = xvgropen (file, "Scattering Intensity", "q (1/nm)",
+ "Intensity (a.u.)",oenv);
+
+ snew (tmp, ngrps);
+
+ for (g = 0; g < ngrps; g++)
+ for (i = 0; i < sf->n_angles; i++) {
+
+/*
+ * theta is half the angle between incoming and scattered vectors.
+ *
+ * polar. fact. = 0.5*(1+cos^2(2*theta)) = 1 - 0.5 * sin^2(2*theta)
+ *
+ * sin(theta) = q/(2k) := A -> sin^2(theta) = 4*A^2 (1-A^2) ->
+ * -> 0.5*(1+cos^2(2*theta)) = 1 - 2 A^2 (1-A^2)
+ */
+ A = (double) (i * sf->ref_k) / (2.0 * sf->momentum);
+ polarization_factor = 1 - 2.0 * sqr (A) * (1 - sqr (A));
+ sf->F[g][i] *= polarization_factor;
+ }
+ for (i = 0; i < sf->n_angles; i++) {
+ if (i * sf->ref_k >= start_q && i * sf->ref_k <= end_q) {
+ fprintf (fp, "%10.5f ", i * sf->ref_k);
+ for (g = 0; g < ngrps; g++)
+ fprintf (fp, " %10.5f ", (sf->F[g][i]) /( sf->total_n_atoms*
+ sf->nSteps));
+ fprintf (fp, "\n");
+ }
+ }
+
+ ffclose (fp);
+}
+
+
+extern double CMSF (gmx_structurefactors_t *gsf,int type,int nh,double lambda, double sin_theta)
+/*
+ * return Cromer-Mann fit for the atomic scattering factor:
+ * sin_theta is the sine of half the angle between incoming and scattered
+ * vectors. See g_sq.h for a short description of CM fit.
+ */
+{
+ int i,success;
+ double tmp = 0.0, k2;
+ real *a,*b;
+ real c;
+
+ snew(a,4);
+ snew(b,4);
+
+ /*
+ *
+ * f0[k] = c + [SUM a_i*EXP(-b_i*(k^2)) ]
+ * i=1,4
+ */
+
+ /*
+ * united atoms case
+ * CH2 / CH3 groups
+ */
+ if (nh > 0) {
+ tmp = (CMSF (gsf,return_atom_type ("C",gsf),0,lambda, sin_theta) +
+ nh*CMSF (gsf,return_atom_type ("H",gsf),0,lambda, sin_theta));
+ }
+ /* all atom case */
+ else {
+ k2 = (sqr (sin_theta) / sqr (10.0 * lambda));
+ success=gmx_structurefactors_get_sf(gsf,type,a,b,&c);
+ tmp = c;
+ for (i = 0; (i < 4); i++)
+ tmp += a[i] * exp (-b[i] * k2);
+ }
+ return tmp;
+}
+
+
+
+extern real **gmx_structurefactors_table(gmx_structurefactors_t *gsf,real momentum, real ref_k, real lambda, int n_angles){
+
+ int NCMT;
+ int nsftable;
+ int i,j;
+ double q,sin_theta;
+ real **sf_table;
+ gmx_structurefactors *gsft=(gmx_structurefactors *)gsf;
+
+ NCMT=gsft->nratoms;
+ nsftable = NCMT+3;
+
+ snew (sf_table,nsftable);
+ for (i = 0; (i < nsftable); i++) {
+ snew (sf_table[i], n_angles);
+ for (j = 0; j < n_angles; j++) {
+ q = ((double) j * ref_k);
+ /* theta is half the angle between incoming
+ and scattered wavevectors. */
+ sin_theta = q / (2.0 * momentum);
+ if (i < NCMT){
+ sf_table[i][j] = CMSF (gsf,i,0,lambda, sin_theta);
+ }
+ else
+ sf_table[i][j] = CMSF (gsf,i,i-NCMT+1,lambda, sin_theta);
+ }
+ }
+ return sf_table;
+}
+
+extern void gmx_structurefactors_done(gmx_structurefactors_t *gsf){
+
+ int i;
+ gmx_structurefactors *sf;
+ sf=(gmx_structurefactors *) gsf;
+
+ for(i=0;i<sf->nratoms;i++){
+ sfree(sf->a[i]);
+ sfree(sf->b[i]);
+ sfree(sf->atomnm[i]);
+ }
+
+ sfree(sf->a);
+ sfree(sf->b);
+ sfree(sf->atomnm);
+ sfree(sf->p);
+ sfree(sf->n);
+ sfree(sf->c);
+
+ sfree(sf);
+
+}
+
+extern real **compute_scattering_factor_table (gmx_structurefactors_t *gsf,structure_factor_t *sft,int *nsftable)
+{
+/*
+ * this function build up a table of scattering factors for every atom
+ * type and for every scattering angle.
+ */
+
+ double hc=1239.842;
+ real ** sf_table;
+
+ structure_factor *sf=(structure_factor *)sft;
+
+
+ /* \hbar \omega \lambda = hc = 1239.842 eV * nm */
+ sf->momentum = ((double) (2. * 1000.0 * M_PI * sf->energy) / hc);
+ sf->lambda = hc / (1000.0 * sf->energy);
+ fprintf (stderr, "\nwavelenght = %f nm\n", sf->lambda);
+
+ sf_table=gmx_structurefactors_table(gsf,sf->momentum,sf->ref_k,sf->lambda,sf->n_angles);
+
+ return sf_table;
+}
+
+
#include "pppm.h"
#include "gmxfio.h"
+#include "thread_mpi.h"
+
#define p2(x) ((x)*(x))
#define p3(x) ((x)*(x)*(x))
#define p4(x) ((x)*(x)*(x)*(x))
static real A,A_3,B,B_4,C,c1,c2,c3,c4,c5,c6,One_4pi,FourPi_V,Vol,N0;
+#ifdef GMX_THREADS
+static tMPI_Thread_mutex_t shift_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
+#endif
+
void set_shift_consts(FILE *log,real r1,real rc,rvec box,t_forcerec *fr)
{
+#ifdef GMX_THREADS
+ /* at the very least we shouldn't allow multiple threads to set these
+ simulataneously */
+ tMPI_Thread_mutex_lock(&shift_mutex);
+#endif
/* A, B and C are recalculated in tables.c */
if (r1 < rc) {
A = (2*r1-5*rc)/(p3(rc)*p2(rc-r1));
}
One_4pi = 1.0/(4.0*M_PI);
+#ifdef GMX_THREADS
+ tMPI_Thread_mutex_unlock(&shift_mutex);
+#endif
}
real gk(real k,real rc,real r1)
#include "gmx_fatal.h"
#include "sighandler.h"
-/* The following two variables and the signal_handler function
- * are used from md.c and pme.c as well
- *
- * Do not fear these global variables: they represent inherently process-global
- * information that needs to be shared across threads
- */
-
-/* we got a signal to stop in the next step: */
-volatile sig_atomic_t bGotStopNextStepSignal=FALSE;
-/* we got a signal to stop in the next neighbour search step: */
-volatile sig_atomic_t bGotStopNextNSStepSignal=FALSE;
+const char *gmx_stop_cond_name[] =
+{
+ "None",
+ "Stop at the next neighbor search step",
+ "Stop at the next step",
+ "Abort"
+};
-/* our names for the handled signals. These must match the number given
- in signal_handler. */
-const char *signal_name[] =
+/* these do not neccesarily match the stop condition, but are
+ referred to in the signal handler. */
+const char *gmx_signal_name[] =
{
- "TERM",
+ "None",
"INT",
- "second INT"
+ "TERM",
+ "second INT/TERM",
+ "remote INT/TERM",
+ "remote second INT/TERM",
+ "USR1",
+ "Abort"
};
-/* the last signal received, according to the numbering
- we use in signal_name */
-volatile sig_atomic_t last_signal_number_recvd=-1;
+static volatile sig_atomic_t stop_condition=gmx_stop_cond_none;
+static volatile sig_atomic_t last_signal_name=0;
-RETSIGTYPE signal_handler(int n)
+static volatile sig_atomic_t usr_condition=0;
+
+static RETSIGTYPE signal_handler(int n)
{
switch (n) {
- case SIGTERM:
- bGotStopNextStepSignal = TRUE;
- last_signal_number_recvd = 0;
- break;
/* windows doesn't do SIGINT correctly according to ANSI (yes, signals are in
ANSI C89, and windows spawns a thread specifically to run the INT signal
handler), but that doesn't matter for a simple signal handler like this. */
+ case SIGTERM:
case SIGINT:
- if (!bGotStopNextNSStepSignal)
- {
- bGotStopNextNSStepSignal = TRUE;
- last_signal_number_recvd = 1;
- } else if (!bGotStopNextStepSignal)
- {
- bGotStopNextStepSignal = TRUE;
- last_signal_number_recvd = 2;
- }
- else
+ /* we explicitly set things up to allow this: */
+ stop_condition++;
+ if (n==SIGINT)
+ last_signal_name=1;
+ if (n==SIGTERM)
+ last_signal_name=2;
+ if (stop_condition == gmx_stop_cond_next)
+ last_signal_name=3;
+ if (stop_condition >= gmx_stop_cond_abort)
abort();
break;
+#ifdef HAVE_SIGUSR1
+ case SIGUSR1:
+ usr_condition=1;
+ break;
+#endif
+ default:
+ break;
}
}
}
signal(SIGINT,signal_handler);
}
+#ifdef HAVE_SIGUSR1
+ if (getenv("GMX_NO_USR1") == NULL)
+ {
+ if (debug)
+ {
+ fprintf(debug,"Installing signal handler for SIGUSR1\n");
+ }
+ signal(SIGUSR1,signal_handler);
+ }
+#endif
+}
+
+gmx_stop_cond_t gmx_get_stop_condition(void)
+{
+ return (gmx_stop_cond_t)stop_condition;
+}
+
+void gmx_set_stop_condition(gmx_stop_cond_t recvd_stop_cond)
+{
+ if (recvd_stop_cond > stop_condition)
+ {
+ stop_condition=recvd_stop_cond;
+ if (stop_condition == gmx_stop_cond_next_ns)
+ last_signal_name=4;
+ if (stop_condition == gmx_stop_cond_next)
+ last_signal_name=5;
+ }
+}
+const char *gmx_get_signal_name(void)
+{
+ return gmx_signal_name[last_signal_name];
}
+bool gmx_got_usr_signal(void)
+{
+#ifdef HAVE_SIGUSR1
+ bool ret=(bool)usr_condition;
+ usr_condition=0;
+ return ret;
+#else
+ return FALSE;
+#endif
+}
p=NULL;
if (size==0)
- p=NULL;
+ {
+ save_free(name, file, line, ptr);
+ }
else
{
#ifdef PRINT_ALLOC_KB
"Not enough memory. Failed to realloc %"gmx_large_int_fmt
" bytes for %s, %s=%x\n(called from file %s, line %d)",
(gmx_large_int_t)size,name,name,ptr,file,line);
- }
#ifdef DEBUG
- log_action(1,name,file,line,1,size,p);
+ log_action(1,name,file,line,1,size,p);
#endif
+ }
return p;
}
}
return size;
}
+
+/* If we don't have useful routines for allocating aligned memory,
+ * then we have to use the old-style GROMACS approach bitwise-ANDing
+ * pointers to ensure alignment. We store the pointer to the originally
+ * allocated region in the space before the returned pointer */
+
+/* we create a positive define for the absence of an system-provided memalign */
+#if (!defined HAVE_POSIX_MEMALIGN && !defined HAVE_MEMALIGN && \
+ !defined HAVE__ALIGNED_MALLOC)
+#define GMX_OWN_MEMALIGN
+#endif
+
+
+/* Pointers allocated with this routine should only be freed
+ * with save_free_aligned, however this will only matter
+ * on systems that lack posix_memalign() and memalign() when
+ * freeing memory that needed to be adjusted to achieve
+ * the necessary alignment. */
+void *save_calloc_aligned(const char *name,const char *file,int line,
+ unsigned nelem,size_t elsize,size_t alignment)
+{
+ void **aligned=NULL;
+ void *malloced=NULL;
+ bool allocate_fail;
+
+ if (alignment == 0)
+ {
+ gmx_fatal(errno,__FILE__,__LINE__,
+ "Cannot allocate aligned memory with alignment of zero!\n(called from file %s, line %d)",file,line);
+ }
+
+
+ if (nelem ==0 || elsize == 0)
+ {
+ aligned = NULL;
+ }
+ else
+ {
+#ifdef PRINT_ALLOC_KB
+ if (nelem*elsize >= PRINT_ALLOC_KB*1024)
+ {
+ printf("Allocating %.1f MB for %s\n",
+ nelem*elsize/(PRINT_ALLOC_KB*1024.0),name);
+ }
+#endif
+
+ allocate_fail = FALSE; /* stop compiler warnings */
+#ifdef HAVE_POSIX_MEMALIGN
+ allocate_fail = (0!=posix_memalign(&malloced, alignment, nelem*elsize));
+#elif defined HAVE_MEMALIGN
+ allocate_fail = ((malloced=memalign(alignment, nelem*elsize)) == NULL);
+#elif defined HAVE__ALIGNED_MALLOC
+ allocate_fail = ((malloced=_aligned_malloc(nelem*elsize, alignment))
+ == NULL);
+#else
+ allocate_fail = ((malloced = malloc(nelem*elsize+alignment+
+ sizeof(void*)))==NULL);
+#endif
+ if (allocate_fail)
+ {
+ gmx_fatal(errno,__FILE__,__LINE__,
+ "Not enough memory. Failed to allocate %u aligned elements of size %u for %s\n(called from file %s, line %d)",nelem,elsize,name,file,line);
+ }
+ /* we start with the original pointer */
+ aligned=(void**)malloced;
+
+#ifdef GMX_OWN_MEMALIGN
+ /* Make the aligned pointer, and save the underlying pointer that
+ * we're allowed to free(). */
+
+ /* we first make space to store that underlying pointer: */
+ aligned = aligned + 1;
+ /* then we apply a bit mask */
+ aligned = (void *) (((size_t) aligned + alignment - 1) &
+ (~((size_t) (alignment-1))));
+ /* and we store the original pointer in the area just before the
+ pointer we're going to return */
+ aligned[-1] = malloced;
+#endif
+ memset(aligned, 0,(size_t) (nelem * elsize));
+ }
+ return (void*)aligned;
+}
+
+/* This routine can NOT be called with any pointer */
+void save_free_aligned(const char *name,const char *file,int line,void *ptr)
+{
+ int i, j;
+ void *free=ptr;
+
+ if (NULL != ptr)
+ {
+#ifdef GMX_OWN_MEMALIGN
+ /* we get the pointer from just before the memaligned pointer */
+ free= ((void**)ptr)[-1];
+#endif
+
+#ifndef HAVE__ALIGNED_MALLOC
+ /* (Now) we're allowed to use a normal free() on this pointer. */
+ save_free(name,file,line,free);
+#else
+ _aligned_free(free);
+#endif
+ }
+}
+
natoms = cgs->index[cgs->nr];
- if (debug) {
+ if (NULL != debug) {
pr_block(debug,0,"cgs",cgs,TRUE);
pr_blocka(debug,0,"sblock",sblock,TRUE);
+ fflush(debug);
}
cgsnum = make_invblock(cgs,natoms+1);
return estatsOK;
}
-int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int nbins,
- int normalized,real **x,real **y)
+int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int *nb,
+ int ehisto,int normalized,real **x,real **y)
{
gmx_stats *stats = (gmx_stats *) gstats;
- int i,ok,index;
- double maxy,miny,dy;
+ int i,ok,index=0,nbins=*nb,*nindex;
+ double minx,maxx,maxy,miny,delta,dd,minh;
if (((binwidth <= 0) && (nbins <= 0)) ||
((binwidth > 0) && (nbins > 0)))
{
return estatsNO_POINTS;
}
+ minx = maxx = stats->x[0];
miny = maxy = stats->y[0];
for(i=1; (i<stats->np); i++)
{
miny = (stats->y[i] < miny) ? stats->y[i] : miny;
maxy = (stats->y[i] > maxy) ? stats->y[i] : maxy;
+ minx = (stats->x[i] < minx) ? stats->x[i] : minx;
+ maxx = (stats->x[i] > maxx) ? stats->x[i] : maxx;
}
+ if (ehisto == ehistoX)
+ {
+ delta = maxx-minx;
+ minh = minx;
+ }
+ else if (ehisto == ehistoY)
+ {
+ delta = maxy-miny;
+ minh = miny;
+ }
+ else
+ return estatsINVALID_INPUT;
+
if (binwidth == 0)
{
- binwidth = (maxy-miny)/nbins;
+ binwidth = (delta)/nbins;
}
else
{
- nbins = gmx_nint((maxy-miny)/binwidth + 0.5);
+ nbins = gmx_nint((delta)/binwidth + 0.5);
}
snew(*x,nbins);
+ snew(nindex,nbins);
for(i=0; (i<nbins); i++)
{
- (*x)[i] = miny + binwidth*(i+0.5);
+ (*x)[i] = minh + binwidth*(i+0.5);
}
if (normalized == 0)
{
- dy = 1;
+ dd = 1;
}
else
{
- dy = 1.0/(binwidth*stats->np);
+ dd = 1.0/(binwidth*stats->np);
}
snew(*y,nbins);
for(i=0; (i<stats->np); i++)
{
- index = (stats->y[i]-miny)/binwidth;
-
- if(index<0)
+ if (ehisto == ehistoY)
+ index = (stats->y[i]-miny)/binwidth;
+ else if (ehisto == ehistoX)
+ index = (stats->x[i]-minx)/binwidth;
+ if (index<0)
{
index = 0;
}
- if(index>nbins-1)
+ if (index>nbins-1)
{
index = nbins-1;
}
- (*y)[index] += dy;
- }
+ (*y)[index] += dd;
+ nindex[index]++;
+ }
+ if (*nb == 0)
+ *nb = nbins;
+ for(i=0; (i<nbins); i++)
+ if (nindex[i] > 0)
+ (*y)[i] /= nindex[i];
+
+ sfree(nindex);
return estatsOK;
}
#endif
if ((pr=strrchr(ret,'/')) != NULL)
ret=pr+1;
- /*else
- ret=ret;*/
+ /* Strip away the libtool prefix if it's still there. */
+ if(strlen(ret) > 3 && !strncmp(ret, "lt-", 3))
+ ret = ret + 3;
return ret;
}
{
FILE *fp;
char buf[256];
- const char *pr;
- const char *program_name=output_env_get_program_name(oenv);
-
- if ( (pr=strrchr(program_name,'/')) == NULL)
- pr=program_name;
- else
- pr+=1;
+ const char *pr = output_env_get_short_program_name(oenv);
if (strcmp(mantp,"ascii") != 0)
sprintf(buf,"%s.%s",pr,mantp);
setTimeValue(TDELTA,opt2parg_real("-dt",npall,all_pa));
/* clear memory */
+ for (i = 0; i < npall; ++i)
+ sfree((void *)all_pa[i].desc);
sfree(all_pa);
if (!FF(PCA_NOEXIT_ON_ARGS)) {
{
FILE *in;
char **ptr=NULL;
- char buf[256];
+ char buf[STRLEN];
int i,nstr,maxi;
in=libopen(db);
i=maxi=0;
- while (fgets2(buf,255,in)) {
+ while (fgets2(buf,STRLEN-1,in)) {
if (i>=maxi) {
maxi+=50;
srenew(ptr,maxi);
}
++pattern;
}
- return 0;
+ /* When the pattern runs out, we have a match if the string has ended. */
+ return (*str == 0) ? 0 : GMX_NO_WCMATCH;
}
char *wrap_lines(const char *buf,int line_width, int indent,bool bIndentFirst)
add_library(thread_mpi STATIC threads.c tmpi_init.c errhandler.c
type.c group.c comm.c topology.c p2p.c collective.c
once.c list.c reduce_fast.c profile.c event.c barrier.c
- hwinfo.c)
+ lock.c hwinfo.c)
# make it link to the threads library (-lpthreads, for example)
target_link_libraries(thread_mpi ${THREAD_LIB})
#add_definitions(-DHAVE_TMPI_CONFIG_H)
#include_directories( . )
+# this configure file only works here. If you include the source
+# files into your project, insert the contest of the tmpi_config.h.cmakein
+# into your config.h.cmakein file
configure_file(tmpi_config.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/tmpi_config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_definitions(-DHAVE_TMPI_CONFIG_H)
once.c tmpi_init.c comm.c \
profile.c errhandler.c topology.c \
event.c type.c reduce_fast.c \
- hwinfo.c
+ hwinfo.c lock.c
CLEANFILES = *.la *~ \\\#*
-void tMPI_Spinlock_barrier_init(tMPI_Spinlock_barrier_t *barrier, int count)
+void tMPI_Barrier_init(tMPI_Barrier_t *barrier, int count)
{
barrier->threshold = count;
barrier->cycle = 0;
}
-int tMPI_Spinlock_barrier_wait(tMPI_Spinlock_barrier_t *barrier)
+int tMPI_Barrier_wait(tMPI_Barrier_t *barrier)
{
int cycle;
int status;
tMPI_Profile_wait_start(cur);
#endif
- tMPI_Spinlock_barrier_wait( &(comm->barrier) );
+ tMPI_Barrier_wait( &(comm->barrier) );
#if defined(TMPI_PROFILE)
tMPI_Profile_wait_stop(cur, TMPIWAIT_Barrier);
#endif
return tMPI_Group_rank(&(comm->grp), rank);
}
+
+int tMPI_Comm_compare(tMPI_Comm comm1, tMPI_Comm comm2, int *result)
+{
+ int i,j;
+#ifdef TMPI_TRACE
+ tMPI_Trace_print("tMPI_Comm_compare(%p, %p, %p)", comm1, comm2, result);
+#endif
+ if (comm1 == comm2)
+ {
+ *result=TMPI_IDENT;
+ return TMPI_SUCCESS;
+ }
+
+ if ( (!comm1) || (!comm2) )
+ {
+ *result=TMPI_UNEQUAL;
+ return TMPI_SUCCESS;
+ }
+
+ if (comm1->grp.N != comm2->grp.N)
+ {
+ *result=TMPI_UNEQUAL;
+ return TMPI_SUCCESS;
+ }
+
+ *result=TMPI_CONGRUENT;
+ /* we assume that there are two identical comm members within a comm */
+ for(i=0;i<comm1->grp.N;i++)
+ {
+ if (comm1->grp.peers[i] != comm2->grp.peers[i])
+ {
+ bool found=FALSE;
+
+ *result=TMPI_SIMILAR;
+ for(j=0;j<comm2->grp.N;j++)
+ {
+ if (comm1->grp.peers[i] == comm2->grp.peers[j])
+ {
+ found=TRUE;
+ break;
+ }
+ }
+ if (!found)
+ {
+ *result=TMPI_UNEQUAL;
+ return TMPI_SUCCESS;
+ }
+ }
+ }
+ return TMPI_SUCCESS;
+}
+
+
tMPI_Comm tMPI_Comm_alloc(tMPI_Comm parent, int N)
{
struct tmpi_comm_ *ret;
/* initialize the main barrier */
- tMPI_Spinlock_barrier_init(&(ret->barrier), N);
+ tMPI_Barrier_init(&(ret->barrier), N);
#if 0
{
}
ret->Nreduce_barriers=Nbarriers;
- ret->reduce_barrier=(tMPI_Spinlock_barrier_t*)
- tMPI_Malloc(sizeof(tMPI_Spinlock_barrier_t)*(Nbarriers+1));
+ ret->reduce_barrier=(tMPI_Barrier_t*)
+ tMPI_Malloc(sizeof(tMPI_Barrier_t)*(Nbarriers+1));
ret->N_reduce_barrier=(int*)tMPI_Malloc(sizeof(int)*(Nbarriers+1));
Nred=N;
for(i=0;i<Nbarriers;i++)
{
- tMPI_Spinlock_barrier_init( &(ret->reduce_barrier[i]), Nred);
+ tMPI_Barrier_init( &(ret->reduce_barrier[i]), Nred);
ret->N_reduce_barrier[i]=Nred;
/* Nred is now Nred/2 + a rest term because solitary
process at the end of the list must still be accounter for */
ret->N_reduce_iter=Niter;
/* allocate the list */
- ret->reduce_barrier=(tMPI_Spinlock_barrier_t**)
- tMPI_Malloc(sizeof(tMPI_Spinlock_barrier_t*)*(Niter+1));
+ ret->reduce_barrier=(tMPI_Barrier_t**)
+ tMPI_Malloc(sizeof(tMPI_Barrier_t*)*(Niter+1));
ret->N_reduce=(int*)tMPI_Malloc(sizeof(int)*(Niter+1));
/* we re-set Nred to N */
Nred = Nred/2 + Nred%2;
ret->N_reduce[i] = Nred;
/* allocate the sub-list */
- ret->reduce_barrier[i]=(tMPI_Spinlock_barrier_t*)
- tMPI_Malloc(sizeof(tMPI_Spinlock_barrier_t)*(Nred));
+ ret->reduce_barrier[i]=(tMPI_Barrier_t*)
+ tMPI_Malloc(sizeof(tMPI_Barrier_t)*(Nred));
for(j=0;j<Nred;j++)
{
- tMPI_Spinlock_barrier_init(&(ret->reduce_barrier[i][j]),2);
+ tMPI_Barrier_init(&(ret->reduce_barrier[i][j]),2);
}
}
}
#include "thread_mpi/collective.h"
#include "thread_mpi/barrier.h"
#include "thread_mpi/hwinfo.h"
-#include "wait.h"
-#include "barrier.h"
-#include "event.h"
+#include "thread_mpi/lock.h"
#ifdef TMPI_PROFILE
#include "profile.h"
#endif
struct tmpi_group_ grp; /* the communicator group */
/* the barrier for tMPI_Barrier() */
- tMPI_Spinlock_barrier_t barrier;
+ tMPI_Barrier_t barrier;
/* List of barriers for reduce operations.
reduce_barrier[2] contains a list of N/8 barriers for N/4 threads
and so on. (until N/x reaches 1)
This is to facilitate tree-based algorithms for tMPI_Reduce, etc. */
- tMPI_Spinlock_barrier_t **reduce_barrier;
+ tMPI_Barrier_t **reduce_barrier;
int *N_reduce; /* the number of barriers in each iteration */
int N_reduce_iter; /* the number of iterations */
files.
*/
+#ifdef HAVE_TMPI_CONFIG_H
+#include "tmpi_config.h"
+#endif
-struct tMPI_Spinlock_barrier
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "impl.h"
+
+
+
+void tMPI_Lock_init(tMPI_Lock_t *lock)
+{
+ tMPI_Spinlock_init(&(lock->lock));
+ TMPI_YIELD_WAIT_DATA_INIT(lock);
+}
+
+
+void tMPI_Lock_lock(tMPI_Lock_t *lock)
{
- tMPI_Atomic_t count; /*!< Number of threads remaining */
- int threshold; /*!< Total number of threads */
- volatile int cycle; /*!< Current cycle (alternating 0/1) */
- TMPI_YIELD_WAIT_DATA
-};
+ while(!tMPI_Spinlock_trylock(&(lock->lock)))
+ {
+ TMPI_YIELD_WAIT(lock);
+ }
+}
+void tMPI_Lock_unlock(tMPI_Lock_t *lock)
+{
+ tMPI_Spinlock_unlock(&(lock->lock));
+}
+
+int tMPI_Lock_trylock(tMPI_Lock_t *lock)
+{
+ return tMPI_Spinlock_trylock(&(lock->lock));
+}
+
+int tMPI_Lock_islocked(const tMPI_Lock_t *lock)
+{
+ return tMPI_Spinlock_islocked(&(lock->lock));
+}
#endif
evl->Nalloc=N;
- evl->alloc_head=(struct envelope*)tMPI_Malloc(sizeof(struct envelope)*N );
+ evl->alloc_head=(struct envelope*)tMPI_Malloc(sizeof(struct envelope)*N);
for(i=0;i<N;i++)
{
evl->alloc_head[i].next=(i<(N-1)) ? &(evl->alloc_head[i+1]) : NULL;
#include <stdarg.h>
#endif
+int tMPI_Profile_started=0;
+
/* this must match the tmpi_functions enum: */
const char *tmpi_function_names[] =
prof->buffered_coll_xfers=0;
prof->total_p2p_xfers=0;
prof->total_coll_xfers=0;
+ tMPI_Profile_started=1;
}
#ifdef TMPI_CYCLE_COUNT
prof->global_stop=tmpi_cycles_read();
#endif
+ tMPI_Profile_started=0;
}
/* output functions */
#endif
};
+extern int tMPI_Profile_started;
+
/* initialize the profile counter */
void tMPI_Profile_init(struct tmpi_profile *prof);
#ifdef TMPI_DEBUG
printf("%d: iteration %d: myrank_rtr=%d, stepping=%d\n",
myrank, iteration, myrank_rtr, stepping);
- fflush(0);
+ fflush(stdout);
#endif
/* check if I'm the reducing thread in this iteration's pair: */
if (myrank_rtr%stepping == 0)
#ifdef TMPI_DEBUG
printf("%d: waiting to reduce with %d, iteration=%d\n",
myrank, nbr, iteration);
- fflush(0);
+ fflush(stdout);
#endif
#if defined(TMPI_PROFILE) && defined(TMPI_CYCLE_COUNT)
#ifdef TMPI_DEBUG
printf("%d: reducing with %d, iteration=%d\n",
myrank, nbr, iteration);
- fflush(0);
+ fflush(stdout);
#endif
/* we reduce with our neighbour*/
if (iteration==0)
{
#ifdef TMPI_DEBUG
printf("%d: not waiting copying buffer\n", myrank);
- fflush(0);
+ fflush(stdout);
#endif
/* we still need to put things in the right buffer for the next
iteration. We need to check for overlapping buffers
#ifdef TMPI_DEBUG
printf("%d: signalled %d, now waiting: iteration=%d\n",
nbr, myrank, iteration);
- fflush(0);
+ fflush(stdout);
#endif
/* And wait for an incoming event from out neighbour */
#ifdef TMPI_DEBUG
printf("%d: iteration over, iteration=%d\n", myrank, iteration);
- fflush(0);
+ fflush(stdout);
#endif
Nred = Nred/2 + Nred%2;
#if defined(TMPI_PROFILE)
tMPI_Profile_wait_start(cur);
#endif
- tMPI_Spinlock_barrier_wait( &(comm->barrier));
+ tMPI_Barrier_wait( &(comm->barrier));
#if defined(TMPI_PROFILE) && defined(TMPI_CYCLE_COUNT)
tMPI_Profile_wait_stop(cur, TMPIWAIT_Reduce);
#endif
#if defined(TMPI_PROFILE) && defined(TMPI_CYCLE_COUNT)
tMPI_Profile_wait_start(cur);
#endif
- tMPI_Spinlock_barrier_wait( &(comm->barrier));
+ tMPI_Barrier_wait( &(comm->barrier));
#if defined(TMPI_PROFILE)
tMPI_Profile_wait_stop(cur, TMPIWAIT_Reduce);
tMPI_Profile_count_stop(cur, TMPIFN_Allreduce);
/* the number of envelopes to allocate per thread-to-thread path */
-#define N_EV_ALLOC 8
+#define N_EV_ALLOC 16
/* the normal maximum number of threads for pre-defined arrays
(if the actual number of threads is bigger than this, it'll
+++ /dev/null
-/*
-This source code file is part of thread_mpi.
-Written by Sander Pronk, Erik Lindahl, and possibly others.
-
-Copyright (c) 2009, Sander Pronk, Erik Lindahl.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-1) Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2) Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3) Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-If you want to redistribute modifications, please consider that
-scientific software is very special. Version control is crucial -
-bugs must be traceable. We will be happy to consider code for
-inclusion in the official distribution, but derived work should not
-be called official thread_mpi. Details are found in the README & COPYING
-files.
-*/
-
-
-
-#include "settings.h"
-
-
-/* BASIC DEFINITIONS */
-
-
-#ifndef __cplusplus
-typedef int bool;
-#define TRUE 1
-#define FALSE 0
-#else
-#ifndef TRUE
-#define TRUE true
-#endif
-#ifndef FALSE
-#define FALSE false
-#endif
-#endif
-
-
-
-
-
-#ifdef USE_COLLECTIVE_COPY_BUFFER
-/* PRE-ALLOCATED COMMUNICATION BUFFERS */
-
-/* Buffer structure. Every thread structure has several of these ready to
- be used when the data transmission is small enough for double copying to
- occur (i.e. the size of the transmission is less than N*MAX_COPY_BUFFER_SIZE,
- where N is the number of receiving threads).
-
- These buffers come in two sizes: one pre-allocated to MAX_COPY_BUFFER_SIZE
- (for point-to-point transmissions, and one pre-allocated to
- Nthreads*MAX_COPY_BUFFE_SIZE). */
-struct copy_buffer
-{
- void *buf; /* the actual buffer */
- struct copy_buffer *next; /* pointer to next free buffer in buffer_list */
- size_t size; /* allocated size of buffer */
-};
-
-/* a list of copy_buffers of a specific size. */
-struct copy_buffer_list
-{
- struct copy_buffer *cb; /* pointer to the first copy_buffer */
- size_t size; /* allocated size of buffers in this list */
- struct copy_buffer *cb_alloc; /* list as allocated */
- int Nbufs; /* number of allocated buffers */
-};
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* POINT-TO-POINT COMMUNICATION DATA STRUCTURES */
-
-/* the message envelopes (as described in the MPI standard).
- These fully describes the message, and make each message unique (enough).
-
- Transmitting data works by having the sender put a pointer to an envelope
- onto the receiver's new envelope list corresponding to the originating
- thread.
- The sender then waits until the receiver finishes the transmission, while
- matching all incoming new envelopes against its own list of receive
- envelopes.
-
- The receiver either directly matches its receiving envelope against
- all previously un-matched sending envelopes, or, if no suitable envelope
- is found, it puts the receive envelope on a receive list.
- Once waiting for completion, the receiver matches against all incoming
- new envelopes. */
-
-/* the state of an individual point-to-point transmission */
-enum envelope_state
-{
- env_unmatched = 0, /* the envelope has not had a match yet */
- env_copying = 1, /* busy copying (only used for send_envelope
- by receiver if using_cpbuf is true,
- but cb was still NULL). */
- env_cb_available = 2, /* the copy buffer is available. Set by
- the sender on a send_buffer. */
- env_finished = 3 /* the transmission has finished */
-};
-
-
-/* the send envelope. Held in tmpi_thread->evs[src_thread] */
-struct send_envelope
-{
- int tag; /* the tag */
- tMPI_Comm comm; /* this is a structure shared across threads, so we
- can test easily whether two threads are talking
- about the same comm. */
-
- struct tmpi_thread *src, *dest; /* these are pretty obvious */
-
- void *buf; /* buffer to be sent */
- size_t bufsize; /* the size of the data to be transmitted */
- tMPI_Datatype datatype; /* the data type */
-
- bool nonblock; /* whether the receiver is non-blocking */
-
- /* state, values from enum_envelope_state .
- (there's a few busy-waits relying on this flag).
- status=env_unmatched is the initial state.*/
- tMPI_Atomic_t state;
-
- /* the error condition */
- int error;
-
- /* the message status */
- tMPI_Status *status;
- /* prev and next envelopes in the linked list */
- struct send_envelope *prev,*next;
-#ifdef USE_SEND_RECV_COPY_BUFFER
- bool using_cb; /* whether a copy buffer is (going to be) used */
- void* cb;/* the allocated copy buffer pointer */
-#endif
- /* the list I'm in */
- struct send_envelope_list *list;
-};
-
-/* the receive envelope. Held in tmpi_thread->evl */
-struct recv_envelope
-{
- int tag; /* the tag */
- /* transmission type flags */
-
-
- tMPI_Comm comm; /* this is a structure shared across threads, so we
- can test easily whether two threads are talking
- about the same comm. */
-
- struct tmpi_thread *src, *dest; /* these are pretty obvious */
-
- void *buf; /* buffer to be sent */
- size_t bufsize; /* the size of the data to be transmitted, or the
- size of the actually transmitted data after Xfer. */
- tMPI_Datatype datatype; /* the data type */
-
- bool nonblock; /* whether the receiver is non-blocking */
-
- /* state, values from enum_envelope_state .
- (there's a few busy-waits relying on this flag).
- status=env_unmatched is the initial state.*/
- tMPI_Atomic_t state;
-
- /* the error condition */
- int error;
-
- /* prev and next envelopes in the linked list */
- struct recv_envelope *prev,*next;
- /* the list I'm in */
- struct recv_envelope_list *list;
-};
-
-
-/* singly linked lists of free send & receive envelopes belonging to a
- thread. */
-struct free_envelope_list
-{
- struct recv_envelope *head_recv; /* the first element in the
- linked list */
- struct recv_envelope *recv_alloc_head; /* the allocated recv list */
-};
-
-/* collection of send envelopes to a specific thread */
-struct send_envelope_list
-{
- struct send_envelope *head_free; /* singly linked list with free send
- envelopes. A single-thread LIFO.*/
-#ifdef TMPI_LOCK_FREE_LISTS
- tMPI_Atomic_ptr_t head_new; /* singly linked list with the new send
- envelopes (i.e. those that are put there by
- the sending thread, but not yet checked by
- the receiving thread). This is a lock-free
- shared detachable list.*/
- tMPI_Atomic_ptr_t head_rts; /* singly linked list with free send
- envelopes returned by the other thread.
- This is a lock-free shared LIFO.*/
-#else
- struct send_envelope *head_new; /* singly linked list with the new
- send envelopes (i.e. those that
- are put there by the sending
- thread, but not yet checked by
- the receiving thread). */
- struct send_envelope *head_rts; /* singly linked list with free
- send envelopes */
- tMPI_Spinlock_t lock_new; /* this locks head_new */
- tMPI_Spinlock_t lock_rts; /* this locks head_rts */
-#endif
- struct send_envelope *head_old; /* the old send envelopes, in a circular
- doubly linked list. These have been
- checked by the receiving thread against
- the existing recv_envelope_list. */
-
- struct send_envelope *alloc_head; /* the allocated send list */
- size_t Nalloc; /* number of allocted sends */
-};
-
-struct recv_envelope_list
-{
- struct recv_envelope *head; /* first envelope in this list */
- struct recv_envelope dummy; /* the dummy element for the list */
-};
-
-
-/* the request object for asynchronious operations. */
-struct tmpi_req_
-{
- bool recv; /* whether it's a receive request. */
- bool finished; /* whether it's finished */
-
- struct send_envelope *evs; /* the envelope */
- struct recv_envelope *evr; /* the envelope */
-
- struct tmpi_status_ st;
-
- struct tmpi_req_ *next,*prev; /* next,prev request in linked list */
-};
-
-/* pre-allocated request object list */
-struct req_list
-{
- struct tmpi_req_ *head; /* pre-allocated singly linked list of requests.
- (i.e. reqs->prev is undefined). */
- struct tmpi_req_ *alloc_head; /* the allocated block */
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* MULTICAST COMMUNICATION DATA STRUCTURES */
-
-/* these are data structures meant for keeping track of multicast operations
- (tMPI_Bcast, tMPI_Gather, etc.). Because these operations are all collective
- across the comm, and are always blocking, the protocol can be much simpler
- than that for point-to-point communication through tMPI_Send/Recv, etc. */
-
-/* unique tags for multicast & collective operations */
-#define TMPI_BCAST_TAG 1
-#define TMPI_GATHER_TAG 2
-#define TMPI_GATHERV_TAG 3
-#define TMPI_SCATTER_TAG 4
-#define TMPI_SCATTERV_TAG 5
-#define TMPI_REDUCE_TAG 6
-#define TMPI_ALLTOALL_TAG 7
-#define TMPI_ALLTOALLV_TAG 8
-
-
-/* thread-specific part of the coll_env */
-struct coll_env_thread
-{
- tMPI_Atomic_t current_sync; /* sync counter value for the current
- communication */
- tMPI_Atomic_t n_remaining; /* remaining threads count for each thread */
-
- int tag; /* collective communication type */
- tMPI_Datatype datatype; /* datatype */
-
- void **buf; /* array of send/recv buffer values */
- size_t *bufsize; /* array of number of bytes to send/recv */
-
-#ifdef USE_COLLECTIVE_COPY_BUFFER
- bool using_cb; /* whether a copy buffer is (going to be) used */
- tMPI_Atomic_t buf_readcount; /* Number of threads reading from buf
- while using_cpbuf is true, but cpbuf
- is still NULL. */
- tMPI_Atomic_ptr_t *cpbuf; /* copy_buffer pointers. */
- struct copy_buffer *cb; /* the copy buffer cpbuf points to */
-#endif
-#ifdef TMPI_NO_BUSY_WAIT_COLLECTIVE
- tMPI_Thread_mutex_t wait_mutex; /* mutex associated with waiting */
- tMPI_Thread_cond_t send_cond; /* condition associated with the sending */
- tMPI_Thread_cond_t recv_cond; /* condition associated with the receiving */
-#endif
-
- bool *read_data; /* whether we read data from a specific thread. */
-};
-
-/* Collective communications once sync. These run in parallel with
- the collection of coll_env_threads*/
-struct coll_env_coll
-{
- /* collective sync data */
- tMPI_Atomic_t current_sync; /* sync counter value for the current
- communication */
- tMPI_Atomic_t n_remaining; /* remaining threads count */
-
- void *res; /* result data for once calls. */
-};
-
-/* the collective communication envelope. There's a few of these per
- comm, and each one stands for one collective communication call. */
-struct coll_env
-{
- struct coll_env_thread *met; /* thread-specific collective envelope data.*/
-
- struct coll_env_coll coll;
- int N;
-};
-
-/* multicast synchronization data structure. There's one of these for
- each thread in each tMPI_Comm structure */
-struct coll_sync
-{
- int synct; /* sync counter for coll_env_thread. */
- int syncs; /* sync counter for coll_env_coll. */
-};
-
-
-
-
-
-
-
-
-
-
-/* GLOBALLY AVAILABLE DATA STRUCTURES */
-#ifdef TMPI_PROFILE
-#include "profile.h"
-#endif
-
-/* information about a running thread. This structure is put in a
- globally available array; the envelope exchange, etc. are all done through
- the elements of this array.*/
-struct tmpi_thread
-{
- tMPI_Thread_t thread_id;
-
- /* the receive envelopes posted for other threads to check */
- struct recv_envelope_list evr;
- /* the send envelopes posted by other threadas */
- struct send_envelope_list *evs;
-
-
-#ifndef TMPI_NO_BUSY_WAIT_SEND_RECV
- /* send envelope change indicator/count */
- tMPI_Atomic_t evs_new_incoming;
-#else
- /* lock+signal for signaling newly available send envelopes to this thread,
- or finished send envelopes from this thread. */
- tMPI_Thread_mutex_t ev_check_lock;
- tMPI_Thread_cond_t ev_check_cond;
- /* send envelope change count */
- int evs_new_incoming;
- /* the number of send envelopes from this thread that have been
- xmitted by other threads */
- int ev_received;
-#endif
-
- struct req_list rql; /* list of pre-allocated requests */
-
- struct free_envelope_list envelopes; /* free envelopes */
-#ifdef USE_COLLECTIVE_COPY_BUFFER
- /* copy buffer list for multicast communications */
- struct copy_buffer_list cbl_multi;
-#endif
-
- tMPI_Comm self_comm; /* comms for MPI_COMM_SELF */
-
-#ifdef TMPI_PROFILE
- struct tmpi_profile profile;
-#endif
-
- void (*start_fn)(void*); /* The start function (or NULL, if main() is to be
- called) */
- void *start_arg; /* the argument to the start function, if it's not main()*/
-
- /* we copy these for each thread (this is not required by the
- MPI standard, but it's convenient). Note that we copy, because
- some programs (like Gromacs) like to manipulate these. */
- int argc;
- char **argv;
-};
-
-
-/* the error handler */
-struct tmpi_errhandler_
-{
- int err;
- tMPI_Errhandler_fn fn;
-};
-
-/* standard error handler functions */
-void tmpi_errors_are_fatal_fn(tMPI_Comm *comm, int *err);
-void tmpi_errors_return_fn(tMPI_Comm *comm, int *err);
-
-
-/* global MPI information */
-struct tmpi_global
-{
- /* list of pointers to all user-defined types */
- struct tmpi_datatype_ **usertypes;
- int N_usertypes;
- int Nalloc_usertypes;
-
- /* spinlock/mutex for manipulating tmpi_user_types */
- tMPI_Spinlock_t datatype_lock;
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* COMMUNICATOR DATA STRUCTURES */
-
-
-
-struct tmpi_group_
-{
- int N; /* the number of threads */
- struct tmpi_thread **peers; /* the list of peers to communicate with */
-#if 0
- int Nrefs; /* the number of references to this structure */
-#endif
-};
-
-
-/* the communicator objects are globally shared. */
-struct tmpi_comm_
-{
- struct tmpi_group_ grp; /* the communicator group */
-
- /* list of barrier_t's.
- multicast_barrier[0] contains a barrier for N threads
- (N=the number of threads in the communicator)
- multicast_barrier[1] contains a barrier for N/2 threads
- multicast_barrier[2] contains a barrier for N/4 threads
- multicast_barrier[3] contains a barrier for N/8 threads
- and so on. (until N/x reaches 1)
- This is to facilitate tree-based algorithms for tMPI_Reduce, etc. */
-#ifndef TMPI_NO_BUSY_WAIT_BARRIER
- tMPI_Spinlock_barrier_t *multicast_barrier;
-#else
- tMPI_Thread_barrier_t *multicast_barrier;
-#endif
- int *N_multicast_barrier;
- int Nbarriers;
-
- struct coll_env *cev; /* list of multicast envelope objecs */
- struct coll_sync *csync; /* list of multicast sync objecs */
-
- /* lists of globally shared send/receive buffers for tMPI_Reduce, etc. */
- volatile void **sendbuf, **recvbuf;
-
- /* mutex for communication object creation. Traditional mutexes are
- better here because communicator creation should not be done in
- time-critical sections of code. */
- tMPI_Thread_mutex_t comm_create_lock;
- tMPI_Thread_cond_t comm_create_prep;
- tMPI_Thread_cond_t comm_create_finish;
-
- tMPI_Comm *new_comm; /* newly created communicators */
- struct tmpi_split *split;
-
- /* the topologies (only cartesian topology is currently implemented */
- struct cart_topol *cart;
- /*struct tmpi_graph_topol_ *graph;*/
-
- tMPI_Errhandler erh;
-
- /* links of a global list of all comms that starts at TMPI_COMM_WORLD */
- struct tmpi_comm_ *next,*prev;
-};
-
-
-/* specific for tMPI_Split: */
-struct tmpi_split
-{
- volatile int Ncol_init;
- volatile int Ncol_destroy;
- volatile bool can_finish;
- volatile int *colors;
- volatile int *keys;
-};
-
-/* cartesian topology */
-struct cart_topol
-{
- int ndims; /* number of dimensions */
- int *dims; /* procs per coordinate */
- int *periods; /* whether the grid is periodic, per dimension */
-};
-
-#if 0
-/* graph topology */
-struct tmpi_graph_topol_
-{
-};
-#endif
-
-
-
-
-
-
-
-/* tMPI_Reduce Op functions */
-typedef void (*tMPI_Op_fn)(void*, void*, void*, int);
-
-
-struct tmpi_datatype_component
-{
- struct tmpi_datatype_ *type;
- unsigned int count;
-};
-
-/* we don't support datatypes with holes (yet) */
-struct tmpi_datatype_
-{
- size_t size; /* full extent of type. */
- tMPI_Op_fn *op_functions; /* array of op functions for this datatype */
- int N_comp; /* number of components */
- struct tmpi_datatype_component *comps; /* the components */
- bool committed; /* whether the data type is committed */
-};
-/* just as a shorthand: */
-typedef struct tmpi_datatype_ tmpi_dt;
-
-
-
-#if 0
-#ifdef TMPI_PROFILE
-/* bookkeeping structure for a single call */
-struct tmpi_profile_call_
-{
- int Ncalls;
- int Nbuffered;
-}
-
-/* bookkeeping structure for profiling */
-struct tmpi_profile_
-{
- struct tmpi_profile_call_ tMPI_Send;
-};
-#endif
-#endif
-
-
-
-
-
-/* global variables */
-
-/* the threads themselves (tmpi_comm only contains lists of pointers to this
- structure */
-extern struct tmpi_thread *threads;
-extern int Nthreads;
-
-/* thread info */
-extern tMPI_Thread_key_t id_key; /* the key to get the thread id */
-
-/* misc. global information about MPI */
-extern struct tmpi_global *tmpi_global;
-
-
-
-
-
-#ifdef TMPI_TRACE
-void tMPI_Trace_print(const char *fmt, ...);
-#endif
-
-/* error-checking malloc/realloc: */
-void *tMPI_Malloc(size_t size);
-void *tMPI_Realloc(void *p, size_t size);
-
-
-/* get the current thread structure pointer */
-#define tMPI_Get_current() ((struct tmpi_thread*) \
- tMPI_Thread_getspecific(id_key))
-
-/* get the number of this thread */
-/*#define tMPI_This_threadnr() (tMPI_Get_current() - threads)*/
-
-/* get the number of a specific thread. We convert to the resulting size_t to
- int, which is unlikely to cause problems in the foreseeable future. */
-#define tMPI_Threadnr(th) (int)(th - threads)
-
-/* get thread associated with rank */
-#define tMPI_Get_thread(comm, rank) (comm->grp.peers[rank])
-
-
-#if 0
-/* get the current thread structure pointer */
-struct tmpi_thread *tMPI_Get_current(void);
-/* get the thread belonging to comm with rank rank */
-struct tmpi_thread *tMPI_Get_thread(tMPI_Comm comm, int rank);
-
-#endif
-
-/* handle an error, returning the errorcode */
-int tMPI_Error(tMPI_Comm comm, int tmpi_errno);
-
-
-
-/* check whether we're the main thread */
-bool tMPI_Is_master(void);
-/* check whether the current process is in a group */
-bool tMPI_In_group(tMPI_Group group);
-
-/* find the rank of a thread in a comm */
-int tMPI_Comm_seek_rank(tMPI_Comm comm, struct tmpi_thread *th);
-/* find the size of a comm */
-int tMPI_Comm_N(tMPI_Comm comm);
-
-/* allocate a comm object, making space for N threads */
-tMPI_Comm tMPI_Comm_alloc(tMPI_Comm parent, int N);
-/* de-allocate a comm object */
-void tMPI_Comm_destroy(tMPI_Comm comm);
-/* allocate a group object */
-tMPI_Group tMPI_Group_alloc(void);
-
-
-#ifdef USE_COLLECTIVE_COPY_BUFFER
-/* initialize a copy_buffer_list */
-void tMPI_Copy_buffer_list_init(struct copy_buffer_list *cbl, int Nbufs,
- size_t size);
-/* initialize a copy_buffer_list */
-void tMPI_Copy_buffer_list_destroy(struct copy_buffer_list *cbl);
-/* get a copy buffer from a list */
-struct copy_buffer *tMPI_Copy_buffer_list_get(struct copy_buffer_list *cbl);
-/* return a copy buffer to a list */
-void tMPI_Copy_buffer_list_return(struct copy_buffer_list *cbl,
- struct copy_buffer *cb);
-/* initialize a copy buffer */
-void tMPI_Copy_buffer_init(struct copy_buffer *cb, size_t size);
-void tMPI_Copy_buffer_destroy(struct copy_buffer *cb);
-#endif
-
-
-
-
-
-/* initialize a free envelope list with N envelopes */
-void tMPI_Free_env_list_init(struct free_envelope_list *evl, int N);
-/* destroy a free envelope list */
-void tMPI_Free_env_list_destroy(struct free_envelope_list *evl);
-
-
-/* initialize a send envelope list */
-void tMPI_Send_env_list_init(struct send_envelope_list *evl, int N);
-/* destroy a send envelope list */
-void tMPI_Send_env_list_destroy(struct send_envelope_list *evl);
-
-
-
-
-
-
-/* initialize a recv envelope list */
-void tMPI_Recv_env_list_init(struct recv_envelope_list *evl);
-/* destroy a recv envelope list */
-void tMPI_Recv_env_list_destroy(struct recv_envelope_list *evl);
-
-
-
-
-/* initialize request list */
-void tMPI_Req_list_init(struct req_list *rl, int N_reqs);
-/* destroy request list */
-void tMPI_Req_list_destroy(struct req_list *rl);
-
-
-
-
-/* multicast functions */
-/* initialize a coll env structure */
-void tMPI_Coll_env_init(struct coll_env *mev, int N);
-/* destroy a coll env structure */
-void tMPI_Coll_env_destroy(struct coll_env *mev);
-
-/* initialize a coll sync structure */
-void tMPI_Coll_sync_init(struct coll_sync *msc);
-/* destroy a coll sync structure */
-void tMPI_Coll_sync_destroy(struct coll_sync *msc);
-
-
-
-
-/* and we need this prototype */
-int main(int argc, char **argv);
-
-
-
-
-
-
/* start N threads with argc, argv (used by tMPI_Init)*/
-static void tMPI_Start_threads(int N, int *argc, char ***argv,
- void (*start_fn)(void*), void *start_arg);
+static void tMPI_Start_threads(bool main_returns, int N, int *argc,
+ char ***argv, void (*start_fn)(void*),
+ void *start_arg);
/* starter function for threads; takes a void pointer to a
struct tmpi_starter_, which calls main() if tmpi_start_.fn == NULL */
static void* tMPI_Thread_starter(void *arg);
void *tMPI_Malloc(size_t size)
{
void *ret=(void*)malloc(size);
+
if (!ret)
{
tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_MALLOC);
static void tMPI_Thread_init(struct tmpi_thread *th)
{
- int N_envelopes=(Nthreads+1)*(Nthreads+1)*N_EV_ALLOC;
- int N_send_envelopes=(Nthreads+1)*N_EV_ALLOC;
- int N_reqs=(Nthreads+1)*(Nthreads+1)*N_EV_ALLOC;
+ int N_envelopes=(Nthreads+1)*N_EV_ALLOC;
+ int N_send_envelopes=N_EV_ALLOC;
+ int N_reqs=(Nthreads+1)*N_EV_ALLOC;
int i;
+ /* we set our thread id, as a thread-specific piece of global data. */
+ tMPI_Thread_setspecific(id_key, th);
+
/* allocate comm.self */
th->self_comm=tMPI_Comm_alloc(TMPI_COMM_WORLD, 1);
th->self_comm->grp.peers[0]=th;
static void* tMPI_Thread_starter(void *arg)
{
struct tmpi_thread *th=(struct tmpi_thread*)arg;
- /* we set our thread id, as a thread-specific piece of global data. */
- tMPI_Thread_setspecific(id_key, arg);
#ifdef TMPI_TRACE
tMPI_Trace_print("Created thread nr. %d", (int)(th-threads));
}
-void tMPI_Start_threads(int N, int *argc, char ***argv,
+void tMPI_Start_threads(bool main_returns, int N, int *argc, char ***argv,
void (*start_fn)(void*), void *start_arg)
{
#ifdef TMPI_TRACE
{
tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_INIT);
}
- /*printf("thread keys created\n"); fflush(NULL);*/
for(i=0;i<N;i++)
{
TMPI_COMM_WORLD->grp.peers[i]=&(threads[i]);
tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_INIT);
}
}
- /* the main thread now also runs start_fn */
- /*threads[0].thread_id=NULL; we can't count on this being a pointer*/
- tMPI_Thread_starter((void*)&(threads[0]));
+ /* the main thread now also runs start_fn if we don't want
+ it to return */
+ if (!main_returns)
+ tMPI_Thread_starter((void*)&(threads[0]));
+ else
+ tMPI_Thread_init(&(threads[0]));
}
}
{
int N=0;
tMPI_Get_N(argc, argv, "-nt", &N);
- tMPI_Start_threads(N, argc, argv, NULL, NULL);
+ tMPI_Start_threads(FALSE, N, argc, argv, NULL, NULL);
}
else
{
return TMPI_SUCCESS;
}
-int tMPI_Init_fn(int N, void (*start_function)(void*), void *arg)
+int tMPI_Init_fn(int main_thread_returns, int N,
+ void (*start_function)(void*), void *arg)
{
#ifdef TMPI_TRACE
tMPI_Trace_print("tMPI_Init_fn(%d, %p, %p)", N, start_function, arg);
if (TMPI_COMM_WORLD==0 && N>=1) /* we're the main process */
{
- tMPI_Start_threads(N, 0, 0, start_function, arg);
+ tMPI_Start_threads(main_thread_returns, N, 0, 0, start_function, arg);
}
return TMPI_SUCCESS;
}
if (comm==TMPI_COMM_WORLD)
fprintf(stderr, " on TMPI_COMM_WORLD");
fprintf(stderr,"\n");
- fflush(0);
+ fflush(stdout);
abort();
#else
every thread that is part of the new communicator */
if (*comm_cart)
{
- tMPI_Spinlock_barrier_wait( &( (*comm_cart)->barrier) );
+ tMPI_Barrier_wait( &( (*comm_cart)->barrier) );
}
}
return ret==0;
}
-
+#if 0
+/* use once Vista is minimum required version */
static BOOL CALLBACK InitHandleWrapperFunction(PINIT_ONCE InitOnce,
PVOID Parameter,
PVOID *lpContext)
CRITICAL_SECTION tMPI_Once_cs;
tMPI_Spinlock_t tMPI_Once_cs_lock=TMPI_SPINLOCK_INITIALIZER;
volatile int tMPI_Once_init=0;
-
+#endif
int tMPI_Thread_once(tMPI_Thread_once_t *once_control,
void (*init_routine)(void))
{
#if 0
+ /* use once Vista is minimum required version */
BOOL bStatus;
bStatus = InitOnceExecuteOnce(once_control, InitHandleWrapperFunction,
init_routine, NULL);
t_iatom *iabuf;
int iabuf_nalloc;
+ if (qB == NULL)
+ {
+ qB = qA;
+ }
+
iabuf_nalloc = 0;
iabuf = NULL;
/* Needed for backward compatibility */
#define MAXNODES 256
-void _do_section(int fp,int key,bool bRead,const char *src,int line)
+static void _do_section(t_fileio *fio,int key,bool bRead,const char *src,
+ int line)
{
char buf[STRLEN];
bool bDbg;
- if (gmx_fio_getftp(fp) == efTPA) {
+ if (gmx_fio_getftp(fio) == efTPA) {
if (!bRead) {
- do_string(itemstr[key]);
- bDbg = gmx_fio_getdebug(fp);
- gmx_fio_setdebug(fp,FALSE);
- do_string(comment_str[key]);
- gmx_fio_setdebug(fp,bDbg);
+ gmx_fio_write_string(fio,itemstr[key]);
+ bDbg = gmx_fio_getdebug(fio);
+ gmx_fio_setdebug(fio,FALSE);
+ gmx_fio_write_string(fio,comment_str[key]);
+ gmx_fio_setdebug(fio,bDbg);
}
else {
- if (gmx_fio_getdebug(fp))
+ if (gmx_fio_getdebug(fio))
fprintf(stderr,"Looking for section %s (%s, %d)",
itemstr[key],src,line);
do {
- do_string(buf);
+ gmx_fio_do_string(fio,buf);
} while ((strcasecmp(buf,itemstr[key]) != 0));
if (strcasecmp(buf,itemstr[key]) != 0)
gmx_fatal(FARGS,"\nCould not find section heading %s",itemstr[key]);
- else if (gmx_fio_getdebug(fp))
+ else if (gmx_fio_getdebug(fio))
fprintf(stderr," and found it\n");
}
}
}
-#define do_section(key,bRead) _do_section(fp,key,bRead,__FILE__,__LINE__)
+#define do_section(fio,key,bRead) _do_section(fio,key,bRead,__FILE__,__LINE__)
/**************************************************************
*
* Now the higer level routines that do io of the structures and arrays
*
**************************************************************/
-static void do_pullgrp(t_pullgrp *pgrp,bool bRead, int file_version)
+static void do_pullgrp(t_fileio *fio, t_pullgrp *pgrp, bool bRead,
+ int file_version)
{
bool bDum=TRUE;
int i;
- do_int(pgrp->nat);
+ gmx_fio_do_int(fio,pgrp->nat);
if (bRead)
snew(pgrp->ind,pgrp->nat);
- ndo_int(pgrp->ind,pgrp->nat,bDum);
- do_int(pgrp->nweight);
+ bDum=gmx_fio_ndo_int(fio,pgrp->ind,pgrp->nat);
+ gmx_fio_do_int(fio,pgrp->nweight);
if (bRead)
snew(pgrp->weight,pgrp->nweight);
- ndo_real(pgrp->weight,pgrp->nweight,bDum);
- do_int(pgrp->pbcatom);
- do_rvec(pgrp->vec);
- do_rvec(pgrp->init);
- do_real(pgrp->rate);
- do_real(pgrp->k);
+ bDum=gmx_fio_ndo_real(fio,pgrp->weight,pgrp->nweight);
+ gmx_fio_do_int(fio,pgrp->pbcatom);
+ gmx_fio_do_rvec(fio,pgrp->vec);
+ gmx_fio_do_rvec(fio,pgrp->init);
+ gmx_fio_do_real(fio,pgrp->rate);
+ gmx_fio_do_real(fio,pgrp->k);
if (file_version >= 56) {
- do_real(pgrp->kB);
+ gmx_fio_do_real(fio,pgrp->kB);
} else {
pgrp->kB = pgrp->k;
}
}
-static void do_pull(t_pull *pull,bool bRead, int file_version)
+static void do_pull(t_fileio *fio, t_pull *pull,bool bRead, int file_version)
{
int g;
- do_int(pull->ngrp);
- do_int(pull->eGeom);
- do_ivec(pull->dim);
- do_real(pull->cyl_r1);
- do_real(pull->cyl_r0);
- do_real(pull->constr_tol);
- do_int(pull->nstxout);
- do_int(pull->nstfout);
+ gmx_fio_do_int(fio,pull->ngrp);
+ gmx_fio_do_int(fio,pull->eGeom);
+ gmx_fio_do_ivec(fio,pull->dim);
+ gmx_fio_do_real(fio,pull->cyl_r1);
+ gmx_fio_do_real(fio,pull->cyl_r0);
+ gmx_fio_do_real(fio,pull->constr_tol);
+ gmx_fio_do_int(fio,pull->nstxout);
+ gmx_fio_do_int(fio,pull->nstfout);
if (bRead)
snew(pull->grp,pull->ngrp+1);
for(g=0; g<pull->ngrp+1; g++)
- do_pullgrp(&pull->grp[g],bRead,file_version);
+ do_pullgrp(fio,&pull->grp[g],bRead,file_version);
}
-static void do_rotgrp(t_rotgrp *rotg,bool bRead, int file_version)
+
+static void do_rotgrp(t_fileio *fio, t_rotgrp *rotg,bool bRead, int file_version)
{
bool bDum=TRUE;
int i;
- do_int(rotg->eType);
- do_int(rotg->bMassW);
- do_int(rotg->nat);
+ gmx_fio_do_int(fio,rotg->eType);
+ gmx_fio_do_int(fio,rotg->bMassW);
+ gmx_fio_do_int(fio,rotg->nat);
if (bRead)
snew(rotg->ind,rotg->nat);
- ndo_int(rotg->ind,rotg->nat,bDum);
+ gmx_fio_ndo_int(fio,rotg->ind,rotg->nat);
if (bRead)
snew(rotg->x_ref,rotg->nat);
- ndo_rvec(rotg->x_ref,rotg->nat);
- do_rvec(rotg->vec);
- do_rvec(rotg->pivot);
- do_real(rotg->rate);
- do_real(rotg->k);
- do_real(rotg->slab_dist);
- do_real(rotg->min_gaussian);
- do_real(rotg->eps);
- do_int(rotg->eFittype);
+ gmx_fio_ndo_rvec(fio,rotg->x_ref,rotg->nat);
+ gmx_fio_do_rvec(fio,rotg->vec);
+ gmx_fio_do_rvec(fio,rotg->pivot);
+ gmx_fio_do_real(fio,rotg->rate);
+ gmx_fio_do_real(fio,rotg->k);
+ gmx_fio_do_real(fio,rotg->slab_dist);
+ gmx_fio_do_real(fio,rotg->min_gaussian);
+ gmx_fio_do_real(fio,rotg->eps);
+ gmx_fio_do_int(fio,rotg->eFittype);
}
-static void do_rot(t_rot *rot,bool bRead, int file_version)
+static void do_rot(t_fileio *fio, t_rot *rot,bool bRead, int file_version)
{
int g;
- do_int(rot->ngrp);
- do_int(rot->nstrout);
- do_int(rot->nsttout);
+ gmx_fio_do_int(fio,rot->ngrp);
+ gmx_fio_do_int(fio,rot->nstrout);
+ gmx_fio_do_int(fio,rot->nsttout);
if (bRead)
snew(rot->grp,rot->ngrp);
for(g=0; g<rot->ngrp; g++)
- do_rotgrp(&rot->grp[g],bRead,file_version);
+ do_rotgrp(fio, &rot->grp[g],bRead,file_version);
}
-static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
- real *fudgeQQ)
+
+static void do_inputrec(t_fileio *fio, t_inputrec *ir,bool bRead,
+ int file_version, real *fudgeQQ)
{
int i,j,k,*tmp,idum=0;
bool bDum=TRUE;
if (file_version >= 1) {
/* Basic inputrec stuff */
- do_int(ir->eI);
+ gmx_fio_do_int(fio,ir->eI);
if (file_version >= 62) {
- do_gmx_large_int(ir->nsteps);
+ gmx_fio_do_gmx_large_int(fio, ir->nsteps);
} else {
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
ir->nsteps = idum;
}
if(file_version > 25) {
if (file_version >= 62) {
- do_gmx_large_int(ir->init_step);
+ gmx_fio_do_gmx_large_int(fio, ir->init_step);
} else {
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
ir->init_step = idum;
}
} else {
}
if(file_version >= 58)
- do_int(ir->simulation_part);
+ gmx_fio_do_int(fio,ir->simulation_part);
else
ir->simulation_part=1;
if (file_version >= 67) {
- do_int(ir->nstcalcenergy);
+ gmx_fio_do_int(fio,ir->nstcalcenergy);
} else {
ir->nstcalcenergy = 1;
}
/* The pbc info has been moved out of do_inputrec,
* since we always want it, also without reading the inputrec.
*/
- do_int(ir->ePBC);
+ gmx_fio_do_int(fio,ir->ePBC);
if ((file_version <= 15) && (ir->ePBC == 2))
ir->ePBC = epbcNONE;
if (file_version >= 45) {
- do_int(ir->bPeriodicMols);
+ gmx_fio_do_int(fio,ir->bPeriodicMols);
} else {
if (ir->ePBC == 2) {
ir->ePBC = epbcXYZ;
}
}
}
- do_int(ir->ns_type);
- do_int(ir->nstlist);
- do_int(ir->ndelta);
+ gmx_fio_do_int(fio,ir->ns_type);
+ gmx_fio_do_int(fio,ir->nstlist);
+ gmx_fio_do_int(fio,ir->ndelta);
if (file_version < 41) {
- do_int(idum);
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
+ gmx_fio_do_int(fio,idum);
}
if (file_version >= 45)
- do_real(ir->rtpi);
+ gmx_fio_do_real(fio,ir->rtpi);
else
ir->rtpi = 0.05;
- do_int(ir->nstcomm);
+ gmx_fio_do_int(fio,ir->nstcomm);
if (file_version > 34)
- do_int(ir->comm_mode);
+ gmx_fio_do_int(fio,ir->comm_mode);
else if (ir->nstcomm < 0)
ir->comm_mode = ecmANGULAR;
else
ir->nstcomm = abs(ir->nstcomm);
if(file_version > 25)
- do_int(ir->nstcheckpoint);
+ gmx_fio_do_int(fio,ir->nstcheckpoint);
else
ir->nstcheckpoint=0;
- do_int(ir->nstcgsteep);
+ gmx_fio_do_int(fio,ir->nstcgsteep);
if(file_version>=30)
- do_int(ir->nbfgscorr);
+ gmx_fio_do_int(fio,ir->nbfgscorr);
else if (bRead)
ir->nbfgscorr = 10;
- do_int(ir->nstlog);
- do_int(ir->nstxout);
- do_int(ir->nstvout);
- do_int(ir->nstfout);
- do_int(ir->nstenergy);
- do_int(ir->nstxtcout);
+ gmx_fio_do_int(fio,ir->nstlog);
+ gmx_fio_do_int(fio,ir->nstxout);
+ gmx_fio_do_int(fio,ir->nstvout);
+ gmx_fio_do_int(fio,ir->nstfout);
+ gmx_fio_do_int(fio,ir->nstenergy);
+ gmx_fio_do_int(fio,ir->nstxtcout);
if (file_version >= 59) {
- do_double(ir->init_t);
- do_double(ir->delta_t);
+ gmx_fio_do_double(fio,ir->init_t);
+ gmx_fio_do_double(fio,ir->delta_t);
} else {
- do_real(rdum);
+ gmx_fio_do_real(fio,rdum);
ir->init_t = rdum;
- do_real(rdum);
+ gmx_fio_do_real(fio,rdum);
ir->delta_t = rdum;
}
- do_real(ir->xtcprec);
+ gmx_fio_do_real(fio,ir->xtcprec);
if (file_version < 19) {
- do_int(idum);
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
+ gmx_fio_do_int(fio,idum);
}
if(file_version < 18)
- do_int(idum);
- do_real(ir->rlist);
+ gmx_fio_do_int(fio,idum);
+ gmx_fio_do_real(fio,ir->rlist);
if (file_version >= 67) {
- do_real(ir->rlistlong);
+ gmx_fio_do_real(fio,ir->rlistlong);
}
- do_int(ir->coulombtype);
+ gmx_fio_do_int(fio,ir->coulombtype);
if (file_version < 32 && ir->coulombtype == eelRF)
ir->coulombtype = eelRF_NEC;
- do_real(ir->rcoulomb_switch);
- do_real(ir->rcoulomb);
- do_int(ir->vdwtype);
- do_real(ir->rvdw_switch);
- do_real(ir->rvdw);
+ gmx_fio_do_real(fio,ir->rcoulomb_switch);
+ gmx_fio_do_real(fio,ir->rcoulomb);
+ gmx_fio_do_int(fio,ir->vdwtype);
+ gmx_fio_do_real(fio,ir->rvdw_switch);
+ gmx_fio_do_real(fio,ir->rvdw);
if (file_version < 67) {
ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
}
- do_int(ir->eDispCorr);
- do_real(ir->epsilon_r);
+ gmx_fio_do_int(fio,ir->eDispCorr);
+ gmx_fio_do_real(fio,ir->epsilon_r);
if (file_version >= 37) {
- do_real(ir->epsilon_rf);
+ gmx_fio_do_real(fio,ir->epsilon_rf);
} else {
if (EEL_RF(ir->coulombtype)) {
ir->epsilon_rf = ir->epsilon_r;
}
}
if (file_version >= 29)
- do_real(ir->tabext);
+ gmx_fio_do_real(fio,ir->tabext);
else
ir->tabext=1.0;
if(file_version > 25) {
- do_int(ir->gb_algorithm);
- do_int(ir->nstgbradii);
- do_real(ir->rgbradii);
- do_real(ir->gb_saltconc);
- do_int(ir->implicit_solvent);
+ gmx_fio_do_int(fio,ir->gb_algorithm);
+ gmx_fio_do_int(fio,ir->nstgbradii);
+ gmx_fio_do_real(fio,ir->rgbradii);
+ gmx_fio_do_real(fio,ir->gb_saltconc);
+ gmx_fio_do_int(fio,ir->implicit_solvent);
} else {
ir->gb_algorithm=egbSTILL;
ir->nstgbradii=1;
}
if(file_version>=55)
{
- do_real(ir->gb_epsilon_solvent);
- do_real(ir->gb_obc_alpha);
- do_real(ir->gb_obc_beta);
- do_real(ir->gb_obc_gamma);
+ gmx_fio_do_real(fio,ir->gb_epsilon_solvent);
+ gmx_fio_do_real(fio,ir->gb_obc_alpha);
+ gmx_fio_do_real(fio,ir->gb_obc_beta);
+ gmx_fio_do_real(fio,ir->gb_obc_gamma);
if(file_version>=60)
{
- do_real(ir->gb_dielectric_offset);
- do_int(ir->sa_algorithm);
+ gmx_fio_do_real(fio,ir->gb_dielectric_offset);
+ gmx_fio_do_int(fio,ir->sa_algorithm);
}
else
{
ir->gb_dielectric_offset = 0.09;
ir->sa_algorithm = esaAPPROX;
}
- do_real(ir->sa_surface_tension);
+ gmx_fio_do_real(fio,ir->sa_surface_tension);
}
else
{
}
- do_int(ir->nkx);
- do_int(ir->nky);
- do_int(ir->nkz);
- do_int(ir->pme_order);
- do_real(ir->ewald_rtol);
+ gmx_fio_do_int(fio,ir->nkx);
+ gmx_fio_do_int(fio,ir->nky);
+ gmx_fio_do_int(fio,ir->nkz);
+ gmx_fio_do_int(fio,ir->pme_order);
+ gmx_fio_do_real(fio,ir->ewald_rtol);
if (file_version >=24)
- do_int(ir->ewald_geometry);
+ gmx_fio_do_int(fio,ir->ewald_geometry);
else
ir->ewald_geometry=eewg3D;
if (file_version <=17) {
ir->epsilon_surface=0;
if (file_version==17)
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
}
else
- do_real(ir->epsilon_surface);
+ gmx_fio_do_real(fio,ir->epsilon_surface);
- do_int(ir->bOptFFT);
+ gmx_fio_do_bool(fio,ir->bOptFFT);
- do_int(ir->bContinuation);
- do_int(ir->etc);
+ gmx_fio_do_bool(fio,ir->bContinuation);
+ gmx_fio_do_int(fio,ir->etc);
/* before version 18, ir->etc was a bool (ir->btc),
* but the values 0 and 1 still mean no and
* berendsen temperature coupling, respectively.
*/
if (file_version <= 15)
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
if (file_version <=17) {
- do_int(ir->epct);
+ gmx_fio_do_int(fio,ir->epct);
if (file_version <= 15) {
if (ir->epct == 5)
ir->epct = epctSURFACETENSION;
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
}
ir->epct -= 1;
/* we have removed the NO alternative at the beginning */
ir->epc=epcBERENDSEN;
}
else {
- do_int(ir->epc);
- do_int(ir->epct);
+ gmx_fio_do_int(fio,ir->epc);
+ gmx_fio_do_int(fio,ir->epct);
}
- do_real(ir->tau_p);
+ gmx_fio_do_real(fio,ir->tau_p);
if (file_version <= 15) {
- do_rvec(vdum);
+ gmx_fio_do_rvec(fio,vdum);
clear_mat(ir->ref_p);
for(i=0; i<DIM; i++)
ir->ref_p[i][i] = vdum[i];
} else {
- do_rvec(ir->ref_p[XX]);
- do_rvec(ir->ref_p[YY]);
- do_rvec(ir->ref_p[ZZ]);
+ gmx_fio_do_rvec(fio,ir->ref_p[XX]);
+ gmx_fio_do_rvec(fio,ir->ref_p[YY]);
+ gmx_fio_do_rvec(fio,ir->ref_p[ZZ]);
}
if (file_version <= 15) {
- do_rvec(vdum);
+ gmx_fio_do_rvec(fio,vdum);
clear_mat(ir->compress);
for(i=0; i<DIM; i++)
ir->compress[i][i] = vdum[i];
}
else {
- do_rvec(ir->compress[XX]);
- do_rvec(ir->compress[YY]);
- do_rvec(ir->compress[ZZ]);
+ gmx_fio_do_rvec(fio,ir->compress[XX]);
+ gmx_fio_do_rvec(fio,ir->compress[YY]);
+ gmx_fio_do_rvec(fio,ir->compress[ZZ]);
}
if (file_version >= 47) {
- do_int(ir->refcoord_scaling);
- do_rvec(ir->posres_com);
- do_rvec(ir->posres_comB);
+ gmx_fio_do_int(fio,ir->refcoord_scaling);
+ gmx_fio_do_rvec(fio,ir->posres_com);
+ gmx_fio_do_rvec(fio,ir->posres_comB);
} else {
ir->refcoord_scaling = erscNO;
clear_rvec(ir->posres_com);
clear_rvec(ir->posres_comB);
}
if(file_version > 25)
- do_int(ir->andersen_seed);
+ gmx_fio_do_int(fio,ir->andersen_seed);
else
ir->andersen_seed=0;
if(file_version < 26) {
- do_int(bSimAnn);
- do_real(zerotemptime);
+ gmx_fio_do_bool(fio,bSimAnn);
+ gmx_fio_do_real(fio,zerotemptime);
}
if (file_version < 37)
- do_real(rdum);
+ gmx_fio_do_real(fio,rdum);
- do_real(ir->shake_tol);
+ gmx_fio_do_real(fio,ir->shake_tol);
if (file_version < 54)
- do_real(*fudgeQQ);
- do_int(ir->efep);
+ gmx_fio_do_real(fio,*fudgeQQ);
+ gmx_fio_do_int(fio,ir->efep);
if (file_version <= 14 && ir->efep > efepNO)
ir->efep = efepYES;
if (file_version >= 59) {
- do_double(ir->init_lambda);
- do_double(ir->delta_lambda);
+ gmx_fio_do_double(fio, ir->init_lambda);
+ gmx_fio_do_double(fio, ir->delta_lambda);
} else {
- do_real(rdum);
+ gmx_fio_do_real(fio,rdum);
ir->init_lambda = rdum;
- do_real(rdum);
+ gmx_fio_do_real(fio,rdum);
ir->delta_lambda = rdum;
}
if (file_version >= 64) {
- do_int(ir->n_flambda);
+ gmx_fio_do_int(fio,ir->n_flambda);
if (bRead) {
snew(ir->flambda,ir->n_flambda);
}
- ndo_double(ir->flambda,ir->n_flambda,bDum);
+ bDum=gmx_fio_ndo_double(fio,ir->flambda,ir->n_flambda);
} else {
ir->n_flambda = 0;
ir->flambda = NULL;
}
if (file_version >= 13)
- do_real(ir->sc_alpha);
+ gmx_fio_do_real(fio,ir->sc_alpha);
else
ir->sc_alpha = 0;
if (file_version >= 38)
- do_int(ir->sc_power);
+ gmx_fio_do_int(fio,ir->sc_power);
else
ir->sc_power = 2;
if (file_version >= 15)
- do_real(ir->sc_sigma);
+ gmx_fio_do_real(fio,ir->sc_sigma);
else
ir->sc_sigma = 0.3;
if (file_version >= 64) {
- do_int(ir->nstdhdl);
+ gmx_fio_do_int(fio,ir->nstdhdl);
} else {
ir->nstdhdl = 1;
}
if (file_version >= 57) {
- do_int(ir->eDisre);
+ gmx_fio_do_int(fio,ir->eDisre);
}
- do_int(ir->eDisreWeighting);
+ gmx_fio_do_int(fio,ir->eDisreWeighting);
if (file_version < 22) {
if (ir->eDisreWeighting == 0)
ir->eDisreWeighting = edrwEqual;
else
ir->eDisreWeighting = edrwConservative;
}
- do_int(ir->bDisreMixed);
- do_real(ir->dr_fc);
- do_real(ir->dr_tau);
- do_int(ir->nstdisreout);
+ gmx_fio_do_bool(fio,ir->bDisreMixed);
+ gmx_fio_do_real(fio,ir->dr_fc);
+ gmx_fio_do_real(fio,ir->dr_tau);
+ gmx_fio_do_int(fio,ir->nstdisreout);
if (file_version >= 22) {
- do_real(ir->orires_fc);
- do_real(ir->orires_tau);
- do_int(ir->nstorireout);
+ gmx_fio_do_real(fio,ir->orires_fc);
+ gmx_fio_do_real(fio,ir->orires_tau);
+ gmx_fio_do_int(fio,ir->nstorireout);
} else {
ir->orires_fc = 0;
ir->orires_tau = 0;
ir->nstorireout = 0;
}
if(file_version >= 26) {
- do_real(ir->dihre_fc);
+ gmx_fio_do_real(fio,ir->dihre_fc);
if (file_version < 56) {
- do_real(rdum);
- do_int(idum);
+ gmx_fio_do_real(fio,rdum);
+ gmx_fio_do_int(fio,idum);
}
} else {
ir->dihre_fc=0;
}
- do_real(ir->em_stepsize);
- do_real(ir->em_tol);
+ gmx_fio_do_real(fio,ir->em_stepsize);
+ gmx_fio_do_real(fio,ir->em_tol);
if (file_version >= 22)
- do_int(ir->bShakeSOR);
+ gmx_fio_do_bool(fio,ir->bShakeSOR);
else if (bRead)
ir->bShakeSOR = TRUE;
if (file_version >= 11)
- do_int(ir->niter);
+ gmx_fio_do_int(fio,ir->niter);
else if (bRead) {
ir->niter = 25;
fprintf(stderr,"Note: niter not in run input file, setting it to %d\n",
ir->niter);
}
if (file_version >= 21)
- do_real(ir->fc_stepsize);
+ gmx_fio_do_real(fio,ir->fc_stepsize);
else
ir->fc_stepsize = 0;
- do_int(ir->eConstrAlg);
- do_int(ir->nProjOrder);
- do_real(ir->LincsWarnAngle);
+ gmx_fio_do_int(fio,ir->eConstrAlg);
+ gmx_fio_do_int(fio,ir->nProjOrder);
+ gmx_fio_do_real(fio,ir->LincsWarnAngle);
if (file_version <= 14)
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
if (file_version >=26)
- do_int(ir->nLincsIter);
+ gmx_fio_do_int(fio,ir->nLincsIter);
else if (bRead) {
ir->nLincsIter = 1;
fprintf(stderr,"Note: nLincsIter not in run input file, setting it to %d\n",
ir->nLincsIter);
}
if (file_version < 33)
- do_real(bd_temp);
- do_real(ir->bd_fric);
- do_int(ir->ld_seed);
+ gmx_fio_do_real(fio,bd_temp);
+ gmx_fio_do_real(fio,ir->bd_fric);
+ gmx_fio_do_int(fio,ir->ld_seed);
if (file_version >= 33) {
for(i=0; i<DIM; i++)
- do_rvec(ir->deform[i]);
+ gmx_fio_do_rvec(fio,ir->deform[i]);
} else {
for(i=0; i<DIM; i++)
clear_rvec(ir->deform[i]);
}
if (file_version >= 14)
- do_real(ir->cos_accel);
+ gmx_fio_do_real(fio,ir->cos_accel);
else if (bRead)
ir->cos_accel = 0;
- do_int(ir->userint1);
- do_int(ir->userint2);
- do_int(ir->userint3);
- do_int(ir->userint4);
- do_real(ir->userreal1);
- do_real(ir->userreal2);
- do_real(ir->userreal3);
- do_real(ir->userreal4);
+ gmx_fio_do_int(fio,ir->userint1);
+ gmx_fio_do_int(fio,ir->userint2);
+ gmx_fio_do_int(fio,ir->userint3);
+ gmx_fio_do_int(fio,ir->userint4);
+ gmx_fio_do_real(fio,ir->userreal1);
+ gmx_fio_do_real(fio,ir->userreal2);
+ gmx_fio_do_real(fio,ir->userreal3);
+ gmx_fio_do_real(fio,ir->userreal4);
/* pull stuff */
if (file_version >= 48) {
- do_int(ir->ePull);
+ gmx_fio_do_int(fio,ir->ePull);
if (ir->ePull != epullNO) {
if (bRead)
snew(ir->pull,1);
- do_pull(ir->pull,bRead,file_version);
+ do_pull(fio, ir->pull,bRead,file_version);
}
} else {
ir->ePull = epullNO;
/* Enforced rotation */
if (file_version >= 71) {
- do_int(ir->bRot);
+ gmx_fio_do_int(fio,ir->bRot);
if (ir->bRot == TRUE) {
if (bRead)
snew(ir->rot,1);
- do_rot(ir->rot,bRead,file_version);
+ do_rot(fio, ir->rot,bRead,file_version);
}
} else {
ir->bRot = FALSE;
}
/* grpopts stuff */
- do_int(ir->opts.ngtc);
+ gmx_fio_do_int(fio,ir->opts.ngtc);
if (file_version >= 69) {
- do_int(ir->opts.nhchainlength);
+ gmx_fio_do_int(fio,ir->opts.nhchainlength);
} else {
ir->opts.nhchainlength = 1;
}
- do_int(ir->opts.ngacc);
- do_int(ir->opts.ngfrz);
- do_int(ir->opts.ngener);
+ gmx_fio_do_int(fio,ir->opts.ngacc);
+ gmx_fio_do_int(fio,ir->opts.ngfrz);
+ gmx_fio_do_int(fio,ir->opts.ngener);
if (bRead) {
snew(ir->opts.nrdf, ir->opts.ngtc);
if (ir->opts.ngtc > 0) {
if (bRead && file_version<13) {
snew(tmp,ir->opts.ngtc);
- ndo_int (tmp, ir->opts.ngtc,bDum);
+ bDum=gmx_fio_ndo_int(fio,tmp, ir->opts.ngtc);
for(i=0; i<ir->opts.ngtc; i++)
ir->opts.nrdf[i] = tmp[i];
sfree(tmp);
} else {
- ndo_real(ir->opts.nrdf, ir->opts.ngtc,bDum);
+ bDum=gmx_fio_ndo_real(fio,ir->opts.nrdf, ir->opts.ngtc);
}
- ndo_real(ir->opts.ref_t,ir->opts.ngtc,bDum);
- ndo_real(ir->opts.tau_t,ir->opts.ngtc,bDum);
+ bDum=gmx_fio_ndo_real(fio,ir->opts.ref_t,ir->opts.ngtc);
+ bDum=gmx_fio_ndo_real(fio,ir->opts.tau_t,ir->opts.ngtc);
if (file_version<33 && ir->eI==eiBD) {
for(i=0; i<ir->opts.ngtc; i++)
ir->opts.tau_t[i] = bd_temp;
}
}
if (ir->opts.ngfrz > 0)
- ndo_ivec(ir->opts.nFreeze,ir->opts.ngfrz,bDum);
+ bDum=gmx_fio_ndo_ivec(fio,ir->opts.nFreeze,ir->opts.ngfrz);
if (ir->opts.ngacc > 0)
- ndo_rvec(ir->opts.acc,ir->opts.ngacc);
+ gmx_fio_ndo_rvec(fio,ir->opts.acc,ir->opts.ngacc);
if (file_version >= 12)
- ndo_int(ir->opts.egp_flags,ir->opts.ngener*ir->opts.ngener,bDum);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.egp_flags,
+ ir->opts.ngener*ir->opts.ngener);
if(bRead && file_version < 26) {
for(i=0;i<ir->opts.ngtc;i++) {
} else {
/* file version 26 or later */
/* First read the lists with annealing and npoints for each group */
- ndo_int(ir->opts.annealing,ir->opts.ngtc,bDum);
- ndo_int(ir->opts.anneal_npoints,ir->opts.ngtc,bDum);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.annealing,ir->opts.ngtc);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.anneal_npoints,ir->opts.ngtc);
for(j=0;j<(ir->opts.ngtc);j++) {
k=ir->opts.anneal_npoints[j];
if(bRead) {
snew(ir->opts.anneal_time[j],k);
snew(ir->opts.anneal_temp[j],k);
}
- ndo_real(ir->opts.anneal_time[j],k,bDum);
- ndo_real(ir->opts.anneal_temp[j],k,bDum);
+ bDum=gmx_fio_ndo_real(fio,ir->opts.anneal_time[j],k);
+ bDum=gmx_fio_ndo_real(fio,ir->opts.anneal_temp[j],k);
}
}
/* Walls */
if (file_version >= 45) {
- do_int(ir->nwall);
- do_int(ir->wall_type);
+ gmx_fio_do_int(fio,ir->nwall);
+ gmx_fio_do_int(fio,ir->wall_type);
if (file_version >= 50)
- do_real(ir->wall_r_linpot);
+ gmx_fio_do_real(fio,ir->wall_r_linpot);
else
ir->wall_r_linpot = -1;
- do_int(ir->wall_atomtype[0]);
- do_int(ir->wall_atomtype[1]);
- do_real(ir->wall_density[0]);
- do_real(ir->wall_density[1]);
- do_real(ir->wall_ewald_zfac);
+ gmx_fio_do_int(fio,ir->wall_atomtype[0]);
+ gmx_fio_do_int(fio,ir->wall_atomtype[1]);
+ gmx_fio_do_real(fio,ir->wall_density[0]);
+ gmx_fio_do_real(fio,ir->wall_density[1]);
+ gmx_fio_do_real(fio,ir->wall_ewald_zfac);
} else {
ir->nwall = 0;
ir->wall_type = 0;
}
/* Cosine stuff for electric fields */
for(j=0; (j<DIM); j++) {
- do_int (ir->ex[j].n);
- do_int (ir->et[j].n);
+ gmx_fio_do_int(fio,ir->ex[j].n);
+ gmx_fio_do_int(fio,ir->et[j].n);
if (bRead) {
snew(ir->ex[j].a, ir->ex[j].n);
snew(ir->ex[j].phi,ir->ex[j].n);
snew(ir->et[j].a, ir->et[j].n);
snew(ir->et[j].phi,ir->et[j].n);
}
- ndo_real(ir->ex[j].a, ir->ex[j].n,bDum);
- ndo_real(ir->ex[j].phi,ir->ex[j].n,bDum);
- ndo_real(ir->et[j].a, ir->et[j].n,bDum);
- ndo_real(ir->et[j].phi,ir->et[j].n,bDum);
+ bDum=gmx_fio_ndo_real(fio,ir->ex[j].a, ir->ex[j].n);
+ bDum=gmx_fio_ndo_real(fio,ir->ex[j].phi,ir->ex[j].n);
+ bDum=gmx_fio_ndo_real(fio,ir->et[j].a, ir->et[j].n);
+ bDum=gmx_fio_ndo_real(fio,ir->et[j].phi,ir->et[j].n);
}
/* QMMM stuff */
if(file_version>=39){
- do_int(ir->bQMMM);
- do_int(ir->QMMMscheme);
- do_real(ir->scalefactor);
- do_int(ir->opts.ngQM);
+ gmx_fio_do_bool(fio,ir->bQMMM);
+ gmx_fio_do_int(fio,ir->QMMMscheme);
+ gmx_fio_do_real(fio,ir->scalefactor);
+ gmx_fio_do_int(fio,ir->opts.ngQM);
if (bRead) {
snew(ir->opts.QMmethod, ir->opts.ngQM);
snew(ir->opts.QMbasis, ir->opts.ngQM);
snew(ir->opts.bTS, ir->opts.ngQM);
}
if (ir->opts.ngQM > 0) {
- ndo_int(ir->opts.QMmethod,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.QMbasis,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.QMcharge,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.QMmult,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.bSH,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.CASorbitals,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.CASelectrons,ir->opts.ngQM,bDum);
- ndo_real(ir->opts.SAon,ir->opts.ngQM,bDum);
- ndo_real(ir->opts.SAoff,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.SAsteps,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.bOPT,ir->opts.ngQM,bDum);
- ndo_int(ir->opts.bTS,ir->opts.ngQM,bDum);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.QMmethod,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.QMbasis,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.QMcharge,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.QMmult,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_bool(fio,ir->opts.bSH,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.CASorbitals,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.CASelectrons,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_real(fio,ir->opts.SAon,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_real(fio,ir->opts.SAoff,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_int(fio,ir->opts.SAsteps,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_bool(fio,ir->opts.bOPT,ir->opts.ngQM);
+ bDum=gmx_fio_ndo_bool(fio,ir->opts.bTS,ir->opts.ngQM);
}
/* end of QMMM stuff */
}
}
-static void do_harm(t_iparams *iparams,bool bRead)
+static void do_harm(t_fileio *fio, t_iparams *iparams,bool bRead)
{
- do_real(iparams->harmonic.rA);
- do_real(iparams->harmonic.krA);
- do_real(iparams->harmonic.rB);
- do_real(iparams->harmonic.krB);
+ gmx_fio_do_real(fio,iparams->harmonic.rA);
+ gmx_fio_do_real(fio,iparams->harmonic.krA);
+ gmx_fio_do_real(fio,iparams->harmonic.rB);
+ gmx_fio_do_real(fio,iparams->harmonic.krB);
}
-void do_iparams(t_functype ftype,t_iparams *iparams,bool bRead, int file_version)
+void do_iparams(t_fileio *fio, t_functype ftype,t_iparams *iparams,
+ bool bRead, int file_version)
{
int i;
bool bDum;
real rdum;
if (!bRead)
- set_comment(interaction_function[ftype].name);
+ gmx_fio_set_comment(fio, interaction_function[ftype].name);
switch (ftype) {
case F_ANGLES:
case F_G96ANGLES:
case F_G96BONDS:
case F_HARMONIC:
case F_IDIHS:
- do_harm(iparams,bRead);
+ do_harm(fio, iparams,bRead);
if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && bRead) {
/* Correct incorrect storage of parameters */
iparams->pdihs.phiB = iparams->pdihs.phiA;
}
break;
case F_FENEBONDS:
- do_real(iparams->fene.bm);
- do_real(iparams->fene.kb);
+ gmx_fio_do_real(fio,iparams->fene.bm);
+ gmx_fio_do_real(fio,iparams->fene.kb);
break;
case F_RESTRBONDS:
- do_real(iparams->restraint.lowA);
- do_real(iparams->restraint.up1A);
- do_real(iparams->restraint.up2A);
- do_real(iparams->restraint.kA);
- do_real(iparams->restraint.lowB);
- do_real(iparams->restraint.up1B);
- do_real(iparams->restraint.up2B);
- do_real(iparams->restraint.kB);
+ gmx_fio_do_real(fio,iparams->restraint.lowA);
+ gmx_fio_do_real(fio,iparams->restraint.up1A);
+ gmx_fio_do_real(fio,iparams->restraint.up2A);
+ gmx_fio_do_real(fio,iparams->restraint.kA);
+ gmx_fio_do_real(fio,iparams->restraint.lowB);
+ gmx_fio_do_real(fio,iparams->restraint.up1B);
+ gmx_fio_do_real(fio,iparams->restraint.up2B);
+ gmx_fio_do_real(fio,iparams->restraint.kB);
break;
case F_TABBONDS:
case F_TABBONDSNC:
case F_TABANGLES:
case F_TABDIHS:
- do_real(iparams->tab.kA);
- do_int (iparams->tab.table);
- do_real(iparams->tab.kB);
+ gmx_fio_do_real(fio,iparams->tab.kA);
+ gmx_fio_do_int(fio,iparams->tab.table);
+ gmx_fio_do_real(fio,iparams->tab.kB);
break;
case F_CROSS_BOND_BONDS:
- do_real(iparams->cross_bb.r1e);
- do_real(iparams->cross_bb.r2e);
- do_real(iparams->cross_bb.krr);
+ gmx_fio_do_real(fio,iparams->cross_bb.r1e);
+ gmx_fio_do_real(fio,iparams->cross_bb.r2e);
+ gmx_fio_do_real(fio,iparams->cross_bb.krr);
break;
case F_CROSS_BOND_ANGLES:
- do_real(iparams->cross_ba.r1e);
- do_real(iparams->cross_ba.r2e);
- do_real(iparams->cross_ba.r3e);
- do_real(iparams->cross_ba.krt);
+ gmx_fio_do_real(fio,iparams->cross_ba.r1e);
+ gmx_fio_do_real(fio,iparams->cross_ba.r2e);
+ gmx_fio_do_real(fio,iparams->cross_ba.r3e);
+ gmx_fio_do_real(fio,iparams->cross_ba.krt);
break;
case F_UREY_BRADLEY:
- do_real(iparams->u_b.theta);
- do_real(iparams->u_b.ktheta);
- do_real(iparams->u_b.r13);
- do_real(iparams->u_b.kUB);
+ gmx_fio_do_real(fio,iparams->u_b.theta);
+ gmx_fio_do_real(fio,iparams->u_b.ktheta);
+ gmx_fio_do_real(fio,iparams->u_b.r13);
+ gmx_fio_do_real(fio,iparams->u_b.kUB);
break;
case F_QUARTIC_ANGLES:
- do_real(iparams->qangle.theta);
- ndo_real(iparams->qangle.c,5,bDum);
+ gmx_fio_do_real(fio,iparams->qangle.theta);
+ bDum=gmx_fio_ndo_real(fio,iparams->qangle.c,5);
break;
case F_BHAM:
- do_real(iparams->bham.a);
- do_real(iparams->bham.b);
- do_real(iparams->bham.c);
+ gmx_fio_do_real(fio,iparams->bham.a);
+ gmx_fio_do_real(fio,iparams->bham.b);
+ gmx_fio_do_real(fio,iparams->bham.c);
break;
case F_MORSE:
- do_real(iparams->morse.b0);
- do_real(iparams->morse.cb);
- do_real(iparams->morse.beta);
+ gmx_fio_do_real(fio,iparams->morse.b0);
+ gmx_fio_do_real(fio,iparams->morse.cb);
+ gmx_fio_do_real(fio,iparams->morse.beta);
break;
case F_CUBICBONDS:
- do_real(iparams->cubic.b0);
- do_real(iparams->cubic.kb);
- do_real(iparams->cubic.kcub);
+ gmx_fio_do_real(fio,iparams->cubic.b0);
+ gmx_fio_do_real(fio,iparams->cubic.kb);
+ gmx_fio_do_real(fio,iparams->cubic.kcub);
break;
case F_CONNBONDS:
break;
case F_POLARIZATION:
- do_real(iparams->polarize.alpha);
+ gmx_fio_do_real(fio,iparams->polarize.alpha);
break;
case F_WATER_POL:
if (file_version < 31)
gmx_fatal(FARGS,"Old tpr files with water_polarization not supported. Make a new.");
- do_real(iparams->wpol.al_x);
- do_real(iparams->wpol.al_y);
- do_real(iparams->wpol.al_z);
- do_real(iparams->wpol.rOH);
- do_real(iparams->wpol.rHH);
- do_real(iparams->wpol.rOD);
+ gmx_fio_do_real(fio,iparams->wpol.al_x);
+ gmx_fio_do_real(fio,iparams->wpol.al_y);
+ gmx_fio_do_real(fio,iparams->wpol.al_z);
+ gmx_fio_do_real(fio,iparams->wpol.rOH);
+ gmx_fio_do_real(fio,iparams->wpol.rHH);
+ gmx_fio_do_real(fio,iparams->wpol.rOD);
break;
case F_THOLE_POL:
- do_real(iparams->thole.a);
- do_real(iparams->thole.alpha1);
- do_real(iparams->thole.alpha2);
- do_real(iparams->thole.rfac);
+ gmx_fio_do_real(fio,iparams->thole.a);
+ gmx_fio_do_real(fio,iparams->thole.alpha1);
+ gmx_fio_do_real(fio,iparams->thole.alpha2);
+ gmx_fio_do_real(fio,iparams->thole.rfac);
break;
case F_LJ:
- do_real(iparams->lj.c6);
- do_real(iparams->lj.c12);
+ gmx_fio_do_real(fio,iparams->lj.c6);
+ gmx_fio_do_real(fio,iparams->lj.c12);
break;
case F_LJ14:
- do_real(iparams->lj14.c6A);
- do_real(iparams->lj14.c12A);
- do_real(iparams->lj14.c6B);
- do_real(iparams->lj14.c12B);
+ gmx_fio_do_real(fio,iparams->lj14.c6A);
+ gmx_fio_do_real(fio,iparams->lj14.c12A);
+ gmx_fio_do_real(fio,iparams->lj14.c6B);
+ gmx_fio_do_real(fio,iparams->lj14.c12B);
break;
case F_LJC14_Q:
- do_real(iparams->ljc14.fqq);
- do_real(iparams->ljc14.qi);
- do_real(iparams->ljc14.qj);
- do_real(iparams->ljc14.c6);
- do_real(iparams->ljc14.c12);
+ gmx_fio_do_real(fio,iparams->ljc14.fqq);
+ gmx_fio_do_real(fio,iparams->ljc14.qi);
+ gmx_fio_do_real(fio,iparams->ljc14.qj);
+ gmx_fio_do_real(fio,iparams->ljc14.c6);
+ gmx_fio_do_real(fio,iparams->ljc14.c12);
break;
case F_LJC_PAIRS_NB:
- do_real(iparams->ljcnb.qi);
- do_real(iparams->ljcnb.qj);
- do_real(iparams->ljcnb.c6);
- do_real(iparams->ljcnb.c12);
+ gmx_fio_do_real(fio,iparams->ljcnb.qi);
+ gmx_fio_do_real(fio,iparams->ljcnb.qj);
+ gmx_fio_do_real(fio,iparams->ljcnb.c6);
+ gmx_fio_do_real(fio,iparams->ljcnb.c12);
break;
case F_PDIHS:
case F_PIDIHS:
case F_ANGRES:
case F_ANGRESZ:
- do_real(iparams->pdihs.phiA);
- do_real(iparams->pdihs.cpA);
+ gmx_fio_do_real(fio,iparams->pdihs.phiA);
+ gmx_fio_do_real(fio,iparams->pdihs.cpA);
if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && file_version < 42) {
/* Read the incorrectly stored multiplicity */
- do_real(iparams->harmonic.rB);
- do_real(iparams->harmonic.krB);
+ gmx_fio_do_real(fio,iparams->harmonic.rB);
+ gmx_fio_do_real(fio,iparams->harmonic.krB);
iparams->pdihs.phiB = iparams->pdihs.phiA;
iparams->pdihs.cpB = iparams->pdihs.cpA;
} else {
- do_real(iparams->pdihs.phiB);
- do_real(iparams->pdihs.cpB);
- do_int (iparams->pdihs.mult);
+ gmx_fio_do_real(fio,iparams->pdihs.phiB);
+ gmx_fio_do_real(fio,iparams->pdihs.cpB);
+ gmx_fio_do_int(fio,iparams->pdihs.mult);
}
break;
case F_DISRES:
- do_int (iparams->disres.label);
- do_int (iparams->disres.type);
- do_real(iparams->disres.low);
- do_real(iparams->disres.up1);
- do_real(iparams->disres.up2);
- do_real(iparams->disres.kfac);
+ gmx_fio_do_int(fio,iparams->disres.label);
+ gmx_fio_do_int(fio,iparams->disres.type);
+ gmx_fio_do_real(fio,iparams->disres.low);
+ gmx_fio_do_real(fio,iparams->disres.up1);
+ gmx_fio_do_real(fio,iparams->disres.up2);
+ gmx_fio_do_real(fio,iparams->disres.kfac);
break;
case F_ORIRES:
- do_int (iparams->orires.ex);
- do_int (iparams->orires.label);
- do_int (iparams->orires.power);
- do_real(iparams->orires.c);
- do_real(iparams->orires.obs);
- do_real(iparams->orires.kfac);
+ gmx_fio_do_int(fio,iparams->orires.ex);
+ gmx_fio_do_int(fio,iparams->orires.label);
+ gmx_fio_do_int(fio,iparams->orires.power);
+ gmx_fio_do_real(fio,iparams->orires.c);
+ gmx_fio_do_real(fio,iparams->orires.obs);
+ gmx_fio_do_real(fio,iparams->orires.kfac);
break;
case F_DIHRES:
- do_int (iparams->dihres.power);
- do_int (iparams->dihres.label);
- do_real(iparams->dihres.phi);
- do_real(iparams->dihres.dphi);
- do_real(iparams->dihres.kfac);
+ gmx_fio_do_int(fio,iparams->dihres.power);
+ gmx_fio_do_int(fio,iparams->dihres.label);
+ gmx_fio_do_real(fio,iparams->dihres.phi);
+ gmx_fio_do_real(fio,iparams->dihres.dphi);
+ gmx_fio_do_real(fio,iparams->dihres.kfac);
break;
case F_POSRES:
- do_rvec(iparams->posres.pos0A);
- do_rvec(iparams->posres.fcA);
+ gmx_fio_do_rvec(fio,iparams->posres.pos0A);
+ gmx_fio_do_rvec(fio,iparams->posres.fcA);
if (bRead && file_version < 27) {
copy_rvec(iparams->posres.pos0A,iparams->posres.pos0B);
copy_rvec(iparams->posres.fcA,iparams->posres.fcB);
} else {
- do_rvec(iparams->posres.pos0B);
- do_rvec(iparams->posres.fcB);
+ gmx_fio_do_rvec(fio,iparams->posres.pos0B);
+ gmx_fio_do_rvec(fio,iparams->posres.fcB);
}
break;
case F_RBDIHS:
- ndo_real(iparams->rbdihs.rbcA,NR_RBDIHS,bDum);
+ bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcA,NR_RBDIHS);
if(file_version>=25)
- ndo_real(iparams->rbdihs.rbcB,NR_RBDIHS,bDum);
+ bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcB,NR_RBDIHS);
break;
case F_FOURDIHS:
/* Fourier dihedrals are internally represented
* as Ryckaert-Bellemans since those are faster to compute.
*/
- ndo_real(iparams->rbdihs.rbcA, NR_RBDIHS, bDum);
- ndo_real(iparams->rbdihs.rbcB, NR_RBDIHS, bDum);
+ bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcA, NR_RBDIHS);
+ bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcB, NR_RBDIHS);
break;
case F_CONSTR:
case F_CONSTRNC:
- do_real(iparams->constr.dA);
- do_real(iparams->constr.dB);
+ gmx_fio_do_real(fio,iparams->constr.dA);
+ gmx_fio_do_real(fio,iparams->constr.dB);
break;
case F_SETTLE:
- do_real(iparams->settle.doh);
- do_real(iparams->settle.dhh);
+ gmx_fio_do_real(fio,iparams->settle.doh);
+ gmx_fio_do_real(fio,iparams->settle.dhh);
break;
case F_VSITE2:
- do_real(iparams->vsite.a);
+ gmx_fio_do_real(fio,iparams->vsite.a);
break;
case F_VSITE3:
case F_VSITE3FD:
case F_VSITE3FAD:
- do_real(iparams->vsite.a);
- do_real(iparams->vsite.b);
+ gmx_fio_do_real(fio,iparams->vsite.a);
+ gmx_fio_do_real(fio,iparams->vsite.b);
break;
case F_VSITE3OUT:
case F_VSITE4FD:
case F_VSITE4FDN:
- do_real(iparams->vsite.a);
- do_real(iparams->vsite.b);
- do_real(iparams->vsite.c);
+ gmx_fio_do_real(fio,iparams->vsite.a);
+ gmx_fio_do_real(fio,iparams->vsite.b);
+ gmx_fio_do_real(fio,iparams->vsite.c);
break;
case F_VSITEN:
- do_int (iparams->vsiten.n);
- do_real(iparams->vsiten.a);
+ gmx_fio_do_int(fio,iparams->vsiten.n);
+ gmx_fio_do_real(fio,iparams->vsiten.a);
break;
case F_GB12:
case F_GB13:
/* We got rid of some parameters in version 68 */
if(bRead && file_version<68)
{
- do_real(rdum);
- do_real(rdum);
- do_real(rdum);
- do_real(rdum);
- }
- do_real(iparams->gb.sar);
- do_real(iparams->gb.st);
- do_real(iparams->gb.pi);
- do_real(iparams->gb.gbr);
- do_real(iparams->gb.bmlt);
+ gmx_fio_do_real(fio,rdum);
+ gmx_fio_do_real(fio,rdum);
+ gmx_fio_do_real(fio,rdum);
+ gmx_fio_do_real(fio,rdum);
+ }
+ gmx_fio_do_real(fio,iparams->gb.sar);
+ gmx_fio_do_real(fio,iparams->gb.st);
+ gmx_fio_do_real(fio,iparams->gb.pi);
+ gmx_fio_do_real(fio,iparams->gb.gbr);
+ gmx_fio_do_real(fio,iparams->gb.bmlt);
break;
case F_CMAP:
- do_int(iparams->cmap.cmapA);
- do_int(iparams->cmap.cmapB);
+ gmx_fio_do_int(fio,iparams->cmap.cmapA);
+ gmx_fio_do_int(fio,iparams->cmap.cmapB);
break;
default:
gmx_fatal(FARGS,"unknown function type %d (%s) in %s line %d",
ftype,interaction_function[ftype].name,__FILE__,__LINE__);
}
if (!bRead)
- unset_comment();
+ gmx_fio_unset_comment(fio);
}
-static void do_ilist(t_ilist *ilist,bool bRead,int file_version,
+static void do_ilist(t_fileio *fio, t_ilist *ilist,bool bRead,int file_version,
int ftype)
{
int i,k,idum;
bool bDum=TRUE;
if (!bRead) {
- set_comment(interaction_function[ftype].name);
+ gmx_fio_set_comment(fio, interaction_function[ftype].name);
}
if (file_version < 44) {
for(i=0; i<MAXNODES; i++)
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
}
- do_int (ilist->nr);
+ gmx_fio_do_int(fio,ilist->nr);
if (bRead)
snew(ilist->iatoms,ilist->nr);
- ndo_int(ilist->iatoms,ilist->nr,bDum);
+ bDum=gmx_fio_ndo_int(fio,ilist->iatoms,ilist->nr);
if (!bRead)
- unset_comment();
+ gmx_fio_unset_comment(fio);
}
-static void do_ffparams(gmx_ffparams_t *ffparams,
+static void do_ffparams(t_fileio *fio, gmx_ffparams_t *ffparams,
bool bRead, int file_version)
{
int idum,i,j,k;
bool bDum=TRUE;
- do_int(ffparams->atnr);
+ gmx_fio_do_int(fio,ffparams->atnr);
if (file_version < 57) {
- do_int(idum);
+ gmx_fio_do_int(fio,idum);
}
- do_int(ffparams->ntypes);
+ gmx_fio_do_int(fio,ffparams->ntypes);
if (bRead && debug)
fprintf(debug,"ffparams->atnr = %d, ntypes = %d\n",
ffparams->atnr,ffparams->ntypes);
snew(ffparams->iparams,ffparams->ntypes);
}
/* Read/write all the function types */
- ndo_int(ffparams->functype,ffparams->ntypes,bDum);
+ bDum=gmx_fio_ndo_int(fio,ffparams->functype,ffparams->ntypes);
if (bRead && debug)
pr_ivec(debug,0,"functype",ffparams->functype,ffparams->ntypes,TRUE);
if (file_version >= 66) {
- do_double(ffparams->reppow);
+ gmx_fio_do_double(fio,ffparams->reppow);
} else {
ffparams->reppow = 12.0;
}
if (file_version >= 57) {
- do_real(ffparams->fudgeQQ);
+ gmx_fio_do_real(fio,ffparams->fudgeQQ);
}
/* Check whether all these function types are supported by the code.
}
}
- do_iparams(ffparams->functype[i],&ffparams->iparams[i],bRead,file_version);
+ do_iparams(fio, ffparams->functype[i],&ffparams->iparams[i],bRead,
+ file_version);
if (bRead && debug)
pr_iparams(debug,ffparams->functype[i],&ffparams->iparams[i]);
}
}
-static void do_ilists(t_ilist *ilist,bool bRead, int file_version)
+static void do_ilists(t_fileio *fio, t_ilist *ilist,bool bRead,
+ int file_version)
{
int i,j,k,renum[F_NRE];
bool bDum=TRUE,bClear;
ilist[j].nr = 0;
ilist[j].iatoms = NULL;
} else {
- do_ilist(&ilist[j],bRead,file_version,j);
+ do_ilist(fio, &ilist[j],bRead,file_version,j);
}
/*
if (bRead && gmx_debug_at)
}
}
-static void do_idef(gmx_ffparams_t *ffparams,gmx_moltype_t *molt,
+static void do_idef(t_fileio *fio, gmx_ffparams_t *ffparams,gmx_moltype_t *molt,
bool bRead, int file_version)
{
- do_ffparams(ffparams,bRead,file_version);
+ do_ffparams(fio, ffparams,bRead,file_version);
if (file_version >= 54) {
- do_real(ffparams->fudgeQQ);
+ gmx_fio_do_real(fio,ffparams->fudgeQQ);
}
- do_ilists(molt->ilist,bRead,file_version);
+ do_ilists(fio, molt->ilist,bRead,file_version);
}
-static void do_block(t_block *block,bool bRead,int file_version)
+static void do_block(t_fileio *fio, t_block *block,bool bRead,int file_version)
{
int i,idum,dum_nra,*dum_a;
bool bDum=TRUE;
if (file_version < 44)
for(i=0; i<MAXNODES; i++)
- do_int(idum);
- do_int (block->nr);
+ gmx_fio_do_int(fio,idum);
+ gmx_fio_do_int(fio,block->nr);
if (file_version < 51)
- do_int (dum_nra);
+ gmx_fio_do_int(fio,dum_nra);
if (bRead) {
block->nalloc_index = block->nr+1;
snew(block->index,block->nalloc_index);
}
- ndo_int(block->index,block->nr+1,bDum);
+ bDum=gmx_fio_ndo_int(fio,block->index,block->nr+1);
if (file_version < 51 && dum_nra > 0) {
snew(dum_a,dum_nra);
- ndo_int(dum_a,dum_nra,bDum);
+ bDum=gmx_fio_ndo_int(fio,dum_a,dum_nra);
sfree(dum_a);
}
}
-static void do_blocka(t_blocka *block,bool bRead,int file_version)
+static void do_blocka(t_fileio *fio, t_blocka *block,bool bRead,
+ int file_version)
{
int i,idum;
bool bDum=TRUE;
if (file_version < 44)
for(i=0; i<MAXNODES; i++)
- do_int(idum);
- do_int (block->nr);
- do_int (block->nra);
+ gmx_fio_do_int(fio,idum);
+ gmx_fio_do_int(fio,block->nr);
+ gmx_fio_do_int(fio,block->nra);
if (bRead) {
block->nalloc_index = block->nr+1;
snew(block->index,block->nalloc_index);
block->nalloc_a = block->nra;
snew(block->a,block->nalloc_a);
}
- ndo_int(block->index,block->nr+1,bDum);
- ndo_int(block->a,block->nra,bDum);
+ bDum=gmx_fio_ndo_int(fio,block->index,block->nr+1);
+ bDum=gmx_fio_ndo_int(fio,block->a,block->nra);
}
-static void do_atom(t_atom *atom,int ngrp,bool bRead, int file_version,
- gmx_groups_t *groups,int atnr)
+static void do_atom(t_fileio *fio, t_atom *atom,int ngrp,bool bRead,
+ int file_version, gmx_groups_t *groups,int atnr)
{
int i,myngrp;
- do_real (atom->m);
- do_real (atom->q);
- do_real (atom->mB);
- do_real (atom->qB);
- do_ushort(atom->type);
- do_ushort(atom->typeB);
- do_int (atom->ptype);
- do_int (atom->resind);
+ gmx_fio_do_real(fio,atom->m);
+ gmx_fio_do_real(fio,atom->q);
+ gmx_fio_do_real(fio,atom->mB);
+ gmx_fio_do_real(fio,atom->qB);
+ gmx_fio_do_ushort(fio, atom->type);
+ gmx_fio_do_ushort(fio, atom->typeB);
+ gmx_fio_do_int(fio,atom->ptype);
+ gmx_fio_do_int(fio,atom->resind);
if (file_version >= 52)
- do_int(atom->atomnumber);
+ gmx_fio_do_int(fio,atom->atomnumber);
else if (bRead)
atom->atomnumber = NOTSET;
if (file_version < 23)
if (file_version < 57) {
unsigned char uchar[egcNR];
- do_nuchar(uchar,myngrp);
+ gmx_fio_ndo_uchar(fio,uchar,myngrp);
for(i=myngrp; (i<ngrp); i++) {
uchar[i] = 0;
}
}
}
-static void do_grps(int ngrp,t_grps grps[],bool bRead, int file_version)
+static void do_grps(t_fileio *fio, int ngrp,t_grps grps[],bool bRead,
+ int file_version)
{
int i,j,myngrp;
bool bDum=TRUE;
for(j=0; (j<ngrp); j++) {
if (j<myngrp) {
- do_int (grps[j].nr);
+ gmx_fio_do_int(fio,grps[j].nr);
if (bRead)
snew(grps[j].nm_ind,grps[j].nr);
- ndo_int(grps[j].nm_ind,grps[j].nr,bDum);
+ bDum=gmx_fio_ndo_int(fio,grps[j].nm_ind,grps[j].nr);
}
else {
grps[j].nr = 1;
}
}
-static void do_symstr(char ***nm,bool bRead,t_symtab *symtab)
+static void do_symstr(t_fileio *fio, char ***nm,bool bRead,t_symtab *symtab)
{
int ls;
if (bRead) {
- do_int(ls);
+ gmx_fio_do_int(fio,ls);
*nm = get_symtab_handle(symtab,ls);
}
else {
ls = lookup_symtab(symtab,*nm);
- do_int(ls);
+ gmx_fio_do_int(fio,ls);
}
}
-static void do_strstr(int nstr,char ***nm,bool bRead,t_symtab *symtab)
+static void do_strstr(t_fileio *fio, int nstr,char ***nm,bool bRead,
+ t_symtab *symtab)
{
int j;
for (j=0; (j<nstr); j++)
- do_symstr(&(nm[j]),bRead,symtab);
+ do_symstr(fio, &(nm[j]),bRead,symtab);
}
-static void do_resinfo(int n,t_resinfo *ri,bool bRead,t_symtab *symtab,
- int file_version)
+static void do_resinfo(t_fileio *fio, int n,t_resinfo *ri,bool bRead,
+ t_symtab *symtab, int file_version)
{
int j;
for (j=0; (j<n); j++) {
- do_symstr(&(ri[j].name),bRead,symtab);
+ do_symstr(fio, &(ri[j].name),bRead,symtab);
if (file_version >= 63) {
- do_int (ri[j].nr);
- do_uchar(ri[j].ic);
+ gmx_fio_do_int(fio,ri[j].nr);
+ gmx_fio_do_uchar(fio, ri[j].ic);
} else {
ri[j].nr = j + 1;
ri[j].ic = ' ';
}
}
-static void do_atoms(t_atoms *atoms,bool bRead,t_symtab *symtab,
+static void do_atoms(t_fileio *fio, t_atoms *atoms,bool bRead,t_symtab *symtab,
int file_version,
gmx_groups_t *groups)
{
int i;
- do_int(atoms->nr);
- do_int(atoms->nres);
+ gmx_fio_do_int(fio,atoms->nr);
+ gmx_fio_do_int(fio,atoms->nres);
if (file_version < 57) {
- do_int(groups->ngrpname);
+ gmx_fio_do_int(fio,groups->ngrpname);
for(i=0; i<egcNR; i++) {
groups->ngrpnr[i] = atoms->nr;
snew(groups->grpnr[i],groups->ngrpnr[i]);
atoms->pdbinfo = NULL;
}
for(i=0; (i<atoms->nr); i++) {
- do_atom(&atoms->atom[i],egcNR,bRead, file_version,groups,i);
+ do_atom(fio, &atoms->atom[i],egcNR,bRead, file_version,groups,i);
}
- do_strstr(atoms->nr,atoms->atomname,bRead,symtab);
+ do_strstr(fio, atoms->nr,atoms->atomname,bRead,symtab);
if (bRead && (file_version <= 20)) {
for(i=0; i<atoms->nr; i++) {
atoms->atomtype[i] = put_symtab(symtab,"?");
atoms->atomtypeB[i] = put_symtab(symtab,"?");
}
} else {
- do_strstr(atoms->nr,atoms->atomtype,bRead,symtab);
- do_strstr(atoms->nr,atoms->atomtypeB,bRead,symtab);
+ do_strstr(fio, atoms->nr,atoms->atomtype,bRead,symtab);
+ do_strstr(fio, atoms->nr,atoms->atomtypeB,bRead,symtab);
}
- do_resinfo(atoms->nres,atoms->resinfo,bRead,symtab,file_version);
+ do_resinfo(fio, atoms->nres,atoms->resinfo,bRead,symtab,file_version);
if (file_version < 57) {
- do_strstr(groups->ngrpname,groups->grpname,bRead,symtab);
+ do_strstr(fio, groups->ngrpname,groups->grpname,bRead,symtab);
- do_grps(egcNR,groups->grps,bRead,file_version);
+ do_grps(fio, egcNR,groups->grps,bRead,file_version);
}
}
-static void do_groups(gmx_groups_t *groups,
+static void do_groups(t_fileio *fio, gmx_groups_t *groups,
bool bRead,t_symtab *symtab,
int file_version)
{
int g,n,i;
bool bDum=TRUE;
- do_grps(egcNR,groups->grps,bRead,file_version);
- do_int(groups->ngrpname);
+ do_grps(fio, egcNR,groups->grps,bRead,file_version);
+ gmx_fio_do_int(fio,groups->ngrpname);
if (bRead) {
snew(groups->grpname,groups->ngrpname);
}
- do_strstr(groups->ngrpname,groups->grpname,bRead,symtab);
+ do_strstr(fio, groups->ngrpname,groups->grpname,bRead,symtab);
for(g=0; g<egcNR; g++) {
- do_int(groups->ngrpnr[g]);
+ gmx_fio_do_int(fio,groups->ngrpnr[g]);
if (groups->ngrpnr[g] == 0) {
if (bRead) {
groups->grpnr[g] = NULL;
if (bRead) {
snew(groups->grpnr[g],groups->ngrpnr[g]);
}
- ndo_nuchar(groups->grpnr[g],groups->ngrpnr[g],bDum);
+ bDum=gmx_fio_ndo_uchar(fio, groups->grpnr[g],groups->ngrpnr[g]);
}
}
}
-static void do_atomtypes(t_atomtypes *atomtypes,bool bRead,
+static void do_atomtypes(t_fileio *fio, t_atomtypes *atomtypes,bool bRead,
t_symtab *symtab,int file_version)
{
int i,j;
bool bDum = TRUE;
if (file_version > 25) {
- do_int(atomtypes->nr);
+ gmx_fio_do_int(fio,atomtypes->nr);
j=atomtypes->nr;
if (bRead) {
snew(atomtypes->radius,j);
snew(atomtypes->gb_radius,j);
snew(atomtypes->S_hct,j);
}
- ndo_real(atomtypes->radius,j,bDum);
- ndo_real(atomtypes->vol,j,bDum);
- ndo_real(atomtypes->surftens,j,bDum);
+ bDum=gmx_fio_ndo_real(fio,atomtypes->radius,j);
+ bDum=gmx_fio_ndo_real(fio,atomtypes->vol,j);
+ bDum=gmx_fio_ndo_real(fio,atomtypes->surftens,j);
if(file_version >= 40)
{
- ndo_int(atomtypes->atomnumber,j,bDum);
+ bDum=gmx_fio_ndo_int(fio,atomtypes->atomnumber,j);
}
if(file_version >= 60)
{
- ndo_real(atomtypes->gb_radius,j,bDum);
- ndo_real(atomtypes->S_hct,j,bDum);
+ bDum=gmx_fio_ndo_real(fio,atomtypes->gb_radius,j);
+ bDum=gmx_fio_ndo_real(fio,atomtypes->S_hct,j);
}
} else {
/* File versions prior to 26 cannot do GBSA,
}
}
-static void do_symtab(t_symtab *symtab,bool bRead)
+static void do_symtab(t_fileio *fio, t_symtab *symtab,bool bRead)
{
int i,nr;
t_symbuf *symbuf;
char buf[STRLEN];
- do_int(symtab->nr);
+ gmx_fio_do_int(fio,symtab->nr);
nr = symtab->nr;
if (bRead) {
snew(symtab->symbuf,1);
symbuf->bufsize = nr;
snew(symbuf->buf,nr);
for (i=0; (i<nr); i++) {
- do_string(buf);
+ gmx_fio_do_string(fio,buf);
symbuf->buf[i]=strdup(buf);
}
}
symbuf = symtab->symbuf;
while (symbuf!=NULL) {
for (i=0; (i<symbuf->bufsize) && (i<nr); i++)
- do_string(symbuf->buf[i]);
+ gmx_fio_do_string(fio,symbuf->buf[i]);
nr-=i;
symbuf=symbuf->next;
}
}
}
-static void
-do_cmap(gmx_cmap_t *cmap_grid, bool bRead)
+static void do_cmap(t_fileio *fio, gmx_cmap_t *cmap_grid, bool bRead)
{
int i,j,ngrid,gs,nelem;
- do_int(cmap_grid->ngrid);
- do_int(cmap_grid->grid_spacing);
+ gmx_fio_do_int(fio,cmap_grid->ngrid);
+ gmx_fio_do_int(fio,cmap_grid->grid_spacing);
ngrid = cmap_grid->ngrid;
gs = cmap_grid->grid_spacing;
{
for(j=0;j<nelem;j++)
{
- do_real(cmap_grid->cmapdata[i].cmap[j*4]);
- do_real(cmap_grid->cmapdata[i].cmap[j*4+1]);
- do_real(cmap_grid->cmapdata[i].cmap[j*4+2]);
- do_real(cmap_grid->cmapdata[i].cmap[j*4+3]);
+ gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4]);
+ gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+1]);
+ gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+2]);
+ gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+3]);
}
}
}
-void
-tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols)
+void tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols)
{
int m,a,a0,a1,r;
unsigned char c,chain;
}
}
-static void do_moltype(gmx_moltype_t *molt,bool bRead,t_symtab *symtab,
- int file_version,
+static void do_moltype(t_fileio *fio, gmx_moltype_t *molt,bool bRead,
+ t_symtab *symtab, int file_version,
gmx_groups_t *groups)
{
int i;
if (file_version >= 57) {
- do_symstr(&(molt->name),bRead,symtab);
+ do_symstr(fio, &(molt->name),bRead,symtab);
}
- do_atoms(&molt->atoms, bRead, symtab, file_version, groups);
+ do_atoms(fio, &molt->atoms, bRead, symtab, file_version, groups);
if (bRead && gmx_debug_at) {
pr_atoms(debug,0,"atoms",&molt->atoms,TRUE);
}
if (file_version >= 57) {
- do_ilists(molt->ilist,bRead,file_version);
+ do_ilists(fio, molt->ilist,bRead,file_version);
- do_block(&molt->cgs,bRead,file_version);
+ do_block(fio, &molt->cgs,bRead,file_version);
if (bRead && gmx_debug_at) {
pr_block(debug,0,"cgs",&molt->cgs,TRUE);
}
}
/* This used to be in the atoms struct */
- do_blocka(&molt->excls, bRead, file_version);
+ do_blocka(fio, &molt->excls, bRead, file_version);
}
-static void do_molblock(gmx_molblock_t *molb,bool bRead,int file_version)
+static void do_molblock(t_fileio *fio, gmx_molblock_t *molb,bool bRead,
+ int file_version)
{
int i;
- do_int(molb->type);
- do_int(molb->nmol);
- do_int(molb->natoms_mol);
+ gmx_fio_do_int(fio,molb->type);
+ gmx_fio_do_int(fio,molb->nmol);
+ gmx_fio_do_int(fio,molb->natoms_mol);
/* Position restraint coordinates */
- do_int(molb->nposres_xA);
+ gmx_fio_do_int(fio,molb->nposres_xA);
if (molb->nposres_xA > 0) {
if (bRead) {
snew(molb->posres_xA,molb->nposres_xA);
}
- ndo_rvec(molb->posres_xA,molb->nposres_xA);
+ gmx_fio_ndo_rvec(fio,molb->posres_xA,molb->nposres_xA);
}
- do_int(molb->nposres_xB);
+ gmx_fio_do_int(fio,molb->nposres_xB);
if (molb->nposres_xB > 0) {
if (bRead) {
snew(molb->posres_xB,molb->nposres_xB);
}
- ndo_rvec(molb->posres_xB,molb->nposres_xB);
+ gmx_fio_ndo_rvec(fio,molb->posres_xB,molb->nposres_xB);
}
}
}
}
-static void do_mtop(gmx_mtop_t *mtop,bool bRead, int file_version)
+static void do_mtop(t_fileio *fio, gmx_mtop_t *mtop,bool bRead,
+ int file_version)
{
int mt,mb,i;
t_blocka dumb;
if (bRead)
init_mtop(mtop);
- do_symtab(&(mtop->symtab),bRead);
+ do_symtab(fio, &(mtop->symtab),bRead);
if (bRead && debug)
pr_symtab(debug,0,"symtab",&mtop->symtab);
- do_symstr(&(mtop->name),bRead,&(mtop->symtab));
+ do_symstr(fio, &(mtop->name),bRead,&(mtop->symtab));
if (file_version >= 57) {
- do_ffparams(&mtop->ffparams,bRead,file_version);
+ do_ffparams(fio, &mtop->ffparams,bRead,file_version);
- do_int(mtop->nmoltype);
+ gmx_fio_do_int(fio,mtop->nmoltype);
} else {
mtop->nmoltype = 1;
}
}
}
for(mt=0; mt<mtop->nmoltype; mt++) {
- do_moltype(&mtop->moltype[mt],bRead,&mtop->symtab,file_version,
+ do_moltype(fio, &mtop->moltype[mt],bRead,&mtop->symtab,file_version,
&mtop->groups);
}
if (file_version >= 57) {
- do_int(mtop->nmolblock);
+ gmx_fio_do_int(fio,mtop->nmolblock);
} else {
mtop->nmolblock = 1;
}
}
if (file_version >= 57) {
for(mb=0; mb<mtop->nmolblock; mb++) {
- do_molblock(&mtop->molblock[mb],bRead,file_version);
+ do_molblock(fio, &mtop->molblock[mb],bRead,file_version);
}
- do_int(mtop->natoms);
+ gmx_fio_do_int(fio,mtop->natoms);
} else {
mtop->molblock[0].type = 0;
mtop->molblock[0].nmol = 1;
mtop->molblock[0].nposres_xB = 0;
}
- do_atomtypes (&(mtop->atomtypes),bRead,&(mtop->symtab), file_version);
+ do_atomtypes (fio, &(mtop->atomtypes),bRead,&(mtop->symtab), file_version);
if (bRead && debug)
pr_atomtypes(debug,0,"atomtypes",&mtop->atomtypes,TRUE);
if (file_version < 57) {
/* Debug statements are inside do_idef */
- do_idef (&mtop->ffparams,&mtop->moltype[0],bRead,file_version);
+ do_idef (fio, &mtop->ffparams,&mtop->moltype[0],bRead,file_version);
mtop->natoms = mtop->moltype[0].atoms.nr;
}
if(file_version >= 65)
{
- do_cmap(&mtop->ffparams.cmap_grid,bRead);
+ do_cmap(fio, &mtop->ffparams.cmap_grid,bRead);
}
else
{
}
if (file_version >= 57) {
- do_groups(&mtop->groups,bRead,&(mtop->symtab),file_version);
+ do_groups(fio, &mtop->groups,bRead,&(mtop->symtab),file_version);
}
if (file_version < 57) {
- do_block(&mtop->moltype[0].cgs,bRead,file_version);
+ do_block(fio, &mtop->moltype[0].cgs,bRead,file_version);
if (bRead && gmx_debug_at) {
pr_block(debug,0,"cgs",&mtop->moltype[0].cgs,TRUE);
}
- do_block(&mtop->mols,bRead,file_version);
+ do_block(fio, &mtop->mols,bRead,file_version);
/* Add the posres coordinates to the molblock */
add_posres_molblock(mtop);
}
if (file_version < 51) {
/* Here used to be the shake blocks */
- do_blocka(&dumb,bRead,file_version);
+ do_blocka(fio, &dumb,bRead,file_version);
if (dumb.nr > 0)
sfree(dumb.index);
if (dumb.nra > 0)
*
* If possible, we will read the inputrec even when TopOnlyOK is TRUE.
*/
-static void do_tpxheader(int fp,bool bRead,t_tpxheader *tpx, bool TopOnlyOK,
- int *file_version, int *file_generation)
+static void do_tpxheader(t_fileio *fio,bool bRead,t_tpxheader *tpx,
+ bool TopOnlyOK, int *file_version,
+ int *file_generation)
{
char buf[STRLEN];
bool bDouble;
int fver,fgen;
int idum=0;
real rdum=0;
- gmx_fio_select(fp);
- gmx_fio_setdebug(fp,bDebugMode());
+
+ gmx_fio_checktype(fio);
+ gmx_fio_setdebug(fio,bDebugMode());
/* NEW! XDR tpb file */
precision = sizeof(real);
if (bRead) {
- do_string(buf);
+ gmx_fio_do_string(fio,buf);
if (strncmp(buf,"VERSION",7))
gmx_fatal(FARGS,"Can not read file %s,\n"
" this file is from a Gromacs version which is older than 2.0\n"
" Make a new one with grompp or use a gro or pdb file, if possible",
- gmx_fio_getname(fp));
- do_int(precision);
+ gmx_fio_getname(fio));
+ gmx_fio_do_int(fio,precision);
bDouble = (precision == sizeof(double));
if ((precision != sizeof(float)) && !bDouble)
gmx_fatal(FARGS,"Unknown precision in file %s: real is %d bytes "
"instead of %d or %d",
- gmx_fio_getname(fp),precision,sizeof(float),sizeof(double));
- gmx_fio_setprecision(fp,bDouble);
+ gmx_fio_getname(fio),precision,sizeof(float),sizeof(double));
+ gmx_fio_setprecision(fio,bDouble);
fprintf(stderr,"Reading file %s, %s (%s precision)\n",
- gmx_fio_getname(fp),buf,bDouble ? "double" : "single");
+ gmx_fio_getname(fio),buf,bDouble ? "double" : "single");
}
else {
- do_string(GromacsVersion());
+ gmx_fio_write_string(fio,GromacsVersion());
bDouble = (precision == sizeof(double));
- gmx_fio_setprecision(fp,bDouble);
- do_int(precision);
+ gmx_fio_setprecision(fio,bDouble);
+ gmx_fio_do_int(fio,precision);
fver = tpx_version;
fgen = tpx_generation;
}
/* Check versions! */
- do_int(fver);
+ gmx_fio_do_int(fio,fver);
if(fver>=26)
- do_int(fgen);
+ gmx_fio_do_int(fio,fgen);
else
fgen=0;
((fver > tpx_version) && !TopOnlyOK) ||
(fgen > tpx_generation))
gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",
- gmx_fio_getname(fp),fver,tpx_version);
+ gmx_fio_getname(fio),fver,tpx_version);
- do_section(eitemHEADER,bRead);
- do_int (tpx->natoms);
+ do_section(fio,eitemHEADER,bRead);
+ gmx_fio_do_int(fio,tpx->natoms);
if (fver >= 28)
- do_int(tpx->ngtc);
+ gmx_fio_do_int(fio,tpx->ngtc);
else
tpx->ngtc = 0;
if (fver < 62) {
- do_int (idum);
- do_real(rdum);
+ gmx_fio_do_int(fio,idum);
+ gmx_fio_do_real(fio,rdum);
}
- do_real(tpx->lambda);
- do_int (tpx->bIr);
- do_int (tpx->bTop);
- do_int (tpx->bX);
- do_int (tpx->bV);
- do_int (tpx->bF);
- do_int (tpx->bBox);
+ gmx_fio_do_real(fio,tpx->lambda);
+ gmx_fio_do_int(fio,tpx->bIr);
+ gmx_fio_do_int(fio,tpx->bTop);
+ gmx_fio_do_int(fio,tpx->bX);
+ gmx_fio_do_int(fio,tpx->bV);
+ gmx_fio_do_int(fio,tpx->bF);
+ gmx_fio_do_int(fio,tpx->bBox);
if((fgen > tpx_generation)) {
/* This can only happen if TopOnlyOK=TRUE */
}
}
-static int do_tpx(int fp,bool bRead,
+static int do_tpx(t_fileio *fio, bool bRead,
t_inputrec *ir,t_state *state,rvec *f,gmx_mtop_t *mtop,
bool bXVallocated)
{
TopOnlyOK = (ir==NULL);
- do_tpxheader(fp,bRead,&tpx,TopOnlyOK,&file_version,&file_generation);
+ do_tpxheader(fio,bRead,&tpx,TopOnlyOK,&file_version,&file_generation);
if (bRead) {
state->flags = 0;
}
}
-#define do_test(b,p) if (bRead && (p!=NULL) && !b) gmx_fatal(FARGS,"No %s in %s",#p,gmx_fio_getname(fp))
+#define do_test(fio,b,p) if (bRead && (p!=NULL) && !b) gmx_fatal(FARGS,"No %s in %s",#p,gmx_fio_getname(fio))
- do_test(tpx.bBox,state->box);
- do_section(eitemBOX,bRead);
+ do_test(fio,tpx.bBox,state->box);
+ do_section(fio,eitemBOX,bRead);
if (tpx.bBox) {
- ndo_rvec(state->box,DIM);
+ gmx_fio_ndo_rvec(fio,state->box,DIM);
if (file_version >= 51) {
- ndo_rvec(state->box_rel,DIM);
+ gmx_fio_ndo_rvec(fio,state->box_rel,DIM);
} else {
/* We initialize box_rel after reading the inputrec */
clear_mat(state->box_rel);
}
if (file_version >= 28) {
- ndo_rvec(state->boxv,DIM);
+ gmx_fio_ndo_rvec(fio,state->boxv,DIM);
if (file_version < 56) {
matrix mdum;
- ndo_rvec(mdum,DIM);
+ gmx_fio_ndo_rvec(fio,mdum,DIM);
}
}
}
/*ndo_double(state->therm_integral,state->ngtc,bDum);*/
snew(dumv,state->ngtc);
if (file_version < 69) {
- ndo_real(dumv,state->ngtc,bDum);
+ bDum=gmx_fio_ndo_real(fio,dumv,state->ngtc);
}
/* These used to be the Berendsen tcoupl_lambda's */
- ndo_real(dumv,state->ngtc,bDum);
+ bDum=gmx_fio_ndo_real(fio,dumv,state->ngtc);
sfree(dumv);
}
* for analysis/viewer programs.
*/
if(file_version<26) {
- do_test(tpx.bIr,ir);
- do_section(eitemIR,bRead);
+ do_test(fio,tpx.bIr,ir);
+ do_section(fio,eitemIR,bRead);
if (tpx.bIr) {
if (ir) {
- do_inputrec(ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ : NULL);
+ do_inputrec(fio, ir,bRead,file_version,
+ mtop ? &mtop->ffparams.fudgeQQ : NULL);
if (bRead && debug)
pr_inputrec(debug,0,"inputrec",ir,FALSE);
}
else {
- do_inputrec(&dum_ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ :NULL);
+ do_inputrec(fio, &dum_ir,bRead,file_version,
+ mtop ? &mtop->ffparams.fudgeQQ :NULL);
if (bRead && debug)
pr_inputrec(debug,0,"inputrec",&dum_ir,FALSE);
done_inputrec(&dum_ir);
}
}
- do_test(tpx.bTop,mtop);
- do_section(eitemTOP,bRead);
+ do_test(fio,tpx.bTop,mtop);
+ do_section(fio,eitemTOP,bRead);
if (tpx.bTop) {
if (mtop) {
- do_mtop(mtop,bRead, file_version);
+ do_mtop(fio,mtop,bRead, file_version);
} else {
- do_mtop(&dum_top,bRead,file_version);
+ do_mtop(fio,&dum_top,bRead,file_version);
done_mtop(&dum_top,TRUE);
}
}
- do_test(tpx.bX,state->x);
- do_section(eitemX,bRead);
+ do_test(fio,tpx.bX,state->x);
+ do_section(fio,eitemX,bRead);
if (tpx.bX) {
if (bRead) {
state->flags |= (1<<estX);
}
- ndo_rvec(state->x,state->natoms);
+ gmx_fio_ndo_rvec(fio,state->x,state->natoms);
}
- do_test(tpx.bV,state->v);
- do_section(eitemV,bRead);
+ do_test(fio,tpx.bV,state->v);
+ do_section(fio,eitemV,bRead);
if (tpx.bV) {
if (bRead) {
state->flags |= (1<<estV);
}
- ndo_rvec(state->v,state->natoms);
+ gmx_fio_ndo_rvec(fio,state->v,state->natoms);
}
- do_test(tpx.bF,f);
- do_section(eitemF,bRead);
- if (tpx.bF) ndo_rvec(f,state->natoms);
+ do_test(fio,tpx.bF,f);
+ do_section(fio,eitemF,bRead);
+ if (tpx.bF) gmx_fio_ndo_rvec(fio,f,state->natoms);
/* Starting with tpx version 26, we have the inputrec
* at the end of the file, so we can ignore it
ePBC = -1;
bPeriodicMols = FALSE;
if (file_version >= 26) {
- do_test(tpx.bIr,ir);
- do_section(eitemIR,bRead);
+ do_test(fio,tpx.bIr,ir);
+ do_section(fio,eitemIR,bRead);
if (tpx.bIr) {
if (file_version >= 53) {
/* Removed the pbc info from do_inputrec, since we always want it */
ePBC = ir->ePBC;
bPeriodicMols = ir->bPeriodicMols;
}
- do_int(ePBC);
- do_int(bPeriodicMols);
+ gmx_fio_do_int(fio,ePBC);
+ gmx_fio_do_bool(fio,bPeriodicMols);
}
if (file_generation <= tpx_generation && ir) {
- do_inputrec(ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ : NULL);
+ do_inputrec(fio, ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ : NULL);
if (bRead && debug)
pr_inputrec(debug,0,"inputrec",ir,FALSE);
if (file_version < 51)
*
************************************************************/
-int open_tpx(const char *fn,const char *mode)
+t_fileio *open_tpx(const char *fn,const char *mode)
{
return gmx_fio_open(fn,mode);
}
-void close_tpx(int fp)
+void close_tpx(t_fileio *fio)
{
- gmx_fio_close(fp);
+ gmx_fio_close(fio);
}
void read_tpxheader(const char *fn, t_tpxheader *tpx, bool TopOnlyOK,
int *file_version, int *file_generation)
{
- int fp;
+ t_fileio *fio;
- fp = open_tpx(fn,"r");
- do_tpxheader(fp,TRUE,tpx,TopOnlyOK,file_version,file_generation);
- close_tpx(fp);
+ fio = open_tpx(fn,"r");
+ do_tpxheader(fio,TRUE,tpx,TopOnlyOK,file_version,file_generation);
+ close_tpx(fio);
}
void write_tpx_state(const char *fn,
t_inputrec *ir,t_state *state,gmx_mtop_t *mtop)
{
- int fp;
+ t_fileio *fio;
- fp = open_tpx(fn,"w");
- do_tpx(fp,FALSE,ir,state,NULL,mtop,FALSE);
- close_tpx(fp);
+ fio = open_tpx(fn,"w");
+ do_tpx(fio,FALSE,ir,state,NULL,mtop,FALSE);
+ close_tpx(fio);
}
void read_tpx_state(const char *fn,
t_inputrec *ir,t_state *state,rvec *f,gmx_mtop_t *mtop)
{
- int fp;
+ t_fileio *fio;
- fp = open_tpx(fn,"r");
- do_tpx(fp,TRUE,ir,state,f,mtop,FALSE);
- close_tpx(fp);
+ fio = open_tpx(fn,"r");
+ do_tpx(fio,TRUE,ir,state,f,mtop,FALSE);
+ close_tpx(fio);
}
int read_tpx(const char *fn,
t_inputrec *ir, matrix box,int *natoms,
rvec *x,rvec *v,rvec *f,gmx_mtop_t *mtop)
{
- int fp;
+ t_fileio *fio;
t_state state;
int ePBC;
state.x = x;
state.v = v;
- fp = open_tpx(fn,"r");
- ePBC = do_tpx(fp,TRUE,ir,&state,f,mtop,TRUE);
- close_tpx(fp);
+ fio = open_tpx(fn,"r");
+ ePBC = do_tpx(fio,TRUE,ir,&state,f,mtop,TRUE);
+ close_tpx(fio);
*natoms = state.natoms;
if (box)
copy_mat(state.box,box);
m->bMapStatic = TRUE;
}
+/*!
+ * \param[in,out] m Mapping structure to initialize.
+ * \param[in] b Block information to use for data.
+ *
+ * Frees some memory that is not necessary for static index group mappings.
+ * Internal pointers are set to point to data in \p b; it is the responsibility
+ * of the caller to ensure that the block information matches the contents of
+ * the mapping.
+ * After this function has been called, the index group provided to
+ * gmx_ana_indexmap_update() should always be the same as \p g given here.
+ *
+ * This function breaks modularity of the index group mapping interface in an
+ * ugly way, but allows reducing memory usage of static selections by a
+ * significant amount.
+ */
+void
+gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b)
+{
+ sfree(m->mapid);
+ m->mapid = m->orgid;
+ sfree(m->b.index);
+ m->b.nalloc_index = 0;
+ m->b.index = b->index;
+ sfree(m->mapb.index);
+ m->mapb.nalloc_index = 0;
+ m->mapb.index = m->b.index;
+ sfree(m->b.a);
+ m->b.nalloc_a = 0;
+ m->b.a = b->a;
+}
+
/*!
* \param[in,out] dest Destination data structure.
* \param[in] src Source mapping.
gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m)
{
sfree(m->refid);
- sfree(m->mapid);
- sfree(m->mapb.index);
+ if (m->mapid != m->orgid)
+ {
+ sfree(m->mapid);
+ }
+ if (m->mapb.nalloc_index > 0)
+ {
+ sfree(m->mapb.index);
+ }
sfree(m->orgid);
- sfree(m->b.index);
- sfree(m->b.a);
+ if (m->b.nalloc_index > 0)
+ {
+ sfree(m->b.index);
+ }
+ if (m->b.nalloc_a > 0)
+ {
+ sfree(m->b.a);
+ }
gmx_ana_indexmap_clear(m);
}
* When the data structure is no longer required, it can be freed with
* gmx_ana_nbsearch_free().
*
- * \todo
- * Implement grid-based searching
- * (currently everything is implemented using an expensive O(n^2) loop).
- * Optimally, the MD neighborhood searching routines could be used, but
- * currently they are quite difficult to interface flexibly.
- *
- * \todo
- * Implement a set of functions for looping through all pairs within a cutoff.
+ * \internal
*
* \todo
- * Implement an API that allows for excluding certain pairs of atoms from
- * neighborhood searching.
+ * The grid implementation could still be optimized in several different ways:
+ * - Triclinic grid cells are not the most efficient shape, but make PBC
+ * handling easier.
+ * - Precalculating the required PBC shift for a pair of cells outside the
+ * inner loop. After this is done, it should be quite straightforward to
+ * move to rectangular cells.
+ * - Pruning grid cells from the search list if they are completely outside
+ * the sphere that is being considered.
+ * - A better heuristic could be added for falling back to simple loops for a
+ * small number of reference particles.
+ * - A better heuristic for selecting the grid size.
+ * - A multi-level grid implementation could be used to be able to use small
+ * grids for short cutoffs with very inhomogeneous particle distributions
+ * without a memory cost.
*/
/*! \internal \file
* \brief Implementation of functions in nbsearch.h.
#include <config.h>
#endif
+#include <math.h>
+
#include <smalloc.h>
#include <typedefs.h>
#include <pbc.h>
*/
struct gmx_ana_nbsearch_t
{
+ /** The cutoff. */
+ real cutoff;
/** The cutoff squared. */
real cutoff2;
/** Maximum number of reference points. */
int maxnref;
+
/** Number of reference points for the current frame. */
int nref;
/** Reference point positions. */
rvec *xref;
+ /** Reference position ids (NULL if not available). */
+ int *refid;
/** PBC data. */
t_pbc *pbc;
+
+ /** Number of excluded reference positions for current test particle. */
+ int nexcl;
+ /** Exclusions for current test particle. */
+ int *excl;
+
+ /** Whether to try grid searching. */
+ bool bTryGrid;
+ /** Whether grid searching is actually used for the current positions. */
+ bool bGrid;
+ /** Array allocated for storing in-unit-cell reference positions. */
+ rvec *xref_alloc;
+ /** FALSE if the box is rectangular. */
+ bool bTric;
+ /** Box vectors of a single grid cell. */
+ matrix cellbox;
+ /** The reciprocal cell vectors as columns; the inverse of \p cellbox. */
+ matrix recipcell;
+ /** Number of cells along each dimension. */
+ ivec ncelldim;
+ /** Total number of cells. */
+ int ncells;
+ /** Number of reference positions in each cell. */
+ int *ncatoms;
+ /** List of reference positions in each cell. */
+ atom_id **catom;
+ /** Allocation counts for each \p catom[i]. */
+ int *catom_nalloc;
+ /** Allocation count for the per-cell arrays. */
+ int cells_nalloc;
+ /** Number of neighboring cells to consider. */
+ int ngridnb;
+ /** Offsets of the neighboring cells to consider. */
+ ivec *gnboffs;
+ /** Allocation count for \p gnboffs. */
+ int gnboffs_nalloc;
+
+ /** Stores test position during a pair loop. */
+ rvec xtest;
+ /** Stores the previous returned position during a pair loop. */
+ int previ;
+ /** Stores the current exclusion index during loops. */
+ int exclind;
+ /** Stores the test particle cell index during loops. */
+ ivec testcell;
+ /** Stores the current cell neighbor index during pair loops. */
+ int prevnbi;
+ /** Stores the index within the current cell during pair loops. */
+ int prevcai;
};
/*!
gmx_ana_nbsearch_t *d;
snew(d, 1);
+ d->bTryGrid = TRUE;
if (cutoff <= 0)
{
cutoff = HUGE_VAL;
+ d->bTryGrid = FALSE;
}
+ d->cutoff = cutoff;
d->cutoff2 = sqr(cutoff);
d->maxnref = maxn;
+
+ d->xref = NULL;
+ d->nexcl = 0;
+ d->exclind = 0;
+
+ d->xref_alloc = NULL;
+ d->ncells = 0;
+ d->ncatoms = NULL;
+ d->catom = NULL;
+ d->catom_nalloc = 0;
+ d->cells_nalloc = 0;
+
+ d->ngridnb = 0;
+ d->gnboffs = NULL;
+ d->gnboffs_nalloc = 0;
+
*data = d;
return 0;
}
void
gmx_ana_nbsearch_free(gmx_ana_nbsearch_t *d)
{
+ sfree(d->xref_alloc);
+ sfree(d->ncatoms);
+ if (d->catom)
+ {
+ int ci;
+
+ for (ci = 0; ci < d->ncells; ++ci)
+ {
+ sfree(d->catom[ci]);
+ }
+ sfree(d->catom);
+ }
+ sfree(d->catom_nalloc);
+ sfree(d->gnboffs);
sfree(d);
}
+/*! \brief
+ * Calculates offsets to neighboring grid cells that should be considered.
+ *
+ * \param[in,out] d Grid information.
+ * \param[in] pbc Information about the box.
+ */
+static void
+grid_init_cell_nblist(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+ int maxx, maxy, maxz;
+ int x, y, z, i;
+ real rvnorm;
+
+ /* Find the extent of the sphere in triclinic coordinates */
+ maxz = (int)(d->cutoff * d->recipcell[ZZ][ZZ]) + 1;
+ rvnorm = sqrt(sqr(d->recipcell[YY][YY]) + sqr(d->recipcell[ZZ][YY]));
+ maxy = (int)(d->cutoff * rvnorm) + 1;
+ rvnorm = sqrt(sqr(d->recipcell[XX][XX]) + sqr(d->recipcell[YY][XX])
+ + sqr(d->recipcell[ZZ][XX]));
+ maxx = (int)(d->cutoff * rvnorm) + 1;
+
+ /* Calculate the number of cells and reallocate if necessary */
+ d->ngridnb = (2 * maxx + 1) * (2 * maxy + 1) * (2 * maxz + 1);
+ if (d->gnboffs_nalloc < d->ngridnb)
+ {
+ d->gnboffs_nalloc = d->ngridnb;
+ srenew(d->gnboffs, d->gnboffs_nalloc);
+ }
+
+ /* Store the whole cube */
+ /* TODO: Prune off corners that are not needed */
+ i = 0;
+ for (x = -maxx; x <= maxx; ++x)
+ {
+ for (y = -maxy; y <= maxy; ++y)
+ {
+ for (z = -maxz; z <= maxz; ++z)
+ {
+ d->gnboffs[i][XX] = x;
+ d->gnboffs[i][YY] = y;
+ d->gnboffs[i][ZZ] = z;
+ ++i;
+ }
+ }
+ }
+}
+
+/*! \brief
+ * Determines a suitable grid size.
+ *
+ * \param[in,out] d Grid information.
+ * \param[in] pbc Information about the box.
+ * \returns FALSE if grid search is not suitable.
+ */
+static bool
+grid_setup_cells(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+ real targetsize;
+ int dd;
+
+#ifdef HAVE_CBRT
+ targetsize = cbrt(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
+ * 10 / d->nref);
+#else
+ targetsize = pow(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
+ * 10 / d->nref, 1./3.);
+#endif
+
+ d->ncells = 1;
+ for (dd = 0; dd < DIM; ++dd)
+ {
+ d->ncelldim[dd] = (int)(pbc->box[dd][dd] / targetsize);
+ d->ncells *= d->ncelldim[dd];
+ if (d->ncelldim[dd] < 3)
+ {
+ return FALSE;
+ }
+ }
+ /* Reallocate if necessary */
+ if (d->cells_nalloc < d->ncells)
+ {
+ int i;
+
+ srenew(d->ncatoms, d->ncells);
+ srenew(d->catom, d->ncells);
+ srenew(d->catom_nalloc, d->ncells);
+ for (i = d->cells_nalloc; i < d->ncells; ++i)
+ {
+ d->catom[i] = NULL;
+ d->catom_nalloc[i] = 0;
+ }
+ d->cells_nalloc = d->ncells;
+ }
+ return TRUE;
+}
+
+/*! \brief
+ * Sets ua a search grid for a given box.
+ *
+ * \param[in,out] d Grid information.
+ * \param[in] pbc Information about the box.
+ * \returns FALSE if grid search is not suitable.
+ */
+static bool
+grid_set_box(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+ int dd;
+
+ /* TODO: This check could be improved. */
+ if (0.5*pbc->max_cutoff2 < d->cutoff2)
+ {
+ return FALSE;
+ }
+
+ if (!grid_setup_cells(d, pbc))
+ {
+ return FALSE;
+ }
+
+ d->bTric = TRICLINIC(pbc->box);
+ if (d->bTric)
+ {
+ for (dd = 0; dd < DIM; ++dd)
+ {
+ svmul(1.0 / d->ncelldim[dd], pbc->box[dd], d->cellbox[dd]);
+ }
+ m_inv_ur0(d->cellbox, d->recipcell);
+ }
+ else
+ {
+ for (dd = 0; dd < DIM; ++dd)
+ {
+ d->cellbox[dd][dd] = pbc->box[dd][dd] / d->ncelldim[dd];
+ d->recipcell[dd][dd] = 1 / d->cellbox[dd][dd];
+ }
+ }
+ grid_init_cell_nblist(d, pbc);
+ return TRUE;
+}
+
+/*! \brief
+ * Maps a point into a grid cell.
+ *
+ * \param[in] d Grid information.
+ * \param[in] x Point to map.
+ * \param[out] cell Indices of the grid cell in which \p x lies.
+ *
+ * \p x should be in the triclinic unit cell.
+ */
+static void
+grid_map_onto(gmx_ana_nbsearch_t *d, const rvec x, ivec cell)
+{
+ int dd;
+
+ if (d->bTric)
+ {
+ rvec tx;
+
+ tmvmul_ur0(d->recipcell, x, tx);
+ for (dd = 0; dd < DIM; ++dd)
+ {
+ cell[dd] = (int)tx[dd];
+ }
+ }
+ else
+ {
+ for (dd = 0; dd < DIM; ++dd)
+ {
+ cell[dd] = (int)(x[dd] * d->recipcell[dd][dd]);
+ }
+ }
+}
+
+/*! \brief
+ * Calculates linear index of a grid cell.
+ *
+ * \param[in] d Grid information.
+ * \param[in] cell Cell indices.
+ * \returns Linear index of \p cell.
+ */
+static int
+grid_index(gmx_ana_nbsearch_t *d, const ivec cell)
+{
+ return cell[XX] + cell[YY] * d->ncelldim[XX]
+ + cell[ZZ] * d->ncelldim[YY] * d->ncelldim[ZZ];
+}
+
+/*! \brief
+ * Clears all grid cells.
+ *
+ * \param[in,out] d Grid information.
+ */
+static void
+grid_clear_cells(gmx_ana_nbsearch_t *d)
+{
+ int ci;
+
+ for (ci = 0; ci < d->ncells; ++ci)
+ {
+ d->ncatoms[ci] = 0;
+ }
+}
+
+/*! \brief
+ * Adds an index into a grid cell.
+ *
+ * \param[in,out] d Grid information.
+ * \param[in] cell Cell into which \p i should be added.
+ * \param[in] i Index to add.
+ */
+static void
+grid_add_to_cell(gmx_ana_nbsearch_t *d, const ivec cell, int i)
+{
+ int ci = grid_index(d, cell);
+
+ if (d->ncatoms[ci] == d->catom_nalloc[ci])
+ {
+ d->catom_nalloc[ci] += 10;
+ srenew(d->catom[ci], d->catom_nalloc[ci]);
+ }
+ d->catom[ci][d->ncatoms[ci]++] = i;
+}
+
/*!
* \param[in,out] d Neighborhood search data structure.
* \param[in] pbc PBC information for the frame.
{
d->pbc = pbc;
d->nref = n;
- d->xref = x;
+ if (!pbc)
+ {
+ d->bGrid = FALSE;
+ }
+ else if (d->bTryGrid)
+ {
+ d->bGrid = grid_set_box(d, pbc);
+ }
+ if (d->bGrid)
+ {
+ int i;
+
+ if (!d->xref_alloc)
+ {
+ snew(d->xref_alloc, d->maxnref);
+ }
+ d->xref = d->xref_alloc;
+ grid_clear_cells(d);
+
+ for (i = 0; i < n; ++i)
+ {
+ copy_rvec(x[i], d->xref[i]);
+ }
+ put_atoms_in_triclinic_unitcell(ecenterTRIC, pbc->box, n, d->xref);
+ for (i = 0; i < n; ++i)
+ {
+ ivec refcell;
+
+ grid_map_onto(d, d->xref[i], refcell);
+ grid_add_to_cell(d, refcell, i);
+ }
+ }
+ else
+ {
+ d->xref = x;
+ }
+ d->refid = NULL;
return 0;
}
int
gmx_ana_nbsearch_pos_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, gmx_ana_pos_t *p)
{
- return gmx_ana_nbsearch_init(d, pbc, p->nr, p->x);
+ int rc;
+
+ rc = gmx_ana_nbsearch_init(d, pbc, p->nr, p->x);
+ d->refid = (p->nr < d->maxnref ? p->m.refid : NULL);
+ return rc;
}
/*!
- * \param[in] d Neighborhood search data structure.
- * \param[in] x Test position.
- * \returns TRUE if \p x is within the cutoff of any reference position,
- * FALSE otherwise.
+ * \param[in,out] d Neighborhood search data structure.
+ * \param[in] nexcl Number of reference positions to exclude from next
+ * search.
+ * \param[in] excl Indices of reference positions to exclude.
+ * \returns 0 on success.
+ *
+ * The set exclusions remain in effect until the next call of this function.
*/
-bool
-gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, rvec x)
+int
+gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[])
{
- int i;
- rvec dx;
- for (i = 0; i < d->nref; ++i)
+ d->nexcl = nexcl;
+ d->excl = excl;
+ return 0;
+}
+
+/*! \brief
+ * Helper function to check whether a reference point should be excluded.
+ */
+static bool
+is_excluded(gmx_ana_nbsearch_t *d, int j)
+{
+ if (d->exclind < d->nexcl)
{
- if (d->pbc)
+ if (d->refid)
{
- pbc_dx(d->pbc, x, d->xref[i], dx);
+ while (d->exclind < d->nexcl && d->refid[j] > d->excl[d->exclind])
+ {
+ ++d->exclind;
+ }
+ if (d->exclind < d->nexcl && d->refid[j] == d->excl[d->exclind])
+ {
+ ++d->exclind;
+ return TRUE;
+ }
}
else
{
- rvec_sub(x, d->xref[i], dx);
+ while (d->bGrid && d->exclind < d->nexcl && d->excl[d->exclind] < j)
+ {
+ ++d->exclind;
+ }
+ if (d->excl[d->exclind] == j)
+ {
+ ++d->exclind;
+ return TRUE;
+ }
}
- if (norm2(dx) <= d->cutoff2)
+ }
+ return FALSE;
+}
+
+/*! \brief
+ * Initializes a grid search to find reference positions neighboring \p x.
+ */
+static void
+grid_search_start(gmx_ana_nbsearch_t *d, rvec x)
+{
+ copy_rvec(x, d->xtest);
+ if (d->bGrid)
+ {
+ put_atoms_in_triclinic_unitcell(ecenterTRIC, d->pbc->box, 1, &d->xtest);
+ grid_map_onto(d, d->xtest, d->testcell);
+ d->prevnbi = 0;
+ d->prevcai = -1;
+ }
+ else
+ {
+ d->previ = -1;
+ }
+ d->exclind = 0;
+}
+
+/*! \brief
+ * Does a grid search.
+ */
+static bool
+grid_search(gmx_ana_nbsearch_t *d,
+ bool (*action)(gmx_ana_nbsearch_t *d, int i, real r2))
+{
+ int i;
+ rvec dx;
+ real r2;
+
+ if (d->bGrid)
+ {
+ int nbi, ci, cai;
+
+ nbi = d->prevnbi;
+ cai = d->prevcai + 1;
+
+ for ( ; nbi < d->ngridnb; ++nbi)
+ {
+ ivec cell;
+
+ ivec_add(d->testcell, d->gnboffs[nbi], cell);
+ /* TODO: Support for 2D and screw PBC */
+ cell[XX] = (cell[XX] + d->ncelldim[XX]) % d->ncelldim[XX];
+ cell[YY] = (cell[YY] + d->ncelldim[YY]) % d->ncelldim[YY];
+ cell[ZZ] = (cell[ZZ] + d->ncelldim[ZZ]) % d->ncelldim[ZZ];
+ ci = grid_index(d, cell);
+ /* TODO: Calculate the required PBC shift outside the inner loop */
+ for ( ; cai < d->ncatoms[ci]; ++cai)
+ {
+ i = d->catom[ci][cai];
+ if (is_excluded(d, i))
+ {
+ continue;
+ }
+ pbc_dx_aiuc(d->pbc, d->xtest, d->xref[i], dx);
+ r2 = norm2(dx);
+ if (r2 <= d->cutoff2)
+ {
+ if (action(d, i, r2))
+ {
+ d->prevnbi = nbi;
+ d->prevcai = cai;
+ d->previ = i;
+ return TRUE;
+ }
+ }
+ }
+ d->exclind = 0;
+ cai = 0;
+ }
+ }
+ else
+ {
+ i = d->previ + 1;
+ for ( ; i < d->nref; ++i)
{
- return TRUE;
+ if (is_excluded(d, i))
+ {
+ continue;
+ }
+ if (d->pbc)
+ {
+ pbc_dx(d->pbc, d->xtest, d->xref[i], dx);
+ }
+ else
+ {
+ rvec_sub(d->xtest, d->xref[i], dx);
+ }
+ r2 = norm2(dx);
+ if (r2 <= d->cutoff2)
+ {
+ if (action(d, i, r2))
+ {
+ d->previ = i;
+ return TRUE;
+ }
+ }
}
}
return FALSE;
}
+/*! \brief
+ * Helper function to use with grid_search() to find the next neighbor.
+ *
+ * Simply breaks the loop on the first found neighbor.
+ */
+static bool
+within_action(gmx_ana_nbsearch_t *d, int i, real r2)
+{
+ return TRUE;
+}
+
+/*! \brief
+ * Helper function to use with grid_search() to find the minimum distance.
+ */
+static bool
+mindist_action(gmx_ana_nbsearch_t *d, int i, real r2)
+{
+ d->cutoff2 = r2;
+ return FALSE;
+}
+
+/*!
+ * \param[in] d Neighborhood search data structure.
+ * \param[in] x Test position.
+ * \returns TRUE if \p x is within the cutoff of any reference position,
+ * FALSE otherwise.
+ */
+bool
+gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, rvec x)
+{
+ grid_search_start(d, x);
+ return grid_search(d, &within_action);
+}
+
/*!
* \param[in] d Neighborhood search data structure.
* \param[in] p Test positions.
real
gmx_ana_nbsearch_mindist(gmx_ana_nbsearch_t *d, rvec x)
{
- int i;
- rvec dx;
- real d2, mind2;
+ real mind;
- mind2 = d->cutoff2;
- for (i = 0; i < d->nref; ++i)
- {
- if (d->pbc)
- {
- pbc_dx(d->pbc, x, d->xref[i], dx);
- }
- else
- {
- rvec_sub(x, d->xref[i], dx);
- }
- d2 = norm2(dx);
- if (d2 < mind2)
- {
- mind2 = d2;
- }
- }
- return sqrt(mind2);
+ grid_search_start(d, x);
+ grid_search(d, &mindist_action);
+ mind = sqrt(d->cutoff2);
+ d->cutoff2 = sqr(d->cutoff);
+ return mind;
}
/*!
{
return gmx_ana_nbsearch_mindist(d, p->x[i]);
}
+
+/*!
+ * \param[in] d Neighborhood search data structure.
+ * \param[in] n Number of test positions in \p x.
+ * \param[in] x Test positions.
+ * \param[out] jp Index of the reference position in the first pair.
+ * \returns TRUE if there are positions within the cutoff.
+ */
+bool
+gmx_ana_nbsearch_first_within(gmx_ana_nbsearch_t *d, rvec x, int *jp)
+{
+ grid_search_start(d, x);
+ return gmx_ana_nbsearch_next_within(d, jp);
+}
+
+/*!
+ * \param[in] d Neighborhood search data structure.
+ * \param[in] p Test positions.
+ * \param[in] i Use the i'th position in \p p.
+ * \param[out] jp Index of the reference position in the first pair.
+ * \returns TRUE if there are positions within the cutoff.
+ */
+bool
+gmx_ana_nbsearch_pos_first_within(gmx_ana_nbsearch_t *d, gmx_ana_pos_t *p,
+ int i, int *jp)
+{
+ return gmx_ana_nbsearch_first_within(d, p->x[i], jp);
+}
+
+/*!
+ * \param[in] d Neighborhood search data structure.
+ * \param[out] jp Index of the test position in the next pair.
+ * \returns TRUE if there are positions within the cutoff.
+ */
+bool
+gmx_ana_nbsearch_next_within(gmx_ana_nbsearch_t *d, int *jp)
+{
+ if (grid_search(d, &within_action))
+ {
+ *jp = d->previ;
+ return TRUE;
+ }
+ *jp = -1;
+ return FALSE;
+}
gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p)
{
gmx_ana_indexmap_init(&p->m, &pc->gmax, pc->coll->top, pc->itype);
+ if (!(pc->flags & POS_DYNAMIC))
+ {
+ gmx_ana_indexmap_set_static(&p->m, &pc->b);
+ }
gmx_ana_pos_reserve(p, p->m.nr, 0);
if (pc->flags & POS_VELOCITIES)
{
}
}
/* Free the block data for dynamic calculations */
- if ((pc->flags & POS_DYNAMIC) && pc->b.nalloc_index > 0)
+ if (pc->flags & POS_DYNAMIC)
{
- sfree(pc->b.index);
- sfree(pc->b.a);
- pc->b.nalloc_index = 0;
- pc->b.nalloc_a = 0;
+ if (pc->b.nalloc_index > 0)
+ {
+ sfree(pc->b.index);
+ pc->b.nalloc_index = 0;
+ }
+ if (pc->b.nalloc_a > 0)
+ {
+ sfree(pc->b.a);
+ pc->b.nalloc_a = 0;
+ }
}
pc = pc->next;
}
bool bPBC;
/** Name of the trajectory file (NULL if not provided). */
- const char *trjfile;
+ char *trjfile;
/** Name of the topology file (NULL if no topology loaded). */
- const char *topfile;
+ char *topfile;
/** Non-NULL name of the topology file. */
- const char *topfile_notnull;
+ char *topfile_notnull;
/** Name of the index file (NULL if no index file provided). */
- const char *ndxfile;
+ char *ndxfile;
/** Name of the selection file (NULL if no file provided). */
- const char *selfile;
+ char *selfile;
/** The selection string (NULL if not provided). */
- const char *selection;
+ char *selection;
/** The topology structure, or \p NULL if no topology loaded. */
t_topology *top;
/** The current frame, or \p NULL if no frame loaded yet. */
t_trxframe *fr;
/** Used to store the status variable from read_first_frame(). */
- int status;
+ t_trxstatus *status;
/** The number of frames read. */
int nframes;
*data = NULL;
return rc;
}
- d->status = -1;
+ d->status = NULL;
d->oenv = NULL;
*data = d;
{
int i;
+ sfree(d->trjfile);
+ sfree(d->topfile);
+ sfree(d->topfile_notnull);
+ sfree(d->ndxfile);
+ sfree(d->selfile);
if (d->top)
{
done_top(d->top);
gmx_ana_selcollection_free(d->sc);
gmx_ana_poscalc_coll_free(d->pcc);
sfree(d->grpnames);
+ output_env_done(d->oenv);
sfree(d);
}
size_t i;
int k;
int rc;
+ const char *tmp_fnm;
t_filenm def_fnm[] = {
{efTRX, NULL, NULL, ffOPTRD},
ndesc, desc, nbugs, bugs,oenv);
d->oenv = *oenv;
- /* Copy the results back */
- for (k = 0; k < nfile; ++k)
- {
- memcpy(&(fnm[k]), &(all_fnm[fnm_map[k]]), sizeof(fnm[k]));
- }
- for (i = 0, k = npall - npargs; i < (size_t)npargs; ++i, ++k)
- {
- memcpy(&(pa[i]), &(all_pa[k]), sizeof(pa[i]));
- }
-
- d->trjfile = ftp2fn_null(efTRX, nfall, all_fnm);
- d->topfile = ftp2fn_null(efTPS, nfall, all_fnm);
- d->topfile_notnull = ftp2fn(efTPS, nfall, all_fnm);
- d->ndxfile = ftp2fn_null(efNDX, nfall, all_fnm);
+ /* Process our own options.
+ * Make copies of file names for easier memory management. */
+ tmp_fnm = ftp2fn_null(efTRX, nfall, all_fnm);
+ d->trjfile = tmp_fnm ? strdup(tmp_fnm) : NULL;
+ tmp_fnm = ftp2fn_null(efTPS, nfall, all_fnm);
+ d->topfile = tmp_fnm ? strdup(tmp_fnm) : NULL;
+ d->topfile_notnull = strdup(ftp2fn(efTPS, nfall, all_fnm));
+ tmp_fnm = ftp2fn_null(efNDX, nfall, all_fnm);
+ d->ndxfile = tmp_fnm ? strdup(tmp_fnm) : NULL;
if (!(d->flags & ANA_NOUSER_RMPBC))
{
d->bRmPBC = bRmPBC;
d->bPBC = bPBC;
}
d->selection = selection;
- d->selfile = opt2fn_null("-sf", nfall, all_fnm);
+ tmp_fnm = opt2fn_null("-sf", nfall, all_fnm);
+ d->selfile = tmp_fnm ? strdup(tmp_fnm) : NULL;
+ /* Copy the results back */
+ for (k = 0; k < nfile; ++k)
+ {
+ memcpy(&(fnm[k]), &(all_fnm[fnm_map[k]]), sizeof(fnm[k]));
+ /* Delegate responsibility of freeing the file names to caller. */
+ all_fnm[fnm_map[k]].nfiles = 0;
+ all_fnm[fnm_map[k]].fns = NULL;
+ }
+ for (i = 0, k = npall - npargs; i < (size_t)npargs; ++i, ++k)
+ {
+ memcpy(&(pa[i]), &(all_pa[k]), sizeof(pa[i]));
+ }
+
+ /* Free memory we have allocated. */
+ done_filenms(nfall, all_fnm);
sfree(all_fnm);
sfree(fnm_map);
sfree(all_pa);
t_pbc pbc;
t_pbc *ppbc;
int rc;
-
+ gmx_rmpbc_t gpbc=NULL;
+
rc = init_first_frame(d);
if (rc != 0)
{
{
d->bRmPBC = FALSE;
}
-
+ if (d->bRmPBC)
+ {
+ gpbc = gmx_rmpbc_init(&d->top->idef,d->ePBC,d->fr->natoms,d->fr->box);
+ }
d->nframes = 0;
do
{
if (d->bRmPBC)
{
- rm_pbc(&d->top->idef, d->ePBC, d->fr->natoms, d->fr->box,
- d->fr->x, d->fr->x);
+ gmx_rmpbc(gpbc,d->fr->box,d->fr->x, d->fr->x);
}
if (ppbc)
{
d->nframes++;
}
while (d->trjfile && read_next_frame(d->oenv, d->status, d->fr));
-
+ if (d->bRmPBC)
+ {
+ gmx_rmpbc_done(gpbc);
+ }
if (d->trjfile)
{
close_trj(d->status);
return nflsize;
}
-static bool do_trnheader(int fp,bool bRead,t_trnheader *sh, bool *bOK)
+static bool do_trnheader(t_fileio *fio,bool bRead,t_trnheader *sh, bool *bOK)
{
- const int magic=GROMACS_MAGIC;
- const char *version = "GMX_trn_file";
+ int magic=GROMACS_MAGIC;
static bool bFirst=TRUE;
char buf[256];
*bOK=TRUE;
- gmx_fio_select(fp);
- if (!do_int(magic))
+ gmx_fio_checktype(fio);
+
+ if (!gmx_fio_do_int(fio,magic) || magic!=GROMACS_MAGIC)
return FALSE;
if (bRead) {
- *bOK = *bOK && do_string(buf);
+ *bOK = *bOK && gmx_fio_do_string(fio,buf);
if (bFirst)
fprintf(stderr,"trn version: %s ",buf);
}
- else
- *bOK = *bOK && do_string(version);
- *bOK = *bOK && do_int(sh->ir_size);
- *bOK = *bOK && do_int(sh->e_size);
- *bOK = *bOK && do_int(sh->box_size);
- *bOK = *bOK && do_int(sh->vir_size);
- *bOK = *bOK && do_int(sh->pres_size);
- *bOK = *bOK && do_int(sh->top_size);
- *bOK = *bOK && do_int(sh->sym_size);
- *bOK = *bOK && do_int(sh->x_size);
- *bOK = *bOK && do_int(sh->v_size);
- *bOK = *bOK && do_int(sh->f_size);
- *bOK = *bOK && do_int(sh->natoms);
+ else {
+ sprintf(buf,"GMX_trn_file");
+ *bOK = *bOK && gmx_fio_do_string(fio,buf);
+ }
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->ir_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->e_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->box_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->vir_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->pres_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->top_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->sym_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->x_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->v_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->f_size);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->natoms);
if (!*bOK) return *bOK;
sh->bDouble = (nFloatSize(sh) == sizeof(double));
- gmx_fio_setprecision(fp,sh->bDouble);
+ gmx_fio_setprecision(fio,sh->bDouble);
if (bRead && bFirst) {
fprintf(stderr,"(%s precision)\n",sh->bDouble ? "double" : "single");
bFirst = FALSE;
}
- *bOK = *bOK && do_int(sh->step);
- *bOK = *bOK && do_int(sh->nre);
- *bOK = *bOK && do_real(sh->t);
- *bOK = *bOK && do_real(sh->lambda);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->step);
+ *bOK = *bOK && gmx_fio_do_int(fio,sh->nre);
+ *bOK = *bOK && gmx_fio_do_real(fio,sh->t);
+ *bOK = *bOK && gmx_fio_do_real(fio,sh->lambda);
return *bOK;
}
}
}
-static bool do_htrn(int fp,bool bRead,t_trnheader *sh,
+static bool do_htrn(t_fileio *fio,bool bRead,t_trnheader *sh,
rvec *box,rvec *x,rvec *v,rvec *f)
{
matrix pv;
bool bOK;
bOK = TRUE;
- if (sh->box_size != 0) bOK = bOK && ndo_rvec(box,DIM);
- if (sh->vir_size != 0) bOK = bOK && ndo_rvec(pv,DIM);
- if (sh->pres_size!= 0) bOK = bOK && ndo_rvec(pv,DIM);
- if (sh->x_size != 0) bOK = bOK && ndo_rvec(x,sh->natoms);
- if (sh->v_size != 0) bOK = bOK && ndo_rvec(v,sh->natoms);
- if (sh->f_size != 0) bOK = bOK && ndo_rvec(f,sh->natoms);
+ if (sh->box_size != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,box,DIM);
+ if (sh->vir_size != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,pv,DIM);
+ if (sh->pres_size!= 0) bOK = bOK && gmx_fio_ndo_rvec(fio,pv,DIM);
+ if (sh->x_size != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,x,sh->natoms);
+ if (sh->v_size != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,v,sh->natoms);
+ if (sh->f_size != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,f,sh->natoms);
return bOK;
}
-static bool do_trn(int fp,bool bRead,int *step,real *t,real *lambda,
+static bool do_trn(t_fileio *fio,bool bRead,int *step,real *t,real *lambda,
rvec *box,int *natoms,rvec *x,rvec *v,rvec *f)
{
t_trnheader *sh;
sh->t = *t;
sh->lambda = *lambda;
}
- if (!do_trnheader(fp,bRead,sh,&bOK))
+ if (!do_trnheader(fio,bRead,sh,&bOK))
return FALSE;
if (bRead) {
*natoms = sh->natoms;
if (sh->sym_size)
gmx_file("symbol table in trn file");
}
- bOK = do_htrn(fp,bRead,sh,box,x,v,f);
+ bOK = do_htrn(fio,bRead,sh,box,x,v,f);
sfree(sh);
void read_trnheader(const char *fn,t_trnheader *trn)
{
- int fp;
+ t_fileio *fio;
bool bOK;
- fp = open_trn(fn,"r");
- if (!do_trnheader(fp,TRUE,trn,&bOK))
+ fio = open_trn(fn,"r");
+ if (!do_trnheader(fio,TRUE,trn,&bOK))
gmx_fatal(FARGS,"Empty file %s",fn);
- close_trn(fp);
+ close_trn(fio);
}
-bool fread_trnheader(int fp,t_trnheader *trn, bool *bOK)
+bool fread_trnheader(t_fileio *fio,t_trnheader *trn, bool *bOK)
{
- return do_trnheader(fp,TRUE,trn,bOK);
+ return do_trnheader(fio,TRUE,trn,bOK);
}
void write_trn(const char *fn,int step,real t,real lambda,
rvec *box,int natoms,rvec *x,rvec *v,rvec *f)
{
- int fp;
+ t_fileio *fio;
- fp = open_trn(fn,"w");
- do_trn(fp,FALSE,&step,&t,&lambda,box,&natoms,x,v,f);
- close_trn(fp);
+ fio = open_trn(fn,"w");
+ do_trn(fio,FALSE,&step,&t,&lambda,box,&natoms,x,v,f);
+ close_trn(fio);
}
void read_trn(const char *fn,int *step,real *t,real *lambda,
rvec *box,int *natoms,rvec *x,rvec *v,rvec *f)
{
- int fp;
+ t_fileio *fio;
- fp = open_trn(fn,"r");
- (void) do_trn(fp,TRUE,step,t,lambda,box,natoms,x,v,f);
- close_trn(fp);
+ fio = open_trn(fn,"r");
+ (void) do_trn(fio,TRUE,step,t,lambda,box,natoms,x,v,f);
+ close_trn(fio);
}
-void fwrite_trn(int fp,int step,real t,real lambda,
+void fwrite_trn(t_fileio *fio,int step,real t,real lambda,
rvec *box,int natoms,rvec *x,rvec *v,rvec *f)
{
- if( do_trn(fp,FALSE,&step,&t,&lambda,box,&natoms,x,v,f) == FALSE)
+ if( do_trn(fio,FALSE,&step,&t,&lambda,box,&natoms,x,v,f) == FALSE)
{
- gmx_file("Cannot write trajectory frame; maybe you are out of quota?");
+ gmx_file("Cannot write trajectory frame; maybe you are out of quota?");
}
}
-bool fread_trn(int fp,int *step,real *t,real *lambda,
+bool fread_trn(t_fileio *fio,int *step,real *t,real *lambda,
rvec *box,int *natoms,rvec *x,rvec *v,rvec *f)
{
- return do_trn(fp,TRUE,step,t,lambda,box,natoms,x,v,f);
+ return do_trn(fio,TRUE,step,t,lambda,box,natoms,x,v,f);
}
-bool fread_htrn(int fp,t_trnheader *trn,rvec *box,rvec *x,rvec *v,rvec *f)
+bool fread_htrn(t_fileio *fio,t_trnheader *trn,rvec *box,rvec *x,rvec *v,
+ rvec *f)
{
- return do_htrn(fp,TRUE,trn,box,x,v,f);
+ return do_htrn(fio,TRUE,trn,box,x,v,f);
}
-int open_trn(const char *fn,const char *mode)
+t_fileio *open_trn(const char *fn,const char *mode)
{
return gmx_fio_open(fn,mode);
}
-void close_trn(int fp)
+void close_trn(t_fileio *fio)
{
- gmx_fio_close(fp);
+ gmx_fio_close(fio);
}
#include <math.h>
/* defines for frame counter output */
-static int __frame=NOTSET;
#define SKIP1 10
#define SKIP2 100
#define SKIP3 1000
-#define INITCOUNT __frame=-1
+/* Globals for gromos-87 input */
+typedef enum { effXYZ, effXYZBox, effG87, effG87Box, effNR } eFileFormat;
-/* frames for read_first/next_x */
-static t_trxframe *xframe=NULL;
-static int nxframe=0;
+struct t_trxstatus
+{
+ int __frame;
+ t_trxframe *xframe;
+ int nxframe;
+ t_fileio *fio;
+ eFileFormat eFF;
+ int NATOMS;
+ double DT,BOX[3];
+ bool bReadBox;
+};
+
+static void initcount(t_trxstatus *status)
+{
+ status->__frame=-1;
+}
+static void status_init(t_trxstatus *status)
+{
+ status->nxframe=0;
+ status->xframe=NULL;
+ status->fio=NULL;
+ status->__frame=-1;
+}
-int nframes_read(void)
+
+int nframes_read(t_trxstatus *status)
{
- return __frame;
+ return status->__frame;
}
-static void printcount_(const output_env_t oenv,const char *l,real t)
+static void printcount_(t_trxstatus *status, const output_env_t oenv,
+ const char *l,real t)
{
- if ((__frame < 2*SKIP1 || __frame % SKIP1 == 0) &&
- (__frame < 2*SKIP2 || __frame % SKIP2 == 0) &&
- (__frame < 2*SKIP3 || __frame % SKIP3 == 0))
- fprintf(stderr,"\r%-14s %6d time %8.3f ",l,__frame,output_env_conv_time(oenv,t));
+ if ((status->__frame < 2*SKIP1 || status->__frame % SKIP1 == 0) &&
+ (status->__frame < 2*SKIP2 || status->__frame % SKIP2 == 0) &&
+ (status->__frame < 2*SKIP3 || status->__frame % SKIP3 == 0))
+ fprintf(stderr,"\r%-14s %6d time %8.3f ",l,status->__frame,
+ output_env_conv_time(oenv,t));
}
-static void printcount(const output_env_t oenv,real t,bool bSkip)
+static void printcount(t_trxstatus *status, const output_env_t oenv,real t,
+ bool bSkip)
{
- __frame++;
- printcount_(oenv,bSkip ? "Skipping frame" : "Reading frame",t);
+ status->__frame++;
+ printcount_(status, oenv,bSkip ? "Skipping frame" : "Reading frame",t);
}
-static void printlast(const output_env_t oenv,real t)
+static void printlast(t_trxstatus *status, const output_env_t oenv,real t)
{
- printcount_(oenv,"Last frame",t);
+ printcount_(status, oenv,"Last frame",t);
fprintf(stderr,"\n");
}
-static void printincomp(t_trxframe *fr)
+static void printincomp(t_trxstatus *status, t_trxframe *fr)
{
if (fr->not_ok & HEADER_NOT_OK)
fprintf(stderr,"WARNING: Incomplete header: nr %d time %g\n",
- __frame+1,fr->time);
+ status->__frame+1,fr->time);
else if (fr->not_ok)
fprintf(stderr,"WARNING: Incomplete frame: nr %d time %g\n",
- __frame+1,fr->time);
+ status->__frame+1,fr->time);
}
int prec2ndec(real prec)
return (int)(log(prec)/log(10.0)+0.5);
}
-/* Globals for gromos-87 input */
-typedef enum { effXYZ, effXYZBox, effG87, effG87Box, effNR } eFileFormat;
-static eFileFormat eFF;
-static int NATOMS;
-static double DT,BOX[3];
-static bool bReadBox;
+
+t_fileio *trx_get_fileio(t_trxstatus *status)
+{
+ return status->fio;
+}
+
+
void clear_trxframe(t_trxframe *fr,bool bFirst)
{
fr->ePBC = ePBC;
}
-int write_trxframe_indexed(int fnum,t_trxframe *fr,int nind,atom_id *ind,
- gmx_conect gc)
+int write_trxframe_indexed(t_trxstatus *status,t_trxframe *fr,int nind,
+ atom_id *ind, gmx_conect gc)
{
char title[STRLEN];
rvec *xout=NULL,*vout=NULL,*fout=NULL;
else
prec = 1000.0;
- switch (gmx_fio_getftp(fnum)) {
+ switch (gmx_fio_getftp(status->fio)) {
case efTRJ:
case efTRR:
break;
default:
if (!fr->bX)
gmx_fatal(FARGS,"Need coordinates to write a %s trajectory",
- ftp2ext(gmx_fio_getftp(fnum)));
+ ftp2ext(gmx_fio_getftp(status->fio)));
break;
}
- switch (gmx_fio_getftp(fnum)) {
+ switch (gmx_fio_getftp(status->fio)) {
case efTRJ:
case efTRR:
if (fr->bV) {
break;
}
- switch (gmx_fio_getftp(fnum)) {
+ switch (gmx_fio_getftp(status->fio)) {
case efXTC:
- write_xtc(fnum,nind,fr->step,fr->time,fr->box,xout,prec);
+ write_xtc(status->fio,nind,fr->step,fr->time,fr->box,xout,prec);
break;
case efTRJ:
case efTRR:
- fwrite_trn(fnum,nframes_read(),
+ fwrite_trn(status->fio,nframes_read(status),
fr->time,fr->step,fr->box,nind,xout,vout,fout);
break;
case efGRO:
case efENT:
if (!fr->bAtoms)
gmx_fatal(FARGS,"Can not write a %s file without atom names",
- ftp2ext(gmx_fio_getftp(fnum)));
+ ftp2ext(gmx_fio_getftp(status->fio)));
sprintf(title,"frame t= %.3f",fr->time);
- if (gmx_fio_getftp(fnum) == efGRO)
- write_hconf_indexed_p(gmx_fio_getfp(fnum),title,fr->atoms,nind,ind,
+ if (gmx_fio_getftp(status->fio) == efGRO)
+ write_hconf_indexed_p(gmx_fio_getfp(status->fio),title,fr->atoms,nind,ind,
prec2ndec(prec),
fr->x,fr->bV ? fr->v : NULL,fr->box);
else
- write_pdbfile_indexed(gmx_fio_getfp(fnum),title,fr->atoms,
+ write_pdbfile_indexed(gmx_fio_getfp(status->fio),title,fr->atoms,
fr->x,-1,fr->box,0,fr->step,nind,ind,gc);
break;
case efG87:
- write_gms(gmx_fio_getfp(fnum),nind,xout,fr->box);
+ write_gms(gmx_fio_getfp(status->fio),nind,xout,fr->box);
break;
case efG96:
- write_g96_conf(gmx_fio_getfp(fnum),fr,nind,ind);
+ write_g96_conf(gmx_fio_getfp(status->fio),fr,nind,ind);
break;
default:
gmx_fatal(FARGS,"Sorry, write_trxframe_indexed can not write %s",
- ftp2ext(gmx_fio_getftp(fnum)));
+ ftp2ext(gmx_fio_getftp(status->fio)));
break;
}
- switch (gmx_fio_getftp(fnum)) {
+ switch (gmx_fio_getftp(status->fio)) {
case efTRN:
case efTRJ:
case efTRR:
return 0;
}
-int write_trxframe(int fnum,t_trxframe *fr,gmx_conect gc)
+int write_trxframe(t_trxstatus *status,t_trxframe *fr,gmx_conect gc)
{
char title[STRLEN];
real prec;
else
prec = 1000.0;
- switch (gmx_fio_getftp(fnum)) {
+ switch (gmx_fio_getftp(status->fio)) {
case efTRJ:
case efTRR:
break;
default:
if (!fr->bX)
gmx_fatal(FARGS,"Need coordinates to write a %s trajectory",
- ftp2ext(gmx_fio_getftp(fnum)));
+ ftp2ext(gmx_fio_getftp(status->fio)));
break;
}
- switch (gmx_fio_getftp(fnum)) {
+ switch (gmx_fio_getftp(status->fio)) {
case efXTC:
- write_xtc(fnum,fr->natoms,fr->step,fr->time,fr->box,fr->x,prec);
+ write_xtc(status->fio,fr->natoms,fr->step,fr->time,fr->box,fr->x,prec);
break;
case efTRJ:
case efTRR:
- fwrite_trn(fnum,fr->step,fr->time,fr->lambda,fr->box,fr->natoms,
+ fwrite_trn(status->fio,fr->step,fr->time,fr->lambda,fr->box,fr->natoms,
fr->bX ? fr->x:NULL,fr->bV ? fr->v:NULL ,fr->bF ? fr->f:NULL);
break;
case efGRO:
case efENT:
if (!fr->bAtoms)
gmx_fatal(FARGS,"Can not write a %s file without atom names",
- ftp2ext(gmx_fio_getftp(fnum)));
+ ftp2ext(gmx_fio_getftp(status->fio)));
sprintf(title,"frame t= %.3f",fr->time);
- if (gmx_fio_getftp(fnum) == efGRO)
- write_hconf_p(gmx_fio_getfp(fnum),title,fr->atoms,
+ if (gmx_fio_getftp(status->fio) == efGRO)
+ write_hconf_p(gmx_fio_getfp(status->fio),title,fr->atoms,
prec2ndec(prec),fr->x,fr->bV ? fr->v : NULL,fr->box);
else
- write_pdbfile(gmx_fio_getfp(fnum),title,
+ write_pdbfile(gmx_fio_getfp(status->fio),title,
fr->atoms,fr->x,fr->bPBC ? fr->ePBC : -1,fr->box,
0,fr->step,gc);
break;
case efG87:
- write_gms(gmx_fio_getfp(fnum),fr->natoms,fr->x,fr->box);
+ write_gms(gmx_fio_getfp(status->fio),fr->natoms,fr->x,fr->box);
break;
case efG96:
- write_g96_conf(gmx_fio_getfp(fnum),fr,-1,NULL);
+ write_g96_conf(gmx_fio_getfp(status->fio),fr,-1,NULL);
break;
default:
gmx_fatal(FARGS,"Sorry, write_trxframe can not write %s",
- ftp2ext(gmx_fio_getftp(fnum)));
+ ftp2ext(gmx_fio_getftp(status->fio)));
break;
}
return 0;
}
-int write_trx(int fnum,int nind,atom_id *ind,t_atoms *atoms,
+int write_trx(t_trxstatus *status,int nind,atom_id *ind,t_atoms *atoms,
int step,real time,matrix box,rvec x[],rvec *v,
gmx_conect gc)
{
fr.bBox = TRUE;
copy_mat(box,fr.box);
- return write_trxframe_indexed(fnum,&fr,nind,ind,gc);
+ return write_trxframe_indexed(status,&fr,nind,ind,gc);
}
-void close_trx(int status)
+void close_trx(t_trxstatus *status)
{
- gmx_fio_close(status);
+ gmx_fio_close(status->fio);
+ sfree(status);
}
-int open_trx(const char *outfile,const char *filemode)
+t_trxstatus *open_trx(const char *outfile,const char *filemode)
{
- if (filemode[0]!='w' && filemode[0]!='a' && filemode[1]!='+')
- gmx_fatal(FARGS,"Sorry, write_trx can only write");
+ t_trxstatus *stat;
+ if (filemode[0]!='w' && filemode[0]!='a' && filemode[1]!='+')
+ gmx_fatal(FARGS,"Sorry, write_trx can only write");
+
+ snew(stat,1);
+ status_init(stat);
- return gmx_fio_open(outfile,filemode);
+ stat->fio=gmx_fio_open(outfile,filemode);
+ return stat;
}
-static bool gmx_next_frame(int status,t_trxframe *fr)
+static bool gmx_next_frame(t_trxstatus *status,t_trxframe *fr)
{
t_trnheader sh;
bool bOK,bRet;
bRet = FALSE;
- if (fread_trnheader(status,&sh,&bOK)) {
+ if (fread_trnheader(status->fio,&sh,&bOK)) {
fr->bDouble=sh.bDouble;
fr->natoms=sh.natoms;
fr->bStep=TRUE;
snew(fr->f,sh.natoms);
fr->bF = sh.f_size>0;
}
- if (fread_htrn(status,&sh,fr->box,fr->x,fr->v,fr->f))
+ if (fread_htrn(status->fio,&sh,fr->box,fr->x,fr->v,fr->f))
bRet = TRUE;
else
fr->not_ok = DATA_NOT_OK;
return bRet;
}
-static void choose_ff(FILE *status)
+static void choose_ff(FILE *fp)
{
int i,m,c;
int rc;
+ eFileFormat eFF;
+ t_trxstatus *stat;
printf("\n\n");
printf(" Select File Format\n");
printf("3. Gromos-87 Ascii Trajectory\n");
printf("4. Gromos-87 Ascii Trajectory with Box\n");
+ snew(stat,1);
+ status_init(stat);
+
do {
printf("\nChoice: ");
fflush(stdout);
} while ((i < 0) || (i >= effNR));
printf("\n");
- eFF = (eFileFormat) i;
+ stat->eFF = (eFileFormat) i;
- for(m=0; (m<DIM); m++) BOX[m]=0;
+ for(m=0; (m<DIM); m++) stat->BOX[m]=0;
- bReadBox = (eFF == effG87Box) || (eFF == effXYZBox);
+ stat->bReadBox = (stat->eFF == effG87Box) || (stat->eFF == effXYZBox);
- switch (eFF) {
+ switch (stat->eFF) {
case effXYZ:
case effXYZBox:
- if( 5 != fscanf(status,"%d%lf%lf%lf%lf",&NATOMS,&BOX[XX],&BOX[YY],&BOX[ZZ],&DT))
+ if( 5 != fscanf(fp,"%d%lf%lf%lf%lf",&stat->NATOMS,&stat->BOX[XX],&stat->BOX[YY],&stat->BOX[ZZ],&stat->DT))
{
gmx_fatal(FARGS,"Error reading natoms/box in file");
}
printf("GROMOS! OH DEAR...\n\n");
printf("Number of atoms ? ");
fflush(stdout);
- if (1 != scanf("%d",&NATOMS))
+ if (1 != scanf("%d",&stat->NATOMS))
{
gmx_fatal(FARGS,"Error reading natoms in file");
}
printf("Time between timeframes ? ");
fflush(stdout);
- if( 1 != scanf("%lf",&DT))
+ if( 1 != scanf("%lf",&stat->DT))
{
gmx_fatal(FARGS,"Error reading dt from file");
}
- if (eFF == effG87) {
+ if (stat->eFF == effG87) {
printf("Box X Y Z ? ");
fflush(stdout);
- if(3 != scanf("%lf%lf%lf",&BOX[XX],&BOX[YY],&BOX[ZZ]))
+ if(3 != scanf("%lf%lf%lf",&stat->BOX[XX],&stat->BOX[YY],&stat->BOX[ZZ]))
{
gmx_fatal(FARGS,"Error reading box in file");
}
}
do {
- c=fgetc(status);
+ c=fgetc(fp);
printf("%c",c);
} while (c != '\n');
printf("\n");
}
}
-static bool do_read_xyz(FILE *status,int natoms,rvec x[],matrix box)
+static bool do_read_xyz(t_trxstatus *status, FILE *fp,int natoms,
+ rvec x[],matrix box)
{
int i,m;
double x0;
for(i=0; (i<natoms); i++) {
for(m=0; (m<DIM); m++) {
- if (fscanf(status,"%lf",&x0) != 1) {
+ if (fscanf(fp,"%lf",&x0) != 1) {
if (i || m)
fprintf(stderr,"error reading statusfile: x[%d][%d]\n",i,m);
/* else eof! */
x[i][m]=x0;
}
}
- if (bReadBox) {
+ if (status->bReadBox) {
for(m=0; (m<DIM); m++) {
- if (fscanf(status,"%lf",&x0) != 1)
+ if (fscanf(fp,"%lf",&x0) != 1)
return FALSE;
box[m][m]=x0;
}
return TRUE;
}
-static bool xyz_next_x(FILE *status, const output_env_t oenv,
+static bool xyz_next_x(t_trxstatus *status, FILE *fp, const output_env_t oenv,
real *t, int natoms, rvec x[], matrix box)
/* Reads until a new x can be found (return TRUE)
* or eof (return FALSE)
pt=*t;
while (!bTimeSet(TBEGIN) || (*t < rTimeValue(TBEGIN))) {
- if (!do_read_xyz(status,natoms,x,box))
+ if (!do_read_xyz(status,fp,natoms,x,box))
return FALSE;
- printcount(oenv,*t,FALSE);
- *t+=DT;
+ printcount(status,oenv,*t,FALSE);
+ *t+=status->DT;
pt=*t;
}
if (!bTimeSet(TEND) || (*t <= rTimeValue(TEND))) {
- if (!do_read_xyz(status,natoms,x,box)) {
- printlast(oenv,*t);
+ if (!do_read_xyz(status,fp,natoms,x,box)) {
+ printlast(status, oenv,*t);
return FALSE;
}
- printcount(oenv,*t,FALSE);
+ printcount(status,oenv,*t,FALSE);
pt=*t;
- *t+=DT;
+ *t+=status->DT;
return TRUE;
}
- printlast(oenv,pt);
+ printlast(status,oenv,pt);
return FALSE;
}
-static int xyz_first_x(FILE *status, const output_env_t oenv,
+static int xyz_first_x(t_trxstatus *status, FILE *fp, const output_env_t oenv,
real *t, rvec **x, matrix box)
-/* Reads status, mallocs x, and returns x and box
- * Returns natoms when succesful, FALSE otherwise
+/* Reads fp, mallocs x, and returns x and box
+ * Returns natoms when successful, FALSE otherwise
*/
{
int m;
- INITCOUNT;
+ initcount(status);
clear_mat(box);
- choose_ff(status);
+ choose_ff(fp);
for(m=0; (m<DIM); m++)
- box[m][m]=BOX[m];
+ box[m][m]=status->BOX[m];
- snew(*x,NATOMS);
- *t=DT;
- if (!xyz_next_x(status,oenv,t,NATOMS,*x,box))
+ snew(*x,status->NATOMS);
+ *t=status->DT;
+ if (!xyz_next_x(status, fp,oenv,t,status->NATOMS,*x,box))
return 0;
*t=0.0;
- return NATOMS;
+ return status->NATOMS;
}
-static bool pdb_next_x(FILE *status,t_trxframe *fr)
+static bool pdb_next_x(t_trxstatus *status, FILE *fp,t_trxframe *fr)
{
t_atoms atoms;
matrix boxpdb;
atoms.pdbinfo=NULL;
/* the other pointers in atoms should not be accessed if these are NULL */
model_nr=NOTSET;
- na=read_pdbfile(status,title,&model_nr,&atoms,fr->x,&ePBC,boxpdb,TRUE,NULL);
+ na=read_pdbfile(fp,title,&model_nr,&atoms,fr->x,&ePBC,boxpdb,TRUE,NULL);
set_trxframe_ePBC(fr,ePBC);
- if (nframes_read()==0)
+ if (nframes_read(status)==0)
fprintf(stderr," '%s', %d atoms\n",title, fr->natoms);
fr->bPrec = TRUE;
fr->prec = 10000;
if (fr->bStep)
fr->time=(real)fr->step;
else
- fr->time=(real)nframes_read();
+ fr->time=(real)nframes_read(status);
}
if (na == 0) {
return FALSE;
} else {
if (na != fr->natoms)
gmx_fatal(FARGS,"Number of atoms in pdb frame %d is %d instead of %d",
- nframes_read(),na,fr->natoms);
+ nframes_read(status),na,fr->natoms);
return TRUE;
}
}
-static int pdb_first_x(FILE *status, t_trxframe *fr)
+static int pdb_first_x(t_trxstatus *status, FILE *fp, t_trxframe *fr)
{
- INITCOUNT;
+ initcount(status);
fprintf(stderr,"Reading frames from pdb file");
- frewind(status);
- get_pdb_coordnum(status, &fr->natoms);
+ frewind(fp);
+ get_pdb_coordnum(fp, &fr->natoms);
if (fr->natoms==0)
gmx_fatal(FARGS,"\nNo coordinates in pdb file\n");
- frewind(status);
+ frewind(fp);
snew(fr->x,fr->natoms);
- pdb_next_x(status, fr);
+ pdb_next_x(status, fp, fr);
return fr->natoms;
}
-bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr)
+bool read_next_frame(const output_env_t oenv,t_trxstatus *status,t_trxframe *fr)
{
real pt;
int ct;
bool bOK,bRet,bMissingData=FALSE,bSkip=FALSE;
+ int dummy=0;
bRet = FALSE;
pt=fr->time;
fr->tppf = fr->tpf;
fr->tpf = fr->time;
- switch (gmx_fio_getftp(status)) {
+ switch (gmx_fio_getftp(status->fio)) {
case efTRJ:
case efTRR:
bRet = gmx_next_frame(status,fr);
/* Checkpoint files can not contain mulitple frames */
break;
case efG96:
- read_g96_conf(gmx_fio_getfp(status),NULL,fr);
+ read_g96_conf(gmx_fio_getfp(status->fio),NULL,fr);
bRet = (fr->natoms > 0);
break;
case efG87:
- bRet = xyz_next_x(gmx_fio_getfp(status),oenv,&fr->time,fr->natoms,
- fr->x,fr->box);
+ bRet = xyz_next_x(status, gmx_fio_getfp(status->fio),oenv,&fr->time,
+ fr->natoms, fr->x,fr->box);
fr->bTime = bRet;
fr->bX = bRet;
fr->bBox = bRet;
* accuracy of the control over -b and -e options.
*/
if (bTimeSet(TBEGIN) && (fr->time < rTimeValue(TBEGIN))) {
- if (xtc_seek_time(rTimeValue(TBEGIN),status,fr->natoms)) {
+ if (xtc_seek_time(status->fio, rTimeValue(TBEGIN),fr->natoms)) {
gmx_fatal(FARGS,"Specified frame doesn't exist or file not seekable");
}
- INITCOUNT;
+ initcount(status);
}
- bRet = read_next_xtc(status,fr->natoms,&fr->step,&fr->time,fr->box,
+ bRet = read_next_xtc(status->fio,fr->natoms,&fr->step,&fr->time,fr->box,
fr->x,&fr->prec,&bOK);
fr->bPrec = (bRet && fr->prec > 0);
fr->bStep = bRet;
}
break;
case efPDB:
- bRet = pdb_next_x(gmx_fio_getfp(status),fr);
+ bRet = pdb_next_x(status, gmx_fio_getfp(status->fio),fr);
break;
case efGRO:
- bRet = gro_next_x_or_v(gmx_fio_getfp(status),fr);
+ bRet = gro_next_x_or_v(gmx_fio_getfp(status->fio),fr);
break;
default:
#ifdef GMX_DLOPEN
- bRet = read_next_vmd_frame(status,fr);
+ bRet = read_next_vmd_frame(dummy,fr);
#else
- gmx_fatal(FARGS,"DEATH HORROR in read_next_frame ftp=%s,status=%d",
- ftp2ext(gmx_fio_getftp(status)),status);
+ gmx_fatal(FARGS,"DEATH HORROR in read_next_frame ftp=%s,status=%s",
+ ftp2ext(gmx_fio_getftp(status->fio)),
+ gmx_fio_getname(status->fio));
#endif
}
if (!bMissingData) {
ct=check_times2(fr->time,fr->t0,fr->tpf,fr->tppf,fr->bDouble);
if (ct == 0 || (fr->flags & TRX_DONT_SKIP && ct<0)) {
- printcount(oenv,fr->time,FALSE);
+ printcount(status, oenv,fr->time,FALSE);
} else if (ct > 0)
bRet = FALSE;
else {
- printcount(oenv,fr->time,TRUE);
+ printcount(status, oenv,fr->time,TRUE);
bSkip = TRUE;
}
}
} while (bRet && (bMissingData || bSkip));
if (!bRet) {
- printlast(oenv,pt);
+ printlast(status, oenv,pt);
if (fr->not_ok)
- printincomp(fr);
+ printincomp(status, fr);
}
return bRet;
}
-int read_first_frame(const output_env_t oenv,int *status,
+int read_first_frame(const output_env_t oenv,t_trxstatus **status,
const char *fn,t_trxframe *fr,int flags)
{
- int fp;
+ t_fileio *fio;
bool bFirst,bOK;
+ int dummy=0;
clear_trxframe(fr,TRUE);
fr->flags = flags;
bFirst = TRUE;
- INITCOUNT;
+
+ snew((*status), 1);
+
+ status_init( *status );
+ (*status)->nxframe=1;
+ initcount(*status);
- fp = *status =gmx_fio_open(fn,"r");
- switch (gmx_fio_getftp(fp))
+ fio = (*status)->fio =gmx_fio_open(fn,"r");
+ switch (gmx_fio_getftp(fio))
{
case efTRJ:
case efTRR:
break;
case efCPT:
- read_checkpoint_trxframe(fp,fr);
+ read_checkpoint_trxframe(fio,fr);
bFirst = FALSE;
break;
case efG96:
/* Can not rewind a compressed file, so open it twice */
- read_g96_conf(gmx_fio_getfp(fp),fn,fr);
- gmx_fio_close(fp);
+ read_g96_conf(gmx_fio_getfp(fio),fn,fr);
+ gmx_fio_close(fio);
clear_trxframe(fr,FALSE);
if (flags & (TRX_READ_X | TRX_NEED_X))
snew(fr->x,fr->natoms);
if (flags & (TRX_READ_V | TRX_NEED_V))
snew(fr->v,fr->natoms);
- fp = *status =gmx_fio_open(fn,"r");
+ fio = (*status)->fio =gmx_fio_open(fn,"r");
break;
case efG87:
- fr->natoms=xyz_first_x(gmx_fio_getfp(fp),oenv,&fr->time,&fr->x,fr->box);
+ fr->natoms=xyz_first_x(*status, gmx_fio_getfp(fio),oenv,&fr->time,
+ &fr->x,fr->box);
if (fr->natoms) {
fr->bTime = TRUE;
fr->bX = TRUE;
fr->bBox = TRUE;
- printcount(oenv,fr->time,FALSE);
+ printcount(*status,oenv,fr->time,FALSE);
}
bFirst = FALSE;
break;
case efXTC:
- if (read_first_xtc(fp,&fr->natoms,&fr->step,&fr->time,fr->box,&fr->x,
+ if (read_first_xtc(fio,&fr->natoms,&fr->step,&fr->time,fr->box,&fr->x,
&fr->prec,&bOK) == 0) {
if (bOK) {
gmx_fatal(FARGS,"No XTC!\n");
}
if (fr->not_ok) {
fr->natoms = 0;
- printincomp(fr);
+ printincomp(*status,fr);
} else {
fr->bPrec = (fr->prec > 0);
fr->bStep = TRUE;
fr->bTime = TRUE;
fr->bX = TRUE;
fr->bBox = TRUE;
- printcount(oenv,fr->time,FALSE);
+ printcount(*status,oenv,fr->time,FALSE);
}
bFirst = FALSE;
break;
case efPDB:
- pdb_first_x(gmx_fio_getfp(fp),fr);
+ pdb_first_x(*status, gmx_fio_getfp(fio),fr);
if (fr->natoms)
- printcount(oenv,fr->time,FALSE);
+ printcount(*status,oenv,fr->time,FALSE);
bFirst = FALSE;
break;
case efGRO:
- if (gro_first_x_or_v(gmx_fio_getfp(fp),fr))
- printcount(oenv,fr->time,FALSE);
+ if (gro_first_x_or_v(gmx_fio_getfp(fio),fr))
+ printcount(*status,oenv,fr->time,FALSE);
bFirst = FALSE;
break;
default:
#ifdef GMX_DLOPEN
- gmx_fio_fp_close(fp); /*only close the file without removing FIO entry*/
- if (!read_first_vmd_frame(status,fn,fr,flags))
+ gmx_fio_fp_close(fio); /*only close the file without removing FIO entry*/
+ if (!read_first_vmd_frame(&dummy,fn,fr,flags))
{
gmx_fatal(FARGS,"Not supported in read_first_frame: %s",fn);
}
#endif
break;
}
+
+ /* Return FALSE if we read a frame that's past the set ending time. */
+ if (!bFirst && (!(fr->flags & TRX_DONT_SKIP) && check_times(fr->time) > 0)) {
+ fr->t0 = fr->time;
+ return FALSE;
+ }
if (bFirst ||
(!(fr->flags & TRX_DONT_SKIP) && check_times(fr->time) < 0))
/***** C O O R D I N A T E S T U F F *****/
-int read_first_x(const output_env_t oenv,int *status,const char *fn,
+int read_first_x(const output_env_t oenv,t_trxstatus **status,const char *fn,
real *t,rvec **x,matrix box)
{
t_trxframe fr;
read_first_frame(oenv,status,fn,&fr,TRX_NEED_X);
- if (*status >= nxframe) {
- nxframe = *status+1;
- srenew(xframe,nxframe);
- }
- xframe[*status] = fr;
- *t = xframe[*status].time;
- *x = xframe[*status].x;
- copy_mat(xframe[*status].box,box);
+
+ snew((*status)->xframe, 1);
+ (*status)->nxframe=1;
+ (*(*status)->xframe) = fr;
+ *t = (*status)->xframe->time;
+ *x = (*status)->xframe->x;
+ copy_mat((*status)->xframe->box,box);
- return xframe[*status].natoms;
+ return (*status)->xframe->natoms;
}
-bool read_next_x(const output_env_t oenv, int status,real *t, int natoms,
- rvec x[], matrix box)
+bool read_next_x(const output_env_t oenv, t_trxstatus *status,real *t,
+ int natoms, rvec x[], matrix box)
{
bool bRet;
-
- xframe[status].x = x;
- bRet = read_next_frame(oenv,status,&xframe[status]);
- *t = xframe[status].time;
- copy_mat(xframe[status].box,box);
+
+ status->xframe->x= x;
+ /*xframe[status].x = x;*/
+ bRet = read_next_frame(oenv,status,status->xframe);
+ *t = status->xframe->time;
+ copy_mat(status->xframe->box,box);
return bRet;
}
-void close_trj(int status)
+void close_trj(t_trxstatus *status)
{
- gmx_fio_close(status);
+ gmx_fio_close(status->fio);
}
-void rewind_trj(int status)
+void rewind_trj(t_trxstatus *status)
{
- INITCOUNT;
+ initcount(status);
- gmx_fio_rewind(status);
+ gmx_fio_rewind(status->fio);
}
/***** V E L O C I T Y S T U F F *****/
clear_rvec(fr->v[i]);
}
-int read_first_v(const output_env_t oenv, int *status,const char *fn,real *t,
- rvec **v,matrix box)
+int read_first_v(const output_env_t oenv, t_trxstatus **status,const char *fn,
+ real *t, rvec **v,matrix box)
{
t_trxframe fr;
return fr.natoms;
}
-bool read_next_v(const output_env_t oenv,int status,real *t,int natoms,rvec v[],
- matrix box)
+bool read_next_v(const output_env_t oenv,t_trxstatus *status,real *t,
+ int natoms,rvec v[], matrix box)
{
t_trxframe fr;
bool bRet;
sfree(at->atom);
sfree(at->resinfo);
sfree(at->atomname);
+ sfree(at->atomtype);
+ sfree(at->atomtypeB);
}
void done_atomtypes(t_atomtypes *atype)
sfree(atype->radius);
sfree(atype->vol);
sfree(atype->surftens);
+ sfree(atype->atomnumber);
sfree(atype->gb_radius);
sfree(atype->S_hct);
}
void done_top(t_topology *top)
{
- int i;
+ int f;
+ sfree(top->idef.functype);
+ sfree(top->idef.iparams);
+ for (f = 0; f < F_NRE; ++f)
+ {
+ sfree(top->idef.il[f].iatoms);
+ top->idef.il[f].iatoms = NULL;
+ top->idef.il[f].nalloc = 0;
+ }
+
done_atom (&(top->atoms));
/* For GB */
ri = &atoms->resinfo[atoms->atom[atom_ind].resind];
ri->name = put_symtab(symtab,resname);
+ ri->rtp = NULL;
ri->nr = resnr;
ri->ic = ic;
ri->chain = chain;
#include "gstat.h"
#include "wgms.h"
-static int n=0;
+/*static int n=0;*/
#define FPL 10
void write_gms(FILE *fp,int natoms,rvec x[],matrix box)
{
- int i,j;
+ int i,j,n;
n=0;
for(i=0;(i<natoms);i++)
void write_gms_ndx(FILE *fp,int isize,atom_id index[],rvec x[],matrix box)
{
- int i,j;
+ int i,j,n;
n=0;
for(i=0;(i<isize);i++)
#endif
}
-int xdr3drcoord(XDR *xdrs, real *fp, int *size, real *precision)
+int xdr3drcoord(XDR *xdrs, real *fp, int *size, real *precision, bool bRead)
{
#ifdef GMX_DOUBLE
float *ffp;
for(i=0; (i<isize); i++)
ffp[i]=fp[i];
fprec=*precision;
- ret=xdr3dfcoord(xdrs,ffp,size,&fprec);
+ ret=xdr3dfcoord(xdrs,ffp,size,&fprec,bRead);
*precision=fprec;
for(i=0; (i<isize); i++)
sfree(ffp);
return ret;
#else
- return xdr3dfcoord(xdrs,(float *)fp,size,(float *)precision);
+ return xdr3dfcoord(xdrs,(float *)fp,size,(float *)precision,bRead);
#endif
}
}
-int open_xtc(const char *fn,const char *mode)
+t_fileio *open_xtc(const char *fn,const char *mode)
{
- return gmx_fio_open(fn,mode);
+ return gmx_fio_open(fn,mode);
}
-void close_xtc(int fp)
+void close_xtc(t_fileio *fio)
{
- gmx_fio_close(fp);
+ gmx_fio_close(fio);
}
static void check_xtc_magic(int magic)
}
fprec = *prec;
}
- result=XTC_CHECK("x",xdr3dfcoord(xd,ftmp,natoms,&fprec));
+ result=XTC_CHECK("x",xdr3dfcoord(xd,ftmp,natoms,&fprec,bRead));
/* Copy from temp. array if reading */
if(bRead)
}
sfree(ftmp);
#else
- result=XTC_CHECK("x",xdr3dfcoord(xd,x[0],natoms,prec));
+ result=XTC_CHECK("x",xdr3dfcoord(xd,x[0],natoms,prec,bRead));
#endif
return result;
-int write_xtc(int fp,
+int write_xtc(t_fileio *fio,
int natoms,int step,real time,
matrix box,rvec *x,real prec)
{
bool bDum;
int bOK;
- xd = gmx_fio_getxdr(fp);
+ xd = gmx_fio_getxdr(fio);
/* write magic number and xtc identidier */
if (xtc_header(xd,&magic_number,&natoms,&step,&time,FALSE,&bDum) == 0)
{
if(bOK)
{
- if(gmx_fio_flush(fp) !=0)
+ if(gmx_fio_flush(fio) !=0)
{
bOK = 0;
}
return bOK; /* 0 if bad, 1 if writing went well */
}
-int read_first_xtc(int fp,int *natoms,int *step,real *time,
+int read_first_xtc(t_fileio *fio,int *natoms,int *step,real *time,
matrix box,rvec **x,real *prec,bool *bOK)
{
int magic;
XDR *xd;
*bOK=TRUE;
- xd = gmx_fio_getxdr(fp);
+ xd = gmx_fio_getxdr(fio);
/* read header and malloc x */
if ( !xtc_header(xd,&magic,natoms,step,time,TRUE,bOK))
return *bOK;
}
-int read_next_xtc(int fp,
+int read_next_xtc(t_fileio* fio,
int natoms,int *step,real *time,
matrix box,rvec *x,real *prec,bool *bOK)
{
XDR *xd;
*bOK=TRUE;
- xd = gmx_fio_getxdr(fp);
+ xd = gmx_fio_getxdr(fio);
/* read header */
if (!xtc_header(xd,&magic,&n,step,time,TRUE,bOK))
add_library(gmxpreprocess ${GMXPREPROCESS_SOURCES})
target_link_libraries(gmxpreprocess md)
+set_target_properties(gmxpreprocess PROPERTIES OUTPUT_NAME "gmxpreprocess${GMX_BINARY_SUFFIX}")
+set_target_properties(md PROPERTIES OUTPUT_NAME "md${GMX_BINARY_SUFFIX}")
if(GMX_OPENMM)
add_subdirectory(gmx_gpu_utils)
include_directories(./gmx_gpu_utils ${OpenMM_INCLUDE_DIR})
link_directories(${OpenMM_LIBRARY_DIR})
- add_definitions( -DOPENMM_PLUGIN_DIR="${OpenMM_PLUGIN_DIR}" )
+ # only define if this is a local build not a release
+ # we assume that the auto-generated version is not used &&
+ # version string does not contain "-dev" => it's a release build
+ if(NOT USE_VERSION_H AND NOT PROJECT_VERSION MATCHES ".*-dev.*")
+ add_definitions( -DOPENMM_PLUGIN_DIR="${OpenMM_PLUGIN_DIR}" )
+ else()
+ add_definitions( -DOPENMM_PLUGIN_DIR="" )
+ endif()
add_library(openmm_api_wrapper openmm_wrapper.cpp)
# remove_definitions( -DOPENMM_PLUGIN_DIR="${OpenMM_PLUGIN_DIR}" ) # TODO where should this go?!
set(GMX_OPENMM_LIBRARIES openmm_api_wrapper gmx_gpu_utils OpenMM)
- install(TARGETS openmm_api_wrapper DESTINATION ${LIB_INSTALL_DIR})
endif(GMX_OPENMM)
if(GMX_FAHCORE)
add_executable(grompp grompp.c)
target_link_libraries(grompp ${GMX_EXTRA_LIBRARIES})
+set_target_properties(grompp PROPERTIES OUTPUT_NAME "grompp${GMX_BINARY_SUFFIX}")
add_executable(tpbconv tpbconv.c)
target_link_libraries(tpbconv ${GMX_EXTRA_LIBRARIES})
+set_target_properties(tpbconv PROPERTIES OUTPUT_NAME "tpbconv${GMX_BINARY_SUFFIX}")
add_executable(pdb2gmx pdb2gmx.c)
target_link_libraries(pdb2gmx ${GMX_EXTRA_LIBRARIES})
+set_target_properties(pdb2gmx PROPERTIES OUTPUT_NAME "pdb2gmx${GMX_BINARY_SUFFIX}")
-add_executable(protonate protonate.c)
-target_link_libraries(protonate ${GMX_EXTRA_LIBRARIES})
+add_executable(g_protonate g_protonate.c)
+target_link_libraries(g_protonate ${GMX_EXTRA_LIBRARIES})
+set_target_properties(g_protonate PROPERTIES OUTPUT_NAME "g_protonate${GMX_BINARY_SUFFIX}")
-add_executable(luck luck.c)
-target_link_libraries(luck ${GMX_EXTRA_LIBRARIES})
+add_executable(g_luck g_luck.c)
+target_link_libraries(g_luck ${GMX_EXTRA_LIBRARIES})
+set_target_properties(g_luck PROPERTIES OUTPUT_NAME "g_luck${GMX_BINARY_SUFFIX}")
add_executable(gmxdump gmxdump.c)
target_link_libraries(gmxdump ${GMX_EXTRA_LIBRARIES})
+set_target_properties(gmxdump PROPERTIES OUTPUT_NAME "gmxdump${GMX_BINARY_SUFFIX}")
-add_executable(x2top x2top.c)
-target_link_libraries(x2top ${GMX_EXTRA_LIBRARIES})
+add_executable(g_x2top g_x2top.c)
+target_link_libraries(g_x2top ${GMX_EXTRA_LIBRARIES})
+set_target_properties(g_x2top PROPERTIES OUTPUT_NAME "g_x2top${GMX_BINARY_SUFFIX}")
add_executable(gmxcheck gmxcheck.c)
target_link_libraries(gmxcheck ${GMX_EXTRA_LIBRARIES})
+set_target_properties(gmxcheck PROPERTIES OUTPUT_NAME "gmxcheck${GMX_BINARY_SUFFIX}")
add_executable(mdrun ${MDRUN_SOURCES})
target_link_libraries(mdrun ${GMX_EXTRA_LIBRARIES} ${GMX_OPENMM_LIBRARIES})
+# set binary name to mdrun-gpu
+if(GMX_OPENMM)
+ set(_mdrun_exec_name "mdrun-gpu")
+else()
+ set(_mdrun_exec_name "mdrun${GMX_BINARY_SUFFIX}")
+endif()
+set_target_properties(mdrun PROPERTIES OUTPUT_NAME "${_mdrun_exec_name}")
+
+# this is to circumvent the following MSVC error:
+# warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs
+# fatal error LNK1169: one or more multiply defined symbols found
+if(GMX_OPENMM AND MSVC)
+ set_target_properties(mdrun PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMT")
+endif()
+
install(TARGETS
grompp
tpbconv
pdb2gmx
- protonate
- luck
+ g_protonate
+ g_luck
gmxdump
- x2top
+ g_x2top
gmxcheck
mdrun
gmxpreprocess DESTINATION ${LIB_INSTALL_DIR}
RUNTIME DESTINATION ${BIN_INSTALL_DIR})
+
+get_target_property(MDRUN_PATH mdrun LOCATION)
+add_custom_target(install-mdrun
+ COMMAND ${CMAKE_COMMAND} -E copy "${MDRUN_PATH}"
+ "${CMAKE_INSTALL_PREFIX}/bin/${_mdrun_exec_name}"
+ DEPENDS mdrun
+ COMMENT "Installing mdrun")
+
endif(GMX_FAHCORE)
bin_PROGRAMS = \
grompp mdrun tpbconv pdb2gmx \
- protonate luck gmxdump \
- gmxcheck x2top
+ g_protonate g_luck gmxdump \
+ gmxcheck g_x2top
-x2top_SOURCES = x2top.c nm2type.c x2top.h
+g_x2top_SOURCES = g_x2top.c nm2type.c g_x2top.h
mdrun_SOURCES = \
gctio.c \
{
cptr = filename;
}
- if (strlen(filename) >= maxlen)
+ if (strlen(filename) >= (size_t)maxlen)
{
gmx_fatal(FARGS,"filename is longer (%d) than maxlen (%d)",
strlen(filename),maxlen);
}
static int low_fflib_search_file_end(const char *ffdir,
+ bool bAddCWD,
const char *file_end,
bool bFatalError,
char ***filenames,
/* GMXLIB can be a path now */
lib = getenv("GMXLIB");
snew(libpath,GMX_PATH_MAX);
+ if (bAddCWD)
+ {
+ sprintf(libpath,"%s%s",".",PATH_SEPARATOR);
+ }
if (lib != NULL)
{
env_is_set = TRUE;
- strncpy(libpath,lib,GMX_PATH_MAX);
+ strncat(libpath,lib,GMX_PATH_MAX);
}
- else if (!get_libdir(libpath))
+ else if (!get_libdir(libpath+strlen(libpath)))
{
- strncpy(libpath,GMXLIBDIR,GMX_PATH_MAX);
+ strncat(libpath,GMXLIBDIR,GMX_PATH_MAX);
}
}
s = libpath;
n = 0;
fns = NULL;
fns_short = NULL;
- /* Start with the current directory, continue with libpath */
- dir = ".";
- do
+ /* Loop over all the entries in libpath */
+ while ((dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
{
dirptr = opendir(dir);
if (dirptr != NULL)
}
}
- sort_filenames(n_thisdir,fns+n-n_thisdir,fns_short+n-n_thisdir);
+ sort_filenames(n_thisdir,
+ fns+n-n_thisdir,
+ fns_short==NULL ? NULL : fns_short+n-n_thisdir);
}
}
- while((dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL);
sfree(libpath);
#endif
}
-int fflib_search_file_end(const char *ffdir,const char *file_end,
+int fflib_search_file_end(const char *ffdir,bool bAddCWD,
+ const char *file_end,
bool bFatalError,
char ***filenames)
{
- return low_fflib_search_file_end(ffdir,file_end,bFatalError,filenames,NULL);
+ return low_fflib_search_file_end(ffdir,bAddCWD,file_end,bFatalError,
+ filenames,NULL);
}
int fflib_search_file_in_dirend(const char *filename,const char *dirend,
struct dirent *dirent;
/* Find all files (not only dir's) ending on dirend */
- nf = low_fflib_search_file_end(NULL,dirend,FALSE,&f,&f_short);
+ nf = low_fflib_search_file_end(NULL,TRUE,dirend,FALSE,&f,&f_short);
n = 0;
dns = NULL;
* base should be at least of size maxlen.
*/
-extern int fflib_search_file_end(const char *ffdir,const char *file_end,
+extern int fflib_search_file_end(const char *ffdir,bool bAddCWD,
+ const char *file_end,
bool bFatalError,
char ***filenames);
/* Search for files ending on file_end in the force field directory fflib.
- * fflib should be in the current working directory or the GROMACS lib.path.
+ * fflib should be in the GROMACS lib.path or, when bAddCWD is set,
+ * in the current working directory.
* Return the number of files and the file names in filenames.
*/
t_atoms *atoms,*iatoms;
t_protonate protdata;
atom_id *index;
- int status,out;
+ t_trxstatus *status;
+ t_trxstatus *out;
t_trxframe fr,frout;
rvec *x,*ix;
int nidx,natoms,natoms_out;
#include "gen_ad.h"
#include "gpp_nextnb.h"
#include "vec.h"
-#include "x2top.h"
+#include "g_x2top.h"
#include "atomprop.h"
char atp[7] = "HCNOSX";
b.c[i] = 0.0;
if (bPBC)
- set_pbc(&pbc,epbcXYZ,box);
+ set_pbc(&pbc,-1,box);
for(i=0; (i<atoms->nr); i++) {
if ((i % 10) == 0)
fprintf(stderr,"\ratom %d",i);
"and force constants will be printed in the topology for all",
"interactions. The equilibrium distances and angles are taken",
"from the input coordinates, the force constant are set with",
- "command line options."
- "The force fields supported currently are:[PAR]",
- "G43a1 GROMOS96 43a1 Forcefield (official distribution)[PAR]",
+ "command line options.",
+ "The force fields somewhat supported currently are:[PAR]",
+ "G53a5 GROMOS96 53a5 Forcefield (official distribution)[PAR]",
"oplsaa OPLS-AA/L all-atom force field (2001 aminoacid dihedrals)[PAR]",
- "G43b1 GROMOS96 43b1 Vacuum Forcefield (official distribution)[PAR]",
- "gmx Gromacs Forcefield (a modified GROMOS87, see manual)[PAR]",
- "G43a2 GROMOS96 43a2 Forcefield (development) (improved alkane dihedrals)[PAR]",
"The corresponding data files can be found in the library directory",
- "with names like ffXXXX.YYY. Check chapter 5 of the manual for more",
+ "with name atomname2type.n2t. Check chapter 5 of the manual for more",
"information about file formats. By default the forcefield selection",
"is interactive, but you can use the [TT]-ff[tt] option to specify",
"one of the short names above on the command line instead. In that",
"The atom type selection is primitive. Virtually no chemical knowledge is used",
"Periodic boundary conditions screw up the bonding",
"No improper dihedrals are generated",
- "The atoms to atomtype translation table is incomplete (ffG43a1.n2t file in the $GMXLIB directory). Please extend it and send the results back to the GROMACS crew."
+ "The atoms to atomtype translation table is incomplete (atomname2type.n2t files in the data directory). Please extend it and send the results back to the GROMACS crew."
};
FILE *fp;
t_params plist[F_NRE];
bool bRTP,bTOP,bOPLS;
t_symtab symtab;
real cutoff,qtot,mtot;
+ char n2t[STRLEN];
output_env_t oenv;
t_filenm fnm[] = {
{ efRTP, "-r", "out", ffOPTWR }
};
#define NFILE asize(fnm)
+ static bool bAddCWD = FALSE;
static real scale = 1.1, kb = 4e5,kt = 400,kp = 5;
static int nexcl = 3;
static bool bRemoveDih = FALSE;
static const char *ff = "oplsaa";
t_pargs pa[] = {
{ "-ff", FALSE, etSTR, {&ff},
- "Force field for your simulation. Type \"select\" for interactive selcection." },
+ "Force field for your simulation. Type \"select\" for interactive selection." },
+ { "-cwd", FALSE, etBOOL, {&bAddCWD},
+ "Also read force field files from the current working directory" },
{ "-v", FALSE, etBOOL, {&bVerbose},
"Generate verbose output in the top file." },
{ "-nexcl", FALSE, etINT, {&nexcl},
forcefield,sizeof(forcefield),
ffdir,sizeof(ffdir));
- bOPLS = (strcmp(forcefield,"ffoplsaa") == 0);
+ bOPLS = (strcmp(forcefield,"oplsaa") == 0);
mymol.name = strdup(molnm);
read_stx_conf(opt2fn("-f",NFILE,fnm),title,atoms,x,NULL,&epbc,box);
- nm2t = rd_nm2type(ffdir,&nnm);
- printf("There are %d name to type translations\n",nnm);
+ sprintf(n2t,"%s",ffdir);
+ nm2t = rd_nm2type(n2t,bAddCWD,&nnm);
+ if (nnm == 0)
+ gmx_fatal(FARGS,"No or incorrect atomname2type.n2t file found (looking for %s)",
+ n2t);
+ else
+ printf("There are %d name to type translations in file %s\n",nnm,n2t);
if (debug)
dump_nm2type(debug,nnm,nm2t);
-
printf("Generating bonds from distances...\n");
snew(nbonds,atoms->nr);
mk_bonds(nnm,nm2t,atoms,x,&(plist[F_BONDS]),nbonds,forcefield,
double *blen;
} t_nm2type;
-extern t_nm2type *rd_nm2type(const char *ffdir,int *nnm);
+extern t_nm2type *rd_nm2type(const char *ffdir,bool bAddCWD,int *nnm);
/* Read the name 2 type database. nnm is the number of entries
* ff is the force field.
*/
t_atoms *at, t_symtab *symtab, rvec *x[],
t_params plist[], int *vsite_type[], int *cgnr[],
real mHmult, bool bVsiteAromatics,
- const char *ffdir)
+ const char *ffdir,bool bAddCWD)
{
#define MAXATOMSPERRESIDUE 16
int i,j,k,i0,ni0,whatres,resind,add_shift,ftype,nvsite,nadd;
fprintf(debug,"# # # VSITES # # #\n");
}
- ndb = fflib_search_file_end(ffdir,".vsd",FALSE,&db);
+ ndb = fflib_search_file_end(ffdir,bAddCWD,".vsd",FALSE,&db);
nvsiteconf = 0;
vsiteconflist = NULL;
nvsitetop = 0;
t_atoms *at, t_symtab *symtab, rvec *x[],
t_params plist[], int *dummy_type[], int *cgnr[],
real mHmult, bool bVSiteAromatics,
- const char *ffdir);
+ const char *ffdir,bool bAddCWD);
extern void do_h_mass(t_params *psb, int vsite_type[], t_atoms *at, real mHmult,
bool bDeuterate);
return hb;
}
-static const char Hnum[] = "123456";
-
static void expand_hackblocks_one(t_hackblock *hbr, char *atomname,
int *nabi, t_hack **abi, bool bN, bool bC)
{
srenew(*abi,*nabi + hbr->hack[j].nr);
for(k=0; k < hbr->hack[j].nr; k++) {
copy_t_hack(&hbr->hack[j], &(*abi)[*nabi + k]);
- for(d=0; d<DIM; d++)
- (*abi)[*nabi + k].newx[d]=NOTSET;
+ (*abi)[*nabi + k].bXSet = FALSE;
/* if we're adding (oname==NULL) and don't have a new name (nname)
yet, build it from atomname */
if ( (*abi)[*nabi + k].nname==NULL ) {
sfree((*abi)[*nabi + k].nname);
(*abi)[*nabi + k].nname=strdup(hbr->hack[j].nname);
}
- /* if adding more than one atom, number them */
- if ( hbr->hack[j].nr > 1 ) {
+
+ if (hbr->hack[j].tp == 10 && k == 2) {
+ /* This is a water virtual site, not a hydrogen */
+ /* Ugly hardcoded name hack */
+ (*abi)[*nabi + k].nname[0] = 'M';
+ } else if (hbr->hack[j].tp == 11 && k >= 2) {
+ /* This is a water lone pair, not a hydrogen */
+ /* Ugly hardcoded name hack */
+ srenew((*abi)[*nabi + k].nname,4);
+ (*abi)[*nabi + k].nname[0] = 'L';
+ (*abi)[*nabi + k].nname[1] = 'P';
+ (*abi)[*nabi + k].nname[2] = '1' + k - 2;
+ (*abi)[*nabi + k].nname[3] = '\0';
+ } else if ( hbr->hack[j].nr > 1 ) {
+ /* adding more than one atom, number them */
l = strlen((*abi)[*nabi + k].nname);
srenew((*abi)[*nabi + k].nname, l+2);
- (*abi)[*nabi + k].nname[l] = Hnum[k]; /* 1, 2, 3 .... */
+ (*abi)[*nabi + k].nname[l] = '1' + k;
(*abi)[*nabi + k].nname[l+1] = '\0';
}
}
else
xh[m][d] = NOTSET;
calc_h_pos(ab[i][j].tp, xa, xh, &l);
- for(m=0; m<ab[i][j].nr; m++)
+ for(m=0; m<ab[i][j].nr; m++) {
copy_rvec(xh[m],ab[i][j+m].newx);
+ ab[i][j+m].bXSet = TRUE;
+ }
}
}
}
bool bUpdate_pdba, bool bKeep_old_pdba)
{
t_atoms *newpdba=NULL,*pdba=NULL;
- bool bSet;
int nadd;
int i,newi,j,d,natoms,nalreadypresent;
int *nab=NULL;
/* newpdba->atom[newi].type = ab[i][j].atom->type; */
}
}
- bSet=TRUE;
- for(d=0; d<DIM; d++)
- bSet = bSet && ab[i][j].newx[d]!=NOTSET;
- if (bSet)
+ if (ab[i][j].bXSet)
copy_rvec(ab[i][j].newx, xn[newi]);
}
if (bUpdate_pdba && debug)
/* set forcefield to use: */
strcpy(protdata->FF,"ffgmx2");
/* get the databases: */
- protdata->nah=read_h_db(protdata->FF,&protdata->ah);
+ protdata->nah=read_h_db(protdata->FF,FALSE,&protdata->ah);
open_symtab(&protdata->tab);
- protdata->atype=read_atype(protdata->FF,&protdata->tab);
- nntdb = read_ter_db(protdata->FF,'n',&protdata->ntdb,protdata->atype);
+ protdata->atype=read_atype(protdata->FF,FALSE,&protdata->tab);
+ nntdb = read_ter_db(protdata->FF,FALSE,'n',&protdata->ntdb,protdata->atype);
if (nntdb < 1)
gmx_fatal(FARGS,"no n-terminus db");
- nctdb = read_ter_db(protdata->FF,'c',&protdata->ctdb,protdata->atype);
+ nctdb = read_ter_db(protdata->FF,FALSE,'c',&protdata->ctdb,protdata->atype);
if (nctdb < 1)
gmx_fatal(FARGS,"no c-terminus db");
+# (slightly sloppy) OS definitions required by memtestG80
+set(_os_def)
+if(UNIX)
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(_os_def "-DOSX")
+ else() # everything that's UNIX & UNIX-like except OS X
+ set(_os_def "-DLINUX")
+ endif()
+else()
+ if(WIN32)
+ set(_os_def "-DWINDOWS")
+ else()
+ message(FATAL_ERROR " Could not detect OS required for memtestG80.")
+ endif()
+endif()
CUDA_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE OFF)
CUDA_ADD_LIBRARY(gmx_gpu_utils
gmx_gpu_utils.cu
memtestG80_core.cu
- OPTIONS "-DLINUX"
+ OPTIONS ${_os_def}
DEBUG -g -D_DEBUG_=1
)
else()
CUDA_ADD_LIBRARY(gmx_gpu_utils
gmx_gpu_utils.cu
memtestG80_core.cu
- OPTIONS "-DLINUX"
+ OPTIONS ${_os_def}
)
endif()
CUDA_BUILD_CLEAN_TARGET()
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include "memtestG80_core.h"
-#include "gmx_fatal.h"
-#include "string2.h"
-
-#define BMARK_MEM 80
-
-#define QUICK_MEM 250
-#define QUICK_TESTS MOD_20_32BIT | LOGIC_4_ITER_SHMEM | RANDOM_BLOCKS
-#define QUICK_ITER 3 /* TODO adjust this for production version */
-
-#define FULL_MEM -1
-#define FULL_TESTS 0x3FFF
-#define FULL_ITER 25 /* TODO adjust this for production version */
-
-#ifndef _DEBUG_
-#define _DEBUG_ 0
+/*! \cond TEST */
+#ifdef _DEBUG_
+#undef _DEBUG_
#endif
+#define _DEBUG_ 0
-#if _DEBUG_ == 1
+#if _DEBUG_ >= 1
+#define debug stderr
#define DUPME(msg) printf("---> %s\n", msg);
#else
#define DUPME(msg) ;
#endif
+/*! \endcond TEST*/
+#if _DEBUG_ == 0/* no gromacs utils in debug mode */
+#include "gmx_fatal.h"
+#include "string2.h"
+#endif
+
+#define QUICK_MEM 250 /*!< Amount of memory to be used in quick memtest. */
+#define QUICK_TESTS MOD_20_32BIT | LOGIC_4_ITER_SHMEM | RANDOM_BLOCKS /*!< Bitflag with type of tests
+ to run in quick memtest. */
+#define QUICK_ITER 3 /*!< Number of iterations in quick memtest. */
+
+#define FULL_TESTS 0x3FFF /*!< Bitflag with all test set on for full memetest. */
+#define FULL_ITER 25 /*!< Number of iterations in full memtest. */
+
+#define TIMED_TESTS MOD_20_32BIT | LOGIC_4_ITER_SHMEM | RANDOM_BLOCKS /*!< Bitflag with type of tests to
+ run in time constrained memtest. */
+
+/*! Number of supported GPUs */
#define NB_GPUS (sizeof(SupportedGPUs)/sizeof(SupportedGPUs[0]))
/*
-TODO fine-tune parameters for quick/full test
-TODO add logging capability when integrating into gmx
-TODO add verbosity level
+TODO add proper gromacs logging?
*/
-/** Bit-flags which refer to memtestG80 test types and are used in do_memtest to specify which tests to run. */
+
+/*! Bit-flags which refer to memtestG80 test types and are used in do_memtest to specify which tests to run. */
enum memtest_G80_test_types {
MOVING_INVERSIONS_10 = 0x1,
MOVING_INVERSIONS_RAND = 0x2,
LOGIC_4_ITER_SHMEM = 0x1000
};
-/* List of GPUs that we want to support. */
// TODO put this list into an external file and include it so that the list is easily accessible
-/** List of supported GPU names. */
+/*! List of supported GPUs. */
static const char * const SupportedGPUs[] = {
+ /* GT400 */
+ "Geforce GTX 480",
+ "Geforce GTX 470",
+
+ "Tesla C2070",
+ "Tesla C2050",
+ "Tesla S2070",
+ "Tesla S2050",
+
/* GT200 */
"Geforce GTX 295",
"Geforce GTX 285",
"Geforce GTX 275",
"Geforce GTX 260",
"GeForce GTS 250",
+ "GeForce GTS 150",
+
+ "GeForce GTX 285M",
+ "GeForce GTX 280M",
"Tesla S1070",
"Tesla C1060",
+ "Tesla M1060",
"Quadro FX 5800",
"Quadro FX 4800",
"Quadro Plex 2200 S4",
/* G90 */
- "GeForce 9800 G", /*GX2, GTX, GTX+ */
- "GeForce 9600 G", /* */
+ "GeForce 9800 G", /* GX2, GTX, GTX+, GT */
+ "GeForce 9800M GTX",
"Quadro FX 4700",
"Quadro Plex 2100 D4"
};
+/*! \cond TEST */
#ifndef _string2_h
-#include <string.h>
-/* - duplicated from ~/src/gmxlib/string2.c - */
-void ltrim (char *str)
-{
- char *tr;
- int c;
-
- if (!str)
- return;
-
- tr = strdup (str);
- c = 0;
- while ((tr[c] == ' ') || (tr[c] == '\t'))
- c++;
-
- strcpy (str,tr+c);
- free (tr);
-}
-
-void rtrim (char *str)
-{
- int nul;
-
- if (!str)
- return;
-
- nul = strlen(str)-1;
- while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
- str[nul] = '\0';
- nul--;
- }
-}
-
-void trim (char *str)
-{
- ltrim (str);
- rtrim (str);
-}
+/* debug functions, see @the end */
+void ltrim (char *);
+void rtrim (char *);
+void trim (char *);
+int gmx_strncasecmp(const char*, const char*, int);
#endif
+/*! \endcond TEST */
-/** Runs sanity checks and returned properties of a device with given id or the one that has
- * already been selected in the case if of dev_id == -1.
+
+/*!
+ * \brief Runs GPU sanity checks.
+ * Returnes properties of a device with given id or the one that has
+ * already been initialized earlier in the case if of dev_id == -1.
*
- * @param dev_id the device id of the GPU or -1 if the device has laredy been selected
- * @param dev_prop pointer to the structure in which the device properties will be returned
+ * \param[in] dev_id the device id of the GPU or -1 if the device has laredy been selected
+ * \param[out] dev_prop pointer to the structure in which the device properties will be returned
*/
static int do_sanity_checks(int dev_id, cudaDeviceProp *dev_prop)
{
if ((dev_id != -1) && (cu_err = cudaSetDevice(dev_id)) != cudaSuccess)
{
- fprintf(stderr, "Error %d while switching to device #%d: %s\n", cu_err, dev_id,
+ fprintf(stderr, "Error %d while switching to device #%d: %s\n", cu_err, dev_id,
cudaGetErrorString(cu_err));
return -1;
}
return 0;
}
-/**
- * Checks whether the GPU with the given name is supported or not. In case of a positive
- * answer returns 1, otherwise 0;
- *
- * @param dev_id the device id of the GPU or -1 if the device has laredy been selected
- * @param gpu_name the name of the CUDA device
- * @returns 1 if the device is supported, otherwise 0
+/*!
+ * \brief Checks whether the GPU with the given name is supported.
+ *
+ * \param[in] gpu_name the name of the CUDA device
+ * \returns 1 if the device is supported, otherwise 0
*/
static int is_supported_gpu_n(char *gpuName)
{
return 0;
}
-/**
- * Checks whether the GPU with the given device id is supported or not. In case of a positive
- * answer returns 1, otherwise 0;
+/*! \brief Checks whether the GPU with the given device id is supported.
*
- * @param dev_id the device id of the GPU or -1 if the device has laredy been selected
- * @param gpu_name the name of the CUDA device
- * @returns 1 if the device is supported, otherwise 0
+ * \param[in] dev_id the device id of the GPU or -1 if the device has laredy been selected
+ * \param[out] gpu_name Set to contain the name of the CUDA device, if NULL passed, no device name is set.
+ * \returns 1 if the device is supported, otherwise 0
*/
-
int is_supported_cuda_gpu(int dev_id, char *gpu_name)
{
cudaDeviceProp dev_prop;
if (do_sanity_checks(dev_id, &dev_prop) != 0)
return -1;
- strcpy(gpu_name, dev_prop.name);
+ if (gpu_name != NULL)
+ {
+ strcpy(gpu_name, dev_prop.name);
+ }
return is_supported_gpu_n(dev_prop.name);
}
-/**
- * Runs a set of memory tests specified by the given bit-flags. In case if an error is detected
- * it stops without finishing the remainings steps/iterations and returns greater then zero value.
- * In case of other errors (e.g. kernel launch errors, device querying erros) -1 is returned.
+/*!
+ * \brief Runs a set of memory tests specified by the given bit-flags.
+ * Tries to allocate and do the test on \p megs Mb memory or
+ * the greatest amount that can be allocated (>10Mb).
+ * In case if an error is detected it stops without finishing the remainings
+ * steps/iterations and returns greater then zero value.
+ * In case of other errors (e.g. kernel launch errors, device querying erros)
+ * -1 is returned.
*
- * @param which_tests - variable with bit-flags of the requested tests
- * @param megs - amount of memory that will be tested in MB
- * @param iter - number of iterations
- * @returns - 0 if no error was detected, otherwise >0
+ * \param[in] which_tests variable with bit-flags of the requested tests
+ * \param[in] megs amount of memory that will be tested in MB
+ * \param[in] iter number of iterations
+ * \returns 0 if no error was detected, otherwise >0
*/
static int do_memtest(unsigned int which_tests, int megs, int iter)
{
return err_count;
}
-/**
- * Runs a quick memory test and returns 0 in case if no error is detected. If an error is detected it stops
- * before completing the test and returns a value greater then 0. In case of other errors
- * (e.g. kernel launch errors, device querying erros) -1 is returned.
+/*! \brief Runs a quick memory test and returns 0 in case if no error is detected.
+ * If an error is detected it stops before completing the test and returns a
+ * value greater then 0. In case of other errors (e.g. kernel launch errors,
+ * device querying erros) -1 is returned.
*
- * @param dev_id the device id of the GPU or -1 if the device has laredy been selected
- * @returns 0 if no error was detected, otherwise >0
+ * \param[in] dev_id the device id of the GPU or -1 if the device has laredy been selected
+ * \returns 0 if no error was detected, otherwise >0
*/
int do_quick_memtest(int dev_id)
{
cudaDeviceProp dev_prop;
- int devmem, res, time;
+ int devmem, res, time=0;
if (debug) { time = getTimeMilliseconds(); }
return -1;
}
- devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
-
if (debug)
{
+ devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
fprintf(debug, ">> Running QUICK memtests on %d MiB (out of total %d MiB), %d iterations\n",
QUICK_MEM, devmem, QUICK_ITER);
}
return res;
}
-/**
- * Runs a full memory test and returns 0 in case if no error is detected. If an error is detected it stops
- * before completing the test and returns a value greater then 0. In case of other errors
- * (e.g. kernel launch errors, device querying erros) -1 is returned.
+/*! \brief Runs a full memory test and returns 0 in case if no error is detected.
+ * If an error is detected it stops before completing the test and returns a
+ * value greater then 0. In case of other errors (e.g. kernel launch errors,
+ * device querying erros) -1 is returned.
*
- * @param dev_id the device id of the GPU or -1 if the device has laredy been selected
- * @returns 0 if no error was detected, otherwise >0
+ * \param[in] dev_id the device id of the GPU or -1 if the device has laredy been selected
+ * \returns 0 if no error was detected, otherwise >0
*/
int do_full_memtest(int dev_id)
{
cudaDeviceProp dev_prop;
- int devmem, res, time;
+ int devmem, res, time=0;
if (debug) { time = getTimeMilliseconds(); }
}
devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
- if (debug) { fprintf(debug, ">> Running FULL memtests on %d MiB (out of total %d MiB), %d iterations\n",
- devmem, devmem, FULL_ITER); }
+ if (debug)
+ {
+ fprintf(debug, ">> Running FULL memtests on %d MiB (out of total %d MiB), %d iterations\n",
+ devmem, devmem, FULL_ITER);
+ }
+
+ /* do all test on the entire memory */
res = do_memtest(FULL_TESTS, devmem, FULL_ITER);
if (debug)
return res;
}
-/*******************************************************/
-/* FIXME test it! */
-
-/**
- * Runs a time constrained memory test and returns 0 in case if no error is detected. If an error is detected
- * it stops before completing the test and returns a value greater then zero. In case of other errors
- * (e.g. kernel launch errors, device querying erros) -1 is returned. Note, that test iterations are not
- * interrupted therefor the total runtime of the test will always be multipple of one iteration's runtime.
+/*! \brief Runs a time constrained memory test and returns 0 in case if no error is detected.
+ * If an error is detected it stops before completing the test and returns a value greater
+ * than zero. In case of other errors (e.g. kernel launch errors, device querying erros) -1
+ * is returned. Note, that test iterations are not interrupted therefor the total runtime of
+ * the test will always be multipple of one iteration's runtime.
*
- * @param dev_id the device id of the GPU or -1 if the device has laredy been selected
- * @param time_constr the time limit of the testing
- * @returns 0 if no error was detected, otherwise >0
+ * \param[in] dev_id the device id of the GPU or -1 if the device has laredy been selected
+ * \param[in] time_constr the time limit of the testing
+ * \returns 0 if no error was detected, otherwise >0
*/
-
int do_timed_memtest(int dev_id, int time_constr)
{
cudaDeviceProp dev_prop;
- int devmem, res, time, startt;
+ int devmem, res=0, time=0, startt;
if (debug) { time = getTimeMilliseconds(); }
}
devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
- if (debug) { fprintf(debug, ">> Running time constrained memtests on %d MiB (out of total %d MiB), time limit of %d s \n",
- devmem, devmem, time_constr); }
- while ( (getTimeMilliseconds() - startt) < time_constr)
- {
- res = do_memtest(QUICK_TESTS, devmem, 1);
+ if (debug)
+ {
+ fprintf(debug, ">> Running time constrained memtests on %d MiB (out of total %d MiB), time limit of %d s \n",
+ devmem, devmem, time_constr);
+ }
+
+ /* do the TIMED_TESTS set, one step at a time on the entire memory
+ that can be allocated, and stop when the given time is exceeded */
+ while ( ((int)getTimeMilliseconds() - startt) < time_constr)
+ {
+ res = do_memtest(TIMED_TESTS, devmem, 1);
if (res != 0) break;
}
if (dev_id != -1) cudaThreadExit();
return res;
}
-/*******************************************************/
+/*! \cond TEST */
+
+/*******************************************************
+ * The code below is for testing purposes. */
int do_custom_memtest(int dev_id)
{
cudaDeviceProp dev_prop;
// tester.deallocate();
// devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
- mem2test = BMARK_MEM;
+ mem2test = 80;
#if _DEBUG_ >= 1
- printf(">> Running CUSTOM memtests [%x] on %d MiB (out of total %d MiB), %d iterations\n",
- QUICK_TESTS, mem2test, devmem, 1);
+ printf(">> Running CUSTOM memtests [%x] on %d MiB, %d iterations\n",
+ QUICK_TESTS, mem2test, 1);
#endif
res = do_memtest(QUICK_TESTS, mem2test, 1);
}
#if _DEBUG_ > 1
-/**
+/*!
* Only for debugging purposes, compile with:
* nvcc -DLINUX -D_DEBUG_=2 -L -O -Xcompiler -Wall memtestG80_core.o gmx_gpu_utils.cu -o gmx_gpu_utils_test
*/
int dev_id = 0;
char msg[100];
sprintf(msg, "Device #%d supported: ", dev_id);
- switch (is_supported_cuda_gpu(dev_id))
+ switch (is_supported_cuda_gpu(dev_id, NULL))
{
case -1: strcat(msg, "error occured"); break;
case 0: strcat(msg, "no"); break;
printf("Doing memtest.\n");
printf("quick memtest result: %d\n", do_quick_memtest(dev_id));
+ printf("timed memtest result: %d\n", do_timed_memtest(dev_id, 15));
printf("full memtest result: %d\n", do_full_memtest(dev_id));
return 0;
}
#endif
+
+
+#ifndef _string2_h
+#include <string.h>
+/*
+ Functions only used if this file is compiled in debug mode (_DEBUG_ > 0)
+ when the gromacs version are not available.
+ - string trimming function - duplicated from ~/src/gmxlib/string2.c
+ - case agnostic straing compare
+ */
+static void ltrim (char *str)
+{
+ char *tr;
+ int c;
+
+ if (!str)
+ return;
+
+ tr = strdup (str);
+ c = 0;
+ while ((tr[c] == ' ') || (tr[c] == '\t'))
+ c++;
+
+ strcpy (str,tr+c);
+ free (tr);
+}
+
+static void rtrim (char *str)
+{
+ int nul;
+
+ if (!str)
+ return;
+
+ nul = strlen(str)-1;
+ while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
+ str[nul] = '\0';
+ nul--;
+ }
+}
+
+static void trim (char *str)
+{
+ ltrim (str);
+ rtrim (str);
+}
+
+static int gmx_strncasecmp(const char* s1, const char* s2, int len)
+{
+ return strncasecmp(s1, s2, len);
+}
+#endif
+
+/*! \endcond TEST */
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
#ifndef _GMX_GPU_UTILS_H_
#define _GMX_GPU_UTILS_H_
extern "C" {
#endif
-/** Runs a quick memory test and returns 0 in case if no error is detected. */
int do_quick_memtest(int /*dev_id*/);
-/** Runs a full memory test and returns 0 in case if no error is detected. */
int do_full_memtest(int /*dev_id*/);
-/** Runs a time constrained memory test and returns 0 in case if no error is detected. */
int do_timed_memtest(int /*dev_id*/, int /*time_limit*/);
-/** Checks whether the GPU with the given device id is supported or not. */
int is_supported_cuda_gpu(int /*dev_id*/, char* /*gpu_name*/);
#ifndef __cplusplus
-/*\r
- * memtestG80_core.h\r
- * Public API for core memory test functions for MemtestG80\r
- * Includes functional and OO interfaces to GPU test functions.\r
- *\r
- * Author: Imran Haque, 2009\r
- * Copyright 2009, Stanford University\r
- *\r
- * This file is licensed under the terms of the LGPL. Please see\r
- * the COPYING file in the accompanying source distribution for\r
- * full license terms.\r
- *\r
- */\r
-#ifndef _MEMTESTG80_CORE_H_\r
-#define _MEMTESTG80_CORE_H_\r
-\r
-#if defined (WINDOWS) || defined (WINNV)\r
- #include <windows.h>\r
- inline unsigned int getTimeMilliseconds(void) {\r
- return GetTickCount();\r
- }\r
- #include <windows.h>\r
- #define SLEEPMS(x) Sleep(x)\r
-#elif defined (LINUX) || defined (OSX)\r
- #include <sys/time.h>\r
- inline unsigned int getTimeMilliseconds(void) {\r
- struct timeval tv;\r
- gettimeofday(&tv,NULL);\r
- return tv.tv_sec*1000 + tv.tv_usec/1000;\r
- }\r
- #include <unistd.h>\r
- #define SLEEPMS(x) usleep(x*1000)\r
-#else\r
- #error Must #define LINUX, WINDOWS, WINNV, or OSX\r
-#endif\r
-\r
-// By default the driver will spinwait when blocked on a kernel call\r
-// Use the SOFTWAIT macro to replace this with a thread sleep and occasional poll\r
-// limit expresses the max time we're willing to stay in the sleep loop - default = 15sec\r
-inline int _pollStatus(unsigned length=1,unsigned limit=15000) {\r
- //while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(length);}\r
- unsigned startTime = getTimeMilliseconds();\r
- while (cudaStreamQuery(0) == cudaErrorNotReady) {\r
- if ((getTimeMilliseconds() - startTime) > limit) return -1;\r
- SLEEPMS(length);\r
- }\r
- return 0;\r
-}\r
-#define SOFTWAIT() if (_pollStatus() != 0) {return 0xFFFFFFFE;} // -2\r
-#define SOFTWAIT_LIM(lim) if (_pollStatus(1,lim) != 0) {return 0xFFFFFFFE;} // -2\r
-//#define SOFTWAIT()\r
-//#define SOFTWAIT(delay) if (_pollStatus(delay) != 0) return -2;\r
-//#define SOFTWAIT(delay,limit) if (_pollStatus(delay,limit) != 0) return -2;\r
-//#define SOFTWAIT() while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(1);}\r
-//#define SOFTWAIT(x) while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(x);}\r
-//#define SOFTWAIT()\r
-\r
-// Use this macro to check for kernel errors\r
-#define CHECK_LAUNCH_ERROR() if (cudaGetLastError() != cudaSuccess) {return 0xFFFFFFFF; /* -1 */}\r
-\r
-\r
-typedef unsigned int uint;\r
-\r
-// OO interface to MemtestG80 functions\r
-class memtestState {\r
-protected:\r
- const uint nBlocks;\r
- const uint nThreads;\r
- uint loopIters;\r
- uint megsToTest;\r
- int lcgPeriod;\r
- uint* devTestMem;\r
- uint* devTempMem;\r
- uint* hostTempMem;\r
- bool allocated;\r
-public:\r
- uint initTime;\r
- memtestState() : nBlocks(1024), nThreads(512), allocated(false), devTestMem(NULL),devTempMem(NULL),hostTempMem(NULL), initTime(0),lcgPeriod(1024) {};\r
- ~memtestState() {deallocate();}\r
-\r
- uint allocate(uint mbToTest);\r
- void deallocate();\r
- bool isAllocated() const {return allocated;}\r
- uint size() const {return megsToTest;}\r
- void setLCGPeriod(int period) {lcgPeriod = period;}\r
- int getLCGPeriod() const {return lcgPeriod;}\r
-\r
- bool gpuMemoryBandwidth(double& bandwidth,uint mbToTest,uint iters=5);\r
- bool gpuWriteConstant(const uint constant) const;\r
- bool gpuVerifyConstant(uint& errorCount,const uint constant) const;\r
- bool gpuShortLCG0(uint& errorCount,const uint repeats) const;\r
- bool gpuShortLCG0Shmem(uint& errorCount,const uint repeats) const;\r
- bool gpuMovingInversionsOnesZeros(uint& errorCount) const;\r
- bool gpuWalking8BitM86(uint& errorCount,const uint shift) const;\r
- bool gpuWalking8Bit(uint& errorCount,const bool ones,const uint shift) const;\r
- bool gpuMovingInversionsRandom(uint& errorCount) const;\r
- bool gpuWalking32Bit(uint& errorCount,const bool ones,const uint shift) const;\r
- bool gpuRandomBlocks(uint& errorCount,const uint seed) const;\r
- bool gpuModuloX(uint& errorCount,const uint shift,const uint pattern,const uint modulus,const uint overwriteIters) const;\r
-};\r
-\r
-// Utility functions\r
-__host__ double gpuMemoryBandwidth(uint* src,uint* dst,uint mbToTest,uint iters);\r
-__host__ void gpuWriteConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);\r
-__host__ uint gpuVerifyConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant,uint* blockErrorCount,uint* errorCounts);\r
-\r
-__host__ void cpuWriteConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);\r
-__host__ uint cpuVerifyConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);\r
-\r
-// Logic tests\r
-__host__ uint gpuShortLCG0(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint repeats,const int period,uint* blockErrorCounts,uint* errorCounts);\r
-__host__ uint gpuShortLCG0Shmem(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint repeats,const int period,uint* blockErrorCounts,uint* errorCounts);\r
-\r
-// Memtest86 Test 2: tseq=0,4\r
-__host__ uint gpuMovingInversionsOnesZeros(const uint nBlocks,const uint nThreads,uint* base,uint N,uint* blockErrorCounts,uint* errorCounts);\r
-\r
-// Memtest86 Test 3: tseq=1\r
-__host__ uint gpuWalking8BitM86(const uint nBlocks,const uint nThreads,uint* base,uint N,uint shift,uint* blockErrorCounts,uint* errorCounts);\r
-__host__ uint cpuWalking8BitM86(const uint nBlocks,const uint nThreads,uint* base,uint N,uint shift);\r
-__host__ uint gpuWalking8Bit(const uint nBlocks,const uint nThreads,uint* base,uint N,bool ones,uint shift,uint* blockErrorCount,uint* errorCounts);\r
-\r
-// Memtest86 Test 4: tseq=10\r
-__host__ uint gpuMovingInversionsRandom(const uint nBlocks,const uint nThreads,uint* base,uint N,uint* blockErrorCounts,uint* errorCounts);\r
-\r
-// Memtest86 Test 6: tseq=2\r
-__host__ uint gpuWalking32Bit(const uint nBlocks,const uint nThreads,uint* base,uint N,bool ones,uint shift,uint* blockErrorCount,uint* errorCounts);\r
-//\r
-// Memtest86 Test 7: tseq=9\r
-__host__ uint gpuRandomBlocks(const uint nBlocks,const uint nThreads,uint* base,uint N,uint seed,uint* blockErrorCount,uint* errorCounts);\r
-\r
-// Memtest86 Test 8: tseq=3 (M86 uses modulus = 20)\r
-__host__ uint gpuModuloX(const uint nBlocks,const uint nThreads,uint* base,const uint N,uint shift,uint pattern1,const uint modulus,const uint iters,uint* blockErrorCount,uint* errorCounts);\r
-\r
-#endif\r
+/*
+ * memtestG80_core.h
+ * Public API for core memory test functions for MemtestG80
+ * Includes functional and OO interfaces to GPU test functions.
+ *
+ * Author: Imran Haque, 2009
+ * Copyright 2009, Stanford University
+ *
+ * This file is licensed under the terms of the LGPL. Please see
+ * the COPYING file in the accompanying source distribution for
+ * full license terms.
+ *
+ */
+#ifndef _MEMTESTG80_CORE_H_
+#define _MEMTESTG80_CORE_H_
+
+#if defined (WINDOWS) || defined (WINNV)
+ #include <windows.h>
+ inline unsigned int getTimeMilliseconds(void) {
+ return GetTickCount();
+ }
+ #include <windows.h>
+ #define SLEEPMS(x) Sleep(x)
+#elif defined (LINUX) || defined (OSX)
+ #include <sys/time.h>
+ inline unsigned int getTimeMilliseconds(void) {
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return tv.tv_sec*1000 + tv.tv_usec/1000;
+ }
+ #include <unistd.h>
+ #define SLEEPMS(x) usleep(x*1000)
+#else
+ #error Must #define LINUX, WINDOWS, WINNV, or OSX
+#endif
+
+// By default the driver will spinwait when blocked on a kernel call
+// Use the SOFTWAIT macro to replace this with a thread sleep and occasional poll
+// limit expresses the max time we're willing to stay in the sleep loop - default = 15sec
+inline int _pollStatus(unsigned length=1,unsigned limit=15000) {
+ //while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(length);}
+ unsigned startTime = getTimeMilliseconds();
+ while (cudaStreamQuery(0) == cudaErrorNotReady) {
+ if ((getTimeMilliseconds() - startTime) > limit) return -1;
+ SLEEPMS(length);
+ }
+ return 0;
+}
+#define SOFTWAIT() if (_pollStatus() != 0) {return 0xFFFFFFFE;} // -2
+#define SOFTWAIT_LIM(lim) if (_pollStatus(1,lim) != 0) {return 0xFFFFFFFE;} // -2
+//#define SOFTWAIT()
+//#define SOFTWAIT(delay) if (_pollStatus(delay) != 0) return -2;
+//#define SOFTWAIT(delay,limit) if (_pollStatus(delay,limit) != 0) return -2;
+//#define SOFTWAIT() while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(1);}
+//#define SOFTWAIT(x) while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(x);}
+//#define SOFTWAIT()
+
+// Use this macro to check for kernel errors
+#define CHECK_LAUNCH_ERROR() if (cudaGetLastError() != cudaSuccess) {return 0xFFFFFFFF; /* -1 */}
+
+
+typedef unsigned int uint;
+
+// OO interface to MemtestG80 functions
+class memtestState {
+protected:
+ const uint nBlocks;
+ const uint nThreads;
+ uint loopIters;
+ uint megsToTest;
+ int lcgPeriod;
+ uint* devTestMem;
+ uint* devTempMem;
+ uint* hostTempMem;
+ bool allocated;
+public:
+ uint initTime;
+ memtestState() : nBlocks(1024), nThreads(512), allocated(false), devTestMem(NULL),devTempMem(NULL),hostTempMem(NULL), initTime(0),lcgPeriod(1024) {};
+ ~memtestState() {deallocate();}
+
+ uint allocate(uint mbToTest);
+ void deallocate();
+ bool isAllocated() const {return allocated;}
+ uint size() const {return megsToTest;}
+ void setLCGPeriod(int period) {lcgPeriod = period;}
+ int getLCGPeriod() const {return lcgPeriod;}
+
+ bool gpuMemoryBandwidth(double& bandwidth,uint mbToTest,uint iters=5);
+ bool gpuWriteConstant(const uint constant) const;
+ bool gpuVerifyConstant(uint& errorCount,const uint constant) const;
+ bool gpuShortLCG0(uint& errorCount,const uint repeats) const;
+ bool gpuShortLCG0Shmem(uint& errorCount,const uint repeats) const;
+ bool gpuMovingInversionsOnesZeros(uint& errorCount) const;
+ bool gpuWalking8BitM86(uint& errorCount,const uint shift) const;
+ bool gpuWalking8Bit(uint& errorCount,const bool ones,const uint shift) const;
+ bool gpuMovingInversionsRandom(uint& errorCount) const;
+ bool gpuWalking32Bit(uint& errorCount,const bool ones,const uint shift) const;
+ bool gpuRandomBlocks(uint& errorCount,const uint seed) const;
+ bool gpuModuloX(uint& errorCount,const uint shift,const uint pattern,const uint modulus,const uint overwriteIters) const;
+};
+
+// Utility functions
+__host__ double gpuMemoryBandwidth(uint* src,uint* dst,uint mbToTest,uint iters);
+__host__ void gpuWriteConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);
+__host__ uint gpuVerifyConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant,uint* blockErrorCount,uint* errorCounts);
+
+__host__ void cpuWriteConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);
+__host__ uint cpuVerifyConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);
+
+// Logic tests
+__host__ uint gpuShortLCG0(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint repeats,const int period,uint* blockErrorCounts,uint* errorCounts);
+__host__ uint gpuShortLCG0Shmem(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint repeats,const int period,uint* blockErrorCounts,uint* errorCounts);
+
+// Memtest86 Test 2: tseq=0,4
+__host__ uint gpuMovingInversionsOnesZeros(const uint nBlocks,const uint nThreads,uint* base,uint N,uint* blockErrorCounts,uint* errorCounts);
+
+// Memtest86 Test 3: tseq=1
+__host__ uint gpuWalking8BitM86(const uint nBlocks,const uint nThreads,uint* base,uint N,uint shift,uint* blockErrorCounts,uint* errorCounts);
+__host__ uint cpuWalking8BitM86(const uint nBlocks,const uint nThreads,uint* base,uint N,uint shift);
+__host__ uint gpuWalking8Bit(const uint nBlocks,const uint nThreads,uint* base,uint N,bool ones,uint shift,uint* blockErrorCount,uint* errorCounts);
+
+// Memtest86 Test 4: tseq=10
+__host__ uint gpuMovingInversionsRandom(const uint nBlocks,const uint nThreads,uint* base,uint N,uint* blockErrorCounts,uint* errorCounts);
+
+// Memtest86 Test 6: tseq=2
+__host__ uint gpuWalking32Bit(const uint nBlocks,const uint nThreads,uint* base,uint N,bool ones,uint shift,uint* blockErrorCount,uint* errorCounts);
+//
+// Memtest86 Test 7: tseq=9
+__host__ uint gpuRandomBlocks(const uint nBlocks,const uint nThreads,uint* base,uint N,uint seed,uint* blockErrorCount,uint* errorCounts);
+
+// Memtest86 Test 8: tseq=3 (M86 uses modulus = 20)
+__host__ uint gpuModuloX(const uint nBlocks,const uint nThreads,uint* base,const uint N,uint shift,uint pattern1,const uint modulus,const uint iters,uint* blockErrorCount,uint* errorCounts);
+
+#endif
fprintf(fp,"\\subsection{Simulation settings}\n");
fprintf(fp,"A total of %g ns were simulated with a time step of %g fs.\n",
ir->nsteps*ir->delta_t*0.001,1000*ir->delta_t);
- fprintf(fp,"Neighborsearching was performed every %d steps.\n",ir->nstlist);
+ fprintf(fp,"Neighbor searching was performed every %d steps.\n",ir->nstlist);
fprintf(fp,"The %s algorithm was used for electrostatic interactions.\n",
EELTYPE(ir->coulombtype));
fprintf(fp,"with a cut-off of %g nm.\n",ir->rcoulomb);
off_t fpos;
real rdum,tt,old_t1,old_t2,prec;
bool bShowTimestep=TRUE,bOK,newline=FALSE;
- int status;
+ t_trxstatus *status;
gmx_mtop_t mtop;
gmx_localtop_t *top;
t_state state;
INC(fr,count,first,last,bF);
INC(fr,count,first,last,bBox);
#undef INC
- fpos = gmx_fio_ftell(status);
+ fpos = gmx_fio_ftell(trx_get_fileio(status));
} while (read_next_frame(oenv,status,&fr));
fprintf(stderr,"\n");
"radii) and atoms outside the box (these may occur often and are",
"no problem). If velocities are present, an estimated temperature",
"will be calculated from them.[PAR]",
- "If an index file is given it's contents will be sumamrized.[PAR]",
+ "If an index file, is given its contents will be summarized.[PAR]",
"If both a trajectory and a tpr file are given (with [TT]-s1[tt])",
"the program will check whether the bond lengths defined in the tpr",
"file are indeed correct in the trajectory. If not you may have",
"non-matching files due to e.g. deshuffling or due to problems with",
- "virtual sites. With these flags, gmxcheck provides a quick check for such problems.[PAR]"
- "The program can compare run two input ([TT].tpr[tt], [TT].tpb[tt] or",
+ "virtual sites. With these flags, gmxcheck provides a quick check for such problems.[PAR]",
+ "The program can compare two run input ([TT].tpr[tt], [TT].tpb[tt] or",
"[TT].tpa[tt]) files",
"when both [TT]-s1[tt] and [TT]-s2[tt] are supplied.",
"Similarly a pair of trajectory files can be compared (using the [TT]-f2[tt]",
"For free energy simulations the A and B state topology from one",
"run input file can be compared with options [TT]-s1[tt] and [TT]-ab[tt].[PAR]",
"In case the [TT]-m[tt] flag is given a LaTeX file will be written",
- "consisting a rough outline for a methods section for a paper."
+ "consisting of a rough outline for a methods section for a paper."
};
t_filenm fnm[] = {
{ efTRX, "-f", NULL, ffOPTRD },
static void list_trn(const char *fn)
{
- int fpread,fpwrite,nframe,indent;
+ t_fileio *fpread, *fpwrite;
+ int nframe,indent;
char buf[256];
rvec *x,*v,*f;
matrix box;
void list_xtc(const char *fn, bool bXVG)
{
- int xd,indent;
+ t_fileio *xd;
+ int indent;
char buf[256];
rvec *x;
matrix box;
{
int i;
+ /* Atom types are always case sensitive */
for (i=0; (i<ga->nr); i++)
- if (strcasecmp(str,*(ga->atomname[i])) == 0)
+ if (strcmp(str,*(ga->atomname[i])) == 0)
return i;
return NOTSET;
for(i=0; (i<ga->nr); i++) {
if (strcmp(*ga->atomname[i],name) == 0) {
- fprintf(stderr,"Trying to add atomtype %s again. Skipping it.\n",name);
+ if (NULL != debug)
+ fprintf(debug,"Trying to add atomtype %s again. Skipping it.\n",name);
break;
}
}
/* If fr_time == -1 read the last frame available which is complete */
{
t_trxframe fr;
- int fp;
+ t_trxstatus *fp;
fprintf(stderr,
"Reading Coordinates%s and Box size from old trajectory\n",
"unless the [TT]-time[tt] option is used.",
"Note that these velocities will not be used when [TT]gen_vel = yes[tt]",
"in your [TT].mdp[tt] file. An energy file can be supplied with",
- "[TT]-e[tt] to have exact restarts when using pressure and/or",
- "Nose-Hoover temperature coupling. For an exact restart do not forget",
- "to turn off velocity generation and turn on unconstrained starting",
- "when constraints are present in the system.",
- "If you want to continue a crashed run, it is",
- "easier to use [TT]tpbconv[tt].[PAR]",
+ "[TT]-e[tt] to read Nose-Hoover and/or Parrinello-Rahman coupling",
+ "variables. Note that for continuation it is better and easier to supply",
+ "a checkpoint file directly to mdrun, since that always contains",
+ "the complete state of the system and you don't need to generate",
+ "a new run input file. Note that if you only want to change the number",
+ "of run steps tpbconv is more convenient than grompp.[PAR]",
"Using the [TT]-morse[tt] option grompp can convert the harmonic bonds",
"in your topology to morse potentials. This makes it possible to break",
static int i,maxwarn=0;
static real fr_time=-1;
t_pargs pa[] = {
+ { "-v", FALSE, etBOOL,{&bVerbose},
+ "Be loud and noisy" },
{ "-time", FALSE, etREAL, {&fr_time},
"Take frame at or first after this time." },
{ "-rmvsbds",FALSE, etBOOL, {&bRmVSBds},
/* Parse the command line */
parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa,
asize(desc),desc,0,NULL,&oenv);
- bVerbose = (output_env_get_verbosity(oenv) > 0);
wi = init_warning(TRUE,maxwarn);
if (ir->ePBC==epbcXY && ir->nwall==2)
svmul(ir->wall_ewald_zfac,box[ZZ],box[ZZ]);
max_spacing = calc_grid(stdout,box,opts->fourierspacing,
- &(ir->nkx),&(ir->nky),&(ir->nkz),1);
+ &(ir->nkx),&(ir->nky),&(ir->nkz));
if ((ir->coulombtype == eelPPPM) && (max_spacing > 0.1)) {
set_warning_line(wi,mdparin,-1);
warning_note(wi,"Grid spacing larger then 0.1 while using PPPM.");
hack->nctl = ns - 3;
if ((hack->nctl != ncontrol[hack->tp]) && (ncontrol[hack->tp] != -1))
gmx_fatal(FARGS,"Error in hdb file %s:\nWrong number of control atoms (%d iso %d) on line:\n%s\n",fn,hack->nctl,ncontrol[hack->tp],line);
- for(i=0; (i<hack->nctl); i++)
+ for(i=0; (i<hack->nctl); i++) {
hack->a[i]=strdup(a[i]);
- for( ; i<4; i++)
+ }
+ for( ; i<4; i++) {
hack->a[i]=NULL;
+ }
hack->oname=NULL;
hack->nname=strdup(hn);
hack->atom=NULL;
hack->cgnr=NOTSET;
+ hack->bXSet=FALSE;
for(i=0; i<DIM; i++)
hack->newx[i]=NOTSET;
}
*ah = aah;
}
-int read_h_db(const char *ffdir,t_hackblock **ah)
+int read_h_db(const char *ffdir,bool bAddCWD,t_hackblock **ah)
{
int nhdbf,f;
char **hdbf;
/* Read the hydrogen database file(s).
* Do not generate an error when no files are found.
*/
- nhdbf = fflib_search_file_end(ffdir,".hdb",FALSE,&hdbf);
+ nhdbf = fflib_search_file_end(ffdir,bAddCWD,".hdb",FALSE,&hdbf);
nah = 0;
*ah = NULL;
for(f=0; f<nhdbf; f++) {
extern void read_ab(char *line,const char *fn,t_hack *ab);
/* Read one add block */
-extern int read_h_db(const char *ffdir,t_hackblock **ah);
+extern int read_h_db(const char *ffdir,bool bAddCWD,t_hackblock **ah);
/* Read the database from hdb file(s) in ffdir or current dir */
extern void print_ab(FILE *out,t_hack *ab,char *nname);
bool bHDd,bHEd;
rvec xh1,xh2;
int natom;
- int i,j,nd,na,aj,hisind,his0,type=-1;
+ int i,nd,na,aj,hisind,his0,type=-1;
int nd1,ne2,cg,cd2,ce1;
t_blocka *hb;
real d;
/* Find the atoms in the ring */
nd1=ne2=cg=cd2=ce1=-1;
- for(j=i; (pdba->atom[j].resind==hisind) && (j<natom); j++) {
- atomnm=*pdba->atomname[j];
+ while (i<natom && pdba->atom[i].resind==hisind) {
+ atomnm = *pdba->atomname[i];
if (strcmp(atomnm,"CD2") == 0)
- cd2=j;
+ cd2 = i;
else if (strcmp(atomnm,"CG") == 0)
- cg=j;
+ cg = i;
else if (strcmp(atomnm,"CE1") == 0)
- ce1=j;
+ ce1 = i;
else if (strcmp(atomnm,"ND1") == 0)
- nd1=j;
+ nd1 = i;
else if (strcmp(atomnm,"NE2") == 0)
- ne2=j;
+ ne2 = i;
+
+ i++;
}
if (!((cg == -1 ) || (cd2 == -1) || (ce1 == -1) ||
gmx_fatal(FARGS,"Incomplete ring in HIS%d",
pdba->resinfo[hisind].nr);
- sfree(*pdba->resinfo[hisind].name);
- *pdba->resinfo[hisind].name = strdup(hh[type]);
+ snew(pdba->resinfo[hisind].rtp,1);
+ *pdba->resinfo[hisind].rtp = strdup(hh[type]);
}
}
}
#endif
-
-enum { eglsNABNSB, eglsCHKPT, eglsTERM, eglsRESETCOUNTERS, eglsNR };
+/* simulation conditions to transmit. Keep in mind that they are
+ transmitted to other nodes through an MPI_Reduce after
+ casting them to a real (so the signals can be sent together with other
+ data). This means that the only meaningful values are positive,
+ negative or zero. */
+enum { eglsNABNSB, eglsCHKPT, eglsSTOPCOND, eglsRESETCOUNTERS, eglsNR };
/* Is the signal in one simulation independent of other simulations? */
bool gs_simlocal[eglsNR] = { TRUE, FALSE, FALSE, TRUE };
/* we calculate a full state kinetic energy either with full-step velocity verlet
or half step where we need the pressure */
- bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir) && bPres) || bReadEkin);
-
+ /*bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir) && bPres) || bReadEkin);*/
+
+ bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && bPres) || bReadEkin);
+
/* in initalization, it sums the shake virial in vv, and to
- sums ekinh_old in leapfrog (or if we are calculating ekinh_old for other reasons */
+ sums ekinh_old in leapfrog (or if we are calculating ekinh_old) for other reasons */
/* ########## Kinetic energy ############## */
if (bTemp)
{
/* Sum the kinetic energies of the groups & calc temp */
- /* compute full step kinetic energies if vv, or if vv2 and we are computing the pressure with IR_NPT_TROTTER */
+ /* compute full step kinetic energies if vv, or if vv-avek and we are computing the pressure with IR_NPT_TROTTER */
/* three maincase: VV with AveVel (md-vv), vv with AveEkin (md-vv-avek), leap with AveEkin (md).
- Leap with AveVel is also an option for the future but not supported now.
+ Leap with AveVel is not supported; it's not clear that it will actually work.
bEkinAveVel: If TRUE, we simply multiply ekin by ekinscale to get a full step kinetic energy.
If FALSE, we average ekinh_old and ekinh*ekinscale_nhc to get an averaged half step kinetic energy.
bSaveEkinOld: If TRUE (in the case of iteration = bIterate is TRUE), we don't reset the ekinscale_nhc.
}
check_nst_param(fplog,cr,"nstlist",ir->nstlist,
"nstcalcenergy",&ir->nstcalcenergy);
- }
- check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
- "nstenergy",&ir->nstenergy);
- check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
- "nstlog",&ir->nstlog);
- if (ir->efep != efepNO)
- {
- check_nst_param(fplog,cr,"nstdhdl",ir->nstdhdl,
+ check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
"nstenergy",&ir->nstenergy);
+ check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+ "nstlog",&ir->nstlog);
+ if (ir->efep != efepNO)
+ {
+ check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+ "nstdhdl",&ir->nstdhdl);
+ }
}
}
}
}
+static void rerun_parallel_comm(t_commrec *cr,t_trxframe *fr,
+ bool *bNotLastFrame)
+{
+ bool bAlloc;
+ rvec *xp,*vp;
+
+ bAlloc = (fr->natoms == 0);
+
+ if (MASTER(cr) && !*bNotLastFrame)
+ {
+ fr->natoms = -1;
+ }
+ xp = fr->x;
+ vp = fr->v;
+ gmx_bcast(sizeof(*fr),fr,cr);
+ fr->x = xp;
+ fr->v = vp;
+
+ *bNotLastFrame = (fr->natoms >= 0);
+
+ if (*bNotLastFrame && PARTDECOMP(cr))
+ {
+ /* x and v are the only variable size quantities stored in trr
+ * that are required for rerun (f is not needed).
+ */
+ if (bAlloc)
+ {
+ snew(fr->x,fr->natoms);
+ snew(fr->v,fr->natoms);
+ }
+ if (fr->bX)
+ {
+ gmx_bcast(fr->natoms*sizeof(fr->x[0]),fr->x[0],cr);
+ }
+ if (fr->bV)
+ {
+ gmx_bcast(fr->natoms*sizeof(fr->v[0]),fr->v[0],cr);
+ }
+ }
+}
+
double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
const output_env_t oenv, bool bVerbose,bool bCompact,
int nstglobalcomm,
gmx_large_int_t step,step_rel;
double run_time;
double t,t0,lam0;
- bool bGStatEveryStep,bGStat,bNstEner,bCalcPres,bCalcEner;
+ bool bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres;
bool bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
bFirstStep,bStateFromTPX,bInitStep,bLastStep,
bBornRadii,bStartingFromCpt;
bool bMasterState;
int force_flags,cglo_flags;
tensor force_vir,shake_vir,total_vir,tmp_vir,pres;
- int i,m,status;
+ int i,m;
+ t_trxstatus *status;
rvec mu_tot;
t_vcm *vcm;
t_state *bufstate=NULL;
bool bTCR=FALSE,bConverged=TRUE,bOK,bSumEkinhOld,bExchanged;
bool bAppend;
bool bResetCountersHalfMaxH=FALSE;
- bool bVV,bIterations,bIterate,bFirstIterate,bTemp,bPres,bTrotter;
+ bool bVV,bIterations,bFirstIterate,bTemp,bPres,bTrotter;
real temp0,mu_aver=0,dvdl;
int a0,a1,gnx=0,ii;
atom_id *grpindex=NULL;
t_extmass MassQ;
int **trotter_seq;
char sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
- int handledSignal=-1; /* compare to last_signal_recvd */
+ int handled_stop_condition=gmx_stop_cond_none; /* compare to get_stop_condition*/
gmx_iterate_t iterate;
#ifdef GMX_FAHCORE
/* Temporary addition for FAHCORE checkpointing */
}
/* md-vv uses averaged full step velocities for T-control
- md-vv2 uses averaged half step velocities for T-control (but full step ekin for P control)
+ md-vv-avek uses averaged half step velocities for T-control (but full step ekin for P control)
md uses averaged half step kinetic energies to determine temperature unless defined otherwise by GMX_EKIN_AVE_VEL; */
bVV = EI_VV(ir->eI);
if (bVV) /* to store the initial velocities while computing virial */
top_global,&pcurr,top_global->natoms,&bSumEkinhOld,cglo_flags);
if (ir->eI == eiVVAK) {
/* a second call to get the half step temperature initialized as well */
- /* we do the same call as above, but turn the pressure off -- internally, this
- is recognized as a velocity verlet half-step kinetic energy calculation.
- This minimized excess variables, but perhaps loses some logic?*/
+ /* we do the same call as above, but turn the pressure off -- internally to
+ compute_globals, this is recognized as a velocity verlet half-step
+ kinetic energy calculation. This minimized excess variables, but
+ perhaps loses some logic?*/
compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
"RMS relative constraint deviation after constraining: %.2e\n",
constr_rmsd(constr,FALSE));
}
- if (bVV)
+ if (!bVV)
{
enerd->term[F_TEMP] *= 2; /* result of averages being done over previous and current step,
and there is no previous step */
bForceUpdate = TRUE;
}
- bNotLastFrame = read_first_frame(oenv,&status,
- opt2fn("-rerun",nfile,fnm),
- &rerun_fr,TRX_NEED_X | TRX_READ_V);
- if (rerun_fr.natoms != top_global->natoms)
- {
- gmx_fatal(FARGS,
- "Number of atoms in trajectory (%d) does not match the "
- "run input file (%d)\n",
- rerun_fr.natoms,top_global->natoms);
- }
- if (ir->ePBC != epbcNONE)
+ rerun_fr.natoms = 0;
+ if (MASTER(cr))
{
- if (!rerun_fr.bBox)
+ bNotLastFrame = read_first_frame(oenv,&status,
+ opt2fn("-rerun",nfile,fnm),
+ &rerun_fr,TRX_NEED_X | TRX_READ_V);
+ if (rerun_fr.natoms != top_global->natoms)
{
- gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
+ gmx_fatal(FARGS,
+ "Number of atoms in trajectory (%d) does not match the "
+ "run input file (%d)\n",
+ rerun_fr.natoms,top_global->natoms);
}
- if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
+ if (ir->ePBC != epbcNONE)
{
- gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
+ if (!rerun_fr.bBox)
+ {
+ gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
+ }
+ if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
+ {
+ gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
+ }
}
+ }
+
+ if (PAR(cr))
+ {
+ rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
+ }
+ if (ir->ePBC != epbcNONE)
+ {
/* Set the shift vectors.
* Necessary here when have a static box different from the tpr box.
*/
}
}
- if (gs.set[eglsTERM] > 0 || (gs.set[eglsTERM] < 0 && bNS))
+ /* < 0 means stop at next step, > 0 means stop at next NS step */
+ if ( (gs.set[eglsSTOPCOND] < 0 ) ||
+ ( (gs.set[eglsSTOPCOND] > 0 ) && ( bNS || ir->nstlist==0)) )
{
bLastStep = TRUE;
}
gs.set[eglsCHKPT] = 0;
}
- /* Determine the pressure:
- * always when we want exact averages in the energy file,
- * at ns steps when we have pressure coupling,
- * otherwise only at energy output steps (set below).
+ /* Determine the energy and pressure:
+ * at nstcalcenergy steps and at energy output steps (set below).
*/
bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
- bCalcEner = bNstEner;
- bCalcPres = (bNstEner || (ir->epc != epcNO && bNS));
+ bCalcEnerPres = bNstEner;
/* Do we need global communication ? */
- bGStat = (bCalcEner || bStopCM ||
+ bGStat = (bCalcEnerPres || bStopCM ||
(ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
if (do_ene || do_log)
{
- bCalcPres = TRUE;
- bCalcEner = TRUE;
- bGStat = TRUE;
+ bCalcEnerPres = TRUE;
+ bGStat = TRUE;
}
/* these CGLO_ options remain the same throughout the iteration */
GMX_FORCE_ALLFORCES |
(bNStList ? GMX_FORCE_DOLR : 0) |
GMX_FORCE_SEPLRF |
- (bCalcEner ? GMX_FORCE_VIRIAL : 0) |
+ (bCalcEnerPres ? GMX_FORCE_VIRIAL : 0) |
(bDoDHDL ? GMX_FORCE_DHDL : 0)
);
if (!bStartingFromCpt && !bRerunMD)
{
- if (ir->eI == eiVV)
+ if (ir->eI==eiVV && bInitStep)
{
- if (bInitStep)
- {
- /* if using velocity verlet with full time step Ekin,
- * take the first half step only to compute the
- * virial for the first step. From there,
- * revert back to the initial coordinates
- * so that the input is actually the initial step.
- */
- copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
- }
-
+ /* if using velocity verlet with full time step Ekin,
+ * take the first half step only to compute the
+ * virial for the first step. From there,
+ * revert back to the initial coordinates
+ * so that the input is actually the initial step.
+ */
+ copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
+ } else {
/* this is for NHC in the Ekin(t+dt/2) version of vv */
- if (!bInitStep)
- {
- trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[1]);
- }
-
- update_coords(fplog,step,ir,mdatoms,state,
- f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
- ekind,M,wcycle,upd,bInitStep,etrtVELOCITY,
- cr,nrnb,constr,&top->idef);
-
- if (bIterations)
- {
- gmx_iterate_init(&iterate,bIterations && !bInitStep);
- }
- /* for iterations, we save these vectors, as we will be self-consistently iterating
- the calculations */
- /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
-
- /* save the state */
- if (bIterations && iterate.bIterate) {
- copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
- }
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[1]);
+ }
+
+ update_coords(fplog,step,ir,mdatoms,state,
+ f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+ ekind,M,wcycle,upd,bInitStep,etrtVELOCITY,
+ cr,nrnb,constr,&top->idef);
+
+ if (bIterations)
+ {
+ gmx_iterate_init(&iterate,bIterations && !bInitStep);
+ }
+ /* for iterations, we save these vectors, as we will be self-consistently iterating
+ the calculations */
+ /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
+
+ /* save the state */
+ if (bIterations && iterate.bIterate) {
+ copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
}
bFirstIterate = TRUE;
of veta. */
veta_save = state->veta;
- trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[0]);
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[0]);
vetanew = state->veta;
state->veta = veta_save;
}
update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
&top->idef,shake_vir,NULL,
cr,nrnb,wcycle,upd,constr,
- bInitStep,TRUE,bCalcPres,vetanew);
+ bInitStep,TRUE,bCalcEnerPres,vetanew);
if (!bOK && !bFFscan)
{
if (bVV) {
/* if VV, compute the pressure and constraints */
- /* if VV2, the pressure and constraints only if using pressure control.*/
- bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir));
- bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));
+ /* For VV2, we strictly only need this if using pressure control, but we really would
+ like to have accurate pressures printed out. Think about ways around this in the future?
+ For now, keep this choice in comments */
+ /*bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir)); */
+ /*bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));*/
+ bPres = TRUE;
+ bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK));
compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
constr,NULL,FALSE,state->box,
| (bTemp ? CGLO_TEMPERATURE:0)
| (bPres ? CGLO_PRESSURE : 0)
| (bPres ? CGLO_CONSTRAINT : 0)
- | (iterate.bIterate ? CGLO_ITERATE : 0)
+ | ((bIterations && iterate.bIterate) ? CGLO_ITERATE : 0)
| (bFirstIterate ? CGLO_FIRSTITERATE : 0)
| CGLO_SCALEEKIN
);
a) We compute Ekin at the full time step
if 1) we are using the AveVel Ekin, and it's not the
initial step, or 2) if we are using AveEkin, but need the full
- time step kinetic energy for the pressure.
+ time step kinetic energy for the pressure (always true now, since we want accurate statistics).
b) If we are using EkinAveEkin for the kinetic energy for the temperture control, we still feed in
EkinAveVel because it's needed for the pressure */
/* temperature scaling and pressure scaling to produce the extended variables at t+dt */
if (bVV && !bInitStep)
{
- trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[2]);
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[2]);
}
if (bIterations &&
*/
bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
- bCalcEner = bNstEner;
- bCalcPres = (bNstEner || (ir->epc != epcNO && bNS));
+ bCalcEnerPres = bNstEner;
/* Do we need global communication ? */
bGStat = (bGStatEveryStep || bStopCM || bNS ||
if (do_ene || do_log)
{
- bCalcPres = TRUE;
- bGStat = TRUE;
+ bCalcEnerPres = TRUE;
+ bGStat = TRUE;
}
/* Determine the wallclock run time up till now */
run_time = gmx_gettime() - (double)runtime->real;
/* Check whether everything is still allright */
- if ((bGotStopNextStepSignal || bGotStopNextNSStepSignal) &&
- (handledSignal!=last_signal_number_recvd) &&
+ if (((int)gmx_get_stop_condition() > handled_stop_condition) &&
MASTERTHREAD(cr))
{
- if (bGotStopNextStepSignal || ir->nstlist == 0)
- {
- gs.sig[eglsTERM] = 1;
- }
- else
- {
- gs.sig[eglsTERM] = -1;
- }
+ /* this is just make gs.sig compatible with the hack
+ of sending signals around by MPI_Reduce with together with
+ other floats */
+ if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
+ gs.sig[eglsSTOPCOND]=1;
+ if ( gmx_get_stop_condition() == gmx_stop_cond_next )
+ gs.sig[eglsSTOPCOND]=-1;
+ /* < 0 means stop at next step, > 0 means stop at next NS step */
if (fplog)
{
fprintf(fplog,
"\n\nReceived the %s signal, stopping at the next %sstep\n\n",
- signal_name[last_signal_number_recvd],
- gs.sig[eglsTERM]==-1 ? "NS " : "");
+ gmx_get_signal_name(),
+ gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
fflush(fplog);
}
fprintf(stderr,
"\n\nReceived the %s signal, stopping at the next %sstep\n\n",
- signal_name[last_signal_number_recvd],
- gs.sig[eglsTERM]==-1 ? "NS " : "");
+ gmx_get_signal_name(),
+ gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
fflush(stderr);
- handledSignal=last_signal_number_recvd;
+ handled_stop_condition=(int)gmx_get_stop_condition();
}
else if (MASTER(cr) && (bNS || ir->nstlist <= 0) &&
(max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
- gs.sig[eglsTERM] == 0)
+ gs.sig[eglsSTOPCOND] == 0 && gs.set[eglsSTOPCOND] == 0)
{
/* Signal to terminate the run */
- gs.sig[eglsTERM] = (ir->nstlist == 0 ? 1 : -1);
+ gs.sig[eglsSTOPCOND] = 1;
if (fplog)
{
fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
/* ######### START SECOND UPDATE STEP ################# */
GMX_MPE_LOG(ev_update_start);
+ /* Box is changed in update() when we do pressure coupling,
+ * but we should still use the old box for energy corrections and when
+ * writing it to the energy file, so it matches the trajectory files for
+ * the same timestep above. Make a copy in a separate array.
+ */
+ copy_mat(state->box,lastbox);
+
bOK = TRUE;
- if (!bRerunMD || rerun_fr.bV || bForceUpdate)
+ if (!(bRerunMD && !rerun_fr.bV && !bForceUpdate))
{
wallcycle_start(wcycle,ewcUPDATE);
dvdl = 0;
- /* Box is changed in update() when we do pressure coupling,
- * but we should still use the old box for energy corrections and when
- * writing it to the energy file, so it matches the trajectory files for
- * the same timestep above. Make a copy in a separate array.
- */
- copy_mat(state->box,lastbox);
/* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
if (bTrotter)
{
m_add(force_vir,shake_vir,total_vir);
clear_mat(shake_vir);
}
- trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[3]);
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[3]);
}
/* We can only do Berendsen coupling after we have summed
* the kinetic energy or virial. Since the happens
update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
&top->idef,shake_vir,force_vir,
cr,nrnb,wcycle,upd,constr,
- bInitStep,FALSE,bCalcPres,state->veta);
+ bInitStep,FALSE,bCalcEnerPres,state->veta);
if (ir->eI==eiVVAK)
{
wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
constr,NULL,FALSE,lastbox,
top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
- cglo_flags | CGLO_TEMPERATURE | CGLO_CONSTRAINT
+ cglo_flags | CGLO_TEMPERATURE
);
wallcycle_start(wcycle,ewcUPDATE);
- trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[4]);
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[4]);
/* now we know the scaling, we can compute the positions again again */
copy_rvecn(cbuf,state->x,0,state->natoms);
update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
&top->idef,tmp_vir,force_vir,
cr,nrnb,wcycle,upd,NULL,
- bInitStep,FALSE,bCalcPres,state->veta);
+ bInitStep,FALSE,bCalcEnerPres,
+ state->veta);
}
if (!bOK && !bFFscan)
{
/* Remaining runtime */
- if (MULTIMASTER(cr) && do_verbose)
+ if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
{
if (shellfc)
{
bExchanged = replica_exchange(fplog,cr,repl_ex,
state_global,enerd->term,
state,step,t);
- }
- if (bExchanged && PAR(cr))
- {
- if (DOMAINDECOMP(cr))
+
+ if (bExchanged && DOMAINDECOMP(cr))
{
dd_partition_system(fplog,step,cr,TRUE,1,
state_global,top_global,ir,
state,&f,mdatoms,top,fr,
vsite,shellfc,constr,
nrnb,wcycle,FALSE);
- }
- else
- {
- bcast_state(cr,state,FALSE);
}
}
if (bRerunMD)
{
- /* read next frame from input trajectory */
- bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
+ if (MASTER(cr))
+ {
+ /* read next frame from input trajectory */
+ bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
+ }
+
+ if (PAR(cr))
+ {
+ rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
+ }
}
if (!bRerunMD || !rerun_fr.bStep)
/* Reset all the counters related to performance over the run */
reset_all_counters(fplog,cr,step,&step_rel,ir,wcycle,nrnb,runtime);
wcycle_set_reset_counters(wcycle,-1);
+ /* Correct max_hours for the elapsed time */
+ max_hours -= run_time/(60.0*60.0);
bResetCountersHalfMaxH = FALSE;
gs.set[eglsRESETCOUNTERS] = 0;
}
/* Stop the time */
runtime_end(runtime);
- if (bRerunMD)
+ if (bRerunMD && MASTER(cr))
{
close_trj(status);
}
if (MASTER(cr))
{
- if (bGStatEveryStep && !bRerunMD)
+ if (ir->nstcalcenergy > 0 && !bRerunMD)
{
print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/* include even when OpenMM not used to force compilation of do_md_openmm */
#include "openmm_wrapper.h"
+/* simulation conditions to transmit */
+enum { eglsNABNSB, eglsCHKPT, eglsSTOPCOND, eglsRESETCOUNTERS, eglsNR };
-enum { eglsNABNSB, eglsCHKPT, eglsTERM, eglsRESETCOUNTERS, eglsNR };
-
-typedef struct {
+typedef struct
+{
int nstms; /* The frequency for intersimulation communication */
int sig[eglsNR]; /* The signal set by one process in do_md */
int set[eglsNR]; /* The communicated signal, equal for all processes */
gmx_sumi_sim(ms->nsim,buf,ms);
bPos = TRUE;
bEqual = TRUE;
- for(s=0; s<ms->nsim; s++)
+ for (s=0; s<ms->nsim; s++)
{
bPos = bPos && (buf[s] > 0);
bEqual = bEqual && (buf[s] == buf[0]);
else
{
/* Find the least common multiple */
- for(d=2; d<nmin; d++)
+ for (d=2; d<nmin; d++)
{
s = 0;
while (s < ms->nsim && d % buf[s] == 0)
gs->nstms = 1;
- for(i=0; i<eglsNR; i++)
+ for (i=0; i<eglsNR; i++)
{
gs->sig[i] = 0;
gs->set[i] = 0;
double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
- const output_env_t oenv, bool bVerbose,bool bCompact,
- int nstglobalcomm,
- gmx_vsite_t *vsite,gmx_constr_t constr,
- int stepout,t_inputrec *ir,
- gmx_mtop_t *top_global,
- t_fcdata *fcd,
- t_state *state_global,
- t_mdatoms *mdatoms,
- t_nrnb *nrnb,gmx_wallcycle_t wcycle,
- gmx_edsam_t ed,t_forcerec *fr,
- int repl_ex_nst,int repl_ex_seed,
- real cpt_period,real max_hours,
- const char *deviceOptions,
- unsigned long Flags,
- gmx_runtime_t *runtime)
+ const output_env_t oenv, bool bVerbose,bool bCompact,
+ int nstglobalcomm,
+ gmx_vsite_t *vsite,gmx_constr_t constr,
+ int stepout,t_inputrec *ir,
+ gmx_mtop_t *top_global,
+ t_fcdata *fcd,
+ t_state *state_global,
+ t_mdatoms *mdatoms,
+ t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+ gmx_edsam_t ed,t_forcerec *fr,
+ int repl_ex_nst,int repl_ex_seed,
+ real cpt_period,real max_hours,
+ const char *deviceOptions,
+ unsigned long Flags,
+ gmx_runtime_t *runtime)
{
gmx_mdoutf_t *outf;
gmx_large_int_t step,step_rel;
double run_time;
double t,t0,lam0;
bool bSimAnn,
- bFirstStep,bStateFromTPX,bLastStep,bStartingFromCpt;
+ bFirstStep,bStateFromTPX,bLastStep,bStartingFromCpt;
bool bInitStep=TRUE;
bool bNEMD,do_ene,do_log, do_verbose,
- bX,bV,bF,bXTC,bCPT;
+ bX,bV,bF,bCPT;
tensor force_vir,shake_vir,total_vir,pres;
int i,m;
int mdof_flags;
rvec mu_tot;
t_vcm *vcm;
int nchkpt=1;
- gmx_localtop_t *top;
+ gmx_localtop_t *top;
t_mdebin *mdebin=NULL;
t_state *state=NULL;
rvec *f_global=NULL;
matrix lastbox;
real reset_counters=0,reset_counters_now=0;
char sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
- int handledSignal=-1; /* compare to last_signal_recvd */
- bool bHandledSignal=FALSE;
-
+ int handled_stop_condition=gmx_stop_cond_none;
+
const char *ommOptions = NULL;
void *openmmData;
/* needed for iteration of constraints */
snew(ekind_save,1);
init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
- /* Copy the cos acceleration to the groups struct */
+ /* Copy the cos acceleration to the groups struct */
ekind->cosacc.cos_accel = ir->cos_accel;
gstat = global_stat_init(ir);
io);
}
- top = gmx_mtop_generate_local_top(top_global,ir);
+ top = gmx_mtop_generate_local_top(top_global,ir);
- a0 = 0;
- a1 = top_global->natoms;
+ a0 = 0;
+ a1 = top_global->natoms;
- state = partdec_init_local_state(cr,state_global);
- f_global = f;
+ state = partdec_init_local_state(cr,state_global);
+ f_global = f;
- atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
+ atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
- if (vsite) {
- set_vsite_top(vsite,top,mdatoms,cr);
- }
+ if (vsite)
+ {
+ set_vsite_top(vsite,top,mdatoms,cr);
+ }
- if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) {
- graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
- }
+ if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
+ {
+ graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
+ }
update_mdatoms(mdatoms,state->lambda);
-
- if(deviceOptions[0]=='\0')
- {
- /* empty options, which should default to OpenMM in this build */
- ommOptions=deviceOptions;
- }
- else
- {
- if(gmx_strncasecmp(deviceOptions,"OpenMM",6)!=0)
- {
- gmx_fatal(FARGS, "This Gromacs version currently only works with OpenMM. Use -device \"OpenMM:<options>\"");
- }
- else
- {
- ommOptions=strchr(deviceOptions,':');
- if(NULL!=ommOptions)
- {
- /* Increase the pointer to skip the colon */
- ommOptions++;
- }
- }
- }
-
- openmmData = openmm_init(fplog, ommOptions, cr, ir, top_global, top, mdatoms, fr, state);
+ if (deviceOptions[0]=='\0')
+ {
+ /* empty options, which should default to OpenMM in this build */
+ ommOptions=deviceOptions;
+ }
+ else
+ {
+ if (gmx_strncasecmp(deviceOptions,"OpenMM",6)!=0)
+ {
+ gmx_fatal(FARGS, "This Gromacs version currently only works with OpenMM. Use -device \"OpenMM:<options>\"");
+ }
+ else
+ {
+ ommOptions=strchr(deviceOptions,':');
+ if (NULL!=ommOptions)
+ {
+ /* Increase the pointer to skip the colon */
+ ommOptions++;
+ }
+ }
+ }
+ openmmData = openmm_init(fplog, ommOptions, ir, top_global, top, mdatoms, fr, state);
if (MASTER(cr))
{
}
/* Set the initial energy history in state to zero by updating once */
update_energyhistory(&state_global->enerhist,mdebin);
- }
+ }
- if (constr) {
- set_constraints(constr,top,ir,mdatoms,cr);
+ if (constr)
+ {
+ set_constraints(constr,top,ir,mdatoms,cr);
}
if (!ir->bContinuation)
if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
{
/* Set the velocities of frozen particles to zero */
- for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
+ for (i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
{
- for(m=0; m<DIM; m++)
+ for (m=0; m<DIM; m++)
{
if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
{
}
debug_gmx();
-
+
if (MASTER(cr))
{
char tbuf[20];
debug_gmx();
/***********************************************************
*
- * Loop over MD steps
+ * Loop over MD steps
*
************************************************************/
step = ir->init_step;
step_rel = 0;
- bLastStep = ((ir->nsteps >= 0 && step_rel > ir->nsteps));
-
- while (!bLastStep) {
-
+ while (!bLastStep)
+ {
wallcycle_start(wcycle,ewcSTEP);
GMX_MPE_LOG(ev_timestep1);
bLastStep = (step_rel == ir->nsteps);
t = t0 + step*ir->delta_t;
- if (gs.set[eglsTERM] != 0 )
+ if (gs.set[eglsSTOPCOND] != 0)
{
bLastStep = TRUE;
}
do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
do_verbose = bVerbose &&
- (step % stepout == 0 || bFirstStep || bLastStep);
+ (step % stepout == 0 || bFirstStep || bLastStep);
if (MASTER(cr) && do_log)
{
gs.set[eglsCHKPT] = 0;
}
- /* Now we have the energies and forces corresponding to the
+ /* Now we have the energies and forces corresponding to the
* coordinates at time t. We must output all of this before
* the update.
* for RerunMD t is read from input trajectory
GMX_MPE_LOG(ev_output_start);
mdof_flags = 0;
- if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; }
- if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; }
- if (do_per_step(step,ir->nstfout)) { mdof_flags |= MDOF_F; }
- if (do_per_step(step,ir->nstxtcout)) { mdof_flags |= MDOF_XTC; }
- if (bCPT) { mdof_flags |= MDOF_CPT; };
- bX = MDOF_X || (bLastStep && ir->nstxout);
- bV = MDOF_V || (bLastStep && ir->nstvout);
- bF = MDOF_F || (bLastStep && ir->nstfout);
- bXTC = MDOF_XTC || (bLastStep && ir->nstxtcout);
- do_ene = do_per_step(step,ir->nstenergy) || (bLastStep && ir->nstenergy);
-
- if( bX || bXTC || bV ){
- wallcycle_start(wcycle,ewcTRAJ);
- openmm_copy_state(openmmData, state, &t, f, enerd, bX||bXTC, bV, 0, 0);
- wallcycle_stop(wcycle,ewcTRAJ);
- }
-
- openmm_take_one_step(openmmData);
-
- if (bX || bV || bF || bXTC || do_ene) {
- wallcycle_start(wcycle,ewcTRAJ);
- if( bF || do_ene ){
- openmm_copy_state(openmmData, state, &t, f, enerd, 0, 0, bF, do_ene);
- }
- upd_mdebin(mdebin, NULL,TRUE,
- t,mdatoms->tmass,enerd,state,lastbox,
- shake_vir,force_vir,total_vir,pres,
- ekind,mu_tot,constr);
- print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,fplog,step,t,
- eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+ if (do_per_step(step,ir->nstxout))
+ {
+ mdof_flags |= MDOF_X;
+ }
+ if (do_per_step(step,ir->nstvout))
+ {
+ mdof_flags |= MDOF_V;
+ }
+ if (do_per_step(step,ir->nstfout))
+ {
+ mdof_flags |= MDOF_F;
+ }
+ if (do_per_step(step,ir->nstxtcout))
+ {
+ mdof_flags |= MDOF_XTC;
+ }
+ if (bCPT)
+ {
+ mdof_flags |= MDOF_CPT;
+ };
+ do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+ if (mdof_flags != 0)
+ {
+ bX = (mdof_flags & (MDOF_X | MDOF_XTC | MDOF_CPT));
+ bV = (mdof_flags & (MDOF_V | MDOF_CPT));
+ wallcycle_start(wcycle,ewcTRAJ);
+ openmm_copy_state(openmmData, state, &t, f, enerd, bX, bV, 0, 0);
+ wallcycle_stop(wcycle,ewcTRAJ);
+ }
+
+ openmm_take_one_step(openmmData);
+
+ if (mdof_flags != 0 || do_ene || do_log)
+ {
+ wallcycle_start(wcycle,ewcTRAJ);
+ bF = (mdof_flags & MDOF_F);
+ if (bF || do_ene || do_log)
+ {
+ openmm_copy_state(openmmData, state, &t, f, enerd, 0, 0, bF, do_ene);
+ }
+ upd_mdebin(mdebin, NULL,TRUE,
+ t,mdatoms->tmass,enerd,state,lastbox,
+ shake_vir,force_vir,total_vir,pres,
+ ekind,mu_tot,constr);
+ print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,do_log?fplog:NULL,
+ step,t,
+ eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
write_traj(fplog,cr,outf,mdof_flags,top_global,
step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
if (bCPT)
}
debug_gmx();
if (bLastStep && step_rel == ir->nsteps &&
- (Flags & MD_CONFOUT) && MASTER(cr))
+ (Flags & MD_CONFOUT) && MASTER(cr))
{
/* x and v have been collected in write_traj,
* because a checkpoint file will always be written
wallcycle_stop(wcycle,ewcTRAJ);
}
GMX_MPE_LOG(ev_output_finish);
-
+
/* Determine the wallclock run time up till now */
run_time = gmx_gettime() - (double)runtime->real;
- /* Check whether everything is still allright */
- if ((bGotStopNextStepSignal || bGotStopNextNSStepSignal) &&
- (handledSignal!=last_signal_number_recvd) &&
+ /* Check whether everything is still allright */
+ if (((int)gmx_get_stop_condition() > handled_stop_condition) &&
MASTERTHREAD(cr))
{
- if (bGotStopNextStepSignal)
- {
- gs.set[eglsTERM] = 1;
- }
- else
- {
- gs.set[eglsTERM] = -1;
- }
+ /* this is just make gs.sig compatible with the hack
+ of sending signals around by MPI_Reduce with together with
+ other floats */
+ /* NOTE: this only works for serial code. For code that allows
+ MPI nodes to propagate their condition, see kernel/md.c*/
+ if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
+ gs.set[eglsSTOPCOND]=1;
+ if ( gmx_get_stop_condition() == gmx_stop_cond_next )
+ gs.set[eglsSTOPCOND]=1;
+ /* < 0 means stop at next step, > 0 means stop at next NS step */
if (fplog)
{
fprintf(fplog,
"\n\nReceived the %s signal, stopping at the next %sstep\n\n",
- signal_name[last_signal_number_recvd],
- gs.set[eglsTERM]==-1 ? "NS " : "");
+ gmx_get_signal_name(),
+ gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
fflush(fplog);
}
fprintf(stderr,
"\n\nReceived the %s signal, stopping at the next %sstep\n\n",
- signal_name[last_signal_number_recvd],
- gs.set[eglsTERM]==-1 ? "NS " : "");
+ gmx_get_signal_name(),
+ gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
fflush(stderr);
- handledSignal=last_signal_number_recvd;
+ handled_stop_condition=(int)gmx_get_stop_condition();
}
else if (MASTER(cr) &&
(max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
- gs.set[eglsTERM] == 0)
+ gs.set[eglsSTOPCOND] == 0)
{
/* Signal to terminate the run */
- gs.set[eglsTERM] = 1;
+ gs.set[eglsSTOPCOND] = 1;
if (fplog)
{
fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
}
fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
}
-
/* checkpoints */
if (MASTER(cr) && (cpt_period >= 0 &&
- (cpt_period == 0 ||
+ (cpt_period == 0 ||
run_time >= nchkpt*cpt_period*60.0)) &&
- gs.set[eglsCHKPT] == 0)
+ gs.set[eglsCHKPT] == 0)
{
gs.set[eglsCHKPT] = 1;
}
-
-
+
/* Time for performance */
- if (((step % stepout) == 0) || bLastStep)
+ if (((step % stepout) == 0) || bLastStep)
{
runtime_upd_proc(runtime);
}
-
- if (do_per_step(step,ir->nstlog))
+ if (do_per_step(step,ir->nstlog))
+ {
+ if (fflush(fplog) != 0)
{
- if(fflush(fplog) != 0)
- {
- gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
- }
+ gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
}
-
+ }
/* Remaining runtime */
- if (MULTIMASTER(cr) && do_verbose)
+ if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
{
print_time(stderr,runtime,step,ir,cr);
}
-
bFirstStep = FALSE;
bInitStep = FALSE;
bStartingFromCpt = FALSE;
step++;
step_rel++;
-
-
-
}
/* End of main MD loop */
debug_gmx();
-
- openmm_cleanup(fplog, openmmData);
/* Stop the time */
runtime_end(runtime);
-
+
+ if (MASTER(cr))
+ {
+ if (ir->nstcalcenergy > 0)
+ {
+ print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
+ eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+ }
+ }
+
+ openmm_cleanup(fplog, openmmData);
done_mdoutf(outf);
debug_gmx();
runtime->nsteps_done = step_rel;
-
+
return 0;
}
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
#ifndef _MD_OPENMM_H
#define _MD_OPENMM_H
unsigned long Flags,
gmx_runtime_t *runtime);
-#endif // _MD_OPENMM_H
+#endif /* _MD_OPENMM_H */
" * The current release runs only on modern nVidia GPU hardware with CUDA support.",
"Make sure that the necessary CUDA drivers and libraries for your operating system",
"are already installed. The CUDA SDK also should be installed in order to compile",
- "the program from source (http://www.nvidia.com/object/cuda_home.html).[PAR]"
- " * Multiple GPU cards are not supported.[PAR]"
+ "the program from source (http://www.nvidia.com/object/cuda_home.html).[PAR]",
+ " * Multiple GPU cards are not supported.[PAR]",
" * Only a small subset of the GROMACS features and options are supported on the GPUs.",
"See below for a detailed list.[PAR]",
" * Consumer level GPU cards are known to often have problems with faulty memory.",
"(for example, using the memtest=full option).",
"A partial memory check (for example, memtest=15) before and",
"after the simulation run would help spot",
- "problems resulting from processor overheating.[PAR]"
+ "problems resulting from processor overheating.[PAR]",
" * The maximum size of the simulated systems depends on the available",
"GPU memory,for example, a GTX280 with 1GB memory has been tested with systems",
"of up to about 100,000 atoms.[PAR]",
"have been implemented in a very different way than they are on the CPUs.",
"Therefore numercal correspondence between properties of the state of",
"simulated systems should not be expected. Moreover, the values will likely vary",
- "when simulations are done on different GPU hardware.[PAR]"
+ "when simulations are done on different GPU hardware.[PAR]",
" * Frequent retrieval of system state information such as",
"trajectory coordinates and energies can greatly influence the performance",
"of the program due to slow CPU<->GPU memory transfer speed.[PAR]",
"can be as high as 20 times, but in most other setups involving cutoffs and PME the",
"acceleration is usually only 4~6 times relative to a 3GHz CPU.[PAR]",
"Supported features:[PAR]",
- " * Integrators: md, md-vv, md-vv2, sd and bd.\n",
+ " * Integrators: md/md-vv/md-vv-avek, sd/sd1 and bd.\n",
" * Long-range interactions (option coulombtype): Reaction-Field, Ewald, PME.\n",
- " * Temperature control: Supported only with the sd, bd, md-vv and md-vv2 integrators.\n",
+ " * Temperature control: Supported only with the md/md-vv/md-vv-avek, sd/sd1 and bd integrators.\n",
" * Pressure control: Not supported.\n",
" * Implicit solvent: Supported.\n",
"A detailed description can be found on the website:\n",
- "http://www.gromacs.org/index.php?title=Download_%26_Installation/Related_Software/OpenMM[PAR]",
-// From the original mdrun documentaion
+ "http://www.gromacs.org/gpu[PAR]",
+/* From the original mdrun documentaion */
"The mdrun program reads the run input file ([TT]-s[tt])",
"and distributes the topology over nodes if needed.",
"mdrun produces at least four output files.",
"pressure, etc, a lot of these things are also printed in the log file.",
"Optionally coordinates can be written to a compressed trajectory file",
"([TT]-x[tt]).[PAR]",
-//////////////////////////////////////
+/* openmm specific information */
"Usage with OpenMM:[BR]",
"$ mdrun -device \"OpenMM:platform=Cuda,memtest=15,deviceid=0,force-device=no\"[PAR]",
"Options:[PAR]",
"high or low spatial inhomogeneity of the system.",
"[PAR]",
"The option [TT]-gcom[tt] can be used to only do global communication",
- "every n steps."
+ "every n steps.",
"This can improve performance for highly parallel simulations",
"where this global communication step becomes the bottleneck.",
"For a global thermostat and/or barostat the temperature",
"The previous checkpoint is backed up to [TT]state_prev.cpt[tt] to",
"make sure that a recent state of the system is always available,",
"even when the simulation is terminated while writing a checkpoint.",
+ "With [TT]-cpnum[tt] all checkpoint files are kept and appended",
+ "with the step number.",
"A simulation can be continued by reading the full state from file",
"with option [TT]-cpi[tt]. This option is intelligent in the way that",
"if no checkpoint file is found, Gromacs just assumes a normal run and",
- "starts from the first step of the tpr file.",
- "The simulation part number is added to all output files,",
- "unless [TT]-append[tt] or [TT]-noaddpart[tt] are set.",
+ "starts from the first step of the tpr file. By default the output",
+ "will be appending to the existing output files. The checkpoint file",
+ "contains checksums of all output files, such that you will never",
+ "loose data when some output files are modified, corrupt or removed.",
+ "There are three scenarios with [TT]-cpi[tt]:[BR]",
+ "* no files with matching names are present: new output files are written[BR]",
+ "* all files are present with names and checksums matching those stored",
+ "in the checkpoint file: files are appended[BR]",
+ "* otherwise no files are modified and a fatal error is generated[BR]",
+ "With [TT]-noappend[tt] new output files are opened and the simulation",
+ "part number is added to all output file names.",
+ "Note that in all cases the checkpoint file itself is not renamed",
+ "and will be overwritten, unless its name does not match",
+ "the [TT]-cpo[tt] option.",
"[PAR]",
"With checkpointing the output is appended to previously written",
"output files, unless [TT]-noappend[tt] is used or none of the previous",
"The result with appending will be the same as from a single run.",
"The contents will be binary identical, unless you use a different number",
"of nodes or dynamic load balancing or the FFT library uses optimizations",
- "through timing."
+ "through timing.",
"[PAR]",
"With option [TT]-maxh[tt] a simulation is terminated and a checkpoint",
"file is written at the first neighbor search step where the run time",
{ efSTO, "-c", "confout", ffWRITE },
{ efEDR, "-e", "ener", ffWRITE },
{ efLOG, "-g", "md", ffWRITE },
- { efEDI, "-ei", "sam", ffOPTRD },
- { efTRX, "-rerun", "rerun", ffOPTRD },
- { efXVG, "-table", "table", ffOPTRD },
- { efXVG, "-tablep", "tablep", ffOPTRD },
- { efXVG, "-tableb", "table", ffOPTRD },
-#ifndef GMX_OPENMM
{ efXVG, "-dhdl", "dhdl", ffOPTWR },
{ efXVG, "-field", "field", ffOPTWR },
{ efXVG, "-table", "table", ffOPTRD },
{ efLOG, "-rt", "rottorque",ffOPTWR },
{ efMTX, "-mtx", "nm", ffOPTWR },
{ efNDX, "-dn", "dipole", ffOPTWR }
-#endif
};
#define NFILE asize(fnm)
real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
real cpt_period=15.0,max_hours=-1;
- bool bAppendFiles=TRUE,bAddPart=TRUE;
+ bool bAppendFiles=TRUE;
+ bool bKeepAndNumCPT=FALSE;
bool bResetCountersHalfWay=FALSE;
output_env_t oenv=NULL;
const char *deviceOptions = "";
t_pargs pa[] = {
-// arguments relevant to OPENMM only
-#ifdef GMX_OPENMM
- { "-device", FALSE, etSTR, {&deviceOptions},
- "Device option string" },
-// args for non-OpenMM binaries
-#else
{ "-pd", FALSE, etBOOL,{&bPartDec},
"Use particle decompostion" },
{ "-dd", FALSE, etRVEC,{&realddxyz},
"Domain decomposition grid, 0 is optimize" },
+#ifdef GMX_THREADS
{ "-nt", FALSE, etINT, {&nthreads},
"Number of threads to start (0 is guess)" },
+#endif
{ "-npme", FALSE, etINT, {&npme},
"Number of separate nodes to be used for PME, -1 is guess" },
{ "-ddorder", FALSE, etENUM, {ddno_opt},
"HIDDENThe DD cell sizes in z" },
{ "-gcom", FALSE, etINT,{&nstglobalcomm},
"Global communication frequency" },
+ { "-v", FALSE, etBOOL,{&bVerbose},
+ "Be loud and noisy" },
{ "-compact", FALSE, etBOOL,{&bCompact},
"Write a compact log file" },
{ "-seppot", FALSE, etBOOL, {&bSepPot},
"Print all forces larger than this (kJ/mol nm)" },
{ "-reprod", FALSE, etBOOL,{&bReproducible},
"Try to avoid optimizations that affect binary reproducibility" },
+ { "-cpt", FALSE, etREAL, {&cpt_period},
+ "Checkpoint interval (minutes)" },
+ { "-cpnum", FALSE, etBOOL, {&bKeepAndNumCPT},
+ "Keep and number checkpoint files" },
+ { "-append", FALSE, etBOOL, {&bAppendFiles},
+ "Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names" },
+ { "-maxh", FALSE, etREAL, {&max_hours},
+ "Terminate after 0.99 times this time (hours)" },
{ "-multi", FALSE, etINT,{&nmultisim},
"Do multiple simulations in parallel" },
{ "-replex", FALSE, etINT, {&repl_ex_nst},
{ "-resetstep", FALSE, etINT, {&resetstep},
"HIDDENReset cycle counters after these many time steps" },
{ "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
- "HIDDENReset the cycle counters after half the number of steps or halfway -maxh" },
+ "HIDDENReset the cycle counters after half the number of steps or halfway -maxh" }
+#ifdef GMX_OPENMM
+ ,
+ { "-device", FALSE, etSTR, {&deviceOptions},
+ "Device option string" }
#endif
-// args for both
- { "-v", FALSE, etBOOL,{&bVerbose},
- "Be loud and noisy" },
- { "-maxh", FALSE, etREAL, {&max_hours},
- "Terminate after 0.99 times this time (hours)" },
- { "-cpt", FALSE, etREAL, {&cpt_period},
- "Checkpoint interval (minutes)" },
- { "-append", FALSE, etBOOL, {&bAppendFiles},
- "Append to previous output files when continuing from checkpoint" },
- { "-addpart", FALSE, etBOOL, {&bAddPart},
- "Add the simulation part number to all output files when continuing from checkpoint" },
};
gmx_edsam_t ed;
unsigned long Flags, PCA_Flags;
ivec ddxyz;
int dd_node_order;
- bool HaveCheckpoint;
+ bool bAddPart;
FILE *fplog,*fptest;
int sim_part,sim_part_fn;
const char *part_suffix=".part";
cr = init_par(&argc,&argv);
-
+
+ if (MASTER(cr))
+ CopyRight(stderr, argv[0]);
+
PCA_Flags = (PCA_KEEP_ARGS | PCA_NOEXIT_ON_ARGS | PCA_CAN_SET_DEFFNM
| (MASTER(cr) ? 0 : PCA_QUIET));
parse_common_args(&argc,argv,PCA_Flags, NFILE,fnm,asize(pa),pa,
asize(desc),desc,0,NULL, &oenv);
-#ifdef GMX_THREADS
- if (nthreads<1)
- {
- nthreads=tMPI_Get_recommended_nthreads();
- }
-#else
+ /* we set these early because they might be used in init_multisystem()
+ Note that there is the potential for npme>nnodes until the number of
+ threads is set later on, if there's thread parallelization. That shouldn't
+ lead to problems. */
+ dd_node_order = nenum(ddno_opt);
+ cr->npmenodes = npme;
+
+#ifndef GMX_THREADS
nthreads=1;
#endif
- cr->nthreads = nthreads;
-
- dd_node_order = nenum(ddno_opt);
- cr->npmenodes = npme;
if (repl_ex_nst != 0 && nmultisim < 2)
gmx_fatal(FARGS,"Need at least two replicas for replica exchange (option -multi)");
#endif
}
- /* Check if there is ANY checkpoint file available */
- sim_part = 1;
- sim_part_fn = sim_part;
- if (opt2bSet("-cpi",NFILE,fnm))
- {
- bAppendFiles =
- read_checkpoint_simulation_part(opt2fn_master("-cpi",NFILE,fnm,cr),
- &sim_part_fn,NULL,cr,
- bAppendFiles,
- part_suffix,&bAddPart);
- if (sim_part_fn==0 && MASTER(cr))
- {
- fprintf(stdout,"No previous checkpoint file present, assuming this is a new run.\n");
- }
- else
- {
- sim_part = sim_part_fn + 1;
- }
- }
- else
- {
- bAppendFiles = FALSE;
- }
-
- if (!bAppendFiles)
- {
- sim_part_fn = sim_part;
- }
-
- if (bAddPart && sim_part_fn > 1)
- {
- /* This is a continuation run, rename trajectory output files
- (except checkpoint files) */
- /* create new part name first (zero-filled) */
- sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
-
- add_suffix_to_output_names(fnm,NFILE,suffix);
- fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
- }
+ bAddPart = !bAppendFiles;
+
+ /* Check if there is ANY checkpoint file available */
+ sim_part = 1;
+ sim_part_fn = sim_part;
+ if (opt2bSet("-cpi",NFILE,fnm))
+ {
+ bAppendFiles =
+ read_checkpoint_simulation_part(opt2fn_master("-cpi", NFILE,
+ fnm,cr),
+ &sim_part_fn,NULL,cr,
+ bAppendFiles,
+ part_suffix,&bAddPart);
+ if (sim_part_fn==0 && MASTER(cr))
+ {
+ fprintf(stdout,"No previous checkpoint file present, assuming this is a new run.\n");
+ }
+ else
+ {
+ sim_part = sim_part_fn + 1;
+ }
+ }
+ else
+ {
+ bAppendFiles = FALSE;
+ }
+
+ if (!bAppendFiles)
+ {
+ sim_part_fn = sim_part;
+ }
+
+ if (bAddPart)
+ {
+ /* Rename all output files (except checkpoint files) */
+ /* create new part name first (zero-filled) */
+ sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
+
+ add_suffix_to_output_names(fnm,NFILE,suffix);
+ if (MASTER(cr))
+ {
+ fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
+ }
+ }
Flags = opt2bSet("-rerun",NFILE,fnm) ? MD_RERUN : 0;
Flags = Flags | (bSepPot ? MD_SEPPOT : 0);
Flags = Flags | (bRerunVSite ? MD_RERUN_VSITE : 0);
Flags = Flags | (bReproducible ? MD_REPRODUCIBLE : 0);
Flags = Flags | (bAppendFiles ? MD_APPENDFILES : 0);
+ Flags = Flags | (bKeepAndNumCPT ? MD_KEEPANDNUMCPT : 0);
Flags = Flags | (sim_part>1 ? MD_STARTFROMCPT : 0);
Flags = Flags | (bResetCountersHalfWay ? MD_RESETCOUNTERSHALFWAY : 0);
fplog = NULL;
}
-#if 0
- /* this is now done in mdrunner: */
- /* Essential dynamics */
- if (opt2bSet("-ei",NFILE,fnm)) {
- /* Open input and output files, allocate space for ED data structure */
- ed = ed_open(NFILE,fnm,cr);
- } else
- ed=NULL;
-#endif
-
ddxyz[XX] = (int)(realddxyz[XX] + 0.5);
ddxyz[YY] = (int)(realddxyz[YY] + 0.5);
ddxyz[ZZ] = (int)(realddxyz[ZZ] + 0.5);
- /* even if nthreads = 1, we still call this one */
- rc = mdrunner_threads(nthreads,
- fplog,cr,NFILE,fnm,oenv,bVerbose,bCompact,nstglobalcomm,
- ddxyz,dd_node_order,rdd,rconstr,
- dddlb_opt[0],dlb_scale,ddcsx,ddcsy,ddcsz,
- nstepout,resetstep,nmultisim,repl_ex_nst,repl_ex_seed,
- pforce, cpt_period,max_hours,deviceOptions,Flags);
+ rc = mdrunner(nthreads, fplog,cr,NFILE,fnm,oenv,bVerbose,bCompact,
+ nstglobalcomm, ddxyz,dd_node_order,rdd,rconstr,
+ dddlb_opt[0],dlb_scale,ddcsx,ddcsy,ddcsz,
+ nstepout,resetstep,nmultisim,repl_ex_nst,repl_ex_seed,
+ pforce, cpt_period,max_hours,deviceOptions,Flags);
if (gmx_parallel_env_initialized())
gmx_finalize();
#include "pdb2top.h"
#include "gpp_nextnb.h"
#include "gpp_atomtype.h"
-#include "x2top.h"
+#include "g_x2top.h"
#include "fflibutil.h"
static void rd_nm2type_file(const char *fn,int *nnm,t_nm2type **nmp)
t_nm2type *nm2t=NULL;
fp = fflib_open(fn);
-
+ if (NULL == fp)
+ gmx_fatal(FARGS,"Can not find %s in library directory",fn);
+
nnnm = *nnm;
nm2t = *nmp;
do {
*nmp = nm2t;
}
-t_nm2type *rd_nm2type(const char *ffdir,int *nnm)
+t_nm2type *rd_nm2type(const char *ffdir,bool bAddCWD,int *nnm)
{
int nff,f;
char **ff;
t_nm2type *nm;
- nff = fflib_search_file_end(ffdir,".n2t",FALSE,&ff);
+ nff = fflib_search_file_end(ffdir,bAddCWD,".n2t",FALSE,&ff);
*nnm = 0;
nm = NULL;
for(f=0; f<nff; f++) {
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
+/*
+ * Note, that parts of this source code originate from the Simtk release
+ * of OpenMM accelerated Gromacs, for more details see:
+ * https://simtk.org/project/xml/downloads.xml?group_id=161#package_id600
+ */
+
#include <cmath>
#include <set>
#include <iostream>
#include "string2.h"
#include "gmx_gpu_utils.h"
#include "mtop_util.h"
-#include "warninp.h"
#include "openmm_wrapper.h"
using namespace OpenMM;
+/*! \cond */
#define MEM_ERR_MSG(str) \
"The %s-simulation GPU memory test detected errors. As memory errors would cause incorrect " \
"simulation results, gromacs has aborted execution.\n Make sure that your GPU's memory is not " \
"overclocked and that the device is properly cooled.\n", (str)
-
-
-/** Convert string to type T. */
+/*! \endcond */
+
+#define COMBRULE_CHK_TOL 1e-6
+#define COMBRULE_SIGMA(sig1, sig2) (((sig1) + (sig2))/2)
+#define COMBRULE_EPS(eps1, eps2) (sqrt((eps1) * (eps2)))
+
+/*!
+ * \brief Convert string to integer type.
+ * \param[in] s String to convert from.
+ * \param[in] f Basefield format flag that takes any of the following I/O
+ * manipulators: dec, hex, oct.
+ * \param[out] t Destination variable to convert to.
+ */
template <class T>
static bool from_string(T& t, const string& s, ios_base& (*f)(ios_base&))
{
- istringstream iss(s);
- return !(iss >> f >> t).fail();
+ istringstream iss(s);
+ return !(iss >> f >> t).fail();
}
-/**
- * Split string around a given delimiter.
+/*!
+ * \brief Split string around a given delimiter.
+ * \param[in] s String to split.
+ * \param[in] delim Delimiter character.
+ * \returns Vector of strings found in \p s.
*/
static vector<string> split(const string &s, char delim)
{
vector<string> elems;
stringstream ss(s);
string item;
- while(getline(ss, item, delim))
+ while (getline(ss, item, delim))
{
if (item.length() != 0)
elems.push_back(item);
return elems;
}
-/**
- * Split a string "option=value" into "option" and "value" strings.
+/*!
+ * \brief Split a string of the form "option=value" into "option" and "value" strings.
+ * This string corresponds to one option and the associated value from the option list
+ * in the mdrun -device argument.
+ *
+ * \param[in] s A string containing an "option=value" pair that needs to be split up.
+ * \param[out] opt The name of the option.
+ * \param[out] val Value of the option.
*/
-static void split_opt_val(const string &s, string &opt, string &val)
+static void splitOptionValue(const string &s, string &opt, string &val)
{
size_t eqPos = s.find('=');
if (eqPos != string::npos)
}
}
-/**
- * Compare two strings ignoring case.
+/*!
+ * \brief Compare two strings ignoring case.
+ * This function is in fact a wrapper around the gromacs function gmx_strncasecmp().
+ * \param[in] s1 String.
+ * \param[in] s2 String.
+ * \returns Similarly to the C function strncasecmp(), the return value is an
+ integer less than, equal to, or greater than 0 if \p s1 less than,
+ identical to, or greater than \p s2.
*/
static bool isStringEqNCase(const string s1, const string s2)
{
return (gmx_strncasecmp(s1.c_str(), s2.c_str(), max(s1.length(), s2.length())) == 0);
}
-/**
- * Conver string to upper case.
+/*!
+ * \brief Convert string to upper case.
+ *
+ * \param[in] s String to convert to uppercase.
+ * \returns The given string converted to uppercase.
*/
static string toUpper(const string &s)
{
return stmp;
}
-#define SIZEOF_PLATFORMS 1
-#define SIZEOF_MEMTESTS 3
-#define SIZEOF_DEVICEIDS 1
-#define SIZEOF_FORCE_DEV 2
-
-/** Possible options of the mdrun -device parameter. */
-static const char *devOptStrings[] = { "platform", "deviceid", "memtest", "force-device" };
-enum devOpt {
- PLATFORM = 0,
- DEVICEID = 1,
- MEMTEST = 2,
- FORCE_DEVICE = 3
+/*!
+ \name Sizes of constant device option arrays GmxOpenMMPlatformOptions#platforms,
+ GmxOpenMMPlatformOptions#memtests, GmxOpenMMPlatformOptions#deviceid,
+ GmxOpenMMPlatformOptions#force_dev. */
+/* {@ */
+#define SIZEOF_PLATFORMS 1 // 2
+#define SIZEOF_MEMTESTS 3
+#define SIZEOF_DEVICEIDS 1
+#define SIZEOF_FORCE_DEV 2
+
+#define SIZEOF_CHECK_COMBRULE 2
+/* @} */
+
+/*! Possible platform options in the mdrun -device option. */
+static const char *devOptStrings[] = { "platform", "deviceid", "memtest", "force-device", "check-combrule" };
+
+/*! Enumerated platform options in the mdrun -device option. */
+enum devOpt
+{
+ PLATFORM = 0,
+ DEVICEID = 1,
+ MEMTEST = 2,
+ FORCE_DEVICE = 3
};
-/**
- * Parse the options string provided to mdrun.
+/*!
+ * \brief Class to extract and manage the platform options in the mdrun -device option.
+ *
*/
class GmxOpenMMPlatformOptions
{
public:
- GmxOpenMMPlatformOptions(const char *optionString);
-// GmxOpenMMPlatformOptions(string &optionString);
+ GmxOpenMMPlatformOptions(const char *opt);
~GmxOpenMMPlatformOptions() { options.clear(); }
- string getOptionValue(const string &optName);
- void remOption(const string &optName) { options.erase(toUpper(optName)); }
+ string getOptionValue(const string &opt);
+ void remOption(const string &opt);
+ void print();
private:
void setOption(const string &opt, const string &val);
- map<string, string> options;
- static const char * const platforms[SIZEOF_PLATFORMS];
- static const char * const memtests[SIZEOF_MEMTESTS];
- static const char * const deviceid[SIZEOF_DEVICEIDS];
- static const char * const force_dev[SIZEOF_FORCE_DEV];
-};
-/* possible values of the parameters that will not be passed to OMM
- first value will always be the default used in case if the option is not specified */
-const char * const GmxOpenMMPlatformOptions::platforms[SIZEOF_PLATFORMS] = { "Cuda" /*,"OpenCL"*/ };
-const char * const GmxOpenMMPlatformOptions::memtests[SIZEOF_MEMTESTS] = { "15", "full", "off" }; /* also valid any positive integer >15 */
-const char * const GmxOpenMMPlatformOptions::deviceid[SIZEOF_DEVICEIDS] = { "0" }; /* also valid any positive integer */
-const char * const GmxOpenMMPlatformOptions::force_dev[SIZEOF_FORCE_DEV] = { "no", "yes" };
+ map<string, string> options; /*!< Data structure to store the option (name, value) pairs. */
+
+ static const char * const platforms[SIZEOF_PLATFORMS]; /*!< Available OpenMM platforms; size #SIZEOF_PLATFORMS */
+ static const char * const memtests[SIZEOF_MEMTESTS]; /*!< Available types of memory tests, also valid
+ any positive integer >=15; size #SIZEOF_MEMTESTS */
+ static const char * const deviceid[SIZEOF_DEVICEIDS]; /*!< Possible values for deviceid option;
+ also valid any positive integer; size #SIZEOF_DEVICEIDS */
+ static const char * const force_dev[SIZEOF_FORCE_DEV]; /*!< Possible values for for force-device option;
+ size #SIZEOF_FORCE_DEV */
+ static const char * const check_combrule[SIZEOF_CHECK_COMBRULE]; /* XXX temporary debug feature to
+ turn off combination rule check */
+};
+const char * const GmxOpenMMPlatformOptions::platforms[SIZEOF_PLATFORMS]
+ = {"CUDA"};
+ //= { "Reference", "CUDA" /*,"OpenCL"*/ };
+const char * const GmxOpenMMPlatformOptions::memtests[SIZEOF_MEMTESTS]
+ = { "15", "full", "off" };
+const char * const GmxOpenMMPlatformOptions::deviceid[SIZEOF_DEVICEIDS]
+ = { "0" };
+const char * const GmxOpenMMPlatformOptions::force_dev[SIZEOF_FORCE_DEV]
+ = { "no", "yes" };
+const char * const GmxOpenMMPlatformOptions::check_combrule[SIZEOF_CHECK_COMBRULE]
+ = { "yes", "no" };
+
+/*!
+ * \brief Contructor.
+ * Takes the option list, parses it, checks the options and their values for validity.
+ * When certain options are not provided by the user, as default value the first item
+ * of the respective constant array is taken (GmxOpenMMPlatformOptions#platforms,
+ * GmxOpenMMPlatformOptions#memtests, GmxOpenMMPlatformOptions#deviceid,
+ * GmxOpenMMPlatformOptions#force_dev).
+ * \param[in] optionString Option list part of the mdrun -device parameter.
+ */
GmxOpenMMPlatformOptions::GmxOpenMMPlatformOptions(const char *optionString)
{
// set default values
setOption("memtest", memtests[0]);
setOption("deviceid", deviceid[0]);
setOption("force-device", force_dev[0]);
+ setOption("check-combrule", check_combrule[0]);
string opt(optionString);
- // remove all the whitespaces
+ // remove all whitespaces
opt.erase(remove_if(opt.begin(), opt.end(), ::isspace), opt.end());
// tokenize around ","-s
vector<string> tokens = split(opt, ',');
for (vector<string>::iterator it = tokens.begin(); it != tokens.end(); ++it)
{
string opt = "", val = "";
- split_opt_val(*it, opt, val);
+ splitOptionValue(*it, opt, val);
if (isStringEqNCase(opt, "platform"))
{
+ /* no check, this will fail if platform does not exist when we try to set it */
setOption(opt, val);
continue;
}
if (isStringEqNCase(opt, "memtest"))
{
- if (!isStringEqNCase(val, "full") && !isStringEqNCase(val, "off")) /* the value has to be an integer >15 */
+ /* the value has to be an integer >15(s) or "full" OR "off" */
+ if (!isStringEqNCase(val, "full") && !isStringEqNCase(val, "off"))
{
int secs;
if (!from_string<int>(secs, val, std::dec))
{
- gmx_fatal(FARGS, "Invalid value for option memtestoption: \"%s\"!\n", val.c_str());
+ gmx_fatal(FARGS, "Invalid value for option memtest option: \"%s\"!", val.c_str());
}
if (secs < 15)
{
- gmx_fatal(FARGS, "Incorrect value for memtest option (%d). Memtest needs to run for at least 15s!\n", secs);
+ gmx_fatal(FARGS, "Incorrect value for memtest option (%d). "
+ "Memtest needs to run for at least 15s!", secs);
}
}
setOption(opt, val);
int id;
if (!from_string<int>(id, val, std::dec) )
{
- gmx_fatal(FARGS, "Invalid device id: \"%s\"!\n", val.c_str());
+ gmx_fatal(FARGS, "Invalid device id: \"%s\"!", val.c_str());
+ }
+ setOption(opt, val);
+ continue;
+ }
+
+ if (isStringEqNCase(opt, "force-device"))
+ {
+ /* */
+ if (!isStringEqNCase(val, "yes") && !isStringEqNCase(val, "no"))
+ {
+ gmx_fatal(FARGS, "Invalid OpenMM force option: \"%s\"!", val.c_str());
}
setOption(opt, val);
continue;
}
- if (isStringEqNCase(opt,"force-device"))
+ if (isStringEqNCase(opt, "check-combrule"))
{
+ /* */
if (!isStringEqNCase(val, "yes") && !isStringEqNCase(val, "no"))
{
- gmx_fatal(FARGS, "Invalid OpenMM force option: \"%s\"!\n", val.c_str());
+ gmx_fatal(FARGS, "Invalid OpenMM force option: \"%s\"!", val.c_str());
}
setOption(opt, val);
continue;
}
+
// if we got till here something went wrong
- gmx_fatal(FARGS, "Invalid OpenMM platform option: \"%s\"!\n", (*it).c_str());
+ gmx_fatal(FARGS, "Invalid OpenMM platform option: \"%s\"!", (*it).c_str());
}
-
-/* cout << "== platform = " << getOptionValue("platform") << endl
- << "== deviceID = " << getOptionValue("deviceid") << endl
- << "== memtest = " << getOptionValue("memtest") << endl
- << "== force = " << getOptionValue("force-device") << endl;
-*/
}
-string GmxOpenMMPlatformOptions::getOptionValue(const string &optName)
+
+/*!
+ * \brief Getter function.
+ * \param[in] opt Name of the option.
+ * \returns Returns the value associated to an option.
+ */
+string GmxOpenMMPlatformOptions::getOptionValue(const string &opt)
{
- if (options.find(toUpper(optName)) != options.end())
+ map<string, string> :: const_iterator it = options.find(toUpper(opt));
+ if (it != options.end())
{
- return options[toUpper(optName)];
+ return it->second;
}
else
{
}
}
+/*!
+ * \brief Setter function - private, only used from contructor.
+ * \param[in] opt Name of the option.
+ * \param[in] val Value for the option.
+ */
void GmxOpenMMPlatformOptions::setOption(const string &opt, const string &val)
{
options[toUpper(opt)] = val;
}
+/*!
+ * \brief Removes an option with its value from the map structure. If the option
+ * does not exist, returns without any action.
+ * \param[in] opt Name of the option.
+ */
+void GmxOpenMMPlatformOptions::remOption(const string &opt)
+{
+ options.erase(toUpper(opt));
+}
+
+/*!
+ * \brief Print option-value pairs to a file (debugging function).
+ */
+void GmxOpenMMPlatformOptions::print()
+{
+ cout << ">> Platform options: " << endl
+ << ">> platform = " << getOptionValue("platform") << endl
+ << ">> deviceID = " << getOptionValue("deviceid") << endl
+ << ">> memtest = " << getOptionValue("memtest") << endl
+ << ">> force-device = " << getOptionValue("force-device") << endl;
+}
+
+/*!
+ * \brief Container for OpenMM related data structures that represent the bridge
+ * between the Gromacs data-structures and the OpenMM library and is but it's
+ * only passed through the API functions as void to disable direct access.
+ */
class OpenMMData
{
public:
- System* system;
- Context* context;
- Integrator* integrator;
- bool removeCM;
- GmxOpenMMPlatformOptions *platformOpt;
+ System* system; /*! The system to simulate. */
+ Context* context; /*! The OpenMM context in which the simulation is carried out. */
+ Integrator* integrator; /*! The integrator used in the simulation. */
+ bool removeCM; /*! If \true remove venter of motion, false otherwise. */
+ GmxOpenMMPlatformOptions *platformOpt; /*! Platform options. */
};
-void run_memtest(FILE* fplog, int devId, const char* pre_post, GmxOpenMMPlatformOptions *opt)
+/*!
+ * \brief Runs memtest on the GPU that has alreaby been initialized by OpenMM.
+ * \param[in] fplog Pointer to gromacs log file.
+ * \param[in] devId Device id of the GPU to run the test on.
+ Note: as OpenMM previously creates the context,for now this is always -1.
+ * \param[in] pre_post Contains either "Pre" or "Post" just to be able to differentiate in
+ * stdout messages/log between memtest carried out before and after simulation.
+ * \param[in] opt Pointer to platform options object.
+ */
+static void runMemtest(FILE* fplog, int devId, const char* pre_post, GmxOpenMMPlatformOptions *opt)
{
+ char strout_buf[STRLEN];
+ int which_test;
+ int res = 0;
+ string s = opt->getOptionValue("memtest");
+ const char *test_type = s.c_str();
- char warn_buf[STRLEN];
-
- // TODO I guess the log entries should go on stdout as well, shouldn't they? [sz]
- int which_test;
- int res;
- const char * test_type = opt->getOptionValue("memtest").c_str();
if (!gmx_strcasecmp(test_type, "off"))
{
- which_test = 0;
+ which_test = 0;
}
else
{
}
else
{
- from_string<int>(which_test, test_type, std::dec);
+ from_string<int>(which_test, test_type, std::dec);
}
}
+ if (which_test < 0)
+ {
+ gmx_fatal(FARGS, "Amount of seconds for memetest is negative (%d). ", which_test);
+ }
+
switch (which_test)
{
case 0: /* no memtest */
-
- sprintf(warn_buf, "%s-simulation GPU memtest skipped. Note, that faulty memory can cause "
- "incorrect results!\n", pre_post);
- fprintf(fplog, "%s", warn_buf);
- gmx_warning(warn_buf);
+ sprintf(strout_buf, "%s-simulation GPU memtest skipped. Note, that faulty memory can cause "
+ "incorrect results!", pre_post);
+ fprintf(fplog, "%s\n", strout_buf);
+ gmx_warning(strout_buf);
break; /* case 0 */
case 1: /* quick memtest */
fprintf(fplog, "%s-simulation %s GPU memtest in progress...\n", pre_post, test_type);
fprintf(stdout, "\n%s-simulation %s GPU memtest in progress...", pre_post, test_type);
- fflush(fplog); fflush(stdout);
- if (do_quick_memtest(-1) != 0)
- {
- gmx_fatal(FARGS,MEM_ERR_MSG(pre_post));
-
- }
- else
- {
- fprintf(fplog, "Memory test completed without errors.\n");
- fprintf(stdout, "done, no errors detected\n");
- }
+ fflush(fplog);
+ fflush(stdout);
+ res = do_quick_memtest(devId);
break; /* case 1 */
case 2: /* full memtest */
fprintf(fplog, "%s-simulation %s memtest in progress...\n", pre_post, test_type);
fprintf(stdout, "\n%s-simulation %s memtest in progress...", pre_post, test_type);
- fflush(fplog); fflush(stdout);
- if (do_full_memtest(-1) != 0)
- {
- gmx_fatal(FARGS, MEM_ERR_MSG(pre_post) );
-
- }
- else
- {
- fprintf(fplog, "Memory test completed without errors.\n");
- fprintf(stdout, "done, no errors detected\n");
- }
+ fflush(fplog);
+ fflush(stdout);
+ res = do_full_memtest(devId);
break; /* case 2 */
default: /* timed memtest */
- fprintf(fplog, "%s-simulation memtest for ~%ds in progress...\n", pre_post, which_test);
- fprintf(stdout, "\n%s-simulation memtest for ~%ds in progress...", pre_post, which_test);
- fflush(fplog); fflush(stdout);
- if (do_timed_memtest(-1, which_test) != 0)
+ fprintf(fplog, "%s-simulation ~%ds memtest in progress...\n", pre_post, which_test);
+ fprintf(stdout, "\n%s-simulation ~%ds memtest in progress...", pre_post, which_test);
+ fflush(fplog);
+ fflush(stdout);
+ res = do_timed_memtest(devId, which_test);
+ }
+
+ if (which_test != 0)
+ {
+ if (res != 0)
{
gmx_fatal(FARGS, MEM_ERR_MSG(pre_post));
-
}
else
{
- fprintf(fplog, "Memory test completed without errors.\n");
- fprintf(stdout, "done, no errors detected.\n");
+ fprintf(fplog, "Memory test completed without errors.\n");
+ fflush(fplog);
+ fprintf(stdout, "done, no errors detected\n");
+ fflush(stdout);
}
- }
- fflush(fplog); fflush(stdout);
+ }
}
-void checkGmxOptions(t_inputrec *ir, gmx_localtop_t *top)
+/*!
+ * \brief Convert Lennard-Jones parameters c12 and c6 to sigma and epsilon.
+ *
+ * \param[in] c12
+ * \param[in] c6
+ * \param[out] sigma
+ * \param[out] epsilon
+ */
+static void convert_c_12_6(double c12, double c6, double *sigma, double *epsilon)
{
+ if (c12 == 0 && c6 == 0)
+ {
+ *epsilon = 0.0;
+ *sigma = 1.0;
+ }
+ else if (c12 > 0 && c6 > 0)
+ {
+ *epsilon = (c6*c6)/(4.0*c12);
+ *sigma = pow(c12/c6, 1.0/6.0);
+ }
+ else
+ {
+ gmx_fatal(FARGS,"OpenMM only supports c6 > 0 and c12 > 0 or c6 = c12 = 0.");
+ }
+}
- char warn_buf[STRLEN];
+/*!
+ * \brief Does gromacs option checking.
+ *
+ * Checks the gromacs mdp options for features unsupported in OpenMM, case in which
+ * interrupts the execution. It also warns the user about pecularities of OpenMM
+ * implementations.
+ * \param[in] fplog Gromacs log file pointer.
+ * \param[in] ir Gromacs input parameters, see ::t_inputrec
+ * \param[in] top Gromacs node local topology, \see gmx_localtop_t
+ * \param[in] state Gromacs state structure \see ::t_state
+ * \param[in] mdatoms Gromacs atom parameters, \see ::t_mdatoms
+ * \param[in] fr \see ::t_forcerec
+ * \param[in] state Gromacs systems state, \see ::t_state
+ */
+static void checkGmxOptions(FILE* fplog, GmxOpenMMPlatformOptions *opt,
+ t_inputrec *ir, gmx_localtop_t *top,
+ t_forcerec *fr, t_state *state)
+{
+ char warn_buf[STRLEN];
+ int i, j, natoms;
+ double c6, c12;
+ double sigma_ij=0, sigma_ji=0, sigma_ii=0, sigma_jj=0, sigma_comb;
+ double eps_ij=0, eps_ji=0, eps_ii=0, eps_jj=0, eps_comb;
- // Abort if unsupported critical options are present
+ /* Abort if unsupported critical options are present */
/* Integrator */
if (ir->eI == eiMD)
- gmx_warning(FARGS, "OpenMM does not support leap-frog, will use velocity-verlet integrator.\n");
+ {
+ gmx_warning( "OpenMM does not support leap-frog, will use velocity-verlet integrator.");
+ }
- if ( (ir->eI != eiMD) &&
- (ir->eI != eiVV) &&
- (ir->eI != eiVVAK) &&
- (ir->eI != eiSD1) &&
- (ir->eI != eiSD2) &&
- (ir->eI != eiBD)
- )
+ if ( (ir->eI != eiMD) &&
+ (ir->eI != eiVV) &&
+ (ir->eI != eiVVAK) &&
+ (ir->eI != eiSD1) &&
+ (ir->eI != eiSD2) &&
+ (ir->eI != eiBD) )
{
- gmx_fatal(FARGS, "OpenMM supports only the following integrators: md-vv/md-vvak, sd/sd1, and bd.\n");
+ gmx_fatal(FARGS, "OpenMM supports only the following integrators: md/md-vv/md-vv-avek, sd/sd1, and bd.");
}
/* Electroctstics */
- if (
- (ir->coulombtype != eelPME) &&
- (ir->coulombtype != eelRF) &&
- (ir->coulombtype != eelEWALD) &&
- // no-cutoff
- ( !(ir->coulombtype == eelCUT && ir->rcoulomb == 0 && ir->rvdw == 0))
- )
- {
- gmx_fatal(FARGS,"OpenMM supports only the following methods for electrostatics: NoCutoff (i.e. rcoulomb = rvdw = 0 ),Reaction-Field, Ewald or PME.\n");
+ if ( (ir->coulombtype != eelPME) &&
+ (ir->coulombtype != eelRF) &&
+ (ir->coulombtype != eelEWALD) &&
+ // no-cutoff
+ ( !(ir->coulombtype == eelCUT && ir->rcoulomb == 0 && ir->rvdw == 0)) )
+ {
+ gmx_fatal(FARGS,"OpenMM supports only the following methods for electrostatics: "
+ "NoCutoff (i.e. rcoulomb = rvdw = 0 ),Reaction-Field, Ewald or PME.");
}
- if ( (ir->etc != etcNO) &&
- (ir->eI != eiSD1) &&
- (ir->eI != eiSD2) &&
- (ir->eI != eiBD) )
- gmx_warning("OpenMM supports only Andersen thermostat with the md-vv/md-vvak integrators.\n");
+ if (ir->etc != etcNO &&
+ ir->eI != eiSD1 &&
+ ir->eI != eiSD2 &&
+ ir->eI != eiBD )
+ {
+ gmx_warning("OpenMM supports only Andersen thermostat with the md/md-vv/md-vv-avek integrators.");
+ }
+
+ if (ir->implicit_solvent == eisGBSA &&
+ ir->gb_algorithm != egbOBC )
+ {
+ gmx_warning("OpenMM does not support the specified algorithm for Generalized Born, will use OBC instead.");
+ }
if (ir->opts.ngtc > 1)
- gmx_fatal(FARGS,"OpenMM does not support multiple temperature coupling groups.\n");
+ gmx_fatal(FARGS,"OpenMM does not support multiple temperature coupling groups.");
if (ir->epc != etcNO)
- gmx_fatal(FARGS,"OpenMM does not support pressure coupling.\n");
+ gmx_fatal(FARGS,"OpenMM does not support pressure coupling.");
if (ir->opts.annealing[0])
- gmx_fatal(FARGS,"OpenMM does not support simulated annealing.\n");
-
- if (ir->eConstrAlg != econtSHAKE)
- gmx_warning("Constraints in OpenMM are done by a combination "
- "of SHAKE, SETTLE and CCMA. Accuracy is based on the SHAKE tolerance set "
- "by the \"shake_tol\" option.\n");
+ gmx_fatal(FARGS,"OpenMM does not support simulated annealing.");
+
+ if (top->idef.il[F_CONSTR].nr > 0 && ir->eConstrAlg != econtSHAKE)
+ gmx_warning("OpenMM provides contraints as a combination "
+ "of SHAKE, SETTLE and CCMA. Accuracy is based on the SHAKE tolerance set "
+ "by the \"shake_tol\" option.");
if (ir->nwall != 0)
- gmx_fatal(FARGS,"OpenMM does not support walls.\n");
+ gmx_fatal(FARGS,"OpenMM does not support walls.");
if (ir->ePull != epullNO)
- gmx_fatal(FARGS,"OpenMM does not support pulling.\n");
-
- if (top->idef.il[F_DISRES].nr > 0)
- gmx_fatal(FARGS,"OpenMM does not support distant restraints.\n");
+ gmx_fatal(FARGS,"OpenMM does not support pulling.");
- if (top->idef.il[F_ORIRES].nr > 0)
- gmx_fatal(FARGS,"OpenMM does not support orientation restraints.\n");
-
- if (top->idef.il[F_ANGRES].nr > 0)
- gmx_fatal(FARGS,"OpenMM does not support angle restraints.\n");
-
- if (top->idef.il[F_DIHRES].nr > 0)
- gmx_fatal(FARGS,"OpenMM does not support dihedral restraints.\n");
+ /* check for interaction types */
+ for (i = 0; i < F_EPOT; i++)
+ {
+ if (!(i == F_CONSTR ||
+ i == F_SETTLE ||
+ i == F_BONDS ||
+ i == F_UREY_BRADLEY ||
+ i == F_ANGLES ||
+ i == F_PDIHS ||
+ i == F_RBDIHS ||
+ i == F_LJ14 ||
+ i == F_GB12 || /* The GB parameters are hardcoded both in */
+ i == F_GB13 || /* Gromacs and OpenMM */
+ i == F_GB14 ) &&
+ top->idef.il[i].nr > 0)
+ {
+ gmx_fatal(FARGS, "OpenMM does not support (some) of the provided interaction "
+ "type(s) (%s) ", interaction_function[i].longname);
+ }
+ }
if (ir->efep != efepNO)
- gmx_fatal(FARGS,"OpenMM does not support free energy calculations.\n");
+ gmx_fatal(FARGS,"OpenMM does not support free energy calculations.");
if (ir->opts.ngacc > 1)
- gmx_fatal(FARGS,"OpenMM does not support non-equilibrium MD (accelerated groups).\n");
+ gmx_fatal(FARGS,"OpenMM does not support non-equilibrium MD (accelerated groups).");
if (IR_ELEC_FIELD(*ir))
- gmx_fatal(FARGS,"OpenMM does not support electric fields.\n");
+ gmx_fatal(FARGS,"OpenMM does not support electric fields.");
if (ir->bQMMM)
- gmx_fatal(FARGS,"OpenMM does not support QMMM calculations.\n");
+ gmx_fatal(FARGS,"OpenMM does not support QMMM calculations.");
if (ir->rcoulomb != ir->rvdw)
gmx_fatal(FARGS,"OpenMM uses a single cutoff for both Coulomb "
- "and VdW interactions. Please set rcoulomb equal to rvdw.\n");
+ "and VdW interactions. Please set rcoulomb equal to rvdw.");
+
+ if (EEL_FULL(ir->coulombtype))
+ {
+ if (ir->ewald_geometry == eewg3DC)
+ gmx_fatal(FARGS,"OpenMM supports only Ewald 3D geometry.");
+ if (ir->epsilon_surface != 0)
+ gmx_fatal(FARGS,"OpenMM does not support dipole correction in Ewald summation.");
+ }
+
+ if (TRICLINIC(state->box))
+ {
+ gmx_fatal(FARGS,"OpenMM does not support triclinic unit cells.");
+ }
+
+ /* XXX this is just debugging code to disable the combination rule check */
+ if ( isStringEqNCase(opt->getOptionValue("check-combrule"), "yes") )
+ {
+ /* As OpenMM by default uses hardcoded combination rules
+ sigma_ij = (sigma_i + sigma_j)/2, eps_ij = sqrt(eps_i * eps_j)
+ we need to check whether the force field params obey this
+ and if not, we can't use this force field so we exit
+ grace-fatal-fully. */
+ real *nbfp = fr->nbfp;
+ natoms = fr->ntype;
+ if (debug)
+ {
+ fprintf(debug, ">> Atom parameters: <<\n%10s%5s %5s %5s %5s COMB\n",
+ "", "i-j", "j-i", "i-i", "j-j");
+ }
+ /* loop over all i-j atom pairs and verify if
+ sigma_ij = sigma_ji = sigma_comb and eps_ij = eps_ji = eps_comb */
+ for (i = 0; i < natoms; i++)
+ {
+ /* i-i */
+ c12 = C12(nbfp, natoms, i, i);
+ c6 = C6(nbfp, natoms, i, i);
+ convert_c_12_6(c12, c6, &sigma_ii, &eps_ii);
+
+ for (j = 0; j < i; j++)
+ {
+ /* i-j */
+ c12 = C12(nbfp, natoms, i, j);
+ c6 = C6(nbfp, natoms, i, j);
+ convert_c_12_6(c12, c6, &sigma_ij, &eps_ij);
+ /* j-i */
+ c12 = C12(nbfp, natoms, j, i);
+ c6 = C6(nbfp, natoms, j, i);
+ convert_c_12_6(c12, c6, &sigma_ji, &eps_ji);
+ /* j-j */
+ c12 = C12(nbfp, natoms, j, j);
+ c6 = C6(nbfp, natoms, j, j);
+ convert_c_12_6(c12, c6, &sigma_jj, &eps_jj);
+ /* OpenMM hardcoded combination rules */
+ sigma_comb = COMBRULE_SIGMA(sigma_ii, sigma_jj);
+ eps_comb = COMBRULE_EPS(eps_ii, eps_jj);
+
+ if (debug)
+ {
+ fprintf(debug, "i=%-3d j=%-3d", i, j);
+ fprintf(debug, "%-11s", "sigma");
+ fprintf(debug, "%5.3f %5.3f %5.3f %5.3f %5.3f\n",
+ sigma_ij, sigma_ji, sigma_ii, sigma_jj, sigma_comb);
+ fprintf(debug, "%11s%-11s", "", "epsilon");
+ fprintf(debug, "%5.3f %5.3f %5.3f %5.3f %5.3f\n",
+ eps_ij, eps_ji, eps_ii, eps_jj, eps_comb);
+ }
+
+ /* check the values against the rule used by omm */
+ if((fabs(eps_ij) > COMBRULE_CHK_TOL &&
+ fabs(eps_ji) > COMBRULE_CHK_TOL) &&
+ (fabs(sigma_comb - sigma_ij) > COMBRULE_CHK_TOL ||
+ fabs(sigma_comb - sigma_ji) > COMBRULE_CHK_TOL ||
+ fabs(eps_comb - eps_ij) > COMBRULE_CHK_TOL ||
+ fabs(eps_comb - eps_ji) > COMBRULE_CHK_TOL ))
+ {
+ gmx_fatal(FARGS,
+ "The combination rules of the used force-field do not "
+ "match the one supported by OpenMM: "
+ "sigma_ij = (sigma_i + sigma_j)/2, eps_ij = sqrt(eps_i * eps_j). "
+ "Switch to a force-field that uses these rules in order to "
+ "simulate this system using OpenMM.\n");
+ }
+ }
+ }
+ if (debug) { fprintf(debug, ">><<\n\n"); }
+
+ /* if we got here, log that everything is fine */
+ if (debug)
+ {
+ fprintf(debug, ">> The combination rule of the used force matches the one used by OpenMM.\n");
+ }
+ fprintf(fplog, "The combination rule of the force used field matches the one used by OpenMM.\n");
+ } /* if (are we checking the combination rules) ... */
}
-/**
- * Initialize OpenMM, and return a pointer to the OpenMMData object containing the System, Integrator, and Context.
+
+/*!
+ * \brief Initialize OpenMM, run sanity/consistency checks, and return a pointer to
+ * the OpenMMData.
+ *
+ * Various gromacs data structures are passed that contain the parameters, state and
+ * other porperties of the system to simulate. These serve as input for initializing
+ * OpenMM. Besides, a set of misc action are taken:
+ * - OpenMM plugins are loaded;
+ * - platform options in \p platformOptStr are parsed and checked;
+ * - Gromacs parameters are checked for OpenMM support and consistency;
+ * - after the OpenMM is initialized memtest executed in the same GPU context.
+ *
+ * \param[in] fplog Gromacs log file handler.
+ * \param[in] platformOptStr Platform option string.
+ * \param[in] ir The Gromacs input parameters, see ::t_inputrec
+ * \param[in] top_global Gromacs system toppology, \see ::gmx_mtop_t
+ * \param[in] top Gromacs node local topology, \see gmx_localtop_t
+ * \param[in] mdatoms Gromacs atom parameters, \see ::t_mdatoms
+ * \param[in] fr \see ::t_forcerec
+ * \param[in] state Gromacs systems state, \see ::t_state
+ * \returns Pointer to a
+ *
*/
void* openmm_init(FILE *fplog, const char *platformOptStr,
- t_commrec *cr,t_inputrec *ir,
- gmx_mtop_t *top_global, gmx_localtop_t *top,
- t_mdatoms *mdatoms, t_forcerec *fr,t_state *state)
+ t_inputrec *ir,
+ gmx_mtop_t *top_global, gmx_localtop_t *top,
+ t_mdatoms *mdatoms, t_forcerec *fr, t_state *state)
{
char warn_buf[STRLEN];
-
static bool hasLoadedPlugins = false;
string usedPluginDir;
+ int devId;
- try {
- if (!hasLoadedPlugins)
- {
- vector<string> loadedPlugins;
- /* Look for OpenMM plugins at various locations (listed in order of priority):
- - on the path in OPENMM_PLUGIN_DIR environment variable if this is specified
- - on the path in the OPENMM_PLUGIN_DIR macro that is set by the build script
- - at the default location assumed by OpenMM
- */
- /* env var */
- char *pluginDir = getenv("OPENMM_PLUGIN_DIR");
- trim(pluginDir);
- /* no env var or empty */
- if (pluginDir != NULL && *pluginDir != '\0')
- {
- loadedPlugins = Platform::loadPluginsFromDirectory(pluginDir);
- if (loadedPlugins.size() > 0)
- {
- hasLoadedPlugins = true;
- usedPluginDir = pluginDir;
- }
- else
+ try
+ {
+ if (!hasLoadedPlugins)
+ {
+ vector<string> loadedPlugins;
+ /* Look for OpenMM plugins at various locations (listed in order of priority):
+ - on the path in OPENMM_PLUGIN_DIR environment variable if this is specified
+ - on the path in the OPENMM_PLUGIN_DIR macro that is set by the build script
+ - at the default location assumed by OpenMM
+ */
+ /* env var */
+ char *pluginDir = getenv("OPENMM_PLUGIN_DIR");
+ trim(pluginDir);
+ /* no env var or empty */
+ if (pluginDir != NULL && *pluginDir != '\0')
{
- gmx_fatal(FARGS, "The directory provided in the OPENMM_PLUGIN_DIR environment variable "
- "(%s) does not contain valid OpenMM plugins. Check your OpenMM installation!", pluginDir);
+ loadedPlugins = Platform::loadPluginsFromDirectory(pluginDir);
+ if (loadedPlugins.size() > 0)
+ {
+ hasLoadedPlugins = true;
+ usedPluginDir = pluginDir;
+ }
+ else
+ {
+ gmx_fatal(FARGS, "The directory provided in the OPENMM_PLUGIN_DIR environment variable "
+ "(%s) does not contain valid OpenMM plugins. Check your OpenMM installation!",
+ pluginDir);
+ }
}
- }
- /* macro set at build time */
+ /* macro set at build time */
#ifdef OPENMM_PLUGIN_DIR
- if (!hasLoadedPlugins)
- {
- loadedPlugins = Platform::loadPluginsFromDirectory(OPENMM_PLUGIN_DIR);
- if (loadedPlugins.size() > 0)
+ if (!hasLoadedPlugins)
{
- hasLoadedPlugins = true;
- usedPluginDir = OPENMM_PLUGIN_DIR;
+ loadedPlugins = Platform::loadPluginsFromDirectory(OPENMM_PLUGIN_DIR);
+ if (loadedPlugins.size() > 0)
+ {
+ hasLoadedPlugins = true;
+ usedPluginDir = OPENMM_PLUGIN_DIR;
+ }
}
- }
#endif
- /* default loocation */
- if (!hasLoadedPlugins)
- {
- loadedPlugins = Platform::loadPluginsFromDirectory(Platform::getDefaultPluginsDirectory());
- if (loadedPlugins.size() > 0)
+ /* default loocation */
+ if (!hasLoadedPlugins)
+ {
+ loadedPlugins = Platform::loadPluginsFromDirectory(Platform::getDefaultPluginsDirectory());
+ if (loadedPlugins.size() > 0)
+ {
+ hasLoadedPlugins = true;
+ usedPluginDir = Platform::getDefaultPluginsDirectory();
+ }
+ }
+
+ /* if there are still no plugins loaded there won't be any */
+ if (!hasLoadedPlugins)
+ {
+ gmx_fatal(FARGS, "No OpenMM plugins were found! You can provide the"
+ " plugin directory in the OPENMM_PLUGIN_DIR environment variable.", pluginDir);
+ }
+
+ fprintf(fplog, "\nOpenMM plugins loaded from directory %s:\t", usedPluginDir.c_str());
+ for (int i = 0; i < (int)loadedPlugins.size(); i++)
{
- hasLoadedPlugins = true;
- usedPluginDir = Platform::getDefaultPluginsDirectory();
+ fprintf(fplog, "%s, ", loadedPlugins[i].c_str());
}
+ fprintf(fplog, "\n");
}
- /* if there are still no plugins loaded there won't be any */
- if (!hasLoadedPlugins)
+ /* parse option string */
+ GmxOpenMMPlatformOptions *opt = new GmxOpenMMPlatformOptions(platformOptStr);
+ devId = atoi(opt->getOptionValue("deviceid").c_str());
+
+ if (debug)
{
- gmx_fatal(FARGS, "No OpenMM plugins were found! You can provide the"
- " plugin directory in the OPENMM_PLUGIN_DIR environment variable.", pluginDir);
+ opt->print();
}
- fprintf(fplog, "\nPlugins loaded from directory %s:\t", usedPluginDir.c_str());
- for (int i = 0; i < loadedPlugins.size(); i++)
+ /* check wheter Gromacs options compatibility with OpenMM */
+ checkGmxOptions(fplog, opt, ir, top, fr, state);
+
+ // Create the system.
+ const t_idef& idef = top->idef;
+ const int numAtoms = top_global->natoms;
+ const int numConstraints = idef.il[F_CONSTR].nr/3;
+ const int numSettle = idef.il[F_SETTLE].nr/2;
+ const int numBonds = idef.il[F_BONDS].nr/3;
+ const int numUB = idef.il[F_UREY_BRADLEY].nr/4;
+ const int numAngles = idef.il[F_ANGLES].nr/4;
+ const int numPeriodic = idef.il[F_PDIHS].nr/5;
+ const int numRB = idef.il[F_RBDIHS].nr/5;
+ const int num14 = idef.il[F_LJ14].nr/3;
+ System* sys = new System();
+ if (ir->nstcomm > 0)
+ sys->addForce(new CMMotionRemover(ir->nstcomm));
+
+ // Set bonded force field terms.
+ const int* bondAtoms = (int*) idef.il[F_BONDS].iatoms;
+ HarmonicBondForce* bondForce = new HarmonicBondForce();
+ sys->addForce(bondForce);
+ int offset = 0;
+ for (int i = 0; i < numBonds; ++i)
{
- fprintf(fplog, "%s, ", loadedPlugins[i].c_str());
+ int type = bondAtoms[offset++];
+ int atom1 = bondAtoms[offset++];
+ int atom2 = bondAtoms[offset++];
+ bondForce->addBond(atom1, atom2,
+ idef.iparams[type].harmonic.rA, idef.iparams[type].harmonic.krA);
+ }
+ // Urey-Bradley includes both the angle and bond potential for 1-3 interactions
+ const int* ubAtoms = (int*) idef.il[F_UREY_BRADLEY].iatoms;
+ HarmonicBondForce* ubBondForce = new HarmonicBondForce();
+ HarmonicAngleForce* ubAngleForce = new HarmonicAngleForce();
+ sys->addForce(ubBondForce);
+ sys->addForce(ubAngleForce);
+ offset = 0;
+ for (int i = 0; i < numUB; ++i)
+ {
+ int type = ubAtoms[offset++];
+ int atom1 = ubAtoms[offset++];
+ int atom2 = ubAtoms[offset++];
+ int atom3 = ubAtoms[offset++];
+ ubBondForce->addBond(atom1, atom3,
+ idef.iparams[type].u_b.r13, idef.iparams[type].u_b.kUB);
+ ubAngleForce->addAngle(atom1, atom2, atom3,
+ idef.iparams[type].u_b.theta*M_PI/180.0, idef.iparams[type].u_b.ktheta);
+ }
+ const int* angleAtoms = (int*) idef.il[F_ANGLES].iatoms;
+ HarmonicAngleForce* angleForce = new HarmonicAngleForce();
+ sys->addForce(angleForce);
+ offset = 0;
+ for (int i = 0; i < numAngles; ++i)
+ {
+ int type = angleAtoms[offset++];
+ int atom1 = angleAtoms[offset++];
+ int atom2 = angleAtoms[offset++];
+ int atom3 = angleAtoms[offset++];
+ angleForce->addAngle(atom1, atom2, atom3,
+ idef.iparams[type].harmonic.rA*M_PI/180.0, idef.iparams[type].harmonic.krA);
+ }
+ const int* periodicAtoms = (int*) idef.il[F_PDIHS].iatoms;
+ PeriodicTorsionForce* periodicForce = new PeriodicTorsionForce();
+ sys->addForce(periodicForce);
+ offset = 0;
+ for (int i = 0; i < numPeriodic; ++i)
+ {
+ int type = periodicAtoms[offset++];
+ int atom1 = periodicAtoms[offset++];
+ int atom2 = periodicAtoms[offset++];
+ int atom3 = periodicAtoms[offset++];
+ int atom4 = periodicAtoms[offset++];
+ periodicForce->addTorsion(atom1, atom2, atom3, atom4,
+ idef.iparams[type].pdihs.mult,
+ idef.iparams[type].pdihs.phiA*M_PI/180.0,
+ idef.iparams[type].pdihs.cpA);
+ }
+ const int* rbAtoms = (int*) idef.il[F_RBDIHS].iatoms;
+ RBTorsionForce* rbForce = new RBTorsionForce();
+ sys->addForce(rbForce);
+ offset = 0;
+ for (int i = 0; i < numRB; ++i)
+ {
+ int type = rbAtoms[offset++];
+ int atom1 = rbAtoms[offset++];
+ int atom2 = rbAtoms[offset++];
+ int atom3 = rbAtoms[offset++];
+ int atom4 = rbAtoms[offset++];
+ rbForce->addTorsion(atom1, atom2, atom3, atom4,
+ idef.iparams[type].rbdihs.rbcA[0], idef.iparams[type].rbdihs.rbcA[1],
+ idef.iparams[type].rbdihs.rbcA[2], idef.iparams[type].rbdihs.rbcA[3],
+ idef.iparams[type].rbdihs.rbcA[4], idef.iparams[type].rbdihs.rbcA[5]);
}
- fprintf(fplog, "\n");
- }
- /* parse option string */
- GmxOpenMMPlatformOptions *opt = new GmxOpenMMPlatformOptions(platformOptStr);
-
- /* check wheter Gromacs options compatibility with OpenMM */
- checkGmxOptions(ir, top);
-
- /* check GPU support */
- char s[1000];
- is_supported_cuda_gpu(atoi(opt->getOptionValue("deviceid").c_str()), s);
-
- // Create the system.
- const t_idef& idef = top->idef;
- const int numAtoms = top_global->natoms;
- const int numConstraints = idef.il[F_CONSTR].nr/3;
- const int numSettle = idef.il[F_SETTLE].nr/2;
- const int numBonds = idef.il[F_BONDS].nr/3;
- const int numAngles = idef.il[F_ANGLES].nr/4;
- const int numPeriodic = idef.il[F_PDIHS].nr/5;
- const int numRB = idef.il[F_RBDIHS].nr/5;
- const int num14 = idef.il[F_LJ14].nr/3;
- System* sys = new System();
- if (ir->nstcomm > 0)
- sys->addForce(new CMMotionRemover(ir->nstcomm));
-
- // Set bonded force field terms.
- const int* bondAtoms = (int*) idef.il[F_BONDS].iatoms;
- HarmonicBondForce* bondForce = new HarmonicBondForce();
- sys->addForce(bondForce);
- int offset = 0;
- for (int i = 0; i < numBonds; ++i) {
- int type = bondAtoms[offset++];
- int atom1 = bondAtoms[offset++];
- int atom2 = bondAtoms[offset++];
- bondForce->addBond(atom1, atom2, idef.iparams[type].harmonic.rA, idef.iparams[type].harmonic.krA);
- }
- const int* angleAtoms = (int*) idef.il[F_ANGLES].iatoms;
- HarmonicAngleForce* angleForce = new HarmonicAngleForce();
- sys->addForce(angleForce);
- offset = 0;
- for (int i = 0; i < numAngles; ++i) {
- int type = angleAtoms[offset++];
- int atom1 = angleAtoms[offset++];
- int atom2 = angleAtoms[offset++];
- int atom3 = angleAtoms[offset++];
- angleForce->addAngle(atom1, atom2, atom3, idef.iparams[type].harmonic.rA*M_PI/180.0, idef.iparams[type].harmonic.krA);
- }
- const int* periodicAtoms = (int*) idef.il[F_PDIHS].iatoms;
- PeriodicTorsionForce* periodicForce = new PeriodicTorsionForce();
- sys->addForce(periodicForce);
- offset = 0;
- for (int i = 0; i < numPeriodic; ++i) {
- int type = periodicAtoms[offset++];
- int atom1 = periodicAtoms[offset++];
- int atom2 = periodicAtoms[offset++];
- int atom3 = periodicAtoms[offset++];
- int atom4 = periodicAtoms[offset++];
- periodicForce->addTorsion(atom1, atom2, atom3, atom4, idef.iparams[type].pdihs.mult, idef.iparams[type].pdihs.phiA*M_PI/180.0, idef.iparams[type].pdihs.cpA);
- }
- const int* rbAtoms = (int*) idef.il[F_RBDIHS].iatoms;
- RBTorsionForce* rbForce = new RBTorsionForce();
- sys->addForce(rbForce);
- offset = 0;
- for (int i = 0; i < numRB; ++i) {
- int type = rbAtoms[offset++];
- int atom1 = rbAtoms[offset++];
- int atom2 = rbAtoms[offset++];
- int atom3 = rbAtoms[offset++];
- int atom4 = rbAtoms[offset++];
- rbForce->addTorsion(atom1, atom2, atom3, atom4, idef.iparams[type].rbdihs.rbcA[0], idef.iparams[type].rbdihs.rbcA[1],
- idef.iparams[type].rbdihs.rbcA[2], idef.iparams[type].rbdihs.rbcA[3], idef.iparams[type].rbdihs.rbcA[4], idef.iparams[type].rbdihs.rbcA[5]);
- }
+ // Set nonbonded parameters and masses.
+ int ntypes = fr->ntype;
+ int* types = mdatoms->typeA;
+ real* nbfp = fr->nbfp;
+ real* charges = mdatoms->chargeA;
+ real* masses = mdatoms->massT;
+ NonbondedForce* nonbondedForce = new NonbondedForce();
+ sys->addForce(nonbondedForce);
+
+ switch (ir->ePBC)
+ {
+ case epbcNONE:
+ if (ir->rcoulomb == 0)
+ {
+ nonbondedForce->setNonbondedMethod(NonbondedForce::NoCutoff);
+ }
+ else
+ {
+ nonbondedForce->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
+ }
+ break;
+ case epbcXYZ:
+ switch (ir->coulombtype)
+ {
+ case eelRF:
+ nonbondedForce->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
+ break;
+
+ case eelEWALD:
+ nonbondedForce->setNonbondedMethod(NonbondedForce::Ewald);
+ break;
+
+ case eelPME:
+ nonbondedForce->setNonbondedMethod(NonbondedForce::PME);
+ break;
+
+ default:
+ gmx_fatal(FARGS,"Internal error: you should not see this message, it that the"
+ "electrosatics option check failed. Please report this error!");
+ }
+ sys->setPeriodicBoxVectors(Vec3(state->box[0][0], 0, 0),
+ Vec3(0, state->box[1][1], 0), Vec3(0, 0, state->box[2][2]));
+ nonbondedForce->setCutoffDistance(ir->rcoulomb);
+
+ break;
+ default:
+ gmx_fatal(FARGS,"OpenMM supports only full periodic boundary conditions "
+ "(pbc = xyz), or none (pbc = no).");
+ }
- // Set nonbonded parameters and masses.
-
- int ntypes = fr->ntype;
- int* types = mdatoms->typeA;
- real* nbfp = fr->nbfp;
- real* charges = mdatoms->chargeA;
- real* masses = mdatoms->massT;
- NonbondedForce* nonbondedForce = new NonbondedForce();
- sys->addForce(nonbondedForce);
-
- if (ir->rcoulomb == 0)
- nonbondedForce->setNonbondedMethod(NonbondedForce::NoCutoff);
-
- else {
- switch (ir->coulombtype)
- {
- case eelRF: // TODO what is the correct condition?
- if (ir->ePBC == epbcXYZ) {
- nonbondedForce->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
- sys->setPeriodicBoxVectors(Vec3(state->box[0][0], 0, 0), Vec3(0, state->box[1][1], 0), Vec3(0, 0, state->box[2][2]));
- }
- else if (ir->ePBC == epbcNONE)
- nonbondedForce->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
- else
- gmx_fatal(FARGS,"OpenMM supports only full periodic boundary conditions (pbc = xyz), or none (pbc = no).\n");
- nonbondedForce->setCutoffDistance(ir->rcoulomb);
- break;
-
- case eelEWALD:
- if (ir->ewald_geometry == eewg3DC)
- gmx_fatal(FARGS,"OpenMM supports only Ewald 3D geometry.\n");
- if (ir->epsilon_surface != 0)
- gmx_fatal(FARGS,"OpenMM does not support dipole correction in Ewald summation.\n");
- nonbondedForce->setNonbondedMethod(NonbondedForce::Ewald);
- nonbondedForce->setCutoffDistance(ir->rcoulomb);
- sys->setPeriodicBoxVectors(Vec3(state->box[0][0], 0, 0), Vec3(0, state->box[1][1], 0), Vec3(0, 0, state->box[2][2]));
- break;
-
- case eelPME:
- nonbondedForce->setNonbondedMethod(NonbondedForce::PME);
- nonbondedForce->setCutoffDistance(ir->rcoulomb);
- sys->setPeriodicBoxVectors(Vec3(state->box[0][0], 0, 0), Vec3(0, state->box[1][1], 0), Vec3(0, 0, state->box[2][2]));
- break;
-
- default:
- gmx_fatal(FARGS,"Internal error: you should not see this message, it that the"
- "electrosatics option check failed. Please report this error!");
- }
- }
- for (int i = 0; i < numAtoms; ++i) {
- real c6 = nbfp[types[i]*2*ntypes+types[i]*2];
- real c12 = nbfp[types[i]*2*ntypes+types[i]*2+1];
- if (c12 <= 0)
- nonbondedForce->addParticle(charges[i], 1.0, 0.0);
- else
- nonbondedForce->addParticle(charges[i], pow(c12/c6, (real) (1.0/6.0)), c6*c6/(4.0*c12));
- sys->addParticle(masses[i]);
- }
+ /* Fix for PME and Ewald error tolerance
+ *
+ * OpenMM uses approximate formulas to calculate the Ewald parameter:
+ * alpha = (1.0/cutoff)*sqrt(-log(2.0*tolerlance));
+ * and the grid spacing for PME:
+ * gridX = ceil(alpha*box[0][0]/pow(0.5*tol, 0.2));
+ * gridY = ceil(alpha*box[1][1]/pow(0.5*tol, 0.2));
+ * gridZ = ceil(alpha*box[2][2]/pow(0.5*tol, 0.2));
+ *
+ * It overestimates the precision and setting it to
+ * (500 x ewald_rtol) seems to give a reasonable match to the GROMACS settings
+ *
+ * If the default ewald_rtol=1e-5 is used we silently adjust the value,
+ * otherwise a warning is issued about the action taken.
+ */
+ double corr_ewald_rtol = 500.0 * ir->ewald_rtol;
+ if ((ir->ePBC == epbcXYZ) &&
+ (ir->coulombtype == eelEWALD || ir->coulombtype == eelPME))
+ {
+ if (debug)
+ {
+ fprintf(debug, ">> ewald_rtol = %e (corrected = %e) \n",
+ ir->ewald_rtol, corr_ewald_rtol);
+ }
- // Build a table of all exclusions.
+ if (fabs(ir->ewald_rtol - 1e-5) > 1e-10)
+ {
+ gmx_warning("OpenMM uses the ewald_rtol parameter with approximate formulas "
+ "to calculate the alpha and grid spacing parameters of the Ewald "
+ "and PME methods. This tolerance need to be corrected in order to get "
+ "settings close to the ones used in GROMACS. Although the internal correction "
+ "should work for any reasonable value of ewald_rtol, using values other than "
+ "the default 1e-5 might cause incorrect behavior.");
+
+ if (corr_ewald_rtol > 1)
+ {
+ gmx_fatal(FARGS, "The ewald_rtol accuracy term is >1 after the "
+ "adjustment for OpenMM (%e)", corr_ewald_rtol);
+ }
+ }
+ nonbondedForce->setEwaldErrorTolerance(corr_ewald_rtol);
+ }
- vector<set<int> > exclusions(numAtoms);
- for (int i = 0; i < numAtoms; i++) {
- int start = top->excls.index[i];
- int end = top->excls.index[i+1];
- for (int j = start; j < end; j++)
- exclusions[i].insert(top->excls.a[j]);
- }
+ for (int i = 0; i < numAtoms; ++i)
+ {
+ double c12 = nbfp[types[i]*2*ntypes+types[i]*2+1];
+ double c6 = nbfp[types[i]*2*ntypes+types[i]*2];
+ double sigma=0.0, epsilon=0.0;
+ convert_c_12_6(c12, c6, &sigma, &epsilon);
+ nonbondedForce->addParticle(charges[i], sigma, epsilon);
+ sys->addParticle(masses[i]);
+ }
- // Record the 1-4 interactions, and remove them from the list of exclusions.
-
- const int* nb14Atoms = (int*) idef.il[F_LJ14].iatoms;
- offset = 0;
- for (int i = 0; i < num14; ++i) {
- int type = nb14Atoms[offset++];
- int atom1 = nb14Atoms[offset++];
- int atom2 = nb14Atoms[offset++];
- real c6 = idef.iparams[type].lj14.c6A;
- real c12 = idef.iparams[type].lj14.c12A;
- real sigma, epsilon;
- if (c12 <= 0) {
- epsilon = (real) 0.0;
- sigma = (real) 1.0;
- }
- else {
- epsilon = (real) ((c6*c6)/(4.0*c12));
- sigma = (real) pow(c12/c6, (real) (1.0/6.0));
- }
- nonbondedForce->addException(atom1, atom2, fr->fudgeQQ*charges[atom1]*charges[atom2], sigma, epsilon);
- exclusions[atom1].erase(atom2);
- exclusions[atom2].erase(atom1);
- }
+ // Build a table of all exclusions.
+ vector<set<int> > exclusions(numAtoms);
+ for (int i = 0; i < numAtoms; i++)
+ {
+ int start = top->excls.index[i];
+ int end = top->excls.index[i+1];
+ for (int j = start; j < end; j++)
+ exclusions[i].insert(top->excls.a[j]);
+ }
- // Record exclusions.
+ // Record the 1-4 interactions, and remove them from the list of exclusions.
+ const int* nb14Atoms = (int*) idef.il[F_LJ14].iatoms;
+ offset = 0;
+ for (int i = 0; i < num14; ++i)
+ {
+ int type = nb14Atoms[offset++];
+ int atom1 = nb14Atoms[offset++];
+ int atom2 = nb14Atoms[offset++];
+ double sigma=0, epsilon=0;
+ convert_c_12_6(idef.iparams[type].lj14.c12A,
+ idef.iparams[type].lj14.c6A,
+ &sigma, &epsilon);
+ nonbondedForce->addException(atom1, atom2,
+ fr->fudgeQQ*charges[atom1]*charges[atom2], sigma, epsilon);
+ exclusions[atom1].erase(atom2);
+ exclusions[atom2].erase(atom1);
+ }
- for (int i = 0; i < numAtoms; i++) {
- for (set<int>::const_iterator iter = exclusions[i].begin(); iter != exclusions[i].end(); ++iter) {
- if (i < *iter)
- nonbondedForce->addException(i, *iter, 0.0, 1.0, 0.0);
+ // Record exclusions.
+ for (int i = 0; i < numAtoms; i++)
+ {
+ for (set<int>::const_iterator iter = exclusions[i].begin(); iter != exclusions[i].end(); ++iter)
+ {
+ if (i < *iter)
+ {
+ nonbondedForce->addException(i, *iter, 0.0, 1.0, 0.0);
+ }
+ }
}
- }
- // Add GBSA if needed.
- t_atoms atoms;
- atoms = gmx_mtop_global_atoms(top_global);
+ // Add GBSA if needed.
+ if (ir->implicit_solvent == eisGBSA)
+ {
+ gmx_warning("The OBC scale factors alpha, beta and gamma are hardcoded in OpenMM with the default Gromacs values.");
+ t_atoms atoms = gmx_mtop_global_atoms(top_global);
+ GBSAOBCForce* gbsa = new GBSAOBCForce();
- if (ir->implicit_solvent == eisGBSA) {
- GBSAOBCForce* gbsa = new GBSAOBCForce();
sys->addForce(gbsa);
gbsa->setSoluteDielectric(ir->epsilon_r);
gbsa->setSolventDielectric(ir->gb_epsilon_solvent);
else if (nonbondedForce->getNonbondedMethod() == NonbondedForce::CutoffPeriodic)
gbsa->setNonbondedMethod(GBSAOBCForce::CutoffPeriodic);
else
- gmx_fatal(FARGS,"OpenMM supports only Reaction-Field electrostatics with OBC/GBSA.\n");
+ gmx_fatal(FARGS,"OpenMM supports only Reaction-Field electrostatics with OBC/GBSA.");
for (int i = 0; i < numAtoms; ++i)
+ {
gbsa->addParticle(charges[i],
top_global->atomtypes.gb_radius[atoms.atom[i].type],
top_global->atomtypes.S_hct[atoms.atom[i].type]);
- }
-
- // Set constraints.
-
- const int* constraintAtoms = (int*) idef.il[F_CONSTR].iatoms;
- offset = 0;
- for (int i = 0; i < numConstraints; ++i) {
- int type = constraintAtoms[offset++];
- int atom1 = constraintAtoms[offset++];
- int atom2 = constraintAtoms[offset++];
- sys->addConstraint(atom1, atom2, idef.iparams[type].constr.dA);
- }
- const int* settleAtoms = (int*) idef.il[F_SETTLE].iatoms;
- offset = 0;
- for (int i = 0; i < numSettle; ++i) {
- int type = settleAtoms[offset++];
- int oxygen = settleAtoms[offset++];
- sys->addConstraint(oxygen, oxygen+1, idef.iparams[type].settle.doh);
- sys->addConstraint(oxygen, oxygen+2, idef.iparams[type].settle.doh);
- sys->addConstraint(oxygen+1, oxygen+2, idef.iparams[type].settle.dhh);
- }
-
- // Create an integrator for simulating the system.
+ }
+ free_t_atoms(&atoms, FALSE);
+ }
- real friction = (ir->opts.tau_t[0] == 0.0 ? 0.0 : 1.0/ir->opts.tau_t[0]);
- Integrator* integ;
- if (ir->eI == eiMD || ir->eI == eiVV || ir->eI == eiVVAK) {
- integ = new VerletIntegrator(ir->delta_t);
- if ( ir->etc != etcNO) {
- real collisionFreq = ir->opts.tau_t[0] / 1000; /* tau_t (ps) / 1000 = collisionFreq (fs^-1) */
- AndersenThermostat* thermostat = new AndersenThermostat(ir->opts.ref_t[0], friction); /* TODO test this */
- sys->addForce(thermostat);
+ // Set constraints.
+ const int* constraintAtoms = (int*) idef.il[F_CONSTR].iatoms;
+ offset = 0;
+ for (int i = 0; i < numConstraints; ++i)
+ {
+ int type = constraintAtoms[offset++];
+ int atom1 = constraintAtoms[offset++];
+ int atom2 = constraintAtoms[offset++];
+ sys->addConstraint(atom1, atom2, idef.iparams[type].constr.dA);
+ }
+ const int* settleAtoms = (int*) idef.il[F_SETTLE].iatoms;
+ offset = 0;
+ for (int i = 0; i < numSettle; ++i)
+ {
+ int type = settleAtoms[offset++];
+ int oxygen = settleAtoms[offset++];
+ sys->addConstraint(oxygen, oxygen+1, idef.iparams[type].settle.doh);
+ sys->addConstraint(oxygen, oxygen+2, idef.iparams[type].settle.doh);
+ sys->addConstraint(oxygen+1, oxygen+2, idef.iparams[type].settle.dhh);
}
- }
- else if (ir->eI == eiBD) {
- integ = new BrownianIntegrator(ir->opts.ref_t[0], friction, ir->delta_t);
- static_cast<BrownianIntegrator*>(integ)->setRandomNumberSeed(ir->ld_seed); /* TODO test this */
- }
- else if (EI_SD(ir->eI)) {
- integ = new LangevinIntegrator(ir->opts.ref_t[0], friction, ir->delta_t);
- static_cast<LangevinIntegrator*>(integ)->setRandomNumberSeed(ir->ld_seed); /* TODO test this */
- }
- else {
- gmx_fatal(FARGS, "OpenMM supports only the following integrators: md-vv/md-vvak, sd/sd1, and bd.\n");
- }
+ // Create an integrator for simulating the system.
+ double friction = (ir->opts.tau_t[0] == 0.0 ? 0.0 : 1.0/ir->opts.tau_t[0]);
+ Integrator* integ;
+ if (ir->eI == eiBD)
+ {
+ integ = new BrownianIntegrator(ir->opts.ref_t[0], friction, ir->delta_t);
+ static_cast<BrownianIntegrator*>(integ)->setRandomNumberSeed(ir->ld_seed);
+ }
+ else if (EI_SD(ir->eI))
+ {
+ integ = new LangevinIntegrator(ir->opts.ref_t[0], friction, ir->delta_t);
+ static_cast<LangevinIntegrator*>(integ)->setRandomNumberSeed(ir->ld_seed);
+ }
+ else
+ {
+ integ = new VerletIntegrator(ir->delta_t);
+ if ( ir->etc != etcNO)
+ {
+ real collisionFreq = ir->opts.tau_t[0] / 1000; /* tau_t (ps) / 1000 = collisionFreq (fs^-1) */
+ AndersenThermostat* thermostat = new AndersenThermostat(ir->opts.ref_t[0], friction);
+ sys->addForce(thermostat);
+ }
+ }
+ integ->setConstraintTolerance(ir->shake_tol);
- integ->setConstraintTolerance(ir->shake_tol);
+ // Create a context and initialize it.
+ Context* context = NULL;
- // Create a context and initialize it.
- Context* context = NULL;
- if (platformOptStr == NULL || platformOptStr == "")
- {
- context = new Context(*sys, *integ);
- }
- else
- {
- // Find which platform is it.
- for (int i = 0; i < Platform::getNumPlatforms() && context == NULL; i++)
+ /*
+ OpenMM could automatically select the "best" GPU, however we're not't
+ going to let it do that for now, as the current algorithm is very rudimentary
+ and we anyway support only CUDA.
+ if (platformOptStr == NULL || platformOptStr == "")
{
- if (isStringEqNCase(opt->getOptionValue("platform"), Platform::getPlatform(i).getName()))
- {
- Platform& platform = Platform::getPlatform(i);
- // set standard properties
- platform.setPropertyDefaultValue("CudaDevice", opt->getOptionValue("deviceid"));
- // TODO add extra properties
- context = new Context(*sys, *integ, platform);
- }
+ context = new Context(*sys, *integ);
}
- if (context == NULL)
+ else
+ */
{
- gmx_fatal(FARGS, "The requested platform \"%s\" could not be found.\n", opt->getOptionValue("platform").c_str());
+ /* which platform should we use */
+ for (int i = 0; i < (int)Platform::getNumPlatforms() && context == NULL; i++)
+ {
+ if (isStringEqNCase(opt->getOptionValue("platform"), Platform::getPlatform(i).getName()))
+ {
+ Platform& platform = Platform::getPlatform(i);
+ // set standard properties
+ platform.setPropertyDefaultValue("CudaDevice", opt->getOptionValue("deviceid"));
+ // TODO add extra properties
+ context = new Context(*sys, *integ, platform);
+ }
+ }
+ if (context == NULL)
+ {
+ gmx_fatal(FARGS, "The requested platform \"%s\" could not be found.",
+ opt->getOptionValue("platform").c_str());
+ }
}
- }
- Platform& platform = context->getPlatform();
- fprintf(fplog, "Gromacs will use the OpenMM platform: %s\n", platform.getName().c_str());
+ Platform& platform = context->getPlatform();
+ fprintf(fplog, "Gromacs will use the OpenMM platform: %s\n", platform.getName().c_str());
- const vector<string>& properties = platform.getPropertyNames();
- if (debug)
- {
- for (int i = 0; i < properties.size(); i++)
+ const vector<string>& properties = platform.getPropertyNames();
+ if (debug)
{
- printf(">> %s: %s\n", properties[i].c_str(), platform.getPropertyValue(*context, properties[i]).c_str());
- fprintf(fplog, ">> %s: %s\n", properties[i].c_str(), platform.getPropertyValue(*context, properties[i]).c_str());
+ for (int i = 0; i < (int)properties.size(); i++)
+ {
+ fprintf(debug, ">> %s: %s\n", properties[i].c_str(),
+ platform.getPropertyValue(*context, properties[i]).c_str());
+ }
}
- }
- int devId;
- if (!from_string<int>(devId, platform.getPropertyValue(*context, "CudaDevice"), std::dec))
- {
- gmx_fatal(FARGS, "Internal error: couldn't determine the device selected by OpenMM");
- }
+ /* only for CUDA */
+ if (isStringEqNCase(opt->getOptionValue("platform"), "CUDA"))
+ {
+ int tmp;
+ if (!from_string<int>(tmp, platform.getPropertyValue(*context, "CudaDevice"), std::dec))
+ {
+ gmx_fatal(FARGS, "Internal error: couldn't determine the device selected by OpenMM");
- /* check GPU compatibility */
- char gpuname[STRLEN];
- if (!is_supported_cuda_gpu(-1, gpuname))
- {
- if (!gmx_strcasecmp(opt->getOptionValue("force-device").c_str(), "yes"))
+ }
+
+ /* For now this is just to double-check if OpenMM selected the GPU we wanted,
+ but when we'll let OpenMM select the GPU automatically, it will query the devideId.
+ */
+ if (tmp != devId)
+ {
+ gmx_fatal(FARGS, "Internal error: OpenMM is using device #%d"
+ "while initialized for device #%d", tmp, devId);
+ }
+ cout << ">>>>> OpenMM devId=" << tmp << endl;
+
+ /* check GPU compatibility */
+ char gpuname[STRLEN];
+ devId = atoi(opt->getOptionValue("deviceid").c_str());
+ if (!is_supported_cuda_gpu(-1, gpuname))
+ {
+ if (!gmx_strcasecmp(opt->getOptionValue("force-device").c_str(), "yes"))
+ {
+ sprintf(warn_buf, "Non-supported GPU selected (#%d, %s), forced continuing."
+ "Note, that the simulation can be slow or it migth even crash.",
+ devId, gpuname);
+ fprintf(fplog, "%s\n", warn_buf);
+ gmx_warning(warn_buf);
+ }
+ else
+ {
+ gmx_fatal(FARGS, "The selected GPU (#%d, %s) is not supported by Gromacs! "
+ "Most probably you have a low-end GPU which would not perform well, "
+ "or new hardware that has not been tested with the current release. "
+ "If you still want to try using the device, use the force-device=yes option.",
+ devId, gpuname);
+ }
+ }
+ else
+ {
+ fprintf(fplog, "Gromacs will run on the GPU #%d (%s).\n", devId, gpuname);
+ }
+ }
+
+ /* only for CUDA */
+ if (isStringEqNCase(opt->getOptionValue("platform"), "CUDA"))
{
- sprintf(warn_buf, "Non-supported GPU selected (#%d, %s), forced continuing.\n"
- "Note, that the simulation can be slow or it migth even crash.", devId, gpuname);
- fprintf(fplog, "%s", warn_buf);
- gmx_warning(warn_buf);
+ /* pre-simulation memtest */
+ runMemtest(fplog, -1, "Pre", opt);
}
- else
+
+ vector<Vec3> pos(numAtoms);
+ vector<Vec3> vel(numAtoms);
+ for (int i = 0; i < numAtoms; ++i)
{
- gmx_fatal(FARGS, "The selected GPU (#%d, %s) is not supported by Gromacs! "
- "Most probably you have a low-end GPU which would not perform well, or new hardware that"
- "has not been tested yet with Gromacs-OpenMM. If you still want to try using this "
- "device use the force=on option.", devId, gpuname);
+ pos[i] = Vec3(state->x[i][0], state->x[i][1], state->x[i][2]);
+ vel[i] = Vec3(state->v[i][0], state->v[i][1], state->v[i][2]);
}
+ context->setPositions(pos);
+ context->setVelocities(vel);
+
+ // Return a structure containing the system, integrator, and context.
+ OpenMMData* data = new OpenMMData();
+ data->system = sys;
+ data->integrator = integ;
+ data->context = context;
+ data->removeCM = (ir->nstcomm > 0);
+ data->platformOpt = opt;
+ return data;
}
- else
+ catch (std::exception& e)
{
- fprintf(fplog, "Gromacs will run on the GPU #%d (%s).\n", devId, gpuname);
- }
-
- /* do the pre-simulation memtest */
- run_memtest(fplog, -1, "Pre", opt);
-
- vector<Vec3> pos(numAtoms);
- vector<Vec3> vel(numAtoms);
- for (int i = 0; i < numAtoms; ++i) {
- pos[i] = Vec3(state->x[i][0], state->x[i][1], state->x[i][2]);
- vel[i] = Vec3(state->v[i][0], state->v[i][1], state->v[i][2]);
- }
- context->setPositions(pos);
- context->setVelocities(vel);
-
- // Return a structure containing the system, integrator, and context.
- OpenMMData* data = new OpenMMData();
- data->system = sys;
- data->integrator = integ;
- data->context = context;
- data->removeCM = (ir->nstcomm > 0);
- data->platformOpt = opt;
- return data;
-
- } catch (std::exception& e) {
- gmx_fatal(FARGS, "OpenMM exception caught while initializating: %s\n", e.what());
- }
+ gmx_fatal(FARGS, "OpenMM exception caught while initializating: %s", e.what());
+ }
+ return NULL; /* just to avoid warnings */
}
-/**
- * Integrate one step.
+/*!
+ * \brief Integrate one step.
*
- * @param data the OpenMMData object created by openmm_init().
+ * \param[in] data OpenMMData object created by openmm_init().
*/
void openmm_take_one_step(void* data)
{
- // static int step = 0; printf("----> taking step #%d\n", step++);
- try {
+ // static int step = 0; printf("----> taking step #%d\n", step++);
+ try
+ {
static_cast<OpenMMData*>(data)->integrator->step(1);
- } catch (std::exception& e) {
- gmx_fatal(FARGS, "OpenMM exception caught while taking a step: %s\n", e.what());
+ }
+ catch (std::exception& e)
+ {
+ gmx_fatal(FARGS, "OpenMM exception caught while taking a step: %s", e.what());
}
}
-/**
- * Integrate n steps.
+/*!
+ * \brief Integrate n steps.
*
- * @param data the OpenMMData object created by openmm_init().
+ * \param[in] data OpenMMData object created by openmm_init().
*/
void openmm_take_steps(void* data, int nstep)
{
- try {
+ try
+ {
static_cast<OpenMMData*>(data)->integrator->step(nstep);
- } catch (std::exception& e) {
- gmx_fatal(FARGS, "OpenMM exception caught while taking a step: %s\n", e.what());
+ }
+ catch (std::exception& e)
+ {
+ gmx_fatal(FARGS, "OpenMM exception caught while taking a step: %s", e.what());
}
}
-/**
- * Clean up all the data structures used by OpenMM.
+/*!
+ * \brief Clean up the data structures cretead for OpenMM.
*
- * @param log file pointer
- * @param data the OpenMMData object created by openmm_init().
+ * \param[in] log Log file pointer.
+ * \param[in] data OpenMMData object created by openmm_init().
*/
void openmm_cleanup(FILE* fplog, void* data)
{
OpenMMData* d = static_cast<OpenMMData*>(data);
- run_memtest(fplog, -1, "Post", d->platformOpt);
+ /* only for CUDA */
+ if (isStringEqNCase(d->platformOpt->getOptionValue("platform"), "CUDA"))
+ {
+ /* post-simulation memtest */
+ runMemtest(fplog, -1, "Post", d->platformOpt);
+ }
delete d->system;
delete d->integrator;
delete d->context;
delete d;
}
-/**
- * Copy the current state information (positions, velocities, and forces) into the data structures used
- * by Gromacs.
+/*!
+ * \brief Copy the current state information from OpenMM into the Gromacs data structures.
+ *
+ * This function results in the requested proprties to be copied from the
+ * GPU to host. As this represents a bottleneck, the frequency of pulling data
+ * should be minimized.
*
- * @param data the OpenMMData object created by openmm_init().
+ * \param[in] data OpenMMData object created by openmm_init().
+ * \param[out] time Simulation time for which the state was created.
+ * \param[out] state State of the system: coordinates and velocities.
+ * \param[out] f Forces.
+ * \param[out] enerd Energies.
+ * \param[in] includePos True if coordinates are requested.
+ * \param[in] includeVel True if velocities are requested.
+ * \param[in] includeForce True if forces are requested.
+ * \param[in] includeEnergy True if energies are requested.
*/
void openmm_copy_state(void *data,
- t_state *state, double *time,
- rvec f[], gmx_enerdata_t *enerd,
- bool includePos, bool includeVel, bool includeForce, bool includeEnergy)
+ t_state *state, double *time,
+ rvec f[], gmx_enerdata_t *enerd,
+ bool includePos, bool includeVel, bool includeForce, bool includeEnergy)
{
int types = 0;
if (includePos)
types += State::Energy;
if (types == 0)
return;
- try {
+ try
+ {
State currentState = static_cast<OpenMMData*>(data)->context->getState(types);
int numAtoms = static_cast<OpenMMData*>(data)->system->getNumParticles();
- if (includePos) {
- for (int i = 0; i < numAtoms; i++) {
+ if (includePos)
+ {
+ for (int i = 0; i < numAtoms; i++)
+ {
Vec3 x = currentState.getPositions()[i];
state->x[i][0] = x[0];
state->x[i][1] = x[1];
state->x[i][2] = x[2];
}
}
- if (includeVel) {
- for (int i = 0; i < numAtoms; i++) {
+ if (includeVel)
+ {
+ for (int i = 0; i < numAtoms; i++)
+ {
Vec3 v = currentState.getVelocities()[i];
state->v[i][0] = v[0];
state->v[i][1] = v[1];
state->v[i][2] = v[2];
}
}
- if (includeForce) {
- for (int i = 0; i < numAtoms; i++) {
+ if (includeForce)
+ {
+ for (int i = 0; i < numAtoms; i++)
+ {
Vec3 force = currentState.getForces()[i];
f[i][0] = force[0];
f[i][1] = force[1];
f[i][2] = force[2];
}
}
- if (includeEnergy) {
+ if (includeEnergy)
+ {
int numConstraints = static_cast<OpenMMData*>(data)->system->getNumConstraints();
int dof = 3*numAtoms-numConstraints;
if (static_cast<OpenMMData*>(data)->removeCM)
enerd->term[F_TEMP] = 2.0*enerd->term[F_EKIN]/dof/BOLTZ;
}
*time = currentState.getTime();
- } catch (std::exception& e) {
- gmx_fatal(FARGS, "OpenMM exception caught while retrieving state information: %s\n", e.what());
+ }
+ catch (std::exception& e)
+ {
+ gmx_fatal(FARGS, "OpenMM exception caught while retrieving state information: %s", e.what());
}
}
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
#ifndef _OPENMM_WRAPPER_H_
#define _OPENMM_WRAPPER_H_
#ifdef GMX_OPENMM
void* openmm_init(FILE *fplog, const char *platformOptStr,
- t_commrec *cr,t_inputrec *ir,
+ t_inputrec *ir,
gmx_mtop_t *top_global, gmx_localtop_t *top,
- t_mdatoms *mdatoms, t_forcerec *fr,t_state *state);
+ t_mdatoms *mdatoms, t_forcerec *fr, t_state *state);
void openmm_take_one_step(void* data);
void openmm_cleanup(FILE *fplog, void* data);
#else
-/* dummy versions of the openmm wrapper functions to enable compilation of
+/* dummy versions of the wrapper functions to enable compilation of
do_md_openmm even when OpenMM is not used */
void* openmm_init(FILE *fplog, const char *platformOptStr,
- t_commrec *cr,t_inputrec *ir,
+ t_inputrec *ir,
gmx_mtop_t *top_global, gmx_localtop_t *top,
- t_mdatoms *mdatoms, t_forcerec *fr,t_state *state){return NULL;}
+ t_mdatoms *mdatoms, t_forcerec *fr, t_state *state){return NULL;}
void openmm_take_one_step(void* data){}
void openmm_cleanup(FILE *fplog, void* data){}
-#endif //GMX_OPENMM
+#endif /*GMX_OPENMM*/
#ifdef __cplusplus
char main[6];
char nter[6];
char cter[6];
+ char bter[6];
} rtprename_t;
static const char *get_lystp(int resnr,int nrr,const rtprename_t *rr)
{
enum { elys, elysH, elysNR };
- const char *lh[elysNR] = { "LYS", "LYSH" };
+ const char *lh[elysNR] = { "LYSN", "LYS" };
const char *expl[elysNR] = {
"Not protonated (charge 0)",
"Protonated (charge +1)"
static const char *get_cystp(int resnr,int nrr,const rtprename_t *rr)
{
enum { ecys, ecysH, ecysNR };
- const char *lh[ecysNR] = { "CYS", "CYSH" };
+ const char *lh[ecysNR] = { "CYS2", "CYS" };
const char *expl[ecysNR] = {
"Cysteine in disulfide bridge",
"Protonated"
ncol = 0;
while(get_a_line(fp,line,STRLEN)) {
srenew(rr,n+1);
- nc = sscanf(line,"%s %s %s %s %s",
- rr[n].gmx,rr[n].main,rr[n].nter,rr[n].cter,buf);
+ nc = sscanf(line,"%s %s %s %s %s %s",
+ rr[n].gmx,rr[n].main,rr[n].nter,rr[n].cter,rr[n].bter,buf);
if (ncol == 0) {
- if (nc != 2 && nc != 4) {
- gmx_fatal(FARGS,"Residue renaming database '%s' has %d columns instead of %d or %d",fname,ncol,2,4);
+ if (nc != 2 && nc != 5) {
+ gmx_fatal(FARGS,"Residue renaming database '%s' has %d columns instead of %d or %d",fname,ncol,2,5);
}
ncol = nc;
} else if (nc != ncol) {
/* This file does not have special termini names, copy them from main */
strcpy(rr[n].nter,rr[n].main);
strcpy(rr[n].cter,rr[n].main);
+ strcpy(rr[n].bter,rr[n].main);
}
n++;
bC = TRUE;
}
}
- if (bN) {
+ if (bN && bC) {
+ nn = rr[i].bter;
+ } else if (bN) {
nn = rr[i].nter;
} else if (bC) {
nn = rr[i].cter;
rename_pdbres(atoms,"HOH",watres,FALSE,symtab);
rename_pdbres(atoms,"SOL",watres,FALSE,symtab);
rename_pdbres(atoms,"WAT",watres,FALSE,symtab);
-
- rename_pdbres(atoms,"HEM","HEME",FALSE,symtab);
- rename_atoms("xlateat.dat",NULL,atoms,symtab,NULL,TRUE,aan,TRUE,bVerbose);
+ rename_atoms("xlateat.dat",NULL,FALSE,
+ atoms,symtab,NULL,TRUE,aan,TRUE,bVerbose);
if (natom == 0)
return 0;
if (bPheU) rename_bb(pdba,"PHE","PHEU",FALSE,symtab);
if (bLysMan)
rename_bbint(pdba,"LYS",get_lystp,FALSE,symtab,nrr,rr);
- else
- rename_bb(pdba,"LYS","LYSH",FALSE,symtab);
if (bArgMan)
rename_bbint(pdba,"ARG",get_argtp,FALSE,symtab,nrr,rr);
if (bGlnMan)
else
rename_bb(pdba,"GLUH","GLU",FALSE,symtab);
- if (bRenameCys)
- /* Make sure we don't have things like CYS? */
+ if (bRenameCys) {
+ /* Make sure we don't have things like CYS?
+ * And rename CYS to CYSH, since that is the Gromacs standard
+ * unbound cysteine rtp entry name.
+ */
rename_bb(pdba,"CYS","CYS",FALSE,symtab);
+ }
if (!bHisMan)
set_histp(pdba,x,angle,distance);
*rc=-1;
for(rnr=r0; rnr<r1; rnr++) {
- if ((*rn == -1) && (is_protein(aan,*pdba->resinfo[rnr].name)))
+ if ((*rn == -1) && (is_residue(aan,*pdba->resinfo[rnr].name)))
*rn=rnr;
- if ((*rc != rnr) && (is_protein(aan,*pdba->resinfo[rnr].name)))
+ if ((*rc != rnr) && (is_residue(aan,*pdba->resinfo[rnr].name)))
*rc=rnr;
}
"The corresponding data files can be found in the library directory",
"in the subdirectory <forcefield>.ff.",
- "Check chapter 5 of the manual for more",
- "information about file formats. By default the forcefield selection",
- "is interactive, but you can use the [TT]-ff[tt] option to specify",
+ "Note that pdb2gmx will also look for a [TT]forcefield.itp[tt] file",
+ "in such subdirectories in the current working directory.",
+ "After choosing a force field, all files will be read only from",
+ "the corresponding directory, unless the [TT]-cwd[tt] option is used.",
+ "Check chapter 5 of the manual for more information about file formats.",
+ "By default the forcefield selection is interactive,",
+ "but you can use the [TT]-ff[tt] option to specify",
"one of the short names above on the command line instead. In that",
"case pdb2gmx just looks for the corresponding file.[PAR]",
"files, that allow it to make special bonds (Cys-Cys, Heme-His, etc.),",
"if necessary this can be done manually. The program can prompt the",
"user to select which kind of LYS, ASP, GLU, CYS or HIS residue she",
- "wants. For LYS the choice is between LYS (two protons on NZ) or LYSH",
- "(three protons, default), for ASP and GLU unprotonated (default) or",
- "protonated, for HIS the proton can be either on ND1 (HISA), on NE2",
- "(HISB) or on both (HISH). By default these selections are done",
- "automatically. For His, this is based on an optimal hydrogen bonding",
+ "wants. For LYS the choice is between neutral (two protons on NZ) or",
+ "protonated (three protons, default), for ASP and GLU unprotonated",
+ "(default) or protonated, for HIS the proton can be either on ND1,",
+ "on NE2 or on both. By default these selections are done automatically.",
+ "For His, this is based on an optimal hydrogen bonding",
"conformation. Hydrogen bonds are defined based on a simple geometric",
"criterium, specified by the maximum hydrogen-donor-acceptor angle",
"and donor-acceptor distance, which are set by [TT]-angle[tt] and",
"with a disulfide brigde or intermolecular distance restraints.[PAR]",
"pdb2gmx will also check the occupancy field of the pdb file.",
- "If any of the occupanccies are not one, indicating that the atom is",
+ "If any of the occupancies are not one, indicating that the atom is",
"not resolved well in the structure, a warning message is issued.",
"When a pdb file does not originate from an X-Ray structure determination",
"all occupancy fields may be zero. Either way, it is up to the user",
t_aa_names *aan;
const char *top_fn;
char fn[256],itp_fn[STRLEN],posre_fn[STRLEN],buf_fn[STRLEN];
- char molname[STRLEN],title[STRLEN],resname[STRLEN],quote[STRLEN];
+ char molname[STRLEN],title[STRLEN],quote[STRLEN],generator[STRLEN];
char *c,forcefield[STRLEN],ffdir[STRLEN];
- char fff[STRLEN],suffix[STRLEN];
+ char ffname[STRLEN],suffix[STRLEN];
+ char *watermodel;
const char *watres;
int nrtpf;
char **rtpf;
/* Command line arguments must be static */
- static bool bNewRTP=FALSE,bAllowOverrideRTP=FALSE,bMerge=FALSE;
+ static bool bNewRTP=FALSE,bAddCWD=FALSE,bAllowOverrideRTP=FALSE,bMerge=FALSE;
static bool bInter=FALSE, bCysMan=FALSE;
static bool bLysMan=FALSE, bAspMan=FALSE, bGluMan=FALSE, bHisMan=FALSE;
static bool bGlnMan=FALSE, bArgMan=FALSE;
static real angle=135.0, distance=0.3,posre_fc=1000;
static real long_bond_dist=0.25, short_bond_dist=0.05;
static const char *vsitestr[] = { NULL, "none", "hydrogens", "aromatics", NULL };
- static const char *watstr[] = { NULL, "spc", "spce", "tip3p", "tip4p", "tip5p", "f3c", NULL };
+ static const char *watstr[] = { NULL, "select", "none", "spc", "spce", "tip3p", "tip4p", "tip5p", NULL };
static const char *ff = "select";
t_pargs pa[] = {
{ "-newrtp", FALSE, etBOOL, {&bNewRTP},
"HIDDENWrite the residue database in new format to 'new.rtp'"},
+ { "-cwd", FALSE, etBOOL, {&bAddCWD},
+ "Also read force field files from the current working directory" },
{ "-rtpo", FALSE, etBOOL, {&bAllowOverrideRTP},
"Allow an entry in a local rtp file to override a library rtp entry"},
{ "-lb", FALSE, etREAL, {&long_bond_dist},
{ "-ff", FALSE, etSTR, {&ff},
"Force field, interactive by default. Use -h for information." },
{ "-water", FALSE, etENUM, {watstr},
- "Water model to use: with GROMOS we recommend SPC, with OPLS, TIP4P" },
+ "Water model to use" },
{ "-inter", FALSE, etBOOL, {&bInter},
"Set the next 8 options to interactive"},
{ "-ss", FALSE, etBOOL, {&bCysMan},
"Interactive Glutamine selection, iso neutral" },
{ "-his", FALSE, etBOOL, {&bHisMan},
"Interactive Histidine selection, iso checking H-bonds" },
- { "-cys", FALSE, etBOOL, {&bRenameCys},
- "HIDDENRename cysteines to cys" },
+ { "-cysh", FALSE, etBOOL, {&bRenameCys},
+ "HIDDENUse rtp entry CYSH for cysteines" },
{ "-angle", FALSE, etREAL, {&angle},
"Minimum hydrogen-donor-acceptor angle for a H-bond (degrees)" },
{ "-dist", FALSE, etREAL, {&distance},
forcefield,sizeof(forcefield),
ffdir,sizeof(ffdir));
- if (strlen(forcefield) > 2)
- strcpy(fff,&(forcefield[2]));
- else
- gmx_incons(forcefield);
+ if (strlen(forcefield) > 0) {
+ strcpy(ffname,forcefield);
+ ffname[0] = toupper(ffname[0]);
+ } else {
+ gmx_fatal(FARGS,"Empty forcefield string");
+ }
- printf("\nUsing force field '%s' in directory '%s'\n\n",
- forcefield,ffdir);
+ printf("\nUsing the %s force field in directory %s\n\n",
+ ffname,ffdir);
+ choose_watermodel(watstr[0],ffdir,&watermodel);
+
if (bInter) {
/* if anything changes here, also change description of -inter */
bCysMan = TRUE;
aan = get_aa_names();
/* Read residue renaming database(s), if present */
- nrrn = fflib_search_file_end(ffdir,".r2b",FALSE,&rrn);
+ nrrn = fflib_search_file_end(ffdir,bAddCWD,".r2b",FALSE,&rrn);
nrtprename = 0;
rtprename = NULL;
for(i=0; i<nrrn; i++) {
}
sfree(rrn);
- /* Encad only works with the f3c water model */
- if(strncmp(forcefield,"ffencad",7) == 0)
- {
- printf("Encad detected, switching to the F3C water model...\n");
- watstr[0] = "f3c";
- watres = "WAT";
- }
-
clear_mat(box);
- if (strcmp(watstr[0],"tip4p") == 0)
+ if (watermodel != NULL && (strstr(watermodel,"4p") ||
+ strstr(watermodel,"4P"))) {
watres = "HO4";
- else if (strcmp(watstr[0],"tip5p") == 0)
+ } else if (watermodel != NULL && (strstr(watermodel,"5p") ||
+ strstr(watermodel,"5P"))) {
watres = "HO5";
- else
+ } else {
watres = "HOH";
+ }
aps = gmx_atomprop_init();
natom = read_pdball(opt2fn("-f",NFILE,fnm),opt2fn_null("-q",NFILE,fnm),title,
check_occupancy(&pdba_all,opt2fn("-f",NFILE,fnm),bVerbose);
/* Read atomtypes... */
- atype = read_atype(ffdir,&symtab);
+ atype = read_atype(ffdir,bAddCWD,&symtab);
/* read residue database */
printf("Reading residue database... (%s)\n",forcefield);
- nrtpf = fflib_search_file_end(ffdir,".rtp",TRUE,&rtpf);
+ nrtpf = fflib_search_file_end(ffdir,bAddCWD,".rtp",TRUE,&rtpf);
nrtp = 0;
restp = NULL;
for(i=0; i<nrtpf; i++) {
}
/* read hydrogen database */
- nah = read_h_db(ffdir,&ah);
+ nah = read_h_db(ffdir,bAddCWD,&ah);
/* Read Termini database... */
- nNtdb=read_ter_db(ffdir,'n',&ntdb,atype);
- nCtdb=read_ter_db(ffdir,'c',&ctdb,atype);
+ nNtdb=read_ter_db(ffdir,bAddCWD,'n',&ntdb,atype);
+ nCtdb=read_ter_db(ffdir,bAddCWD,'c',&ctdb,atype);
top_fn=ftp2fn(efTOP,NFILE,fnm);
top_file=gmx_fio_fopen(top_fn,"w");
- print_top_header(top_file,top_fn,title,FALSE,ffdir,mHmult);
+
+#ifdef PACKAGE_VERSION
+ sprintf(generator,"%s - version %s",ShortProgram(), PACKAGE_VERSION );
+#else
+ sprintf(generator,"%s - version %s",ShortProgram(), "unknown" );
+#endif
+ print_top_header(top_file,top_fn,generator,FALSE,ffdir,mHmult);
nincl=0;
nmol=0;
}
/* Check for disulphides and other special bonds */
- rename_bb(pdba,"CYSH","CYS",TRUE,&symtab);
- nssbonds=mk_specbonds(pdba,x,bCysMan,&ssbonds);
- rename_bb(pdba,"CYS","CYSH",TRUE,&symtab);
+ nssbonds = mk_specbonds(pdba,x,bCysMan,&ssbonds,bVerbose);
if (nrtprename > 0) {
rename_resrtp(pdba,cc->nterpairs,cc->rN,cc->rC,nrtprename,rtprename,
*/
/* First the N terminus */
if (nNtdb > 0) {
- strncpy(resname,*pdba->resinfo[cc->rN[i]].name,3);
- resname[3] = '\0';
- tdblist=filter_ter(nrtp,restp,nNtdb,ntdb,resname,&ntdblist);
+ tdblist = filter_ter(nrtp,restp,nNtdb,ntdb,
+ *pdba->resinfo[cc->rN[i]].name,
+ *pdba->resinfo[cc->rN[i]].rtp,
+ &ntdblist);
if(ntdblist==0)
gmx_fatal(FARGS,"No suitable N-terminus found in database");
/* And the C terminus */
if (nCtdb > 0) {
- strncpy(resname,*pdba->resinfo[cc->rC[i]].name,3);
- tdblist=filter_ter(nrtp,restp,nCtdb,ctdb,resname,&ntdblist);
+ tdblist = filter_ter(nrtp,restp,nCtdb,ctdb,
+ *pdba->resinfo[cc->rC[i]].name,
+ *pdba->resinfo[cc->rC[i]].rtp,
+ &ntdblist);
if(ntdblist==0)
gmx_fatal(FARGS,"No suitable C-terminus found in database");
requires some re-thinking of code in gen_vsite.c, which I won't
do now :( AF 26-7-99 */
- rename_atoms(NULL,ffdir,pdba,&symtab,restp_chain,FALSE,aan,FALSE,bVerbose);
+ rename_atoms(NULL,ffdir,bAddCWD,
+ pdba,&symtab,restp_chain,FALSE,aan,FALSE,bVerbose);
- match_atomnames_with_rtp(restp_chain,hb_chain,pdba,bVerbose);
+ match_atomnames_with_rtp(restp_chain,hb_chain,pdba,x,bVerbose);
if (bSort) {
block = new_blocka();
nmol++;
if (bITP)
- print_top_comment(itp_file,itp_fn,title,TRUE);
+ print_top_comment(itp_file,itp_fn,generator,TRUE);
if (cc->bAllWat)
top_file2=NULL;
nrtp,restp,
restp_chain,hb_chain,
cc->nterpairs,cc->ntdb,cc->ctdb,cc->rN,cc->rC,bAllowMissing,
- bVsites,bVsiteAromatics,forcefield,ffdir,
+ bVsites,bVsiteAromatics,forcefield,ffdir,bAddCWD,
mHmult,nssbonds,ssbonds,
long_bond_dist,short_bond_dist,bDeuterate,bChargeGroups,bCmap,
bRenumRes,bRTPresname);
write_sto_conf(fn,quote,pdba,x,NULL,ePBC,box);
}
}
-
- sprintf(buf_fn,"%s%c%s.itp",ffdir,DIR_SEPARATOR,watstr[0]);
- if (!fflib_fexist(buf_fn)) {
+
+ if (watermodel == NULL) {
for(chain=0; chain<nch; chain++) {
if (chains[chain].bAllWat) {
- gmx_fatal(FARGS,"The topology file '%s' for the selected water model '%s' can not be found in the force field directory. Select a different water model or remove the water from your input file.",
- buf_fn,watstr[0]);
+ gmx_fatal(FARGS,"You have chosen not to include a water model, but there is water in the input file. Select a water model or remove the water from your input file.");
}
}
- /* Do not include the water topology file. */
- watstr[0] = NULL;
+ } else {
+ sprintf(buf_fn,"%s%c%s.itp",ffdir,DIR_SEPARATOR,watermodel);
+ if (!fflib_fexist(buf_fn)) {
+ gmx_fatal(FARGS,"The topology file '%s' for the selected water model '%s' can not be found in the force field directory. Select a different water model.",
+ buf_fn,watermodel);
+ }
}
- print_top_mols(top_file,title,ffdir,watstr[0],nincl,incls,nmol,mols);
+ print_top_mols(top_file,title,ffdir,watermodel,nincl,incls,nmol,mols);
gmx_fio_fclose(top_file);
done_aa_names(&aan);
write_sto_conf(ftp2fn(efSTO,NFILE,fnm),title,atoms,x,NULL,ePBC,box);
printf("\t\t--------- PLEASE NOTE ------------\n");
- printf("You have succesfully generated a topology from: %s.\n",
+ printf("You have successfully generated a topology from: %s.\n",
opt2fn("-f",NFILE,fnm));
- printf("The %s force field and the %s water model are used.\n",
- fff,watstr[0]);
- printf("Note that the default mechanism for selecting a force fields has\n"
- "changed, starting from GROMACS version 3.2.0\n");
+ if (watstr[0] != NULL) {
+ printf("The %s force field and the %s water model are used.\n",
+ ffname,watstr[0]);
+ } else {
+ printf("The %s force field is used.\n",
+ ffname);
+ }
printf("\t\t--------- ETON ESAELP ------------\n");
#include "macros.h"
#include "symtab.h"
#include "futil.h"
+#include "statutil.h"
#include "gmx_fatal.h"
#include "pdb2top.h"
#include "gpp_nextnb.h"
#include "strdb.h"
/* this must correspond to enum in pdb2top.h */
-const char *hh[ehisNR] = { "HISA", "HISB", "HISH", "HIS1" };
+const char *hh[ehisNR] = { "HISD", "HISE", "HISH", "HIS1" };
static int missing_atoms(t_restp *rp, int resind,t_atoms *at, int i0, int i)
{
return (fabs(x-ix) < tol);
}
+static void swap_strings(char **s,int i,int j)
+{
+ char *tmp;
+
+ tmp = s[i];
+ s[i] = s[j];
+ s[j] = tmp;
+}
+
void
choose_ff(const char *ffsel,
char *forcefield, int ff_maxlen,
{
int nff;
char **ffdirs,**ffs,*ptr;
- int i,sel;
- char buf[STRLEN],*doc_dir;
+ int i,j,sel;
+ char buf[STRLEN],**desc,*doc_dir;
FILE *fp;
char *pret;
}
else if (nff > 1)
{
- printf("\nSelect the Force Field:\n");
+ snew(desc,nff);
for(i=0; (i<nff); i++)
{
sprintf(buf,"%s%c%s",
{
/* We don't use fflib_open, because we don't want printf's */
fp = ffopen(doc_dir,"r");
- get_a_line(fp,buf,STRLEN);
+ snew(desc[i],STRLEN);
+ get_a_line(fp,desc[i],STRLEN);
ffclose(fp);
sfree(doc_dir);
- printf("%2d: %s\n",i,buf);
}
else
{
- printf("%2d: %s\n",i,ffs[i]);
+ desc[i] = strdup(ffs[i]);
+ }
+ }
+ for(i=0; (i<nff); i++)
+ {
+ for(j=i+1; (j<nff); j++)
+ {
+ if ((desc[i][0] == '[' && desc[j][0] != '[') ||
+ ((desc[i][0] == '[' || desc[j][0] != '[') &&
+ strcasecmp(desc[i],desc[j]) > 0))
+ {
+ swap_strings(ffdirs,i,j);
+ swap_strings(ffs ,i,j);
+ swap_strings(desc ,i,j);
+ }
}
}
+
+ printf("\nSelect the Force Field:\n");
+ for(i=0; (i<nff); i++)
+ {
+ printf("%2d: %s\n",i+1,desc[i]);
+ sfree(desc[i]);
+ }
+ sfree(desc);
+
do
{
pret = fgets(buf,STRLEN,stdin);
- if(pret != NULL)
+ if (pret != NULL)
{
sscanf(buf,"%d",&sel);
+ sel--;
}
}
while ( pret==NULL || (sel < 0) || (sel >= nff));
sel = 0;
}
- if (strlen(ffs[sel]) >= ff_maxlen)
+ if (strlen(ffs[sel]) >= (size_t)ff_maxlen)
{
gmx_fatal(FARGS,"Length of force field name (%d) >= maxlen (%d)",
strlen(ffs[sel]),ff_maxlen);
}
strcpy(forcefield,ffs[sel]);
- if (strlen(ffdirs[sel]) >= ffdir_maxlen)
+ if (strlen(ffdirs[sel]) >= (size_t)ffdir_maxlen)
{
gmx_fatal(FARGS,"Length of force field dir (%d) >= maxlen (%d)",
strlen(ffdirs[sel]),ffdir_maxlen);
sfree(ffs);
}
+void choose_watermodel(const char *wmsel,const char *ffdir,
+ char **watermodel)
+{
+ const char *fn_watermodels="watermodels.dat";
+ char fn_list[STRLEN];
+ FILE *fp;
+ char buf[STRLEN];
+ int nwm,sel,i;
+ char **model;
+ char *pret;
+
+ if (strcmp(wmsel,"none") == 0)
+ {
+ *watermodel = NULL;
+
+ return;
+ }
+ else if (strcmp(wmsel,"select") != 0)
+ {
+ *watermodel = strdup(wmsel);
+
+ return;
+ }
+
+ sprintf(fn_list,"%s%c%s",ffdir,DIR_SEPARATOR,fn_watermodels);
+
+ if (!fflib_fexist(fn_list))
+ {
+ fprintf(stderr,"No file '%s' found, will not include a water model\n",
+ fn_watermodels);
+ *watermodel = NULL;
+
+ return;
+ }
+
+ fp = fflib_open(fn_list);
+ printf("\nSelect the Water Model:\n");
+ nwm = 0;
+ model = NULL;
+ while (get_a_line(fp,buf,STRLEN))
+ {
+ srenew(model,nwm+1);
+ snew(model[nwm],STRLEN);
+ sscanf(buf,"%s%n",model[nwm],&i);
+ if (i > 0)
+ {
+ ltrim(buf+i);
+ fprintf(stderr,"%2d: %s\n",nwm+1,buf+i);
+ nwm++;
+ }
+ else
+ {
+ sfree(model[nwm]);
+ }
+ }
+ fclose(fp);
+ fprintf(stderr,"%2d: %s\n",nwm,"None");
+
+ do
+ {
+ pret = fgets(buf,STRLEN,stdin);
+
+ if (pret != NULL)
+ {
+ sscanf(buf,"%d",&sel);
+ sel--;
+ }
+ }
+ while (pret == NULL || sel < 0 || sel > nwm);
+
+ if (sel == nwm)
+ {
+ *watermodel = NULL;
+ }
+ else
+ {
+ *watermodel = strdup(model[sel]);
+ }
+
+ for(i=0; i<nwm; i++)
+ {
+ sfree(model[i]);
+ }
+ sfree(model);
+}
+
static int name2type(t_atoms *at, int **cgnr, gpp_atomtype_t atype,
t_restp restp[])
{
"in pdb2top\n",mHmult);
}
-void print_top_comment(FILE *out,const char *filename,const char *title,bool bITP)
+void print_top_comment(FILE *out,const char *filename,
+ const char *generator,bool bITP)
{
char tmp[256];
-
+
nice_header(out,filename);
fprintf(out,";\tThis is your %stopology file\n",bITP ? "include " : "");
- cool_quote(tmp,255,NULL);
- fprintf(out,";\t%s\n",title[0]?title:tmp);
- fprintf(out,";\n");
+ fprintf(out,";\tit was generated using program:\n;\t%s\n",
+ (NULL == generator) ? "unknown" : generator);
+ fprintf(out,";\twith command line:\n;\t%s\n;\n\n",command_line());
}
void print_top_header(FILE *out,const char *filename,
}
}
-static bool match_atomnames_with_rtp_atom(t_atoms *pdba,int atind,
+static bool match_atomnames_with_rtp_atom(t_atoms *pdba,rvec *x,int atind,
t_restp *rptr,t_hackblock *hbr,
bool bVerbose)
{
printf("Deleting atom '%s' in residue '%s' %d\n",
oldnm,rptr->resname,resnr);
}
- sfree(pdba->atomname[atind]);
+ /* We should free the atom name,
+ * but it might be used multiple times in the symtab.
+ * sfree(pdba->atomname[atind]);
+ */
for(k=atind+1; k<pdba->nr; k++)
{
pdba->atom[k-1] = pdba->atom[k];
pdba->atomname[k-1] = pdba->atomname[k];
+ copy_rvec(x[k],x[k-1]);
}
pdba->nr--;
bDeleted = TRUE;
}
void match_atomnames_with_rtp(t_restp restp[],t_hackblock hb[],
- t_atoms *pdba,
+ t_atoms *pdba,rvec *x,
bool bVerbose)
{
int i,j,k;
if (j == rptr->natom)
{
/* Not found yet, check if we have to rename this atom */
- if (match_atomnames_with_rtp_atom(pdba,i,
+ if (match_atomnames_with_rtp_atom(pdba,x,i,
rptr,&(hb[pdba->atom[i].resind]),
bVerbose))
{
int nterpairs,t_hackblock **ntdb, t_hackblock **ctdb,
int *rn, int *rc, bool bAllowMissing,
bool bVsites, bool bVsiteAromatics,
- const char *ff, const char *ffdir, real mHmult,
+ const char *ff, const char *ffdir, bool bAddCWD,
+ real mHmult,
int nssbonds, t_ssbond *ssbonds,
real long_bond_dist, real short_bond_dist,
bool bDeuterate, bool bChargeGroups, bool bCmap,
/* determine which atoms will be vsites and add dummy masses
also renumber atom numbers in plist[0..F_NRE]! */
do_vsites(nrtp, rtp, atype, atoms, tab, x, plist,
- &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir);
+ &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir, bAddCWD);
}
/* Make Angles and Dihedrals */
* If ffsel==NULL: interactive selection.
*/
+extern void choose_watermodel(const char *wmsel,const char *ffdir,
+ char **watermodel);
+/* Choose, possibly interactively, which water model to include,
+ * based on the wmsel command line option choice and watermodels.dat
+ * in ffdir.
+ */
+
extern void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp,
int nrtp, t_restp rtp[],
int nres, t_resinfo *resinfo,
*/
extern void match_atomnames_with_rtp(t_restp restp[],t_hackblock hb[],
- t_atoms *pdba,
+ t_atoms *pdba,rvec *x,
bool bVerbose);
/* Check if atom in pdba need to be deleted of renamed due to tdb or hdb.
* If renaming involves atoms added wrt to the rtp database,
int nterpairs, t_hackblock **ntdb, t_hackblock **ctdb,
int *rn, int *rc, bool bAllowMissing,
bool bVsites, bool bVsiteAromatics,
- const char *ff, const char *ffdir, real mHmult,
+ const char *ff, const char *ffdir, bool bAddCWD,
+ real mHmult,
int nssbonds, t_ssbond ssbonds[],
real long_bond_dist, real short_bond_dist,
bool bDeuterate, bool bChargeGroups, bool bCmap,
enum { egrptpALL, egrptpALL_GENREST, egrptpPART, egrptpONE };
+/* Minimum number of time steps required for accurate coupling integration
+ * of first and second order thermo- and barostats:
+ */
+int nstcmin1 = 10;
+int nstcmin2 = 20;
+
+
void init_ir(t_inputrec *ir, t_gromppopts *opts)
{
snew(opts->include,STRLEN);
warninp_t wi)
/* Check internal consistency */
{
- /* Strange macro: first one fills the err_buf, and then one can check
- * the condition, which will print the message and increase the error
- * counter.
- */
+ /* Strange macro: first one fills the err_buf, and then one can check
+ * the condition, which will print the message and increase the error
+ * counter.
+ */
#define CHECK(b) _low_check(b,err_buf,wi)
char err_buf[256],warn_buf[STRLEN];
- int ns_type=0;
- real dt_coupl=0;
+ int ns_type=0;
+ real dt_coupl=0;
+ int nstcmin;
set_warning_line(wi,mdparin,-1);
warning_error(wi,"Can not have nstlist<=0 with twin-range interactions");
}
- /* GENERAL INTEGRATOR STUFF */
- if (!(ir->eI == eiMD || EI_VV(ir->eI))) {
- ir->etc = etcNO;
- }
- if (!EI_DYNAMICS(ir->eI)) {
- ir->epc = epcNO;
- }
- if (EI_DYNAMICS(ir->eI)) {
- if (ir->nstcalcenergy < 0) {
- gmx_fatal(FARGS,"Can not have nstcalcenergy < 0");
- }
- if ((ir->etc != etcNO || ir->epc != epcNO) && ir->nstcalcenergy == 0) {
- gmx_fatal(FARGS,"Can not have nstcalcenergy=0 with global T/P-coupling");
+ /* GENERAL INTEGRATOR STUFF */
+ if (!(ir->eI == eiMD || EI_VV(ir->eI)))
+ {
+ ir->etc = etcNO;
}
- if (IR_TWINRANGE(*ir)) {
- check_nst("nstlist",ir->nstlist,"nstcalcenergy",&ir->nstcalcenergy,wi);
+ if (!EI_DYNAMICS(ir->eI))
+ {
+ ir->epc = epcNO;
}
- dt_coupl = ir->nstcalcenergy*ir->delta_t;
+ if (EI_DYNAMICS(ir->eI))
+ {
+ if (ir->nstcalcenergy < 0)
+ {
+ if (EI_VV(ir->eI))
+ {
+ /* VV coupling algorithms currently only support 1 */
+ ir->nstcalcenergy = 1;
+ }
+ else
+ {
+ if (ir->nstlist > 0)
+ {
+ ir->nstcalcenergy = ir->nstlist;
+ }
+ else
+ {
+ ir->nstcalcenergy = 10;
+ }
+ }
+ }
+ if (ir->etc != etcNO || ir->epc != epcNO)
+ {
+ if (ir->nstcalcenergy == 0)
+ {
+ gmx_fatal(FARGS,"Can not have nstcalcenergy=0 with global T/P-coupling");
+ }
+ if (EI_VV(ir->eI))
+ {
+ sprintf(err_buf,"T- and P-coupling with VV integrators currently only supports nstcalcenergy=1");
+ CHECK(ir->nstcalcenergy > 1);
+ }
+ }
+ if (IR_TWINRANGE(*ir))
+ {
+ check_nst("nstlist",ir->nstlist,
+ "nstcalcenergy",&ir->nstcalcenergy,wi);
+ }
+ dt_coupl = ir->nstcalcenergy*ir->delta_t;
- if (ir->nstcalcenergy > 1) {
- /* Energy and log file writing trigger energy calculation,
- * so we need some checks.
- */
- check_nst("nstcalcenergy",ir->nstcalcenergy,"nstenergy",&ir->nstenergy,wi);
- check_nst("nstcalcenergy",ir->nstcalcenergy,"nstlog",&ir->nstlog,wi);
- if (ir->efep != efepNO) {
- check_nst("nstcalcenergy",ir->nstcalcenergy,"nstdhdl",&ir->nstdhdl,wi);
- }
+ if (ir->nstcalcenergy > 1)
+ {
+ /* for storing exact averages nstenergy should be
+ * a multiple of nstcalcenergy
+ */
+ check_nst("nstcalcenergy",ir->nstcalcenergy,
+ "nstenergy",&ir->nstenergy,wi);
+ if (ir->efep != efepNO)
+ {
+ /* nstdhdl should be a multiple of nstcalcenergy */
+ check_nst("nstcalcenergy",ir->nstcalcenergy,
+ "nstdhdl",&ir->nstdhdl,wi);
+ }
+ }
}
- }
/* LD STUFF */
if ((EI_SD(ir->eI) || ir->eI == eiBD) &&
CHECK(((ir->rcoulomb > ir->rlist) || (ir->rvdw > ir->rlist))
&& (ir->ns_type == ensSIMPLE));
- /* TEMPERATURE COUPLING */
- if(ir->etc == etcYES) {
- ir->etc = etcBERENDSEN;
- warning_note(wi,"Old option for temperature coupling given: "
- "changing \"yes\" to \"Berendsen\"\n");
- }
- if (ir->etc == etcNOSEHOOVER) {
- if (ir->opts.nhchainlength < 1)
- {
- sprintf(warn_buf,"number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to 1\n",ir->opts.nhchainlength);
- ir->opts.nhchainlength =1;
- warning(wi,warn_buf);
- }
-
- if (ir->etc==etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1) {
- warning_note(wi,"leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
- ir->opts.nhchainlength = 1;
+ /* TEMPERATURE COUPLING */
+ if (ir->etc == etcYES)
+ {
+ ir->etc = etcBERENDSEN;
+ warning_note(wi,"Old option for temperature coupling given: "
+ "changing \"yes\" to \"Berendsen\"\n");
}
- } else {
- ir->opts.nhchainlength = 0;
- }
-
- if (ir->etc == etcBERENDSEN) {
- sprintf(warn_buf,"The %s thermostat does not generate the correct kinetic energy distribution. You might want to consider using the %s thermostat.",
- ETCOUPLTYPE(ir->etc),ETCOUPLTYPE(etcVRESCALE));
- warning_note(wi,warn_buf);
- }
- if((ir->etc==etcNOSEHOOVER || ir->etc==etcANDERSEN || ir->etc==etcANDERSENINTERVAL )
- && ir->epc==epcBERENDSEN) {
- sprintf(warn_buf,"Using Berendsen pressure coupling invalidates the "
- "true ensemble for the thermostat");
- warning(wi,warn_buf);
- }
+ if (ir->etc == etcNOSEHOOVER)
+ {
+ if (ir->opts.nhchainlength < 1)
+ {
+ sprintf(warn_buf,"number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to 1\n",ir->opts.nhchainlength);
+ ir->opts.nhchainlength =1;
+ warning(wi,warn_buf);
+ }
+
+ if (ir->etc==etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1)
+ {
+ warning_note(wi,"leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
+ ir->opts.nhchainlength = 1;
+ }
+ }
+ else
+ {
+ ir->opts.nhchainlength = 0;
+ }
- /* PRESSURE COUPLING */
- if (ir->epc == epcISOTROPIC) {
- ir->epc = epcBERENDSEN;
- warning_note(wi,"Old option for pressure coupling given: "
- "changing \"Isotropic\" to \"Berendsen\"\n");
- }
+ if (ir->etc == etcBERENDSEN)
+ {
+ sprintf(warn_buf,"The %s thermostat does not generate the correct kinetic energy distribution. You might want to consider using the %s thermostat.",
+ ETCOUPLTYPE(ir->etc),ETCOUPLTYPE(etcVRESCALE));
+ warning_note(wi,warn_buf);
+ }
- if (ir->epc != epcNO) {
- sprintf(err_buf,"tau_p must be > 0 instead of %g\n",ir->tau_p);
- CHECK(ir->tau_p <= 0);
+ if ((ir->etc==etcNOSEHOOVER || ir->etc==etcANDERSEN || ir->etc==etcANDERSENINTERVAL)
+ && ir->epc==epcBERENDSEN)
+ {
+ sprintf(warn_buf,"Using Berendsen pressure coupling invalidates the "
+ "true ensemble for the thermostat");
+ warning(wi,warn_buf);
+ }
- if (ir->tau_p < 100*dt_coupl) {
- sprintf(warn_buf,"For proper barostat integration tau_p (%g) should be more than two orders of magnitude larger than nstcalcenergy*dt (%g)",
- ir->tau_p,dt_coupl);
- warning(wi,warn_buf);
- }
-
- sprintf(err_buf,"compressibility must be > 0 when using pressure"
- " coupling %s\n",EPCOUPLTYPE(ir->epc));
- CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 ||
- ir->compress[ZZ][ZZ] < 0 ||
- (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
- ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
-
- sprintf(err_buf,"pressure coupling with PPPM not implemented, use PME");
- CHECK(ir->coulombtype == eelPPPM);
-
- } else if (ir->coulombtype == eelPPPM) {
- sprintf(warn_buf,"The pressure with PPPM is incorrect, if you need the pressure use PME");
- warning(wi,warn_buf);
- }
+ /* PRESSURE COUPLING */
+ if (ir->epc == epcISOTROPIC)
+ {
+ ir->epc = epcBERENDSEN;
+ warning_note(wi,"Old option for pressure coupling given: "
+ "changing \"Isotropic\" to \"Berendsen\"\n");
+ }
- if (EI_VV(ir->eI)) {
- if (ir->epc > epcNO) {
- if (ir->epc!=epcMTTK) {
- warning_error(wi,"NPT only defined for vv using Martyna-Tuckerman-Tobias-Klein equations");
- }
+ if (ir->epc != epcNO)
+ {
+ sprintf(err_buf,"tau_p must be > 0 instead of %g\n",ir->tau_p);
+ CHECK(ir->tau_p <= 0);
+
+ nstcmin = (ir->epc == epcBERENDSEN ? nstcmin1 : nstcmin2);
+ if (ir->tau_p < nstcmin*dt_coupl)
+ {
+ sprintf(warn_buf,"For proper integration of the %s barostat, tau_p (%g) should be at least %d times larger than nstcalcenergy*dt (%g)",
+ EPCOUPLTYPE(ir->epc),ir->tau_p,nstcmin,dt_coupl);
+ warning(wi,warn_buf);
+ }
+
+ sprintf(err_buf,"compressibility must be > 0 when using pressure"
+ " coupling %s\n",EPCOUPLTYPE(ir->epc));
+ CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 ||
+ ir->compress[ZZ][ZZ] < 0 ||
+ (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
+ ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
+
+ sprintf(err_buf,"pressure coupling with PPPM not implemented, use PME");
+ CHECK(ir->coulombtype == eelPPPM);
+
+ }
+ else if (ir->coulombtype == eelPPPM)
+ {
+ sprintf(warn_buf,"The pressure with PPPM is incorrect, if you need the pressure use PME");
+ warning(wi,warn_buf);
+ }
+
+ if (EI_VV(ir->eI))
+ {
+ if (ir->epc > epcNO)
+ {
+ if (ir->epc!=epcMTTK)
+ {
+ warning_error(wi,"NPT only defined for vv using Martyna-Tuckerman-Tobias-Klein equations");
+ }
+ }
}
- }
/* ELECTROSTATICS */
/* More checks are in triple check (grompp.c) */
+ if (ir->coulombtype == eelPPPM)
+ {
+ warning_error(wi,"PPPM is not functional in the current version, we plan to implement PPPM through a small modification of the PME code");
+ }
+
if (ir->coulombtype == eelSWITCH) {
sprintf(warn_buf,"coulombtype = %s is only for testing purposes and can lead to serious artifacts, advice: use coulombtype = %s",
eel_names[ir->coulombtype],
warning_note(wi,warn_buf);
}
}
-
+
+ /* IMPLICIT SOLVENT */
if(ir->coulombtype==eelGB_NOTUSED)
{
ir->coulombtype=eelCUT;
{
sprintf(err_buf,"With GBSA implicit solvent, rgbradii must be equal to rlist.");
CHECK(ir->rgbradii != ir->rlist);
+
+ if(ir->coulombtype!=eelCUT)
+ {
+ sprintf(err_buf,"With GBSA, coulombtype must be equal to %s\n",eel_names[eelCUT]);
+ CHECK(ir->coulombtype!=eelCUT);
+ }
+ if(ir->vdwtype!=evdwCUT)
+ {
+ sprintf(err_buf,"With GBSA, vdw-type must be equal to %s\n",evdw_names[evdwCUT]);
+ CHECK(ir->vdwtype!=evdwCUT);
+ }
+
+ if(ir->nstgbradii<1)
+ {
+ sprintf(warn_buf,"Using GBSA with nstgbradii<1, setting nstgbradii=1");
+ warning_note(wi,warn_buf);
+ ir->nstgbradii=1;
+ }
}
}
ITYPE ("simulation_part", ir->simulation_part, 1);
CTYPE ("mode for center of mass motion removal");
CTYPE ("energy calculation and T/P-coupling frequency");
- ITYPE ("nstcalcenergy",ir->nstcalcenergy, 1);
+ ITYPE ("nstcalcenergy",ir->nstcalcenergy, -1);
EETYPE("comm-mode", ir->comm_mode, ecm_names);
CTYPE ("number of steps for center of mass motion removal");
- ITYPE ("nstcomm", ir->nstcomm, 1);
+ ITYPE ("nstcomm", ir->nstcomm, 10);
CTYPE ("group(s) for center of mass motion removal");
STYPE ("comm-grps", vcm, NULL);
t_atoms atoms_all;
char warnbuf[STRLEN],**gnames;
int nr,ntcg,ntau_t,nref_t,nacc,nofg,nSA,nSA_points,nSA_time,nSA_temp;
+ int nstcmin;
int nacg,nfreeze,nfrdim,nenergy,nvcm,nuser;
char *ptr1[MAXPTR],*ptr2[MAXPTR],*ptr3[MAXPTR];
int i,j,k,restnm;
if (ir->eI==eiBD && ir->bd_fric==0) {
fprintf(stderr,"bd_fric=0, so tau_t will be used as the inverse friction constant(s)\n");
}
- if (bSetTCpar) {
- if (nr != nref_t)
- gmx_fatal(FARGS,"Not enough ref_t and tau_t values!");
- for(i=0; (i<nr); i++) {
- ir->opts.tau_t[i]=strtod(ptr1[i],NULL);
- if (ir->opts.tau_t[i] < 0) {
- gmx_fatal(FARGS,"tau_t for group %d negative",i);
- }
- /* We check the relative magnitude of the coupling time tau_t.
- * V-rescale works correctly, even for tau_t=0.
- */
- if ((ir->etc == etcBERENDSEN || ir->etc == etcNOSEHOOVER) &&
- ir->opts.tau_t[i] != 0 &&
- ir->opts.tau_t[i] < 10*ir->nstcalcenergy*ir->delta_t) {
- sprintf(warn_buf,"For proper thermostat integration tau_t (%g) should be more than an order of magnitude larger than nstcalcenergy*dt (%g)",
- ir->opts.tau_t[i],ir->nstcalcenergy*ir->delta_t);
- warning(wi,warn_buf);
- }
- }
- for(i=0; (i<nr); i++) {
- ir->opts.ref_t[i]=strtod(ptr2[i],NULL);
- if (ir->opts.ref_t[i] < 0)
- gmx_fatal(FARGS,"ref_t for group %d negative",i);
- }
- }
+ if (bSetTCpar)
+ {
+ if (nr != nref_t)
+ {
+ gmx_fatal(FARGS,"Not enough ref_t and tau_t values!");
+ }
+ nstcmin = (ir->etc == etcBERENDSEN ? nstcmin1 : nstcmin2);
+
+ for(i=0; (i<nr); i++)
+ {
+ ir->opts.tau_t[i] = strtod(ptr1[i],NULL);
+ if (ir->opts.tau_t[i] < 0)
+ {
+ gmx_fatal(FARGS,"tau_t for group %d negative",i);
+ }
+ /* We check the relative magnitude of the coupling time tau_t.
+ * V-rescale works correctly, even for tau_t=0.
+ */
+ if ((ir->etc == etcBERENDSEN || ir->etc == etcNOSEHOOVER) &&
+ ir->opts.tau_t[i] != 0 &&
+ ir->opts.tau_t[i] < nstcmin*ir->nstcalcenergy*ir->delta_t)
+ {
+ sprintf(warn_buf,"For proper integration of the %s thermostat, tau_t (%g) should be at least %d times larger than nstcalcenergy*dt (%g)",
+ ETCOUPLTYPE(ir->etc),
+ ir->opts.tau_t[i],nstcmin,
+ ir->nstcalcenergy*ir->delta_t);
+ warning(wi,warn_buf);
+ }
+ }
+ for(i=0; (i<nr); i++)
+ {
+ ir->opts.ref_t[i] = strtod(ptr2[i],NULL);
+ if (ir->opts.ref_t[i] < 0)
+ {
+ gmx_fatal(FARGS,"ref_t for group %d negative",i);
+ }
+ }
+ }
+
/* Simulated annealing for each group. There are nr groups */
nSA = str_nelem(anneal,MAXPTR,ptr1);
if (nSA == 1 && (ptr1[0][0]=='n' || ptr1[0][0]=='N'))
t_pull *pull,bool *bStart,
warninp_t wi)
{
- int ninp,nerror,i,nchar,ndim,nscan,m;
+ int ninp,nerror=0,i,nchar,ndim,nscan,m;
t_inpfile *inp;
const char *tmp;
char **grpbuf;
static void exchange_state(const gmx_multisim_t *ms,int b,t_state *state)
{
-
/* When t_state changes, this code should be updated. */
int ngtc,nnhpres;
ngtc = state->ngtc * state->nhchainlength;
exchange_rvecs(ms,b,state->sd_X,state->natoms);
}
+static void copy_rvecs(rvec *s,rvec *d,int n)
+{
+ int i;
+
+ for(i=0; i<n; i++)
+ {
+ copy_rvec(s[i],d[i]);
+ }
+}
+
+static void copy_doubles(double *s,double *d,int n)
+{
+ int i;
+
+ for(i=0; i<n; i++)
+ {
+ d[i] = s[i];
+ }
+}
+
+#define scopy_rvecs(v,n) copy_rvecs(state->v,state_local->v,n)
+#define scopy_doubles(v,n) copy_doubles(state->v,state_local->v,n)
+
+static void copy_state_nonatomdata(t_state *state,t_state *state_local)
+{
+ /* When t_state changes, this code should be updated. */
+ int ngtc,nnhpres;
+ ngtc = state->ngtc * state->nhchainlength;
+ nnhpres = state->nnhpres* state->nhchainlength;
+ scopy_rvecs(box,DIM);
+ scopy_rvecs(box_rel,DIM);
+ scopy_rvecs(boxv,DIM);
+ state_local->veta = state->veta;
+ state_local->vol0 = state->vol0;
+ scopy_rvecs(svir_prev,DIM);
+ scopy_rvecs(fvir_prev,DIM);
+ scopy_rvecs(pres_prev,DIM);
+ scopy_doubles(nosehoover_xi,ngtc);
+ scopy_doubles(nosehoover_vxi,ngtc);
+ scopy_doubles(nhpres_xi,nnhpres);
+ scopy_doubles(nhpres_vxi,nnhpres);
+ scopy_doubles(therm_integral,state->ngtc);
+ scopy_rvecs(x,state->natoms);
+ scopy_rvecs(v,state->natoms);
+ scopy_rvecs(sd_X,state->natoms);
+}
+
static void scale_velocities(t_state *state,real fac)
{
int i;
}
bool replica_exchange(FILE *fplog,const t_commrec *cr,struct gmx_repl_ex *re,
- t_state *state,real *ener,
- t_state *state_local,
- int step,real time)
+ t_state *state,real *ener,
+ t_state *state_local,
+ int step,real time)
{
- gmx_multisim_t *ms;
- int exchange=-1,shift;
- bool bExchanged=FALSE;
-
- ms = cr->ms;
-
- if (MASTER(cr)) {
- exchange = get_replica_exchange(fplog,ms,re,ener,det(state->box),
- step,time);
- bExchanged = (exchange >= 0);
- }
-
- if (PAR(cr)) {
+ gmx_multisim_t *ms;
+ int exchange=-1,shift;
+ bool bExchanged=FALSE;
+
+ ms = cr->ms;
+
+ if (MASTER(cr))
+ {
+ exchange = get_replica_exchange(fplog,ms,re,ener,det(state->box),
+ step,time);
+ bExchanged = (exchange >= 0);
+ }
+
+ if (PAR(cr))
+ {
#ifdef GMX_MPI
- MPI_Bcast(&bExchanged,sizeof(bool),MPI_BYTE,MASTERRANK(cr),
- cr->mpi_comm_mygroup);
+ MPI_Bcast(&bExchanged,sizeof(bool),MPI_BYTE,MASTERRANK(cr),
+ cr->mpi_comm_mygroup);
#endif
- }
-
- if (bExchanged) {
- if (PAR(cr)) {
- if (DOMAINDECOMP(cr))
- dd_collect_state(cr->dd,state_local,state);
- else
- pd_collect_state(cr,state);
}
- if (MASTER(cr)) {
- if (debug)
- fprintf(debug,"Exchanging %d with %d\n",ms->sim,exchange);
- exchange_state(ms,exchange,state);
- if (re->type == ereTEMP)
- scale_velocities(state,sqrt(re->q[ms->sim]/re->q[exchange]));
+
+ if (bExchanged)
+ {
+ /* Exchange the states */
+
+ if (PAR(cr))
+ {
+ /* Collect the global state on the master node */
+ if (DOMAINDECOMP(cr))
+ {
+ dd_collect_state(cr->dd,state_local,state);
+ }
+ else
+ {
+ pd_collect_state(cr,state);
+ }
+ }
+
+ if (MASTER(cr))
+ {
+ /* Exchange the global states between the master nodes */
+ if (debug)
+ {
+ fprintf(debug,"Exchanging %d with %d\n",ms->sim,exchange);
+ }
+ exchange_state(ms,exchange,state);
+
+ if (re->type == ereTEMP)
+ {
+ scale_velocities(state,sqrt(re->q[ms->sim]/re->q[exchange]));
+ }
+ }
+
+ /* With domain decomposition the global state is distributed later */
+ if (!DOMAINDECOMP(cr))
+ {
+ /* Copy the global state to the local state data structure */
+ copy_state_nonatomdata(state,state_local);
+
+ if (PAR(cr))
+ {
+ bcast_state(cr,state,FALSE);
+ }
+ }
}
- }
-
- return bExchanged;
+
+ return bExchanged;
}
void print_replica_exchange_statistics(FILE *fplog,struct gmx_repl_ex *re)
/* Attempts replica exchange, should be called on all nodes.
* Returns TRUE if this state has been exchanged.
* When running each replica in parallel,
- * this routine collects the state on the master node before exchange,
- * but it does not redistribute the state over the nodes after exchange.
+ * this routine collects the state on the master node before exchange.
+ * With particle the state is redistributed over the nodes after exchange.
+ * With domain decomposition the global state after exchanged in stored
+ * in state and still needs to be redistributed over the nodes.
*/
extern void print_replica_exchange_statistics(FILE *fplog,gmx_repl_ex_t re);
#include "pgutil.h"
#include "fflibutil.h"
-gpp_atomtype_t read_atype(const char *ffdir,t_symtab *tab)
+gpp_atomtype_t read_atype(const char *ffdir,bool bAddCWD,t_symtab *tab)
{
int nfile,f;
char **file;
t_atom *a;
t_param *nb;
- nfile = fflib_search_file_end(ffdir,".atp",TRUE,&file);
+ nfile = fflib_search_file_end(ffdir,bAddCWD,".atp",TRUE,&file);
at = init_atomtype();
snew(a,1);
snew(nb,1);
***********************************************************/
int neq_str(const char *a1,const char *a2)
{
- int j,l;
+ int j,l,l1,l2;;
- l=min((int)strlen(a1),(int)strlen(a2));
- j=0;
- while ( (j<l) && (toupper(a1[j]) == toupper(a2[j])) )
- j++;
-
- return j;
+ l1 = (int)strlen(a1);
+ l2 = (int)strlen(a2);
+ l = min(l1,l2);
+
+ j=0;
+ while (j < l && toupper(a1[j]) == toupper(a2[j]))
+ {
+ j++;
+ }
+ if (j == l1 && j == l2)
+ {
+ /* Exact match */
+ return 1000;
+ }
+ else
+ {
+ /* Partial match */
+ return j;
+ }
}
t_restp *search_rtp(const char *key,int nrtp,t_restp rtp[])
#include "mvdata.h"
#include "checkpoint.h"
#include "mtop_util.h"
-#include "pull_rotation.h"
#include "sighandler.h"
+#include "tpxio.h"
+#include "txtdump.h"
+#include "pull_rotation.h"
#include "md_openmm.h"
#ifdef GMX_LIB_MPI
};
+/* The function used for spawning threads. Extracts the mdrunner()
+ arguments from its one argument and calls mdrunner(), after making
+ a commrec. */
static void mdrunner_start_fn(void *arg)
{
struct mdrunner_arglist *mda=(struct mdrunner_arglist*)arg;
but those are all const. */
t_commrec *cr; /* we need a local version of this */
FILE *fplog=NULL;
- t_filenm *fnm=dup_tfn(mc.nfile, mc.fnm);
+ t_filenm *fnm;
+
+ fnm = dup_tfn(mc.nfile, mc.fnm);
+
+ cr = init_par_threads(mc.cr);
- cr=init_par_threads(mc.cr);
if (MASTER(cr))
{
fplog=mc.fplog;
}
-
- mda->ret=mdrunner(fplog, cr, mc.nfile, mc.fnm, mc.oenv, mc.bVerbose,
- mc.bCompact, mc.nstglobalcomm,
+ mda->ret=mdrunner(cr->nthreads, fplog, cr, mc.nfile, fnm, mc.oenv,
+ mc.bVerbose, mc.bCompact, mc.nstglobalcomm,
mc.ddxyz, mc.dd_node_order, mc.rdd,
mc.rconstr, mc.dddlb_opt, mc.dlb_scale,
- mc.ddcsx, mc.ddcsy, mc.ddcsz, mc.nstepout, mc.resetstep, mc.nmultisim,
- mc.repl_ex_nst, mc.repl_ex_seed, mc.pforce,
+ mc.ddcsx, mc.ddcsy, mc.ddcsz, mc.nstepout, mc.resetstep,
+ mc.nmultisim, mc.repl_ex_nst, mc.repl_ex_seed, mc.pforce,
mc.cpt_period, mc.max_hours, mc.deviceOptions, mc.Flags);
}
-#endif
-
-int mdrunner_threads(int nthreads,
- FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
- const output_env_t oenv, bool bVerbose,bool bCompact,
- int nstglobalcomm,
- ivec ddxyz,int dd_node_order,real rdd,real rconstr,
- const char *dddlb_opt,real dlb_scale,
- const char *ddcsx,const char *ddcsy,const char *ddcsz,
- int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
- int repl_ex_seed, real pforce,real cpt_period,
- real max_hours, const char *deviceOptions, unsigned long Flags)
+/* called by mdrunner() to start a specific number of threads (including
+ the main thread) for thread-parallel runs. This in turn calls mdrunner()
+ for each thread.
+ All options besides nthreads are the same as for mdrunner(). */
+static t_commrec *mdrunner_start_threads(int nthreads,
+ FILE *fplog,t_commrec *cr,int nfile,
+ const t_filenm fnm[], const output_env_t oenv, bool bVerbose,
+ bool bCompact, int nstglobalcomm,
+ ivec ddxyz,int dd_node_order,real rdd,real rconstr,
+ const char *dddlb_opt,real dlb_scale,
+ const char *ddcsx,const char *ddcsy,const char *ddcsz,
+ int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
+ int repl_ex_seed, real pforce,real cpt_period, real max_hours,
+ const char *deviceOptions, unsigned long Flags)
{
int ret;
+ struct mdrunner_arglist *mda;
+ t_commrec *crn; /* the new commrec */
+ t_filenm *fnmn;
+
/* first check whether we even need to start tMPI */
- if (nthreads < 2)
+ if (nthreads<2)
+ return cr;
+
+ /* a few small, one-time, almost unavoidable memory leaks: */
+ snew(mda,1);
+ fnmn=dup_tfn(nfile, fnm);
+
+ /* fill the data structure to pass as void pointer to thread start fn */
+ mda->fplog=fplog;
+ mda->cr=cr;
+ mda->nfile=nfile;
+ mda->fnm=fnmn;
+ mda->oenv=oenv;
+ mda->bVerbose=bVerbose;
+ mda->bCompact=bCompact;
+ mda->nstglobalcomm=nstglobalcomm;
+ mda->ddxyz[XX]=ddxyz[XX];
+ mda->ddxyz[YY]=ddxyz[YY];
+ mda->ddxyz[ZZ]=ddxyz[ZZ];
+ mda->dd_node_order=dd_node_order;
+ mda->rdd=rdd;
+ mda->rconstr=rconstr;
+ mda->dddlb_opt=dddlb_opt;
+ mda->dlb_scale=dlb_scale;
+ mda->ddcsx=ddcsx;
+ mda->ddcsy=ddcsy;
+ mda->ddcsz=ddcsz;
+ mda->nstepout=nstepout;
+ mda->resetstep=resetstep;
+ mda->nmultisim=nmultisim;
+ mda->repl_ex_nst=repl_ex_nst;
+ mda->repl_ex_seed=repl_ex_seed;
+ mda->pforce=pforce;
+ mda->cpt_period=cpt_period;
+ mda->max_hours=max_hours;
+ mda->deviceOptions=deviceOptions;
+ mda->Flags=Flags;
+
+ fprintf(stderr, "Starting %d threads\n",nthreads);
+ fflush(stderr);
+ /* now spawn new threads that start mdrunner_start_fn(), while
+ the main thread returns */
+ ret=tMPI_Init_fn(TRUE, nthreads, mdrunner_start_fn, (void*)(mda) );
+ if (ret!=TMPI_SUCCESS)
+ return NULL;
+
+ /* make a new comm_rec to reflect the new situation */
+ crn=init_par_threads(cr);
+ return crn;
+}
+
+
+/* get the number of threads based on how many there were requested,
+ which algorithms we're using, and how many particles there are. */
+static int get_nthreads(int nthreads_requested, t_inputrec *inputrec,
+ gmx_mtop_t *mtop)
+{
+ int nthreads,nthreads_new;
+
+ nthreads = nthreads_requested;
+
+ /* determine # of hardware threads. */
+ if (nthreads_requested < 1)
{
- ret=mdrunner(fplog, cr, nfile, fnm, oenv, bVerbose, bCompact,
- nstglobalcomm,
- ddxyz, dd_node_order, rdd, rconstr, dddlb_opt, dlb_scale,
- ddcsx, ddcsy, ddcsz, nstepout, resetstep, nmultisim, repl_ex_nst,
- repl_ex_seed, pforce, cpt_period, max_hours, deviceOptions, Flags);
+ nthreads = tMPI_Get_recommended_nthreads();
}
- else
+ /* Check if an algorithm does not support parallel simulation. */
+ if (nthreads != 1 &&
+ ( inputrec->eI == eiLBFGS ||
+ inputrec->eI == eiNM ||
+ inputrec->coulombtype == eelEWALD) )
+ {
+ fprintf(stderr,"\nThe integration or electrostatics algorithm doesn't support parallel runs. Not starting any threads.\n");
+ nthreads = 1;
+ }
+ else if ((nthreads_requested < 1) &&
+ (mtop->natoms/nthreads < MIN_ATOMS_PER_THREAD) )
{
-#ifdef GMX_THREADS
- struct mdrunner_arglist mda;
- /* fill the data structure to pass as void pointer to thread start fn */
- mda.fplog=fplog;
- mda.cr=cr;
- mda.nfile=nfile;
- mda.fnm=fnm;
- mda.oenv=oenv;
- mda.bVerbose=bVerbose;
- mda.bCompact=bCompact;
- mda.nstglobalcomm=nstglobalcomm;
- mda.ddxyz[XX]=ddxyz[XX];
- mda.ddxyz[YY]=ddxyz[YY];
- mda.ddxyz[ZZ]=ddxyz[ZZ];
- mda.dd_node_order=dd_node_order;
- mda.rdd=rdd;
- mda.rconstr=rconstr;
- mda.dddlb_opt=dddlb_opt;
- mda.dlb_scale=dlb_scale;
- mda.ddcsx=ddcsx;
- mda.ddcsy=ddcsy;
- mda.ddcsz=ddcsz;
- mda.nstepout=nstepout;
- mda.resetstep=resetstep;
- mda.nmultisim=nmultisim;
- mda.repl_ex_nst=repl_ex_nst;
- mda.repl_ex_seed=repl_ex_seed;
- mda.pforce=pforce;
- mda.cpt_period=cpt_period;
- mda.max_hours=max_hours;
- mda.deviceOptions=deviceOptions;
- mda.Flags=Flags;
-
- fprintf(stderr, "Starting %d threads\n",nthreads);
- fflush(stderr);
- tMPI_Init_fn(nthreads, mdrunner_start_fn, (void*)(&mda) );
- ret=mda.ret;
-#else
- ret=-1;
- gmx_comm("Multiple threads requested but not compiled with threads");
-#endif
+ /* the thread number was chosen automatically, but there are too many
+ threads (too few atoms per thread) */
+ nthreads_new = max(1,mtop->natoms/MIN_ATOMS_PER_THREAD);
+
+ if (nthreads_new > 8 || (nthreads == 8 && nthreads_new > 4))
+ {
+ /* Use only multiples of 4 above 8 threads
+ * or with an 8-core processor
+ * (to avoid 6 threads on 8 core processors with 4 real cores).
+ */
+ nthreads_new = (nthreads_new/4)*4;
+ }
+ else if (nthreads_new > 4)
+ {
+ /* Avoid 5 or 7 threads */
+ nthreads_new = (nthreads_new/2)*2;
+ }
+
+ nthreads = nthreads_new;
+
+ fprintf(stderr,"\n");
+ fprintf(stderr,"NOTE: Parallelization is limited by the small number of atoms,\n");
+ fprintf(stderr," only starting %d threads.\n",nthreads);
+ fprintf(stderr," You can use the -nt option to optimize the number of threads.\n\n");
}
- return ret;
+ return nthreads;
}
+#endif
-int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
- const output_env_t oenv, bool bVerbose,bool bCompact,
- int nstglobalcomm,
+int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
+ const t_filenm fnm[], const output_env_t oenv, bool bVerbose,
+ bool bCompact, int nstglobalcomm,
ivec ddxyz,int dd_node_order,real rdd,real rconstr,
const char *dddlb_opt,real dlb_scale,
const char *ddcsx,const char *ddcsy,const char *ddcsz,
- int nstepout,int resetstep,int nmultisim,int repl_ex_nst,int repl_ex_seed,
- real pforce,real cpt_period,real max_hours,
- const char *deviceOptions,
- unsigned long Flags)
+ int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
+ int repl_ex_seed, real pforce,real cpt_period,real max_hours,
+ const char *deviceOptions, unsigned long Flags)
{
double nodetime=0,realtime;
t_inputrec *inputrec;
t_state *state=NULL;
matrix box;
- gmx_ddbox_t ddbox;
- int npme_major;
+ gmx_ddbox_t ddbox={0};
+ int npme_major,npme_minor;
real tmpr1,tmpr2;
t_nrnb *nrnb;
gmx_mtop_t *mtop=NULL;
gmx_runtime_t runtime;
int rc;
gmx_large_int_t reset_counters;
- gmx_edsam_t ed;
-
- /* A parallel command line option consistency check */
- if (!PAR(cr) &&
- (ddxyz[XX] > 1 || ddxyz[YY] > 1 || ddxyz[ZZ] > 1 || cr->npmenodes > 0))
- {
- gmx_fatal(FARGS,
- "The -dd or -npme option request a parallel simulation, "
-#ifndef GMX_MPI
- "but mdrun was compiled without threads or MPI enabled"
-#else
-#ifdef GMX_THREADS
- "but the number of threads (option -nt) is 1"
-#else
- "but mdrun was not started through mpirun/mpiexec or only one process was requested through mpirun/mpiexec"
-#endif
-#endif
- );
- }
-
- /* Essential dynamics */
- if (opt2bSet("-ei",nfile,fnm))
- {
- /* Open input and output files, allocate space for ED data structure */
- ed = ed_open(nfile,fnm,cr);
- }
- else
- ed=NULL;
+ gmx_edsam_t ed=NULL;
+ t_commrec *cr_old=cr;
+ int nthreads=1;
+ /* CAUTION: threads may be started later on in this function, so
+ cr doesn't reflect the final parallel state right now */
snew(inputrec,1);
snew(mtop,1);
fplog = NULL;
}
- if (PAR(cr))
+ snew(state,1);
+ if (MASTER(cr))
{
- /* The master thread on the master node reads from disk,
- * then distributes everything to the other processors.
- */
+ /* Read (nearly) all data required for the simulation */
+ read_tpx_state(ftp2fn(efTPX,nfile,fnm),inputrec,state,NULL,mtop);
- list = (SIMMASTER(cr) && !(Flags & MD_APPENDFILES)) ? (LIST_SCALARS | LIST_INPUTREC) : 0;
+ /* NOW the threads will be started: */
+#ifdef GMX_THREADS
+ nthreads = get_nthreads(nthreads_requested, inputrec, mtop);
- snew(state,1);
- /* NOTE: if the run is thread-parallel but the integrator doesn't support this
- such as with LBGFS, this function may cancel the threads
- through cancel_par_threads(), and make the commrec serial. The
- rest of the simulation is then only performed by the main thread,
- as if it were a serial run. */
- init_parallel(fplog, opt2fn_master("-s",nfile,fnm,cr),cr,
- inputrec,mtop,state,list);
+ if (nthreads > 1)
+ {
+ /* now start the threads. */
+ cr=mdrunner_start_threads(nthreads, fplog, cr_old, nfile, fnm,
+ oenv, bVerbose, bCompact, nstglobalcomm,
+ ddxyz, dd_node_order, rdd, rconstr,
+ dddlb_opt, dlb_scale, ddcsx, ddcsy, ddcsz,
+ nstepout, resetstep, nmultisim,
+ repl_ex_nst, repl_ex_seed, pforce,
+ cpt_period, max_hours, deviceOptions,
+ Flags);
+ /* the main thread continues here with a new cr. We don't deallocate
+ the old cr because other threads may still be reading it. */
+ if (cr == NULL)
+ {
+ gmx_comm("Failed to spawn threads");
+ }
+ }
+#endif
+ }
+ /* END OF CAUTION: cr is now reliable */
+ /* now make sure the state is initialized and propagated */
+ set_state_entries(state,inputrec,cr->nnodes);
+ if (PAR(cr))
+ {
+ /* now broadcast everything to the non-master nodes/threads: */
+ init_parallel(fplog, cr, inputrec, mtop, state);
}
- else
+
+ if (fplog)
+ {
+ pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE);
+ }
+
+ /* A parallel command line option consistency check that we can
+ only do after any threads have started. */
+ if (!PAR(cr) &&
+ (ddxyz[XX] > 1 || ddxyz[YY] > 1 || ddxyz[ZZ] > 1 || cr->npmenodes > 0))
+ {
+ gmx_fatal(FARGS,
+ "The -dd or -npme option request a parallel simulation, "
+#ifndef GMX_MPI
+ "but mdrun was compiled without threads or MPI enabled"
+#else
+#ifdef GMX_THREADS
+ "but the number of threads (option -nt) is 1"
+#else
+ "but mdrun was not started through mpirun/mpiexec or only one process was requested through mpirun/mpiexec"
+#endif
+#endif
+ );
+ }
+
+ if (can_use_allvsall(inputrec,mtop,TRUE,cr,fplog))
{
- /* Read a file for a single processor */
- snew(state,1);
- init_single(fplog,inputrec,ftp2fn(efTPX,nfile,fnm),mtop,state);
+ /* All-vs-all loops do not work with domain decomposition */
+ Flags |= MD_PARTDEC;
}
+
if (!EEL_PME(inputrec->coulombtype) || (Flags & MD_PARTDEC))
{
cr->npmenodes = 0;
gmx_bcast(sizeof(box),box,cr);
}
+ /* Essential dynamics */
+ if (opt2bSet("-ei",nfile,fnm))
+ {
+ /* Open input and output files, allocate space for ED data structure */
+ ed = ed_open(nfile,fnm,Flags,cr);
+ }
+
if (bVerbose && SIMMASTER(cr))
{
fprintf(stderr,"Loaded with Money\n\n");
ddcsx,ddcsy,ddcsz,
mtop,inputrec,
box,state->x,
- &ddbox,&npme_major);
+ &ddbox,&npme_major,&npme_minor);
make_dd_communicators(fplog,cr,dd_node_order);
}
else
{
+ /* PME, if used, is done on all nodes with 1D decomposition */
+ cr->npmenodes = 0;
cr->duty = (DUTY_PP | DUTY_PME);
npme_major = cr->nnodes;
+ npme_minor = 1;
if (inputrec->ePBC == epbcSCREW)
{
}
if (cr->duty & DUTY_PME)
{
- status = gmx_pme_init(pmedata,cr,npme_major,inputrec,
+ status = gmx_pme_init(pmedata,cr,npme_major,npme_minor,inputrec,
mtop ? mtop->natoms : 0,nChargePerturbed,
(Flags & MD_REPRODUCIBLE));
if (status != 0)
if (EI_DYNAMICS(inputrec->eI) || EI_TPI(inputrec->eI))
{
/* Some timing stats */
- if (MASTER(cr))
+ if (SIMMASTER(cr))
{
if (runtime.proc == 0)
{
gmx_log_close(fplog);
}
- if(bGotStopNextStepSignal)
- {
- rc = 1;
- }
- else if(bGotStopNextNSStepSignal)
- {
- rc = 2;
- }
- else
+ rc=(int)gmx_get_stop_condition();
+
+#ifdef GMX_THREADS
+ /* we need to join all threads. The sub-threads join when they
+ exit this function, but the master thread needs to be told to
+ wait for that. */
+ if (nthreads>1 && MASTERTHREAD(cr) )
{
- rc = 0;
+ tMPI_Finalize();
}
+#endif
return rc;
}
}
if (nlines > 0)
sfree(lines);
- fprintf(stderr,"%d out of %d lines of %s converted succesfully\n",
+ fprintf(stderr,"%d out of %d lines of %s converted successfully\n",
n,nlines,sbfile);
*nspecbond = n;
return FALSE;
}
-static void rename_1res(t_atoms *pdba,int resind,char *newres)
+static void rename_1res(t_atoms *pdba,int resind,char *newres,bool bVerbose)
{
- if(debug) fprintf(stderr,"Renaming %s-%d to %s\n",
- *pdba->resinfo[resind].name,
- pdba->resinfo[resind].nr,
- newres);
+ if (bVerbose) {
+ printf("Using rtp entry %s for %s %d\n",
+ newres,
+ *pdba->resinfo[resind].name,
+ pdba->resinfo[resind].nr);
+ }
/* this used to free *resname, which fucks up the symtab! */
- snew(pdba->resinfo[resind].name,1);
- *pdba->resinfo[resind].name = strdup(newres);
+ snew(pdba->resinfo[resind].rtp,1);
+ *pdba->resinfo[resind].rtp = strdup(newres);
}
int mk_specbonds(t_atoms *pdba,rvec x[],bool bInteractive,
- t_ssbond **specbonds)
+ t_ssbond **specbonds,bool bVerbose)
{
t_specbond *sb=NULL;
t_ssbond *bonds=NULL;
bonds[nbonds].a2 = strdup(*pdba->atomname[aj]);
/* rename residues */
if (bSwap) {
- rename_1res(pdba,specp[i],sb[index_sb].newres2);
- rename_1res(pdba,specp[j],sb[index_sb].newres1);
+ rename_1res(pdba,specp[i],sb[index_sb].newres2,bVerbose);
+ rename_1res(pdba,specp[j],sb[index_sb].newres1,bVerbose);
}
else {
- rename_1res(pdba,specp[i],sb[index_sb].newres1);
- rename_1res(pdba,specp[j],sb[index_sb].newres2);
+ rename_1res(pdba,specp[i],sb[index_sb].newres1,bVerbose);
+ rename_1res(pdba,specp[j],sb[index_sb].newres2,bVerbose);
}
nbonds++;
}
#include "pdb2top.h"
extern int mk_specbonds(t_atoms *pdba,rvec x[],bool bInteractive,
- t_ssbond **specbonds);
+ t_ssbond **specbonds,bool bVerbose);
extern bool yesno(void);
get_atomtype_name(a->type,atype),a->m,a->q);
}
-static void print_ter_db(char *ff,char C,int nb,t_hackblock tb[],
+static void print_ter_db(const char *ff,char C,int nb,t_hackblock tb[],
gpp_atomtype_t atype)
{
FILE *out;
*tbptr = tb;
}
-int read_ter_db(const char *ffdir,char ter,
+int read_ter_db(const char *ffdir,bool bAddCWD,char ter,
t_hackblock **tbptr,gpp_atomtype_t atype)
{
char ext[STRLEN];
/* Search for termini database files.
* Do not generate an error when none are found.
*/
- ntdbf = fflib_search_file_end(ffdir,ext,FALSE,&tdbf);
+ ntdbf = fflib_search_file_end(ffdir,bAddCWD,ext,FALSE,&tdbf);
ntb = 0;
*tbptr = NULL;
for(f=0; f<ntdbf; f++) {
t_hackblock **filter_ter(int nrtp,t_restp rtp[],
int nb,t_hackblock tb[],
const char *resname,
+ const char *rtpname,
int *nret)
{
/* Since some force fields (e.g. OPLS) needs different
char *s,*s2,*c;
t_hackblock **list;
- restp = search_rtp(resname,nrtp,rtp);
+ restp = search_rtp(rtpname,nrtp,rtp);
n=0;
list=NULL;
#include "hackblock.h"
#include "grompp.h"
-extern int read_ter_db(const char *ffdir,char ter,
+extern int read_ter_db(const char *ffdir,bool bAddCWD,char ter,
t_hackblock **tbptr,gpp_atomtype_t atype);
/* Read database for N&C terminal hacking */
extern t_hackblock **filter_ter(int nrtp,t_restp rtp[],
int nb,t_hackblock tb[],
const char *resname,
+ const char *rtpname,
int *nret);
/* Return a list of pointers to blocks that match residue name */
return F_UREY_BRADLEY;
case 6:
return F_QUARTIC_ANGLES;
- case 7:
+ case 8:
return F_TABANGLES;
default:
gmx_fatal(FARGS,"Invalid angle type %d",type);
static void sum_q(t_atoms *atoms,int n,double *qt,double *qBt)
{
- int i;
+ double qmolA,qmolB;
+ int i;
- /* sum charge */
- for (i=0; (i<atoms->nr); i++) {
- *qt += n*atoms->atom[i].q;
- *qBt += n*atoms->atom[i].qB;
- }
+ /* sum charge */
+ qmolA = 0;
+ qmolB = 0;
+ for (i=0; i<atoms->nr; i++)
+ {
+ qmolA += atoms->atom[i].q;
+ qmolB += atoms->atom[i].qB;
+ }
+ /* Unfortunately an absolute comparison,
+ * but this avoids unnecessary warnings and gmx-users mails.
+ */
+ if (fabs(qmolA) >= 1e-6 || fabs(qmolB) >= 1e-6)
+ {
+ *qt += n*qmolA;
+ *qBt += n*qmolB;
+ }
}
static void get_nbparm(char *nb_str,char *comb_str,int *nb,int *comb,
warninp_t wi)
{
int nfield;
- int i,n,k,found,gfound;
+ int atype;
double radius,vol,surftens,gb_radius,S_hct;
char atypename[STRLEN];
char errbuf[STRLEN];
}
/* Search for atomtype */
- found = 0;
- gfound = -1;
- for(i=0;i<get_atomtype_ntypes(at) && !found;i++)
- {
- if(gmx_strncasecmp(atypename,get_atomtype_name(i,at),STRLEN-1)==0)
- {
- found = i;
- gfound = i;
- }
- }
+ atype = get_atomtype_type(atypename,at);
- if (gfound==-1)
+ if (atype == NOTSET)
{
printf("Couldn't find topology match for atomtype %s\n",atypename);
abort();
}
- set_atomtype_gbparam(at,found,radius,vol,surftens,gb_radius,S_hct);
+ set_atomtype_gbparam(at,atype,radius,vol,surftens,gb_radius,S_hct);
}
void
/* if the information is present... */
for (i=0; (i < at->nr); i++) {
ri = at->atom[i].resind;
- if (i == 0 || ri != at->atom[i-1].resind &&
+ if ((i == 0 || ri != at->atom[i-1].resind) &&
at->resinfo[ri].rtp != NULL) {
qres = get_residue_charge(at,i);
fprintf(out,"; residue %3d %-3s rtp %-4s q ",
int i;
const char *fn[2];
t_trxframe fr[2];
- int status[2];
+ t_trxstatus *status[2];
bool b[2];
fn[0]=fn1;
else if (!b1 && b2)
fprintf(stdout,"\nEnd of file on %s but not on %s\n",fn1,fn2);
else if (!b1 && !b2)
- fprintf(stdout,"\nFiles read succesfully\n");
+ fprintf(stdout,"\nFiles read successfully\n");
else {
cmp_real(stdout,"t",-1,fr1->t,fr2->t,ftol,abstol);
cmp_int(stdout,"step",-1,fr1->step,fr2->step);
int main (int argc, char *argv[])
{
const char *desc[] = {
- "tpbconv can edit run input files in four ways.[PAR]"
+ "tpbconv can edit run input files in four ways.[PAR]",
"[BB]1st.[bb] by modifying the number of steps in a run input file",
- "with option [TT]-nsteps[tt] or option [TT]-runtime[tt].[PAR]",
- "[BB]2st.[bb] (OBSOLETE) by creating a run input file",
+ "with options [TT]-extend[tt], [TT]-until[tt] or [TT]-nsteps[tt]",
+ "(nsteps=-1 means unlimited number of steps)[PAR]",
+ "[BB]2nd.[bb] (OBSOLETE) by creating a run input file",
"for a continuation run when your simulation has crashed due to e.g.",
"a full disk, or by making a continuation run input file.",
"This option is obsolete, since mdrun now writes and reads",
"When pressure and/or Nose-Hoover temperature coupling is used",
"an energy file can be supplied to get an exact continuation",
"of the original run.[PAR]",
- "[BB]3nd.[bb] by creating a tpx file for a subset of your original",
+ "[BB]3rd.[bb] by creating a tpx file for a subset of your original",
"tpx file, which is useful when you want to remove the solvent from",
"your tpx file, or when you want to make e.g. a pure Ca tpx file.",
"[BB]WARNING: this tpx file is not fully functional[bb].",
- "[BB]4rd.[bb] by setting the charges of a specified group",
+ "[BB]4th.[bb] by setting the charges of a specified group",
"to zero. This is useful when doing free energy estimates",
"using the LIE (Linear Interaction Energy) method."
};
const char *top_fn,*frame_fn;
- int fp;
+ t_fileio *fp;
ener_file_t fp_ener=NULL;
t_trnheader head;
int i;
#define NFILE asize(fnm)
/* Command line options */
- static int nsteps_req_int = -1;
- static real runtime_req = -1;
+ static int nsteps_req_int = 0;
static real start_t = -1.0, extend_t = 0.0, until_t = 0.0;
static bool bContinuation = TRUE,bZeroQ = FALSE,bVel=TRUE;
static t_pargs pa[] = {
- { "-nsteps", FALSE, etINT, {&nsteps_req_int},
- "Change the number of steps" },
- { "-runtime", FALSE, etREAL, {&runtime_req},
- "Set the run time (ps)" },
- { "-time", FALSE, etREAL, {&start_t},
- "Continue from frame at this time (ps) instead of the last frame" },
{ "-extend", FALSE, etREAL, {&extend_t},
"Extend runtime by this amount (ps)" },
{ "-until", FALSE, etREAL, {&until_t},
"Extend runtime until this ending time (ps)" },
+ { "-nsteps", FALSE, etINT, {&nsteps_req_int},
+ "Change the number of steps" },
+ { "-time", FALSE, etREAL, {&start_t},
+ "Continue from frame at this time (ps) instead of the last frame" },
{ "-zeroq", FALSE, etBOOL, {&bZeroQ},
"Set the charges of a group (from the index) to zero" },
{ "-vel", FALSE, etBOOL, {&bVel},
/* Convert int to gmx_large_int_t */
nsteps_req = nsteps_req_int;
- bNsteps = (nsteps_req >= 0 || runtime_req >= 0);
+ bNsteps = opt2parg_bSet("-nsteps",asize(pa),pa);
bExtend = opt2parg_bSet("-extend",asize(pa),pa);
bUntil = opt2parg_bSet("-until",asize(pa),pa);
bTime = opt2parg_bSet("-time",asize(pa),pa);
bTraj = (opt2bSet("-f",NFILE,fnm) || bTime);
top_fn = ftp2fn(efTPX,NFILE,fnm);
- fprintf(stderr,"Reading toplogy and shit from %s\n",top_fn);
+ fprintf(stderr,"Reading toplogy and stuff from %s\n",top_fn);
snew(ir,1);
read_tpx_state(top_fn,ir,&state,NULL,&mtop);
}
if (bNsteps) {
- if (nsteps_req < 0) {
- if (!EI_DYNAMICS(ir->eI)) {
- gmx_fatal(FARGS,"Can not set the run time with integrator '%s'",
- EI(ir->eI));
- }
- nsteps_req = (int)(runtime_req/ir->delta_t + 0.5);
- }
fprintf(stderr,"Setting nsteps to %s\n",gmx_step_str(nsteps_req,buf));
ir->nsteps = nsteps_req;
} else {
#include "fflibutil.h"
#include "hackblock.h"
#include "gmx_fatal.h"
+#include "xlate.h"
typedef struct {
char *filebase;
sfree(xlatom);
}
-void rename_atoms(const char *xlfile,const char *ffdir,
+void rename_atoms(const char *xlfile,const char *ffdir,bool bAddCWD,
t_atoms *atoms,t_symtab *symtab,const t_restp *restp,
bool bResname,t_aa_names *aan,bool bReorderNum,
bool bVerbose)
}
else
{
- nf = fflib_search_file_end(ffdir,".arn",FALSE,&f);
+ nf = fflib_search_file_end(ffdir,bAddCWD,".arn",FALSE,&f);
for(i=0; i<nf; i++)
{
fp = fflib_open(f[i]);
/* If bResname is true renames atoms based on residue names,
* otherwise renames atoms based on rtp entry names.
*/
-extern void rename_atoms(const char *xlfile,const char *ffdir,
+extern void rename_atoms(const char *xlfile,const char *ffdir,bool bAddCWD,
t_atoms *atoms,t_symtab *symtab,const t_restp *restp,
bool bResname,t_aa_names *aan,bool bReorderNum,
bool bVerbose);
domdec.c domdec_box.c domdec_con.c \
domdec_network.c domdec_setup.c domdec_top.c \
ebin.c \
- edsam.c ewald.c fftgrid.c \
+ edsam.c ewald.c \
force.c forcerec.c \
ghat.c init.c \
mdatom.c mdebin.c minimize.c \
wall.c wnblist.c \
csettle.c clincs.c \
qmmm.c gmx_fft.c gmx_parallel_3dfft.c \
- gmx_wallcycle.c \
+ fft5d.c fft5d.h \
+ gmx_wallcycle.c \
qm_gaussian.c qm_mopac.c qm_gamess.c \
gmx_fft_fftw2.c gmx_fft_fftw3.c gmx_fft_fftpack.c \
- gmx_fft_mkl.c
+ gmx_fft_mkl.c qm_orca.c
LDADD = ../mdlib/libmd@LIBSUFFIX@.la ../gmxlib/libgmx@LIBSUFFIX@.la
{
char buf[256];
sprintf(buf,
- "\nt = %.3f ps: Water molecule starting at atom %d can not be "
- "settled.\nCheck for bad contacts and/or reduce the timestep.\n",
- ir->init_t+step*ir->delta_t,
- ddglatnr(cr->dd,settle->iatoms[error*2+1]));
+ "\nstep " gmx_large_int_pfmt ": Water molecule starting at atom %d can not be "
+ "settled.\nCheck for bad contacts and/or reduce the timestep if appropriate.\n",
+ step,ddglatnr(cr->dd,settle->iatoms[error*2+1]));
if (fplog)
{
fprintf(fplog,"%s",buf);
#include "txtdump.h"
#include "nrnb.h"
#include "gmx_random.h"
+#include "update.h"
+#include "mdrun.h"
#define NTROTTERCALLS 5
#define NTROTTERPARTS 3
-/* these integration routines are only references inside this file */
+/* these integration routines are only referenced inside this file */
static void NHC_trotter(t_grpopts *opts,int nvar, gmx_ekindata_t *ekind,real dtfull,
double xi[],double vxi[], double scalefac[], real *veta, t_extmass *MassQ, bool bEkinAveVel)
sfree(state);
}
-void trotter_update(t_inputrec *ir,gmx_ekindata_t *ekind,
+void trotter_update(t_inputrec *ir,gmx_large_int_t step, gmx_ekindata_t *ekind,
gmx_enerdata_t *enerd, t_state *state,
tensor vir, t_mdatoms *md,
t_extmass *MassQ, int *trotter_seq)
real ecorr,pcorr,dvdlcorr;
real bmass,qmass,reft,kT,dt,nd;
tensor dumpres,dumvir;
- double *scalefac;
+ double *scalefac,dtc;
rvec sumv,consk;
+ bool bCouple;
+ bCouple = (ir->nstcalcenergy == 1 ||
+ do_per_step(step+ir->nstcalcenergy,ir->nstcalcenergy));
+
/* signal we are returning if nothing is going to be done in this routine */
- if (trotter_seq[0] == etrtSKIPALL)
+ if ((trotter_seq[0] == etrtSKIPALL) || !(bCouple))
{
return;
}
+
+ dtc = ir->nstcalcenergy*ir->delta_t;
opts = &(ir->opts); /* just for ease of referencing */
ngtc = opts->ngtc;
snew(scalefac,opts->ngtc);
/* allow for doubled intgrators by doubling dt instead of making 2 calls */
if ((trotter_seq[i] == etrtBAROV2) || (trotter_seq[i] == etrtBARONHC2) || (trotter_seq[i] == etrtNHC2))
{
- dt = 2 * ir->delta_t;
+ dt = 2 * dtc;
}
else
{
- dt = ir->delta_t;
+ dt = dtc;
}
-
+
switch (trotter_seq[i])
{
case etrtBAROV:
for (j=0;j<nh;j++)
{
- ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
- /* contribution from the thermal variable of the NH chain */
- ener_npt += ixi[j]*kT;
+ if (iQinv[j] > 0)
+ {
+ ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
+ /* contribution from the thermal variable of the NH chain */
+ ener_npt += ixi[j]*kT;
+ }
if (debug)
{
fprintf(debug,"P-T-group: %10d Chain %4d ThermV: %15.8f ThermX: %15.8f",i,j,ivxi[j],ixi[j]);
/* contribution from the thermal momenta of the NH chain */
for (j=0;j<nh;j++)
{
- ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
- /* contribution from the thermal variable of the NH chain */
- if (j==0) {
- ndj = nd;
- }
- else
- {
- ndj = 1;
- }
- ener_npt += ndj*ixi[j]*kT;
+ if (iQinv[j] > 0) {
+ ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
+ /* contribution from the thermal variable of the NH chain */
+ if (j==0) {
+ ndj = nd;
+ }
+ else
+ {
+ ndj = 1;
+ }
+ ener_npt += ndj*ixi[j]*kT;
+ }
}
}
else /* Other non Trotter temperature NH control -- no chains yet. */
#include "mtop_util.h"
#include "gmxfio.h"
#include "gmx_ga2la.h"
+#include "gmx_sort.h"
#ifdef GMX_LIB_MPI
#include <mpi.h>
typedef struct
{
- int dimind; /* The dimension index */
+ int dim; /* The dimension */
int nslab; /* The number of PME slabs in this dimension */
real *slb_dim_f; /* Cell sizes for determining the PME comm. with SLB */
int *pp_min; /* The minimum pp node location, size nslab */
/* The number of nodes doing PME (PP/PME or only PME) */
int npmenodes;
int npmenodes_major;
+ int npmenodes_minor;
/* The communication setup including the PME only nodes */
bool bCartesianPP_PME;
ivec ntot;
return load;
}
-static void set_slb_pme_dim_f(gmx_domdec_t *dd,int dimind,real **dim_f)
+static void set_slb_pme_dim_f(gmx_domdec_t *dd,int dim,real **dim_f)
{
gmx_domdec_comm_t *comm;
int i;
comm = dd->comm;
- if (dd->dim[dimind] != dimind)
- {
- *dim_f = NULL;
- return;
- }
-
- snew(*dim_f,dd->nc[dimind]+1);
+ snew(*dim_f,dd->nc[dim]+1);
(*dim_f)[0] = 0;
- for(i=1; i<dd->nc[dimind]; i++)
+ for(i=1; i<dd->nc[dim]; i++)
{
- if (comm->slb_frac[dimind])
+ if (comm->slb_frac[dim])
{
- (*dim_f)[i] = (*dim_f)[i-1] + comm->slb_frac[dimind][i-1];
+ (*dim_f)[i] = (*dim_f)[i-1] + comm->slb_frac[dim][i-1];
}
else
{
- (*dim_f)[i] = (real)i/(real)dd->nc[dimind];
+ (*dim_f)[i] = (real)i/(real)dd->nc[dim];
}
}
- (*dim_f)[dd->nc[dimind]] = 1;
+ (*dim_f)[dd->nc[dim]] = 1;
}
static void init_ddpme(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
int pmeindex,slab,nso,i;
ivec xyz;
- ddpme->dimind = dimind;
- ddpme->nslab = nslab;
+ ddpme->dim = dd->dim[dimind];
+ ddpme->nslab = nslab;
if (nslab <= 1)
{
}
nso = dd->comm->npmenodes/nslab;
- /* Determine for each PME slab the PP locacation range for dimension dim */
+ /* Determine for each PME slab the PP location range for dimension dim */
snew(ddpme->pp_min,nslab);
snew(ddpme->pp_max,nslab);
for(slab=0; slab<nslab; slab++) {
/* For y only use our y/z slab.
* This assumes that the PME x grid size matches the DD grid size.
*/
- if (dimind == 0 || xyz[YY] == dd->ci[YY]) {
+ if (dimind == 0 || xyz[XX] == dd->ci[XX]) {
pmeindex = ddindex2pmeindex(dd,i);
if (dimind == 0) {
slab = pmeindex/nso;
}
}
- set_slb_pme_dim_f(dd,ddpme->dimind,&ddpme->slb_dim_f);
+ set_slb_pme_dim_f(dd,ddpme->dim,&ddpme->slb_dim_f);
}
int dd_pme_maxshift0(gmx_domdec_t *dd)
int dd_pme_maxshift1(gmx_domdec_t *dd)
{
- return dd->comm->ddpme[1].maxshift;
+ /* This should return the maxshift for dim Y,
+ * where comm indexes ddpme with dimind.
+ */
+ if (dd->comm->npmedecompdim == 1 && dd->dim[0] == YY)
+ {
+ return dd->comm->ddpme[0].maxshift;
+ }
+ else
+ {
+ return dd->comm->ddpme[1].maxshift;
+ }
}
static void set_pme_maxshift(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
bool bUniform,gmx_ddbox_t *ddbox,real *cell_f)
{
gmx_domdec_comm_t *comm;
- int dim,nc,ns,s;
+ int nc,ns,s;
int *xmin,*xmax;
real range,pme_boundary;
int sh;
comm = dd->comm;
- dim = ddpme->dimind;
- nc = dd->nc[dim];
+ nc = dd->nc[ddpme->dim];
ns = ddpme->nslab;
- if (dd->dim[dim] != dim)
+ if (nc == 1)
{
/* PP decomposition is not along dim: the worst situation */
sh = ns/2;
*/
xmin = ddpme->pp_min;
xmax = ddpme->pp_max;
- /* Allow for atoms to be maximally half the cell size or cut-off
- * out of their DD cell.
+ /* Allow for atoms to be maximally 2/3 times the cut-off
+ * out of their DD cell. This is a reasonable balance between
+ * between performance and support for most charge-group/cut-off
+ * combinations.
*/
- range = 0.5*min(comm->cellsize_min[dim],comm->cutoff);
- range /= ddbox->skew_fac[dim]*ddbox->box_size[dim];
- /* Avoid unlucky rounding at exactly 0.5 */
+ range = 2.0/3.0*comm->cutoff/ddbox->box_size[ddpme->dim];
+ /* Avoid extra communication when we are exactly at a boundary */
range *= 0.999;
sh = 1;
if (debug)
{
- fprintf(debug,"PME slab communication range for dimind %d is %d\n",
- ddpme->dimind,ddpme->maxshift);
+ fprintf(debug,"PME slab communication range for dim %d is %d\n",
+ ddpme->dim,ddpme->maxshift);
}
}
if (d < ddbox->npbcdim &&
dd->nc[d] > 1 && npulse[d] >= dd->nc[d])
{
- gmx_fatal_collective(FARGS,DDMASTER(dd),
+ gmx_fatal_collective(FARGS,NULL,dd,
"The box size in direction %c (%f) times the triclinic skew factor (%f) is too small for a cut-off of %f with %d domain decomposition cells, use 1 or more than %d %s or increase the box size in this direction",
dim2char(d),ddbox->box_size[d],ddbox->skew_fac[d],
comm->cutoff,
static void print_cg_move(FILE *fplog,
gmx_domdec_t *dd,
gmx_large_int_t step,int cg,int dim,int dir,
- real limitd,
+ bool bHaveLimitdAndCMOld,real limitd,
rvec cm_old,rvec cm_new,real pos_d)
{
gmx_domdec_comm_t *comm;
comm = dd->comm;
fprintf(fplog,"\nStep %s:\n",gmx_step_str(step,buf));
- fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition (%f) in direction %c\n",
- ddglatnr(dd,dd->cgindex[cg]),limitd,dim2char(dim));
+ if (bHaveLimitdAndCMOld)
+ {
+ fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition (%f) in direction %c\n",
+ ddglatnr(dd,dd->cgindex[cg]),limitd,dim2char(dim));
+ }
+ else
+ {
+ fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition in direction %c\n",
+ ddglatnr(dd,dd->cgindex[cg]),dim2char(dim));
+ }
fprintf(fplog,"distance out of cell %f\n",
dir==1 ? pos_d - comm->cell_x1[dim] : pos_d - comm->cell_x0[dim]);
- fprintf(fplog,"Old coordinates: %8.3f %8.3f %8.3f\n",
- cm_old[XX],cm_old[YY],cm_old[ZZ]);
+ if (bHaveLimitdAndCMOld)
+ {
+ fprintf(fplog,"Old coordinates: %8.3f %8.3f %8.3f\n",
+ cm_old[XX],cm_old[YY],cm_old[ZZ]);
+ }
fprintf(fplog,"New coordinates: %8.3f %8.3f %8.3f\n",
cm_new[XX],cm_new[YY],cm_new[ZZ]);
fprintf(fplog,"Old cell boundaries in direction %c: %8.3f %8.3f\n",
static void cg_move_error(FILE *fplog,
gmx_domdec_t *dd,
gmx_large_int_t step,int cg,int dim,int dir,
- real limitd,
+ bool bHaveLimitdAndCMOld,real limitd,
rvec cm_old,rvec cm_new,real pos_d)
{
if (fplog)
{
- print_cg_move(fplog, dd,step,cg,dim,dir,limitd,cm_old,cm_new,pos_d);
+ print_cg_move(fplog, dd,step,cg,dim,dir,
+ bHaveLimitdAndCMOld,limitd,cm_old,cm_new,pos_d);
}
- print_cg_move(stderr,dd,step,cg,dim,dir,limitd,cm_old,cm_new,pos_d);
+ print_cg_move(stderr,dd,step,cg,dim,dir,
+ bHaveLimitdAndCMOld,limitd,cm_old,cm_new,pos_d);
gmx_fatal(FARGS,
"A charge group moved too far between two domain decomposition steps\n"
"This usually means that your system is not well equilibrated");
{
cell_x1[d] = comm->cell_x1[d];
}
- limit0[d] = comm->old_cell_x0[d] - limitd[d];
- limit1[d] = comm->old_cell_x1[d] + limitd[d];
+ if (d < npbcdim)
+ {
+ limit0[d] = comm->old_cell_x0[d] - limitd[d];
+ limit1[d] = comm->old_cell_x1[d] + limitd[d];
+ }
+ else
+ {
+ /* We check after communication if a charge group moved
+ * more than one cell. Set the pre-comm check limit to float_max.
+ */
+ limit0[d] = -GMX_FLOAT_MAX;
+ limit1[d] = GMX_FLOAT_MAX;
+ }
}
make_tric_corr_matrix(npbcdim,state->box,tcm);
{
if (pos_d >= limit1[d])
{
- cg_move_error(fplog,dd,step,cg,d,1,limitd[d],
+ cg_move_error(fplog,dd,step,cg,d,1,TRUE,limitd[d],
cg_cm[cg],cm_new,pos_d);
}
dev[d] = 1;
{
if (pos_d < limit0[d])
{
- cg_move_error(fplog,dd,step,cg,d,-1,limitd[d],
+ cg_move_error(fplog,dd,step,cg,d,-1,TRUE,limitd[d],
cg_cm[cg],cm_new,pos_d);
}
dev[d] = -1;
for(cg=0; cg<ncg_recv; cg++)
{
flag = comm->buf_int[cg*DD_CGIBS+1];
+
+ if (dim >= npbcdim && dd->nc[dim] > 2)
+ {
+ /* No pbc in this dim and more than one domain boundary.
+ * We to a separate check if a charge did not move too far.
+ */
+ if (((flag & DD_FLAG_FW(d)) &&
+ comm->vbuf.v[buf_pos][d] > cell_x1[dim]) ||
+ ((flag & DD_FLAG_BW(d)) &&
+ comm->vbuf.v[buf_pos][d] < cell_x0[dim]))
+ {
+ cg_move_error(fplog,dd,step,cg,d,
+ (flag & DD_FLAG_FW(d)) ? 1 : 0,
+ FALSE,0,
+ comm->vbuf.v[buf_pos],
+ comm->vbuf.v[buf_pos],
+ comm->vbuf.v[buf_pos][d]);
+ }
+ }
+
mc = -1;
if (d < dd->ndim-1)
{
}
static void split_communicator(FILE *fplog,t_commrec *cr,int dd_node_order,
- int reorder)
+ int reorder)
{
gmx_domdec_t *dd;
gmx_domdec_comm_t *comm;
if (bDiv[YY] || bDiv[ZZ])
{
comm->bCartesianPP_PME = TRUE;
- /* We choose the direction that provides the thinnest slab
+ /* If we have 2D PME decomposition, which is always in x+y,
+ * we stack the PME only nodes in z.
+ * Otherwise we choose the direction that provides the thinnest slab
* of PME only nodes as this will have the least effect
* on the PP communication.
* But for the PME communication the opposite might be better.
*/
- if (bDiv[YY] && (!bDiv[ZZ] || dd->nc[YY] <= dd->nc[ZZ]))
+ if (bDiv[ZZ] && (comm->npmenodes_minor > 1 ||
+ !bDiv[YY] ||
+ dd->nc[YY] > dd->nc[ZZ]))
{
- comm->cartpmedim = YY;
+ comm->cartpmedim = ZZ;
}
else
{
- comm->cartpmedim = ZZ;
+ comm->cartpmedim = YY;
}
comm->ntot[comm->cartpmedim]
+= (cr->npmenodes*dd->nc[comm->cartpmedim])/dd->nnodes;
gmx_mtop_t *mtop,t_inputrec *ir,
matrix box,rvec *x,
gmx_ddbox_t *ddbox,
- int *npme_major)
+ int *npme_x,int *npme_y)
{
gmx_domdec_t *dd;
gmx_domdec_comm_t *comm;
}
snew(dd,1);
+
dd->comm = init_dd_comm();
comm = dd->comm;
snew(comm->cggl_flag,DIM*2);
{
fprintf(fplog,"ERROR: The initial cell size (%f) is smaller than the cell size limit (%f)\n",acs,comm->cellsize_limit);
}
- gmx_fatal_collective(FARGS,MASTER(cr),
+ gmx_fatal_collective(FARGS,cr,NULL,
"The initial cell size (%f) is smaller than the cell size limit (%f), change options -dd, -rdd or -rcon, see the log file for details",
acs,comm->cellsize_limit);
}
comm->eDLB!=edlbNO ? " or -dds" : "",
bC ? " or your LINCS settings" : "");
- gmx_fatal_collective(FARGS,MASTER(cr),
+ gmx_fatal_collective(FARGS,cr,NULL,
"There is no domain decomposition for %d nodes that is compatible with the given box and a minimum cell size of %g nm\n"
"%s\n"
"Look in the log file for details on the domain decomposition",
dd->nnodes = dd->nc[XX]*dd->nc[YY]*dd->nc[ZZ];
if (cr->nnodes - dd->nnodes != cr->npmenodes)
{
- gmx_fatal(FARGS,"The size of the domain decomposition grid (%d) does not match the number of nodes (%d). The total number of nodes is %d",
- dd->nnodes,cr->nnodes - cr->npmenodes,cr->nnodes);
+ gmx_fatal_collective(FARGS,cr,NULL,
+ "The size of the domain decomposition grid (%d) does not match the number of nodes (%d). The total number of nodes is %d",
+ dd->nnodes,cr->nnodes - cr->npmenodes,cr->nnodes);
}
if (cr->npmenodes > dd->nnodes)
{
- gmx_fatal(FARGS,"The number of separate PME node (%d) is larger than the number of PP nodes (%d), this is not supported.",cr->npmenodes,dd->nnodes);
+ gmx_fatal_collective(FARGS,cr,NULL,
+ "The number of separate PME node (%d) is larger than the number of PP nodes (%d), this is not supported.",cr->npmenodes,dd->nnodes);
}
if (cr->npmenodes > 0)
{
if (EEL_PME(ir->coulombtype))
{
- if (FALSE && dd->nc[XX] > cr->npmenodes && cr->npmenodes % dd->nc[XX] == 0)
+ if (dd->nc[XX] > 1 && dd->nc[YY] > 1 &&
+ comm->npmenodes > dd->nc[XX] && comm->npmenodes % dd->nc[XX] == 0 &&
+ getenv("GMX_PMEONEDD") == NULL)
{
comm->npmedecompdim = 2;
comm->npmenodes_major = dd->nc[XX];
+ comm->npmenodes_minor = comm->npmenodes/comm->npmenodes_major;
}
else
{
comm->npmedecompdim = 1;
comm->npmenodes_major = comm->npmenodes;
+ comm->npmenodes_minor = comm->npmenodes/comm->npmenodes_major;
+ }
+ if (fplog)
+ {
+ fprintf(fplog,"PME domain decomposition: %d x %d x %d\n",
+ comm->npmenodes_major,comm->npmenodes_minor,1);
}
}
else
{
comm->npmedecompdim = 0;
comm->npmenodes_major = 0;
+ comm->npmenodes_minor = 0;
+ }
+
+ /* Technically we don't need both of these,
+ * but it simplifies code not having to recalculate it.
+ */
+ if (comm->npmedecompdim == 1 && dd->dim[0] == YY)
+ {
+ *npme_x = 1;
+ *npme_y = comm->npmenodes;
+ }
+ else
+ {
+ *npme_x = comm->npmenodes_major;
+ *npme_y = comm->npmenodes_minor;
}
- *npme_major = comm->npmenodes_major;
snew(comm->slb_frac,DIM);
if (comm->eDLB == edlbNO)
comm->npmenodes = 0;
if (dd->pme_nodeid >= 0)
{
- gmx_fatal(FARGS,"Can not have separate PME nodes without PME electrostatics");
+ gmx_fatal_collective(FARGS,NULL,dd,
+ "Can not have separate PME nodes without PME electrostatics");
}
}
print_dd_settings(fplog,dd,ir,TRUE,dlb_scale,ddbox);
}
- vol_frac = 1/(real)dd->nnodes + comm_box_frac(dd->nc,comm->cutoff,ddbox);
+ if (ir->ePBC == epbcNONE)
+ {
+ vol_frac = 1;
+ }
+ else
+ {
+ vol_frac =
+ 1/(real)dd->nnodes + comm_box_frac(dd->nc,comm->cutoff,ddbox);
+ }
if (debug)
{
fprintf(debug,"Volume fraction for all DD zones: %f\n",vol_frac);
int i1,i2,i_new;
/* The new indices are not very ordered, so we qsort them */
- qsort(sort_new,nsort_new,sizeof(sort_new[0]),comp_cgsort);
+ qsort_threadsafe(sort_new,nsort_new,sizeof(sort_new[0]),comp_cgsort);
/* sort2 is already ordered, so now we can merge the two arrays */
i1 = 0;
fprintf(debug,"qsort cgs: %d new home %d\n",dd->ncg_home,ncg_new);
}
/* Determine the order of the charge groups using qsort */
- qsort(cgsort,dd->ncg_home,sizeof(cgsort[0]),comp_cgsort);
+ qsort_threadsafe(cgsort,dd->ncg_home,sizeof(cgsort[0]),comp_cgsort);
}
cgsort = sort->sort1;
{
gmx_domdec_t *dd;
gmx_domdec_comm_t *comm;
- gmx_ddbox_t ddbox;
+ gmx_ddbox_t ddbox={0};
t_block *cgs_gl;
gmx_large_int_t step_pcoupl;
rvec cell_ns_x0,cell_ns_x1;
int rcount,void *rbuf)
{
#ifdef GMX_MPI
+ int dum;
+
+ if (rcount == 0)
+ {
+ /* MPI does not allow NULL pointers */
+ rbuf = &dum;
+ }
MPI_Scatterv(sbuf,scounts,disps,MPI_BYTE,
rbuf,rcount,MPI_BYTE,
DDMASTERRANK(dd),dd->mpi_comm_all);
int *rcounts,int *disps,void *rbuf)
{
#ifdef GMX_MPI
+ int dum;
+
+ if (scount == 0)
+ {
+ /* MPI does not allow NULL pointers */
+ sbuf = &dum;
+ }
MPI_Gatherv(sbuf,scount,MPI_BYTE,
rbuf,rcounts,disps,MPI_BYTE,
DDMASTERRANK(dd),dd->mpi_comm_all);
#include "network.h"
#include "perf_est.h"
#include "physics.h"
-#include "pme.h"
#include "smalloc.h"
#include "typedefs.h"
#include "vec.h"
}
/* Does this division gives a reasonable PME load? */
- return (fits_pme_ratio(nnodes,npme,ratio) &&
- pme_inconvenient_nnodes(ir->nkx,ir->nky,npme) <= 1);
+ return fits_pme_ratio(nnodes,npme,ratio);
}
static int guess_npme(FILE *fplog,gmx_mtop_t *mtop,t_inputrec *ir,matrix box,
return d;
}
+static int div_up(int n,int f)
+{
+ return (n + f - 1)/f;
+}
+
real comm_box_frac(ivec dd_nc,real cutoff,gmx_ddbox_t *ddbox)
{
int i,j,k,npp;
}
}
}
- /* Normalize by the number of PP nodes */
- comm_vol /= npp;
return comm_vol;
}
}
static float comm_cost_est(gmx_domdec_t *dd,real limit,real cutoff,
- matrix box,gmx_ddbox_t *ddbox,t_inputrec *ir,
+ matrix box,gmx_ddbox_t *ddbox,
+ int natoms,t_inputrec *ir,
float pbcdxr,
- int npme,ivec nc)
+ int npme_tot,ivec nc)
{
- int i,j,k,npp;
+ ivec npme={1,1,1};
+ int i,j,k,nk,overlap;
rvec bt;
- float comm_vol,comm_vol_pme,cost_pbcdx;
+ float comm_vol,comm_vol_xf,comm_pme,cost_pbcdx;
/* This is the cost of a pbc_dx call relative to the cost
* of communicating the coordinate and force of an atom.
* This will be machine dependent.
}
}
- npp = 1;
for(i=0; i<DIM; i++)
{
- npp *= nc[i];
bt[i] = ddbox->box_size[i]*ddbox->skew_fac[i];
/* Without PBC there are no cell size limits with 2 cells */
return -1;
}
}
+
+ if (npme_tot > 1)
+ {
+ /* Will we use 1D or 2D PME decomposition? */
+ npme[XX] = (npme_tot % nc[XX] == 0) ? nc[XX] : npme_tot;
+ npme[YY] = npme_tot/npme[XX];
+ }
/* When two dimensions are (nearly) equal, use more cells
* for the smallest index, so the decomposition does not
*/
for(i=0; i<DIM; i++)
{
- if (npme == 0 || i != XX)
+ for(j=i+1; j<DIM; j++)
{
- for(j=i+1; j<DIM; j++)
+ /* Check if dimension i and j are equivalent,
+ * both for PME and for the box size.
+ * The XX/YY check is a bit compact. If nc[YY]==npme[YY]
+ * this means the swapped nc has nc[XX]=npme[XX],
+ * and we can also swap X and Y for PME.
+ */
+ if (!((i == XX && j == YY && npme[YY] > 1 && nc[YY] != npme[YY]) ||
+ (i == YY && j == ZZ && npme[YY] > 1)) &&
+ fabs(bt[j] - bt[i]) < 0.01*bt[i] && nc[j] > nc[i])
{
- if (fabs(bt[j] - bt[i]) < 0.01*bt[i] && nc[j] > nc[i])
- {
- return -1;
- }
+ return -1;
}
}
}
+
+ /* This function determines only half of the communication cost.
+ * All PP, PME and PP-PME communication is symmetric
+ * and the "back"-communication cost is identical to the forward cost.
+ */
comm_vol = comm_box_frac(nc,cutoff,ddbox);
- /* Determine the largest volume that a PME only needs to communicate */
- comm_vol_pme = 0;
- if ((npme > 0) && (nc[XX] % npme != 0))
+ comm_pme = 0;
+ for(i=0; i<2; i++)
{
- if (nc[XX] > npme)
+ /* Determine the largest volume for PME x/f redistribution */
+ if (nc[i] % npme[i] != 0)
{
- comm_vol_pme = (npme==2 ? 1.0/3.0 : 0.5);
+ if (nc[i] > npme[i])
+ {
+ comm_vol_xf = (npme[i]==2 ? 1.0/3.0 : 0.5);
+ }
+ else
+ {
+ comm_vol_xf = 1.0 - lcd(nc[i],npme[i])/(double)npme[i];
+ }
+ comm_pme += 3*natoms*comm_vol_xf;
}
- else
+
+ /* Grid overlap communication */
+ if (npme[i] > 1)
{
- comm_vol_pme = 1.0 - lcd(nc[XX],npme)/(double)npme;
+ nk = (i==0 ? ir->nkx : ir->nky);
+ overlap = (nk % npme[i] == 0 ? ir->pme_order-1 : ir->pme_order);
+ comm_pme += npme[i]*overlap*ir->nkx*ir->nky*ir->nkz/nk;
}
- /* Normalize by the number of PME only nodes */
- comm_vol_pme /= npme;
}
+
+ /* PME FFT communication volume.
+ * This only takes the communication into account and not imbalance
+ * in the calculation. But the imbalance in communication and calculation
+ * are similar and therefore these formulas also prefer load balance
+ * in the FFT and pme_solve calculation.
+ */
+ comm_pme += (npme[YY] - 1)*npme[YY]*div_up(ir->nky,npme[YY])*div_up(ir->nkz,npme[YY])*ir->nkx;
+ comm_pme += (npme[XX] - 1)*npme[XX]*div_up(ir->nkx,npme[XX])*div_up(ir->nky,npme[XX])*ir->nkz;
/* Add cost of pbc_dx for bondeds */
cost_pbcdx = 0;
if ((ddbox->tric_dir[XX] && nc[XX] == 1) ||
(ddbox->tric_dir[YY] && nc[YY] == 1))
{
- cost_pbcdx = pbcdxr*pbcdx_tric_fac/npp;
+ cost_pbcdx = pbcdxr*pbcdx_tric_fac;
}
else
{
- cost_pbcdx = pbcdxr*pbcdx_rect_fac/npp;
+ cost_pbcdx = pbcdxr*pbcdx_rect_fac;
}
}
if (debug)
{
fprintf(debug,
- "nc %2d %2d %2d vol pp %6.4f pbcdx %6.4f pme %6.4f tot %6.4f\n",
- nc[XX],nc[YY],nc[ZZ],
- comm_vol,cost_pbcdx,comm_vol_pme,
- comm_vol + cost_pbcdx + comm_vol_pme);
+ "nc %2d %2d %2d %2d %2d vol pp %6.4f pbcdx %6.4f pme %9.3e tot %9.3e\n",
+ nc[XX],nc[YY],nc[ZZ],npme[XX],npme[YY],
+ comm_vol,cost_pbcdx,comm_pme,
+ 3*natoms*(comm_vol + cost_pbcdx) + comm_pme);
}
- return comm_vol + cost_pbcdx + comm_vol_pme;
+ return 3*natoms*(comm_vol + cost_pbcdx) + comm_pme;
}
static void assign_factors(gmx_domdec_t *dd,
real limit,real cutoff,
- matrix box,gmx_ddbox_t *ddbox,t_inputrec *ir,
+ matrix box,gmx_ddbox_t *ddbox,
+ int natoms,t_inputrec *ir,
float pbcdxr,int npme,
int ndiv,int *div,int *mdiv,ivec ir_try,ivec opt)
{
if (ndiv == 0)
{
- ce = comm_cost_est(dd,limit,cutoff,box,ddbox,ir,pbcdxr,npme,ir_try);
+ ce = comm_cost_est(dd,limit,cutoff,box,ddbox,
+ natoms,ir,pbcdxr,npme,ir_try);
if (ce >= 0 && (opt[XX] == 0 ||
- ce < comm_cost_est(dd,limit,cutoff,box,ddbox,ir,pbcdxr,
+ ce < comm_cost_est(dd,limit,cutoff,box,ddbox,
+ natoms,ir,pbcdxr,
npme,opt)))
{
copy_ivec(ir_try,opt);
}
/* recurse */
- assign_factors(dd,limit,cutoff,box,ddbox,ir,pbcdxr,npme,
+ assign_factors(dd,limit,cutoff,box,ddbox,natoms,ir,pbcdxr,npme,
ndiv-1,div+1,mdiv+1,ir_try,opt);
for(i=0; i<mdiv[0]-x-y; i++)
itry[YY] = 1;
itry[ZZ] = 1;
clear_ivec(nc);
- assign_factors(dd,limit,cutoff,box,ddbox,ir,pbcdxr,
+ assign_factors(dd,limit,cutoff,box,ddbox,mtop->natoms,ir,pbcdxr,
npme,ndiv,div,mdiv,itry,nc);
sfree(div);
}
else
{
- if (cr->nnodes < 12 &&
- pme_inconvenient_nnodes(ir->nkx,ir->nky,cr->nnodes) == 0)
+ if (cr->nnodes <= 10)
{
cr->npmenodes = 0;
}
* so it's index is the current number of position restraints.
*/
n = idef->il[F_POSRES].nr/2;
- if (n >= idef->iparams_posres_nalloc)
+ if (n+1 > idef->iparams_posres_nalloc)
{
- idef->iparams_posres_nalloc = over_alloc_dd(n);
+ idef->iparams_posres_nalloc = over_alloc_dd(n+1);
srenew(idef->iparams_posres,idef->iparams_posres_nalloc);
}
ip = &idef->iparams_posres[n];
FILE *edo; /* output file pointer */
t_edpar *edpar;
bool bFirst;
+ bool bStartFromCpt;
} t_gmx_edsam;
static void project(rvec *x, /* positions to project */
t_edpar *edi) /* edi data set */
{
- /* It is not more work to subtract the average position in every s
- * ubroutine again, because these routines are rarely used simultanely */
+ /* It is not more work to subtract the average position in every
+ * subroutine again, because these routines are rarely used simultanely */
project_to_eigvectors(x, &edi->vecs.mon , edi);
project_to_eigvectors(x, &edi->vecs.linfix, edi);
project_to_eigvectors(x, &edi->vecs.linacc, edi);
fprintf(fp," %f",edi->flood.vecs.fproj[i]);
fprintf(fp,"\n");
- fflush(fp);
}
for every atom we add all the contributions to this atom from all the different eigenvectors.
NOTE: one could add directly to the forcefield forces, would mean we wouldn't have to clear the
- field forces_cart prior the computation, but momentarily we want to compute the forces seperately
+ field forces_cart prior the computation, but momentarily we want to compute the forces separately
to have them accessible for diagnostics
*/
int j,eig;
#endif
-gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],t_commrec *cr)
+gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],unsigned long Flags,t_commrec *cr)
{
gmx_edsam_t ed;
/* The master opens the .edo output file */
fprintf(stderr,"ED sampling will be performed!\n");
ed->edonam = ftp2fn(efEDO,nfile,fnm);
- ed->edo = gmx_fio_fopen(ed->edonam,"w");
+ ed->edo = gmx_fio_fopen(ed->edonam,(Flags & MD_APPENDFILES)? "a+" : "w+");
+ ed->bStartFromCpt = Flags & MD_STARTFROMCPT;
}
return ed;
}
}
-static void ed_apply_constraints(rvec *xcoll, t_edpar *edi, int step, t_commrec *cr)
+static void ed_apply_constraints(rvec *xcoll, t_edpar *edi, gmx_large_int_t step, t_commrec *cr)
{
int i;
rad_project(edi, xstart, &edi->vecs.linfix, cr);
/* Output to file, set the step to -1 so that write_edo knows it was called from init_edsam */
- if (ed->edo)
+ if (ed->edo && !(ed->bStartFromCpt))
write_edo(nr_edi, edi, ed, -1, 0);
/* Prepare for the next edi data set: */
void do_edsam(t_inputrec *ir,
- int step,
+ gmx_large_int_t step,
t_mdatoms *md,
t_commrec *cr,
rvec xs[], /* The local current positions on this processor */
}
/* update radsam references, when required */
- if (do_per_step(step,edi->maxedsteps) && step > edi->presteps)
+ if (do_per_step(step,edi->maxedsteps) && step >= edi->presteps)
{
project(buf->xcoll, edi);
rad_project(edi, buf->xcoll, &edi->vecs.radacc, cr);
}
/* update radacc references, when required */
- if (do_per_step(step,iupdate) && step > edi->presteps)
+ if (do_per_step(step,iupdate) && step >= edi->presteps)
{
edi->vecs.radacc.radius = calc_radius(&edi->vecs.radacc);
if (edi->vecs.radacc.radius - buf->oldrad < edi->slope)
}
/* apply the constraints */
- if (step > edi->presteps && ed_constraints(ed->eEDtype, edi))
- ed_apply_constraints(buf->xcoll, edi, step, cr);
+ if (step >= edi->presteps && ed_constraints(ed->eEDtype, edi))
+ {
+ /* ED constraints should be applied already in the first MD step
+ * (which is step 0), therfore we pass step+1 to the routine */
+ ed_apply_constraints(buf->xcoll, edi, step+1 - ir->init_step, cr);
+ }
/* write to edo, when required */
if (do_per_step(step,edi->outfrq))
#include "gmxcomplex.h"
#include "smalloc.h"
#include "futil.h"
-#include "fftgrid.h"
#include "gmx_fatal.h"
#include "physics.h"
#include "coulomb.h"
ewald_tab_t et)
{
real factor=-1.0/(4*ewaldcoeff*ewaldcoeff);
- real scaleRecip =4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0/ir->epsilon_r; // 1/(Vol*e0) //
+ real scaleRecip =4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0/ir->epsilon_r; /* 1/(Vol*e0) */
real *charge,energy_AB[2],energy;
rvec lll;
int lowiy,lowiz,ix,iy,iz,n,q;
--- /dev/null
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NOGMX
+#define GMX_PARALLEL_ENV_INITIALIZED 1
+#else
+#include "main.h"
+#define GMX_PARALLEL_ENV_INITIALIZED gmx_parallel_env_initialized()
+#endif
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+#ifdef FFT5D_THREADS
+#include <omp.h>
+#endif
+
+#include "fft5d.h"
+#include <float.h>
+#include <math.h>
+#include <assert.h>
+
+#ifndef __FLT_EPSILON__
+#define __FLT_EPSILON__ FLT_EPSILON
+#define __DBL_EPSILON__ DBL_EPSILON
+#endif
+
+#ifdef NOGMX
+FILE* debug=0;
+#endif
+
+#include "gmx_fatal.h"
+
+
+#ifdef GMX_FFT_FFTW3
+#ifdef GMX_THREADS
+/* none of the fftw3 calls, except execute(), are thread-safe, so
+ we need to serialize them with this mutex. */
+static tMPI_Thread_mutex_t big_fftw_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
+
+#define FFTW_LOCK tMPI_Thread_mutex_lock(&big_fftw_mutex);
+#define FFTW_UNLOCK tMPI_Thread_mutex_unlock(&big_fftw_mutex);
+#else /* GMX_THREADS */
+#define FFTW_LOCK
+#define FFTW_UNLOCK
+#endif /* GMX_THREADS */
+#endif /* GMX_FFT_FFTW3 */
+
+static double fft5d_fmax(double a, double b){
+ return (a>b)?a:b;
+}
+
+/* largest factor smaller than sqrt */
+static int lfactor(int z) {
+ int i;
+ for (i=sqrt(z);;i--)
+ if (z%i==0) return i;
+}
+
+/* largest factor */
+static int l2factor(int z) {
+ int i;
+ if (z==1) return 1;
+ for (i=z/2;;i--)
+ if (z%i==0) return i;
+}
+
+/* largest prime factor: WARNING: slow recursion, only use for small numbers */
+static int lpfactor(int z) {
+ int f = l2factor(z);
+ if (f==1) return z;
+ return fft5d_fmax(lpfactor(f),lpfactor(z/f));
+}
+
+#ifndef GMX_MPI
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+double MPI_Wtime() {
+ struct timeval tv;
+ gettimeofday(&tv,0);
+ return tv.tv_sec+tv.tv_usec*1e-6;
+}
+#else
+double MPI_Wtime() {
+ return 0.0;
+}
+#endif
+#endif
+
+static int vmax(int* a, int s) {
+ int i,max=0;
+ for (i=0;i<s;i++)
+ {
+ if (a[i]>max) max=a[i];
+ }
+ return max;
+}
+
+/*
+copied here from fftgrid, because:
+1. function there not publically available
+2. not sure whether we keep fftgrid
+3. less dependencies for fft5d
+
+Only used for non-fftw case
+*/
+static void *
+gmx_calloc_aligned(size_t size)
+{
+ void *p0,*p;
+
+ /*We initialize by zero for Valgrind
+ For non-divisible case we communicate more than the data.
+ If we don't initialize the data we communicate uninitialized data*/
+ p0 = calloc(size+32,1);
+
+ if(p0 == NULL)
+ {
+ gmx_fatal(FARGS,"Failed to allocated %u bytes of aligned memory.",size+32);
+ }
+
+ p = (void *) (((size_t) p0 + 32) & (~((size_t) 31)));
+
+ /* Yeah, yeah, we cannot free this pointer, but who cares... */
+ return p;
+}
+
+
+/* NxMxK the size of the data
+ * comm communicator to use for fft5d
+ * P0 number of processor in 1st axes (can be null for automatic)
+ * lin is allocated by fft5d because size of array is only known after planning phase */
+fft5d_plan fft5d_plan_3d(int NG, int MG, int KG, MPI_Comm comm[2], int flags, t_complex** rlin, t_complex** rlout)
+{
+
+ int P[2],bMaster,prank[2],i;
+ int rNG,rMG,rKG;
+ int *N0=0, *N1=0, *M0=0, *M1=0, *K0=0, *K1=0, *oN0=0, *oN1=0, *oM0=0, *oM1=0, *oK0=0, *oK1=0;
+ int N[3],M[3],K[3],pN[3],pM[3],pK[3],oM[3],oK[3],*iNin[3]={0},*oNin[3]={0},*iNout[3]={0},*oNout[3]={0};
+ int C[3],rC[3],nP[2];
+ int lsize;
+ t_complex *lin=0,*lout=0;
+ fft5d_plan plan;
+ int s;
+
+ /* comm, prank and P are in the order of the decomposition (plan->cart is in the order of transposes) */
+#ifdef GMX_MPI
+ if (GMX_PARALLEL_ENV_INITIALIZED && comm[0] != 0)
+ {
+ MPI_Comm_size(comm[0],&P[0]);
+ MPI_Comm_rank(comm[0],&prank[0]);
+ }
+ else
+#endif
+ {
+ P[0] = 1;
+ prank[0] = 0;
+ }
+#ifdef GMX_MPI
+ if (GMX_PARALLEL_ENV_INITIALIZED && comm[1] != 0)
+ {
+ MPI_Comm_size(comm[1],&P[1]);
+ MPI_Comm_rank(comm[1],&prank[1]);
+ }
+ else
+#endif
+ {
+ P[1] = 1;
+ prank[1] = 0;
+ }
+
+ bMaster=(prank[0]==0&&prank[1]==0);
+
+
+ if (debug)
+ {
+ fprintf(debug,"FFT5D: Using %dx%d processor grid, rank %d,%d\n",
+ P[0],P[1],prank[0],prank[1]);
+ }
+
+ if (bMaster) {
+ if (debug)
+ fprintf(debug,"FFT5D: N: %d, M: %d, K: %d, P: %dx%d, real2complex: %d, backward: %d, order yz: %d, debug %d\n",
+ NG,MG,KG,P[0],P[1],(flags&FFT5D_REALCOMPLEX)>0,(flags&FFT5D_BACKWARD)>0,(flags&FFT5D_ORDER_YZ)>0,(flags&FFT5D_DEBUG)>0);
+ /* The check below is not correct, one prime factor 11 or 13 is ok.
+ if (fft5d_fmax(fft5d_fmax(lpfactor(NG),lpfactor(MG)),lpfactor(KG))>7) {
+ printf("WARNING: FFT very slow with prime factors larger 7\n");
+ printf("Change FFT size or in case you cannot change it look at\n");
+ printf("http://www.fftw.org/fftw3_doc/Generating-your-own-code.html\n");
+ }
+ */
+ }
+
+ if (NG==0 || MG==0 || KG==0) {
+ if (bMaster) printf("FFT5D: FATAL: Datasize cannot be zero in any dimension\n");
+ return 0;
+ }
+
+ rNG=NG;rMG=MG;rKG=KG;
+
+ if (flags&FFT5D_REALCOMPLEX) {
+ if (!(flags&FFT5D_BACKWARD)) NG = NG/2+1;
+ else {
+ if (!(flags&FFT5D_ORDER_YZ)) MG=MG/2+1;
+ else KG=KG/2+1;
+ }
+ }
+
+
+ /*for transpose we need to know the size for each processor not only our own size*/
+
+ N0 = (int*)malloc(P[0]*sizeof(int)); N1 = (int*)malloc(P[1]*sizeof(int));
+ M0 = (int*)malloc(P[0]*sizeof(int)); M1 = (int*)malloc(P[1]*sizeof(int));
+ K0 = (int*)malloc(P[0]*sizeof(int)); K1 = (int*)malloc(P[1]*sizeof(int));
+ oN0 = (int*)malloc(P[0]*sizeof(int));oN1 = (int*)malloc(P[1]*sizeof(int));
+ oM0 = (int*)malloc(P[0]*sizeof(int));oM1 = (int*)malloc(P[1]*sizeof(int));
+ oK0 = (int*)malloc(P[0]*sizeof(int));oK1 = (int*)malloc(P[1]*sizeof(int));
+
+ for (i=0;i<P[0];i++)
+ {
+ #define EVENDIST
+ #ifndef EVENDIST
+ oN0[i]=i*ceil((double)NG/P[0]);
+ oM0[i]=i*ceil((double)MG/P[0]);
+ oK0[i]=i*ceil((double)KG/P[0]);
+ #else
+ oN0[i]=(NG*i)/P[0];
+ oM0[i]=(MG*i)/P[0];
+ oK0[i]=(KG*i)/P[0];
+ #endif
+ }
+ for (i=0;i<P[1];i++)
+ {
+ #ifndef EVENDIST
+ oN1[i]=i*ceil((double)NG/P[1]);
+ oM1[i]=i*ceil((double)MG/P[1]);
+ oK1[i]=i*ceil((double)KG/P[1]);
+ #else
+ oN1[i]=(NG*i)/P[1];
+ oM1[i]=(MG*i)/P[1];
+ oK1[i]=(KG*i)/P[1];
+ #endif
+ }
+ for (i=0;i<P[0]-1;i++)
+ {
+ N0[i]=oN0[i+1]-oN0[i];
+ M0[i]=oM0[i+1]-oM0[i];
+ K0[i]=oK0[i+1]-oK0[i];
+ }
+ N0[P[0]-1]=NG-oN0[P[0]-1];
+ M0[P[0]-1]=MG-oM0[P[0]-1];
+ K0[P[0]-1]=KG-oK0[P[0]-1];
+ for (i=0;i<P[1]-1;i++)
+ {
+ N1[i]=oN1[i+1]-oN1[i];
+ M1[i]=oM1[i+1]-oM1[i];
+ K1[i]=oK1[i+1]-oK1[i];
+ }
+ N1[P[1]-1]=NG-oN1[P[1]-1];
+ M1[P[1]-1]=MG-oM1[P[1]-1];
+ K1[P[1]-1]=KG-oK1[P[1]-1];
+
+ /* for step 1-3 the local N,M,K sizes of the transposed system
+ C: contiguous dimension, and nP: number of processor in subcommunicator
+ for that step */
+
+
+ pM[0] = M0[prank[0]];
+ oM[0] = oM0[prank[0]];
+ pK[0] = K1[prank[1]];
+ oK[0] = oK1[prank[1]];
+ C[0] = NG;
+ rC[0] = rNG;
+ if (!(flags&FFT5D_ORDER_YZ)) {
+ N[0] = vmax(N1,P[1]);
+ M[0] = M0[prank[0]];
+ K[0] = vmax(K1,P[1]);
+ pN[0] = N1[prank[1]];
+ iNout[0] = N1;
+ oNout[0] = oN1;
+ nP[0] = P[1];
+ C[1] = KG;
+ rC[1] =rKG;
+ N[1] = vmax(K0,P[0]);
+ pN[1] = K0[prank[0]];
+ iNin[1] = K1;
+ oNin[1] = oK1;
+ iNout[1] = K0;
+ oNout[1] = oK0;
+ M[1] = vmax(M0,P[0]);
+ pM[1] = M0[prank[0]];
+ oM[1] = oM0[prank[0]];
+ K[1] = N1[prank[1]];
+ pK[1] = N1[prank[1]];
+ oK[1] = oN1[prank[1]];
+ nP[1] = P[0];
+ C[2] = MG;
+ rC[2] = rMG;
+ iNin[2] = M0;
+ oNin[2] = oM0;
+ M[2] = vmax(K0,P[0]);
+ pM[2] = K0[prank[0]];
+ oM[2] = oK0[prank[0]];
+ K[2] = vmax(N1,P[1]);
+ pK[2] = N1[prank[1]];
+ oK[2] = oN1[prank[1]];
+ free(N0); free(oN0); /*these are not used for this order*/
+ free(M1); free(oM1); /*the rest is freed in destroy*/
+ } else {
+ N[0] = vmax(N0,P[0]);
+ M[0] = vmax(M0,P[0]);
+ K[0] = K1[prank[1]];
+ pN[0] = N0[prank[0]];
+ iNout[0] = N0;
+ oNout[0] = oN0;
+ nP[0] = P[0];
+ C[1] = MG;
+ rC[1] =rMG;
+ N[1] = vmax(M1,P[1]);
+ pN[1] = M1[prank[1]];
+ iNin[1] = M0;
+ oNin[1] = oM0;
+ iNout[1] = M1;
+ oNout[1] = oM1;
+ M[1] = N0[prank[0]];
+ pM[1] = N0[prank[0]];
+ oM[1] = oN0[prank[0]];
+ K[1] = vmax(K1,P[1]);
+ pK[1] = K1[prank[1]];
+ oK[1] = oK1[prank[1]];
+ nP[1] = P[1];
+ C[2] = KG;
+ rC[2] = rKG;
+ iNin[2] = K1;
+ oNin[2] = oK1;
+ M[2] = vmax(N0,P[0]);
+ pM[2] = N0[prank[0]];
+ oM[2] = oN0[prank[0]];
+ K[2] = vmax(M1,P[1]);
+ pK[2] = M1[prank[1]];
+ oK[2] = oM1[prank[1]];
+ free(N1); free(oN1); /*these are not used for this order*/
+ free(K0); free(oK0); /*the rest is freed in destroy*/
+ }
+
+ /*
+ Difference between x-y-z regarding 2d decomposition is whether they are
+ distributed along axis 1, 2 or both
+ */
+
+ /* int lsize = fmax(N[0]*M[0]*K[0]*nP[0],N[1]*M[1]*K[1]*nP[1]); */
+ lsize = fft5d_fmax(N[0]*M[0]*K[0]*nP[0],fft5d_fmax(N[1]*M[1]*K[1]*nP[1],C[2]*M[2]*K[2]));
+ /* int lsize = fmax(C[0]*M[0]*K[0],fmax(C[1]*M[1]*K[1],C[2]*M[2]*K[2])); */
+ if (!(flags&FFT5D_NOMALLOC)) {
+ lin = (t_complex*)gmx_calloc_aligned(sizeof(t_complex) * lsize);
+ lout = (t_complex*)gmx_calloc_aligned(sizeof(t_complex) * lsize);
+ } else {
+ lin = *rlin;
+ lout = *rlout;
+ }
+
+ plan = (fft5d_plan)calloc(1,sizeof(struct fft5d_plan_t));
+
+
+#ifdef FFT5D_THREADS /*requires fftw with openmp and openmp*/
+ FFTW(init_threads)();
+ int nthreads;
+ #pragma omp parallel
+ {
+ #pragma omp master
+ {
+ nthreads = omp_get_num_threads();
+ }
+ }
+ printf("Running on %d threads\n",nthreads);
+ FFTW(plan_with_nthreads)(nthreads);
+
+#endif
+
+#ifdef GMX_FFT_FFTW3 /*if not FFTW - then we don't do a 3d plan but insead only 1D plans */
+ if ((!(flags&FFT5D_INPLACE)) && (!(P[0]>1 || P[1]>1))) { /*don't do 3d plan in parallel or if in_place requested */
+ int fftwflags=FFTW_DESTROY_INPUT;
+ fftw_iodim dims[3];
+ int inNG=NG,outMG=MG,outKG=KG;
+
+ FFTW_LOCK;
+ if (!(flags&FFT5D_NOMEASURE)) fftwflags|=FFTW_MEASURE;
+ if (flags&FFT5D_REALCOMPLEX) {
+ if (!(flags&FFT5D_BACKWARD)) { /*input pointer is not complex*/
+ inNG*=2;
+ } else { /*output pointer is not complex*/
+ if (!(flags&FFT5D_ORDER_YZ)) outMG*=2;
+ else outKG*=2;
+ }
+ }
+
+ if (!(flags&FFT5D_BACKWARD)) {
+ dims[0].n = KG;
+ dims[1].n = MG;
+ dims[2].n = rNG;
+
+ dims[0].is = inNG*MG; /*N M K*/
+ dims[1].is = inNG;
+ dims[2].is = 1;
+ if (!(flags&FFT5D_ORDER_YZ)) {
+ dims[0].os = MG; /*M K N*/
+ dims[1].os = 1;
+ dims[2].os = MG*KG;
+ } else {
+ dims[0].os = 1; /*K N M*/
+ dims[1].os = KG*NG;
+ dims[2].os = KG;
+ }
+ } else {
+ if (!(flags&FFT5D_ORDER_YZ)) {
+ dims[0].n = NG;
+ dims[1].n = KG;
+ dims[2].n = rMG;
+
+ dims[0].is = 1;
+ dims[1].is = NG*MG;
+ dims[2].is = NG;
+
+ dims[0].os = outMG*KG;
+ dims[1].os = outMG;
+ dims[2].os = 1;
+ } else {
+ dims[0].n = MG;
+ dims[1].n = NG;
+ dims[2].n = rKG;
+
+ dims[0].is = NG;
+ dims[1].is = 1;
+ dims[2].is = NG*MG;
+
+ dims[0].os = outKG*NG;
+ dims[1].os = outKG;
+ dims[2].os = 1;
+ }
+ }
+ if ((flags&FFT5D_REALCOMPLEX) && !(flags&FFT5D_BACKWARD)) {
+ plan->p3d = FFTW(plan_guru_dft_r2c)(/*rank*/ 3, dims,
+ /*howmany*/ 0, /*howmany_dims*/0 ,
+ (real*)lin, (FFTW(complex) *)lout,
+ /*flags*/ fftwflags);
+ } else if ((flags&FFT5D_REALCOMPLEX) && (flags&FFT5D_BACKWARD)) {
+ plan->p3d = FFTW(plan_guru_dft_c2r)(/*rank*/ 3, dims,
+ /*howmany*/ 0, /*howmany_dims*/0 ,
+ (FFTW(complex) *)lin, (real*)lout,
+ /*flags*/ fftwflags);
+ } else {
+ plan->p3d = FFTW(plan_guru_dft)(/*rank*/ 3, dims,
+ /*howmany*/ 0, /*howmany_dims*/0 ,
+ (FFTW(complex) *)lin, (FFTW(complex) *)lout,
+ /*sign*/ (flags&FFT5D_BACKWARD)?1:-1, /*flags*/ fftwflags);
+ }
+ FFTW_UNLOCK;
+ }
+ if (!plan->p3d) { /* for decomposition and if 3d plan did not work */
+#endif /* GMX_FFT_FFTW3 */
+ for (s=0;s<3;s++) {
+ if (debug)
+ {
+ fprintf(debug,"FFT5D: Plan s %d rC %d M %d pK %d C %d lsize %d\n",
+ s,rC[s],M[s],pK[s],C[s],lsize);
+ }
+ if ((flags&FFT5D_REALCOMPLEX) && ((!(flags&FFT5D_BACKWARD) && s==0) || ((flags&FFT5D_BACKWARD) && s==2))) {
+ gmx_fft_init_many_1d_real( &plan->p1d[s], rC[s], pM[s]*pK[s], (flags&FFT5D_NOMEASURE)?GMX_FFT_FLAG_CONSERVATIVE:0 );
+ } else {
+ gmx_fft_init_many_1d ( &plan->p1d[s], C[s], pM[s]*pK[s], (flags&FFT5D_NOMEASURE)?GMX_FFT_FLAG_CONSERVATIVE:0 );
+ }
+ }
+#ifdef GMX_FFT_FFTW3
+ }
+#endif
+ if ((flags&FFT5D_ORDER_YZ)) { /*plan->cart is in the order of transposes */
+ plan->cart[0]=comm[0]; plan->cart[1]=comm[1];
+ } else {
+ plan->cart[1]=comm[0]; plan->cart[0]=comm[1];
+ }
+#ifdef FFT5D_MPI_TRANSPOSE
+ FFTW_LOCK
+ for (s=0;s<2;s++) {
+ if ((s==0 && !(flags&FFT5D_ORDER_YZ)) || (s==1 && (flags&FFT5D_ORDER_YZ)))
+ plan->mpip[s] = FFTW(mpi_plan_many_transpose)(nP[s], nP[s], N[s]*K[s]*pM[s]*2, 1, 1, (real*)lin, (real*)lout, plan->cart[s], FFTW_PATIENT);
+ else
+ plan->mpip[s] = FFTW(mpi_plan_many_transpose)(nP[s], nP[s], N[s]*pK[s]*M[s]*2, 1, 1, (real*)lin, (real*)lout, plan->cart[s], FFTW_PATIENT);
+ }
+ FFTW_UNLOCK
+#endif
+
+
+ plan->lin=lin;
+ plan->lout=lout;
+
+ plan->NG=NG;plan->MG=MG;plan->KG=KG;
+
+ for (s=0;s<3;s++) {
+ plan->N[s]=N[s];plan->M[s]=M[s];plan->K[s]=K[s];plan->pN[s]=pN[s];plan->pM[s]=pM[s];plan->pK[s]=pK[s];
+ plan->oM[s]=oM[s];plan->oK[s]=oK[s];
+ plan->C[s]=C[s];plan->rC[s]=rC[s];
+ plan->iNin[s]=iNin[s];plan->oNin[s]=oNin[s];plan->iNout[s]=iNout[s];plan->oNout[s]=oNout[s];
+ }
+ for (s=0;s<2;s++) {
+ plan->P[s]=nP[s];plan->coor[s]=prank[s];
+ }
+
+/* plan->fftorder=fftorder;
+ plan->direction=direction;
+ plan->realcomplex=realcomplex;
+*/
+ plan->flags=flags;
+ *rlin=lin;
+ *rlout=lout;
+ return plan;
+}
+
+
+enum order {
+ XYZ,
+ XZY,
+ YXZ,
+ YZX,
+ ZXY,
+ ZYX
+};
+
+
+
+/*here x,y,z and N,M,K is in rotated coordinate system!!
+ x (and N) is mayor (consecutive) dimension, y (M) middle and z (K) major
+ maxN,maxM,maxK is max size of local data
+ pN, pM, pK is local size specific to current processor (only different to max if not divisible)
+ NG, MG, KG is size of global data*/
+static void splitaxes(t_complex* lout,const t_complex* lin,
+ int maxN,int maxM,int maxK, int pN, int pM, int pK,
+ int P,int NG,int *N, int* oN) {
+ int x,y,z,i;
+ int in_i,out_i,in_z,out_z,in_y,out_y;
+
+ for (i=0;i<P;i++) { /*index cube along long axis*/
+ in_i = i*maxN*maxM*maxK;
+ out_i = oN[i];
+ for (z=0;z<pK;z++) { /*3. z l*/
+ in_z = in_i + z*maxN*maxM;
+ out_z = out_i + z*NG*pM;
+ for (y=0;y<pM;y++) { /*2. y k*/
+ in_y = in_z + y*maxN;
+ out_y = out_z + y*NG;
+ for (x=0;x<N[i];x++) { /*1. x j*/
+ lout[in_y+x] = lin[out_y+x];
+ /*after split important that each processor chunk i has size maxN*maxM*maxK and thus being the same size*/
+ /*before split data contiguos - thus if different processor get different amount oN is different*/
+ }
+ }
+ }
+ }
+}
+
+/*make axis contiguous again (after AllToAll) and also do local transpose*/
+/*transpose mayor and major dimension
+ variables see above
+ the major, middle, minor order is only correct for x,y,z (N,M,K) for the input
+ N,M,K local dimensions
+ KG global size*/
+static void joinAxesTrans13(t_complex* lin,const t_complex* lout,
+ int maxN,int maxM,int maxK,int pN, int pM, int pK,
+ int P,int KG, int* K, int* oK)
+{
+ int i,x,y,z;
+ int in_i,out_i,in_x,out_x,in_z,out_z;
+
+ for (i=0;i<P;i++) { /*index cube along long axis*/
+ in_i = oK[i];
+ out_i = i*maxM*maxN*maxK;
+ for (x=0;x<pN;x++) { /*1.j*/
+ in_x = in_i + x*KG*pM;
+ out_x = out_i + x;
+ for (z=0;z<K[i];z++) { /*3.l*/
+ in_z = in_x + z;
+ out_z = out_x + z*maxM*maxN;
+ for (y=0;y<pM;y++) { /*2.k*/
+ lin[in_z+y*KG] = lout[out_z+y*maxN];
+ }
+ }
+ }
+ }
+}
+
+/*make axis contiguous again (after AllToAll) and also do local transpose
+ tranpose mayor and middle dimension
+ variables see above
+ the minor, middle, major order is only correct for x,y,z (N,M,K) for the input
+ N,M,K local size
+ MG, global size*/
+static void joinAxesTrans12(t_complex* lin,const t_complex* lout,int maxN,int maxM,int maxK,int pN, int pM, int pK,
+ int P,int MG, int* M, int* oM) {
+ int i,z,y,x;
+ int in_i,out_i,in_z,out_z,in_x,out_x;
+
+ for (i=0;i<P;i++) { /*index cube along long axis*/
+ in_i = oM[i];
+ out_i = i*maxM*maxN*maxK;
+ for (z=0;z<pK;z++) {
+ in_z = in_i + z*MG*pN;
+ out_z = out_i + z*maxM*maxN;
+ for (x=0;x<pN;x++) {
+ in_x = in_z + x*MG;
+ out_x = out_z + x;
+ for (y=0;y<M[i];y++) {
+ lin[in_x+y] = lout[out_x+y*maxN];
+ }
+ }
+ }
+ }
+}
+
+
+static void rotate(int x[]) {
+ int t=x[0];
+/* x[0]=x[2];
+ x[2]=x[1];
+ x[1]=t;*/
+ x[0]=x[1];
+ x[1]=x[2];
+ x[2]=t;
+}
+
+/*compute the offset to compare or print transposed local data in original input coordinates
+ xs matrix dimension size, xl dimension length, xc decomposition offset
+ s: step in computation = number of transposes*/
+static void compute_offsets(fft5d_plan plan, int xs[], int xl[], int xc[], int NG[], int s) {
+/* int direction = plan->direction;
+ int fftorder = plan->fftorder;*/
+
+ int o;
+ int pos[3],i;
+ int *pM=plan->pM, *pK=plan->pK, *oM=plan->oM, *oK=plan->oK,
+ *C=plan->C, *rC=plan->rC;
+
+ NG[0]=plan->NG;NG[1]=plan->MG;NG[2]=plan->KG;
+
+ if (!(plan->flags&FFT5D_ORDER_YZ)) {
+ switch (s) {
+ case 0: o=XYZ; break;
+ case 1: o=ZYX; break;
+ case 2: o=YZX; break;
+ default: assert(0);
+ }
+ } else {
+ switch (s) {
+ case 0: o=XYZ; break;
+ case 1: o=YXZ; break;
+ case 2: o=ZXY; break;
+ default: assert(0);
+ }
+ }
+
+ switch (o) {
+ case XYZ:pos[0]=1;pos[1]=2;pos[2]=3;break;
+ case XZY:pos[0]=1;pos[1]=3;pos[2]=2;break;
+ case YXZ:pos[0]=2;pos[1]=1;pos[2]=3;break;
+ case YZX:pos[0]=3;pos[1]=1;pos[2]=2;break;
+ case ZXY:pos[0]=2;pos[1]=3;pos[2]=1;break;
+ case ZYX:pos[0]=3;pos[1]=2;pos[2]=1;break;
+ }
+ /*if (debug) printf("pos: %d %d %d\n",pos[0],pos[1],pos[2]);*/
+
+ /*xs, xl give dimension size and data length in local transposed coordinate system
+ for 0(/1/2): x(/y/z) in original coordinate system*/
+ for (i=0;i<3;i++) {
+ switch (pos[i]) {
+ case 1: xs[i]=1; xc[i]=0; xl[i]=C[s];break;
+ case 2: xs[i]=C[s]; xc[i]=oM[s]; xl[i]=pM[s];break;
+ case 3: xs[i]=C[s]*pM[s];xc[i]=oK[s]; xl[i]=pK[s];break;
+ }
+ }
+ /*input order is different for test program to match FFTW order
+ (important for complex to real)*/
+ if (plan->flags&FFT5D_BACKWARD) {
+ rotate(xs);
+ rotate(xl);
+ rotate(xc);
+ rotate(NG);
+ if (plan->flags&FFT5D_ORDER_YZ) {
+ rotate(xs);
+ rotate(xl);
+ rotate(xc);
+ rotate(NG);
+ }
+ }
+ if (plan->flags&FFT5D_REALCOMPLEX && ((!(plan->flags&FFT5D_BACKWARD) && s==0) || (plan->flags&FFT5D_BACKWARD && s==2))) {
+ xl[0] = rC[s];
+ }
+}
+
+static void print_localdata(const t_complex* lin, const char* txt, int s, fft5d_plan plan) {
+ int x,y,z,l;
+ int *coor = plan->coor;
+ int xs[3],xl[3],xc[3],NG[3];
+ int ll=(plan->flags&FFT5D_REALCOMPLEX)?1:2;
+ compute_offsets(plan,xs,xl,xc,NG,s);
+ fprintf(debug,txt,coor[0],coor[1],s);
+ /*printf("xs: %d %d %d, xl: %d %d %d\n",xs[0],xs[1],xs[2],xl[0],xl[1],xl[2]);*/
+ for(z=0;z<xl[2];z++) {
+ for(y=0;y<xl[1];y++) {
+ fprintf(debug,"%d %d: ",coor[0],coor[1]);
+ for (x=0;x<xl[0];x++) {
+ for (l=0;l<ll;l++) {
+ fprintf(debug,"%f ",((real*)lin)[(z*xs[2]+y*xs[1])*2+(x*xs[0])*ll+l]);
+ }
+ fprintf(debug,",");
+ }
+ fprintf(debug,"\n");
+ }
+ }
+}
+
+void fft5d_execute(fft5d_plan plan,fft5d_time times) {
+ t_complex *lin = plan->lin;
+ t_complex *lout = plan->lout;
+
+ gmx_fft_t *p1d=plan->p1d;
+#ifdef FFT5D_MPI_TRANSPOSE
+ FFTW(plan) *mpip=plan->mpip;
+#endif
+#ifdef GMX_MPI
+ MPI_Comm *cart=plan->cart;
+#endif
+
+ double time_fft=0,time_local=0,time_mpi[2]={0},time=0;
+ int *N=plan->N,*M=plan->M,*K=plan->K,*pN=plan->pN,*pM=plan->pM,*pK=plan->pK,
+ *C=plan->C,*P=plan->P,**iNin=plan->iNin,**oNin=plan->oNin,**iNout=plan->iNout,**oNout=plan->oNout;
+ int s=0;
+
+
+#ifdef GMX_FFT_FFTW3
+ if (plan->p3d) {
+ if (times!=0)
+ time=MPI_Wtime();
+ FFTW(execute)(plan->p3d);
+ if (times!=0)
+ times->fft+=MPI_Wtime()-time;
+ return;
+ }
+#endif
+
+ /*lin: x,y,z*/
+ if (plan->flags&FFT5D_DEBUG) print_localdata(lin, "%d %d: copy in lin\n", s, plan);
+ for (s=0;s<2;s++) {
+ if (times!=0)
+ time=MPI_Wtime();
+
+ if ((plan->flags&FFT5D_REALCOMPLEX) && !(plan->flags&FFT5D_BACKWARD) && s==0) {
+ gmx_fft_many_1d_real(p1d[s],(plan->flags&FFT5D_BACKWARD)?GMX_FFT_COMPLEX_TO_REAL:GMX_FFT_REAL_TO_COMPLEX,lin,lout);
+ } else {
+ gmx_fft_many_1d( p1d[s],(plan->flags&FFT5D_BACKWARD)?GMX_FFT_BACKWARD:GMX_FFT_FORWARD, lin,lout);
+ }
+ if (times!=0)
+ time_fft+=MPI_Wtime()-time;
+
+ if (plan->flags&FFT5D_DEBUG) print_localdata(lout, "%d %d: FFT %d\n", s, plan);
+
+#ifdef GMX_MPI
+ if (GMX_PARALLEL_ENV_INITIALIZED && cart[s] !=0 && P[s]>1 )
+ {
+ if (times!=0)
+ time=MPI_Wtime();
+ /*prepare for AllToAll
+ 1. (most outer) axes (x) is split into P[s] parts of size N[s]
+ for sending*/
+ splitaxes(lin,lout,N[s],M[s],K[s], pN[s],pM[s],pK[s],P[s],C[s],iNout[s],oNout[s]);
+
+ if (times!=0)
+ {
+ time_local+=MPI_Wtime()-time;
+
+ /*send, recv*/
+ time=MPI_Wtime();
+ }
+
+#ifdef FFT5D_MPI_TRANSPOSE
+ FFTW(execute)(mpip[s]);
+#else
+ if ((s==0 && !(plan->flags&FFT5D_ORDER_YZ)) || (s==1 && (plan->flags&FFT5D_ORDER_YZ)))
+ MPI_Alltoall(lin,N[s]*pM[s]*K[s]*sizeof(t_complex)/sizeof(real),GMX_MPI_REAL,lout,N[s]*pM[s]*K[s]*sizeof(t_complex)/sizeof(real),GMX_MPI_REAL,cart[s]);
+ else
+ MPI_Alltoall(lin,N[s]*M[s]*pK[s]*sizeof(t_complex)/sizeof(real),GMX_MPI_REAL,lout,N[s]*M[s]*pK[s]*sizeof(t_complex)/sizeof(real),GMX_MPI_REAL,cart[s]);
+#endif /*FFT5D_MPI_TRANSPOSE*/
+ if (times!=0)
+ time_mpi[s]=MPI_Wtime()-time;
+ }
+#endif /*GMX_MPI*/
+
+
+ if (times!=0)
+ time=MPI_Wtime();
+ /*bring back in matrix form
+ thus make new 1. axes contiguos
+ also local transpose 1 and 2/3 */
+ if ((s==0 && !(plan->flags&FFT5D_ORDER_YZ)) || (s==1 && (plan->flags&FFT5D_ORDER_YZ)))
+ joinAxesTrans13(lin,lout,N[s],pM[s],K[s],pN[s],pM[s],pK[s],P[s],C[s+1],iNin[s+1],oNin[s+1]);
+ else
+ joinAxesTrans12(lin,lout,N[s],M[s],pK[s],pN[s],pM[s],pK[s],P[s],C[s+1],iNin[s+1],oNin[s+1]);
+ if (times!=0)
+ time_local+=MPI_Wtime()-time;
+
+ if (plan->flags&FFT5D_DEBUG) print_localdata(lin, "%d %d: tranposed %d\n", s+1, plan);
+
+ /*if (debug) print_localdata(lin, "%d %d: transposed x-z\n", N1, M0, K, ZYX, coor);*/
+ }
+
+ if (times!=0)
+ time=MPI_Wtime();
+ if (plan->flags&FFT5D_INPLACE) lout=lin;
+ if ((plan->flags&FFT5D_REALCOMPLEX) && (plan->flags&FFT5D_BACKWARD)) {
+ gmx_fft_many_1d_real(p1d[s],(plan->flags&FFT5D_BACKWARD)?GMX_FFT_COMPLEX_TO_REAL:GMX_FFT_REAL_TO_COMPLEX,lin,lout);
+ } else {
+ gmx_fft_many_1d( p1d[s],(plan->flags&FFT5D_BACKWARD)?GMX_FFT_BACKWARD:GMX_FFT_FORWARD, lin,lout);
+ }
+
+ if (times!=0)
+ time_fft+=MPI_Wtime()-time;
+ if (plan->flags&FFT5D_DEBUG) print_localdata(lout, "%d %d: FFT %d\n", s, plan);
+ /*if (debug) print_localdata(lout, "%d %d: FFT in y\n", N1, M, K0, YZX, coor);*/
+
+ if (times!=0) {
+ times->fft+=time_fft;
+ times->local+=time_local;
+ times->mpi2+=time_mpi[1];
+ times->mpi1+=time_mpi[0];
+ }
+}
+
+void fft5d_destroy(fft5d_plan plan) {
+ int s;
+ for (s=0;s<3;s++) {
+ gmx_many_fft_destroy(plan->p1d[s]);
+ if (plan->iNin[s]) {
+ free(plan->iNin[s]);
+ plan->iNin[s]=0;
+ }
+ if (plan->oNin[s]) {
+ free(plan->oNin[s]);
+ plan->oNin[s]=0;
+ }
+ if (plan->iNout[s]) {
+ free(plan->iNout[s]);
+ plan->iNout[s]=0;
+ }
+ if (plan->oNout[s]) {
+ free(plan->oNout[s]);
+ plan->oNout[s]=0;
+ }
+ }
+#ifdef GMX_FFT_FFTW3
+ FFTW_LOCK;
+#ifdef FFT5D_MPI_TRANSPOS
+ for (s=0;s<2;s++)
+ FFTW(destroy_plan)(plan->mpip[s]);
+#endif /* FFT5D_MPI_TRANSPOS */
+#endif /* GMX_FFT_FFTW3 */
+
+ /*We can't free lin/lout here - is allocated by gmx_calloc_aligned which can't be freed*/
+
+
+#ifdef FFT5D_THREADS
+ FFTW(cleanup_threads)();
+#endif
+
+ free(plan);
+}
+
+/*Is this better than direct access of plan? enough data?
+ here 0,1 reference divided by which processor grid dimension (not FFT step!)*/
+void fft5d_local_size(fft5d_plan plan,int* N1,int* M0,int* K0,int* K1,int** coor) {
+ *N1=plan->N[0];
+ *M0=plan->M[0];
+ *K1=plan->K[0];
+ *K0=plan->N[1];
+
+ *coor=plan->coor;
+}
+
+
+/*same as fft5d_plan_3d but with cartesian coordinator and automatic splitting
+ of processor dimensions*/
+fft5d_plan fft5d_plan_3d_cart(int NG, int MG, int KG, MPI_Comm comm, int P0, int flags, t_complex** rlin, t_complex** rlout) {
+ MPI_Comm cart[2]={0};
+#ifdef GMX_MPI
+ int size=1,prank=0;
+ int P[2];
+ int coor[2];
+ int wrap[]={0,0};
+ MPI_Comm gcart;
+ int rdim1[] = {0,1}, rdim2[] = {1,0};
+
+ MPI_Comm_size(comm,&size);
+ MPI_Comm_rank(comm,&prank);
+
+ if (P0==0) P0 = lfactor(size);
+ if (size%P0!=0) {
+ if (prank==0) printf("FFT5D: WARNING: Number of processors %d not evenly dividable by %d\n",size,P0);
+ P0 = lfactor(size);
+ }
+
+ P[0] = P0; P[1]=size/P0; /*number of processors in the two dimensions*/
+
+ /*Difference between x-y-z regarding 2d decomposition is whether they are
+ distributed along axis 1, 2 or both*/
+
+ MPI_Cart_create(comm,2,P,wrap,1,&gcart); /*parameter 4: value 1: reorder*/
+ MPI_Cart_get(gcart,2,P,wrap,coor);
+ MPI_Cart_sub(gcart, rdim1 , &cart[0]);
+ MPI_Cart_sub(gcart, rdim2 , &cart[1]);
+#endif
+ return fft5d_plan_3d(NG, MG, KG, cart, flags, rlin, rlout);
+}
+
+
+
+/*prints in original coordinate system of data (as the input to FFT)*/
+void fft5d_compare_data(const t_complex* lin, const t_complex* in, fft5d_plan plan, int bothLocal, int normalize) {
+ int xs[3],xl[3],xc[3],NG[3];
+ int x,y,z,l;
+ int *coor = plan->coor;
+ int ll=2; /*compare ll values per element (has to be 2 for complex)*/
+ if (plan->flags&FFT5D_REALCOMPLEX && plan->flags&FFT5D_BACKWARD)
+ {
+ ll=1;
+ }
+
+ compute_offsets(plan,xs,xl,xc,NG,2);
+ if (plan->flags&FFT5D_DEBUG) printf("Compare2\n");
+ for (z=0;z<xl[2];z++) {
+ for(y=0;y<xl[1];y++) {
+ if (plan->flags&FFT5D_DEBUG) printf("%d %d: ",coor[0],coor[1]);
+ for (x=0;x<xl[0];x++) {
+ for (l=0;l<ll;l++) { /*loop over real/complex parts*/
+ real a,b;
+ a=((real*)lin)[(z*xs[2]+y*xs[1])*2+x*xs[0]*ll+l];
+ if (normalize) a/=plan->rC[0]*plan->rC[1]*plan->rC[2];
+ if (!bothLocal)
+ b=((real*)in)[((z+xc[2])*NG[0]*NG[1]+(y+xc[1])*NG[0])*2+(x+xc[0])*ll+l];
+ else
+ b=((real*)in)[(z*xs[2]+y*xs[1])*2+x*xs[0]*ll+l];
+ if (plan->flags&FFT5D_DEBUG) {
+ printf("%f %f, ",a,b);
+ } else {
+ if (fabs(a-b)>2*NG[0]*NG[1]*NG[2]*GMX_REAL_EPS) {
+ printf("result incorrect on %d,%d at %d,%d,%d: FFT5D:%f reference:%f\n",coor[0],coor[1],x,y,z,a,b);
+ }
+/* assert(fabs(a-b)<2*NG[0]*NG[1]*NG[2]*GMX_REAL_EPS);*/
+ }
+ }
+ if (plan->flags&FFT5D_DEBUG) printf(",");
+ }
+ if (plan->flags&FFT5D_DEBUG) printf("\n");
+ }
+ }
+
+}
+
--- /dev/null
+#ifndef FFT5D_H_
+#define FFT5D_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef NOGMX
+/*#define GMX_MPI*/
+/*#define GMX_FFT_FFTW3*/
+FILE* debug;
+#endif
+
+#include <types/commrec.h>
+#include "gmxcomplex.h"
+#include "gmx_fft.h"
+
+#ifndef GMX_LIB_MPI
+double MPI_Wtime();
+#endif
+
+/*currently only special optimization for FFTE*/
+#ifdef GMX_FFT_FFTW3
+#include <fftw3.h>
+#endif
+
+#ifndef GMX_DOUBLE
+#define FFTW(x) fftwf_##x
+#else
+#define FFTW(x) fftw_##x
+#endif
+
+struct fft5d_time_t {
+ double fft,local,mpi1,mpi2;
+};
+typedef struct fft5d_time_t *fft5d_time;
+
+typedef enum fft5d_flags_t {
+ FFT5D_ORDER_YZ=1,
+ FFT5D_BACKWARD=2,
+ FFT5D_REALCOMPLEX=4,
+ FFT5D_DEBUG=8,
+ FFT5D_NOMEASURE=16,
+ FFT5D_INPLACE=32,
+ FFT5D_NOMALLOC=64
+} fft5d_flags;
+
+struct fft5d_plan_t {
+ t_complex *lin;
+ t_complex *lout;
+ gmx_fft_t p1d[3]; /*1D plans*/
+#ifdef GMX_FFT_FFTW3
+ FFTW(plan) p2d; /*2D plan: used for 1D decomposition if FFT supports transposed output*/
+ FFTW(plan) p3d; /*3D plan: used for 0D decomposition if FFT supports transposed output*/
+ FFTW(plan) mpip[2];
+#endif
+ MPI_Comm cart[2];
+
+ int N[3],M[3],K[3]; /*local length in transposed coordinate system (if not divisisable max)*/
+ int pN[3],pM[3], pK[3]; /*local length - not max but length for this processor*/
+ int oM[3],oK[3]; /*offset for current processor*/
+ int *iNin[3],*oNin[3],*iNout[3],*oNout[3]; /*size for each processor (if divisisable=max) for out(=split)
+ and in (=join) and offsets in transposed coordinate system*/
+ int C[3],rC[3]; /*global length (of the one global axes) */
+ /* C!=rC for real<->complex. then C=rC/2 but with potential padding*/
+ int P[2]; /*size of processor grid*/
+/* int fftorder;*/
+/* int direction;*/
+/* int realcomplex;*/
+ int flags;
+ /*int N0,N1,M0,M1,K0,K1;*/
+ int NG,MG,KG;
+ /*int P[2];*/
+ int coor[2];
+};
+
+typedef struct fft5d_plan_t *fft5d_plan;
+
+void fft5d_execute(fft5d_plan plan,fft5d_time times);
+fft5d_plan fft5d_plan_3d(int N, int M, int K, MPI_Comm comm[2], int flags, t_complex** lin, t_complex** lin2);
+void fft5d_local_size(fft5d_plan plan,int* N1,int* M0,int* K0,int* K1,int** coor);
+void fft5d_destroy(fft5d_plan plan);
+fft5d_plan fft5d_plan_3d_cart(int N, int M, int K, MPI_Comm comm, int P0, int flags, t_complex** lin, t_complex** lin2);
+void fft5d_compare_data(const t_complex* lin, const t_complex* in, fft5d_plan plan, int bothLocal, int normarlize);
+#endif /*FFTLIB_H_*/
+++ /dev/null
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- * This source code is part of
- *
- * G R O M A C S
- *
- * GROningen MAchine for Chemical Simulations
- *
- * VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- *
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-/* This file is completely threadsafe - keep it that way! */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "typedefs.h"
-#include "futil.h"
-#include "smalloc.h"
-#include "futil.h"
-#include "macros.h"
-#include "network.h"
-#include "fftgrid.h"
-#include "gmx_fft.h"
-#include "gmx_parallel_3dfft.h"
-#include "gmxfio.h"
-
-
-#ifdef GMX_MPI
-static void print_parfft(FILE *fp,char *title,t_parfft *pfft)
-{
- fprintf(fp,"PARALLEL FFT DATA:\n"
- " local_nx: %3d local_x_start: %3d\n"
- " local_ny_after_transpose: %3d local_y_start_after_transpose %3d\n",
- pfft->local_nx,pfft->local_x_start,pfft->local_ny_after_transpose,
- pfft->local_y_start_after_transpose);
-}
-#endif
-
-
-void *
-gmx_alloc_aligned(size_t size)
-{
- void *p0,*p;
-
- p0 = malloc(size+32);
-
- if(p0 == NULL)
- {
- gmx_fatal(FARGS,"Failed to allocated %u bytes of aligned memory.",size+32);
- }
-
- p = (void *) (((size_t) p0 + 32) & (~((size_t) 31)));
-
- /* Yeah, yeah, we cannot free this pointer, but who cares... */
- return p;
-}
-
-t_fftgrid *mk_fftgrid(int nx,
- int ny,
- int nz,
- int *node2slab,
- int *slab2grid_x,
- t_commrec * cr,
- bool bReproducible)
-{
-/* parallel runs with non-parallel ffts haven't been tested yet */
- int nnodes;
- int x1,y1,maxlocalsize;
- t_fftgrid * grid;
- int flags;
-
- nnodes = 1;
-#ifdef GMX_MPI
- if (cr && cr->nnodes > 1) {
- MPI_Comm_size(cr->mpi_comm_mygroup,&nnodes);
- }
-#endif
-
- snew(grid,1);
- grid->nx = nx;
- grid->ny = ny;
- grid->nz = nz;
- grid->nxyz = nx*ny*nz;
- grid->bParallel = (nnodes > 1);
-
- if (grid->bParallel)
- {
- grid->la2r = (nz/2+1)*2;
- }
- else
- {
- grid->la2r = nz;
- }
-
- grid->la2c = (nz/2+1);
-
- grid->la12r = ny*grid->la2r;
-
- if (grid->bParallel)
- {
- grid->la12c = nx*grid->la2c;
- }
- else
- {
- grid->la12c = ny*grid->la2c;
- }
-
- /* This code assumes that the when the grid is not divisble by nnodes,
- * the maximum difference in local grid sizes is 1.
- */
- x1 = (nx % nnodes == 0 ? 0 : 1);
- y1 = (ny % nnodes == 0 ? 0 : 1);
-
- grid->nptr = (nx + x1)*(ny + y1)*grid->la2c*2;
-
- if (grid->bParallel)
- {
-#ifdef GMX_MPI
- gmx_parallel_3dfft_init(&grid->mpi_fft_setup,nx,ny,nz,
- node2slab,slab2grid_x,cr->mpi_comm_mygroup,
- bReproducible);
-
- gmx_parallel_3dfft_limits(grid->mpi_fft_setup,
- &(grid->pfft.local_x_start),
- &(grid->pfft.local_nx),
- &(grid->pfft.local_y_start_after_transpose),
- &(grid->pfft.local_ny_after_transpose));
-#else
- gmx_fatal(FARGS,"Parallel FFT supported with MPI only!");
-#endif
- }
- else
- {
- gmx_fft_init_3d_real(&grid->fft_setup,nx,ny,nz,bReproducible ? GMX_FFT_FLAG_CONSERVATIVE : GMX_FFT_FLAG_NONE);
- }
- grid->ptr = (real *)gmx_alloc_aligned(grid->nptr*sizeof(*(grid->ptr)));
-
-#ifdef GMX_MPI
- if (grid->bParallel && debug)
- {
- print_parfft(debug,"Plan", &grid->pfft);
- }
- if (grid->bParallel)
- {
- maxlocalsize = max((nx/nnodes + x1)*ny*grid->la2c*2,
- (ny/nnodes + y1)*nx*grid->la2c*2);
- grid->workspace = (real *)
- gmx_alloc_aligned(maxlocalsize*sizeof(*(grid->workspace)));
- }
- else
- {
- grid->workspace =
- (real*)gmx_alloc_aligned(grid->nptr*sizeof(*(grid->workspace)));
- }
-#else /* no MPI */
- grid->workspace = (real *)gmx_alloc_aligned(grid->nptr*sizeof(*(grid->workspace)));
-#endif
-
- return grid;
-}
-
-void
-pr_fftgrid(FILE *fp,char *title,t_fftgrid *grid)
-{
- int i,j,k,index_x,index_xy,ntot=0;
- int nx,ny,nz,nx2,ny2,nz2,la12,la2;
- real * ptr;
-
- /* Unpack structure */
- unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
- for(i=0; (i<nx); i++) {
- index_x = la12*i;
- for(j=0; (j<ny); j++) {
- index_xy = index_x + la2*j;
- for(k=0; (k<nz); k++) {
- if (ptr[index_xy+k] != 0) {
- fprintf(fp,"%-12s %5d %5d %5d %12.5e\n",
- title,i,j,k,ptr[index_xy+k]);
- ntot++;
- }
- }
- }
- }
- fprintf(fp,"%d non zero elements in %s\n",ntot,title);
-}
-
-void done_fftgrid(t_fftgrid *grid)
-{
- /* memory can't be freed because it is allocated by gmx_alloc_aligned */
- if (grid->ptr) {
- /* sfree(grid->ptr); */
- grid->ptr = NULL;
- }
-
- if (grid->workspace) {
- /* sfree(grid->workspace); */
- grid->workspace=NULL;
- }
-}
-
-
-void gmxfft3D(t_fftgrid *grid,enum gmx_fft_direction dir,t_commrec *cr)
-{
- real *tmp;
-
- if (grid->bParallel)
- {
-#ifdef GMX_MPI
- if( dir == GMX_FFT_REAL_TO_COMPLEX || dir == GMX_FFT_COMPLEX_TO_REAL )
- {
- gmx_parallel_3dfft(grid->mpi_fft_setup,dir,grid->ptr,grid->ptr);
- }
- else
- {
- gmx_fatal(FARGS,"Invalid direction for FFT: %d",dir);
- }
-#else
- gmx_fatal(FARGS,"Parallel FFT supported with MPI only!");
-#endif
- }
- else
- {
- if( dir == GMX_FFT_REAL_TO_COMPLEX || dir == GMX_FFT_COMPLEX_TO_REAL)
- {
- gmx_fft_3d_real(grid->fft_setup,dir,grid->ptr,grid->workspace);
- tmp = grid->ptr;
- grid->ptr = grid->workspace;
- grid->workspace = tmp;
- }
- else
- {
- gmx_fatal(FARGS,"Invalid direction for FFT: %d",dir);
- }
- }
-}
-
-void clear_fftgrid(t_fftgrid *grid)
-{
- /* clears the whole grid */
- int i,ngrid;
- real * ptr;
-
- ngrid = grid->nptr;
- ptr = grid->ptr;
-
- for (i=0; (i<ngrid); i++) {
- ptr[i] = 0;
- }
-}
-
-void unpack_fftgrid(t_fftgrid *grid,int *nx,int *ny,int *nz,
- int *nx2,int *ny2,int *nz2,
- int *la2,int *la12,bool bReal,real **ptr)
-{
- *nx = grid->nx;
- *ny = grid->ny;
- *nz = grid->nz;
- *nx2 = 2*grid->nx;
- *ny2 = 2*grid->ny;
- *nz2 = 2*grid->nz;
- if(bReal) {
- *la2 = grid->la2r;
- *la12= grid->la12r;
- }
- else {
- *la2 = grid->la2c;
- *la12= grid->la12c;
- }
- *ptr = grid->ptr;
-}
-
-
-
-/*****************************************************************
- *
- * For backward compatibility (for testing the ewald code vs. PPPM etc)
- * some old grid routines are retained here.
- *
- ************************************************************************/
-
-real ***mk_rgrid(int nx,int ny,int nz)
-{
- real *ptr1;
- real **ptr2;
- real ***ptr3;
- int i,j,n2,n3;
-
- snew(ptr1,nx*ny*nz);
- snew(ptr2,nx*ny);
- snew(ptr3,nx);
-
- n2=n3=0;
- for(i=0; (i<nx); i++) {
- ptr3[i]=&(ptr2[n2]);
- for(j=0; (j<ny); j++,n2++) {
- ptr2[n2] = &(ptr1[n3]);
- n3 += nz;
- }
- }
- return ptr3;
-}
-
-void free_rgrid(real ***grid,int nx,int ny)
-{
- int i;
-
- sfree(grid[0][0]);
- for(i=0; (i<nx); i++) {
- sfree(grid[i]);
- }
- sfree(grid);
-}
-
-real print_rgrid(FILE *fp,char *title,int nx,int ny,int nz,real ***grid)
-{
- int ix,iy,iz;
- real g,gtot;
-
- gtot=0;
- if (fp)
- fprintf(fp,"Printing all non-zero real elements of %s\n",title);
- for(ix=0; (ix<nx); ix++)
- for(iy=0; (iy<ny); iy++)
- for(iz=0; (iz<nz); iz++) {
- g=grid[ix][iy][iz];
- if (fp && (g != 0))
- fprintf(fp,"%s[%2d][%2d][%2d] = %12.5e\n",title,ix,iy,iz,g);
- gtot+=g;
- }
- return gtot;
-}
-
-void print_rgrid_pdb(char *fn,int nx,int ny,int nz,real ***grid)
-{
- FILE *fp;
- int ix,iy,iz,n,ig;
- real x,y,z,g;
-
- n=1;
- fp=gmx_fio_fopen(fn,"w");
- for(ix=0; (ix<nx); ix++) {
- for(iy=0; (iy<ny); iy++) {
- for(iz=0; (iz<nz); iz++) {
- g=grid[ix][iy][iz];
- ig=g;
- if ((ig != 0) || (1)) {
- x = 4*ix;
- y = 4*iy;
- z = 4*iz;
- fprintf(fp,"ATOM %5d Na Na 1 %8.3f%8.3f%8.3f%6.2f%6.2f\n",
- n++,x,y,z,0.0,g);
- }
- }
- }
- }
- gmx_fio_fclose(fp);
-}
-
-void clear_rgrid(int nx,int ny,int nz,real ***grid)
-{
- int i,j,k;
-
- for(i=0; (i<nx); i++)
- for(j=0; (j<ny); j++)
- for(k=0; (k<nz); k++)
- grid[i][j][k] = 0;
-}
-
-void clear_cgrid(int nx,int ny,int nz,t_complex ***grid)
-{
- int i,j,k;
-
- for(i=0; (i<nx); i++)
- for(j=0; (j<ny); j++)
- for(k=0; (k<nz); k++)
- grid[i][j][k] = cnul;
-}
-
-t_complex ***mk_cgrid(int nx,int ny,int nz)
-{
- t_complex *ptr1;
- t_complex **ptr2;
- t_complex ***ptr3;
- int i,j,n2,n3;
-
- snew(ptr1,nx*ny*nz);
- snew(ptr2,nx*ny);
- snew(ptr3,nx);
-
- n2=n3=0;
- for(i=0; (i<nx); i++) {
- ptr3[i]=&(ptr2[n2]);
- for(j=0; (j<ny); j++,n2++) {
- ptr2[n2] = &(ptr1[n3]);
- n3 += nz;
- }
- }
- return ptr3;
-}
-
-void free_cgrid(t_complex ***grid,int nx,int ny)
-{
- int i;
-
- sfree(grid[0][0]);
- for(i=0; (i<nx); i++)
- sfree(grid[i]);
- sfree(grid);
-}
-
-t_complex print_cgrid(FILE *fp,char *title,int nx,int ny,int nz,
- t_complex ***grid)
-{
- int ix,iy,iz;
- t_complex g,gtot;
-
- gtot=cnul;
- if (fp)
- fprintf(fp,"Printing all non-zero complex elements of %s\n",title);
- for(ix=0; (ix<nx); ix++)
- for(iy=0; (iy<ny); iy++)
- for(iz=0; (iz<nz); iz++) {
- g=grid[ix][iy][iz];
- if (fp && ((g.re != 0) || (g.im != 0)))
- fprintf(fp,"%s[%2d][%2d][%2d] = %12.5e + i %12.5e\n",
- title,ix,iy,iz,g.re,g.im);
- gtot = cadd(gtot,g);
- }
- return gtot;
-}
-
-void print_cgrid_pdb(char *fn,int nx,int ny,int nz,t_complex ***grid)
-{
- FILE *fp;
- int ix,iy,iz,n;
- real x,y,z,g;
-
- n=1;
- fp=gmx_fio_fopen(fn,"w");
- for(ix=0; (ix<nx); ix++) {
- for(iy=0; (iy<ny); iy++) {
- for(iz=0; (iz<nz); iz++) {
- g=grid[ix][iy][iz].re;
- if (g != 0) {
- x = 4*ix;
- y = 4*iy;
- z = 4*iz;
- fprintf(fp,"ATOM %5d Na Na 1 %8.3f%8.3f%8.3f%6.2f%6.2f\n",
- n++,x,y,z,0.0,g);
- }
- }
- }
- }
- gmx_fio_fclose(fp);
-}
-
-
-
-
-
-
-
-
{
pme_flags |= GMX_PME_CALC_F;
}
+ if (flags & GMX_FORCE_VIRIAL)
+ {
+ pme_flags |= GMX_PME_CALC_ENER_VIR;
+ }
wallcycle_start(wcycle,ewcPMEMESH);
status = gmx_pme_do(fr->pmedata,
md->start,md->homenr - fr->n_tpi,
return cutoff;
}
+bool can_use_allvsall(const t_inputrec *ir, const gmx_mtop_t *mtop,
+ bool bPrintNote,t_commrec *cr,FILE *fp)
+{
+ bool bAllvsAll;
+
+#ifdef GMX_DOUBLE
+ /* double not done yet */
+ bAllvsAll = FALSE;
+#else
+ bAllvsAll =
+ (
+ /* disable for very small systems (bug 416) */
+ mtop->natoms > 64 &&
+ ir->rlist==0 &&
+ ir->rcoulomb==0 &&
+ ir->rvdw==0 &&
+ ir->ePBC==epbcNONE &&
+ ir->vdwtype==evdwCUT &&
+ ir->coulombtype==eelCUT &&
+ ir->efep==efepNO &&
+ (ir->implicit_solvent == eisNO ||
+ (ir->implicit_solvent==eisGBSA && (ir->gb_algorithm==egbSTILL ||
+ ir->gb_algorithm==egbHCT ||
+ ir->gb_algorithm==egbOBC))) &&
+ getenv("GMX_NO_ALLVSALL") == NULL
+ );
+
+ if (bAllvsAll && ir->opts.ngener > 1)
+ {
+ const char *note="NOTE: Can not use all-vs-all force loops, because there are multiple energy monitor groups; you might get significantly higher performance when using only a single energy monitor group.\n";
+
+ if (bPrintNote)
+ {
+ if (MASTER(cr))
+ {
+ fprintf(stderr,"\n%s\n",note);
+ }
+ if (fp != NULL)
+ {
+ fprintf(fp,"\n%s\n",note);
+ }
+ }
+ bAllvsAll = FALSE;
+ }
+#endif
+
+ return bAllvsAll;
+}
+
+
void init_forcerec(FILE *fp,
const output_env_t oenv,
t_forcerec *fr,
fr->sc_sigma6 = pow(ir->sc_sigma,6);
/* Check if we can/should do all-vs-all kernels */
-#ifdef GMX_DOUBLE
- /* double not done yet */
- fr->bAllvsAll = FALSE;
-#else
- fr->bAllvsAll = (ir->rlist==0 &&
- ir->rcoulomb==0 &&
- ir->rvdw==0 &&
- ir->ePBC==epbcNONE &&
- ir->vdwtype==evdwCUT &&
- ir->coulombtype==eelCUT &&
- ir->efep==efepNO &&
- (ir->implicit_solvent == eisNO ||
- (ir->implicit_solvent==eisGBSA && (ir->gb_algorithm==egbSTILL ||
- ir->gb_algorithm==egbHCT ||
- ir->gb_algorithm==egbOBC)))
- );
- if (fr->bAllvsAll && ir->opts.ngener > 1)
- {
- const char *note="NOTE: Can not use all-vs-all force loops, because there are multiple energy monitor groups; you might get significantly higher performance when using only a single energy monitor group.\n";
- if (MASTER(cr))
- {
- fprintf(stderr,"\n%s\n",note);
- }
- if (fp != NULL)
- {
- fprintf(fp,"\n%s\n",note);
- }
- fr->bAllvsAll = FALSE;
- }
-#endif
+ fr->bAllvsAll = can_use_allvsall(ir,mtop,FALSE,NULL,NULL);
fr->AllvsAll_work = NULL;
fr->AllvsAll_workgb = NULL;
#include "tmpi.h"
#endif
-#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_SSE2) )
#ifdef GMX_DOUBLE
+#if ( defined(GMX_IA32_SSE2) || defined(GMX_X86_64_SSE2) || defined(GMX_SSE2) )
#include "genborn_sse2_double.h"
+#endif
#else
+#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_SSE2) )
#include "genborn_sse2_single.h"
#include "genborn_allvsall_sse2_single.h"
-#endif /* GMX_DOUBLE */
#endif /* GMX_SSE */
+#endif /* GMX_DOUBLE */
#include "genborn_allvsall.h"
- //#define DISABLE_SSE
+/*#define DISABLE_SSE*/
typedef struct {
int shift;
}
}
-#ifndef DOUBLE
+#ifndef GMX_DOUBLE
if(fr->bAllvsAll)
{
cnt = md->homenr*(md->nr/2+1);
switch(ir->gb_algorithm)
{
case egbSTILL:
- calc_gb_rad_still_sse(cr,fr,born->nr,top, atype, x[0], nl, born, md);
+ calc_gb_rad_still_sse(cr,fr,born->nr,top, atype, x[0], nl, born);
break;
case egbHCT:
case egbOBC:
{
ai = nl->iinr[i];
- nj0 = nl->jindex[ai];
- nj1 = nl->jindex[ai+1];
+ nj0 = nl->jindex[i];
+ nj1 = nl->jindex[i+1];
/* Load shifts for this list */
shift = nl->shift[i];
dd_atom_spread_real(cr->dd,fr->dvda);
}
-#ifndef DOUBLE
+#ifndef GMX_DOUBLE
if(fr->bAllvsAll)
{
#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_SSE2) )
/* x86 or x86-64 with GCC inline assembly and/or SSE intrinsics */
calc_gb_chainrule_sse(born->nr, &(fr->gblist), fr->dadx, fr->dvda,
x[0], f[0], fr->fshift[0], fr->shift_vec[0],
- gb_algorithm, born, md);
+ gb_algorithm, born, md);
#else
/* Calculate the forces due to chain rule terms with non sse code */
calc_gb_chainrule(born->nr, &(fr->gblist), fr->dadx, fr->dvda,
#include <xmmintrin.h>
#include <emmintrin.h>
+#include "genborn_sse2_double.h"
+
#if (defined (_MSC_VER) || defined(__INTEL_COMPILER))
#define gmx_castsi128_pd(a) _mm_castsi128_pd(a)
#define gmx_castpd_si128(a) _mm_castpd_si128(a)
const __m128d sincosd_sc4 = {0.00833333333331908278,0.00833333333331908278};
const __m128d sincosd_sc5 = {-0.16666666666666612594,-0.16666666666666612594};
- __m128d signbit = (__m128d) _mm_set1_epi64x(0x8000000000000000ULL);
- __m128d tiny = (__m128d) _mm_set1_epi64x(0x3e40000000000000ULL);
+ __m128d signbit = gmx_castsi128_pd(_mm_set1_epi64x(0x8000000000000000ULL));
+ __m128d tiny = gmx_castsi128_pd(_mm_set1_epi64x(0x3e40000000000000ULL));
__m128d xl,xl2,xl3,qd,absxl,p1,cx,sx,ts,tc,tsn,tcn;
__m128i q;
sx = _mm_or_pd( _mm_and_pd(isTiny,xl) , _mm_andnot_pd(isTiny,sx) );
cx = _mm_or_pd( _mm_and_pd(isTiny,one) , _mm_andnot_pd(isTiny,cx) );
- sinMask = (__m128d) _mm_cmpeq_epi32( _mm_and_si128(offsetSin,ione), izero);
- cosMask = (__m128d) _mm_cmpeq_epi32( _mm_and_si128(offsetCos,ione), izero);
+ sinMask = gmx_castsi128_pd(_mm_cmpeq_epi32( _mm_and_si128(offsetSin,ione), izero));
+ cosMask = gmx_castsi128_pd(_mm_cmpeq_epi32( _mm_and_si128(offsetCos,ione), izero));
ts = _mm_or_pd( _mm_and_pd(sinMask,sx) , _mm_andnot_pd(sinMask,cx) );
tc = _mm_or_pd( _mm_and_pd(cosMask,sx) , _mm_andnot_pd(cosMask,cx) );
/* Flip the sign of the result when (offset mod 4) = 1 or 2 */
- sinMask = (__m128d) _mm_cmpeq_epi32( _mm_and_si128(offsetSin,itwo), izero);
+ sinMask = gmx_castsi128_pd(_mm_cmpeq_epi32( _mm_and_si128(offsetSin,itwo), izero));
tsn = _mm_xor_pd(signbit,ts);
ts = _mm_or_pd( _mm_and_pd(sinMask,ts) , _mm_andnot_pd(sinMask,tsn) );
- cosMask = (__m128d) _mm_cmpeq_epi32( _mm_and_si128(offsetCos,itwo), izero);
+ cosMask = gmx_castsi128_pd(_mm_cmpeq_epi32( _mm_and_si128(offsetCos,itwo), izero));
tcn = _mm_xor_pd(signbit,tc);
tc = _mm_or_pd( _mm_and_pd(cosMask,tc) , _mm_andnot_pd(cosMask,tcn) );
_mm_store_sd(born->gpol_still_work+ai,gpi);
}
- /* Parallell summations */
+ /* Parallel summations */
if(PARTDECOMP(cr))
{
gmx_sum(natoms,born->gpol_still_work, cr);
gpi2 = gpi_ai*gpi_ai;
born->bRad[i]=factor*gmx_invsqrt(gpi2);
- fr->invsqrta[i]=gmx_invsqrt(born->bRad[ai]);
+ fr->invsqrta[i]=gmx_invsqrt(born->bRad[i]);
}
}
born->bRad[i] = rr_inv - tsum*rr_inv2;
born->bRad[i] = 1.0 / born->bRad[i];
- fr->invsqrta[ai]=gmx_invsqrt(born->bRad[ai]);
+ fr->invsqrta[i] = gmx_invsqrt(born->bRad[i]);
tchain = rr * (born->obc_alpha-2*born->obc_beta*sum+3*born->obc_gamma*sum2);
born->drobc[i] = (1.0-tsum*tsum)*tchain*rr_inv2;
+/*
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
#ifndef _genborn_sse2_double_h
#define _genborn_sse2_double_h
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <xmmintrin.h>
#include <emmintrin.h>
+#include "genborn_sse2_single.h"
+
int
-calc_gb_rad_still_sse(t_commrec *cr, t_forcerec *fr,int natoms, gmx_localtop_t *top,
- const t_atomtypes *atype, float *x, t_nblist *nl, gmx_genborn_t *born, t_mdatoms *md)
+calc_gb_rad_still_sse(t_commrec *cr, t_forcerec *fr,
+ int natoms, gmx_localtop_t *top,
+ const t_atomtypes *atype, float *x, t_nblist *nl,
+ gmx_genborn_t *born)
{
int i,k,n,ii,is3,ii3,nj0,nj1,offset;
- int n0,n1;
int jnrA,jnrB,jnrC,jnrD,j3A,j3B,j3C,j3D;
int jnrE,jnrF,jnrG,jnrH,j3E,j3F,j3G,j3H;
int shift;
n = 0;
- n0 = md->start;
- n1 = md->start+md->homenr+natoms/2+1;
-
for(i=0;i<natoms;i++)
{
work[i]=0;
xmm3 = _mm_shuffle_ps(xmm3,xmm4,_MM_SHUFFLE(0,0,0,0));
isaj = _mm_shuffle_ps(xmm1,xmm3,_MM_SHUFFLE(2,0,2,0));
- isaprod = _mm_mul_ps(isai,isaj); // rb2 in tinker
+ isaprod = _mm_mul_ps(isai,isaj); /* rb2 in tinker */
inv_isaprod = _mm_mul_ps(isaprod,isaprod);
- inv_isaprod = gmx_mm_inv_ps(inv_isaprod); //1/rb2 in tinker
+ inv_isaprod = gmx_mm_inv_ps(inv_isaprod); /* 1/rb2 in tinker*/
/* Load charges for ai's and aj's */
xmm1 = _mm_load_ss(charge+ai1);
float
calc_gb_chainrule_sse(int natoms, t_nblist *nl, float *dadx, float *dvda,
- float *xd, float *f, float *fshift, float *shift_vec, int gb_algorithm, gmx_genborn_t *born, t_mdatoms *md);
-
+ float *xd, float *f, float *fshift, float *shift_vec,
+ int gb_algorithm, gmx_genborn_t *born, t_mdatoms *md);
int
calc_gb_rad_still_sse(t_commrec *cr, t_forcerec *fr,int natoms, gmx_localtop_t *top,
- const t_atomtypes *atype, float *x, t_nblist *nl, gmx_genborn_t *born, t_mdatoms *md);
+ const t_atomtypes *atype, float *x, t_nblist *nl, gmx_genborn_t *born);
int
calc_gb_rad_hct_obc_sse(t_commrec *cr, t_forcerec * fr, int natoms, gmx_localtop_t *top,
#include "coulomb.h"
#include "pppm.h"
#include "xvgr.h"
-#include "fftgrid.h"
#include "gmxfio.h"
#include "pppm.h"
+#include "smalloc.h"
static void calc_k(rvec lll,int ix,int iy,int iz,int nx,int ny,int nz,rvec k)
{
gmx_fio_fclose(fp);
}
+static real ***mk_rgrid(int nx,int ny,int nz)
+{
+ real *ptr1;
+ real **ptr2;
+ real ***ptr3;
+ int i,j,n2,n3;
+
+ snew(ptr1,nx*ny*nz);
+ snew(ptr2,nx*ny);
+ snew(ptr3,nx);
+
+ n2=n3=0;
+ for(i=0; (i<nx); i++) {
+ ptr3[i]=&(ptr2[n2]);
+ for(j=0; (j<ny); j++,n2++) {
+ ptr2[n2] = &(ptr1[n3]);
+ n3 += nz;
+ }
+ }
+ return ptr3;
+}
+
real ***rd_ghat(FILE *log,const output_env_t oenv,char *fn,ivec igrid,
rvec gridspace, rvec beta,int *porder,real *r1,real *rc)
{
* files like gmx_fft_fftw3.c or gmx_fft_intel_mkl.c for that.
*/
+#ifndef GMX_FFT_FFTW3
+
+ struct gmx_many_fft {
+ int howmany;
+ int dist;
+ gmx_fft_t fft;
+ };
+
+typedef struct gmx_many_fft* gmx_many_fft_t ;
+
+int
+gmx_fft_init_many_1d(gmx_fft_t * pfft,
+ int nx,
+ int howmany,
+ gmx_fft_flag flags)
+{
+ gmx_many_fft_t fft;
+ if(pfft==NULL)
+ {
+ gmx_fatal(FARGS,"Invalid opaque FFT datatype pointer.");
+ return EINVAL;
+ }
+ *pfft = NULL;
+
+ if( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
+ {
+ return ENOMEM;
+ }
+
+ gmx_fft_init_1d(&fft->fft,nx,flags);
+ fft->howmany = howmany;
+ fft->dist = 2*nx;
+
+ *pfft = (gmx_fft_t)fft;
+ return 0;
+}
+
+int
+gmx_fft_init_many_1d_real(gmx_fft_t * pfft,
+ int nx,
+ int howmany,
+ gmx_fft_flag flags)
+{
+ gmx_many_fft_t fft;
+ if(pfft==NULL)
+ {
+ gmx_fatal(FARGS,"Invalid opaque FFT datatype pointer.");
+ return EINVAL;
+ }
+ *pfft = NULL;
+
+ if( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
+ {
+ return ENOMEM;
+ }
+
+ gmx_fft_init_1d_real(&fft->fft,nx,flags);
+ fft->howmany = howmany;
+ fft->dist = 2*(nx/2+1);
+
+ *pfft = (gmx_fft_t)fft;
+ return 0;
+}
+
+int
+gmx_fft_many_1d (gmx_fft_t fft,
+ enum gmx_fft_direction dir,
+ void * in_data,
+ void * out_data)
+{
+ gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
+ int i,ret;
+ for (i=0;i<mfft->howmany;i++)
+ {
+ ret=gmx_fft_1d(mfft->fft,dir,in_data,out_data);
+ if (ret!=0) return ret;
+ in_data=(real*)in_data+mfft->dist;
+ out_data=(real*)out_data+mfft->dist;
+ }
+ return 0;
+}
+
+int
+gmx_fft_many_1d_real (gmx_fft_t fft,
+ enum gmx_fft_direction dir,
+ void * in_data,
+ void * out_data)
+{
+ gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
+ int i,ret;
+ for (i=0;i<mfft->howmany;i++)
+ {
+ ret=gmx_fft_1d_real(mfft->fft,dir,in_data,out_data);
+ if (ret!=0) return ret;
+ in_data=(real*)in_data+mfft->dist;
+ out_data=(real*)out_data+mfft->dist;
+ }
+ return 0;
+}
+
+
+void
+gmx_many_fft_destroy(gmx_fft_t fft)
+{
+ gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
+ if (mfft!=NULL)
+ {
+ if (mfft->fft!=NULL)
+ {
+ gmx_fft_destroy(mfft->fft);
+ }
+ free(mfft);
+ }
+}
+
+#endif
+
int gmx_fft_transpose_2d(t_complex * in_data,
t_complex * out_data,
int nx,
gmx_fft_init_1d(gmx_fft_t * pfft,
int nx,
gmx_fft_flag flags)
+{
+ return gmx_fft_init_many_1d(pfft,nx,1,flags);
+}
+
+
+int
+gmx_fft_init_many_1d(gmx_fft_t * pfft,
+ int nx,
+ int howmany,
+ gmx_fft_flag flags)
{
gmx_fft_t fft;
FFTWPREFIX(complex) *p1,*p2,*up1,*up2;
}
/* allocate aligned, and extra memory to make it unaligned */
- p1 = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2));
+ p1 = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2)*howmany);
if(p1==NULL)
{
FFTWPREFIX(free)(fft);
return ENOMEM;
}
- p2 = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2));
+ p2 = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2)*howmany);
if(p2==NULL)
{
FFTWPREFIX(free)(p1);
pc += 8;
up2 = (FFTWPREFIX(complex) *)pc;
- fft->plan[0][0][0] = FFTWPREFIX(plan_dft_1d)(nx,up1,up2,FFTW_BACKWARD,fftw_flags);
- fft->plan[0][0][1] = FFTWPREFIX(plan_dft_1d)(nx,up1,up2,FFTW_FORWARD,fftw_flags);
- fft->plan[0][1][0] = FFTWPREFIX(plan_dft_1d)(nx,up1,up1,FFTW_BACKWARD,fftw_flags);
- fft->plan[0][1][1] = FFTWPREFIX(plan_dft_1d)(nx,up1,up1,FFTW_FORWARD,fftw_flags);
- fft->plan[1][0][0] = FFTWPREFIX(plan_dft_1d)(nx,p1,p2,FFTW_BACKWARD,fftw_flags);
- fft->plan[1][0][1] = FFTWPREFIX(plan_dft_1d)(nx,p1,p2,FFTW_FORWARD,fftw_flags);
- fft->plan[1][1][0] = FFTWPREFIX(plan_dft_1d)(nx,p1,p1,FFTW_BACKWARD,fftw_flags);
- fft->plan[1][1][1] = FFTWPREFIX(plan_dft_1d)(nx,p1,p1,FFTW_FORWARD,fftw_flags);
-
+ /* int rank, const int *n, int howmany,
+ fftw_complex *in, const int *inembed,
+ int istride, int idist,
+ fftw_complex *out, const int *onembed,
+ int ostride, int odist,
+ int sign, unsigned flags */
+ fft->plan[0][0][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up2,&nx,1,nx,FFTW_BACKWARD,fftw_flags);
+ fft->plan[0][0][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up2,&nx,1,nx,FFTW_FORWARD,fftw_flags);
+ fft->plan[0][1][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up1,&nx,1,nx,FFTW_BACKWARD,fftw_flags);
+ fft->plan[0][1][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up1,&nx,1,nx,FFTW_FORWARD,fftw_flags);
+ fft->plan[1][0][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p2,&nx,1,nx,FFTW_BACKWARD,fftw_flags);
+ fft->plan[1][0][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p2,&nx,1,nx,FFTW_FORWARD,fftw_flags);
+ fft->plan[1][1][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p1,&nx,1,nx,FFTW_BACKWARD,fftw_flags);
+ fft->plan[1][1][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p1,&nx,1,nx,FFTW_FORWARD,fftw_flags);
for(i=0;i<2;i++)
{
}
-
int
gmx_fft_init_1d_real(gmx_fft_t * pfft,
int nx,
gmx_fft_flag flags)
+{
+ return gmx_fft_init_many_1d_real(pfft, nx, 1, flags);
+}
+
+int
+gmx_fft_init_many_1d_real(gmx_fft_t * pfft,
+ int nx,
+ int howmany,
+ gmx_fft_flag flags)
{
gmx_fft_t fft;
real *p1,*p2,*up1,*up2;
}
/* allocate aligned, and extra memory to make it unaligned */
- p1 = (real *) FFTWPREFIX(malloc)(sizeof(real)*(nx+2));
+ p1 = (real *) FFTWPREFIX(malloc)(sizeof(real)*(nx/2+1)*2*howmany + 8);
if(p1==NULL)
{
FFTWPREFIX(free)(fft);
return ENOMEM;
}
- p2 = (real *) FFTWPREFIX(malloc)(sizeof(real)*(nx+2));
+ p2 = (real *) FFTWPREFIX(malloc)(sizeof(real)*(nx/2+1)*2*howmany + 8);
if(p2==NULL)
{
FFTWPREFIX(free)(p1);
pc += 8;
up2 = (real *)pc;
-
- fft->plan[0][0][0] = FFTWPREFIX(plan_dft_c2r_1d)(nx,(FFTWPREFIX(complex) *)up1,up2,fftw_flags);
- fft->plan[0][0][1] = FFTWPREFIX(plan_dft_r2c_1d)(nx,up1,(FFTWPREFIX(complex) *)up2,fftw_flags);
- fft->plan[0][1][0] = FFTWPREFIX(plan_dft_c2r_1d)(nx,(FFTWPREFIX(complex) *)up1,up1,fftw_flags);
- fft->plan[0][1][1] = FFTWPREFIX(plan_dft_r2c_1d)(nx,up1,(FFTWPREFIX(complex) *)up1,fftw_flags);
-
- fft->plan[1][0][0] = FFTWPREFIX(plan_dft_c2r_1d)(nx,(FFTWPREFIX(complex) *)p1,p2,fftw_flags);
- fft->plan[1][0][1] = FFTWPREFIX(plan_dft_r2c_1d)(nx,p1,(FFTWPREFIX(complex) *)p2,fftw_flags);
- fft->plan[1][1][0] = FFTWPREFIX(plan_dft_c2r_1d)(nx,(FFTWPREFIX(complex) *)p1,p1,fftw_flags);
- fft->plan[1][1][1] = FFTWPREFIX(plan_dft_r2c_1d)(nx,p1,(FFTWPREFIX(complex) *)p1,fftw_flags);
-
+ /* int rank, const int *n, int howmany,
+ double *in, const int *inembed,
+ int istride, int idist,
+ fftw_complex *out, const int *onembed,
+ int ostride, int odist,
+ unsigned flag */
+ fft->plan[0][0][1] = FFTWPREFIX(plan_many_dft_r2c)(1,&nx,howmany,up1,0,1,(nx/2+1)*2,(FFTWPREFIX(complex) *)up2,0,1,(nx/2+1),fftw_flags);
+ fft->plan[0][1][1] = FFTWPREFIX(plan_many_dft_r2c)(1,&nx,howmany,up1,0,1,(nx/2+1)*2,(FFTWPREFIX(complex) *)up1,0,1,(nx/2+1),fftw_flags);
+ fft->plan[1][0][1] = FFTWPREFIX(plan_many_dft_r2c)(1,&nx,howmany, p1,0,1,(nx/2+1)*2,(FFTWPREFIX(complex) *)p2 ,0,1,(nx/2+1),fftw_flags);
+ fft->plan[1][1][1] = FFTWPREFIX(plan_many_dft_r2c)(1,&nx,howmany, p1,0,1,(nx/2+1)*2,(FFTWPREFIX(complex) *)p1 ,0,1,(nx/2+1),fftw_flags);
+
+ fft->plan[0][0][0] = FFTWPREFIX(plan_many_dft_c2r)(1,&nx,howmany,(FFTWPREFIX(complex) *)up1,0,1,(nx/2+1),up2,0,1,(nx/2+1)*2,fftw_flags);
+ fft->plan[0][1][0] = FFTWPREFIX(plan_many_dft_c2r)(1,&nx,howmany,(FFTWPREFIX(complex) *)up1,0,1,(nx/2+1),up1,0,1,(nx/2+1)*2,fftw_flags);
+ fft->plan[1][0][0] = FFTWPREFIX(plan_many_dft_c2r)(1,&nx,howmany,(FFTWPREFIX(complex) *) p1,0,1,(nx/2+1), p2,0,1,(nx/2+1)*2,fftw_flags);
+ fft->plan[1][1][0] = FFTWPREFIX(plan_many_dft_c2r)(1,&nx,howmany,(FFTWPREFIX(complex) *) p1,0,1,(nx/2+1), p1,0,1,(nx/2+1)*2,fftw_flags);
for(i=0;i<2;i++)
{
return 0;
}
+int
+gmx_fft_many_1d (gmx_fft_t fft,
+ enum gmx_fft_direction dir,
+ void * in_data,
+ void * out_data)
+{
+ return gmx_fft_1d(fft,dir,in_data,out_data);
+}
int
gmx_fft_1d_real (gmx_fft_t fft,
return 0;
}
+int
+gmx_fft_many_1d_real (gmx_fft_t fft,
+ enum gmx_fft_direction dir,
+ void * in_data,
+ void * out_data)
+{
+ return gmx_fft_1d_real(fft,dir,in_data,out_data);
+}
int
gmx_fft_2d (gmx_fft_t fft,
}
+void
+gmx_many_fft_destroy(gmx_fft_t fft)
+{
+ gmx_fft_destroy(fft);
+}
+
#else
int
gmx_fft_fftw2_empty;
#include <string.h>
#include <errno.h>
-#ifdef GMX_MPI
-
#ifdef GMX_LIB_MPI
#include <mpi.h>
#endif
#include "tmpi.h"
#endif
-
+#include "smalloc.h"
#include "gmx_parallel_3dfft.h"
#include "gmx_fft.h"
#include "gmxcomplex.h"
#include "gmx_fatal.h"
-typedef struct {
- int *sdisps;
- int *scounts;
- int *rdisps;
- int *rcounts;
-} alltoallv_t;
+#include "fft5d.h"
-struct gmx_parallel_3dfft
-{
- int nx;
- int ny;
- int nz;
- int nzc;
- int local_slab;
- int nnodes;
- gmx_fft_t fft_yz;
- gmx_fft_t fft_x;
- void * work_rawptr;
- void * work2_rawptr;
- t_complex * work;
- t_complex * work2;
- int *node2slab;
- int *slab2grid_x;
- int *slab2grid_y;
- alltoallv_t *aav;
- MPI_Comm comm;
+struct gmx_parallel_3dfft {
+ fft5d_plan p1,p2;
};
+
static int *copy_int_array(int n,int *src)
{
int *dest,i;
int
gmx_parallel_3dfft_init (gmx_parallel_3dfft_t * pfft_setup,
- int ngridx,
- int ngridy,
- int ngridz,
- int *node2slab,
- int *slab2grid_x,
- MPI_Comm comm,
+ ivec ndata,
+ real ** real_data,
+ t_complex ** complex_data,
+ MPI_Comm comm[2],
+ int * slab2index_major,
+ int * slab2index_minor,
bool bReproducible)
{
- gmx_parallel_3dfft_t p;
- int nxy_n;
- void *p0;
- int flags;
-
- flags = bReproducible ? GMX_FFT_FLAG_CONSERVATIVE : 0;
+ int rN=ndata[2],M=ndata[1],K=ndata[0];
+ int flags = FFT5D_REALCOMPLEX | FFT5D_ORDER_YZ; /* FFT5D_DEBUG */
+ MPI_Comm rcomm[]={comm[1],comm[0]};
+ int Nb,Mb,Kb; /* dimension for backtransform (in starting order) */
- p = (gmx_parallel_3dfft_t)malloc(sizeof(struct gmx_parallel_3dfft));
+ snew(*pfft_setup,1);
+ if (bReproducible) flags |= FFT5D_NOMEASURE;
- if(p==NULL)
- return ENOMEM;
-
- p->nx = ngridx;
- p->ny = ngridy;
- p->nz = ngridz;
- p->nzc = ngridz/2 + 1;
-
- MPI_Comm_rank( comm , &(p->local_slab) );
-
- MPI_Comm_dup( comm , &(p->comm) );
-
- MPI_Comm_size( p->comm , &p->nnodes);
-
- if (node2slab)
- p->node2slab = copy_int_array(p->nnodes,node2slab);
- else
- p->node2slab = NULL;
-
- if (p->node2slab)
- p->local_slab = p->node2slab[p->local_slab];
-
- MPI_Comm_dup( comm , &(p->comm) );
-
- MPI_Comm_size( p->comm , &p->nnodes);
-
- if (slab2grid_x)
- p->slab2grid_x = copy_int_array(p->nnodes+1,slab2grid_x);
- else
- p->slab2grid_x = make_slab2grid(p->nnodes,p->nx);
- p->slab2grid_y = make_slab2grid(p->nnodes,p->ny);
-
- if (node2slab || p->nx % p->nnodes || p->ny % p->nnodes) {
- p->aav = (alltoallv_t*)malloc(sizeof(alltoallv_t));
- p->aav->sdisps = (int*)malloc(p->nnodes*sizeof(int));
- p->aav->scounts = (int*)malloc(p->nnodes*sizeof(int));
- p->aav->rdisps = (int*)malloc(p->nnodes*sizeof(int));
- p->aav->rcounts = (int*)malloc(p->nnodes*sizeof(int));
+ if (!(flags&FFT5D_ORDER_YZ)) {
+ Nb=M;Mb=K;Kb=rN;
} else {
- p->aav = NULL;
+ Nb=K;Mb=rN;Kb=M; /* currently always true because ORDER_YZ always set */
}
-
- /* initialize transforms */
- if ( ( gmx_fft_init_1d(&(p->fft_x),ngridx,flags) != 0 ) ||
- ( gmx_fft_init_2d_real(&(p->fft_yz),ngridy,ngridz,flags) != 0))
- {
- free(p);
- return -1;
- }
-
- /* Round up */
- nxy_n = p->nnodes*((p->nx + p->nnodes - 1)/p->nnodes)*
- ((p->ny + p->nnodes - 1)/p->nnodes);
-
- p0 = (real*)malloc(sizeof(real)*2*(p->nzc)*nxy_n + 32);
- p->work_rawptr = p0;
- p->work = (t_complex*) ((void *) (((size_t) p0 + 32) &
- (~((size_t) 31))));
-
- p0 = (real*)malloc(sizeof(real)*2*(p->nzc)*nxy_n);
- p->work2_rawptr = p0;
- p->work2 = (t_complex*) ((void *) (((size_t) p0 + 32) &
- (~((size_t) 31))));
+ (*pfft_setup)->p1 = fft5d_plan_3d(rN,M,K,rcomm, flags, (t_complex**)real_data, complex_data);
- if(p->work == NULL || p->work2 == NULL)
- {
- if(p->work_rawptr != NULL)
- free(p->work_rawptr);
- if(p->work2_rawptr != NULL)
- free(p->work2_rawptr);
- free(p);
- return ENOMEM;
- }
-
- *pfft_setup = p;
-
- return 0;
-}
-
-
-
-
-int
-gmx_parallel_3dfft_limits(gmx_parallel_3dfft_t pfft_setup,
- int * local_x_start,
- int * local_nx,
- int * local_y_start,
- int * local_ny)
-{
- int slab;
-
- slab = pfft_setup->local_slab;
-
- *local_x_start = pfft_setup->slab2grid_x[slab];
- *local_y_start = pfft_setup->slab2grid_y[slab];
-
- *local_nx = pfft_setup->slab2grid_x[slab+1] - (*local_x_start);
- *local_ny = pfft_setup->slab2grid_y[slab+1] - (*local_y_start);
+ (*pfft_setup)->p2 = fft5d_plan_3d(Nb,Mb,Kb,rcomm,
+ (flags|FFT5D_BACKWARD|FFT5D_NOMALLOC)^FFT5D_ORDER_YZ, complex_data, (t_complex**)real_data);
- return 0;
+ return (*pfft_setup)->p1 != 0 && (*pfft_setup)->p2 !=0;
}
-
-int
-gmx_parallel_transpose_xy(t_complex * data,
- t_complex * work,
- int nx,
- int ny,
- int local_slab,
- int *s2x,
- int *s2y,
- int nzc,
- int nnodes,
- int *node2slab,
- alltoallv_t *aav,
- MPI_Comm comm)
+static int
+fft5d_limits(fft5d_plan p,
+ ivec local_ndata,
+ ivec local_offset,
+ ivec local_size)
{
- int i,j;
- int local_nx,local_ny,blocksize,slab;
+ int N1,M0,K0,K1,*coor;
+ fft5d_local_size(p,&N1,&M0,&K0,&K1,&coor); /* M0=MG/P[0], K1=KG/P[1], NG,MG,KG global sizes */
- local_nx = s2x[local_slab+1] - s2x[local_slab];
- local_ny = s2y[local_slab+1] - s2y[local_slab];
+ local_offset[2]=0;
+ local_offset[1]=p->oM[0]; /*=p->coor[0]*p->MG/p->P[0]; */
+ local_offset[0]=p->oK[0]; /*=p->coor[1]*p->KG/p->P[1]; */
- /* A: Do a local transpose to get data continuous for communication.
- * We can use NULL for the workarray since we do it out-of-place.
- */
- gmx_fft_transpose_2d_nelem(data,work,local_nx,ny,nzc,NULL);
+ local_ndata[2]=p->rC[0];
+ local_ndata[1]=p->pM[0];
+ local_ndata[0]=p->pK[0];
- /* B: Parallel communication, exchange data blocks. */
- if (aav == NULL) {
- blocksize = local_nx*local_ny*nzc*2;
- MPI_Alltoall(work,
- blocksize,
- GMX_MPI_REAL,
- data,
- blocksize,
- GMX_MPI_REAL,
- comm);
+ if ((!(p->flags&FFT5D_BACKWARD)) && (p->flags&FFT5D_REALCOMPLEX)) {
+ local_size[2]=p->C[0]*2;
} else {
- for(i=0; i<nnodes; i++) {
- slab = (node2slab ? node2slab[i] : i);
- aav->sdisps [i] = s2y[slab] *local_nx*nzc*2;
- aav->scounts[i] = (s2y[slab+1] - s2y[slab])*local_nx*nzc*2;
- aav->rdisps [i] = local_ny* s2x[slab] *nzc*2;
- aav->rcounts[i] = local_ny*(s2x[slab+1] - s2x[slab])*nzc*2;
- }
- MPI_Alltoallv(work,
- aav->scounts,aav->sdisps,
- GMX_MPI_REAL,
- data,
- aav->rcounts,aav->rdisps,
- GMX_MPI_REAL,
- comm);
- }
-
- /* C: Copy entire blocks into place, so we have YXZ. */
- for(j=0;j<local_ny;j++)
- {
- for(i=0;i<nnodes;i++)
- {
- memcpy(work + j*nx*nzc + s2x[i]*nzc,
- data + s2x[i]*local_ny*nzc + j*(s2x[i+1] - s2x[i])*nzc,
- (s2x[i+1] - s2x[i])*nzc*sizeof(t_complex));
- }
+ local_size[2]=p->C[0];
}
+ local_size[1]=p->pM[0];
+ local_size[0]=p->pK[0];
return 0;
}
-
int
-gmx_parallel_3dfft(gmx_parallel_3dfft_t pfft_setup,
- enum gmx_fft_direction dir,
- void * in_data,
- void * out_data)
-{
- int i,j,k;
- int nx,ny,nz,nzc,nzr;
- int local_x_start,local_nx;
- int local_y_start,local_ny;
- t_complex * work;
- real * rdata;
- t_complex * cdata;
- t_complex * ctmp;
-
- work = pfft_setup->work;
-
- /* When we do in-place FFTs the data need to be embedded in the z-dimension,
- * so there is room for the complex data. This means the direct space
- * _grid_ (not data) dimensions will be nx*ny*(nzc*2), where nzc=nz/2+1.
- * If we do out-of-place transforms the direct space dimensions are simply
- * nx*ny*nz, and no embedding is used.
- * The complex dimensions are always ny*nx*nzc (note the transpose).
- *
- * The direct space _grid_ dimension is nzr.
- */
-
- nx = pfft_setup->nx;
- ny = pfft_setup->ny;
- nz = pfft_setup->nz;
- nzc = pfft_setup->nzc;
-
- if(in_data == out_data)
- {
- nzr = 2*nzc;
- }
- else
- {
- nzr = nz;
- }
-
- gmx_parallel_3dfft_limits(pfft_setup,
- &local_x_start,
- &local_nx,
- &local_y_start,
- &local_ny);
-
- if(dir == GMX_FFT_REAL_TO_COMPLEX)
- {
- rdata = (real *)in_data + local_x_start*ny*nzr;
- cdata = (t_complex *)out_data + local_x_start*ny*nzc;
-
- /* Perform nx local 2D real-to-complex FFTs in the yz slices.
- * When the input data is "embedded" for 3D-in-place transforms, this
- * must also be done in-place to get the data embedding right.
- *
- * Note that rdata==cdata when we work in-place.
- */
- for(i=0;i<local_nx;i++)
- {
- gmx_fft_2d_real(pfft_setup->fft_yz,
- GMX_FFT_REAL_TO_COMPLEX,
- rdata + i*ny*nzr,
- cdata + i*ny*nzc);
- }
-
- /* Transpose to temporary work array */
- gmx_parallel_transpose_xy(cdata,
- work,
- nx,
- ny,
- pfft_setup->local_slab,
- pfft_setup->slab2grid_x,
- pfft_setup->slab2grid_y,
- nzc,
- pfft_setup->nnodes,
- pfft_setup->node2slab,
- pfft_setup->aav,
- pfft_setup->comm);
-
- /* Transpose from temporary work array in order YXZ to
- * the output array in order YZX.
- */
- /* output cdata changes when nx or ny not divisible by nnodes */
- cdata = (t_complex *)out_data + local_y_start*nx*nzc;
- for(j=0;j<local_ny;j++)
- {
- gmx_fft_transpose_2d(work + j*nzc*nx,
- cdata + j*nzc*nx,
- nx,
- nzc);
- }
-
- /* Perform local_ny*nzc complex FFTs along the x dimension */
- for(i=0;i<local_ny*nzc;i++)
- {
- gmx_fft_1d(pfft_setup->fft_x,
- GMX_FFT_FORWARD,
- cdata + i*nx,
- work + i*nx);
- }
-
- /* Transpose back from YZX to YXZ. */
- for(j=0;j<local_ny;j++)
- {
- gmx_fft_transpose_2d(work + j*nzc*nx,
- cdata + j*nzc*nx,
- nzc,
- nx);
- }
- }
- else if(dir == GMX_FFT_COMPLEX_TO_REAL)
- {
- cdata = (t_complex *)in_data + local_y_start*nx*nzc;
- rdata = (real *)out_data + local_x_start*ny*nzr;
-
- /* If we are working in-place it doesn't matter that we destroy
- * input data. Otherwise we use an extra temporary workspace array.
- */
- if(in_data == out_data)
- {
- ctmp = cdata;
- }
- else
- {
- ctmp = pfft_setup->work2;
- }
-
- /* Transpose from YXZ to YZX. */
- for(j=0;j<local_ny;j++)
- {
- gmx_fft_transpose_2d(cdata + j*nzc*nx,
- work + j*nzc*nx,
- nx,
- nzc);
- }
-
- /* Perform local_ny*nzc complex FFTs along the x dimension */
- for(i=0;i<local_ny*nzc;i++)
- {
- gmx_fft_1d(pfft_setup->fft_x,
- GMX_FFT_BACKWARD,
- work + i*nx,
- ctmp + i*nx);
- }
-
- /* Transpose from YZX to YXZ. */
- for(j=0;j<local_ny;j++)
- {
- gmx_fft_transpose_2d(ctmp + j*nzc*nx,
- work + j*nzc*nx,
- nzc,
- nx);
- }
-
- if(in_data == out_data)
- {
- /* output cdata changes when nx or ny not divisible by nnodes */
- ctmp = (t_complex *)in_data + local_x_start*ny*nzc;
- }
- gmx_parallel_transpose_xy(work,
- ctmp,
- ny,
- nx,
- pfft_setup->local_slab,
- pfft_setup->slab2grid_y,
- pfft_setup->slab2grid_x,
- nzc,
- pfft_setup->nnodes,
- pfft_setup->node2slab,
- pfft_setup->aav,
- pfft_setup->comm);
-
-
- /* Perform nx local 2D complex-to-real FFTs in the yz slices.
- * The 3D FFT is done in-place, so we need to do this in-place too in order
- * to get the data organization right.
- */
- for(i=0;i<local_nx;i++)
- {
- gmx_fft_2d_real(pfft_setup->fft_yz,
- GMX_FFT_COMPLEX_TO_REAL,
- ctmp + i*ny*nzc,
- rdata + i*ny*nzr);
- }
- }
- else
- {
- gmx_fatal(FARGS,"Incorrect FFT direction.");
- }
-
- /* Skip the YX backtranspose to save communication! Grid is now YXZ */
- return 0;
+gmx_parallel_3dfft_real_limits(gmx_parallel_3dfft_t pfft_setup,
+ ivec local_ndata,
+ ivec local_offset,
+ ivec local_size) {
+ return fft5d_limits(pfft_setup->p1,local_ndata,local_offset,local_size);
}
+static void reorder_ivec_yzx(ivec v)
+{
+ real tmp;
-
+ tmp = v[0];
+ v[XX] = v[2];
+ v[ZZ] = v[1];
+ v[YY] = tmp;
+}
int
-gmx_parallel_3dfft_complex2real(gmx_parallel_3dfft_t pfft_setup,
- void * data)
+gmx_parallel_3dfft_complex_limits(gmx_parallel_3dfft_t pfft_setup,
+ ivec complex_order,
+ ivec local_ndata,
+ ivec local_offset,
+ ivec local_size)
{
- int i,j,k;
- int nx,ny,nzc;
- int local_x_start,local_nx;
- int local_y_start,local_ny;
- t_complex * work;
- t_complex * cdata;
-
- work = pfft_setup->work;
- cdata = (t_complex*)data;
+ int ret;
- nx = pfft_setup->nx;
- ny = pfft_setup->ny;
- nzc = pfft_setup->nzc;
-
- gmx_parallel_3dfft_limits(pfft_setup,
- &local_x_start,
- &local_nx,
- &local_y_start,
- &local_ny);
+ /* For now everything is in-order, but prepare to save communication by avoiding transposes */
+ complex_order[0] = 0;
+ complex_order[1] = 1;
+ complex_order[2] = 2;
-
-
- return 0;
-}
+ ret = fft5d_limits(pfft_setup->p2,local_ndata,local_offset,local_size);
+ reorder_ivec_yzx(local_ndata);
+ reorder_ivec_yzx(local_offset);
+ reorder_ivec_yzx(local_size);
+ return ret;
+}
-int
-gmx_parallel_3dfft_destroy(gmx_parallel_3dfft_t pfft_setup)
-{
- gmx_fft_destroy(pfft_setup->fft_x);
- gmx_fft_destroy(pfft_setup->fft_yz);
- free(pfft_setup->slab2grid_x);
- free(pfft_setup->slab2grid_y);
- if (pfft_setup->aav) {
- free(pfft_setup->aav->sdisps);
- free(pfft_setup->aav->scounts);
- free(pfft_setup->aav->rdisps);
- free(pfft_setup->aav->rcounts);
- free(pfft_setup->aav);
+int
+gmx_parallel_3dfft_execute(gmx_parallel_3dfft_t pfft_setup,
+ enum gmx_fft_direction dir,
+ void * in_data,
+ void * out_data) {
+ if ((!(pfft_setup->p1->flags&FFT5D_REALCOMPLEX)) ^ (dir==GMX_FFT_FORWARD ||dir==GMX_FFT_BACKWARD)) {
+ gmx_fatal(FARGS,"Invalid transform. Plan and execution don't match regarding reel/complex");
+ }
+ if (dir==GMX_FFT_FORWARD || dir==GMX_FFT_REAL_TO_COMPLEX) {
+ fft5d_execute(pfft_setup->p1,0);
+ } else {
+ fft5d_execute(pfft_setup->p2,0);
}
- free(pfft_setup->work_rawptr);
- free(pfft_setup->work2_rawptr);
-
return 0;
}
-#else
-/* Dummy function to avoid warnings without MPI enabled */
-void
-gmx_parallel_3dfft_dummy()
-{
+int
+gmx_parallel_3dfft_destroy(gmx_parallel_3dfft_t pfft_setup) {
+ fft5d_destroy(pfft_setup->p2);
+ fft5d_destroy(pfft_setup->p1);
+ sfree(pfft_setup);
+ return 0;
}
-#endif /* GMX_MPI */
+
+
+
typedef struct gmx_qhop_db_t *gmx_qhop_db;
-/* Return database if succesfull, or NULL on failure */
+/* Return database if successful, or NULL on failure */
extern gmx_qhop_db gmx_qhop_db_read(char *forcefield);
-/* Write the database to a filename. Return 1 on succes, or 0 for
+/* Write the database to a filename. Return 1 on success, or 0 for
failure */
extern int gmx_qhop_db_write(char *fn,gmx_qhop_db qdb);
/* Destroy the internal datastructures to free memory. Return 1 on
- succes, 0 for failure */
+ success, 0 for failure */
extern int gmx_qhop_db_done(gmx_qhop_db qdb);
/* Return the number of states in the database for a given residue
return buf;
}
-static void set_state_entries(t_state *state,t_inputrec *ir,int nnodes)
+void set_state_entries(t_state *state,t_inputrec *ir,int nnodes)
{
int nnhpres;
snew(state->sd_X,state->nalloc);
}
}
- if (ir->eI == eiCG) {
- state->flags |= (1<<estCGP);
- }
+ if (ir->eI == eiCG)
+ {
+ state->flags |= (1<<estCGP);
+ if (state->cg_p == NULL)
+ {
+ /* cg_p is not stored in the tpx file, so we need to allocate it */
+ snew(state->cg_p,state->nalloc);
+ }
+ }
if (EI_SD(ir->eI) || ir->eI == eiBD || ir->etc == etcVRESCALE) {
state->nrng = gmx_rng_n();
state->nrngi = 1;
init_energyhistory(&state->enerhist);
}
-void init_single(FILE *fplog,t_inputrec *inputrec,
- const char *tpxfile,gmx_mtop_t *mtop,
- t_state *state)
-{
- read_tpx_state(tpxfile,inputrec,state,NULL,mtop);
- set_state_entries(state,inputrec,1);
-
- if (fplog)
- pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE);
-}
-void init_parallel(FILE *log,const char *tpxfile,t_commrec *cr,
- t_inputrec *inputrec,gmx_mtop_t *mtop,
- t_state *state,
- int list)
+void init_parallel(FILE *log, t_commrec *cr, t_inputrec *inputrec,
+ gmx_mtop_t *mtop, t_state *state)
{
- char buf[256];
-
- if (MASTER(cr)) {
- init_inputrec(inputrec);
- read_tpx_state(tpxfile,inputrec,state,NULL,mtop);
- /* When we will be doing domain decomposition with separate PME nodes
- * the rng entries will be too large, we correct for this later.
- */
- set_state_entries(state,inputrec,cr->nnodes);
- }
bcast_ir_mtop(cr,inputrec,mtop);
-#ifdef GMX_THREADS
- /* Check if we did not automatically start multiple threads,
- * while an algorithm does not support parallel simulation.
- */
- if (inputrec->eI == eiLBFGS ||
- inputrec->eI == eiNM ||
- inputrec->coulombtype == eelEWALD)
- {
- if (cr->nnodes > 1 && MASTERTHREAD(cr))
- {
- fprintf(stderr,"\nThe integration or electrostatics algorithm doesn't support parallel runs.\n");
- }
- cancel_par_threads(cr);
- }
-#endif
if (inputrec->eI == eiBD || EI_SD(inputrec->eI)) {
/* Make sure the random seeds are different on each node */
inputrec->ld_seed += cr->nodeid;
}
-
- /* Printing */
- if (list!=0 && log!=NULL)
- {
- if (list&LIST_INPUTREC)
- pr_inputrec(log,0,"parameters of the run",inputrec,FALSE);
- if (list&LIST_X)
- pr_rvecs(log,0,"box",state->box,DIM);
- if (list&LIST_X)
- pr_rvecs(log,0,"box_rel",state->box_rel,DIM);
- if (list&LIST_V)
- pr_rvecs(log,0,"boxv",state->boxv,DIM);
- if (list&LIST_X)
- pr_rvecs(log,0,int_title("x",0,buf,255),state->x,state->natoms);
- if (list&LIST_V)
- pr_rvecs(log,0,int_title("v",0,buf,255),state->v,state->natoms);
- if (list&LIST_TOP)
- pr_mtop(log,0,int_title("topology",cr->nodeid,buf,255),mtop,TRUE);
- fflush(log);
- }
}
fp = gmx_fio_fopen(filename,"w+");
xvgr_header(fp,title,label_x,label_y,exvggtXNY,oenv);
- sprintf(buf,"T = %g (K)",ir->opts.ref_t[0]);
+ if (ir->delta_lambda == 0)
+ {
+ sprintf(buf,"T = %g (K), %s = %g",
+ ir->opts.ref_t[0],lambda,ir->init_lambda);
+ }
+ else
+ {
+ sprintf(buf,"T = %g (K)",
+ ir->opts.ref_t[0]);
+ }
xvgr_subtitle(fp,buf,oenv);
if (ir->n_flambda > 0)
fprintf(out," Number of steps = %12d\n",nsteps);
}
-static void warn_step(FILE *fp,real ftol,bool bConstrain)
+static void warn_step(FILE *fp,real ftol,bool bLastStep,bool bConstrain)
{
- fprintf(fp,"\nStepsize too small, or no change in energy.\n"
- "Converged to machine precision,\n"
- "but not to the requested precision Fmax < %g\n",
- ftol);
- if (sizeof(real)<sizeof(double))
- fprintf(fp,"\nDouble precision normally gives you higher accuracy.\n");
-
- if (bConstrain)
- fprintf(fp,"You might need to increase your constraint accuracy, or turn\n"
- "off constraints alltogether (set constraints = none in mdp file)\n");
+ if (bLastStep)
+ {
+ fprintf(fp,"\nReached the maximum number of steps before reaching Fmax < %g\n",ftol);
+ }
+ else
+ {
+ fprintf(fp,"\nStepsize too small, or no change in energy.\n"
+ "Converged to machine precision,\n"
+ "but not to the requested precision Fmax < %g\n",
+ ftol);
+ if (sizeof(real)<sizeof(double))
+ {
+ fprintf(fp,"\nDouble precision normally gives you higher accuracy.\n");
+ }
+ if (bConstrain)
+ {
+ fprintf(fp,"You might need to increase your constraint accuracy, or turn\n"
+ "off constraints alltogether (set constraints = none in mdp file)\n");
+ }
+ }
}
}
state_global->ngtc = 0;
- if (ir->eI == eiCG)
- {
- state_global->flags |= (1<<estCGP);
- snew(state_global->cg_p,state_global->nalloc);
- }
/* Initiate some variables */
if (ir->efep != efepNO)
{
*graph = NULL;
}
- }
-
- clear_rvec(mu_tot);
- calc_shifts(ems->s.box,fr->shift_vec);
-
- if (PARTDECOMP(cr)) {
- pd_at_range(cr,&start,&homenr);
- homenr -= start;
- } else {
- start = 0;
- homenr = top_global->natoms;
- }
- atoms2md(top_global,ir,0,NULL,start,homenr,mdatoms);
- update_mdatoms(mdatoms,state_global->lambda);
-
- if (vsite && !DOMAINDECOMP(cr)) {
- set_vsite_top(vsite,*top,mdatoms,cr);
- }
- if (constr) {
- if (ir->eConstrAlg == econtSHAKE &&
- gmx_mtop_ftype_count(top_global,F_CONSTR) > 0) {
- gmx_fatal(FARGS,"Can not do energy minimization with %s, use %s\n",
- econstr_names[econtSHAKE],econstr_names[econtLINCS]);
+ if (PARTDECOMP(cr))
+ {
+ pd_at_range(cr,&start,&homenr);
+ homenr -= start;
+ }
+ else
+ {
+ start = 0;
+ homenr = top_global->natoms;
+ }
+ atoms2md(top_global,ir,0,NULL,start,homenr,mdatoms);
+ update_mdatoms(mdatoms,state_global->lambda);
+
+ if (vsite)
+ {
+ set_vsite_top(vsite,*top,mdatoms,cr);
+ }
}
+
+ if (constr)
+ {
+ if (ir->eConstrAlg == econtSHAKE &&
+ gmx_mtop_ftype_count(top_global,F_CONSTR) > 0)
+ {
+ gmx_fatal(FARGS,"Can not do energy minimization with %s, use %s\n",
+ econstr_names[econtSHAKE],econstr_names[econtLINCS]);
+ }
+
+ if (!DOMAINDECOMP(cr))
+ {
+ set_constraints(constr,*top,ir,mdatoms,cr);
+ }
- if (!DOMAINDECOMP(cr))
- set_constraints(constr,*top,ir,mdatoms,cr);
-
- /* Constrain the starting coordinates */
- dvdlambda=0;
- constrain(PAR(cr) ? NULL : fplog,TRUE,TRUE,constr,&(*top)->idef,
- ir,NULL,cr,-1,0,mdatoms,
- ems->s.x,ems->s.x,NULL,ems->s.box,ems->s.lambda,&dvdlambda,
- NULL,NULL,nrnb,econqCoord,FALSE,0,0);
- }
-
- if (PAR(cr)) {
- *gstat = global_stat_init(ir);
- }
+ if (!ir->bContinuation)
+ {
+ /* Constrain the starting coordinates */
+ dvdlambda=0;
+ constrain(PAR(cr) ? NULL : fplog,TRUE,TRUE,constr,&(*top)->idef,
+ ir,NULL,cr,-1,0,mdatoms,
+ ems->s.x,ems->s.x,NULL,ems->s.box,
+ ems->s.lambda,&dvdlambda,
+ NULL,NULL,nrnb,econqCoord,FALSE,0,0);
+ }
+ }
+
+ if (PAR(cr))
+ {
+ *gstat = global_stat_init(ir);
+ }
+
+ *outf = init_mdoutf(nfile,fnm,0,cr,ir,NULL);
- *outf = init_mdoutf(nfile,fnm,FALSE,cr,ir,NULL);
+ snew(*enerd,1);
+ init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,*enerd);
- snew(*enerd,1);
- init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,*enerd);
+ /* Init bin for energy stuff */
+ *mdebin = init_mdebin((*outf)->fp_ene,top_global,ir);
- /* Init bin for energy stuff */
- *mdebin = init_mdebin((*outf)->fp_ene,top_global,ir);
+ clear_rvec(mu_tot);
+ calc_shifts(ems->s.box,fr->shift_vec);
}
static void finish_em(FILE *fplog,t_commrec *cr,gmx_mdoutf_t *outf)
* Each successful step is counted, and we continue until
* we either converge or reach the max number of steps.
*/
- for(step=0,converged=FALSE;( step<=number_steps || number_steps==0) && !converged;step++) {
+ converged = FALSE;
+ for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged;step++) {
/* start taking steps in a new direction
* First time we enter the routine, beta=0, and the direction is
if (converged)
step--; /* we never took that last step in this case */
- if (s_min->fmax > inputrec->em_tol) {
- if (MASTER(cr)) {
- warn_step(stderr,inputrec->em_tol,FALSE);
- warn_step(fplog,inputrec->em_tol,FALSE);
+ if (s_min->fmax > inputrec->em_tol)
+ {
+ if (MASTER(cr))
+ {
+ warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
+ warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
+ }
+ converged = FALSE;
}
- converged = FALSE;
- }
if (MASTER(cr)) {
/* If we printed energy and/or logfile last step (which was the last step)
ncorr=0;
/* Set the gradient from the force */
- for(step=0,converged=FALSE;( step<=number_steps || number_steps==0) && !converged;step++) {
+ converged = FALSE;
+ for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged; step++) {
/* Write coordinates if necessary */
do_x = do_per_step(step,inputrec->nstxout);
if(converged)
step--; /* we never took that last step in this case */
- if(fmax>inputrec->em_tol) {
- if (MASTER(cr)) {
- warn_step(stderr,inputrec->em_tol,FALSE);
- warn_step(fplog,inputrec->em_tol,FALSE);
+ if(fmax>inputrec->em_tol)
+ {
+ if (MASTER(cr))
+ {
+ warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
+ warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
+ }
+ converged = FALSE;
}
- converged = FALSE;
- }
/* If we printed energy and/or logfile last step (which was the last step)
* we don't have to do it again, but otherwise print the final values.
bDone = FALSE;
bAbort = FALSE;
while( !bDone && !bAbort ) {
- bAbort = (nsteps > 0) && (count==nsteps);
+ bAbort = (nsteps >= 0) && (count == nsteps);
/* set new coordinates, except for first step */
if (count > 0) {
/* Check if stepsize is too small, with 1 nm as a characteristic length */
#ifdef GMX_DOUBLE
- if (ustep < 1e-12)
+ if (count == nsteps || ustep < 1e-12)
#else
- if (ustep < 1e-6)
+ if (count == nsteps || ustep < 1e-6)
#endif
- {
- if (MASTER(cr)) {
- warn_step(stderr,inputrec->em_tol,constr!=NULL);
- warn_step(fplog,inputrec->em_tol,constr!=NULL);
- }
- bAbort=TRUE;
- }
+ {
+ if (MASTER(cr))
+ {
+ warn_step(stderr,inputrec->em_tol,count==nsteps,constr!=NULL);
+ warn_step(fplog ,inputrec->em_tol,count==nsteps,constr!=NULL);
+ }
+ bAbort=TRUE;
+ }
count++;
} /* End of the loop */
/* added with respect to mdrun */
int idum,jdum,kdum,row,col;
real der_range=10.0*sqrt(GMX_REAL_EPS);
+ real x_min;
real fnorm,fmax;
real dfdx;
+ if (constr != NULL)
+ {
+ gmx_fatal(FARGS,"Constraints present with Normal Mode Analysis, this combination is not supported");
+ }
+
state_work = init_em_state();
/* Init em and store the local state in state_minimum */
for (idum=0; (idum<DIM); idum++)
{
- row = DIM*step+idum;
+ row = DIM*step+idum;
- state_work->s.x[step][idum] -= der_range;
+ x_min = state_work->s.x[step][idum];
+
+ state_work->s.x[step][idum] = x_min - der_range;
- evaluate_energy(fplog,bVerbose,cr,
- state_global,top_global,state_work,top,
- inputrec,nrnb,wcycle,gstat,
- vsite,constr,fcd,graph,mdatoms,fr,
- mu_tot,enerd,vir,pres,count,count==0);
- count++;
+ evaluate_energy(fplog,bVerbose,cr,
+ state_global,top_global,state_work,top,
+ inputrec,nrnb,wcycle,gstat,
+ vsite,constr,fcd,graph,mdatoms,fr,
+ mu_tot,enerd,vir,pres,count,count==0);
+ count++;
- for ( i=0 ; i < top_global->natoms ; i++ )
- {
- copy_rvec ( state_work->f[i] , fneg[i] );
- }
-
- state_work->s.x[step][idum] += 2*der_range;
-
- evaluate_energy(fplog,bVerbose,cr,
- state_global,top_global,state_work,top,
- inputrec,nrnb,wcycle,gstat,
- vsite,constr,fcd,graph,mdatoms,fr,
- mu_tot,enerd,vir,pres,count,count==0);
- count++;
-
- for ( i=0 ; i < top_global->natoms ; i++ )
- {
- copy_rvec ( state_work->f[i] , fpos[i] );
- }
-
- for (jdum=0; (jdum<top_global->natoms); jdum++)
+ for ( i=0 ; i < top_global->natoms ; i++ )
+ {
+ copy_rvec ( state_work->f[i] , fneg[i] );
+ }
+
+ state_work->s.x[step][idum] = x_min + der_range;
+
+ evaluate_energy(fplog,bVerbose,cr,
+ state_global,top_global,state_work,top,
+ inputrec,nrnb,wcycle,gstat,
+ vsite,constr,fcd,graph,mdatoms,fr,
+ mu_tot,enerd,vir,pres,count,count==0);
+ count++;
+
+ for ( i=0 ; i < top_global->natoms ; i++ )
+ {
+ copy_rvec ( state_work->f[i] , fpos[i] );
+ }
+
+ for (jdum=0; (jdum<top_global->natoms); jdum++)
{
for (kdum=0; (kdum<DIM); kdum++)
{
- dfdx=-(fpos[jdum][kdum]-fneg[jdum][kdum])/(2*der_range);
- col = DIM*jdum+kdum;
+ dfdx = -(fpos[jdum][kdum] - fneg[jdum][kdum])/(2*der_range);
+ col = DIM*jdum+kdum;
- if(bSparse)
+ if (bSparse)
{
- if(col>=row && dfdx!=0.0)
- gmx_sparsematrix_increment_value(sparse_matrix,row,col,dfdx);
+ if (col>=row && dfdx!=0.0)
+ {
+ gmx_sparsematrix_increment_value(sparse_matrix,
+ row,col,dfdx);
+ }
}
else
{
}
/* x is restored to original */
- state_work->s.x[step][idum] -= der_range;
+ state_work->s.x[step][idum] = x_min;
if (bVerbose && fplog)
+ {
fflush(fplog);
+ }
}
/* write progress */
if (MASTER(cr) && bVerbose)
grid->dc_nalloc = 0;
if (debug)
- fprintf(debug,"Succesfully freed memory for grid pointers.");
+ fprintf(debug,"Successfully freed memory for grid pointers.");
}
int xyz2ci_(int nry,int nrz,int x,int y,int z)
#include <config.h>
#endif
+#include <math.h>
+
#include "perf_est.h"
#include "physics.h"
#include "vec.h"
t_atom *atom;
int mb,nmol,atnr,cg,a,a0,ncqlj,ncq,nclj;
bool bBHAM,bLJcut,bChargePerturbed,bWater,bQ,bLJ;
- double nw,nqlj,nq,nlj,cost_bond,cost_pp,cost_spread,cost_fft;
- float fq,fqlj,flj,fljtab,fqljw,fqw,fqspread,ffft,fbond;
+ double nw,nqlj,nq,nlj;
+ double cost_bond,cost_pp,cost_spread,cost_fft,cost_solve,cost_pme;
+ float fq,fqlj,flj,fljtab,fqljw,fqw,fqspread,ffft,fsolve,fbond;
float ratio;
t_iparams *iparams;
gmx_moltype_t *molt;
bLJcut = ((ir->vdwtype == evdwCUT) && !bBHAM);
- /* Computational cost relative to a tabulated q-q interaction.
+ /* Computational cost of bonded, non-bonded and PME calculations.
* This will be machine dependent.
* The numbers here are accurate for Intel Core2 and AMD Athlon 64
* in single precision. In double precision PME mesh is slightly cheaper,
* although not so much that the numbers need to be adjusted.
*/
- fq = 1.0;
+ fq = 1.5;
fqlj = (bLJcut ? 1.5 : 2.0 );
- flj = (bLJcut ? 0.5 : 1.5 );
+ flj = (bLJcut ? 1.0 : 1.75);
/* Cost of 1 water with one Q/LJ atom */
- fqljw = (bLJcut ? 1.75 : 2.25);
+ fqljw = (bLJcut ? 2.0 : 2.25);
/* Cost of 1 water with one Q atom or with 1/3 water (LJ negligible) */
- fqw = 1.5;
- /* Cost of q spreading and force interpolation per charge */
- fqspread = 25.0;
- /* Cost of fft's + pme_solve, will be multiplied with N log(N) */
- ffft = 0.4;
- /* Cost of a bonded interaction divided by the number of (pbc_)dx required */
+ fqw = 1.75;
+ /* Cost of q spreading and force interpolation per charge (mainly memory) */
+ fqspread = 0.55;
+ /* Cost of fft's, will be multiplied with N log(N) */
+ ffft = 0.20;
+ /* Cost of pme_solve, will be multiplied with N */
+ fsolve = 0.80;
+ /* Cost of a bonded interaction divided by the number of (pbc_)dx nrequired */
fbond = 5.0;
iparams = mtop->ffparams.iparams;
flj *nlj*(nw + nqlj + nlj))
*4/3*M_PI*ir->rlist*ir->rlist*ir->rlist/det(box);
- cost_spread = fqspread*(3*nw + nqlj + nq);
+ cost_spread = fqspread*(3*nw + nqlj + nq)*pow(ir->pme_order,3);
cost_fft = ffft*ir->nkx*ir->nky*ir->nkz*log(ir->nkx*ir->nky*ir->nkz);
+ cost_solve = fsolve*ir->nkx*ir->nky*ir->nkz;
if (ir->efep != efepNO && bChargePerturbed) {
/* All PME work, except the spline coefficient calculation, doubles */
cost_spread *= 2;
cost_fft *= 2;
+ cost_solve *= 2;
}
- ratio =
- (cost_spread + cost_fft)/(cost_bond + cost_pp + cost_spread + cost_fft);
+ cost_pme = cost_spread + cost_fft + cost_solve;
+
+ ratio = cost_pme/(cost_bond + cost_pp + cost_pme);
if (debug) {
fprintf(debug,
"cost_bond %f\n"
"cost_pp %f\n"
"cost_spread %f\n"
- "cost_fft %f\n",
- cost_bond,cost_pp,cost_spread,cost_fft);
+ "cost_fft %f\n"
+ "cost_solve %f\n",
+ cost_bond,cost_pp,cost_spread,cost_fft,cost_solve);
fprintf(debug,"Estimate for relative PME load: %.3f\n",ratio);
}
#include "smalloc.h"
#include "futil.h"
#include "coulomb.h"
-#include "fftgrid.h"
#include "gmx_fatal.h"
#include "pme.h"
#include "network.h"
#include "nrnb.h"
#include "copyrite.h"
#include "gmx_wallcycle.h"
-#include "sighandler.h"
+#include "gmx_parallel_3dfft.h"
+#include "pdbio.h"
+#if ( !defined(GMX_DOUBLE) && ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) )
+#include "gmx_sse2_single.h"
+#endif
#include "mpelogging.h"
/* Internal datastructures */
typedef struct {
- int snd0;
- int snds;
- int rcv0;
- int rcvs;
+ int send_index0;
+ int send_nindex;
+ int recv_index0;
+ int recv_nindex;
} pme_grid_comm_t;
typedef struct {
#ifdef GMX_MPI
MPI_Comm mpi_comm;
#endif
- int nslab;
- int *s2g;
- int nleftbnd,nrightbnd; /* The number of nodes to communicate with */
- int nodeid,*leftid,*rightid;
- pme_grid_comm_t *leftc,*rightc;
+ int nnodes,nodeid;
+ int ndata;
+ int *s2g0;
+ int *s2g1;
+ int noverlap_nodes;
+ int *send_id,*recv_id;
+ pme_grid_comm_t *comm_data;
} pme_overlap_t;
typedef struct {
typedef struct gmx_pme {
int ndecompdim; /* The number of decomposition dimensions */
int nodeid; /* Our nodeid in mpi->mpi_comm */
+ int nodeid_major;
+ int nodeid_minor;
int nnodes; /* The number of nodes doing PME */
-#ifdef GMX_MPI
+ int nnodes_major;
+ int nnodes_minor;
+
MPI_Comm mpi_comm;
- MPI_Comm mpi_comm_d[2];
+ MPI_Comm mpi_comm_d[2]; /* Indexed on dimension, 0=x, 1=y */
+#ifdef GMX_MPI
MPI_Datatype rvec_mpi; /* the pme vector's MPI type */
#endif
int nkx,nky,nkz; /* Grid dimensions */
int pme_order;
real epsilon_r;
- t_fftgrid *gridA,*gridB;
+
+ real * pmegridA; /* Grids on which we do spreading/interpolation, includes overlap */
+ real * pmegridB;
+ int pmegrid_nx,pmegrid_ny,pmegrid_nz;
+ int pmegrid_start_ix,pmegrid_start_iy,pmegrid_start_iz;
+
+ real * pmegrid_sendbuf;
+ real * pmegrid_recvbuf;
+
+ real *fftgridA; /* Grids for FFT. With 1D FFT decomposition this can be a pointer */
+ real *fftgridB; /* inside the interpolation grid, but separate for 2D PME decomp. */
+ int fftgrid_nx,fftgrid_ny,fftgrid_nz;
+
+ t_complex *cfftgridA; /* Grids for complex FFT data */
+ t_complex *cfftgridB;
+ int cfftgrid_nx,cfftgrid_ny,cfftgrid_nz;
+
+ gmx_parallel_3dfft_t pfft_setupA;
+ gmx_parallel_3dfft_t pfft_setupB;
+
int *nnx,*nny,*nnz;
+ real *fshx,*fshy,*fshz;
- pme_atomcomm_t atc[2];
+ pme_atomcomm_t atc[2]; /* Indexed on decomposition index */
matrix recipbox;
splinevec bsp_mod;
- pme_overlap_t overlap[2];
+ pme_overlap_t overlap[2]; /* Indexed on dimension, 0=x, 1=y */
+
pme_atomcomm_t atc_energy; /* Only for gmx_pme_calc_energy */
int buf_nalloc; /* The communication buffer size */
/* work data for solve_pme */
- int maxkz;
+ int work_nalloc;
+ real * work_mhx;
+ real * work_mhy;
real * work_mhz;
real * work_m2;
real * work_denom;
+ real * work_tmp1_alloc;
real * work_tmp1;
real * work_m2inv;
real * sum_qgrid_dd_tmp;
} t_gmx_pme;
-/* #define SORTPME */
-
-static void pr_grid_dist(FILE *fp,char *title,t_fftgrid *grid)
-{
- int i,j,k,l,ntoti,ntot=0;
- int nx,ny,nz,nx2,ny2,nz2,la12,la2;
- real * ptr;
-
- /* Unpack structure */
- unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
- for(i=0; (i<nx); i++) {
- ntoti=0;
- for(j=0; (j<ny); j++)
- for(k=0; (k<nz); k++) {
- l= INDEX(i,j,k);
- if (ptr[l] != 0) {
- ntoti++;
- ntot++;
- }
- }
- fprintf(fp,"%-12s %5d %5d\n",title,i,ntoti);
- }
- fprintf(fp,"%d non zero elements in %s\n",ntot,title);
-}
-/* test */
-
-static void calc_recipbox(matrix box,matrix recipbox)
-{
- /* Save some time by assuming upper right part is zero */
-
- real tmp=1.0/(box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]);
-
- recipbox[XX][XX]=box[YY][YY]*box[ZZ][ZZ]*tmp;
- recipbox[XX][YY]=0;
- recipbox[XX][ZZ]=0;
- recipbox[YY][XX]=-box[YY][XX]*box[ZZ][ZZ]*tmp;
- recipbox[YY][YY]=box[XX][XX]*box[ZZ][ZZ]*tmp;
- recipbox[YY][ZZ]=0;
- recipbox[ZZ][XX]=(box[YY][XX]*box[ZZ][YY]-box[YY][YY]*box[ZZ][XX])*tmp;
- recipbox[ZZ][YY]=-box[ZZ][YY]*box[XX][XX]*tmp;
- recipbox[ZZ][ZZ]=box[XX][XX]*box[YY][YY]*tmp;
-}
-static void calc_idx(gmx_pme_t pme,pme_atomcomm_t *atc)
+static void calc_interpolation_idx(gmx_pme_t pme,pme_atomcomm_t *atc)
{
int i;
int *idxptr,tix,tiy,tiz;
real *xptr,*fptr,tx,ty,tz;
real rxx,ryx,ryy,rzx,rzy,rzz;
- int nx,ny,nz,nx2,ny2,nz2,la12,la2;
- real *ptr;
-
-#if (defined __GNUC__ && (defined i386 || defined __386__) && !defined GMX_DOUBLE && defined GMX_X86TRUNC)
- int x86_cw,x86_cwsave;
-
- asm("fnstcw %0" : "=m" (*&x86_cwsave));
- x86_cw = x86_cwsave | 3072;
- asm("fldcw %0" : : "m" (*&x86_cw));
-#define x86trunc(a,b) asm("fld %1\nfistpl %0\n" : "=m" (*&b) : "f" (a));
-#endif
-
- /* Unpack structure */
- unpack_fftgrid(pme->gridA,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
+ int nx,ny,nz;
+ int start_ix,start_iy,start_iz;
+
+ nx = pme->nkx;
+ ny = pme->nky;
+ nz = pme->nkz;
+
+ start_ix = pme->pmegrid_start_ix;
+ start_iy = pme->pmegrid_start_iy;
+ start_iz = pme->pmegrid_start_iz;
rxx = pme->recipbox[XX][XX];
ryx = pme->recipbox[YY][XX];
idxptr = atc->idx[i];
fptr = atc->fractx[i];
- /* Fractional coordinates along box vectors */
- tx = nx2 + nx * ( xptr[XX] * rxx + xptr[YY] * ryx + xptr[ZZ] * rzx );
- ty = ny2 + ny * ( xptr[YY] * ryy + xptr[ZZ] * rzy );
- tz = nz2 + nz * ( xptr[ZZ] * rzz );
+ /* Fractional coordinates along box vectors, add 2.0 to make 100% sure we are positive for triclinic boxes */
+ tx = nx * ( xptr[XX] * rxx + xptr[YY] * ryx + xptr[ZZ] * rzx + 2.0 );
+ ty = ny * ( xptr[YY] * ryy + xptr[ZZ] * rzy + 2.0 );
+ tz = nz * ( xptr[ZZ] * rzz + 2.0 );
-#if (defined __GNUC__ && (defined i386 || defined __386__) && !defined GMX_DOUBLE && defined GMX_X86TRUNC)
- x86trunc(tx,tix);
- x86trunc(ty,tiy);
- x86trunc(tz,tiz);
-#else
tix = (int)(tx);
tiy = (int)(ty);
tiz = (int)(tz);
-#endif
- fptr[XX] = tx - tix;
- fptr[YY] = ty - tiy;
+ /* Because decomposition only occurs in x and y,
+ * we never have a fraction correction in z.
+ */
+ fptr[XX] = tx - tix + pme->fshx[tix];
+ fptr[YY] = ty - tiy + pme->fshy[tiy];
fptr[ZZ] = tz - tiz;
-
+
idxptr[XX] = pme->nnx[tix];
idxptr[YY] = pme->nny[tiy];
idxptr[ZZ] = pme->nnz[tiz];
#ifdef DEBUG
- range_check(idxptr[XX],0,nx);
- range_check(idxptr[YY],0,ny);
- range_check(idxptr[ZZ],0,nz);
+ range_check(idxptr[XX],0,pme->pmegrid_nx);
+ range_check(idxptr[YY],0,pme->pmegrid_ny);
+ range_check(idxptr[ZZ],0,pme->pmegrid_nz);
#endif
}
-#if (defined __GNUC__ && (defined i386 || defined __386__) && !defined GMX_DOUBLE && defined GMX_X86TRUNC)
- asm("fldcw %0" : : "m" (*&x86_cwsave));
-#endif
}
-static void pme_calc_pidx(int natoms,matrix box, rvec x[],
+static void pme_calc_pidx(int natoms, matrix recipbox, rvec x[],
pme_atomcomm_t *atc)
{
int nslab,i;
int si;
real *xptr,s;
real rxx,ryx,rzx,ryy,rzy;
- matrix recipbox;
-
+ int *pd,*count;
+
/* Calculate PME task index (pidx) for each grid index.
* Here we always assign equally sized slabs to each node
* for load balancing reasons (the PME grid spacing is not used).
*/
nslab = atc->nslab;
+ pd = atc->pd;
+ count = atc->count;
/* Reset the count */
for(i=0; i<nslab; i++)
{
- atc->count[i] = 0;
+ count[i] = 0;
}
- calc_recipbox(box,recipbox);
if (atc->dimind == 0)
{
rxx = recipbox[XX][XX];
xptr = x[i];
/* Fractional coordinates along box vectors */
s = nslab*(xptr[XX]*rxx + xptr[YY]*ryx + xptr[ZZ]*rzx);
- si = (int)(s + nslab) - nslab;
- if (si < 0)
- {
- si += nslab;
- }
- else if (si >= nslab)
- {
- si -= nslab;
- }
- atc->pd[i] = si;
- atc->count[si]++;
+ si = (int)(s + 2*nslab) % nslab;
+ pd[i] = si;
+ count[si]++;
}
}
else
xptr = x[i];
/* Fractional coordinates along box vectors */
s = nslab*(xptr[YY]*ryy + xptr[ZZ]*rzy);
- si = (int)(s + nslab) - nslab;
- if (si < 0)
- {
- si += nslab;
- }
- else if (si >= nslab)
- {
- si -= nslab;
- }
- atc->pd[i] = si;
- atc->count[si]++;
+ si = (int)(s + 2*nslab) % nslab;
+ pd[i] = si;
+ count[si]++;
}
}
}
static void pme_realloc_atomcomm_things(pme_atomcomm_t *atc)
{
- int i;
+ int nalloc_old,i;
if (atc->n > atc->nalloc) {
+ nalloc_old = atc->nalloc;
atc->nalloc = over_alloc_dd(atc->n);
if (atc->nslab > 1) {
srenew(atc->x,atc->nalloc);
srenew(atc->q,atc->nalloc);
srenew(atc->f,atc->nalloc);
+ for(i=nalloc_old; i<atc->nalloc; i++)
+ {
+ clear_rvec(atc->f[i]);
+ }
}
if (atc->bSpread) {
for(i=0;i<DIM;i++) {
}
}
-static void pmeredist(gmx_pme_t pme, bool forw,
- int n, bool bXF, rvec *x_f, real *charge,
- pme_atomcomm_t *atc)
+static void pmeredist_pd(gmx_pme_t pme, bool forw,
+ int n, bool bXF, rvec *x_f, real *charge,
+ pme_atomcomm_t *atc)
/* Redistribute particle data for PME calculation */
/* domain decomposition by x coordinate */
{
}
if (bX) {
if (atc->count[atc->nodeid] + nsend != n)
- gmx_fatal(FARGS,"%d particles communicated to PME node %d are more than a cell length out of the domain decomposition cell of their charge group in dimension %c",
+ gmx_fatal(FARGS,"%d particles communicated to PME node %d are more than 2/3 times the cut-off out of the domain decomposition cell of their charge group in dimension %c.\n"
+ "This usually means that your system is not well equilibrated.",
n - (atc->count[atc->nodeid] + nsend),
pme->nodeid,'x'+atc->dimind);
}
}
-static void gmx_sum_qgrid_dd(gmx_pme_t pme, pme_overlap_t *ol,t_fftgrid *grid,
- int direction)
-{
- int b,i;
- int la12r,localsize;
- pme_grid_comm_t *pgc;
- real *from, *to;
- real *tmp;
#ifdef GMX_MPI
+static void
+gmx_sum_qgrid_dd(gmx_pme_t pme, real *grid, int direction)
+{
+ pme_overlap_t *overlap;
+ int send_index0,send_nindex;
+ int recv_index0,recv_nindex;
MPI_Status stat;
-#endif
+ int i,j,k,ix,iy,iz,icnt;
+ int ipulse,send_id,recv_id,datasize;
+ real *p;
+ real *sendptr,*recvptr;
- GMX_MPE_LOG(ev_sum_qgrid_start);
-
-#ifdef GMX_MPI
+ /* Start with minor-rank communication. This is a bit of a pain since it is not contiguous */
+ overlap = &pme->overlap[1];
- la12r = grid->la12r;
- localsize = la12r*grid->pfft.local_nx;
-
- if (grid->workspace) {
- tmp = grid->workspace;
- } else {
- if (pme->sum_qgrid_dd_tmp == NULL) {
- snew(pme->sum_qgrid_dd_tmp,localsize);
+ for(ipulse=0;ipulse<overlap->noverlap_nodes;ipulse++)
+ {
+ /* Since we have already (un)wrapped the overlap in the z-dimension,
+ * we only have to communicate 0 to nkz (not pmegrid_nz).
+ */
+ if (direction==GMX_SUM_QGRID_FORWARD)
+ {
+ send_id = overlap->send_id[ipulse];
+ recv_id = overlap->recv_id[ipulse];
+ send_index0 = overlap->comm_data[ipulse].send_index0;
+ send_nindex = overlap->comm_data[ipulse].send_nindex;
+ recv_index0 = overlap->comm_data[ipulse].recv_index0;
+ recv_nindex = overlap->comm_data[ipulse].recv_nindex;
}
- tmp = pme->sum_qgrid_dd_tmp;
- }
-
- if (direction == GMX_SUM_QGRID_FORWARD) {
- /* sum contributions to local grid */
- /* Send left boundaries */
- for(b=0; b<ol->nleftbnd; b++) {
- pgc = &ol->leftc[b];
- from = grid->ptr + la12r*pgc->snd0;
- to = grid->ptr + la12r*pgc->rcv0;
- MPI_Sendrecv(from,la12r*pgc->snds,mpi_type,
- ol->leftid[b], ol->nodeid,
- tmp, la12r*pgc->rcvs,mpi_type,
- ol->rightid[b],ol->rightid[b],
- ol->mpi_comm,&stat);
- GMX_MPE_LOG(ev_test_start);
- for(i=0; (i<la12r*pgc->rcvs); i++) {
- to[i] += tmp[i];
+ else
+ {
+ send_id = overlap->recv_id[ipulse];
+ recv_id = overlap->send_id[ipulse];
+ send_index0 = overlap->comm_data[ipulse].recv_index0;
+ send_nindex = overlap->comm_data[ipulse].recv_nindex;
+ recv_index0 = overlap->comm_data[ipulse].send_index0;
+ recv_nindex = overlap->comm_data[ipulse].send_nindex;
+ }
+
+ /* Copy data to contiguous send buffer */
+ if (debug)
+ {
+ fprintf(debug,"PME send node %d %d -> %d grid start %d Communicating %d to %d\n",
+ pme->nodeid,overlap->nodeid,send_id,
+ pme->pmegrid_start_iy,
+ send_index0-pme->pmegrid_start_iy,
+ send_index0-pme->pmegrid_start_iy+send_nindex);
+ }
+ icnt = 0;
+ for(i=0;i<pme->pmegrid_nx;i++)
+ {
+ ix = i;
+ for(j=0;j<send_nindex;j++)
+ {
+ iy = j + send_index0 - pme->pmegrid_start_iy;
+ for(k=0;k<pme->nkz;k++)
+ {
+ iz = k;
+ pme->pmegrid_sendbuf[icnt++] = grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz];
+ }
}
}
- GMX_MPE_LOG(ev_test_finish);
- /* Send right boundaries */
- for(b=0; b<ol->nrightbnd; b++) {
- pgc = &ol->rightc[b];
- from = grid->ptr + la12r*pgc->snd0;
- to = grid->ptr + la12r*pgc->rcv0;
- MPI_Sendrecv(from,la12r*pgc->snds,mpi_type,
- ol->rightid[b],ol->nodeid,
- tmp, la12r*pgc->rcvs,mpi_type,
- ol->leftid[b], ol->leftid[b],
- ol->mpi_comm,&stat);
- GMX_MPE_LOG(ev_test_start);
- for(i=0; (i<la12r*pgc->rcvs); i++) {
- to[i] += tmp[i];
+
+ datasize = pme->pmegrid_nx * pme->nkz;
+
+ MPI_Sendrecv(pme->pmegrid_sendbuf,send_nindex*datasize,GMX_MPI_REAL,
+ send_id,ipulse,
+ pme->pmegrid_recvbuf,recv_nindex*datasize,GMX_MPI_REAL,
+ recv_id,ipulse,
+ overlap->mpi_comm,&stat);
+
+ /* Get data from contiguous recv buffer */
+ if (debug)
+ {
+ fprintf(debug,"PME recv node %d %d <- %d grid start %d Communicating %d to %d\n",
+ pme->nodeid,overlap->nodeid,recv_id,
+ pme->pmegrid_start_iy,
+ recv_index0-pme->pmegrid_start_iy,
+ recv_index0-pme->pmegrid_start_iy+recv_nindex);
+ }
+ icnt = 0;
+ for(i=0;i<pme->pmegrid_nx;i++)
+ {
+ ix = i;
+ for(j=0;j<recv_nindex;j++)
+ {
+ iy = j + recv_index0 - pme->pmegrid_start_iy;
+ for(k=0;k<pme->nkz;k++)
+ {
+ iz = k;
+ if(direction==GMX_SUM_QGRID_FORWARD)
+ {
+ grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz] += pme->pmegrid_recvbuf[icnt++];
+ }
+ else
+ {
+ grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz] = pme->pmegrid_recvbuf[icnt++];
+ }
+ }
}
}
- GMX_MPE_LOG(ev_test_finish);
- }
- else if (direction == GMX_SUM_QGRID_BACKWARD) {
- /* distribute local grid to all processors */
- /* Send right boundaries */
- for(b=0; b<ol->nrightbnd; b++) {
- pgc = &ol->rightc[b];
- from = grid->ptr + la12r*pgc->rcv0;
- to = grid->ptr + la12r*pgc->snd0;
- MPI_Sendrecv(from,la12r*pgc->rcvs,mpi_type,
- ol->leftid[b], ol->nodeid,
- to, la12r*pgc->snds,mpi_type,
- ol->rightid[b],ol->rightid[b],
- ol->mpi_comm,&stat);
+ }
+
+ /* Major dimension is easier, no copying required,
+ * but we might have to sum to separate array.
+ * Since we don't copy, we have to communicate up to pmegrid_nz,
+ * not nkz as for the minor direction.
+ */
+ overlap = &pme->overlap[0];
+
+ for(ipulse=0;ipulse<overlap->noverlap_nodes;ipulse++)
+ {
+ if(direction==GMX_SUM_QGRID_FORWARD)
+ {
+ send_id = overlap->send_id[ipulse];
+ recv_id = overlap->recv_id[ipulse];
+ send_index0 = overlap->comm_data[ipulse].send_index0;
+ send_nindex = overlap->comm_data[ipulse].send_nindex;
+ recv_index0 = overlap->comm_data[ipulse].recv_index0;
+ recv_nindex = overlap->comm_data[ipulse].recv_nindex;
+ recvptr = pme->pmegrid_recvbuf;
+ }
+ else
+ {
+ send_id = overlap->recv_id[ipulse];
+ recv_id = overlap->send_id[ipulse];
+ send_index0 = overlap->comm_data[ipulse].recv_index0;
+ send_nindex = overlap->comm_data[ipulse].recv_nindex;
+ recv_index0 = overlap->comm_data[ipulse].send_index0;
+ recv_nindex = overlap->comm_data[ipulse].send_nindex;
+ recvptr = grid + (recv_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+ }
+
+ sendptr = grid + (send_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+ datasize = pme->pmegrid_ny * pme->pmegrid_nz;
+
+ if (debug)
+ {
+ fprintf(debug,"PME send node %d %d -> %d grid start %d Communicating %d to %d\n",
+ pme->nodeid,overlap->nodeid,send_id,
+ pme->pmegrid_start_ix,
+ send_index0-pme->pmegrid_start_ix,
+ send_index0-pme->pmegrid_start_ix+send_nindex);
+ fprintf(debug,"PME recv node %d %d <- %d grid start %d Communicating %d to %d\n",
+ pme->nodeid,overlap->nodeid,recv_id,
+ pme->pmegrid_start_ix,
+ recv_index0-pme->pmegrid_start_ix,
+ recv_index0-pme->pmegrid_start_ix+recv_nindex);
}
- /* Send left boundaries */
- for(b=0; b<ol->nleftbnd; b++) {
- pgc = &ol->leftc[b];
- from = grid->ptr + la12r*pgc->rcv0;
- to = grid->ptr + la12r*pgc->snd0;
- MPI_Sendrecv(from,la12r*pgc->rcvs,mpi_type,
- ol->rightid[b],ol->nodeid,
- to, la12r*pgc->snds,mpi_type,
- ol->leftid[b], ol->leftid[b],
- ol->mpi_comm,&stat);
+
+ MPI_Sendrecv(sendptr,send_nindex*datasize,GMX_MPI_REAL,
+ send_id,ipulse,
+ recvptr,recv_nindex*datasize,GMX_MPI_REAL,
+ recv_id,ipulse,
+ overlap->mpi_comm,&stat);
+
+ /* ADD data from contiguous recv buffer */
+ if(direction==GMX_SUM_QGRID_FORWARD)
+ {
+ p = grid + (recv_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+ for(i=0;i<recv_nindex*datasize;i++)
+ {
+ p[i] += pme->pmegrid_recvbuf[i];
+ }
}
}
- else {
- gmx_fatal(FARGS,"Invalid direction %d for summing qgrid",direction);
+}
+#endif
+
+
+static int
+copy_pmegrid_to_fftgrid(gmx_pme_t pme, real *pmegrid, real *fftgrid)
+{
+ ivec local_fft_ndata,local_fft_offset,local_fft_size;
+ ivec local_pme_size;
+ int i,ix,iy,iz;
+ int pmeidx,fftidx;
+
+ /* Dimensions should be identical for A/B grid, so we just use A here */
+ gmx_parallel_3dfft_real_limits(pme->pfft_setupA,
+ local_fft_ndata,
+ local_fft_offset,
+ local_fft_size);
+
+ local_pme_size[0] = pme->pmegrid_nx;
+ local_pme_size[1] = pme->pmegrid_ny;
+ local_pme_size[2] = pme->pmegrid_nz;
+
+ /* The fftgrid is always 'justified' to the lower-left corner of the PME grid,
+ the offset is identical, and the PME grid always has more data (due to overlap)
+ */
+ {
+#ifdef DEBUG_PME
+ FILE *fp,*fp2;
+ char fn[STRLEN],format[STRLEN];
+ real val;
+ sprintf(fn,"pmegrid%d.pdb",pme->nodeid);
+ fp = ffopen(fn,"w");
+ sprintf(fn,"pmegrid%d.txt",pme->nodeid);
+ fp2 = ffopen(fn,"w");
+ sprintf(format,"%s%s\n",pdbformat,"%6.2f%6.2f");
+#endif
+ for(ix=0;ix<local_fft_ndata[XX];ix++)
+ {
+ for(iy=0;iy<local_fft_ndata[YY];iy++)
+ {
+ for(iz=0;iz<local_fft_ndata[ZZ];iz++)
+ {
+ pmeidx = ix*(local_pme_size[YY]*local_pme_size[ZZ])+iy*(local_pme_size[ZZ])+iz;
+ fftidx = ix*(local_fft_size[YY]*local_fft_size[ZZ])+iy*(local_fft_size[ZZ])+iz;
+ fftgrid[fftidx] = pmegrid[pmeidx];
+#ifdef DEBUG_PME
+ val = 100*pmegrid[pmeidx];
+ if (pmegrid[pmeidx] != 0)
+ fprintf(fp,format,"ATOM",pmeidx,"CA","GLY",' ',pmeidx,' ',
+ 5.0*ix,5.0*iy,5.0*iz,1.0,val);
+ if (pmegrid[pmeidx] != 0)
+ fprintf(fp2,"%-12s %5d %5d %5d %12.5e\n",
+ "qgrid",
+ pme->pmegrid_start_ix + ix,
+ pme->pmegrid_start_iy + iy,
+ pme->pmegrid_start_iz + iz,
+ pmegrid[pmeidx]);
+#endif
+ }
+ }
}
-
-#else
- gmx_fatal(FARGS,"Parallel grid summation requires MPI and FFTW.\n");
+#ifdef DEBUG_PME
+ fclose(fp);
+ fclose(fp2);
#endif
- GMX_MPE_LOG(ev_sum_qgrid_finish);
+ }
+ return 0;
}
-void gmx_sum_qgrid(gmx_pme_t pme,t_commrec *cr,t_fftgrid *grid,int direction)
+
+static int
+copy_fftgrid_to_pmegrid(gmx_pme_t pme, real *fftgrid, real *pmegrid)
{
- int i;
- int localsize;
- int maxproc;
- real *tmp;
-
-#ifdef GMX_MPI
- localsize=grid->la12r*grid->pfft.local_nx;
- maxproc=grid->nx/grid->pfft.local_nx;
+ ivec local_fft_ndata,local_fft_offset,local_fft_size;
+ ivec local_pme_size;
+ int i,ix,iy,iz;
+ int pmeidx,fftidx;
+
+ /* Dimensions should be identical for A/B grid, so we just use A here */
+ gmx_parallel_3dfft_real_limits(pme->pfft_setupA,
+ local_fft_ndata,
+ local_fft_offset,
+ local_fft_size);
+
+ local_pme_size[0] = pme->pmegrid_nx;
+ local_pme_size[1] = pme->pmegrid_ny;
+ local_pme_size[2] = pme->pmegrid_nz;
+
+ /* The fftgrid is always 'justified' to the lower-left corner of the PME grid,
+ the offset is identical, and the PME grid always has more data (due to overlap)
+ */
+ for(ix=0;ix<local_fft_ndata[XX];ix++)
+ {
+ for(iy=0;iy<local_fft_ndata[YY];iy++)
+ {
+ for(iz=0;iz<local_fft_ndata[ZZ];iz++)
+ {
+ pmeidx = ix*(local_pme_size[YY]*local_pme_size[ZZ])+iy*(local_pme_size[ZZ])+iz;
+ fftidx = ix*(local_fft_size[YY]*local_fft_size[ZZ])+iy*(local_fft_size[ZZ])+iz;
+ pmegrid[pmeidx] = fftgrid[fftidx];
+ }
+ }
+ }
+ return 0;
+}
+
+
+static void
+wrap_periodic_pmegrid(gmx_pme_t pme, real *pmegrid)
+{
+ int nx,ny,nz,pnx,pny,pnz,ny_x,overlap,ix,iy,iz;
+
+ nx = pme->nkx;
+ ny = pme->nky;
+ nz = pme->nkz;
+
+ pnx = pme->pmegrid_nx;
+ pny = pme->pmegrid_ny;
+ pnz = pme->pmegrid_nz;
+
+ overlap = pme->pme_order - 1;
- if(grid->workspace!=NULL)
+ /* Add periodic overlap in z */
+ for(ix=0; ix<pnx; ix++)
{
- tmp = grid->workspace;
+ for(iy=0; iy<pny; iy++)
+ {
+ for(iz=0; iz<overlap; iz++)
+ {
+ pmegrid[(ix*pny+iy)*pnz+iz] +=
+ pmegrid[(ix*pny+iy)*pnz+nz+iz];
+ }
+ }
+ }
+
+ if (pme->nnodes_minor == 1)
+ {
+ for(ix=0; ix<pnx; ix++)
+ {
+ for(iy=0; iy<overlap; iy++)
+ {
+ for(iz=0; iz<nz; iz++)
+ {
+ pmegrid[(ix*pny+iy)*pnz+iz] +=
+ pmegrid[(ix*pny+ny+iy)*pnz+iz];
+ }
+ }
+ }
}
- else
+
+ if (pme->nnodes_major == 1)
{
- if(pme->sum_qgrid_tmp==NULL)
+ ny_x = (pme->nnodes_minor == 1 ? ny : pny);
+
+ for(ix=0; ix<overlap; ix++)
{
- snew(pme->sum_qgrid_tmp,localsize);
+ for(iy=0; iy<ny_x; iy++)
+ {
+ for(iz=0; iz<nz; iz++)
+ {
+ pmegrid[(ix*pny+iy)*pnz+iz] +=
+ pmegrid[((nx+ix)*pny+iy)*pnz+iz];
+ }
+ }
}
- tmp = pme->sum_qgrid_tmp;
}
+}
- /* NOTE: FFTW doesnt necessarily use all processors for the fft;
- * above I assume that the ones that do have equal amounts of data.
- * this is bad since its not guaranteed by fftw, but works for now...
- * This will be fixed in the next release.
- */
- if (direction == GMX_SUM_QGRID_FORWARD) {
- /* sum contributions to local grid */
-
- GMX_BARRIER(cr->mpi_comm_mygroup);
- GMX_MPE_LOG(ev_reduce_start);
- for(i=0;i<maxproc;i++) {
- MPI_Reduce(grid->ptr+i*localsize, /*ptr arithm. */
- tmp,localsize,
- GMX_MPI_REAL,MPI_SUM,i,cr->mpi_comm_mygroup);
- }
- GMX_MPE_LOG(ev_reduce_finish);
-
- if(cr->nodeid<maxproc) {
- memcpy(grid->ptr+cr->nodeid*localsize,tmp,localsize*sizeof(real));
+
+static void
+unwrap_periodic_pmegrid(gmx_pme_t pme, real *pmegrid)
+{
+ int nx,ny,nz,pnx,pny,pnz,ny_x,overlap,ix,iy,iz;
+
+ nx = pme->nkx;
+ ny = pme->nky;
+ nz = pme->nkz;
+
+ pnx = pme->pmegrid_nx;
+ pny = pme->pmegrid_ny;
+ pnz = pme->pmegrid_nz;
+
+ overlap = pme->pme_order - 1;
+
+ if (pme->nnodes_major == 1)
+ {
+ ny_x = (pme->nnodes_minor == 1 ? ny : pny);
+
+ for(ix=0; ix<overlap; ix++)
+ {
+ for(iy=0; iy<ny_x; iy++)
+ {
+ for(iz=0; iz<nz; iz++)
+ {
+ pmegrid[((nx+ix)*pny+iy)*pnz+iz] =
+ pmegrid[(ix*pny+iy)*pnz+iz];
+ }
+ }
}
}
- else if (direction == GMX_SUM_QGRID_BACKWARD) {
- /* distribute local grid to all processors */
- for(i=0;i<maxproc;i++)
- MPI_Bcast(grid->ptr+i*localsize, /* ptr arithm */
- localsize,
- GMX_MPI_REAL,i,cr->mpi_comm_mygroup);
+
+ if (pme->nnodes_minor == 1)
+ {
+ for(ix=0; ix<pnx; ix++)
+ {
+ for(iy=0; iy<overlap; iy++)
+ {
+ for(iz=0; iz<nz; iz++)
+ {
+ pmegrid[(ix*pny+ny+iy)*pnz+iz] =
+ pmegrid[(ix*pny+iy)*pnz+iz];
+ }
+ }
+ }
}
- else {
- gmx_fatal(FARGS,"Invalid direction %d for summing qgrid",direction);
+
+ /* Copy periodic overlap in z */
+ for(ix=0; ix<pnx; ix++)
+ {
+ for(iy=0; iy<pny; iy++)
+ {
+ for(iz=0; iz<overlap; iz++)
+ {
+ pmegrid[(ix*pny+iy)*pnz+nz+iz] =
+ pmegrid[(ix*pny+iy)*pnz+iz];
+ }
+ }
}
-
-#else
- gmx_fatal(FARGS,"Parallel grid summation requires MPI and FFTW.\n");
-#endif
}
+
/* This has to be a macro to enable full compiler optimization with xlC (and probably others too) */
#define DO_BSPLINE(order) \
for(ithx=0; (ithx<order); ithx++) \
{ \
- index_x = la12*i0[ithx]; \
+ index_x = (i0+ithx)*pny*pnz; \
valx = qn*thx[ithx]; \
\
for(ithy=0; (ithy<order); ithy++) \
{ \
valxy = valx*thy[ithy]; \
- index_xy = index_x+la2*j0[ithy]; \
+ index_xy = index_x+(j0+ithy)*pnz; \
\
for(ithz=0; (ithz<order); ithz++) \
{ \
- index_xyz = index_xy+k0[ithz]; \
- ptr[index_xyz] += valxy*thz[ithz]; \
+ index_xyz = index_xy+(k0+ithz); \
+ grid[index_xyz] += valxy*thz[ithz]; \
} \
} \
}
-
static void spread_q_bsplines(gmx_pme_t pme, pme_atomcomm_t *atc,
- t_fftgrid *grid)
+ real *grid)
{
- /* spread charges from home atoms to local grid */
- real *ptr;
+
+ /* spread charges from home atoms to local grid */
pme_overlap_t *ol;
- int b,i,nn,n,*i0,*j0,*k0,*ii0,*jj0,*kk0,ithx,ithy,ithz;
- int nx,ny,nz,nx2,ny2,nz2,la2,la12;
- int order,norder,*idxptr,index_x,index_xy,index_xyz;
+ int b,i,nn,n,ithx,ithy,ithz,i0,j0,k0;
+ int * idxptr;
+ int order,norder,index_x,index_xy,index_xyz;
real valx,valxy,qn;
real *thx,*thy,*thz;
- int localsize, bndsize;
+ int localsize, bndsize;
- if (pme->ndecompdim == 0) {
- clear_fftgrid(grid);
-#ifdef GMX_MPI
- } else {
- localsize = grid->la12r*grid->pfft.local_nx;
- ptr = grid->ptr + grid->la12r*grid->pfft.local_x_start;
- for (i=0; (i<localsize); i++) {
- ptr[i] = 0;
- }
- ol = &pme->overlap[0];
- /* clear left boundary area */
- for(b=0; b<ol->nleftbnd; b++) {
- ptr = grid->ptr + ol->leftc[b].snd0*grid->la12r;
- bndsize = ol->leftc[b].snds*grid->la12r;
- for (i=0; (i<bndsize); i++) {
- ptr[i] = 0;
- }
- }
- /* clear right boundary area */
- for(b=0; b<ol->nrightbnd; b++) {
- ptr = grid->ptr + ol->rightc[b].snd0*grid->la12r;
- bndsize = ol->rightc[b].snds*grid->la12r;
- for (i=0; (i<bndsize); i++) {
- ptr[i] = 0;
- }
- }
-#endif
+ int pnx,pny,pnz,ndatatot;
+
+ pnx = pme->pmegrid_nx;
+ pny = pme->pmegrid_ny;
+ pnz = pme->pmegrid_nz;
+ ndatatot = pnx*pny*pnz;
+
+ for(i=0;i<ndatatot;i++)
+ {
+ grid[i] = 0;
}
- unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
-
order = pme->pme_order;
- ii0 = pme->nnx + nx2 + 1 - order/2;
- jj0 = pme->nny + ny2 + 1 - order/2;
- kk0 = pme->nnz + nz2 + 1 - order/2;
-
- switch (order)
- {
- case 4:
- for(nn=0; (nn<atc->n);nn++)
- {
- n = nn;
- qn = atc->q[n];
- idxptr = atc->idx[n];
-
- if(qn != 0)
- {
- norder = n*4;
-
- /* Pointer arithmetic alert, next six statements */
- i0 = ii0 + idxptr[XX];
- j0 = jj0 + idxptr[YY];
- k0 = kk0 + idxptr[ZZ];
- thx = atc->theta[XX] + norder;
- thy = atc->theta[YY] + norder;
- thz = atc->theta[ZZ] + norder;
-
-#if ((defined __IBMC__ || defined __IBMCPP__) && defined _IBMSMP)
- /* Magic optimization pragma proposed by Mathias Puetz */
-#pragma ibm independent_loop
-#endif
- DO_BSPLINE(4);
- }
- }
- break;
-
- default:
- for(nn=0; (nn<atc->n); nn++)
- {
- n = nn;
- qn = atc->q[n];
- idxptr = atc->idx[n];
-
- if (qn != 0)
- {
- norder = n*order;
-
- /* Pointer arithmetic alert, next six statements */
- i0 = ii0 + idxptr[XX];
- j0 = jj0 + idxptr[YY];
- k0 = kk0 + idxptr[ZZ];
- thx = atc->theta[XX] + norder;
- thy = atc->theta[YY] + norder;
- thz = atc->theta[ZZ] + norder;
-
-#if ((defined __IBMC__ || defined __IBMCPP__) && defined _IBMSMP)
- /* Magic optimization pragma proposed by Mathias Puetz */
-#pragma ibm independent_loop
-#endif
- DO_BSPLINE(order);
- }
- }
- break;
-
- }
-
+ for(nn=0; (nn<atc->n);nn++)
+ {
+ n = nn;
+ qn = atc->q[n];
+
+ if (qn != 0)
+ {
+ idxptr = atc->idx[n];
+ norder = n*order;
+
+ i0 = idxptr[XX];
+ j0 = idxptr[YY];
+ k0 = idxptr[ZZ];
+ thx = atc->theta[XX] + norder;
+ thy = atc->theta[YY] + norder;
+ thz = atc->theta[ZZ] + norder;
+
+ switch (order) {
+ case 4: DO_BSPLINE(4); break;
+ case 5: DO_BSPLINE(5); break;
+ default: DO_BSPLINE(order); break;
+ }
+ }
+ }
}
-real solve_pme(gmx_pme_t pme,t_fftgrid *grid,
- real ewaldcoeff,real vol,matrix vir,t_commrec *cr)
+
+#if ( !defined(GMX_DOUBLE) && ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) )
+ /* Calculate exponentials through SSE in float precision */
+#define CALC_EXPONENTIALS(start,end,r_aligned) \
+ { \
+ __m128 tmp_sse; \
+ for(kx=0; kx<end; kx+=4) \
+ { \
+ tmp_sse = _mm_load_ps(r_aligned+kx); \
+ tmp_sse = gmx_mm_exp_ps_lbc(tmp_sse); \
+ _mm_store_ps(r_aligned+kx,tmp_sse); \
+ } \
+ }
+#else
+#define CALC_EXPONENTIALS(start,end,r) \
+ for(kx=start; kx<end; kx++) \
+ { \
+ r[kx] = exp(r[kx]); \
+ }
+#endif
+
+
+static int solve_pme_yzx(gmx_pme_t pme,t_complex *grid,
+ real ewaldcoeff,real vol,
+ bool bEnerVir,real *mesh_energy,matrix vir)
{
/* do recip sum over local cells in grid */
- t_complex *ptr,*p0;
- int nx,ny,nz,nx2,ny2,nz2,la2,la12;
- int kx,ky,kz,maxkx,maxky,maxkz,kystart=0,kyend=0,kzstart;
+ /* y major, z middle, x minor or continuous */
+ t_complex *p0;
+ int kx,ky,kz,maxkx,maxky,maxkz;
+ int nx,ny,nz,iy,iz,kxstart,kxend;
real mx,my,mz;
real factor=M_PI*M_PI/(ewaldcoeff*ewaldcoeff);
real ets2,struct2,vfactor,ets2vf;
real eterm,d1,d2,energy=0;
- real bx,by;
- real mhx,mhy;
+ real by,bz;
real virxx=0,virxy=0,virxz=0,viryy=0,viryz=0,virzz=0;
real rxx,ryx,ryy,rzx,rzy,rzz;
- real *mhz,*m2,*denom,*tmp1,*m2inv;
-
-#if ((defined __IBMC__ || defined __IBMCPP__) && defined _IBMSMP)
- /* xlc optimization proposed by Mathias Puetz */
-#pragma disjoint(*mhz,*m2,*denom,*tmp1,*m2inv,*p0)
-#endif
-
- unpack_fftgrid(grid,&nx,&ny,&nz,
- &nx2,&ny2,&nz2,&la2,&la12,FALSE,(real **)&ptr);
+ real *mhx,*mhy,*mhz,*m2,*denom,*tmp1,*m2inv;
+ real mhxk,mhyk,mhzk,m2k;
+ real corner_fac;
+ ivec complex_order;
+ ivec local_ndata,local_offset,local_size;
+
+ nx = pme->nkx;
+ ny = pme->nky;
+ nz = pme->nkz;
+
+ /* Dimensions should be identical for A/B grid, so we just use A here */
+ gmx_parallel_3dfft_complex_limits(pme->pfft_setupA,
+ complex_order,
+ local_ndata,
+ local_offset,
+ local_size);
rxx = pme->recipbox[XX][XX];
ryx = pme->recipbox[YY][XX];
maxkx = (nx+1)/2;
maxky = (ny+1)/2;
maxkz = nz/2+1;
-
- if(maxkz > pme->maxkz)
- {
- /* At the moment the dimensions are actually fixed, but this is for the future... */
- srenew(pme->work_mhz,maxkz);
- srenew(pme->work_m2,maxkz);
- srenew(pme->work_denom,maxkz);
- srenew(pme->work_tmp1,maxkz);
- srenew(pme->work_m2inv,maxkz);
- pme->maxkz=maxkz;
- }
+ mhx = pme->work_mhx;
+ mhy = pme->work_mhy;
mhz = pme->work_mhz;
m2 = pme->work_m2;
denom = pme->work_denom;
tmp1 = pme->work_tmp1;
m2inv = pme->work_m2inv;
-
- if (pme->ndecompdim > 0) {
- /* transpose X & Y and only sum local cells */
-#ifdef GMX_MPI
- kystart = grid->pfft.local_y_start_after_transpose;
- kyend = kystart+grid->pfft.local_ny_after_transpose;
- if (debug)
- fprintf(debug,"solve_pme: kystart = %d, kyend=%d\n",kystart,kyend);
-#else
- gmx_fatal(FARGS,"Parallel PME attempted without MPI and FFTW");
-#endif /* end of parallel case loop */
- }
- else {
- kystart = 0;
- kyend = ny;
- }
-
- for(ky=kystart; (ky<kyend); ky++) { /* our local cells */
+
+ for(iy=0;iy<local_ndata[YY];iy++)
+ {
+ ky = iy + local_offset[YY];
- if(ky<maxky) {
+ if (ky < maxky)
+ {
my = ky;
- } else {
- my = (ky-ny);
}
- by = M_PI*vol*pme->bsp_mod[YY][ky];
+ else
+ {
+ my = (ky - ny);
+ }
- for(kx=0; (kx<nx); kx++) {
- if(kx < maxkx) {
- mx = kx;
- } else {
- mx = (kx-nx);
- }
+ by = M_PI*vol*pme->bsp_mod[YY][ky];
- mhx = mx * rxx;
- mhy = mx * ryx + my * ryy;
+ for(iz=0;iz<local_ndata[ZZ];iz++)
+ {
+ kz = iz + local_offset[ZZ];
- bx = pme->bsp_mod[XX][kx];
+ mz = kz;
+
+ bz = pme->bsp_mod[ZZ][kz];
- if (pme->nnodes > 1) {
- p0 = ptr + INDEX(ky,kx,0); /* Pointer Arithmetic */
- } else {
- p0 = ptr + INDEX(kx,ky,0); /* Pointer Arithmetic */
- }
+ /* 0.5 correction for corner points */
+ corner_fac = 1;
+ if (kz == 0)
+ corner_fac = 0.5;
+ if (kz == (nz+1)/2)
+ corner_fac = 0.5;
+
+ p0 = grid + iy*local_size[ZZ]*local_size[XX] + iz*local_size[XX];
- if ((kx>0) || (ky>0)) {
- kzstart = 0;
- } else {
- kzstart = 1;
- p0++;
+ /* We should skip the k-space point (0,0,0) */
+ if (local_offset[XX] > 0 ||
+ local_offset[YY] > 0 || ky > 0 ||
+ kz > 0)
+ {
+ kxstart = local_offset[XX];
}
-
- for(kz=kzstart,mz=kzstart; (kz<maxkz); kz++,mz+=1.0) {
- mhz[kz] = mx * rzx + my * rzy + mz * rzz;
- m2[kz] = mhx*mhx+mhy*mhy+mhz[kz]*mhz[kz];
- denom[kz] = m2[kz]*bx*by*pme->bsp_mod[ZZ][kz];
- tmp1[kz] = -factor*m2[kz];
+ else
+ {
+ kxstart = local_offset[XX] + 1;
+ p0++;
}
+ kxend = local_offset[XX] + local_ndata[XX];
- for(kz=kzstart; (kz<maxkz); kz++) m2inv[kz] = 1.0/m2[kz];
- for(kz=kzstart; (kz<maxkz); kz++) denom[kz] = 1.0/denom[kz];
- for(kz=kzstart; (kz<maxkz); kz++) tmp1[kz] = exp(tmp1[kz]);
-
- for(kz=kzstart; (kz<maxkz); kz++,p0++) {
- d1 = p0->re;
- d2 = p0->im;
-
- eterm = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kz]*denom[kz];
-
- p0->re = d1*eterm;
- p0->im = d2*eterm;
-
- struct2 = 2.0*(d1*d1+d2*d2);
-
- tmp1[kz] = eterm*struct2;
+ if (bEnerVir)
+ {
+ /* More expensive inner loop, especially because of the storage
+ * of the mh elements in array's.
+ * Because x is the minor grid index, all mh elements
+ * depend on kx for triclinic unit cells.
+ */
+
+ /* Two explicit loops to avoid a conditional inside the loop */
+ for(kx=kxstart; kx<maxkx; kx++)
+ {
+ mx = kx;
+
+ mhxk = mx * rxx;
+ mhyk = mx * ryx + my * ryy;
+ mhzk = mx * rzx + my * rzy + mz * rzz;
+ m2k = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+ mhx[kx] = mhxk;
+ mhy[kx] = mhyk;
+ mhz[kx] = mhzk;
+ m2[kx] = m2k;
+ denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+ tmp1[kx] = -factor*m2k;
+ }
+
+ for(kx=maxkx; kx<kxend; kx++)
+ {
+ mx = (kx - nx);
+
+ mhxk = mx * rxx;
+ mhyk = mx * ryx + my * ryy;
+ mhzk = mx * rzx + my * rzy + mz * rzz;
+ m2k = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+ mhx[kx] = mhxk;
+ mhy[kx] = mhyk;
+ mhz[kx] = mhzk;
+ m2[kx] = m2k;
+ denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+ tmp1[kx] = -factor*m2k;
+ }
+
+ for(kx=kxstart; kx<kxend; kx++)
+ {
+ m2inv[kx] = 1.0/m2[kx];
+ }
+ for(kx=kxstart; kx<kxend; kx++)
+ {
+ denom[kx] = 1.0/denom[kx];
+ }
+
+ CALC_EXPONENTIALS(kxstart,kxend,tmp1);
+
+ for(kx=kxstart; kx<kxend; kx++,p0++)
+ {
+ d1 = p0->re;
+ d2 = p0->im;
+
+ eterm = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kx]*denom[kx];
+
+ p0->re = d1*eterm;
+ p0->im = d2*eterm;
+
+ struct2 = 2.0*(d1*d1+d2*d2);
+
+ tmp1[kx] = eterm*struct2;
+ }
+
+ for(kx=kxstart; kx<kxend; kx++)
+ {
+ ets2 = corner_fac*tmp1[kx];
+ vfactor = (factor*m2[kx] + 1.0)*2.0*m2inv[kx];
+ energy += ets2;
+
+ ets2vf = ets2*vfactor;
+ virxx += ets2vf*mhx[kx]*mhx[kx] - ets2;
+ virxy += ets2vf*mhx[kx]*mhy[kx];
+ virxz += ets2vf*mhx[kx]*mhz[kx];
+ viryy += ets2vf*mhy[kx]*mhy[kx] - ets2;
+ viryz += ets2vf*mhy[kx]*mhz[kx];
+ virzz += ets2vf*mhz[kx]*mhz[kx] - ets2;
+ }
}
-
- /* 0.5 correction for corner points */
-
- if (kzstart == 0)
- tmp1[0] *= 0.5;
-
- if (((nz+1)/2) < maxkz)
- tmp1[((nz+1)/2)] *= 0.5;
-
- for(kz=kzstart; (kz<maxkz); kz++) {
- ets2 = tmp1[kz];
- vfactor = (factor*m2[kz]+1.0)*2.0*m2inv[kz];
- energy += ets2;
-
- ets2vf = ets2*vfactor;
- virxx += ets2vf*mhx*mhx-ets2;
- virxy += ets2vf*mhx*mhy;
- virxz += ets2vf*mhx*mhz[kz];
- viryy += ets2vf*mhy*mhy-ets2;
- viryz += ets2vf*mhy*mhz[kz];
- virzz += ets2vf*mhz[kz]*mhz[kz]-ets2;
+ else
+ {
+ /* We don't need to calculate the energy and the virial.
+ * In this case the triclinic overhead is small.
+ */
+
+ /* Two explicit loops to avoid a conditional inside the loop */
+
+ for(kx=kxstart; kx<maxkx; kx++)
+ {
+ mx = kx;
+
+ mhxk = mx * rxx;
+ mhyk = mx * ryx + my * ryy;
+ mhzk = mx * rzx + my * rzy + mz * rzz;
+ m2k = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+ denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+ tmp1[kx] = -factor*m2k;
+ }
+
+ for(kx=maxkx; kx<kxend; kx++)
+ {
+ mx = (kx - nx);
+
+ mhxk = mx * rxx;
+ mhyk = mx * ryx + my * ryy;
+ mhzk = mx * rzx + my * rzy + mz * rzz;
+ m2k = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+ denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+ tmp1[kx] = -factor*m2k;
+ }
+
+ for(kx=kxstart; kx<kxend; kx++)
+ {
+ denom[kx] = 1.0/denom[kx];
+ }
+
+ CALC_EXPONENTIALS(kxstart,kxend,tmp1);
+
+ for(kx=kxstart; kx<kxend; kx++,p0++)
+ {
+ d1 = p0->re;
+ d2 = p0->im;
+
+ eterm = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kx]*denom[kx];
+
+ p0->re = d1*eterm;
+ p0->im = d2*eterm;
+ }
}
}
}
- /* Update virial with local values. The virial is symmetric by definition.
- * this virial seems ok for isotropic scaling, but I'm
- * experiencing problems on semiisotropic membranes.
- * IS THAT COMMENT STILL VALID??? (DvdS, 2001/02/07).
- */
- vir[XX][XX] = 0.25*virxx;
- vir[YY][YY] = 0.25*viryy;
- vir[ZZ][ZZ] = 0.25*virzz;
- vir[XX][YY] = vir[YY][XX] = 0.25*virxy;
- vir[XX][ZZ] = vir[ZZ][XX] = 0.25*virxz;
- vir[YY][ZZ] = vir[ZZ][YY] = 0.25*viryz;
-
- /* This energy should be corrected for a charged system */
- return(0.5*energy);
+ if (bEnerVir)
+ {
+ /* Update virial with local values.
+ * The virial is symmetric by definition.
+ * this virial seems ok for isotropic scaling, but I'm
+ * experiencing problems on semiisotropic membranes.
+ * IS THAT COMMENT STILL VALID??? (DvdS, 2001/02/07).
+ */
+ vir[XX][XX] = 0.25*virxx;
+ vir[YY][YY] = 0.25*viryy;
+ vir[ZZ][ZZ] = 0.25*virzz;
+ vir[XX][YY] = vir[YY][XX] = 0.25*virxy;
+ vir[XX][ZZ] = vir[ZZ][XX] = 0.25*virxz;
+ vir[YY][ZZ] = vir[ZZ][YY] = 0.25*viryz;
+
+ /* This energy should be corrected for a charged system */
+ *mesh_energy = 0.5*energy;
+ }
+
+ /* Return the loop count */
+ return local_ndata[YY]*local_ndata[ZZ]*local_ndata[XX];
}
+
#define DO_FSPLINE(order) \
for(ithx=0; (ithx<order); ithx++) \
{ \
- index_x = la12*i0[ithx]; \
+ index_x = (i0+ithx)*pny*pnz; \
tx = thx[ithx]; \
dx = dthx[ithx]; \
- \
+ \
for(ithy=0; (ithy<order); ithy++) \
- { \
- index_xy = index_x+la2*j0[ithy]; \
+ { \
+ index_xy = index_x+(j0+ithy)*pnz; \
ty = thy[ithy]; \
dy = dthy[ithy]; \
fxy1 = fz1 = 0; \
\
for(ithz=0; (ithz<order); ithz++) \
- { \
- gval = ptr[index_xy+k0[ithz]]; \
- fxy1 += thz[ithz]*gval; \
- fz1 += dthz[ithz]*gval; \
- } \
- fx += dx*ty*fxy1; \
- fy += tx*dy*fxy1; \
- fz += tx*ty*fz1; \
- } \
+ { \
+ gval = grid[index_xy+(k0+ithz)]; \
+ fxy1 += thz[ithz]*gval; \
+ fz1 += dthz[ithz]*gval; \
+ } \
+ fx += dx*ty*fxy1; \
+ fy += tx*dy*fxy1; \
+ fz += tx*ty*fz1; \
+ } \
}
-void gather_f_bsplines(gmx_pme_t pme,t_fftgrid *grid,
+void gather_f_bsplines(gmx_pme_t pme,real *grid,
bool bClearF,pme_atomcomm_t *atc,real scale)
{
/* sum forces for local particles */
- int nn,n,*i0,*j0,*k0,*ii0,*jj0,*kk0,ithx,ithy,ithz;
- int nx,ny,nz,nx2,ny2,nz2,la2,la12,index_x,index_xy;
- real * ptr;
+ int nn,n,ithx,ithy,ithz,i0,j0,k0;
+ int index_x,index_xy;
+ int nx,ny,nz,pnx,pny,pnz;
+ int * idxptr;
real tx,ty,dx,dy,qn;
real fx,fy,fz,gval;
real fxy1,fz1;
real *thx,*thy,*thz,*dthx,*dthy,*dthz;
- int norder,*idxptr;
+ int norder;
real rxx,ryx,ryy,rzx,rzy,rzz;
int order;
- unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
order = pme->pme_order;
thx = atc->theta[XX];
thy = atc->theta[YY];
dthx = atc->dtheta[XX];
dthy = atc->dtheta[YY];
dthz = atc->dtheta[ZZ];
- ii0 = pme->nnx + nx2 + 1 - order/2;
- jj0 = pme->nny + ny2 + 1 - order/2;
- kk0 = pme->nnz + nz2 + 1 - order/2;
+ nx = pme->nkx;
+ ny = pme->nky;
+ nz = pme->nkz;
+ pnx = pme->pmegrid_nx;
+ pny = pme->pmegrid_ny;
+ pnz = pme->pmegrid_nz;
rxx = pme->recipbox[XX][XX];
ryx = pme->recipbox[YY][XX];
rzy = pme->recipbox[ZZ][YY];
rzz = pme->recipbox[ZZ][ZZ];
- for(nn=0; (nn<atc->n); nn++) {
+ for(nn=0; (nn<atc->n); nn++)
+ {
n = nn;
qn = scale*atc->q[n];
- if (bClearF) {
+ if (bClearF)
+ {
atc->f[n][XX] = 0;
atc->f[n][YY] = 0;
atc->f[n][ZZ] = 0;
}
- if (qn != 0) {
+ if (qn != 0)
+ {
fx = 0;
fy = 0;
fz = 0;
idxptr = atc->idx[n];
norder = n*order;
- /* Pointer arithmetic alert, next nine statements */
- i0 = ii0 + idxptr[XX];
- j0 = jj0 + idxptr[YY];
- k0 = kk0 + idxptr[ZZ];
+ i0 = idxptr[XX];
+ j0 = idxptr[YY];
+ k0 = idxptr[ZZ];
+
+ /* Pointer arithmetic alert, next six statements */
thx = atc->theta[XX] + norder;
thy = atc->theta[YY] + norder;
thz = atc->theta[ZZ] + norder;
dthy = atc->dtheta[YY] + norder;
dthz = atc->dtheta[ZZ] + norder;
- switch(order)
- {
- case 4 :
- DO_FSPLINE(4);
- break;
- default:
- DO_FSPLINE(order);
- break;
+ switch (order) {
+ case 4: DO_FSPLINE(4); break;
+ case 5: DO_FSPLINE(5); break;
+ default: DO_FSPLINE(order); break;
}
-
+
atc->f[n][XX] += -qn*( fx*nx*rxx );
atc->f[n][YY] += -qn*( fx*nx*ryx + fy*ny*ryy );
atc->f[n][ZZ] += -qn*( fx*nx*rzx + fy*ny*rzy + fz*nz*rzz );
*/
}
-static real gather_energy_bsplines(gmx_pme_t pme,t_fftgrid *grid,
+static real gather_energy_bsplines(gmx_pme_t pme,real *grid,
pme_atomcomm_t *atc)
{
- int n,*i0,*j0,*k0,*ii0,*jj0,*kk0,ithx,ithy,ithz;
- int nx,ny,nz,nx2,ny2,nz2,la2,la12,index_x,index_xy;
- real * ptr;
+ int n,ithx,ithy,ithz,i0,j0,k0;
+ int index_x,index_xy;
+ int * idxptr;
real energy,pot,tx,ty,qn,gval;
real *thx,*thy,*thz;
- int norder,*idxptr;
+ int norder;
int order;
- unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
+
order = pme->pme_order;
thx = atc->theta[XX];
thy = atc->theta[YY];
thz = atc->theta[ZZ];
- ii0 = pme->nnx + nx2 + 1 - order/2;
- jj0 = pme->nny + ny2 + 1 - order/2;
- kk0 = pme->nnz + nz2 + 1 - order/2;
energy = 0;
for(n=0; (n<atc->n); n++) {
idxptr = atc->idx[n];
norder = n*order;
- /* Pointer arithmetic alert, next nine statements */
- i0 = ii0 + idxptr[XX];
- j0 = jj0 + idxptr[YY];
- k0 = kk0 + idxptr[ZZ];
+ i0 = idxptr[XX];
+ j0 = idxptr[YY];
+ k0 = idxptr[ZZ];
+
+ /* Pointer arithmetic alert, next three statements */
thx = atc->theta[XX] + norder;
thy = atc->theta[YY] + norder;
thz = atc->theta[ZZ] + norder;
pot = 0;
for(ithx=0; (ithx<order); ithx++)
{
- index_x = la12*i0[ithx];
+ index_x = (i0+ithx)*pme->pmegrid_ny*pme->pmegrid_nz;
tx = thx[ithx];
for(ithy=0; (ithy<order); ithy++)
{
- index_xy = index_x+la2*j0[ithy];
+ index_xy = index_x+(j0+ithy)*pme->pmegrid_nz;
ty = thy[ithy];
for(ithz=0; (ithz<order); ithz++)
{
- gval = ptr[index_xy+k0[ithz]];
+ gval = grid[index_xy+(k0+ithz)];
pot += tx*ty*thz[ithz]*gval;
}
return energy;
}
-void make_bsplines(splinevec theta,splinevec dtheta,int order,int nx,int ny,
- int nz,rvec fractx[],int nr,real charge[],
+void make_bsplines(splinevec theta,splinevec dtheta,int order,
+ rvec fractx[],int nr,real charge[],
bool bFreeEnergy)
{
/* construct splines for local atoms */
sfree((*pmedata)->nny);
sfree((*pmedata)->nnz);
- done_fftgrid((*pmedata)->gridA);
- if((*pmedata)->gridB)
+ sfree((*pmedata)->pmegridA);
+ sfree((*pmedata)->fftgridA);
+ sfree((*pmedata)->cfftgridA);
+ gmx_parallel_3dfft_destroy((*pmedata)->pfft_setupA);
+
+ if((*pmedata)->pmegridB)
{
- done_fftgrid((*pmedata)->gridB);
+ sfree((*pmedata)->pmegridB);
+ sfree((*pmedata)->fftgridB);
+ sfree((*pmedata)->cfftgridB);
+ gmx_parallel_3dfft_destroy((*pmedata)->pfft_setupB);
}
sfree((*pmedata)->work_mhz);
sfree((*pmedata)->work_m2);
sfree((*pmedata)->work_denom);
- sfree((*pmedata)->work_tmp1);
+ sfree((*pmedata)->work_tmp1_alloc);
sfree((*pmedata)->work_m2inv);
sfree(*pmedata);
return 0;
}
-int pme_inconvenient_nnodes(int nkx,int nky,int nnodes)
+static int mult_up(int n,int f)
{
- int nnx,nny;
- float imbal;
- int ret;
-
- ret = 0;
- if (nnodes > nkx && nnodes > nky) {
- /* This is probably always bad */
- ret = 2;
- } else if (2*nnodes > nkx && nnodes != nkx) {
- /* This is inconvenient for the grid overlap communication */
- ret = 1;
- }
-
- /* Determine the maximum number of grid slabs per PME node */
- nnx = (nkx + nnodes - 1)/nnodes;
- nny = (nky + nnodes - 1)/nnodes;
- /* Estimate the FFT + solve_pme load imbalance.
- * Imbalance in x for 2D FFT.
- * Imbalance in y for 1D FFT + solve_pme.
- * x and y imbalance affect the performance roughly equally.
- */
- imbal = (nnx*nnodes/(float)nkx + nny*nnodes/(float)nky)*0.5 - 1;
- if (debug)
- fprintf(debug,"PME load imbalance estimate for npme=%d: %f\n",
- nnodes,imbal);
-
- /* The cost of charge spreading and force gathering (which is always
- * load balanced) is usually 1-2 times more than FFT+solve_pme.
- * So we compare the imbalance to (a rough guess of) the performance gain
- * in spreading and gathering with respect to one node less.
- */
- if (imbal > 2.0/nnodes) {
- ret = max(ret,2);
- } else if (imbal > 1.0/nnodes) {
- ret = max(ret,1);
- }
+ return ((n + f - 1)/f)*f;
+}
+
- return ret;
+static double pme_load_imbalance(gmx_pme_t pme)
+{
+ int nma,nmi;
+ double n1,n2,n3;
+
+ nma = pme->nnodes_major;
+ nmi = pme->nnodes_minor;
+
+ n1 = mult_up(pme->nkx,nma)*mult_up(pme->nky,nmi)*pme->nkz;
+ n2 = mult_up(pme->nkx,nma)*mult_up(pme->nkz,nmi)*pme->nky;
+ n3 = mult_up(pme->nky,nma)*mult_up(pme->nkz,nmi)*pme->nkx;
+
+ /* pme_solve is roughly double the cost of an fft */
+
+ return (n1 + n2 + 3*n3)/(double)(6*pme->nkx*pme->nky*pme->nkz);
}
static void init_atomcomm(gmx_pme_t pme,pme_atomcomm_t *atc, t_commrec *cr,
int dimind,bool bSpread)
{
- int lbnd,rbnd,maxlr,b,i;
- int nn,nk;
- pme_grid_comm_t *pgc;
+ int nk,k,s;
atc->dimind = dimind;
atc->nslab = 1;
atc->nodeid = 0;
atc->pd_nalloc = 0;
#ifdef GMX_MPI
- if (PAR(cr))
+ if (pme->nnodes > 1)
{
- atc->mpi_comm = pme->mpi_comm_d[atc->dimind];
+ atc->mpi_comm = pme->mpi_comm_d[dimind];
MPI_Comm_size(atc->mpi_comm,&atc->nslab);
MPI_Comm_rank(atc->mpi_comm,&atc->nodeid);
}
}
}
-static void init_overlap_comm(gmx_pme_t pme,pme_overlap_t *ol, t_commrec *cr)
+static void
+init_overlap_comm(pme_overlap_t * ol,
+ int norder,
+#ifdef GMX_MPI
+ MPI_Comm comm,
+#endif
+ int nnodes,
+ int nodeid,
+ int ndata)
{
int lbnd,rbnd,maxlr,b,i;
+ int exten;
int nn,nk;
pme_grid_comm_t *pgc;
-
+ bool bCont;
+ int fft_start,fft_end,send_index1,recv_index1;
+
#ifdef GMX_MPI
- ol->mpi_comm = pme->mpi_comm;
+ ol->mpi_comm = comm;
#endif
-
- ol->nodeid = pme->nodeid;
- nn = pme->nnodes;
- nk = pme->nkx;
+ ol->nnodes = nnodes;
+ ol->nodeid = nodeid;
+
+ ol->ndata = ndata;
- /* Determine the grid boundary communication sizes and nodes */
- if (nk % nn == 0) {
- lbnd = pme->pme_order/2 - 1;
- } else {
- lbnd = pme->pme_order - (pme->pme_order/2 - 1) - 1;
- }
- rbnd = pme->pme_order - (pme->pme_order/2 - 1) - 1;
- /* Round up */
- ol->nleftbnd = (lbnd*nn + nk - 1)/nk;
- ol->nrightbnd = (rbnd*nn + nk - 1)/nk;
- maxlr = max(ol->nleftbnd,ol->nrightbnd);
- snew(ol->leftid, maxlr);
- snew(ol->rightid,maxlr);
- for(b=0; b<maxlr; b++) {
- ol->leftid[b] = (ol->nodeid - (b + 1) + nn) % nn;
- ol->rightid[b] = (ol->nodeid + (b + 1)) % nn;
- }
- snew(ol->leftc, ol->nleftbnd);
- snew(ol->rightc,ol->nrightbnd);
- snew(ol->s2g,nn+1);
- for(i=0; i<nn+1; i++) {
- /* The definition of the grid position requires rounding up here */
- ol->s2g[i] = (i*nk + nn - 1)/nn;
- }
- /* The left boundary */
- for(b=0; b<ol->nleftbnd; b++) {
- pgc = &ol->leftc[b];
- /* Send */
- i = ol->s2g[ol->nodeid];
- if (ol->leftid[b] > ol->nodeid) {
- i += pme->nkx;
+ /* Linear translation of the PME grid wo'nt affect reciprocal space
+ * calculations, so to optimize we only interpolate "upwards",
+ * which also means we only have to consider overlap in one direction.
+ * I.e., particles on this node might also be spread to grid indices
+ * that belong to higher nodes (modulo nnodes)
+ */
+
+ snew(ol->s2g0,ol->nnodes+1);
+ snew(ol->s2g1,ol->nnodes);
+ if (debug) { fprintf(debug,"PME slab boundaries:"); }
+ for(i=0; i<nnodes; i++)
+ {
+ /* s2g0 the local interpolation grid start.
+ * s2g1 the local interpolation grid end.
+ * Because grid overlap communication only goes forward,
+ * the grid the slabs for fft's should be rounded down.
+ */
+ ol->s2g0[i] = ( i *ndata + 0 )/nnodes;
+ ol->s2g1[i] = ((i+1)*ndata + nnodes-1)/nnodes + norder - 1;
+
+ if (debug)
+ {
+ fprintf(debug," %3d %3d",ol->s2g0[i],ol->s2g1[i]);
}
- pgc->snd0 = max(i - lbnd,ol->s2g[ol->leftid[b]]);
- pgc->snds = min(i ,ol->s2g[ol->leftid[b]+1]) - pgc->snd0;
- pgc->snds = max(pgc->snds,0);
- /* Receive */
- i = ol->s2g[ol->rightid[b]];
- if (ol->rightid[b] < ol->nodeid)
- i += pme->nkx;
- pgc->rcv0 = max(i - lbnd,ol->s2g[ol->nodeid]);
- pgc->rcvs = min(i ,ol->s2g[ol->nodeid+1]) - pgc->rcv0;
- pgc->rcvs = max(pgc->rcvs,0);
- }
- /* The right boundary */
- for(b=0; b<ol->nrightbnd; b++) {
- pgc = &ol->rightc[b];
+ }
+ ol->s2g0[nnodes] = ndata;
+ if (debug) { fprintf(debug,"\n"); }
+
+ /* Determine with how many nodes we need to communicate the grid overlap */
+ b = 0;
+ do
+ {
+ b++;
+ bCont = FALSE;
+ for(i=0; i<nnodes; i++)
+ {
+ if ((i+b < nnodes && ol->s2g1[i] > ol->s2g0[i+b]) ||
+ (i+b >= nnodes && ol->s2g1[i] > ol->s2g0[i+b-nnodes] + ndata))
+ {
+ bCont = TRUE;
+ }
+ }
+ }
+ while (bCont && b < nnodes);
+ ol->noverlap_nodes = b - 1;
+
+ snew(ol->send_id,ol->noverlap_nodes);
+ snew(ol->recv_id,ol->noverlap_nodes);
+ for(b=0; b<ol->noverlap_nodes; b++)
+ {
+ ol->send_id[b] = (ol->nodeid + (b + 1)) % ol->nnodes;
+ ol->recv_id[b] = (ol->nodeid - (b + 1) + ol->nnodes) % ol->nnodes;
+ }
+ snew(ol->comm_data, ol->noverlap_nodes);
+
+ for(b=0; b<ol->noverlap_nodes; b++)
+ {
+ pgc = &ol->comm_data[b];
/* Send */
- i = ol->s2g[ol->nodeid+1];
- if (ol->rightid[b] < ol->nodeid) {
- i -= nk;
+ fft_start = ol->s2g0[ol->send_id[b]];
+ fft_end = ol->s2g0[ol->send_id[b]+1];
+ if (ol->send_id[b] < nodeid)
+ {
+ fft_start += ol->ndata;
+ fft_end += ol->ndata;
+ }
+ send_index1 = ol->s2g1[nodeid];
+ send_index1 = min(send_index1,fft_end);
+ pgc->send_index0 = fft_start;
+ pgc->send_nindex = max(0,send_index1 - pgc->send_index0);
+
+ /* We always start receiving to the first index of our slab */
+ fft_start = ol->s2g0[ol->nodeid];
+ fft_end = ol->s2g0[ol->nodeid+1];
+ recv_index1 = ol->s2g1[ol->recv_id[b]];
+ if (ol->recv_id[b] > nodeid)
+ {
+ recv_index1 -= ol->ndata;
+ }
+ recv_index1 = min(recv_index1,fft_end);
+ pgc->recv_index0 = fft_start;
+ pgc->recv_nindex = max(0,recv_index1 - pgc->recv_index0);
+ }
+}
+
+static void
+make_gridindex5_to_localindex(int n,int local_start,int local_end,
+ int **global_to_local,
+ real **fraction_shift)
+{
+ int local_size,i;
+ int * gtl;
+ real * fsh;
+
+ local_size = local_end - local_start;
+
+ snew(gtl,5*n);
+ snew(fsh,5*n);
+ for(i=0; (i<5*n); i++) {
+ /* Determine the global to local grid index */
+ gtl[i] = (i - local_start + n) % n;
+ /* For coordinates that fall within the local grid the fraction
+ * is correct, we don't need to shift it.
+ */
+ fsh[i] = 0;
+ if (local_size < n)
+ {
+ /* Due to rounding issues i could be 1 beyond the lower or
+ * upper boundary of the local grid. Correct the index for this.
+ * If we shift the index, we need to shift the fraction by
+ * the same amount in the other direction to not affect
+ * the weights.
+ * Note that due to this shifting the weights at the end of
+ * the spline might change, but that will only involve values
+ * between zero and values close to the precision of a real,
+ * which is anyhow the accuracy of the whole mesh calculation.
+ */
+ /* With local_size=0 we should not change i=local_start */
+ if (i % n != local_start)
+ {
+ if (gtl[i] == n-1)
+ {
+ gtl[i] = 0;
+ fsh[i] = -1;
+ }
+ else if (gtl[i] == local_size)
+ {
+ gtl[i] = local_size - 1;
+ fsh[i] = 1;
+ }
+ }
+ }
+ }
+
+ *global_to_local = gtl;
+ *fraction_shift = fsh;
+}
+
+static void
+gmx_pme_check_grid_restrictions(FILE *fplog,char dim,int nnodes,int *nk)
+{
+ int nk_new;
+
+ if (*nk % nnodes != 0)
+ {
+ nk_new = nnodes*(*nk/nnodes + 1);
+
+ if (2*nk_new >= 3*(*nk))
+ {
+ gmx_fatal(FARGS,"The PME grid size in dim %c (%d) is not divisble by the number of nodes doing PME in dim %c (%d). The grid size would have to be increased by more than 50%% to make the grid divisible. Change the total number of nodes or the number of domain decomposition cells in x or the PME grid %c dimension (and the cut-off).",
+ dim,*nk,dim,nnodes,dim);
}
- pgc->snd0 = max(i ,ol->s2g[ol->rightid[b]]);
- pgc->snds = min(i + rbnd,ol->s2g[ol->rightid[b]+1]) - pgc->snd0;
- pgc->snds = max(pgc->snds,0);
- /* Receive */
- i = ol->s2g[ol->leftid[b]+1];
- if (ol->leftid[b] > ol->nodeid)
- i -= pme->nkx;
- pgc->rcv0 = max(i ,ol->s2g[ol->nodeid]);
- pgc->rcvs = min(i + rbnd,ol->s2g[ol->nodeid+1]) - pgc->rcv0;
- pgc->rcvs = max(pgc->rcvs,0);
+
+ if (fplog != NULL)
+ {
+ fprintf(fplog,"\nNOTE: The PME grid size in dim %c (%d) is not divisble by the number of nodes doing PME in dim %c (%d). Increasing the PME grid size in dim %c to %d. This will increase the accuracy and will not decrease the performance significantly on this number of nodes. For optimal performance change the total number of nodes or the number of domain decomposition cells in x or the PME grid %c dimension (and the cut-off).\n\n",
+ dim,*nk,dim,nnodes,dim,nk_new,dim);
+ }
+
+ *nk = nk_new;
}
}
-int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,int nnodes_major,
- t_inputrec *ir,int homenr,
- bool bFreeEnergy,
- bool bReproducible)
+int gmx_pme_init(gmx_pme_t * pmedata,
+ t_commrec * cr,
+ int nnodes_major,
+ int nnodes_minor,
+ t_inputrec * ir,
+ int homenr,
+ bool bFreeEnergy,
+ bool bReproducible)
{
gmx_pme_t pme=NULL;
pme_atomcomm_t *atc;
- int nminor,b,d,i,lbnd,rbnd,maxlr;
-
+ int bufsizex,bufsizey,bufsize;
+ ivec ndata;
if (debug)
fprintf(debug,"Creating PME data structures.\n");
snew(pme,1);
+
+ pme->redist_init = FALSE;
+ pme->sum_qgrid_tmp = NULL;
+ pme->sum_qgrid_dd_tmp = NULL;
+ pme->buf_nalloc = 0;
+ pme->redist_buf_nalloc = 0;
-
- pme->redist_init = FALSE;
- pme->sum_qgrid_tmp = NULL;
- pme->sum_qgrid_dd_tmp = NULL;
- pme->buf_nalloc = 0;
- pme->redist_buf_nalloc = 0;
+ pme->nnodes = 1;
+ pme->bPPnode = TRUE;
- pme->nnodes = 1;
- pme->bPPnode = TRUE;
+ pme->nnodes_major = nnodes_major;
+ pme->nnodes_minor = nnodes_minor;
+
#ifdef GMX_MPI
if (PAR(cr))
{
- pme->mpi_comm = cr->mpi_comm_mygroup;
+ pme->mpi_comm = cr->mpi_comm_mygroup;
+
MPI_Comm_rank(pme->mpi_comm,&pme->nodeid);
MPI_Comm_size(pme->mpi_comm,&pme->nnodes);
-
- pme->mpi_comm_d[0] = pme->mpi_comm;
}
#endif
if (pme->nnodes == 1)
{
pme->ndecompdim = 0;
+ pme->nodeid_major = 0;
+ pme->nodeid_minor = 0;
}
else
{
- if (pme->nnodes == nnodes_major)
+ if (nnodes_minor == 1)
{
+#ifdef GMX_MPI
+ pme->mpi_comm_d[0] = pme->mpi_comm;
+ pme->mpi_comm_d[1] = NULL;
+#endif
pme->ndecompdim = 1;
+ pme->nodeid_major = pme->nodeid;
+ pme->nodeid_minor = 0;
+
}
- else
+ else if (nnodes_major == 1)
+ {
+#ifdef GMX_MPI
+ pme->mpi_comm_d[0] = NULL;
+ pme->mpi_comm_d[1] = pme->mpi_comm;
+#endif
+ pme->ndecompdim = 1;
+ pme->nodeid_major = 0;
+ pme->nodeid_minor = pme->nodeid;
+ }
+ else
{
if (pme->nnodes % nnodes_major != 0)
{
- gmx_incons("nnodes_major incompatible with #PME nodes");
+ gmx_incons("For 2D PME decomposition, #PME nodes must be divisible by the number of nodes in the major dimension");
}
pme->ndecompdim = 2;
+
#ifdef GMX_MPI
- nminor = pme->nnodes/nnodes_major;
- MPI_Comm_split(pme->mpi_comm,pme->nodeid % nminor,
- pme->nodeid,&pme->mpi_comm_d[0]);
- MPI_Comm_split(pme->mpi_comm,pme->nodeid/nminor,
- pme->nodeid,&pme->mpi_comm_d[1]);
+ MPI_Comm_split(pme->mpi_comm,pme->nodeid % nnodes_minor,
+ pme->nodeid,&pme->mpi_comm_d[0]); /* My communicator along major dimension */
+ MPI_Comm_split(pme->mpi_comm,pme->nodeid/nnodes_minor,
+ pme->nodeid,&pme->mpi_comm_d[1]); /* My communicator along minor dimension */
+
+ MPI_Comm_rank(pme->mpi_comm_d[0],&pme->nodeid_major);
+ MPI_Comm_size(pme->mpi_comm_d[0],&pme->nnodes_major);
+ MPI_Comm_rank(pme->mpi_comm_d[1],&pme->nodeid_minor);
+ MPI_Comm_size(pme->mpi_comm_d[1],&pme->nnodes_minor);
#endif
}
pme->bPPnode = (cr->duty & DUTY_PP);
gmx_fatal(FARGS,"pme does not (yet) work with pbc = screw");
}
- pme->bFEP = ((ir->efep != efepNO) && bFreeEnergy);
- pme->nkx = ir->nkx;
- pme->nky = ir->nky;
- pme->nkz = ir->nkz;
+ pme->bFEP = ((ir->efep != efepNO) && bFreeEnergy);
+ pme->nkx = ir->nkx;
+ pme->nky = ir->nky;
+ pme->nkz = ir->nkz;
pme->pme_order = ir->pme_order;
pme->epsilon_r = ir->epsilon_r;
- /* Use atc[0] for spreading */
- init_atomcomm(pme,&pme->atc[0],cr,0,TRUE);
+ /* Currently pme.c supports only the fft5d FFT code.
+ * Therefore the grid always needs to be divisible by nnodes.
+ * When the old 1D code is also supported again, change this check.
+ *
+ * This check should be done before calling gmx_pme_init
+ * and fplog should be passed iso stderr.
+ *
if (pme->ndecompdim >= 2)
+ */
+ if (pme->ndecompdim >= 1)
{
- init_atomcomm(pme,&pme->atc[1],cr,1,FALSE);
+ /*
+ gmx_pme_check_grid_restrictions(pme->nodeid==0 ? stderr : NULL,
+ 'x',nnodes_major,&pme->nkx);
+ gmx_pme_check_grid_restrictions(pme->nodeid==0 ? stderr : NULL,
+ 'y',nnodes_minor,&pme->nky);
+ */
}
-
- if (pme->nkx <= pme->pme_order*(pme->nnodes > 1 ? 2 : 1) ||
- pme->nky <= pme->pme_order ||
+
+ if (pme->nkx <= pme->pme_order*(pme->nnodes_major > 1 ? 2 : 1) ||
+ pme->nky <= pme->pme_order*(pme->nnodes_minor > 1 ? 2 : 1) ||
pme->nkz <= pme->pme_order)
- gmx_fatal(FARGS,"The pme grid dimensions need to be larger than pme_order (%d) and in parallel larger than 2*pme_order for x",pme->pme_order);
-
+ {
+ gmx_fatal(FARGS,"The pme grid dimensions need to be larger than pme_order (%d) and in parallel larger than 2*pme_ordern for x and/or y",pme->pme_order);
+ }
+
if (pme->nnodes > 1) {
+ double imbal;
+
#ifdef GMX_MPI
MPI_Type_contiguous(DIM, mpi_type, &(pme->rvec_mpi));
MPI_Type_commit(&(pme->rvec_mpi));
* (unless the charge distribution is inhomogeneous).
*/
- if (pme_inconvenient_nnodes(pme->nkx,pme->nky,pme->nnodes) &&
- pme->nodeid == 0) {
+ imbal = pme_load_imbalance(pme);
+ if (imbal >= 1.2 && pme->nodeid_major == 0 && pme->nodeid_minor == 0)
+ {
fprintf(stderr,
"\n"
- "NOTE: For optimal PME load balancing at high parallelization\n"
- " PME grid_x (%d) and grid_y (%d) should be divisible by #PME_nodes (%d)\n"
+ "NOTE: The load imbalance in PME FFT and solve is %d%%.\n"
+ " For optimal PME load balancing\n"
+ " PME grid_x (%d) and grid_y (%d) should be divisible by #PME_nodes_x (%d)\n"
+ " and PME grid_y (%d) and grid_z (%d) should be divisible by #PME_nodes_y (%d)\n"
"\n",
- pme->nkx,pme->nky,pme->nnodes);
- }
-
- if (debug) {
- fprintf(debug,"Parallelized PME sum used. nkx=%d, npme=%d\n",
- ir->nkx,pme->nnodes);
- if ((ir->nkx % pme->nnodes) != 0)
- fprintf(debug,"Warning: For load balance, fourier_nx should be divisible by the number of PME nodes\n");
+ (int)((imbal-1)*100 + 0.5),
+ pme->nkx,pme->nky,pme->nnodes_major,
+ pme->nky,pme->nkz,pme->nnodes_minor);
}
-
- init_overlap_comm(pme,&pme->overlap[0],cr);
- } else {
- pme->overlap[0].s2g = NULL;
}
+
+ init_overlap_comm(&pme->overlap[0],pme->pme_order,
+#ifdef GMX_MPI
+ pme->mpi_comm_d[0],
+#endif
+ pme->nnodes_major,pme->nodeid_major,pme->nkx);
- /* With domain decomposition we need nnx on the PP only nodes */
- snew(pme->nnx,5*pme->nkx);
- snew(pme->nny,5*pme->nky);
- snew(pme->nnz,5*pme->nkz);
- for(i=0; (i<5*pme->nkx); i++) {
- pme->nnx[i] = i % pme->nkx;
- }
- for(i=0; (i<5*pme->nky); i++) {
- pme->nny[i] = i % pme->nky;
- }
- for(i=0; (i<5*pme->nkz); i++) {
- pme->nnz[i] = i % pme->nkz;
- }
+ init_overlap_comm(&pme->overlap[1],pme->pme_order,
+#ifdef GMX_MPI
+ pme->mpi_comm_d[1],
+#endif
+ pme->nnodes_minor,pme->nodeid_minor,pme->nky);
snew(pme->bsp_mod[XX],pme->nkx);
snew(pme->bsp_mod[YY],pme->nky);
snew(pme->bsp_mod[ZZ],pme->nkz);
- pme->gridA = mk_fftgrid(pme->nkx,pme->nky,pme->nkz,
- NULL,pme->overlap[0].s2g,cr,
+ /* Allocate data for the interpolation grid, including overlap */
+ pme->pmegrid_nx = pme->overlap[0].s2g1[pme->nodeid_major] -
+ pme->overlap[0].s2g0[pme->nodeid_major];
+ pme->pmegrid_ny = pme->overlap[1].s2g1[pme->nodeid_minor] -
+ pme->overlap[1].s2g0[pme->nodeid_minor];
+ pme->pmegrid_nz = pme->nkz + pme->pme_order - 1;
+
+ pme->pmegrid_start_ix = pme->overlap[0].s2g0[pme->nodeid_major];
+ pme->pmegrid_start_iy = pme->overlap[1].s2g0[pme->nodeid_minor];
+ pme->pmegrid_start_iz = 0;
+
+ make_gridindex5_to_localindex(pme->nkx,
+ pme->pmegrid_start_ix,
+ pme->overlap[0].s2g0[pme->nodeid_major+1],
+ &pme->nnx,&pme->fshx);
+ make_gridindex5_to_localindex(pme->nky,
+ pme->pmegrid_start_iy,
+ pme->overlap[1].s2g0[pme->nodeid_minor+1],
+ &pme->nny,&pme->fshy);
+ make_gridindex5_to_localindex(pme->nkz,
+ pme->pmegrid_start_iz,
+ pme->nkz,
+ &pme->nnz,&pme->fshz);
+
+ snew(pme->pmegridA,pme->pmegrid_nx*pme->pmegrid_ny*pme->pmegrid_nz);
+
+ /* For non-divisible grid we need pme_order iso pme_order-1 */
+ bufsizex = pme->pme_order*pme->pmegrid_ny*pme->pmegrid_nz;
+ bufsizey = pme->pmegrid_nx*pme->pme_order*pme->nkz;
+ bufsize = (bufsizex>bufsizey) ? bufsizex : bufsizey;
+
+ snew(pme->pmegrid_sendbuf,bufsize);
+ snew(pme->pmegrid_recvbuf,bufsize);
+
+ ndata[0] = pme->nkx;
+ ndata[1] = pme->nky;
+ ndata[2] = pme->nkz;
+
+ /* This routine will allocate the grid data to fit the FFTs */
+ gmx_parallel_3dfft_init(&pme->pfft_setupA,ndata,
+ &pme->fftgridA,&pme->cfftgridA,
+ pme->mpi_comm_d,
+ pme->overlap[0].s2g0,pme->overlap[1].s2g0,
bReproducible);
- if (bFreeEnergy) {
- pme->gridB = mk_fftgrid(pme->nkx,pme->nky,pme->nkz,
- NULL,pme->overlap[0].s2g,cr,
+
+ if (bFreeEnergy)
+ {
+ snew(pme->pmegridB,pme->pmegrid_nx*pme->pmegrid_ny*pme->pmegrid_nz);
+ gmx_parallel_3dfft_init(&pme->pfft_setupB,ndata,
+ &pme->fftgridB,&pme->cfftgridB,
+ pme->mpi_comm_d,
+ pme->overlap[0].s2g0,pme->overlap[1].s2g0,
bReproducible);
- } else {
- pme->gridB = NULL;
+ } else
+ {
+ pme->pmegridB = NULL;
+ pme->fftgridB = NULL;
+ pme->cfftgridB = NULL;
}
make_bspline_moduli(pme->bsp_mod,pme->nkx,pme->nky,pme->nkz,pme->pme_order);
+ /* Use atc[0] for spreading */
+ init_atomcomm(pme,&pme->atc[0],cr,nnodes_major > 1 ? 0 : 1,TRUE);
+ if (pme->ndecompdim >= 2)
+ {
+ init_atomcomm(pme,&pme->atc[1],cr,1,FALSE);
+ }
+
if (pme->nnodes == 1) {
pme->atc[0].n = homenr;
pme_realloc_atomcomm_things(&pme->atc[0]);
}
- pme->maxkz = pme->nkz/2+1;
- snew(pme->work_mhz,pme->maxkz);
- snew(pme->work_m2,pme->maxkz);
- snew(pme->work_denom,pme->maxkz);
- snew(pme->work_tmp1,pme->maxkz);
- snew(pme->work_m2inv,pme->maxkz);
+ /* Use fft5d, order after FFT is y major, z, x minor */
+ pme->work_nalloc = pme->nkx;
+ snew(pme->work_mhx,pme->work_nalloc);
+ snew(pme->work_mhy,pme->work_nalloc);
+ snew(pme->work_mhz,pme->work_nalloc);
+ snew(pme->work_m2,pme->work_nalloc);
+ snew(pme->work_denom,pme->work_nalloc);
+ /* Allocate an aligned pointer for SSE operations, including 3 extra
+ * elements at the end since SSE operates on 4 elements at a time.
+ */
+ snew(pme->work_tmp1_alloc,pme->work_nalloc+8);
+ pme->work_tmp1 = (real *) (((size_t) pme->work_tmp1_alloc + 16) & (~((size_t) 15)));
+ snew(pme->work_m2inv,pme->work_nalloc);
*pmedata = pme;
}
static void spread_on_grid(gmx_pme_t pme,
- pme_atomcomm_t *atc,t_fftgrid *grid,
+ pme_atomcomm_t *atc,real *grid,
bool bCalcSplines,bool bSpread)
-{
- int nx,ny,nz,nx2,ny2,nz2,la2,la12;
- real *ptr;
-
+{
if (bCalcSplines)
{
- /* Unpack structure */
- unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
/* Compute fftgrid index for all atoms,
* with help of some extra variables.
*/
- calc_idx(pme,atc);
+ calc_interpolation_idx(pme,atc);
/* make local bsplines */
- make_bsplines(atc->theta,atc->dtheta,pme->pme_order,nx,ny,nz,
+ make_bsplines(atc->theta,atc->dtheta,pme->pme_order,
atc->fractx,atc->n,atc->q,pme->bFEP);
}
{
/* put local atoms on grid. */
spread_q_bsplines(pme,atc,grid);
- /* pr_grid_dist(logfile,"spread",grid); */
}
}
void gmx_pme_calc_energy(gmx_pme_t pme,int n,rvec *x,real *q,real *V)
{
pme_atomcomm_t *atc;
- t_fftgrid *grid;
+ real *grid;
if (pme->nnodes > 1)
{
atc->q = q;
/* We only use the A-charges grid */
- grid = pme->gridA;
+ grid = pme->pmegridA;
spread_on_grid(pme,atc,grid,TRUE,FALSE);
matrix vir;
float cycles;
int count;
+ bool bEnerVir;
gmx_large_int_t step,step_rel;
natoms = gmx_pme_recv_q_x(pme_pp,
&chargeA,&chargeB,box,&x_pp,&f_pp,
&maxshift0,&maxshift1,
- &pme->bFEP,&lambda,&step);
+ &pme->bFEP,&lambda,
+ &bEnerVir,
+ &step);
if (natoms == -1) {
/* We should stop: break out of the loop */
gmx_pme_do(pme,0,natoms,x_pp,f_pp,chargeA,chargeB,box,
cr,maxshift0,maxshift1,nrnb,wcycle,vir,ewaldcoeff,
&energy,lambda,&dvdlambda,
- GMX_PME_DO_ALL);
+ GMX_PME_DO_ALL_F | (bEnerVir ? GMX_PME_CALC_ENER_VIR : 0));
cycles = wallcycle_stop(wcycle,ewcPMEMESH);
gmx_pme_send_force_vir_ener(pme_pp,
f_pp,vir,energy,dvdlambda,
- cycles,
- bGotStopNextStepSignal,
- bGotStopNextNSStepSignal);
+ cycles);
count++;
real *dvdlambda, int flags)
{
int q,d,i,j,ntot,npme;
- int nx,ny,nz,nx2,ny2,nz2,la12,la2;
+ int nx,ny,nz;
int n_d,local_ny;
+ int loop_count;
pme_atomcomm_t *atc=NULL;
- t_fftgrid *grid=NULL;
+ real * grid=NULL;
real *ptr;
rvec *x_d,*f_d;
real *charge=NULL,*q_d,vol;
real energy_AB[2];
matrix vir_AB[2];
bool bClearF;
-
+ gmx_parallel_3dfft_t pfft_setup;
+ real * fftgrid;
+ t_complex * cfftgrid;
if (pme->nnodes > 1) {
atc = &pme->atc[0];
atc->pd_nalloc = over_alloc_dd(atc->npd);
srenew(atc->pd,atc->pd_nalloc);
}
- atc->maxshift = maxshift0;
+ atc->maxshift = (atc->dimind==0 ? maxshift0 : maxshift1);
}
for(q=0; q<(pme->bFEP ? 2 : 1); q++) {
if (q == 0) {
- grid = pme->gridA;
+ grid = pme->pmegridA;
+ fftgrid = pme->fftgridA;
+ cfftgrid = pme->cfftgridA;
+ pfft_setup = pme->pfft_setupA;
charge = chargeA+start;
} else {
- grid = pme->gridB;
+ grid = pme->pmegridB;
+ fftgrid = pme->fftgridB;
+ cfftgrid = pme->cfftgridB;
+ pfft_setup = pme->pfft_setupB;
charge = chargeB+start;
}
/* Unpack structure */
gmx_fatal(FARGS,"No grid!");
}
where();
- unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
-#ifdef GMX_MPI
- if (pme->nnodes > 1) {
- local_ny = grid->pfft.local_ny_after_transpose;
- } else {
- local_ny = ny;
- }
-#else
- local_ny = ny;
-#endif
- where();
+ m_inv_ur0(box,pme->recipbox);
+
if (pme->nnodes == 1) {
atc = &pme->atc[0];
if (DOMAINDECOMP(cr)) {
atc->pd_nalloc = over_alloc_dd(atc->npd);
srenew(atc->pd,atc->pd_nalloc);
}
- atc->maxshift = (d==0 ? maxshift0 : maxshift1);
- pme_calc_pidx(n_d,box,x_d,atc);
+ atc->maxshift = (atc->dimind==0 ? maxshift0 : maxshift1);
+ pme_calc_pidx(n_d,pme->recipbox,x_d,atc);
where();
GMX_BARRIER(cr->mpi_comm_mygroup);
if (DOMAINDECOMP(cr)) {
dd_pmeredist_x_q(pme, n_d, q==0, x_d, q_d, atc);
} else {
- pmeredist(pme, TRUE, n_d, q==0, x_d, q_d, atc);
+ pmeredist_pd(pme, TRUE, n_d, q==0, x_d, q_d, atc);
}
}
where();
+
wallcycle_stop(wcycle,ewcPME_REDISTXF);
}
fprintf(debug,"Node= %6d, pme local particles=%6d\n",
cr->nodeid,atc->n);
- calc_recipbox(box,pme->recipbox);
-
if (flags & GMX_PME_SPREAD_Q)
{
wallcycle_start(wcycle,ewcPME_SPREADGATHER);
inc_nrnb(nrnb,eNR_SPREADQBSP,
pme->pme_order*pme->pme_order*pme->pme_order*atc->n);
+ wrap_periodic_pmegrid(pme,grid);
+
/* sum contributions to local grid from other nodes */
+#ifdef GMX_MPI
if (pme->nnodes > 1) {
-#ifdef DEBUG
- if (debug)
- pr_fftgrid(debug,"qgrid before dd sum",grid);
-#endif
GMX_BARRIER(cr->mpi_comm_mygroup);
- gmx_sum_qgrid_dd(pme,&pme->overlap[0],grid,
- GMX_SUM_QGRID_FORWARD);
+ gmx_sum_qgrid_dd(pme,grid,GMX_SUM_QGRID_FORWARD);
where();
}
-#ifdef DEBUG
- if (debug)
- pr_fftgrid(debug,"qgrid",grid);
#endif
where();
+
+ copy_pmegrid_to_fftgrid(pme,grid,fftgrid);
+
wallcycle_stop(wcycle,ewcPME_SPREADGATHER);
}
GMX_BARRIER(cr->mpi_comm_mygroup);
GMX_MPE_LOG(ev_gmxfft3d_start);
wallcycle_start(wcycle,ewcPME_FFT);
- gmxfft3D(grid,GMX_FFT_REAL_TO_COMPLEX,cr);
+ gmx_parallel_3dfft_execute(pfft_setup,GMX_FFT_REAL_TO_COMPLEX,fftgrid,cfftgrid);
wallcycle_stop(wcycle,ewcPME_FFT);
GMX_MPE_LOG(ev_gmxfft3d_finish);
where();
GMX_BARRIER(cr->mpi_comm_mygroup);
GMX_MPE_LOG(ev_solve_pme_start);
wallcycle_start(wcycle,ewcPME_SOLVE);
- energy_AB[q]=solve_pme(pme,grid,ewaldcoeff,vol,vir_AB[q],cr);
+ loop_count =
+ solve_pme_yzx(pme,cfftgrid,ewaldcoeff,vol,
+ flags & GMX_PME_CALC_ENER_VIR,
+ &energy_AB[q],vir_AB[q]);
wallcycle_stop(wcycle,ewcPME_SOLVE);
where();
GMX_MPE_LOG(ev_solve_pme_finish);
- inc_nrnb(nrnb,eNR_SOLVEPME,nx*local_ny*(nz/2+1));
+ inc_nrnb(nrnb,eNR_SOLVEPME,loop_count);
+ }
+
+ if (flags & GMX_PME_CALC_F)
+ {
/* do 3d-invfft */
GMX_BARRIER(cr->mpi_comm_mygroup);
GMX_MPE_LOG(ev_gmxfft3d_start);
where();
wallcycle_start(wcycle,ewcPME_FFT);
- gmxfft3D(grid,GMX_FFT_COMPLEX_TO_REAL,cr);
+ gmx_parallel_3dfft_execute(pfft_setup,GMX_FFT_COMPLEX_TO_REAL,cfftgrid,fftgrid);
wallcycle_stop(wcycle,ewcPME_FFT);
+
where();
GMX_MPE_LOG(ev_gmxfft3d_finish);
-
- ntot = grid->nxyz;
- npme = ntot*log((real)ntot)/log(2.0);
- if (pme->nnodes > 1) {
- npme /= (cr->nnodes - cr->npmenodes);
+
+ if (pme->nodeid == 0)
+ {
+ ntot = pme->nkx*pme->nky*pme->nkz;
+ npme = ntot*log((real)ntot)/log(2.0);
+ inc_nrnb(nrnb,eNR_FFT,2*npme);
}
- inc_nrnb(nrnb,eNR_FFT,2*npme);
- where();
- }
- if (flags & GMX_PME_CALC_F)
- {
wallcycle_start(wcycle,ewcPME_SPREADGATHER);
+ copy_fftgrid_to_pmegrid(pme,fftgrid,grid);
+
/* distribute local grid to all nodes */
+#ifdef GMX_MPI
if (pme->nnodes > 1) {
GMX_BARRIER(cr->mpi_comm_mygroup);
- gmx_sum_qgrid_dd(pme, &pme->overlap[0],grid,
- GMX_SUM_QGRID_BACKWARD);
+ gmx_sum_qgrid_dd(pme,grid,GMX_SUM_QGRID_BACKWARD);
}
- where();
-#ifdef DEBUG
- if (debug)
- pr_fftgrid(debug,"potential",grid);
#endif
+ where();
+
+ unwrap_periodic_pmegrid(pme,grid);
/* interpolate forces for our local atoms */
GMX_BARRIER(cr->mpi_comm_mygroup);
dd_pmeredist_f(pme,atc,n_d,f_d,
d==pme->ndecompdim-1 && pme->bPPnode);
} else {
- pmeredist(pme, FALSE, n_d, TRUE, f_d, NULL, atc);
+ pmeredist_pd(pme, FALSE, n_d, TRUE, f_d, NULL, atc);
}
}
+
wallcycle_stop(wcycle,ewcPME_REDISTXF);
}
where();
for(j=0; j<DIM; j++)
vir[i][j] += (1.0-lambda)*vir_AB[0][i][j] + lambda*vir_AB[1][i][j];
}
+
if (debug)
fprintf(debug,"PME mesh energy: %g\n",*energy);
#define PP_PME_CHARGEB (1<<1)
#define PP_PME_COORD (1<<2)
#define PP_PME_FEP (1<<3)
-#define PP_PME_FINISH (1<<4)
+#define PP_PME_ENER_VIR (1<<4)
+#define PP_PME_FINISH (1<<5)
#define PME_PP_SIGSTOP (1<<0)
#define PME_PP_SIGSTOPNSS (1<<1)
real energy;
real dvdlambda;
float cycles;
- int flags;
+ gmx_stop_cond_t stop_cond;
} gmx_pme_comm_vir_ene_t;
}
void gmx_pme_send_x(t_commrec *cr, matrix box, rvec *x,
- bool bFreeEnergy, real lambda,gmx_large_int_t step)
+ bool bFreeEnergy, real lambda,
+ bool bEnerVir,
+ gmx_large_int_t step)
{
int flags;
-
+
flags = PP_PME_COORD;
if (bFreeEnergy)
flags |= PP_PME_FEP;
+ if (bEnerVir)
+ flags |= PP_PME_ENER_VIR;
gmx_pme_send_q_x(cr,flags,NULL,NULL,box,x,lambda,0,0,step);
}
matrix box, rvec **x,rvec **f,
int *maxshift0, int *maxshift1,
bool *bFreeEnergy,real *lambda,
+ bool *bEnerVir,
gmx_large_int_t *step)
{
gmx_pme_comm_n_box_t cnb;
copy_mat(cnb.box,box);
*bFreeEnergy = (cnb.flags & PP_PME_FEP);
*lambda = cnb.lambda;
+ *bEnerVir = (cnb.flags & PP_PME_ENER_VIR);
if (*bFreeEnergy && !(pme_pp->flags_charge & PP_PME_CHARGEB))
gmx_incons("PME-only node received free energy request, but "
*dvdlambda += cve.dvdlambda;
*pme_cycles = cve.cycles;
- bGotStopNextStepSignal = (cve.flags & PME_PP_SIGSTOP);
- bGotStopNextNSStepSignal = (cve.flags & PME_PP_SIGSTOPNSS);
+ if ( cve.stop_cond != gmx_stop_cond_none )
+ {
+ gmx_set_stop_condition(cve.stop_cond);
+ }
} else {
*energy = 0;
*pme_cycles = 0;
void gmx_pme_send_force_vir_ener(struct gmx_pme_pp *pme_pp,
rvec *f, matrix vir,
real energy, real dvdlambda,
- float cycles,
- bool bGotStopNextStepSignal,
- bool bGotStopNextNSStepSignal)
+ float cycles)
{
gmx_pme_comm_vir_ene_t cve;
int messages,ind_start,ind_end,receiver;
copy_mat(vir,cve.vir);
cve.energy = energy;
cve.dvdlambda = dvdlambda;
- cve.flags = 0;
- if (bGotStopNextStepSignal)
- cve.flags |= PME_PP_SIGSTOP;
- if (bGotStopNextNSStepSignal)
- cve.flags |= PME_PP_SIGSTOPNSS;
-
+ /* check for the signals to send back to a PP node */
+ cve.stop_cond = gmx_get_stop_condition();
+
cve.cycles = cycles;
if (debug)
#define ulim2 (3)
+
+/* PPPM temporarily disabled while working on 2D PME */
+#define DISABLE_PPPM
+
+
+
+#ifndef DISABLE_PPPM
+
/* TODO: fix thread-safety */
static void calc_invh(rvec box,int nx,int ny,int nz,rvec invh)
sfree(nTest);
}
+
void solve_pppm(FILE *fp,t_commrec *cr,
t_fftgrid *grid,real ***ghat,rvec box,
bool bVerbose,t_nrnb *nrnb)
static real ***ghat=NULL;
static t_fftgrid *grid=NULL;
+#endif
+
+
int gmx_pppm_init(FILE *log, t_commrec *cr,
const output_env_t oenv, bool bVerbose,
bool bOld, matrix box,
const real tol = 1e-5;
rvec box_diag,spacing;
+#ifdef DISABLE_PPPM
+ gmx_fatal(FARGS,"PPPM is not functional in the current version, we plan to implement PPPM through a small modification of the PME code.");
+ return -1;
+#else
+
#ifdef GMX_WITHOUT_FFTW
gmx_fatal(FARGS,"PPPM used, but GROMACS was compiled without FFTW support!\n");
#endif
grid = mk_fftgrid(nx,ny,nz,NULL,NULL,cr,bReproducible);
return 0;
+#endif
}
int gmx_pppm_do(FILE *log, gmx_pme_t pme,
t_nrnb *nrnb,
int pme_order, real *energy)
{
- /* Make the grid empty */
+#ifdef DISABLE_PPPM
+ gmx_fatal(FARGS,"PPPM temporarily disabled while working on 2DPME\n");
+ return -1;
+#else
+
+ /* Make the grid empty */
clear_fftgrid(grid);
/* First step: spreading the charges over the grid. */
phi,grid,beta,nrnb);
return 0;
+#endif
}
+#ifndef DISABLE_PPPM
static int gmx_pppm_opt_do(FILE *log, gmx_pme_t pme,
t_inputrec *ir, bool bVerbose,
int natoms,
return 0;
}
+#endif
#include "mtop_util.h"
#include "mdrun.h"
#include "gmx_ga2la.h"
+#include "copyrite.h"
static void pull_print_x_grp(FILE *out,bool bRef,ivec dim,t_pullgrp *pgrp)
{
t_pull *pull;
t_pullgrp *pgrp;
int g,start=0,end=0,m;
+ bool bCite;
pull = ir->pull;
fprintf(fplog,"with an absolute reference on %d group%s\n",
pull->ngrp,pull->ngrp==1 ? "" : "s");
}
+ bCite = FALSE;
+ for(g=0; g<pull->ngrp+1; g++)
+ {
+ if (pull->grp[g].nat > 0 &&
+ pull->grp[g].pbcatom < 0)
+ {
+ /* We are using cosine weighting */
+ fprintf(fplog,"Cosine weighting is used for groupd %d\n",g);
+ bCite = TRUE;
+ }
+ }
+ if (bCite)
+ {
+ please_cite(fplog,"Engin2010");
+ }
}
/* We always add the virial contribution,
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include "sysstuff.h"
+#include "typedefs.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "assert.h"
+#include "physics.h"
+#include "macros.h"
+#include "vec.h"
+#include "force.h"
+#include "invblock.h"
+#include "confio.h"
+#include "names.h"
+#include "network.h"
+#include "pbc.h"
+#include "ns.h"
+#include "nrnb.h"
+#include "bondf.h"
+#include "mshift.h"
+#include "txtdump.h"
+#include "copyrite.h"
+#include "qmmm.h"
+#include <stdio.h>
+#include <string.h>
+#include "gmx_fatal.h"
+#include "typedefs.h"
+#include <stdlib.h>
+
+/* ORCA interface routines */
+
+void init_orca(t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
+{
+ char
+ *buf;
+ snew(buf,200);
+ buf = getenv("BASENAME");
+ if (buf){
+ snew(qm->orca_basename,200);
+ sscanf(buf,"%s",qm->orca_basename);
+ }
+ else
+ gmx_fatal(FARGS,"no $BASENAME\n");
+ fprintf(stderr,"orca initialised...\n");
+ /* since we append the output to the BASENAME.out file,
+ we should delete an existent old out-file here. */
+ sprintf(buf,"%s.out",qm->orca_basename);
+ remove(buf);
+}
+
+
+void write_orca_input(int step ,t_forcerec *fr, t_QMrec *qm, t_MMrec *mm)
+{
+ int
+ i;
+ t_QMMMrec
+ *QMMMrec;
+ FILE
+ *out, *pcFile, *addInputFile, *LJCoeff;
+ char
+ *buf,*orcaInput,*addInputFilename,*LJCoeffFilename,
+ *pcFilename,*exclInName,*exclOutName;
+ QMMMrec = fr->qr;
+ /* write the first part of the input-file */
+ snew(orcaInput,200);
+ sprintf(orcaInput,"%s.inp",qm->orca_basename);
+ out = fopen(orcaInput,"w");
+ snew(addInputFilename,200);
+ sprintf(addInputFilename,"%s.ORCAINFO",qm->orca_basename);
+ addInputFile = fopen(addInputFilename,"r");
+ fprintf(out, "#input-file generated by gromacs\n");
+ if(qm->bTS){
+ fprintf(out,"!QMMMOpt TightSCF\n");
+ fprintf(out,"%s\n","%geom TS_Search EF end");
+ }
+ else if (qm->bOPT){
+ fprintf(out,"!QMMMOpt TightSCF\n");
+ }
+ else{
+ fprintf(out,"!EnGrad TightSCF\n");
+ }
+ /* here we include the insertion of the additional orca-input */
+ snew(buf,200);
+ if (addInputFile!=NULL) {
+ while (!feof(addInputFile)) {
+ if (fgets(buf , 200 , addInputFile) != '\0' )
+ fputs(buf, out);
+ }
+ }
+ else {
+ fprintf(stderr,"No information on the calculation given in <%s>\n",addInputFilename);
+ gmx_call("qm_orca.c");
+ }
+ fclose(addInputFile);
+ if(qm->bTS||qm->bOPT){
+ /* freeze the frontier QM atoms and Link atoms. This is
+ * important only if a full QM subsystem optimization is done
+ * with a frozen MM environmeent. For dynamics, or gromacs's own
+ * optimization routines this is not important.
+ */
+ /* ORCA reads the exclusions from LJCoeffFilename.Excl,
+ *so we have to rename the file
+ */
+ int didStart = 0;
+ for(i=0;i<qm->nrQMatoms;i++){
+ if(qm->frontatoms[i]){
+ if (!didStart){
+ fprintf(out,"%s\n","%geom");
+ fprintf(out," Constraints \n");
+ didStart = 1;
+ }
+ fprintf(out," {C %d C}\n",i); /* counting from 0 */
+ }
+ }
+ if (didStart) fprintf(out," end\n end\n");
+ // make a file with information on the C6 and C12 coefficients
+ if(QMMMrec->QMMMscheme!=eQMMMschemeoniom && mm->nrMMatoms){
+ snew(exclInName,200);
+ snew(exclOutName,200);
+ sprintf(exclInName,"QMMMexcl.dat");
+ sprintf(exclOutName,"%s.LJ.Excl",qm->orca_basename);
+ rename(exclInName,exclOutName);
+ snew(LJCoeffFilename,200);
+ sprintf(LJCoeffFilename,"%s.LJ",qm->orca_basename);
+ fprintf(out,"%s%s%s\n","%LJCOEFFICIENTS \"",LJCoeffFilename,"\"");
+ // make a file with information on the C6 and C12 coefficients
+ LJCoeff = fopen(LJCoeffFilename,"w");
+ fprintf(LJCoeff,"%d\n",qm->nrQMatoms);
+ for (i=0;i<qm->nrQMatoms;i++){
+#ifdef GMX_DOUBLE
+ fprintf(LJCoeff,"%10.7lf %10.7lf\n",qm->c6[i],qm->c12[i]);
+#else
+ fprintf(LJCoeff,"%10.7f %10.7f\n",qm->c6[i],qm->c12[i]);
+#endif
+ }
+ fprintf(LJCoeff,"%d\n",mm->nrMMatoms);
+ for (i=0;i<mm->nrMMatoms;i++){
+#ifdef GMX_DOUBLE
+ fprintf(LJCoeff,"%10.7lf %10.7lf\n",mm->c6[i],mm->c12[i]);
+#else
+ fprintf(LJCoeff,"%10.7f %10.7f\n",mm->c6[i],mm->c12[i]);
+#endif
+ }
+ fclose(LJCoeff);
+ }
+ }
+ /* write charge and multiplicity
+ */
+ fprintf(out,"*xyz %2d%2d\n",qm->QMcharge,qm->multiplicity);
+ /* write the QM coordinates
+ */
+ for (i=0;i<qm->nrQMatoms;i++){
+ int atomNr;
+ if (qm->atomicnumberQM[i]==0)
+ atomNr = 1;
+ else
+ atomNr = qm->atomicnumberQM[i];
+#ifdef GMX_DOUBLE
+ fprintf(out,"%3d %10.7lf %10.7lf %10.7lf\n",
+ atomNr,
+ qm->xQM[i][XX]/0.1,
+ qm->xQM[i][YY]/0.1,
+ qm->xQM[i][ZZ]/0.1);
+#else
+ fprintf(out,"%3d %10.7f %10.7f %10.7f\n",
+ atomNr,
+ qm->xQM[i][XX]/0.1,
+ qm->xQM[i][YY]/0.1,
+ qm->xQM[i][ZZ]/0.1);
+#endif
+ }
+ fprintf(out,"*\n");
+ /* write the MM point charge data
+ */
+ if(QMMMrec->QMMMscheme!=eQMMMschemeoniom && mm->nrMMatoms){
+ /* name of the point charge file */
+ snew(pcFilename,200);
+ sprintf(pcFilename,"%s.pc",qm->orca_basename);
+ fprintf(out,"%s%s%s\n","%pointcharges \"",pcFilename,"\"");
+ pcFile = fopen(pcFilename,"w");
+ fprintf(pcFile,"%d\n",mm->nrMMatoms);
+ for(i=0;i<mm->nrMMatoms;i++){
+#ifdef GMX_DOUBLE
+ fprintf(pcFile,"%8.4lf %10.7lf %10.7lf %10.7lf\n",
+ mm->MMcharges[i],
+ mm->xMM[i][XX]/0.1,
+ mm->xMM[i][YY]/0.1,
+ mm->xMM[i][ZZ]/0.1);
+#else
+ fprintf(pcFile,"%8.4f %10.7f %10.7f %10.7f\n",
+ mm->MMcharges[i],
+ mm->xMM[i][XX]/0.1,
+ mm->xMM[i][YY]/0.1,
+ mm->xMM[i][ZZ]/0.1);
+#endif
+ }
+ fprintf(pcFile,"\n");
+ fclose(pcFile);
+ }
+ fprintf(out,"\n");
+
+ fclose(out);
+} /* write_orca_input */
+
+real read_orca_output(rvec QMgrad[],rvec MMgrad[],int step,t_forcerec *fr,
+ t_QMrec *qm, t_MMrec *mm)
+{
+ int
+ i,j,atnum;
+ char
+ buf[300], tmp[300], orca_xyzFilename[300], orca_pcgradFilename[300], orca_engradFilename[300];
+ real
+ QMener;
+ FILE
+ *xyz, *pcgrad, *engrad;
+ int k;
+ t_QMMMrec
+ *QMMMrec;
+ QMMMrec = fr->qr;
+ sprintf(orca_xyzFilename,"%s.xyz",qm->orca_basename);
+ xyz=fopen(orca_xyzFilename,"r");
+ /* in case of an optimization, the coordinates are printed in the
+ * xyz file, the energy and gradients for the QM part are stored in the engrad file
+ * and the gradients for the point charges are stored in the pc file.
+ */
+
+ /* we need the new xyz coordinates of the QM atoms only for separate QM-optimization
+ */
+
+ if(qm->bTS||qm->bOPT){
+ fgets(buf,300,xyz);
+ fgets(buf,300,xyz);
+ for(i=0;i<qm->nrQMatoms;i++){
+ fgets(buf,300,xyz);
+#ifdef GMX_DOUBLE
+ sscanf(buf,"%s%lf%lf%lf\n",
+ tmp,
+ &qm->xQM[i][XX],
+ &qm->xQM[i][YY],
+ &qm->xQM[i][ZZ]);
+#else
+ sscanf(buf,"%d%f%f%f\n",
+ &atnum,
+ &qm->xQM[i][XX],
+ &qm->xQM[i][YY],
+ &qm->xQM[i][ZZ]);
+#endif
+ for(j=0;j<DIM;j++){
+ qm->xQM[i][j]*=0.1;
+ }
+ }
+ fclose(xyz);
+ }
+ sprintf(orca_engradFilename,"%s.engrad",qm->orca_basename);
+ engrad=fopen(orca_engradFilename,"r");
+ /* we read the energy and the gradient for the qm-atoms from the engrad file
+ */
+ /* we can skip the first seven lines
+ */
+ for (j=0;j<7;j++){
+ fgets(buf,300,engrad);
+ }
+ /* now comes the energy
+ */
+ fgets(buf,300,engrad);
+#ifdef GMX_DOUBLE
+ sscanf(buf,"%lf\n",&QMener);
+#else
+ sscanf(buf,"%f\n", &QMener);
+#endif
+ /* we can skip the next three lines
+ */
+ for (j=0;j<3;j++){
+ fgets(buf,300,engrad);
+ }
+ /* next lines contain the gradients of the QM atoms
+ * now comes the gradient, one value per line:
+ * (atom1 x \n atom1 y \n atom1 z \n atom2 x ...
+ */
+
+ for(i=0;i<3*qm->nrQMatoms;i++){
+ k = i/3;
+ fgets(buf,300,engrad);
+#ifdef GMX_DOUBLE
+ if (i%3==0)
+ sscanf(buf,"%lf\n", &QMgrad[k][XX]);
+ else if (i%3==1)
+ sscanf(buf,"%lf\n", &QMgrad[k][YY]);
+ else if (i%3==2)
+ sscanf(buf,"%lf\n", &QMgrad[k][ZZ]);
+#else
+ if (i%3==0)
+ sscanf(buf,"%f\n", &QMgrad[k][XX]);
+ else if (i%3==1)
+ sscanf(buf,"%f\n", &QMgrad[k][YY]);
+ else if (i%3==2)
+ sscanf(buf,"%f\n", &QMgrad[k][ZZ]);
+#endif
+ }
+ fclose(engrad);
+ /* write the MM point charge data
+ */
+ if(QMMMrec->QMMMscheme!=eQMMMschemeoniom && mm->nrMMatoms){
+ sprintf(orca_pcgradFilename,"%s.pcgrad",qm->orca_basename);
+ pcgrad=fopen(orca_pcgradFilename,"r");
+
+ /* we read the gradient for the mm-atoms from the pcgrad file
+ */
+ /* we can skip the first line
+ */
+ fgets(buf,300,pcgrad);
+ for(i=0;i<mm->nrMMatoms;i++){
+ fgets(buf,300,pcgrad);
+ #ifdef GMX_DOUBLE
+ sscanf(buf,"%lf%lf%lf\n",
+ &MMgrad[i][XX],
+ &MMgrad[i][YY],
+ &MMgrad[i][ZZ]);
+ #else
+ sscanf(buf,"%f%f%f\n",
+ &MMgrad[i][XX],
+ &MMgrad[i][YY],
+ &MMgrad[i][ZZ]);
+ #endif
+ }
+ fclose(pcgrad);
+ }
+ return(QMener);
+}
+
+void do_orca(int step,char *exe, char *basename)
+{
+
+ /* make the call to the orca binary through system()
+ * The location of the binary is set through the
+ * environment.
+ */
+ char
+ buf[100];
+ sprintf(buf,"%s %s.inp >> %s.out",
+ "orca",
+ basename,
+ basename);
+ fprintf(stderr,"Calling '%s'\n",buf);
+ if ( system(buf) != 0 )
+ gmx_fatal(FARGS,"Call to '%s' failed\n",buf);
+}
+
+real call_orca(t_commrec *cr, t_forcerec *fr,
+ t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
+{
+ /* normal orca jobs */
+ static int
+ step=0;
+ int
+ i,j;
+ real
+ QMener=0.0;
+ rvec
+ *QMgrad,*MMgrad;
+ char
+ *exe;
+
+ snew(exe,30);
+ sprintf(exe,"%s","orca");
+ snew(QMgrad,qm->nrQMatoms);
+ snew(MMgrad,mm->nrMMatoms);
+
+ write_orca_input(step,fr,qm,mm);
+ do_orca(step,exe,qm->orca_basename);
+ QMener = read_orca_output(QMgrad,MMgrad,step,fr,qm,mm);
+ /* put the QMMM forces in the force array and to the fshift
+ */
+ for(i=0;i<qm->nrQMatoms;i++){
+ for(j=0;j<DIM;j++){
+ f[i][j] = HARTREE_BOHR2MD*QMgrad[i][j];
+ fshift[i][j] = HARTREE_BOHR2MD*QMgrad[i][j];
+ }
+ }
+ for(i=0;i<mm->nrMMatoms;i++){
+ for(j=0;j<DIM;j++){
+ f[i+qm->nrQMatoms][j] = HARTREE_BOHR2MD*MMgrad[i][j];
+ fshift[i+qm->nrQMatoms][j] = HARTREE_BOHR2MD*MMgrad[i][j];
+ }
+ }
+ QMener = QMener*HARTREE2KJ*AVOGADRO;
+ step++;
+ free(exe);
+ return(QMener);
+} /* call_orca */
+
+/* end of orca sub routines */
call_gaussian(t_commrec *cr,t_forcerec *fr, t_QMrec *qm,
t_MMrec *mm,rvec f[], rvec fshift[]);
+#elif defined GMX_QMMM_ORCA
+/* ORCA interface */
+
+void
+init_orca(t_commrec *cr ,t_QMrec *qm, t_MMrec *mm);
+
+real
+call_orca(t_commrec *cr,t_forcerec *fr, t_QMrec *qm,
+ t_MMrec *mm,rvec f[], rvec fshift[]);
+
#endif
QMener = call_gamess(cr,fr,qm,mm,f,fshift);
#elif defined GMX_QMMM_GAUSSIAN
QMener = call_gaussian(cr,fr,qm,mm,f,fshift);
+#elif defined GMX_QMMM_ORCA
+ QMener = call_orca(cr,fr,qm,mm,f,fshift);
#else
- gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess or Gaussian.");
+ gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
#endif
}
}
init_gamess(cr,qm,mm);
#elif defined GMX_QMMM_GAUSSIAN
init_gaussian(cr,qm,mm);
+#elif defined GMX_QMMM_ORCA
+ init_orca(cr,qm,mm);
#else
- gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess or Gaussian.");
+ gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
#endif
}
} /* init_QMroutine */
/* Lennard-Jones coefficients */
snew(qm->c6,nr);
snew(qm->c12,nr);
- /* do we optimize the QM seperately using the algorithms of the QM program??
+ /* do we optimize the QM separately using the algorithms of the QM program??
*/
qm->bTS = ir->opts.bTS[grpnr];
qm->bOPT = ir->opts.bOPT[grpnr];
}
else
{
- /* ab initio calculation requested (gamess/gaussian) */
+ /* ab initio calculation requested (gamess/gaussian/ORCA) */
#ifdef GMX_QMMM_GAMESS
init_gamess(cr,qr->qm[0],qr->mm);
#elif defined GMX_QMMM_GAUSSIAN
init_gaussian(cr,qr->qm[0],qr->mm);
+#elif defined GMX_QMMM_ORCA
+ init_orca(cr,qr->qm[0],qr->mm);
#else
- gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess or Gaussian.");
+ gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
#endif
}
}
real
QMener=0.0;
/* a selection for the QM package depending on which is requested
- * (Gaussian, GAMESS-UK or MOPAC) needs to be implemented here. Now
+ * (Gaussian, GAMESS-UK, MOPAC or ORCA) needs to be implemented here. Now
* it works through defines.... Not so nice yet
*/
t_QMMMrec
}
void cshake(atom_id iatom[],int ncon,int *nnit,int maxnit,
- real dist2[],real xp[],real rij[],real m2[],real omega,
+ real dist2[],real xp[],real rij[],real m2[],real omega,
real invmass[],real tt[],real lagr[],int *nerror)
{
/*
real xh,yh,zh,rijx,rijy,rijz;
real tix,tiy,tiz;
real tjx,tjy,tjz;
- int nit,error,iconv,nconv;
+ int nit,error,nconv;
+ real iconvf;
error=0;
nconv=1;
toler = dist2[ll];
diff = toler-rpij2;
- /* iconv is zero when the error is smaller than a bound */
- iconv = fabs(diff)*tt[ll];
+ /* iconvf is less than 1 when the error is smaller than a bound */
+ /* But if tt is too big, then it will result in looping in iconv */
+
+ iconvf = fabs(diff)*tt[ll];
- if (iconv != 0) {
- nconv = nconv + iconv;
+ if (iconvf > 1) {
+ nconv = iconvf;
rrpr = rijx*tx+rijy*ty+rijz*tz;
if (rrpr < toler*mytol)
rvec *rij;
real *M2,*tt,*dist2;
int maxnit=1000;
- int nit,ll,i,j,type;
+ int nit=0,ll,i,j,type;
t_iatom *ia;
real L1,tol2,toler;
real mm=0.,tmp;
- int error;
+ int error=0;
real g,vscale,rscale,rvscale;
if (ncon > shaked->nalloc)
real xh,yh,zh,rijx,rijy,rijz;
real tix,tiy,tiz;
real tjx,tjy,tjz;
- int nit,error,iconv,nconv;
- real veta,vscale_nhc;
+ int nit,error,nconv;
+ real veta,vscale_nhc,iconvf;
veta = vetavar->veta;
vscale_nhc = vetavar->vscale_nhc[0]; /* for now, just use the first state */
xdotd = vpijd*vscale_nhc + veta*toler;
/* iconv is zero when the error is smaller than a bound */
- iconv = fabs(xdotd)*(tt[ll]/invdt);
+ iconvf = fabs(xdotd)*(tt[ll]/invdt);
- if (iconv != 0) {
- nconv = nconv + iconv;
+ if (iconvf > 1) {
+ nconv = iconvf;
fac = omega*2.0*m2[ll]/toler;
acor = -fac*xdotd;
lagr[ll] += acor;
void print_time(FILE *out,gmx_runtime_t *runtime,gmx_large_int_t step,
t_inputrec *ir, t_commrec *cr)
{
- time_t finish;
-
- double dt;
- char buf[48];
-
+ time_t finish;
+
+ double dt;
+ char buf[48];
+
#ifndef GMX_THREADS
- if (!PAR(cr))
+ if (!PAR(cr))
#endif
- fprintf(out,"\r");
- fprintf(out,"step %s",gmx_step_str(step,buf));
- if ((step >= ir->nstlist)) {
- if ((ir->nstlist == 0) || ((step % ir->nstlist) == 0)) {
- /* We have done a full cycle let's update time_per_step */
- runtime->last = gmx_gettime();
- dt = difftime(runtime->last,runtime->real);
- runtime->time_per_step = dt/(step - ir->init_step + 1);
+ {
+ fprintf(out,"\r");
}
- dt = (ir->nsteps + ir->init_step - step)*runtime->time_per_step;
-
- if (dt >= 300) {
- finish = (time_t) (runtime->last + dt);
- sprintf(buf,"%s",ctime(&finish));
- buf[strlen(buf)-1]='\0';
- fprintf(out,", will finish %s",buf);
+ fprintf(out,"step %s",gmx_step_str(step,buf));
+ if ((step >= ir->nstlist))
+ {
+ if ((ir->nstlist == 0) || ((step % ir->nstlist) == 0))
+ {
+ /* We have done a full cycle let's update time_per_step */
+ runtime->last = gmx_gettime();
+ dt = difftime(runtime->last,runtime->real);
+ runtime->time_per_step = dt/(step - ir->init_step + 1);
+ }
+ dt = (ir->nsteps + ir->init_step - step)*runtime->time_per_step;
+
+ if (ir->nsteps >= 0)
+ {
+ if (dt >= 300)
+ {
+ finish = (time_t) (runtime->last + dt);
+ sprintf(buf,"%s",ctime(&finish));
+ buf[strlen(buf)-1]='\0';
+ fprintf(out,", will finish %s",buf);
+ }
+ else
+ fprintf(out,", remaining runtime: %5d s ",(int)dt);
+ }
+ else
+ {
+ fprintf(out," performance: %.1f ns/day ",
+ ir->delta_t/1000*24*60*60/runtime->time_per_step);
+ }
}
- else
- fprintf(out,", remaining runtime: %5d s ",(int)dt);
- }
#ifndef GMX_THREADS
- if (PAR(cr))
- fprintf(out,"\n");
+ if (PAR(cr))
+ {
+ fprintf(out,"\n");
+ }
#endif
- fflush(out);
+ fflush(out);
}
#ifdef NO_CLOCK
svmul(inputrec->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]);
}
- gmx_pme_send_x(cr,bBS ? boxs : box,x,mdatoms->nChargePerturbed,lambda,step);
+ gmx_pme_send_x(cr,bBS ? boxs : box,x,
+ mdatoms->nChargePerturbed,lambda,
+ ( flags & GMX_FORCE_VIRIAL),step);
GMX_MPE_LOG(ev_send_coordinates_finish);
wallcycle_stop(wcycle,ewcPP_PMESENDX);
print_dd_statistics(cr,inputrec,fplog);
}
- if (SIMMASTER(cr)) {
- if (PARTDECOMP(cr)) {
- pr_load(fplog,cr,nrnb_tot);
+#ifdef GMX_MPI
+ if (PARTDECOMP(cr))
+ {
+ if (MASTER(cr))
+ {
+ t_nrnb *nrnb_all;
+ int s;
+ MPI_Status stat;
+
+ snew(nrnb_all,cr->nnodes);
+ nrnb_all[0] = *nrnb;
+ for(s=1; s<cr->nnodes; s++)
+ {
+ MPI_Recv(nrnb_all[s].n,eNRNB,MPI_DOUBLE,s,0,
+ cr->mpi_comm_mysim,&stat);
+ }
+ pr_load(fplog,cr,nrnb_all);
+ sfree(nrnb_all);
+ }
+ else
+ {
+ MPI_Send(nrnb->n,eNRNB,MPI_DOUBLE,MASTERRANK(cr),0,
+ cr->mpi_comm_mysim);
+ }
}
+#endif
+ if (SIMMASTER(cr)) {
wallcycle_print(fplog,cr->nnodes,cr->npmenodes,runtime->realtime,
wcycle,cycles);
if (nfile != -1)
{
- *outf = init_mdoutf(nfile,fnm,(Flags & MD_APPENDFILES),cr,ir,oenv);
+ *outf = init_mdoutf(nfile,fnm,Flags,cr,ir,oenv);
*mdebin = init_mdebin((Flags & MD_APPENDFILES) ? NULL : (*outf)->fp_ene,
mtop,ir);
bPres = flags & CGLO_PRESSURE;
bConstrVir = flags & CGLO_CONSTRAINT;
bFirstIterate = flags & CGLO_FIRSTITERATE;
- bEkinAveVel = (inputrec->eI==eiVV || (inputrec->eI==eiVVAK && IR_NPT_TROTTER(inputrec) && bPres));
+ //bEkinAveVel = (inputrec->eI==eiVV || (inputrec->eI==eiVVAK && IR_NPT_TROTTER(inputrec) && bPres));
+ bEkinAveVel = (inputrec->eI==eiVV || (inputrec->eI==eiVVAK && bPres));
bReadEkin = flags & CGLO_READEKIN;
rb = gs->rb;
xx,NULL,(cr->nnodes-cr->npmenodes)-1,NULL);
}
-gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],bool bAppendFiles,
+gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],int mdrun_flags,
const t_commrec *cr,const t_inputrec *ir,
const output_env_t oenv)
{
gmx_mdoutf_t *of;
char filemode[3];
+ bool bAppendFiles;
snew(of,1);
- of->fp_trn = -1;
+ of->fp_trn = NULL;
of->fp_ene = NULL;
- of->fp_xtc = -1;
+ of->fp_xtc = NULL;
of->fp_dhdl = NULL;
of->fp_field = NULL;
if (MASTER(cr))
{
+ bAppendFiles = (mdrun_flags & MD_APPENDFILES);
+
+ of->bKeepAndNumCPT = (mdrun_flags & MD_KEEPANDNUMCPT);
+
sprintf(filemode, bAppendFiles ? "a+" : "w+");
- if (ir->eI != eiNM)
+ if (ir->eI != eiNM
+#ifndef GMX_FAHCORE
+ &&
+ !(EI_DYNAMICS(ir->eI) &&
+ ir->nstxout == 0 &&
+ ir->nstvout == 0 &&
+ ir->nstfout == 0)
+#endif
+ )
{
of->fp_trn = open_trn(ftp2fn(efTRN,nfile,fnm), filemode);
}
- if (ir->nstxtcout > 0 && !EI_ENERGY_MINIMIZATION(ir->eI))
+ if (!EI_ENERGY_MINIMIZATION(ir->eI) &&
+ ir->nstxtcout > 0)
{
of->fp_xtc = open_xtc(ftp2fn(efXTC,nfile,fnm), filemode);
of->xtc_prec = ir->xtcprec;
{
close_enx(of->fp_ene);
}
- if (of->fp_xtc >= 0)
+ if (of->fp_xtc)
{
close_xtc(of->fp_xtc);
}
- if (of->fp_trn >= 0)
+ if (of->fp_trn)
{
close_trn(of->fp_trn);
}
{
if (mdof_flags & MDOF_CPT)
{
- write_checkpoint(of->fn_cpt,fplog,cr,of->eIntegrator,
+ write_checkpoint(of->fn_cpt,of->bKeepAndNumCPT,
+ fplog,cr,of->eIntegrator,
of->simulation_part,step,t,state_global);
}
bool b14only,bReadTab,bGenTab;
real x0,y0,yp;
int i,j,k,nx,nx0,tabsel[etiNR];
- void * p_tmp;
t_forcetable table;
}
/* Each table type (e.g. coul,lj6,lj12) requires four
- * numbers per datapoint. For performance reasons we want
- * the table data to be aligned to 16-byte. This is accomplished
- * by allocating 16 bytes extra to a temporary pointer, and then
- * calculating an aligned pointer. This new pointer must not be
- * used in a free() call, but thankfully we're sloppy enough not
- * to do this :-)
+ * numbers per nx+1 data points. For performance reasons we want
+ * the table data to be aligned to 16-byte.
*/
+ snew_aligned(table.tab, 12*(nx+1)*sizeof(real),16);
- /* 12 fp entries per table point, nx+1 points, and 16 bytes extra to align it. */
- p_tmp = malloc(12*(nx+1)*sizeof(real)+16);
-
- /* align it - size_t has the same same as a pointer */
- table.tab = (real *) (((size_t) p_tmp + 16) & (~((size_t) 15)));
-
-
for(k=0; (k<etiNR); k++) {
if (tabsel[k] != etabUSER) {
init_table(out,nx,nx0,
rvec *f;
real lambda,t,temp,beta,drmax,epot;
double embU,sum_embU,*sum_UgembU,V,V_all,VembU_all;
- int status;
+ t_trxstatus *status;
t_trxframe rerun_fr;
bool bDispCorr,bCharge,bRFExcl,bNotLastFrame,bStateChanged,bNS,bOurStep;
tensor force_vir,shake_vir,vir,pres;
# used to create build rules automatically.
#
set(NGMX_PROGRAMS
- ngmx xrama highway gmxlogo dlg scrollw showcol)
+ ngmx g_xrama g_highway g_logo)
foreach(PROG ${NGMX_PROGRAMS})
add_executable(${PROG} ${PROG}.c ${NGMX_COMMON_SOURCE})
- target_link_libraries(${PROG} gmx ${GMX_EXTRA_LIBRARIES} ${X11_LIBRARIES})
+ target_link_libraries(${PROG} gmx ${GMX_EXTRA_LIBRARIES} ${X11_LIBRARIES})
+ set_target_properties(${PROG} PROPERTIES OUTPUT_NAME "${PROG}${GMX_BINARY_SUFFIX}")
endforeach(PROG)
if USE_X11
-bin_PROGRAMS = ngmx xrama highway
-EXTRA_PROGRAMS = gmxlogo dlg scrollw showcol
+bin_PROGRAMS = ngmx g_xrama g_highway g_logo
+EXTRA_PROGRAMS = test_ngmx_dialog g_showcol
endif
ngmx_SOURCES = ngmx.c $(XSRC)
-xrama_SOURCES = xrama.c $(XSRC)
-highway_SOURCES = highway.c $(XSRC)
-gmxlogo_SOURCES = gmxlogo.c logo.c $(XSRC)
-dlg_SOURCES = dlg.c $(XSRC)
-scrollw_SOURCES = scrollw.c $(XSRC)
-showcol_SOURCES = showcol.c $(XSRC)
-
+g_xrama_SOURCES = g_xrama.c $(XSRC)
+g_highway_SOURCES = g_highway.c $(XSRC)
+g_logo_SOURCES = g_logo.c $(XSRC)
+g_showcol_SOURCES = g_showcol.c $(XSRC)
+test_ngmx_dialog_SOURCES = test_ngmx_dialog.c $(XSRC)
CLEANFILES = *~ \\\#*
fprintf(stderr,"No X!\n");
exit(1);
}
- logo=init_logo(x11,x11->root);
+ logo=init_logo(x11,x11->root,TRUE);
show_logo(x11,logo);
x11->MainLoop(x11);
x11->CleanUp(x11);
+ return 0;
}
#include <string2.h>
#include <Xstuff.h>
#include "xutil.h"
+#include "futil.h"
typedef struct {
XColor xc;
fn=argv[1];
else
fn="/usr/lib/X11/rgb.txt";
+ if (!gmx_fexist(fn)) {
+ fprintf(stderr,"Usage: %s rgb.txt\n",argv[0]);
+ fprintf(stderr,"rgb.txt is usually somewhere in your X windows directories.\n");
+ exit(1);
+ }
sc=init_sc(x11,x11->root,fn);
XMapWindow(x11->disp,sc->wd.self);
XMapSubwindows(x11->disp,sc->wd.self);
x11->MainLoop(x11);
x11->CleanUp(x11);
+
+ return 0;
}
static t_mess Mess[] = {
{ "GROMACS", 0, 20, NULL },
{ NULL, 16, 9, NULL },
- { "Copyright (c) 1991-2004", COFFS+ 2, 9, NULL },
+ { "Copyright (c) 1991-2010", COFFS+ 2, 9, NULL },
{ "D.v.d.Spoel, E.Lindahl, B.Hess", COFFS+11, 9, NULL },
{ "& Groningen University ", COFFS+20, 9, NULL },
{ "click to dismiss", COFFS+31, 8, NULL }
break;
case ButtonPress:
hide_logo(x11,logo);
+ return logo->bQuitOnClick;
break;
default:
break;
return FALSE;
}
-t_logo *init_logo(t_x11 *x11,Window parent)
+t_logo *init_logo(t_x11 *x11,Window parent,bool bQuitOnClick)
{
static const char *bfname[]= {
"-b&h-lucida-bold-i-normal-sans-34-240-100-100-p-215-iso8859-1",
t_logo *logo;
snew(logo,1);
+ logo->bQuitOnClick = bQuitOnClick;
InitWin(&logo->wd,0,0,360,270,1,"GROMACS");
bg=LIGHTGREY;
if ((newcol=getenv("LOGO"))!=NULL)
XFontStruct *bigfont;
XFontStruct *smallfont;
t_windata wd;
+ bool bQuitOnClick;
} t_logo;
extern void show_logo(t_x11 *x11,t_logo *logo);
extern void hide_logo(t_x11 *x11,t_logo *logo);
-extern t_logo *init_logo(t_x11 *x11,Window parent);
+extern t_logo *init_logo(t_x11 *x11,Window parent,bool bQuitOnClick);
extern void done_logo(t_x11 *x11,t_logo *logo);
snew(man->bHydro,sh.natoms);
snew(bB,sh.natoms);
read_tpx_top(status,NULL,man->box,&man->natom,NULL,NULL,NULL,&man->top);
+ man->gpbc = gmx_rmpbc_init(&man->top.idef,-1,man->natom,man->box);
man->natom=
read_first_x(man->oenv,&man->status,trajectory,&(man->time),&(man->x),
break;
}
if (man->bPbc) {
- rm_pbc(&(man->top.idef),man->molw->ePBC,
- man->natom,man->box,man->x,man->x);
+ gmx_rmpbc(man->gpbc,man->box,man->x,man->x);
reset_mols(&(man->top.mols),man->box,man->x);
}
ncount=0;
draw_mol(x11,man);
break;
case IDREWIND:
- if (man->status != -1) {
+ if (man->status) {
rewind_trj(man->status);
read_next_x(man->oenv,man->status,&(man->time),man->natom,man->x,
man->box);
bool toggle_animate (t_x11 *x11,t_manager *man)
{
- if (man->status != -1) {
+ if (man->status) {
man->bAnimate=!man->bAnimate;
man->bStop=TRUE;
man->bEof=FALSE;
t_manager *man;
snew(man,1);
- man->status=-1;
+ man->status=NULL;
man->bPlus=TRUE;
man->bSort=TRUE;
man->oenv=oenv;
#include "3dview.h"
#include "nleg.h"
#include "buttons.h"
+#include "statutil.h"
+#include "rmpbc.h"
/* Some window sizes */
#define EWIDTH 200
*
*/
typedef struct {
- int status;
+ t_trxstatus *status;
const char *trajfile;
int natom; /* The number of atoms */
t_topology top; /* topology */
bool bPlus; /* Draw plus for single atom */
int nSkip; /* Skip n steps after each frame */
int nWait; /* Wait n ms after each frame */
-
+ gmx_rmpbc_t gpbc; /* For removing peridiocity */
+
t_windata wd; /* The manager subwindow */
t_windata title; /* Title window */
t_3dview *view; /* The 3d struct */
real sx,sy;
vec4 x4;
- if (man->status == -1)
+ if (!man->status)
return;
view=man->view;
int ePBC;
matrix box;
t_trxframe fr;
- int status;
+ t_trxstatus *status;
char quote[256];
snew(gmx,1);
/* The order of creating windows is important here! */
/* Manager */
gmx->man = init_man(x11,gmx->wd->self,0,0,1,1,WHITE,BLACK,ePBC,box,oenv);
- gmx->logo = init_logo(x11,gmx->wd->self);
+ gmx->logo = init_logo(x11,gmx->wd->self,FALSE);
/* Now put all windows in the proper place */
move_gmx(x11,gmx,w0,h0,FALSE);
real sx,sy;
vec4 x4;
- if (man->status == -1)
+ if (!man->status)
return;
view=man->view;
+++ /dev/null
-/*
- *
- * This source code is part of
- *
- * G R O M A C S
- *
- * GROningen MAchine for Chemical Simulations
- *
- * VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- *
- * And Hey:
- * Gyas ROwers Mature At Cryogenic Speed
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sysstuff.h>
-#include <Xstuff.h>
-#include <xutil.h>
-#include <smalloc.h>
-#include <macros.h>
-#include <futil.h>
-#include <string2.h>
-
-#define YSPACE 2
-
-typedef struct {
- t_windata wd; /* Window structure */
- int nlines,top; /* Number of lines, current top line */
- char **lines; /* The strings */
- int wheight,wwidth; /* The size of the window in chars */
- XFontStruct *font; /* Font */
- unsigned long fg,bg; /* Colours */
-} t_scrollw;
-
-static void calc_scrollw(t_scrollw *sw,int w,int h)
-{
- sw->wd.width=w;
- sw->wd.height=h;
- sw->wheight=h/(YSPACE+XTextHeight(sw->font));
- sw->wwidth=w/XTextWidth(sw->font,"W",1);
-}
-
-static bool SWCallback(t_x11 *x11,XEvent *event,Window w,void *data)
-{
- t_scrollw *sw;
- int i,y,nl,barw,btop,bheight;
- real h,frac;
-
- sw=(t_scrollw *)data;
-
- /* Calc some bar data */
- barw=20;
- h=XTextHeight(sw->font)+YSPACE;
- frac=min(1.0,((real)sw->wheight)/((real)sw->nlines));
- btop=((((real)sw->top)/((real)sw->nlines)))*(sw->wd.height);
- bheight=frac*sw->wd.height;
- bheight-=bheight/h;
-
- switch(event->type) {
- case Expose:
- nl=min(sw->nlines,sw->top+sw->wheight);
- y=0;
-
- XClearWindow(x11->disp,w);
-#ifdef DEBUG
- printf("btop: %d, bheight: %d, frac: %e, h: %e\n",btop,bheight,frac,h);
-#endif
- /* Draw the bar */
- XSetForeground(x11->disp,x11->gc,LIGHTGREY);
- XFillRectangle(x11->disp,w,x11->gc,2,btop+2,barw-4,bheight-4);
- XDrawLine(x11->disp,w,x11->gc,barw,0,barw,sw->wd.height);
-
- /* Draw the text */
- XSetForeground(x11->disp,x11->gc,sw->fg);
- for(i=sw->top; (i<nl); i++) {
- SpecialTextInRect(x11,sw->font,w,
- sw->lines[i],barw+2,y,sw->wd.width-barw-4,(int)h,
- eXLeft,eYCenter);
- y+=h;
- }
- XSetForeground(x11->disp,x11->gc,x11->fg);
- break;
- case ConfigureNotify:
- calc_scrollw(sw,event->xconfigure.width,event->xconfigure.height);
- break;
- case ButtonPress:
- if (event->xbutton.x < barw) {
- int y=event->xbutton.y;
-
- if (sw->nlines > sw->wheight) {
- if (y<btop)
- sw->top=max(0,sw->top-1);
- else if (y>btop+bheight)
- sw->top=min(sw->nlines-sw->wheight,sw->top+1);
- else
- break;
- ExposeWin(x11->disp,sw->wd.self);
- }
- }
- break;
- default:
- break;
- }
-
- return FALSE;
-}
-
-t_scrollw *init_scrollw(t_x11 *x11,Window parent,int x,int y,int w,int h,
- unsigned long fg,unsigned long bg)
-{
- t_scrollw *sw;
-
- snew(sw,1);
-
- InitWin(&sw->wd,x,y,w,h,1,"Scroll Window");
- sw->fg=fg;
- sw->bg=bg;
- sw->font=x11->font;
- sw->wd.self=XCreateSimpleWindow(x11->disp,parent,x,y,w,h,
- sw->wd.bwidth,fg,bg);
- x11->RegisterCallback(x11,sw->wd.self,parent,SWCallback,sw);
- x11->SetInputMask(x11,sw->wd.self,ExposureMask | ButtonPressMask |
- StructureNotifyMask);
- calc_scrollw(sw,w,h);
-
- return sw;
-}
-
-void show_scrollw(t_x11 *x11,t_scrollw *sw)
-{
- XMapWindow(x11->disp,sw->wd.self);
-}
-
-char *tab2spc(char *buf)
-{
- char *buf2;
- char *new;
- int i,j;
-
- snew(buf2,8*strlen(buf)+1);
- for(i=j=0; (buf[i]!='\0'); i++)
- if (buf[i]=='\t')
- do {
- buf2[j++]=' ';
- } while ((j % 8)!=0);
- else
- buf2[j++]=buf[i];
- buf2[j]='\0';
- new=strdup(buf2);
- sfree(buf2);
- return new;
-}
-
-void read_lines(FILE *in,t_scrollw *sw)
-{
- char buf[1024];
-
- while (fgets2(buf,1023,in)) {
- sw->nlines++;
- srenew(sw->lines,sw->nlines);
- sw->lines[sw->nlines-1]=tab2spc(buf);
- }
-}
-
-int
-main(int argc, char *argv[])
-{
- t_x11 *x11;
- t_scrollw *sw;
-
- if ((x11=GetX11(&argc,argv))==NULL) {
- fprintf(stderr,"No X!\n");
- exit(1);
- }
- sw=init_scrollw(x11,x11->root,0,0,600,200,WHITE,BLACK);
- read_lines(stdin,sw);
- show_scrollw(x11,sw);
- x11->MainLoop(x11);
-
- x11->CleanUp(x11);
-}
eigio.c cmat.c
eigensolver.c nsc.c
hxprops.c fitahx.c
+ geminate.c
gmx_analyze.c gmx_anaeig.c gmx_angle.c gmx_bond.c
gmx_bundle.c gmx_chi.c gmx_cluster.c gmx_confrms.c
gmx_covar.c gmx_current.c
gmx_trjconv.c gmx_trjcat.c gmx_trjorder.c gmx_xpm2ps.c
gmx_editconf.c gmx_genbox.c gmx_genion.c gmx_genconf.c
gmx_genpr.c gmx_eneconv.c gmx_vanhove.c gmx_wheel.c
- addconf.c calcpot.c edittop.c gmx_bar.c)
+ addconf.c calcpot.c edittop.c gmx_bar.c
+ gmx_membed.c )
target_link_libraries(gmxana md ${GMX_EXTRA_LIBRARIES})
-
+set_target_properties(gmxana PROPERTIES OUTPUT_NAME "gmxana${GMX_BINARY_SUFFIX}")
# List of programs with single corresponding .c source file,
# used to create build rules automatically.
#
set(GMX_TOOLS_PROGRAMS
do_dssp editconf eneconv genbox genconf genrestr g_nmtraj
- make_ndx mk_angndx trjcat trjconv trjorder wheel
- xpm2ps genion anadock make_edi g_analyze g_anaeig
+ make_ndx mk_angndx trjcat trjconv trjorder g_wheel
+ xpm2ps genion g_anadock make_edi g_analyze g_anaeig
g_angle g_bond g_bundle g_chi g_cluster g_confrms g_covar
g_current g_density g_densmap g_dih g_dielectric
g_helixorient g_principal g_dipoles g_disre g_dist
g_nmens g_order g_polystat g_potential g_rama g_rdf g_rms
g_rmsf g_rotacf g_saltbr g_sas g_select g_sgangle g_sham g_sorient
g_spol g_sdf g_spatial g_tcaf g_traj g_tune_pme g_vanhove
- g_velacc g_clustsize g_mdmat g_wham g_kinetics sigeps g_bar
+ g_velacc g_clustsize g_mdmat g_wham g_kinetics g_sigeps g_bar
+ g_membed
)
foreach(TOOL ${GMX_TOOLS_PROGRAMS})
add_executable(${TOOL} ${TOOL}.c)
target_link_libraries(${TOOL} gmxana)
+ set_target_properties(${TOOL} PROPERTIES OUTPUT_NAME "${TOOL}${GMX_BINARY_SUFFIX}")
endforeach(TOOL ${GMX_TOOLS_PROGRAMS})
libgmxana@LIBSUFFIX@_la_SOURCES = \
+ geminate.c geminate.h \
autocorr.c expfit.c polynomials.c levenmar.c \
anadih.c pp2shift.c pp2shift.h dlist.c \
eigio.c cmat.c cmat.h \
gmx_trjconv.c gmx_trjcat.c gmx_trjorder.c gmx_xpm2ps.c \
gmx_editconf.c gmx_genbox.c gmx_genion.c gmx_genconf.c \
gmx_genpr.c gmx_eneconv.c gmx_vanhove.c gmx_wheel.c \
- addconf.c addconf.h gmx_tune_pme.c \
+ addconf.c addconf.h gmx_tune_pme.c gmx_membed.c \
calcpot.c calcpot.h edittop.c
bin_PROGRAMS = \
do_dssp editconf eneconv \
genbox genconf genrestr g_nmtraj \
make_ndx mk_angndx trjcat trjconv \
- trjorder wheel xpm2ps genion \
- anadock make_edi \
+ trjorder g_wheel xpm2ps genion \
+ g_anadock make_edi \
g_analyze g_anaeig g_bar \
g_angle g_bond \
g_bundle g_chi g_cluster g_confrms \
g_sham g_sorient g_spol \
g_sdf g_spatial \
g_tcaf g_traj g_tune_pme \
- g_vanhove g_velacc \
+ g_vanhove g_velacc g_membed \
g_clustsize g_mdmat g_wham g_kinetics \
- sigeps
+ g_sigeps
LDADD = $(lib_LTLIBRARIES) ../mdlib/libmd@LIBSUFFIX@.la \
dump_nblist(debug,cr,fr,0);
if (bVerbose)
- fprintf(stderr,"Succesfully made neighbourlist\n");
+ fprintf(stderr,"Successfully made neighbourlist\n");
}
bool bXor(bool b1,bool b2)
const output_env_t oenv)
{
t_pbc *pbc;
- int i,angind,status,natoms,total,teller;
+ t_trxstatus *status;
+ int i,angind,natoms,total,teller;
int nangles,n_alloc;
real t,fraction,pifac,aa,angle;
real *angles[2];
bool bFour = acf.bFour;
/* Check flags and parameters */
- /* nout = get_acfnout();*/
+ nout = get_acfnout();
if (nout == -1)
nout = acf.nout = (nframes+1)/2;
else if (nout > nframes)
{ "-beginfit", FALSE, etREAL, {&acf.tbeginfit},
"Time where to begin the exponential fit of the correlation function" },
{ "-endfit", FALSE, etREAL, {&acf.tendfit},
- "Time where to end the exponential fit of the correlation function, -1 is till the end" },
+ "Time where to end the exponential fit of the correlation function, -1 is until the end" },
};
#define NPA asize(acfpa)
t_pargs *ppa;
+++ /dev/null
-/*
- *
- * This source code is part of
- *
- * G R O M A C S
- *
- * GROningen MAchine for Chemical Simulations
- *
- * VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- *
- * And Hey:
- * Green Red Orange Magenta Azure Cyan Skyblue
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <math.h>
-#include "string2.h"
-#include "smalloc.h"
-#include "statutil.h"
-#include "vec.h"
-
-static void my_usage(char *prog,char *arg)
-{
- fprintf(stderr," Usage: %s [-p] [-s] [-c #columns]"
- " naver < infile > outfile\n",prog);
- fprintf(stderr,"-p means picoseconds rather than nanoseconds\n");
- fprintf(stderr,"-s means silent rather than verbose\n");
- fprintf(stderr,"Don't ever use argument %s again!\n",arg);
- exit(1);
-}
-
-void lsq_y_ax_b_double(int n, double x[], double y[], double *a, double *b)
-{
- int i;
- double yx,xx,sx,sy;
-
- yx=xx=sx=sy=0.0;
- for (i=0; (i < n); i++) {
- yx+=y[i]*x[i];
- xx+=x[i]*x[i];
- sx+=x[i];
- sy+=y[i];
- }
- *a=(n*yx-sy*sx)/(n*xx-sx*sx);
- *b=(sy-(*a)*sx)/n;
-}
-
-int main(int argc, char *argv[])
-{
- double *x,**y,value=0.001;
- double *yav,yyy,yyy2,ymin,ymax,aver,var,sd;
- int i,j,k,nav=100,ncol=1,MAX=50000;
- char buf[STRLEN];
- bool bSilent=FALSE,bVerySilent=FALSE;
- double lsq_a,lsq_b,rms_res;
-
- for(i=1; (i<argc); i++) {
- if (argv[i][0] == '-')
- switch (argv[i][1]) {
- case 'p':
- value=1.0;
- break;
- case 'm':
- MAX=iscan(argc,argv,&i);
- break;
- case 'c':
- ncol=iscan(argc,argv,&i);
- break;
- case 's':
- bSilent=TRUE;
- break;
- case 'S':
- bVerySilent=bSilent=TRUE;
- break;
- default:
- my_usage(argv[0],argv[i]);
- }
- else
- nav=strtol(argv[i],NULL,10);
- }
- if (!bSilent)
- fprintf(stderr,"Will average stdin with %d columns, over %d points\n",
- ncol,nav);
-
-
- snew(x,MAX);
- snew(y,ncol);
- for(i=0; (i<ncol); i++) {
- snew(y[i],MAX);
- }
- snew(yav,MAX);
- i=0;
- do {
- if (scanf("%s",buf) == 1) {
- if ((buf[0] != '@') && (buf[0] != '#')) {
- sscanf(buf,"%lf",&x[i]);
- for(k=0; (k<ncol); k++)
- scanf("%lf",&(y[k][i]));
- if (i >= nav) {
- if (!bVerySilent)
- printf("%10e",x[i-nav/2]*value);
- for(k=0; (k<ncol); k++) {
- yav[k]=0;
- for(j=i-nav+1; (j<=i); j++)
- yav[k]+=y[k][j];
- yav[k]/=nav;
- if (!bVerySilent)
- printf(" %10e",yav[k]);
- }
- if (!bVerySilent)
- printf("\n");
- }
- i++;
- }
- else {
- while (getc(stdin) != '\n')
- ;
- }
- }
- else
- break;
- } while (((int)strlen(buf) > 0) && (i<MAX));
-
-
- if (!bSilent)
- fprintf(stderr,"%3s %12s %12s %12s %12s %12s %12s %12s\n",
- "i","min","aver","max","var","sd","drift","fluc");
- for(k=0; (k<ncol); k++) {
- aver=y[k][0];
- ymin=aver;
- ymax=aver;
- yyy2=aver*aver;
- for(j=1; (j<i); j++) {
- yyy=y[k][j];
- aver+=yyy;
- yyy2+=(yyy*yyy);
- if (yyy < ymin)
- ymin=yyy;
- else if (yyy > ymax)
- ymax=yyy;
- }
- aver/=i;
- var=yyy2/i-aver*aver;
- sd=sqrt(var);
-
- lsq_y_ax_b_double(i,x,y[k],&lsq_a,&lsq_b);
- rms_res=0;
- for(j=0; (j<i);j++)
- rms_res+=sqr(y[k][j]-(lsq_a*x[j]+lsq_b));
- rms_res=sqrt(rms_res/i);
-
- fprintf(stderr,"%3d %12g %12g %12g %12g %12g %12g %12g\n",
- k,ymin,aver,ymax,var,sd,lsq_a,rms_res);
- }
- return 0;
-}
-
-
init_nrnb(&nrnb);
snew(state,1);
- init_single(fplog,inputrec,tpx,mtop,state);
+ read_tpx_state(tpx,inputrec,state, NULL, mtop);
+ set_state_entries(state,inputrec,1);
+ if (fplog)
+ pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE);
+
+
if (inputrec->efep) {
fprintf(stderr,"WARNING: turning of free energy, will use lambda=0\n");
*atoms->atomname[i]=OOO;
else if (strcmp(*(atoms->atomname[i]),"O1")==0)
*atoms->atomname[i]=OOO;
+ else if (strcmp(*(atoms->atomname[i]),"OC1")==0)
+ *atoms->atomname[i]=OOO;
}
}
"Secondary structures for structure count"}
};
- int status;
+ t_trxstatus *status;
FILE *tapein;
FILE *ss,*acc,*fTArea,*tmpf;
const char *fnSCount,*fnArea,*fnTArea,*fnAArea;
char dssp[256];
const char *dptr;
output_env_t oenv;
-
+ gmx_rmpbc_t gpbc=NULL;
t_filenm fnm[] = {
{ efTRX, "-f", NULL, ffREAD },
snew(norm_av_area, atoms->nres);
accr=NULL;
naccr=0;
+
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
do {
t = output_env_conv_time(oenv,t);
if (bDoAccSurf && nframe>=naccr) {
for(i=naccr-10; i<naccr; i++)
snew(accr[i],2*atoms->nres-1);
}
- rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
tapein=ffopen(pdbfile,"w");
write_pdbfile_indexed(tapein,NULL,atoms,x,ePBC,box,0,-1,gnx,index,NULL);
ffclose(tapein);
close_trj(status);
if (fTArea)
ffclose(fTArea);
-
+ gmx_rmpbc_done(gpbc);
+
prune_ss_legend(&mat);
ss=opt2FILE("-o",NFILE,fnm,"w");
#include "eigio.h"
#include "trnio.h"
#include "tpxio.h"
+#include "statutil.h"
#include "futil.h"
void read_eigenvectors(const char *file,int *natoms,bool *bFit,
rvec ***eigvec,real **eigval)
{
t_trnheader head;
- int status,i,snew_size;
+ int i,snew_size;
+ t_fileio *status;
rvec *x;
matrix box;
bool bOK;
int WriteXref,rvec *xref,bool bDMR,
rvec xav[], bool bDMA,real eigval[])
{
- int trnout;
+ t_fileio *trnout;
int ndim,i,j,d,vec;
matrix zerobox;
rvec *x;
nparm = nfp_ffn[eFitFn];
if (debug) {
fprintf(debug,"There are %d points to fit %d vars!\n",ndata,nparm);
- fprintf(debug,"Fit to function %d from %g thru %g, dt=%g\n",
+ fprintf(debug,"Fit to function %d from %g through %g, dt=%g\n",
eFitFn,begintimefit,endtimefit,dt);
}
--- /dev/null
+/*
+ * $Id: g_prot2mem.c 2009/04/02 M.G. Wolf $
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 4.0.3
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Green Red Orange Magenta Azure Cyan Skyblue
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gmx_ana.h>
+
+
+/* This is just a wrapper binary.
+* The code that used to be in g_anaeig.c is now in gmx_anaeig.c,
+* where the old main function is called gmx_anaeig().
+*/
+int
+main(int argc, char *argv[])
+{
+ gmx_membed(argc,argv);
+ return 0;
+}
+
+
+
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBGSL
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_blas.h>
+#include <gsl/gsl_multimin.h>
+#include <gsl/gsl_multifit_nlin.h>
+#include <gsl/gsl_sf.h>
+#include <gsl/gsl_version.h>
+#endif
+
+#include "typedefs.h"
+#include "smalloc.h"
+#include "vec.h"
+#include "geminate.h"
+
+#ifdef DOUSEOPENMP
+#define HAVE_OPENMP
+#endif
+#ifdef HAVE_OPENMP
+#include <omp.h>
+#endif
+
+/* The first few sections of this file contain functions that were adopted,
+ * and to some extent modified, by Erik Marklund (erikm[aT]xray.bmc.uu.se,
+ * http://folding.bmc.uu.se) from code written by Omer Markovitch (email, url).
+ * This is also the case with the function eq10v2().
+ *
+ * The parts menetioned in the previous paragraph were contributed under a BSD license.
+ */
+
+
+/* This first part is from complex.c which I recieved from Omer Markowitch.
+ * - Erik Marklund
+ *
+ * ------------- from complex.c ------------- */
+
+/* Complexation of a paired number (r,i) */
+static gem_complex gem_cmplx(double r, double i)
+{
+ gem_complex value;
+ value.r = r;
+ value.i=i;
+ return value;
+}
+
+/* Complexation of a real number, x */
+static gem_complex gem_c(double x)
+{
+ gem_complex value;
+ value.r=x;
+ value.i=0;
+ return value;
+}
+
+/* Real and Imaginary part of a complex number z -- Re (z) and Im (z) */
+static double gem_Re(gem_complex z) {return z.r;}
+static double gem_Im(gem_complex z) {return z.i;}
+
+/* Magnitude of a complex number z */
+static double gem_cx_abs(gem_complex z) { return (sqrt(z.r*z.r+z.i*z.i)); }
+
+/* Addition of two complex numbers z1 and z2 */
+static gem_complex gem_cxadd(gem_complex z1, gem_complex z2)
+{
+ gem_complex value;
+ value.r=z1.r+z2.r;
+ value.i=z1.i+z2.i;
+ return value;
+}
+
+/* Addition of a complex number z1 and a real number r */
+static gem_complex gem_cxradd(gem_complex z, double r)
+{
+ gem_complex value;
+ value.r = z.r + r;
+ value.i = z.i;
+ return value;
+}
+
+/* Subtraction of two complex numbers z1 and z2 */
+static gem_complex gem_cxsub(gem_complex z1, gem_complex z2)
+{
+ gem_complex value;
+ value.r=z1.r-z2.r;
+ value.i=z1.i-z2.i;
+ return value;
+}
+
+/* Multiplication of two complex numbers z1 and z2 */
+static gem_complex gem_cxmul(gem_complex z1, gem_complex z2)
+{
+ gem_complex value;
+ value.r = z1.r*z2.r-z1.i*z2.i;
+ value.i = z1.r*z2.i+z1.i*z2.r;
+ return value;
+}
+
+/* Square of a complex number z */
+static gem_complex gem_cxsq(gem_complex z)
+{
+ gem_complex value;
+ value.r = z.r*z.r-z.i*z.i;
+ value.i = z.r*z.i*2.;
+ return value;
+}
+
+/* multiplication of a complex number z and a real number r */
+static gem_complex gem_cxrmul(gem_complex z, double r)
+{
+ gem_complex value;
+ value.r = z.r*r;
+ value.i= z.i*r;
+ return value;
+}
+
+/* Division of two complex numbers z1 and z2 */
+static gem_complex gem_cxdiv(gem_complex z1, gem_complex z2)
+{
+ gem_complex value;
+ double num;
+ num = z2.r*z2.r+z2.i*z2.i;
+ if(num == 0.)
+ {
+ fprintf(stderr, "ERROR in gem_cxdiv function\n");
+ }
+ value.r = (z1.r*z2.r+z1.i*z2.i)/num; value.i = (z1.i*z2.r-z1.r*z2.i)/num;
+ return value;
+}
+
+/* division of a complex z number by a real number x */
+static gem_complex gem_cxrdiv(gem_complex z, double r)
+{
+ gem_complex value;
+ value.r = z.r/r;
+ value.i = z.i/r;
+ return value;
+}
+
+/* division of a real number r by a complex number x */
+static gem_complex gem_rxcdiv(double r, gem_complex z)
+{
+ gem_complex value;
+ double f;
+ f = r/(z.r*z.r+z.i*z.i);
+ value.r = f*z.r;
+ value.i = -f*z.i;
+ return value;
+}
+
+/* Integer power of a complex number z -- z^x */
+static gem_complex gem_cxintpow(gem_complex z, int x)
+{
+ int i;
+ gem_complex value;
+
+ value.r = 1.;
+ value.i = 0.;
+
+ if(x>0)
+ {
+ for(i=0; i < x; i++)
+ value = gem_cxmul(value, z);
+ return value;
+ }
+ else
+ {
+ if(x<0) {
+ for(i=0; i > x; i--)
+ value = gem_cxdiv(value, z);
+ return value;
+ }
+ else {
+ return value;
+ }
+ }
+}
+
+/* Exponential of a complex number-- exp (z)=|exp(z.r)|*{cos(z.i)+I*sin(z.i)}*/
+static gem_complex gem_cxdexp(gem_complex z)
+{
+ gem_complex value;
+ double exp_z_r;
+ exp_z_r = exp(z.r);
+ value.r = exp_z_r*cos(z.i);
+ value.i = exp_z_r*sin(z.i);
+ return value;
+}
+
+/* Logarithm of a complex number -- log(z)=log|z|+I*Arg(z), */
+/* where -PI < Arg(z) < PI */
+static gem_complex gem_cxlog(gem_complex z)
+{
+ gem_complex value;
+ double mag2;
+ mag2 = z.r*z.r+z.i*z.i;
+ if(mag2 < 0.) {
+ fprintf(stderr, "ERROR in gem_cxlog func\n");
+ }
+ value.r = log(sqrt(mag2));
+ if(z.r == 0.) {
+ value.i = PI/2.;
+ if(z.i <0.) {
+ value.i = -value.i;
+ }
+ } else {
+ value.i = atan2(z.i, z.r);
+ }
+ return value;
+}
+
+/* Square root of a complex number z = |z| exp(I*the) -- z^(1/2) */
+/* z^(1/2)=|z|^(1/2)*[cos(the/2)+I*sin(the/2)] */
+/* where 0 < the < 2*PI */
+static gem_complex gem_cxdsqrt(gem_complex z)
+{
+ gem_complex value;
+ double sq;
+ sq = gem_cx_abs(z);
+ value.r = sqrt(fabs((sq+z.r)*0.5)); /* z'.r={|z|*[1+cos(the)]/2}^(1/2) */
+ value.i = sqrt(fabs((sq-z.r)*0.5)); /* z'.i={|z|*[1-cos(the)]/2}^(1/2) */
+ if(z.i < 0.) {
+ value.r = -value.r;
+ }
+ return value;
+}
+
+/* square root of a real number r */
+static gem_complex gem_cxrsqrt(double r) {
+ if (r < 0)
+ {
+ return(gem_cmplx(0, sqrt(-r)));
+ }
+ else
+ {
+ return(gem_c(sqrt(r)));
+ }
+}
+
+/* Complex power of a complex number z1^z2 */
+static gem_complex gem_cxdpow(gem_complex z1, gem_complex z2)
+{
+ gem_complex value;
+ value=gem_cxdexp(gem_cxmul(gem_cxlog(z1),z2));
+ return value;
+}
+
+/* Print out a complex number z as z: z.r, z.i */
+static void gem_cxprintf(gem_complex z) { fprintf(stdout, "z: %lg + %lg_i\n", z.r, z.i); }
+/* ------------ end of complex.c ------------ */
+
+/* This next part was derived from cubic.c, also received from Omer Markovitch.
+ * ------------- from cubic.c ------------- */
+
+/* Solver for a cubic equation: x^3-a*x^2+b*x-c=0 */
+static void gem_solve(gem_complex *al, gem_complex *be, gem_complex *gam,
+ double a, double b, double c)
+{
+ double t1, t2, two_3, temp;
+ gem_complex ctemp, ct3;
+
+ two_3=pow(2., 1./3.); t1 = -a*a+3.*b; t2 = 2.*a*a*a-9.*a*b+27.*c;
+ temp = 4.*t1*t1*t1+t2*t2;
+
+ ctemp = gem_cmplx(temp,0.); ctemp = gem_cxadd(gem_cmplx(t2,0.),gem_cxdsqrt(ctemp));
+ ct3 = gem_cxdpow(ctemp, gem_cmplx(1./3.,0.));
+
+ ctemp = gem_rxcdiv(-two_3*t1/3., ct3);
+ ctemp = gem_cxadd(ctemp, gem_cxrdiv(ct3, 3.*two_3));
+
+ *gam = gem_cxadd(gem_cmplx(a/3.,0.), ctemp);
+
+ ctemp=gem_cxmul(gem_cxsq(*gam), gem_cxsq(gem_cxsub(*gam, gem_cmplx(a,0.))));
+ ctemp=gem_cxadd(ctemp, gem_cxmul(gem_cmplx(-4.*c,0.), *gam));
+ ctemp = gem_cxdiv(gem_cxdsqrt(ctemp), *gam);
+ *al = gem_cxrmul(gem_cxsub(gem_cxsub(gem_cmplx(a,0.), *gam),ctemp),0.5);
+ *be = gem_cxrmul(gem_cxadd(gem_cxsub(gem_cmplx(a,0.), *gam),ctemp),0.5);
+}
+
+/* ------------ end of cubic.c ------------ */
+
+/* This next part was derived from cerror.c and rerror.c, also received from Omer Markovitch.
+ * ------------- from [cr]error.c ------------- */
+
+/************************************************************/
+/* Real valued error function and related functions */
+/* x, y : real variables */
+/* erf(x) : error function */
+/* erfc(x) : complementary error function */
+/* omega(x) : exp(x*x)*erfc(x) */
+/* W(x,y) : exp(-x*x)*omega(x+y)=exp(2*x*y+y^2)*erfc(x+y) */
+/************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Utilzed the series approximation of erf(x) */
+/* Relative error=|err(x)|/erf(x)<EPS */
+/* Handbook of Mathematical functions, Abramowitz, p 297 */
+/* Note: When x>=6 series sum deteriorates -> Asymptotic series used instead */
+/*---------------------------------------------------------------------------*/
+/* This gives erfc(z) correctly only upto >10-15 */
+
+static double gem_erf(double x)
+{
+ double n,sum,temp,exp2,xm,x2,x4,x6,x8,x10,x12;
+ temp = x;
+ sum = temp;
+ xm = 26.;
+ x2 = x*x;
+ x4 = x2*x2;
+ x6 = x4*x2;
+ x8 = x6*x2;
+ x10 = x8*x2;
+ x12 = x10*x2;
+ exp2 = exp(-x2);
+ if(x <= xm)
+ {
+ for(n=1.; n<=2000.; n+=1.){
+ temp *= 2.*x2/(2.*n+1.);
+ sum += temp;
+ if(fabs(temp/sum)<1.E-16)
+ break;
+ }
+
+ if(n >= 2000.)
+ fprintf(stderr, "In Erf calc - iteration exceeds %lg\n",n);
+ sum *= 2./sPI*exp2;
+ }
+ else
+ {
+ /* from the asymptotic expansion of experfc(x) */
+ sum = (1. - 0.5/x2 + 0.75/x4
+ - 1.875/x6 + 6.5625/x8
+ - 29.53125/x10 + 162.421875/x12)
+ / sPI/x;
+ sum*=exp2; /* now sum is erfc(x) */
+ sum=-sum+1.;
+ }
+ return x>=0.0 ? sum : -sum;
+}
+
+/* Result --> Alex's code for erfc and experfc behaves better than this */
+/* complementray error function. Returns 1.-erf(x) */
+static double gem_erfc(double x)
+{
+ double t,z,ans;
+ z = fabs(x);
+ t = 1.0/(1.0+0.5*z);
+
+ ans = t * exp(-z*z - 1.26551223 +
+ t*(1.00002368 +
+ t*(0.37409196 +
+ t*(0.09678418 +
+ t*(-0.18628806 +
+ t*(0.27886807 +
+ t*(-1.13520398 +
+ t*(1.48851587 +
+ t*(-0.82215223 +
+ t*0.17087277)))))))));
+
+ return x>=0.0 ? ans : 2.0-ans;
+}
+
+/* omega(x)=exp(x^2)erfc(x) */
+static double gem_omega(double x)
+{
+ double xm, ans, xx, x4, x6, x8, x10, x12;
+ xm = 26;
+ xx=x*x;
+ x4=xx*xx;
+ x6=x4*xx;
+ x8=x6*xx;
+ x10=x8*xx;
+ x12=x10*xx;
+
+ if(x <= xm) {
+ ans = exp(xx)*gem_erfc(x);
+ } else {
+ /* Asymptotic expansion */
+ ans = (1. - 0.5/xx + 0.75/x4 - 1.875/x6 + 6.5625/x8 - 29.53125/x10 + 162.421875/x12) / sPI/x;
+ }
+ return ans;
+}
+
+/* W(x,y)=exp(-x^2)*omega(x+y)=exp(2xy+y^2)*erfc(x+y) */
+static double gem_W(double x, double y){ return(exp(-x*x)*gem_omega(x+y)); }
+
+/**************************************************************/
+/* Complex error function and related functions */
+/* x, y : real variables */
+/* z : complex variable */
+/* cerf(z) : error function */
+/* comega(z): exp(z*z)*cerfc(z) */
+/* W(x,z) : exp(-x*x)*comega(x+z)=exp(2*x*z+z^2)*cerfc(x+z) */
+/**************************************************************/
+static gem_complex gem_cerf(gem_complex z)
+{
+ gem_complex value;
+ double x,y;
+ double sumr,sumi,n,n2,f,temp,temp1;
+ double x2,cos_2xy,sin_2xy,cosh_2xy,sinh_2xy,cosh_ny,sinh_ny;
+
+ x = z.r;
+ y = z.i;
+ x2 = x*x;
+ sumr = 0.;
+ sumi = 0.;
+ cos_2xy = cos(2.*x*y);
+ sin_2xy = sin(2.*x*y);
+ cosh_2xy = cosh(2.*x*y);
+ sinh_2xy = sinh(2.*x*y);
+
+ for(n=1.0,temp=0.; n<=2000.; n+=1.0)
+ {
+ n2 = n*n;
+ cosh_ny = cosh(n*y);
+ sinh_ny = sinh(n*y);
+ f = exp(-n2/4.)/(n2+4.*x2);
+ sumr += (2.*x - 2.*x*cosh_ny*cos_2xy+n*sinh_ny*sin_2xy)*f;
+ sumi += (2.*x*cosh_ny*sin_2xy + n*sinh_ny*cos_2xy)*f;
+ temp1 = sqrt(sumr*sumr+sumi*sumi);
+ if(fabs((temp1-temp)/temp1)<1.E-16) {
+ break;
+ }
+ temp = temp1;
+ }
+
+ if(n==2000.) {
+ fprintf(stderr, "iteration exceeds %lg\n",n);
+ }
+
+ sumr*=2./PI;
+ sumi*=2./PI;
+
+ if(x!=0.) {
+ f = 1./2./PI/x;
+ } else {
+ f = 0.;
+ }
+ value.r = gem_erf(x) + (f*(1.-cos_2xy) + sumr)*exp(-x2);
+ value.i = (f*sin_2xy+sumi)*exp(-x2);
+ return value;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Utilzed the series approximation of erf(z=x+iy) */
+/* Relative error=|err(z)|/|erf(z)|<EPS */
+/* Handbook of Mathematical functions, Abramowitz, p 299 */
+/* comega(z=x+iy)=cexp(z^2)*cerfc(z) */
+/*---------------------------------------------------------------------------*/
+static gem_complex gem_comega(gem_complex z)
+{
+ gem_complex value;
+ double x,y;
+ double sumr,sumi,n,n2,f,temp,temp1;
+ double x2, y2,cos_2xy,sin_2xy,cosh_2xy,sinh_2xy,cosh_ny,sinh_ny,exp_y2;
+
+ x = z.r;
+ y = z.i;
+ x2 = x*x;
+ y2 = y*y;
+ sumr = 0.;
+ sumi = 0.;
+ cos_2xy = cos(2.*x*y);
+ sin_2xy = sin(2.*x*y);
+ cosh_2xy = cosh(2.*x*y);
+ sinh_2xy = sinh(2.*x*y);
+ exp_y2 = exp(-y2);
+
+ for(n=1.0, temp=0.; n<=2000.; n+=1.0){
+ n2 = n*n;
+ cosh_ny = cosh(n*y);
+ sinh_ny = sinh(n*y);
+ f = exp(-n2/4.)/(n2+4.*x2);
+ /* if(f<1.E-200) break; */
+ sumr += (2.*x - 2.*x*cosh_ny*cos_2xy + n*sinh_ny*sin_2xy)*f;
+ sumi += (2.*x*cosh_ny*sin_2xy + n*sinh_ny*cos_2xy)*f;
+ temp1 = sqrt(sumr*sumr+sumi*sumi);
+ if(fabs((temp1-temp)/temp1)<1.E-16) {
+ break;
+ }
+ temp=temp1;
+ }
+ if(n==2000.) {
+ fprintf(stderr, "iteration exceeds %lg\n",n);
+ }
+ sumr *= 2./PI;
+ sumi *= 2./PI;
+
+ if(x!=0.) {
+ f = 1./2./PI/x;
+ } else {
+ f = 0.;
+ }
+ value.r = gem_omega(x)-(f*(1.-cos_2xy)+sumr);
+ value.i = -(f*sin_2xy+sumi);
+ value = gem_cxmul(value,gem_cmplx(exp_y2*cos_2xy,exp_y2*sin_2xy));
+ return (value);
+}
+
+/* W(x,z) exp(-x^2)*omega(x+z) */
+static gem_complex gem_cW(double x, gem_complex z){ return(gem_cxrmul(gem_comega(gem_cxradd(z,x)),exp(-x*x))); }
+
+/* ------------ end of [cr]error.c ------------ */
+
+/*_ REVERSIBLE GEMINATE RECOMBINATION
+ *
+ * Here are the functions for reversible geminate recombination. */
+
+/* Changes the unit from square cm per s to square Ångström per ps,
+ * since Omers code uses the latter units while g_mds outputs the former.
+ * g_hbond expects a diffusion coefficent given in square cm per s. */
+static double sqcm_per_s_to_sqA_per_ps (real D) {
+ fprintf(stdout, "Diffusion coefficient is %f A^2/ps\n", D*1e4);
+ return (double)(D*1e4);
+}
+
+
+static double eq10v2(double theoryCt[], double time[], int manytimes,
+ double ka, double kd, t_gemParams *params)
+{
+ /* Finding the 3 roots */
+ int i;
+ double kD, D, r, a, b, c, tsqrt, sumimaginary;
+ gem_complex
+ alpha, beta, gamma,
+ c1, c2, c3, c4,
+ oma, omb, omc,
+ part1, part2, part3, part4;
+
+ kD = params->kD;
+ D = params->D;
+ r = params->sigma;
+ a = (1.0 + ka/kD) * sqrt(D)/r;
+ b = kd;
+ c = kd * sqrt(D)/r;
+
+ gem_solve(&alpha, &beta, &gamma, a, b, c);
+ /* Finding the 3 roots */
+
+ sumimaginary = 0;
+ part1 = gem_cxmul(alpha, gem_cxmul(gem_cxadd(beta, gamma), gem_cxsub(beta, gamma))); /* 1(2+3)(2-3) */
+ part2 = gem_cxmul(beta, gem_cxmul(gem_cxadd(gamma, alpha), gem_cxsub(gamma, alpha))); /* 2(3+1)(3-1) */
+ part3 = gem_cxmul(gamma, gem_cxmul(gem_cxadd(alpha, beta) , gem_cxsub(alpha, beta))); /* 3(1+2)(1-2) */
+ part4 = gem_cxmul(gem_cxsub(gamma, alpha), gem_cxmul(gem_cxsub(alpha, beta), gem_cxsub(beta, gamma))); /* (3-1)(1-2)(2-3) */
+
+#ifdef HAVE_OPENMP
+#pragma omp parallel for \
+ private(i, tsqrt, oma, omb, omc, c1, c2, c3, c4), \
+ reduction(+:sumimaginary), \
+ default(shared), \
+ schedule(guided)
+#endif
+ for (i=0; i<manytimes; i++){
+ tsqrt = sqrt(time[i]);
+ oma = gem_comega(gem_cxrmul(alpha, tsqrt));
+ c1 = gem_cxmul(oma, gem_cxdiv(part1, part4));
+ omb = gem_comega(gem_cxrmul(beta, tsqrt));
+ c2 = gem_cxmul(omb, gem_cxdiv(part2, part4));
+ omc = gem_comega(gem_cxrmul(gamma, tsqrt));
+ c3 = gem_cxmul(omc, gem_cxdiv(part3, part4));
+ c4.r = c1.r+c2.r+c3.r;
+ c4.i = c1.i+c2.i+c3.i;
+ theoryCt[i] = c4.r;
+ sumimaginary += c4.i * c4.i;
+ }
+
+ return sumimaginary;
+
+} /* eq10v2 */
+
+/* This returns the real-valued index(!) to an ACF, equidistant on a log scale. */
+static double getLogIndex(const int i, const t_gemParams *params)
+{
+ return (exp(((double)(i)) * params->logQuota) -1);
+}
+
+extern t_gemParams *init_gemParams(const double sigma, const double D,
+ const real *t, const int len, const int nFitPoints,
+ const real begFit, const real endFit,
+ const real ballistic, const int nBalExp, const bool bDt)
+{
+ double tDelta;
+ t_gemParams *p;
+
+ snew(p,1);
+
+ /* A few hardcoded things here. For now anyway. */
+/* p->ka_min = 0; */
+/* p->ka_max = 100; */
+/* p->dka = 10; */
+/* p->kd_min = 0; */
+/* p->kd_max = 2; */
+/* p->dkd = 0.2; */
+ p->ka = 0;
+ p->kd = 0;
+/* p->lsq = -1; */
+/* p->lifetime = 0; */
+ p->sigma = sigma*10; /* Omer uses Å, not nm */
+/* p->lsq_old = 99999; */
+ p->D = sqcm_per_s_to_sqA_per_ps(D);
+ p->kD = 4*acos(-1.0)*sigma*p->D;
+
+
+ /* Parameters used by calcsquare(). Better to calculate them
+ * here than in calcsquare every time it's called. */
+ p->len = len;
+/* p->logAfterTime = logAfterTime; */
+ tDelta = (t[len-1]-t[0]) / len;
+ if (tDelta <= 0) {
+ gmx_fatal(FARGS, "Time between frames is non-positive!");
+ } else {
+ p->tDelta = tDelta;
+ }
+
+ p->nExpFit = nBalExp;
+/* p->nLin = logAfterTime / tDelta; */
+ p->nFitPoints = nFitPoints;
+ p->begFit = begFit;
+ p->endFit = endFit;
+ p->logQuota = (double)(log(p->len))/(p->nFitPoints-1);
+/* if (p->nLin <= 0) { */
+/* fprintf(stderr, "Number of data points in the linear regime is non-positive!\n"); */
+/* sfree(p); */
+/* return NULL; */
+/* } */
+ /* We want the same number of data points in the log regime. Not crucial, but seems like a good idea. */
+ /* p->logDelta = log(((float)len)/p->nFitPoints) / p->nFitPoints;/\* log(((float)len)/p->nLin) / p->nLin; *\/ */
+/* p->logPF = p->nFitPoints*p->nFitPoints/(float)len; /\* p->nLin*p->nLin/(float)len; *\/ */
+ /* logPF and logDelta are stitched together with the macro GETLOGINDEX defined in geminate.h */
+
+/* p->logMult = pow((float)len, 1.0/nLin);/\* pow(t[len-1]-t[0], 1.0/p->nLin); *\/ */
+ p->ballistic = ballistic;
+ p->bDt;
+ return p;
+}
+
+/* There was a misunderstanding regarding the fitting. From our
+ * recent correspondence it appears that Omer's code require
+ * the ACF data on a log-scale and does not operate on the raw data.
+ * This needs to be redone in gemFunc_residual() as well as in the
+ * t_gemParams structure. */
+#ifdef HAVE_LIBGSL
+static double gemFunc_residual2(const gsl_vector *p, void *data)
+{
+ gemFitData *GD;
+ int i, iLog, nLin, nFitPoints, nData;
+ double r, residual2, *ctTheory, *y;
+
+ GD = (gemFitData *)data;
+ nLin = GD->params->nLin;
+ nFitPoints = GD->params->nFitPoints;
+ nData = GD->nData;
+ residual2 = 0;
+ ctTheory = GD->ctTheory;
+ y = GD->y;
+
+ /* Now, we'd save a lot of time by not calculating eq10v2 for all
+ * time points, but only those that we sample to calculate the mse.
+ */
+
+ eq10v2(GD->ctTheory, GD->doubleLogTime/* GD->time */, nFitPoints/* GD->nData */,
+ gsl_vector_get(p, 0), gsl_vector_get(p, 1),
+ GD->params);
+
+ /* Removing a bunch of points from the log-part. */
+#ifdef HAVE_OPENMP
+#pragma omp parallel for schedule(dynamic) \
+ firstprivate(nData, ctTheory, y, nFitPoints) \
+ private (i, iLog, r) \
+ reduction(+:residual2) \
+ default(shared)
+#endif
+ for(i=0; i<nFitPoints; i++)
+ {
+ iLog = GD->logtime[i];
+ r = log(ctTheory[i /* iLog */]);
+ residual2 += sqr(r-log(y[iLog]));
+ }
+ residual2 /= nFitPoints; /* Not really necessary for the fitting, but gives more meaning to the returned data. */
+ /* printf("ka=%3.5f\tkd=%3.5f\trmse=%3.5f\n", gsl_vector_get(p,0), gsl_vector_get(p,1), residual2); */
+ return residual2;
+
+/* for (i=0; i<nLin; i++) { */
+/* /\* Linear part ----------*\/ */
+/* r = ctTheory[i]; */
+/* residual2 += sqr(r-y[i]); */
+/* /\* Log part -------------*\/ */
+/* iLog = GETLOGINDEX(i, GD->params); */
+/* if (iLog >= nData) */
+/* gmx_fatal(FARGS, "log index out of bounds: %i", iLog); */
+/* r = ctTheory[iLog]; */
+/* residual2 += sqr(r-y[iLog]); */
+
+/* } */
+/* residual2 /= GD->n; */
+/* return residual2; */
+}
+#endif
+
+static real* d2r(const double *d, const int nn);
+
+extern real fitGemRecomb(double *ct, double *time, double **ctFit,
+ const int nData, t_gemParams *params)
+{
+
+ int nThreads, i, iter, status, maxiter;
+ real size, d2, tol, *dumpdata;
+ size_t p, n;
+ gemFitData *GD;
+ char *dumpstr, dumpname[128];
+
+ /* nmsimplex2 had convergence problems prior to gsl v1.14,
+ * but it's O(N) instead of O(N) operations, so let's use it if v >= 1.14 */
+#ifdef HAVE_LIBGSL
+ gsl_multimin_fminimizer *s;
+ gsl_vector *x,*dx; /* parameters and initial step size */
+ gsl_multimin_function fitFunc;
+#ifdef GSL_MAJOR_VERSION
+#ifdef GSL_MINOR_VERSION
+#if ((GSL_MAJOR_VERSION == 1 && GSL_MINOR_VERSION >= 14) || \
+ (GSL_MAJOR_VERSION > 1))
+ const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex2;
+#else
+ const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
+#endif /* #if ... */
+#endif /* GSL_MINOR_VERSION */
+#else
+ const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
+#endif /* GSL_MAJOR_VERSION */
+ fprintf(stdout, "Will fit ka and kd to the ACF according to the reversible geminate recombination model.\n");
+#else /* HAVE_LIBGSL */
+ fprintf(stderr, "Sorry, can't do reversible geminate recombination without gsl. "
+ "Recompile using --with-gsl.\n");
+ return -1;
+#endif /* HAVE_LIBGSL */
+
+#ifdef HAVE_LIBGSL
+#ifdef HAVE_OPENMP
+ nThreads = omp_get_num_procs();
+ omp_set_num_threads(nThreads);
+ fprintf(stdout, "We will be using %i threads.\n", nThreads);
+#endif
+
+ iter = 0;
+ status = 0;
+ maxiter = 100;
+ tol = 1e-10;
+
+ p = 2; /* Number of parameters to fit. ka and kd. */
+ n = params->nFitPoints; /* params->nLin*2 */; /* Number of points in the reduced dataset */
+
+ if (params->D <= 0)
+ {
+ fprintf(stderr, "Fitting of D is not implemented yet. It must be provided on the command line.\n");
+ return -1;
+ }
+
+/* if (nData<n) { */
+/* fprintf(stderr, "Reduced data set larger than the complete data set!\n"); */
+/* n=nData; */
+/* } */
+ snew(dumpdata, nData);
+ snew(GD,1);
+
+ GD->n = n;
+ GD->y = ct;
+ GD->ctTheory=NULL;
+ snew(GD->ctTheory, nData);
+ GD->LinLog=NULL;
+ snew(GD->LinLog, n);
+ GD->time = time;
+ GD->ka = 0;
+ GD->kd = 0;
+ GD->tDelta = time[1]-time[0];
+ GD->nData = nData;
+ GD->params = params;
+ snew(GD->logtime,params->nFitPoints);
+ snew(GD->doubleLogTime,params->nFitPoints);
+
+ for (i=0; i<params->nFitPoints; i++)
+ {
+ GD->doubleLogTime[i] = (double)(getLogIndex(i, params));
+ GD->logtime[i] = (int)(GD->doubleLogTime[i]);
+ GD->doubleLogTime[i]*=GD->tDelta;
+
+ if (GD->logtime[i] >= nData)
+ {
+ fprintf(stderr, "Ayay. It seems we're indexing out of bounds.\n");
+ params->nFitPoints = i;
+ }
+ }
+
+ fitFunc.f = &gemFunc_residual2;
+ fitFunc.n = 2;
+ fitFunc.params = (void*)GD;
+
+ x = gsl_vector_alloc (fitFunc.n);
+ dx = gsl_vector_alloc (fitFunc.n);
+ gsl_vector_set (x, 0, 25);
+ gsl_vector_set (x, 1, 0.5);
+ gsl_vector_set (dx, 0, 0.1);
+ gsl_vector_set (dx, 1, 0.01);
+
+
+ s = gsl_multimin_fminimizer_alloc (T, fitFunc.n);
+ gsl_multimin_fminimizer_set (s, &fitFunc, x, dx);
+ gsl_vector_free (x);
+ gsl_vector_free (dx);
+
+ do {
+ iter++;
+ status = gsl_multimin_fminimizer_iterate (s);
+
+ if (status != 0)
+ gmx_fatal(FARGS,"Something went wrong in the iteration in minimizer %s:\n \"%s\"\n",
+ gsl_multimin_fminimizer_name(s), gsl_strerror(status));
+
+ d2 = gsl_multimin_fminimizer_minimum(s);
+ size = gsl_multimin_fminimizer_size(s);
+ params->ka = gsl_vector_get (s->x, 0);
+ params->kd = gsl_vector_get (s->x, 1);
+
+ if (status)
+ {
+ fprintf(stderr, "%s\n", gsl_strerror(status));
+ break;
+ }
+
+ status = gsl_multimin_test_size(size,tol);
+
+ if (status == GSL_SUCCESS) {
+ fprintf(stdout, "Converged to minimum at\n");
+ }
+
+ printf ("iter %5d: ka = %2.5f kd = %2.5f f() = %7.3f size = %.3f chi2 = %2.5f\n",
+ iter,
+ params->ka,
+ params->kd,
+ s->fval, size, d2);
+
+ if (iter%10 == 1)
+ {
+ eq10v2(GD->ctTheory, time, nData, params->ka, params->kd, params);
+ sprintf(dumpname, "Iter_%i.xvg", iter);
+ for(i=0; i<GD->nData; i++)
+ dumpdata[i] = (real)(GD->ctTheory[i]);
+ dumpN(dumpdata, GD->nData, dumpname);
+ }
+ }
+ while ((status == GSL_CONTINUE) && (iter < maxiter));
+
+ /* /\* Calculate the theoretical ACF from the parameters one last time. *\/ */
+ eq10v2(GD->ctTheory, time, nData, params->ka, params->kd, params);
+ *ctFit = GD->ctTheory;
+
+ sfree(GD);
+ gsl_multimin_fminimizer_free (s);
+
+
+ return d2;
+
+#endif /* HAVE_LIBGSL */
+}
+
+#ifdef HAVE_LIBGSL
+static int balFunc_f(const gsl_vector *x, void *data, gsl_vector *f)
+{
+ /* C + sum{ A_i * exp(-B_i * t) }*/
+
+ balData *BD;
+ int n, i,j, nexp;
+ double *y, *A, *B, C, /* There are the parameters to be optimized. */
+ t, ct;
+
+ BD = (balData *)data;
+ n = BD->n;
+ nexp = BD->nexp;
+ y = BD->y,
+ snew(A, nexp);
+ snew(B, nexp);
+
+ for (i = 0; i<nexp; i++)
+ {
+ A[i] = gsl_vector_get(x, i*2);
+ B[i] = gsl_vector_get(x, i*2+1);
+ }
+ C = gsl_vector_get(x, nexp*2);
+
+ for (i=0; i<n; i++)
+ {
+ t = i*BD->tDelta;
+ ct = 0;
+ for (j=0; j<nexp; j++) {
+ ct += A[j] * exp(B[j] * t);
+ }
+ ct += C;
+ gsl_vector_set (f, i, ct - y[i]);
+ }
+ return GSL_SUCCESS;
+}
+
+/* The derivative stored in jacobian form (J)*/
+static int balFunc_df(const gsl_vector *params, void *data, gsl_matrix *J)
+{
+ balData *BD;
+ size_t n,i,j;
+ double *y, *A, *B, C, /* There are the parameters. */
+ t;
+ int nexp;
+
+ BD = (balData*)data;
+ n = BD->n;
+ y = BD->y;
+ nexp = BD->nexp;
+
+ snew(A, nexp);
+ snew(B, nexp);
+
+ for (i=0; i<nexp; i++)
+ {
+ A[i] = gsl_vector_get(params, i*2);
+ B[i] = gsl_vector_get(params, i*2+1);
+ }
+ C = gsl_vector_get(params, nexp*2);
+ for (i=0; i<n; i++)
+ {
+ t = i*BD->tDelta;
+ for (j=0; j<nexp; j++)
+ {
+ gsl_matrix_set (J, i, j*2, exp(B[j]*t)); /* df(t)/dA_j */
+ gsl_matrix_set (J, i, j*2+1, A[j]*t*exp(B[j]*t)); /* df(t)/dB_j */
+ }
+ gsl_matrix_set (J, i, nexp*2, 1); /* df(t)/dC */
+ }
+ return GSL_SUCCESS;
+}
+
+/* Calculation of the function and its derivative */
+static int balFunc_fdf(const gsl_vector *params, void *data,
+ gsl_vector *f, gsl_matrix *J)
+{
+ balFunc_f(params, data, f);
+ balFunc_df(params, data, J);
+ return GSL_SUCCESS;
+}
+#endif /* HAVE_LIBGSL */
+
+/* Removes the ballistic term from the beginning of the ACF,
+ * just like in Omer's paper.
+ */
+extern void takeAwayBallistic(double *ct, double *t, int len, real tMax, int nexp, bool bDerivative)
+{
+
+ /* Use nonlinear regression with GSL instead.
+ * Fit with 4 exponentials and one constant term,
+ * subtract the fatest exponential. */
+
+ int nData,i,status, iter;
+ balData *BD;
+ double *guess, /* Initial guess. */
+ *A, /* The fitted parameters. (A1, B1, A2, B2,... C) */
+ a[2],
+ ddt[2];
+ bool sorted;
+ size_t n;
+ size_t p;
+
+ nData = 0;
+ do {
+ nData++;
+ } while (t[nData]<tMax+t[0] && nData<len);
+
+ p = nexp*2+1; /* Number of parameters. */
+
+#ifdef HAVE_LIBGSL
+ const gsl_multifit_fdfsolver_type *T
+ = gsl_multifit_fdfsolver_lmsder;
+
+ gsl_multifit_fdfsolver *s; /* The solver itself. */
+ gsl_multifit_function_fdf fitFunction; /* The function to be fitted. */
+ gsl_matrix *covar; /* Covariance matrix for the parameters.
+ * We'll not use the result, though. */
+ gsl_vector_view theParams;
+
+ nData = 0;
+ do {
+ nData++;
+ } while (t[nData]<tMax+t[0] && nData<len);
+
+ guess = NULL;
+ n = nData;
+
+ snew(guess, p);
+ snew(A, p);
+ covar = gsl_matrix_alloc (p, p);
+
+ /* Set up an initial gess for the parameters.
+ * The solver is somewhat sensitive to the initial guess,
+ * but this worked fine for a TIP3P box with -geminate dd
+ * EDIT: In fact, this seems like a good starting pont for other watermodels too. */
+ for (i=0; i<nexp; i++)
+ {
+ guess[i*2] = 0.1;
+ guess[i*2+1] = -0.5 + (((double)i)/nexp - 0.5)*0.3;
+ }
+ guess[nexp * 2] = 0.01;
+
+ theParams = gsl_vector_view_array(guess, p);
+
+ snew(BD,1);
+ BD->n = n;
+ BD->y = ct;
+ BD->tDelta = t[1]-t[0];
+ BD->nexp = nexp;
+
+ fitFunction.f = &balFunc_f;
+ fitFunction.df = &balFunc_df;
+ fitFunction.fdf = &balFunc_fdf;
+ fitFunction.n = nData;
+ fitFunction.p = p;
+ fitFunction.params = BD;
+
+ s = gsl_multifit_fdfsolver_alloc (T, nData, p);
+ if (s==NULL)
+ gmx_fatal(FARGS, "Could not set up the nonlinear solver.");
+
+ gsl_multifit_fdfsolver_set(s, &fitFunction, &theParams.vector);
+
+ /* \=============================================/ */
+
+ iter = 0;
+ do
+ {
+ iter++;
+ status = gsl_multifit_fdfsolver_iterate (s);
+
+ if (status)
+ break;
+ status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4);
+ }
+ while (iter < 5000 && status == GSL_CONTINUE);
+
+ if (iter == 5000)
+ {
+ fprintf(stderr, "The non-linear fitting did not converge in 5000 steps.\n"
+ "Check the quality of the fit!\n");
+ }
+ else
+ {
+ fprintf(stderr, "Non-linear fitting of ballistic term converged in %d steps.\n\n", (int)iter);
+ }
+ for (i=0; i<nexp; i++) {
+ fprintf(stdout, "%c * exp(%c * t) + ", 'A'+(char)i*2, 'B'+(char)i*2);
+ }
+
+ fprintf(stdout, "%c\n", 'A'+(char)nexp*2);
+ fprintf(stdout, "Here are the actual numbers for A-%c:\n", 'A'+nexp*2);
+
+ for (i=0; i<nexp; i++)
+ {
+ A[i*2] = gsl_vector_get(s->x, i*2);
+ A[i*2+1] = gsl_vector_get(s->x, i*2+1);
+ fprintf(stdout, " %g*exp(%g * x) +", A[i*2], A[i*2+1]);
+ }
+ A[i*2] = gsl_vector_get(s->x, i*2); /* The last and constant term */
+ fprintf(stdout, " %g\n", A[i*2]);
+
+ fflush(stdout);
+
+ /* Implement some check for parameter quality */
+ for (i=0; i<nexp; i++)
+ {
+ if (A[i*2]<0 || A[i*2]>1) {
+ fprintf(stderr, "WARNING: ----------------------------------\n"
+ " | A coefficient does not lie within [0,1].\n"
+ " | This may or may not be a problem.\n"
+ " | Double check the quality of the fit!\n");
+ }
+ if (A[i*2+1]>0) {
+ fprintf(stderr, "WARNING: ----------------------------------\n"
+ " | One factor in the exponent is positive.\n"
+ " | This could be a problem if the coefficient\n"
+ " | is large. Double check the quality of the fit!\n");
+ }
+ }
+ if (A[i*2]<0 || A[i*2]>1) {
+ fprintf(stderr, "WARNING: ----------------------------------\n"
+ " | The constant term does not lie within [0,1].\n"
+ " | This may or may not be a problem.\n"
+ " | Double check the quality of the fit!\n");
+ }
+
+ /* Sort the terms */
+ sorted = (nexp > 1) ? FALSE : TRUE;
+ while (!sorted)
+ {
+ sorted = TRUE;
+ for (i=0;i<nexp-1;i++)
+ {
+ ddt[0] = A[i*2] * A[i*2+1];
+ ddt[1] =A[i*2+2] * A[i*2+3];
+
+ if ((bDerivative && (ddt[0]<0 && ddt[1]<0 && ddt[0]>ddt[1])) || /* Compare derivative at t=0... */
+ (!bDerivative && (A[i*2+1] > A[i*2+3]))) /* Or just the coefficient in the exponent */
+ {
+ sorted = FALSE;
+ a[0] = A[i*2]; /* coefficient */
+ a[1] = A[i*2+1]; /* parameter in the exponent */
+
+ A[i*2] = A[i*2+2];
+ A[i*2+1] = A[i*2+3];
+
+ A[i*2+2] = a[0];
+ A[i*2+3] = a[1];
+ }
+ }
+ }
+
+ /* Subtract the fastest component */
+ fprintf(stdout, "Fastest component is %g * exp(%g * t)\n"
+ "Subtracting fastest component from ACF.\n", A[0], A[1]);
+
+ for (i=0; i<len; i++) {
+ ct[i] = (ct[i] - A[0] * exp(A[1] * i*BD->tDelta)) / (1-A[0]);
+ }
+
+ sfree(guess);
+ sfree(A);
+
+ gsl_multifit_fdfsolver_free(s);
+ gsl_matrix_free(covar);
+ fflush(stdout);
+
+#else
+ /* We have no gsl. */
+ fprintf(stderr, "Sorry, can't take away ballistic component without gsl. "
+ "Recompile using --with-gsl.\n");
+ return;
+#endif /* HAVE_LIBGSL */
+
+}
+
+extern void dumpN(const real *e, const int nn, char *fn)
+{
+ /* For debugging only */
+ int i;
+ FILE *f;
+ char standardName[] = "Nt.xvg";
+ if (fn == NULL) {
+ fn = standardName;
+ }
+
+ f = fopen(fn, "w");
+ fprintf(f,
+ "@ type XY\n"
+ "@ xaxis label \"Frame\"\n"
+ "@ yaxis label \"N\"\n"
+ "@ s0 line type 3\n");
+
+ for (i=0; i<nn; i++) {
+ fprintf(f, "%-10i %-g\n", i, e[i]);
+ }
+
+ fclose(f);
+}
+
+static real* d2r(const double *d, const int nn)
+{
+ real *r;
+ int i;
+
+ snew(r, nn);
+ for (i=0; i<nn; i++)
+ r[i] = (real)d[i];
+
+ return r;
+}
--- /dev/null
+#ifndef _GEMINATE_H
+#define _GEMINATE_H
+
+enum { gemNULL, gemNONE, gemDD, gemAD, gemAA, gemA4, gemNR};
+static const char *gemType[] = {NULL, "none", "dd", "ad", "aa", "a4", NULL};
+
+/* The first few sections of this file contain functions that were adopted,
+ * and to some extent modified, by Erik Marklund (erikm[aT]xray.bmc.uu.se,
+ * http://folding.bmc.uu.se) from code written by Omer Markovitch (email, url).
+ * This is also the case with the function eq10v2() in geminate.c.
+ *
+ * The parts menetioned in the previous paragraph were contributed under a BSD license.
+ */
+
+/* This first part is derived from complex.c which I recieved from Omer Markowitch.
+ * - Erik Marklund
+ *
+ * ------------- from complex.c ------------- */
+
+#include <math.h>
+/* definition of PI */
+#ifndef PI
+#define PI (acos(-1.0))
+#endif
+
+/* definition of the type complex */
+typedef struct
+{
+ double r,i;
+} gem_complex;
+
+
+/* ------------ end of complex.c ------------ */
+
+/* This next part was derived from cerror.c and rerror.c,
+ * also received from Omer Markovitch.
+ * ------------- from [cr]error.c ------------- */
+
+#ifndef sPI
+#define sPI (sqrt(PI))
+#endif
+
+/* ------------ end of [cr]error.c ------------ */
+
+/* ///////////////// REVERSIBLE GEMINATE RECOMBINATION ///////////////////
+ * Here follow routines and structs for reversible geminate recombination.
+ */
+
+typedef struct{
+ size_t n;
+ double *y;
+ double tDelta;
+ int nexp;
+} balData;
+
+
+typedef struct {
+ /* Used in the rewritten version of Omer's gem. recomb. analysis */
+ double ka, kd; /* -- || -- results[] */
+ double sigma; /* -- || -- sigma */
+ double D; /* The diffusion coefficient */
+ double kD; /* Replaces kD in analyse_corr_gem3d() */
+
+ /* The following members are for calcsquare() and takeAwayBallistic() */
+ double tDelta; /* Time between frames */
+ /* double logAfterTime; /\* Time after which we do the lsq calculations on a logarithmic timescale. *\/ */
+ int nFitPoints; /* Number of points to take from the ACF for fitting */
+ double begFit; /* Fit from this time (ps) */
+ double endFit; /* Fit up to this time (ps) */
+/* double logDelta; */
+/* double logPF; */
+ /* To get an equal number of points in the lin and log regime,
+ * we'll use logDelta to calculate where to sample the ACF.
+ * if i and j are indices in the linear and log regime, then:
+ * j = Cexp(A(i+nLin)),
+ * where C = (nLin**2 / len) and A = log(len/nLin) / nLin.
+ * This expands to j = (nLin**2 / len) * exp((i+nLin) * log(len/nLin) / nLin).
+ * We'll save part of our brains and some computing time if we pre-calculate
+ * 1) logDelta = log(len/nLin) / nLin
+ * 2) logPF = nLin**2 / len
+ * and get j = logPF * exp((i+nLin) * logDelta). */
+
+ /* I will redo this for a fit done entirely in log-log.
+ * j' = j+1
+ * nFitPoints' = nFitPoints-1
+ *
+ * j' = Cexp(Ai)
+ * (j'= 1 <=> i=0)
+ * => C=1
+ * (j'=len <=> i=nFitPoints')
+ * => A=log(len)/nFitPoints'
+ * => j = exp(i*log(len)/(nFitPoints-1)) -1
+ **/
+/* #define GETLOGINDEX(i,params) (params)->logPF * exp(((i)+(params)->nLin) * (params)->logDelta)
+ */
+ double logQuota;
+ int nLin; /* Number of timepoints in the linear regime */
+ int len; /* Length of time and ct arrays */
+ int nExpFit; /* Number of exponentials to fit */
+ real ballistic; /* Time before which the ballistic term should be fitted */
+ bool bDt; /* TRUE => use time derivative at time 0
+ * to find fastest component.
+ * FALSE => use coefficient in exponenetial
+ * to find fastest component. */
+} t_gemParams;
+
+
+typedef struct{
+ size_t n; /* Number of data points (lin-log) */
+ double *y; /* The datapoints */
+ double *ctTheory; /* The theoretical ct which will be built by gemFunc_f. */
+ double *LinLog;
+ double *time;
+ double ka;
+ double kd;
+ double tDelta; /* time difference between subsequent datapoints */
+ size_t nData; /* real size of the data */
+ int *logtime;
+ double *doubleLogTime;
+ t_gemParams *params;
+} gemFitData;
+
+extern void takeAwayBallistic(double *ct, double *t,
+ int len, real tMax,
+ int nexp, bool bDerivative);
+
+
+extern t_gemParams *init_gemParams(const double sigma, const double D,
+ const real *t, const int len, const int nFitPoints,
+ const real begFit, const real endFit,
+ const real ballistic, const int nBalExp, const bool bDt);
+
+/* Fit to geminate recombination model.
+ Returns root mean square error of fit. */
+extern real fitGemRecomb(double *ct, double *time, double **ctFit,
+ const int nData, t_gemParams *params);
+
+extern void dumpN(const real *e, const int nn, char *fn);
+
+#endif
hbar = PLANCK1/(2*M_PI);
kt = BOLTZMANN*temp;
- kteh = kt*exp(2.0)/(hbar*hbar)*AMU*sqr(NANO);
+ kteh = kt*exp(2.0)/(hbar*hbar)*AMU*(NANO*NANO);
if (debug)
fprintf(debug,"n = %d, nskip = %d kteh = %g\n",n,nskip,kteh);
const output_env_t oenv)
{
FILE *xvgrout=NULL;
- int status,out=0,nat,i,j,d,v,vec,nfr,nframes=0,snew_size,frame;
+ int nat,i,j,d,v,vec,nfr,nframes=0,snew_size,frame;
+ t_trxstatus *out=NULL;
+ t_trxstatus *status;
int noutvec_extr,*imin,*imax;
atom_id *all_at;
matrix box;
real t,inp,**inprod=NULL,min=0,max=0;
char str[STRLEN],str2[STRLEN],**ylabel,*c;
real fact;
+ gmx_rmpbc_t gpbc=NULL;
snew(x,natoms);
if (nat>atoms->nr)
gmx_fatal(FARGS,"the number of atoms in your trajectory (%d) is larger than the number of atoms in your structure file (%d)",nat,atoms->nr);
snew(all_at,nat);
+
+ if (top)
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,nat,box);
+ if (top)
+ gmx_rmpbc_done(gpbc);
+
for(i=0; i<nat; i++)
all_at[i]=i;
do {
if (nfr % skip == 0) {
if (top)
- rm_pbc(&(top->idef),ePBC,nat,box,xread,xread);
+ gmx_rmpbc(gpbc,box,xread,xread);
if (nframes>=snew_size) {
snew_size+=100;
for(i=0; i<noutvec+1; i++)
}
nfr++;
} while (read_next_x(oenv,status,&t,nat,xread,box));
- close_trj(status);
+ close_trj(out);
sfree(x);
if (filterfile)
close_trx(out);
else
snew(xread,atoms->nr);
+ if (top)
+ gmx_rmpbc_done(gpbc);
+
if (projfile) {
snew(ylabel,noutvec);
{
static const char *desc[] = {
"[TT]g_anaeig[tt] analyzes eigenvectors. The eigenvectors can be of a",
- "covariance matrix ([TT]g_covar[tt]) or of a Normal Modes anaysis",
+ "covariance matrix ([TT]g_covar[tt]) or of a Normal Modes analysis",
"([TT]g_nmeig[tt]).[PAR]",
"When a trajectory is projected on eigenvectors, all structures are",
"[TT]-first[tt] to [TT]-last[tt].",
"The projections of a trajectory on the eigenvectors of its",
"covariance matrix are called principal components (pc's).",
- "It is often useful to check the cosine content the pc's,",
+ "It is often useful to check the cosine content of the pc's,",
"since the pc's of random diffusion are cosines with the number",
"of periods equal to half the pc index.",
"The cosine content of the pc's can be calculated with the program",
int neig1,neig2;
double **xvgdata;
output_env_t oenv;
-
+ gmx_rmpbc_t gpbc=NULL;
+
t_filenm fnm[] = {
{ efTRN, "-v", "eigenvec", ffREAD },
{ efTRN, "-v2", "eigenvec2", ffOPTRD },
nfit=0;
ifit=NULL;
w_rls=NULL;
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,atoms->nr,topbox);
+
if (!bTPS)
bTop=FALSE;
else {
bTop=read_tps_conf(ftp2fn(efTPS,NFILE,fnm),
title,&top,&ePBC,&xtop,NULL,topbox,bM);
atoms=&top.atoms;
- rm_pbc(&(top.idef),ePBC,atoms->nr,topbox,xtop,xtop);
+ gmx_rmpbc(gpbc,topbox,xtop,xtop);
/* Fitting is only required for the projection */
if (bProj && bFit1) {
if (xref1 == NULL) {
}
}
}
-
+ gmx_rmpbc_done(gpbc);
+
if (bIndex) {
printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n",natoms);
get_index(atoms,indexfile,1,&i,&index,&grpname);
#include "statutil.h"
#include "txtdump.h"
#include "gstat.h"
+#include "gmx_matrix.h"
#include "gmx_statistics.h"
#include "xvgr.h"
#include "gmx_ana.h"
+#include "geminate.h"
/* must correspond to char *avbar_opt[] declared in main() */
enum { avbarSEL, avbarNONE, avbarSTDDEV, avbarERROR, avbar90, avbarNR };
ffclose(fp);
}
-static void regression_analysis(int n,bool bXYdy,real *x,real **val)
+static void regression_analysis(int n,bool bXYdy,
+ real *x,int nset,real **val)
{
real S,chi2,a,b,da,db,r=0;
- printf("Fitting data to a function f(x) = ax + b\n");
- printf("Minimizing residual chi2 = Sum_i w_i [f(x_i) - y_i]2\n");
- printf("Error estimates will be given if w_i (sigma) values are given\n");
- printf("(use option -xydy).\n\n");
- if (bXYdy)
- lsq_y_ax_b_error(n,x,val[0],val[1],&a,&b,&da,&db,&r,&S);
- else
- lsq_y_ax_b(n,x,val[0],&a,&b,&r,&S);
- chi2 = sqr((n-2)*S);
- printf("Chi2 = %g\n",chi2);
- printf("S (Sqrt(Chi2/(n-2)) = %g\n",S);
- printf("Correlation coefficient = %.1f%%\n",100*r);
- printf("\n");
- if (bXYdy) {
- printf("a = %g +/- %g\n",a,da);
- printf("b = %g +/- %g\n",b,db);
+ if (bXYdy || (nset == 1))
+ {
+ printf("Fitting data to a function f(x) = ax + b\n");
+ printf("Minimizing residual chi2 = Sum_i w_i [f(x_i) - y_i]2\n");
+ printf("Error estimates will be given if w_i (sigma) values are given\n");
+ printf("(use option -xydy).\n\n");
+ if (bXYdy)
+ lsq_y_ax_b_error(n,x,val[0],val[1],&a,&b,&da,&db,&r,&S);
+ else
+ lsq_y_ax_b(n,x,val[0],&a,&b,&r,&S);
+ chi2 = sqr((n-2)*S);
+ printf("Chi2 = %g\n",chi2);
+ printf("S (Sqrt(Chi2/(n-2)) = %g\n",S);
+ printf("Correlation coefficient = %.1f%%\n",100*r);
+ printf("\n");
+ if (bXYdy) {
+ printf("a = %g +/- %g\n",a,da);
+ printf("b = %g +/- %g\n",b,db);
+ }
+ else {
+ printf("a = %g\n",a);
+ printf("b = %g\n",b);
+ }
}
- else {
- printf("a = %g\n",a);
- printf("b = %g\n",b);
+ else
+ {
+ double chi2,*a,**xx,*y;
+ int i,j;
+
+ snew(y,n);
+ snew(xx,nset-1);
+ for(j=0; (j<nset-1); j++)
+ snew(xx[j],n);
+ for(i=0; (i<n); i++)
+ {
+ y[i] = val[0][i];
+ for(j=1; (j<nset); j++)
+ xx[j-1][i] = val[j][i];
+ }
+ snew(a,nset-1);
+ chi2 = multi_regression(NULL,n,y,nset-1,xx,a);
+ printf("Fitting %d data points in %d sets\n",n,nset-1);
+ printf("chi2 = %g\n",chi2);
+ printf("A =");
+ for(i=0; (i<nset-1); i++)
+ {
+ printf(" %g",a[i]);
+ sfree(xx[i]);
+ }
+ printf("\n");
+ sfree(xx);
+ sfree(y);
+ sfree(a);
}
}
}
}
+static void do_ballistic(const char *balFile, int nData,
+ real *t, real **val, int nSet,
+ real balTime, int nBalExp,
+ bool bDerivative,
+ const output_env_t oenv)
+{
+ double **ctd=NULL, *td=NULL;
+ t_gemParams *GP = init_gemParams(0, 0, t, nData, 0, 0, 0, balTime, nBalExp, bDerivative);
+ static char *leg[] = {"Ac'(t)"};
+ FILE *fp;
+ int i, set;
+
+ if (GP->ballistic/GP->tDelta >= GP->nExpFit*2+1)
+ {
+ snew(ctd, nSet);
+ snew(td, nData);
+
+ fp = xvgropen(balFile, "Hydrogen Bond Autocorrelation","Time (ps)","C'(t)", oenv);
+ xvgr_legend(fp,asize(leg),leg,oenv);
+
+ for (set=0; set<nSet; set++)
+ {
+ snew(ctd[set], nData);
+ for (i=0; i<nData; i++) {
+ ctd[set][i] = (double)val[set][i];
+ if (set==0)
+ td[i] = (double)t[i];
+ }
+
+ takeAwayBallistic(ctd[set], td, nData, GP->ballistic, GP->nExpFit, GP->bDt);
+ }
+
+ for (i=0; i<nData; i++)
+ {
+ fprintf(fp, " %g",t[i]);
+ for (set=0; set<nSet; set++)
+ {
+ fprintf(fp, " %g", ctd[set][i]);
+ }
+ fprintf(fp, "\n");
+ }
+
+
+ for (set=0; set<nSet; set++)
+ sfree(ctd[set]);
+ sfree(ctd);
+ sfree(td);
+ }
+ else
+ printf("Number of data points is less than the number of parameters to fit\n."
+ "The system is underdetermined, hence no ballistic term can be found.\n\n");
+}
+
+static void do_geminate(const char *gemFile, int nData,
+ real *t, real **val, int nSet,
+ const real D, const real rcut, const real balTime,
+ const int nFitPoints, const real begFit, const real endFit,
+ const output_env_t oenv)
+{
+ double **ctd=NULL, **ctdGem=NULL, *td=NULL;
+ t_gemParams *GP = init_gemParams(rcut, D, t, nData, nFitPoints,
+ begFit, endFit, balTime, 1, FALSE);
+ static char *leg[] = {"Ac\\sgem\\N(t)"};
+ FILE *fp;
+ int i, set;
+
+ snew(ctd, nSet);
+ snew(ctdGem, nSet);
+ snew(td, nData);
+
+ fp = xvgropen(gemFile, "Hydrogen Bond Autocorrelation","Time (ps)","C'(t)", oenv);
+ xvgr_legend(fp,asize(leg),leg,oenv);
+
+ for (set=0; set<nSet; set++)
+ {
+ snew(ctd[set], nData);
+ snew(ctdGem[set], nData);
+ for (i=0; i<nData; i++) {
+ ctd[set][i] = (double)val[set][i];
+ if (set==0)
+ td[i] = (double)t[i];
+ }
+ fitGemRecomb(ctd[set], td, &(ctd[set]), nData, GP);
+ }
+
+ for (i=0; i<nData; i++)
+ {
+ fprintf(fp, " %g",t[i]);
+ for (set=0; set<nSet; set++)
+ {
+ fprintf(fp, " %g", ctdGem[set][i]);
+ }
+ fprintf(fp, "\n");
+ }
+
+ for (set=0; set<nSet; set++)
+ {
+ sfree(ctd[set]);
+ sfree(ctdGem[set]);
+ }
+ sfree(ctd);
+ sfree(ctdGem);
+ sfree(td);
+}
+
int gmx_analyze(int argc,char *argv[])
{
static const char *desc[] = {
"A line in the input file may start with a time",
"(see option [TT]-time[tt]) and any number of y values may follow.",
"Multiple sets can also be",
- "read when they are seperated by & (option [TT]-n[tt]),",
+ "read when they are separated by & (option [TT]-n[tt]),",
"in this case only one y value is read from each line.",
"All lines starting with # and @ are skipped.",
"All analyses can also be done for the derivative of a set",
"g_analyze always shows the average and standard deviation of each",
"set. For each set it also shows the relative deviation of the third",
- "and forth cumulant from those of a Gaussian distribution with the same",
+ "and fourth cumulant from those of a Gaussian distribution with the same",
"standard deviation.[PAR]",
"Option [TT]-ac[tt] produces the autocorrelation function(s).[PAR]",
"The complete derivation is given in",
"B. Hess, J. Chem. Phys. 116:209-217, 2002.[PAR]",
+ "Option [TT]-bal[TT] finds and subtracts the ultrafast \"ballistic\"",
+ "component from a hydrogen bond autocorrelation function by the fitting",
+ "of a sum of exponentials, as described in e.g.",
+ "O. Markovitch, J. Chem. Phys. 129:084505, 2008. The fastest term",
+ "is the one with the most negative coefficient in the exponential,",
+ "or with [TT]-d[TT], the one with most negative time derivative at time 0.",
+ "[]TT-nbalexp[TT] sets the number of exponentials to fit.[PAR]",
+
+ "Option [TT]-gem[TT] fits bimolecular rate constants ka and kb",
+ "(and optionally kD) to the hydrogen bond autocorrelation function",
+ "according to the reversible geminate recombination model. Removal of",
+ "the ballistic component first is strongly adviced. The model is presented in",
+ "O. Markovitch, J. Chem. Phys. 129:084505, 2008.[PAR]",
+
"Option [TT]-filter[tt] prints the RMS high-frequency fluctuation",
"of each set and over all sets with respect to a filtered average.",
"The filter is proportional to cos(pi t/len) where t goes from -len/2",
static bool bHaveT=TRUE,bDer=FALSE,bSubAv=TRUE,bAverCorr=FALSE,bXYdy=FALSE;
static bool bEESEF=FALSE,bEENLC=FALSE,bEeFitAc=FALSE,bPower=FALSE;
static bool bIntegrate=FALSE,bRegression=FALSE,bLuzar=FALSE,bLuzarError=FALSE;
- static int nsets_in=1,d=1,nb_min=4,resol=10;
- static real temp=298.15,fit_start=1,smooth_tail_start=-1;
+ static int nsets_in=1,d=1,nb_min=4,resol=10, nBalExp=4, nFitPoints=100;
+ static real temp=298.15,fit_start=1, fit_end=60, smooth_tail_start=-1, balTime=0.2, diffusion=5e-5,rcut=0.35;
/* must correspond to enum avbar* declared at beginning of file */
static const char *avbar_opt[avbarNR+1] = {
{ "-e", FALSE, etREAL, {&te},
"Last time to read from set" },
{ "-n", FALSE, etINT, {&nsets_in},
- "Read # sets seperated by &" },
+ "Read # sets separated by &" },
{ "-d", FALSE, etBOOL, {&bDer},
"Use the derivative" },
{ "-dp", FALSE, etINT, {&d},
{ "-xydy", FALSE, etBOOL, {&bXYdy},
"Interpret second data set as error in the y values for integrating" },
{ "-regression",FALSE,etBOOL,{&bRegression},
- "Perform a linear regression analysis on the data" },
+ "Perform a linear regression analysis on the data. If -xydy is set a second set will be interpreted as the error bar in the Y value. Otherwise, if multiple data sets are present a multilinear regression will be performed yielding the constant A that minimize chi^2 = (y - A0 x0 - A1 x1 - ... - AN xN)^2 where now Y is the first data set in the input file and xi the others. Do read the information at the option [TT]-time[tt]." },
{ "-luzar", FALSE, etBOOL, {&bLuzar},
"Do a Luzar and Chandler analysis on a correlation function and related as produced by g_hbond. When in addition the -xydy flag is given the second and fourth column will be interpreted as errors in c(t) and n(t)." },
{ "-temp", FALSE, etREAL, {&temp},
"Temperature for the Luzar hydrogen bonding kinetics analysis" },
{ "-fitstart", FALSE, etREAL, {&fit_start},
"Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" },
+ { "-fitend", FALSE, etREAL, {&fit_end},
+ "Time (ps) where to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. Only with -gem" },
{ "-smooth",FALSE, etREAL, {&smooth_tail_start},
"If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/tau)" },
{ "-nbmin", FALSE, etINT, {&nb_min},
{ "-subav", FALSE, etBOOL, {&bSubAv},
"Subtract the average before autocorrelating" },
{ "-oneacf", FALSE, etBOOL, {&bAverCorr},
- "Calculate one ACF over all sets" }
+ "Calculate one ACF over all sets" },
+ { "-nbalexp", FALSE, etINT, {&nBalExp},
+ "HIDDENNumber of exponentials to fit to the ultrafast component" },
+ { "-baltime", FALSE, etREAL, {&balTime},
+ "HIDDENTime up to which the ballistic component will be fitted" },
+/* { "-gemnp", FALSE, etINT, {&nFitPoints}, */
+/* "HIDDENNumber of data points taken from the ACF to use for fitting to rev. gem. recomb. model."}, */
+/* { "-rcut", FALSE, etREAL, {&rcut}, */
+/* "Cut-off for hydrogen bonds in geminate algorithms" }, */
+/* { "-gemtype", FALSE, etENUM, {gemType}, */
+/* "What type of gminate recombination to use"}, */
+/* { "-D", FALSE, etREAL, {&diffusion}, */
+/* "The self diffusion coefficient which is used for the reversible geminate recombination model."} */
};
#define NPA asize(pa)
int n,nlast,s,nset,i,j=0;
real **val,*t,dt,tot,error;
double *av,*sig,cum1,cum2,cum3,cum4,db;
- const char *acfile,*msdfile,*ccfile,*distfile,*avfile,*eefile,*fitfile;
+ const char *acfile,*msdfile,*ccfile,*distfile,*avfile,*eefile,*balfile,*gemfile,*fitfile;
output_env_t oenv;
t_filenm fnm[] = {
{ efXVG, "-dist", "distr", ffOPTWR },
{ efXVG, "-av", "average", ffOPTWR },
{ efXVG, "-ee", "errest", ffOPTWR },
+ { efXVG, "-bal", "ballisitc",ffOPTWR },
+/* { efXVG, "-gem", "geminate", ffOPTWR }, */
{ efLOG, "-g", "fitlog", ffOPTWR }
};
#define NFILE asize(fnm)
distfile = opt2fn_null("-dist",NFILE,fnm);
avfile = opt2fn_null("-av",NFILE,fnm);
eefile = opt2fn_null("-ee",NFILE,fnm);
+ balfile = opt2fn_null("-bal",NFILE,fnm);
+/* gemfile = opt2fn_null("-gem",NFILE,fnm); */
if (opt2parg_bSet("-fitfn",npargs,ppa))
fitfile = opt2fn("-g",NFILE,fnm);
else
if (eefile)
estimate_error(eefile,nb_min,resol,n,nset,av,sig,val,dt,
bEeFitAc,bEESEF,bEENLC,oenv);
+ if (balfile)
+ do_ballistic(balfile,n,t,val,nset,balTime,nBalExp,bDer,oenv);
+/* if (gemfile) */
+/* do_geminate(gemfile,n,t,val,nset,diffusion,rcut,balTime, */
+/* nFitPoints, fit_start, fit_end, oenv); */
if (bPower)
power_fit(n,nset,val,t);
if (acfile) {
eacNormal,bAverCorr);
}
if (bRegression)
- regression_analysis(n,bXYdy,t,val);
+ regression_analysis(n,bXYdy,t,nset,val);
if (bLuzar)
luzar_correl(n,t,nset,val,temp,bXYdy,fit_start,smooth_tail_start,oenv);
static void dump_dih_trn(int nframes,int nangles,real **dih,const char *fn,
real dt)
{
- int i,j,k,l,m,na,trn;
+ int i,j,k,l,m,na;
+ t_fileio *trn;
rvec *x;
matrix box = {{2,0,0},{0,2,0},{0,0,2}};
"It should be noted that the indexfile should contain",
"atom-triples for angles or atom-quadruplets for dihedrals.",
"If this is not the case, the program will crash.[PAR]",
- "With option [TT]-or[tt] a trajectory file is dumped containing cos and"
+ "With option [TT]-or[tt] a trajectory file is dumped containing cos and",
"sin of selected dihedral angles which subsequently can be used as",
"input for a PCA analysis using [TT]g_covar[tt]."
};
return lambda;
}
+static bool subtitle2lambda(const char *subtitle,double *lambda)
+{
+ bool bFound;
+ char *ptr;
+
+ bFound = FALSE;
+
+ /* plain text lambda string */
+ ptr = strstr(subtitle,"lambda");
+ if (ptr == NULL)
+ {
+ /* xmgrace formatted lambda string */
+ ptr = strstr(subtitle,"\\xl\\f{}");
+ }
+ if (ptr == NULL)
+ {
+ /* xmgr formatted lambda string */
+ ptr = strstr(subtitle,"\\8l\\4");
+ }
+ if (ptr != NULL)
+ {
+ ptr = strstr(ptr,"=");
+ }
+ if (ptr != NULL)
+ {
+ bFound = (sscanf(ptr+1,"%lf",lambda) == 1);
+ }
+
+ return bFound;
+}
+
static double filename2lambda(char *fn)
{
double lambda;
- char *ptr,*endptr;
-
+ char *ptr,*endptr,*digitptr;
+ int dirsep;
ptr = fn;
- while (ptr[0] != '\0' && !isdigit(ptr[0]))
+ /* go to the end of the path string and search backward to find the last
+ directory in the path which has to contain the value of lambda
+ */
+ while (ptr[1] != '\0')
{
ptr++;
}
- if (!isdigit(ptr[0]))
+ /* searching backward to find the second directory separator */
+ dirsep = 0;
+ digitptr = NULL;
+ while (ptr >= fn)
{
- gmx_fatal(FARGS,"While trying to read the lambda value from the filename: filename '%s' does not contain a number",fn);
+ if (ptr[0] != DIR_SEPARATOR && ptr[1] == DIR_SEPARATOR)
+ {
+ if (dirsep == 1) break;
+ dirsep++;
+ }
+ /* save the last position of a digit between the last two
+ separators = in the last dirname */
+ if (dirsep > 0 && isdigit(*ptr))
+ {
+ digitptr = ptr;
+ }
+ ptr--;
}
- if (ptr > fn && fn[ptr-fn-1] == '-')
+ if (!digitptr)
{
- ptr--;
+ gmx_fatal(FARGS,"While trying to read the lambda value from the file path:"
+ " last directory in the path '%s' does not contain a number",fn);
}
-
- lambda = strtod(ptr,&endptr);
- if (endptr == ptr)
+ if (digitptr[-1] == '-')
+ {
+ digitptr--;
+ }
+ lambda = strtod(digitptr,&endptr);
+ if (endptr == digitptr)
{
- gmx_fatal(FARGS,"Malformed number in filename '%s'",fn);
+ gmx_fatal(FARGS,"Malformed number in file path '%s'",fn);
}
return lambda;
/* Check if we have a single set, nset=2 means t and dH/dl */
if (ba->nset == 2)
{
- /* Deduce lambda from the file name */
- ba->lambda[0] = filename2lambda(fn);
+ /* Try to deduce lambda from the subtitle */
+ if (subtitle != NULL &&
+ !subtitle2lambda(subtitle,&ba->lambda[0]))
+ {
+ /* Deduce lambda from the file name */
+ ba->lambda[0] = filename2lambda(fn);
+ }
printf(" %g",ba->lambda[0]);
}
else
"* Files with only one y-value, for such files it is assumed ",
"that the y-value is dH/dlambda and that the Hamiltonian depends ",
"linearly on lambda. The lambda value of the simulation is inferred ",
- "from the legend if present, otherwise from a number in the file ",
- "name.",
+ "from the subtitle if present, otherwise from a number in the",
+ "subdirectory in the file name.",
"[BR]",
"* Files with more than one y-value. The files should have columns ",
"with dH/dlambda and Delta lambda. The lambda values are inferred ",
double *partsum;
double prec,dg_tot,dg,sig;
FILE *fpb,*fpi;
+ char lamformat[20];
char dgformat[20],xvg2format[STRLEN],xvg3format[STRLEN],buf[STRLEN];
char ktformat[STRLEN], sktformat[STRLEN];
char kteformat[STRLEN], skteformat[STRLEN];
gmx_fatal(FARGS,"Can not have negative number of digits");
}
prec = pow(10,-nd);
+ sprintf(lamformat,"%%6.3f");
sprintf( dgformat,"%%%d.%df",3+nd,nd);
/* the format strings of the results in kT */
sprintf( ktformat,"%%%d.%df",5+nd,nd);
printf("\nTemperature: %g K\n", ba[0].temp);
printf("\nDetailed results in kT (see help for explanation):\n\n");
- printf(skteformat, "lam_A ");
- printf(skteformat, "lam_B ");
+ printf("%6s ", " lam_A");
+ printf("%6s ", " lam_B");
printf(sktformat, "DG ");
printf(skteformat, "+/- ");
printf(sktformat, "s_A ");
printf("\n");
for(f=0; f<nfile-1; f++)
{
- printf(kteformat, results[f].lambda_a);
+ printf(lamformat, results[f].lambda_a);
printf(" ");
- printf(kteformat, results[f].lambda_b);
+ printf(lamformat, results[f].lambda_b);
printf(" ");
printf(ktformat, results[f].dg);
printf(" ");
/*printf("lambda %4.2f - %4.2f, DG ", results[f].lambda_a,
results[f].lambda_b);*/
printf("lambda ");
- printf(dgformat, results[f].lambda_a);
+ printf(lamformat, results[f].lambda_a);
printf(" - ");
- printf(dgformat, results[f].lambda_b);
+ printf(lamformat, results[f].lambda_b);
printf(", DG ");
printf(dgformat,results[f].dg*kT);
}
printf("\n");
printf("total ");
- printf(dgformat, ba[0].lambda[0]);
+ printf(lamformat, ba[0].lambda[0]);
printf(" - ");
- printf(dgformat, ba[nfile-1].lambda[0]);
+ printf(lamformat, ba[nfile-1].lambda[0]);
printf(", DG ");
printf(dgformat,dg_tot*kT);
int counter;*/
rvec *x;
rvec dx;
- int status,natoms;
+ t_trxstatus *status;
+ int natoms;
matrix box;
real t,fac;
int bind,i,nframes,i0,i1;
const char *desc[] = {
"g_bond makes a distribution of bond lengths. If all is well a",
"gaussian distribution should be made when using a harmonic potential.",
- "bonds are read from a single group in the index file in order i1-j1",
- "i2-j2 thru in-jn.[PAR]",
+ "Bonds are read from a single group in the index file in order i1-j1",
+ "i2-j2 through in-jn.[PAR]",
"[TT]-tol[tt] gives the half-width of the distribution as a fraction",
"of the bondlength ([TT]-blen[tt]). That means, for a bond of 0.2",
"a tol of 0.1 gives a distribution from 0.18 to 0.22.[PAR]",
}
}
-static void dump_axes(int fp,t_trxframe *fr,t_atoms *outat,t_bundle *bun)
+static void dump_axes(t_trxstatus *status,t_trxframe *fr,t_atoms *outat,
+ t_bundle *bun)
{
t_trxframe frout;
static rvec *xout=NULL;
frout.natoms = outat->nr;
frout.atoms = outat;
frout.x = xout;
- write_trxframe(fp,&frout,NULL);
+ write_trxframe(status,&frout,NULL);
}
int gmx_bundle(int argc,char *argv[])
};
FILE *out,*flen,*fdist,*fz,*ftilt,*ftiltr,*ftiltl;
FILE *fkink=NULL,*fkinkr=NULL,*fkinkl=NULL;
- int status,fpdb;
+ t_trxstatus *status;
+ t_trxstatus *fpdb;
t_topology top;
int ePBC;
rvec *xtop;
bool bKink;
rvec va,vb,vc,vr,vl;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
+
#define NLEG asize(leg)
t_filenm fnm[] = {
{ efTRX, "-f", NULL, ffREAD },
}
fpdb = open_trx(opt2fn("-oa",NFILE,fnm),"w");
} else
- fpdb = -1;
+ fpdb = NULL;
read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_NEED_X);
-
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box);
+
do {
- rm_pbc(&top.idef,ePBC,fr.natoms,fr.box,fr.x,fr.x);
+ gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
calc_axes(fr.x,top.atoms.atom,gnx,index,!bZ,&bun);
t = output_env_conv_time(oenv,fr.time);
fprintf(flen," %10g",t);
fprintf(fkinkr,"\n");
fprintf(fkinkl,"\n");
}
- if (fpdb >= 0)
+ if (fpdb )
dump_axes(fpdb,&fr,&outatoms,&bun);
} while(read_next_frame(oenv,status,&fr));
+ gmx_rmpbc_done(gpbc);
close_trx(status);
- if (fpdb >= 0)
+ if (fpdb )
close_trx(fpdb);
ffclose(flen);
ffclose(fdist);
{
FILE *fp;
int nh[edMax];
+ char buf[STRLEN];
int i,Dih,Xi;
real S2Max, S2Min;
char *leg[2+edMax];
- for(i=0;i<NLEG;i++)
- leg[i]=strdup(const_leg[i]);
+ for(i=0;i<NLEG;i++)
+ leg[i]=strdup(const_leg[i]);
/* Print order parameters */
fp=xvgropen(fn,"Dihedral Order Parameters","Residue","S2",oenv);
}
ffclose(fp);
- if (pdbfn) {
+ if (NULL != pdbfn) {
real x0,y0,z0;
-
+
+ if (NULL == atoms->pdbinfo)
+ snew(atoms->pdbinfo,atoms->nr);
for(i=0; (i<atoms->nr); i++)
atoms->pdbinfo[i].bfac=bfac_init;
x0*=10.0;/* nm -> angstrom */
y0*=10.0;/* nm -> angstrom */
z0*=10.0;/* nm -> angstrom */
- for (i=0; (i<10); i++)
- fprintf(fp,pdbformat,"ATOM ", atoms->nr+1+i, "CA", "LEG",' ',
- atoms->nres+1, x0, y0, z0+(1.2*i), 0.0, -0.1*i);
+ sprintf(buf,"%s%%6.f%%6.2f\n",pdbformat);
+ for (i=0; (i<10); i++) {
+ fprintf(fp,buf,"ATOM ", atoms->nr+1+i, "CA", "LEG",' ',
+ atoms->nres+1, ' ',x0, y0, z0+(1.2*i), 0.0, -0.1*i);
+ }
ffclose(fp);
}
fprintf(log,"%4d ",nh[NONCHI+Xi]);
fprintf(log,"\n");
- for(i=0;i<NLEG;i++)
- sfree(leg[i]);
+ for(i=0;i<NLEG;i++)
+ sfree(leg[i]);
}
matrix box;
real t;
int i,i0,j,max_nf;
- int status,natom;
+ int natom;
+ t_trxstatus *status;
+
max_nf = 0;
xx = NULL;
{
FILE *fp=NULL;
char buf[STRLEN],buf1[40],buf2[40],buf3[40],*trxsfn;
- int trxout=0,trxsout=0;
+ t_trxstatus *trxout=NULL;
+ t_trxstatus *trxsout=NULL;
int i,i1,cl,nstr,*structure,first=0,midstr;
bool *bWrite=NULL;
real r,clrmsd,midrmsd;
/* Prepare a reference structure for the orientation of the clusters */
if (bFit)
- reset_x(ifsize,fitidx,natom,NULL,xtps,mass);
+ reset_x(ifsize,fitidx,natom,NULL,xtps,mass);
trxout = open_trx(trxfn,"w");
/* Calculate the average structure in each cluster, *
* all structures are fitted to the first struture of the cluster */
"Monte Carlo: reorder the RMSD matrix using Monte Carlo.[PAR]",
- "diagonalization: diagonalize the RMSD matrix.[PAR]"
+ "diagonalization: diagonalize the RMSD matrix.[PAR]",
"gromos: use algorithm as described in Daura [IT]et al.[it]",
"([IT]Angew. Chem. Int. Ed.[it] [BB]1999[bb], [IT]38[it], pp 236-240).",
"the smallest average distance to the others or the average structure",
"or all structures for each cluster will be written to a trajectory",
"file. When writing all structures, separate numbered files are made",
- "for each cluster.[PAR]"
+ "for each cluster.[PAR]",
"Two output files are always written:[BR]",
"[TT]-o[tt] writes the RMSD values in the upper left half of the matrix",
t_topology top;
int ePBC;
t_atoms useatoms;
- t_matrix *readmat;
+ t_matrix *readmat=NULL;
real *tmp;
int isize=0,ifsize=0,iosize=0;
atom_id *index=NULL, *fitidx, *outidx;
char *grpname;
- real rmsd,**d1,**d2,*time,time_invfac,*mass=NULL;
+ real rmsd,**d1,**d2,*time=NULL,time_invfac,*mass=NULL;
char buf[STRLEN],buf1[80],title[STRLEN];
bool bAnalyze,bUseRmsdCut,bJP_RMSD=FALSE,bReadMat,bReadTraj;
{
FILE *fp,*gp,*hp,*tp;
atom_id *index=NULL;
- int nindex,natoms,status;
+ int nindex,natoms;
+ t_trxstatus *status;
rvec *x=NULL,*v=NULL,dx;
t_pbc pbc;
char *gname;
"When the [TT]-mol[tt] option is given clusters will be made out of",
"molecules rather than atoms, which allows clustering of large molecules.",
"In this case an index file would still contain atom numbers",
- "or your calculcation will die with a SEGV.[PAR]",
+ "or your calculation will die with a SEGV.[PAR]",
"When velocities are present in your trajectory, the temperature of",
"the largest cluster will be printed in a separate xvg file assuming",
"that the particles are free to move. If you are using constraints,",
{ "-nlevels", FALSE, etINT, {&nlevels},
"Number of levels of grey in xpm output" },
{ "-ndf", FALSE, etINT, {&ndf},
- "Number of degrees of freedom of the entire system for temperature calculation. If not set the number of atoms times three is used." },
+ "Number of degrees of freedom of the entire system for temperature calculation. If not set, the number of atoms times three is used." },
{ "-rgblo", FALSE, etRVEC, {rlo},
"RGB values for the color of the lowest occupied cluster size" },
{ "-rgbhi", FALSE, etRVEC, {rhi},
"only the two index groups used for the fit need to be identical.",
"With [TT]-name[tt] only matching atom names from the selected groups",
"will be used for the fit and RMSD calculation. This can be useful ",
- "when comparing mutants of a protein."
+ "when comparing mutants of a protein.",
"[PAR]",
"The superimposed structures are written to file. In a [TT].pdb[tt] file",
"the two structures will be written as separate models",
}
rms = sqrt(rms/totmass);
- printf("Root mean square deviation after lsq fit = %g\n",rms);
+ printf("Root mean square deviation after lsq fit = %g nm\n",rms);
if (bBfac)
- printf("Atomic MSD's range from %g to %g\n",minmsd, maxmsd);
+ printf("Atomic MSD's range from %g to %g nm^2\n",minmsd, maxmsd);
if (bFit) {
/* reset coordinates of reference and fitted structure */
case efBRK:
case efENT:
if (bBfac || bLabel) {
- snew(atoms1->pdbinfo, atoms1->nr);
- snew(atoms1->atom, atoms1->nr);
+ srenew(atoms1->pdbinfo, atoms1->nr);
+ srenew(atoms1->atom, atoms1->nr); /* Why renew atom? */
+
+ /* Avoid segfaults when writing the pdb-file */
+ for (i=0; i<atoms1->nr; i++) {
+ atoms1->pdbinfo[i].type = eptAtom;
+ atoms1->pdbinfo[i].bAnisotropic = FALSE;
+ if (bBfac)
+ atoms1->pdbinfo[i].bfac = 0;
+ if (bLabel)
+ atoms1->resinfo[atoms1->atom[i].resind].chain = 'A';
+ }
+
for(i=0; i<isize1; i++) {
- atoms1->pdbinfo[index1[i]].type = eptAtom;
- atoms1->pdbinfo[index1[i]].bAnisotropic = FALSE;
+ /* atoms1->pdbinfo[index1[i]].type = eptAtom; */
+/* atoms1->pdbinfo[index1[i]].bAnisotropic = FALSE; */
if (bBfac)
- atoms1->pdbinfo[index1[i]].bfac = 800*M_PI*M_PI/3.0*msds[i]/100;
+ atoms1->pdbinfo[index1[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i];
+/* if (bLabel) */
+/* atoms1->resinfo[atoms1->atom[index1[i]].resind].chain = 'A'; */
+ }
+ srenew(atoms2->pdbinfo, atoms2->nr);
+ srenew(atoms2->atom, atoms2->nr); /* Why renew atom? */
+
+ for (i=0; i<atoms2->nr; i++) {
+ atoms2->pdbinfo[i].type = eptAtom;
+ atoms2->pdbinfo[i].bAnisotropic = FALSE;
+ if (bBfac)
+ atoms2->pdbinfo[i].bfac = 0;
if (bLabel)
- atoms1->resinfo[atoms1->atom[index1[i]].resind].chain = 'A';
+ atoms2->resinfo[atoms1->atom[i].resind].chain = 'B';
}
- snew(atoms2->pdbinfo, atoms2->nr);
- snew(atoms2->atom, atoms2->nr);
+
for(i=0; i<isize2; i++) {
- atoms2->pdbinfo[index2[i]].type = eptAtom;
- atoms2->pdbinfo[index2[i]].bAnisotropic = FALSE;
+ /* atoms2->pdbinfo[index2[i]].type = eptAtom; */
+/* atoms2->pdbinfo[index2[i]].bAnisotropic = FALSE; */
if (bBfac)
- atoms2->pdbinfo[index2[i]].bfac = 800*M_PI*M_PI/3.0*msds[i]/100;
- if (bLabel)
- atoms2->resinfo[atoms2->atom[index2[i]].resind].chain = 'B';
+ atoms2->pdbinfo[index2[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i];
+/* if (bLabel) */
+/* atoms2->resinfo[atoms2->atom[index2[i]].resind].chain = 'B'; */
}
}
fp=ffopen(outfile,"w");
"Apply corrections for periodic boundary conditions" }
};
FILE *out;
- int status,trjout;
+ t_trxstatus *status;
+ t_trxstatus *trjout;
t_topology top;
int ePBC;
t_atoms *atoms;
t_rgb rlo,rmi,rhi;
real *tmp;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
t_filenm fnm[] = {
{ efTRX, "-f", NULL, ffREAD },
w_rls[ifit[i]]=1.0;
}
}
-
+
/* Prepare reference frame */
- if (bPBC)
- rm_pbc(&(top.idef),ePBC,atoms->nr,box,xref,xref);
+ if (bPBC) {
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,atoms->nr,box);
+ gmx_rmpbc(gpbc,box,xref,xref);
+ }
if (bFit)
reset_x(nfit,ifit,atoms->nr,NULL,xref,w_rls);
nframes0++;
/* calculate x: a fitted struture of the selected atoms */
if (bPBC)
- rm_pbc(&(top.idef),ePBC,nat,box,xread,xread);
+ gmx_rmpbc(gpbc,box,xread,xread);
if (bFit) {
reset_x(nfit,ifit,nat,NULL,xread,w_rls);
do_fit(nat,w_rls,xref,xread);
tend = t;
/* calculate x: a (fitted) structure of the selected atoms */
if (bPBC)
- rm_pbc(&(top.idef),ePBC,nat,box,xread,xread);
+ gmx_rmpbc(gpbc,box,xread,xread);
if (bFit) {
reset_x(nfit,ifit,nat,NULL,xread,w_rls);
do_fit(nat,w_rls,xref,xread);
} while (read_next_x(oenv,status,&t,nat,xread,box) &&
(bRef || nframes < nframes0));
close_trj(status);
+ gmx_rmpbc_done(gpbc);
fprintf(stderr,"Read %d frames\n",nframes);
FILE *fmjdsp, bool bNoJump,bool bACF,bool bINT,
int ePBC,t_topology top, t_trxframe fr,real temp,
real trust,real bfit,real efit,real bvit,real evit,
- int status,int isize,int nmols, int nshift,
+ t_trxstatus *status,int isize,int nmols, int nshift,
atom_id *index0,int indexm[],real mass2[],
real qmol[], real eps_rf, const output_env_t oenv)
{
real err=0.0;
real *xfit;
real *yfit;
-
+ gmx_rmpbc_t gpbc=NULL;
+
/*
* indices for EH
*/
clear_rvec(mjd_tmp);
clear_rvec(mdvec);
clear_rvec(tmp);
-
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box);
+
do{
refr=(real)(nfr+1);
}
- rm_pbc(&top.idef,ePBC,fr.natoms,fr.box,fr.x,fr.x);
-
+ gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
+
calc_mj(top,ePBC,fr.box,bNoJump,nmols,indexm,fr.x,mtrans[nfr],mass2,qmol);
for(i=0;i<isize;i++){
}while(read_next_frame(oenv,status,&fr));
+ gmx_rmpbc_done(gpbc);
+
volume_av/=refr;
prefactor=1.0;
atom_id *index0=NULL;
int *indexm=NULL;
int isize;
- int status;
+ t_trxstatus *status;
int flags = 0;
bool bTop;
bool bNEU;
"[PAR]",
"The flag [TT]-caf[tt] is for the output of the current autocorrelation function and [TT]-mc[tt] writes the",
"correlation of the rotational and translational part of the dipole moment in the corresponding",
- "file. However this option is only available for trajectories containing velocities."
+ "file. However this option is only available for trajectories containing velocities.",
"Options [TT]-sh[tt] and [TT]-tr[tt] are responsible for the averaging and integration of the",
"autocorrelation functions. Since averaging proceeds by shifting the starting point",
"through the trajectory, the shift can be modified with [TT]-sh[tt] to enable the choice of uncorrelated",
"the number of frames. The option [TT]-tr[tt] controls the region of the integral taken into account",
"for calculating the static dielectric constant.",
"[PAR]",
- "Option [TT]-temp[tt] sets the temperature required for the computation of the static dielectric constant."
+ "Option [TT]-temp[tt] sets the temperature required for the computation of the static dielectric constant.",
"[PAR]",
"Option [TT]-eps[tt] controls the dielectric constant of the surrounding medium for simulations using",
"a Reaction Field or dipole corrections of the Ewald summation (eps=0 corresponds to",
{
rvec *x0; /* coordinates without pbc */
matrix box; /* box (3x3) */
- int natoms, /* nr. atoms in trj */
- status,
- i,n, /* loop indices */
+ int natoms; /* nr. atoms in trj */
+ t_trxstatus *status;
+ int i,n, /* loop indices */
ax1=0, ax2=0,
nr_frames = 0, /* number of frames */
slice; /* current slice */
t_electron *found; /* found by bsearch */
t_electron sought; /* thingie thought by bsearch */
+ gmx_rmpbc_t gpbc=NULL;
real t,
z;
for (i = 0; i < nr_grps; i++)
snew((*slDensity)[i], *nslices);
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
/*********** Start processing trajectory ***********/
do {
- rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x0);
+ gmx_rmpbc(gpbc,box,x0,x0);
if (bCenter)
center_coords(&top->atoms,box,x0,axis);
}
nr_frames++;
} while (read_next_x(oenv,status,&t,natoms,x0,box));
-
+ gmx_rmpbc_done(gpbc);
+
/*********** done with status file **********/
close_trj(status);
{
rvec *x0; /* coordinates without pbc */
matrix box; /* box (3x3) */
- int natoms, /* nr. atoms in trj */
- status,
- **slCount, /* nr. of atoms in one slice for a group */
+ int natoms; /* nr. atoms in trj */
+ t_trxstatus *status;
+ int **slCount, /* nr. of atoms in one slice for a group */
i,j,n, /* loop indices */
teller = 0,
ax1=0, ax2=0,
real t,
z;
char *buf; /* for tmp. keeping atomname */
+ gmx_rmpbc_t gpbc=NULL;
switch(axis) {
case 0:
for (i = 0; i < nr_grps; i++)
snew((*slDensity)[i], *nslices);
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
/*********** Start processing trajectory ***********/
do {
- rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x0);
+ gmx_rmpbc(gpbc,box,x0,x0);
if (bCenter)
center_coords(&top->atoms,box,x0,axis);
nr_frames++;
} while (read_next_x(oenv,status,&t,natoms,x0,box));
-
+ gmx_rmpbc_done(gpbc);
+
/*********** done with status file **********/
close_trj(status);
};
bool bXmin,bXmax,bRadial;
FILE *fp;
- int status;
+ t_trxstatus *status;
t_topology top;
int ePBC=-1;
rvec *x,xcom[2],direction,center,dx;
else {
i0 = max(0,nbegin);
i1 = min(nx-1,nbegin+nsmooth);
- printf("Making smooth transition from %d thru %d\n",i0,i1);
+ printf("Making smooth transition from %d through %d\n",i0,i1);
for(i=0; (i<i0); i++)
combined[i]=y[i];
for(i=i0; (i<=i1); i++) {
"For an estimate of the error you can run g_statistics on the",
"ACF, and use the output thus generated for this program.",
"The functional forms of the available functions are:[PAR]",
- "One parmeter : y = Exp[-a1 x]",
- "Two parmeters : y = a2 Exp[-a1 x]",
- "Three parmeter: y = a2 Exp[-a1 x] + (1 - a2) Exp[-a3 x]",
- "Startvalues for the fit procedure can be given on the commandline.",
+ "One parameter : y = Exp[-a1 x],",
+ "Two parameters : y = a2 Exp[-a1 x],",
+ "Three parameters: y = a2 Exp[-a1 x] + (1 - a2) Exp[-a3 x].",
+ "Start values for the fit procedure can be given on the command line.",
"It is also possible to fix parameters at their start value, use -fix",
"with the number of the parameter you want to fix.",
"[PAR]",
"numerical derivative of the combination data/fit.",
"The second file contains the real and imaginary parts of the",
"frequency-dependent dielectric constant, the last gives a plot",
- "known as the Cole-Cole plot, in which the imaginary",
+ "known as the Cole-Cole plot, in which the imaginary",
"component is plotted as a function of the real component.",
"For a pure exponential relaxation (Debye relaxation) the latter",
- "plot should be one half of a circle"
+ "plot should be one half of a circle."
};
t_filenm fnm[] = {
{ efXVG, "-f", "dipcorr",ffREAD },
fprintf(out,"%-10s %10s %10s %10s %10s %10s %10s\n",
"index","minimum","average","maximum","variance","std.dev",
"transition");
- for(i=0; (i>xr->ndih); i++) {
+ for(i=0; (i<xr->ndih); i++) {
sprintf(buf,"dih-%d",i);
ana_dih(out,buf,nframes,dih[i],&(xr->dih[i]));
}
t_enxframe *fr;
int nframes=1000,nre,timecheck=0,ncolour=0;
ener_file_t fmu=NULL;
- int i,j,k,n,m,natom=0,nmol,status,gnx_tot,teller,tel3;
+ int i,j,k,n,m,natom=0,nmol,gnx_tot,teller,tel3;
+ t_trxstatus *status;
int *dipole_bin,ndipbin,ibin,iVol,step,idim=-1;
unsigned long mode;
char buf[STRLEN];
rvec *slab_dipoles=NULL;
t_atom *atom=NULL;
t_block *mols=NULL;
+ gmx_rmpbc_t gpbc=NULL;
gnx_tot = gnx[0];
if (ncos > 1) {
gkrbin = mk_gkrbin(rcut,rcmax,bPhi,ndegrees);
}
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natom,box);
/* Start while loop over frames */
t1 = t0 = t;
M_av[m] = 0;
M_av2[m] = 0;
}
- rm_pbc(&(top->idef),ePBC,natom,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
muframelsq = gmx_stats_init();
/* Begin loop of all molecules in frame */
bCont = read_next_x(oenv,status,&t,natom,x,box);
} while (bCont);
+ gmx_rmpbc_done(gpbc);
+
if (!bMU)
close_trj(status);
"option -corr is used. The output file name is given with the [TT]-c[tt]",
"option.",
"The correlation functions can be averaged over all molecules",
- "([TT]mol[tt]), plotted per molecule seperately ([TT]molsep[tt])",
+ "([TT]mol[tt]), plotted per molecule separately ([TT]molsep[tt])",
"or it can be computed over the total dipole moment of the simulation box",
"([TT]total[tt]).[PAR]",
"Option [TT]-g[tt] produces a plot of the distance dependent Kirkwood",
{ "-mumax", FALSE, etREAL, {&mu_max},
"max dipole in Debye (for histrogram)" },
{ "-epsilonRF",FALSE, etREAL, {&epsilonRF},
- "epsilon of the reaction field used during the simulation, needed for dieclectric constant calculation. WARNING: 0.0 means infinity (default)" },
+ "epsilon of the reaction field used during the simulation, needed for dielectric constant calculation. WARNING: 0.0 means infinity (default)" },
{ "-skip", FALSE, etINT, {&skip},
"Skip steps in the output (but not in the computations)" },
{ "-temp", FALSE, etREAL, {&temp},
t_nrnb nrnb;
t_commrec *cr;
t_graph *g;
- int status,ntopatoms,natoms,i,j,kkk;
+ int ntopatoms,natoms,i,j,kkk;
+ t_trxstatus *status;
real t;
rvec *x,*f,*xav=NULL;
matrix box;
int my_clust;
FILE *fplog;
output_env_t oenv;
-
+ gmx_rmpbc_t gpbc=NULL;
+
t_filenm fnm[] = {
{ efTPX, NULL, NULL, ffREAD },
{ efTRX, "-f", NULL, ffREAD },
init_forcerec(fplog,oenv,fr,NULL,&ir,&mtop,cr,box,FALSE,NULL,NULL,NULL,
FALSE,-1);
init_nrnb(&nrnb);
+ if (ir.ePBC != epbcNONE)
+ gpbc = gmx_rmpbc_init(&top->idef,ir.ePBC,natoms,box);
+
j=0;
do {
if (ir.ePBC != epbcNONE) {
if (ir.bPeriodicMols)
set_pbc(&pbc,ir.ePBC,box);
else
- rm_pbc(&top->idef,ir.ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
}
if (clust) {
j++;
} while (read_next_x(oenv,status,&t,natoms,x,box));
close_trj(status);
+ if (ir.ePBC != epbcNONE)
+ gmx_rmpbc_done(gpbc);
if (clust) {
dump_clust_stats(fplog,fcd.disres.nres,&(top->idef.il[F_DISRES]),
real t,t0,cut2,dist2;
rvec *x=NULL,*v=NULL,dx;
matrix box;
- int status;
+ t_trxstatus *status;
int natoms;
int g,d,i,j,res,teller=0;
int *contact_time=NULL,*ccount=NULL,ccount_nalloc=0,sum;
char buf[STRLEN];
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
char *leg[4] = { "|d|","d\\sx\\N","d\\sy\\N","d\\sz\\N" };
else
pbc = NULL;
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
do {
/* initialisation for correct distance calculations */
if (pbc) {
set_pbc(pbc,ePBC,box);
/* make molecules whole again */
- rm_pbc(&top->idef,ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
}
/* calculate center of masses */
for(g=0;(g<ngrps);g++) {
teller++;
} while (read_next_x(oenv,status,&t,natoms,x,box));
+ gmx_rmpbc_done(gpbc);
if (!bCutoff)
ffclose(fp);
{ "-tail", FALSE, etRVEC, {tail},
"Last atom of the arrow vector" }
};
- int i,j,natoms,isize,status;
+ int i,j,natoms,isize;
+ t_trxstatus *status;
atom_id *index=NULL,*index_all;
char title[256],*grpname;
t_atoms atoms;
"[PAR]",
"Option [TT]-bt[tt] determines the box type: [TT]triclinic[tt] is a",
"triclinic box, [TT]cubic[tt] is a rectangular box with all sides equal",
- "[TT]dodecahedron[tt] represents a rhombic dodecahedron and "
- "[TT]octahedron[tt] is a truncated octahedron.",
+ "[TT]dodecahedron[tt] represents a rhombic dodecahedron and",
+ "[TT]octahedron[tt] is a truncated octahedron.",
"The last two are special cases of a triclinic box.",
"The length of the three box vectors of the truncated octahedron is the",
"shortest distance between two opposite hexagons.",
"with an optional center of rotation specified by [TT]-aligncenter[tt].",
"[PAR]",
"Finally with option [TT]-label[tt] editconf can add a chain identifier",
- "to a pdb file, which can be useful for analysis with e.g. rasmol."
+ "to a pdb file, which can be useful for analysis with e.g. rasmol.",
"[PAR]",
"To convert a truncated octrahedron file produced by a package which uses",
"a cubic box with the corners cut off (such as Gromos) use:[BR]",
"where [TT]veclen[tt] is the size of the cubic box times sqrt(3)/2." };
const char *bugs[] =
{
- "For complex molecules, the periodicity removal routine may break down, "
- "in that case you can use trjconv" };
+ "For complex molecules, the periodicity removal routine may break down, ",
+ "in that case you can use trjconv." };
static real dist = 0.0, rbox = 0.0, to_diam = 0.0;
static bool bNDEF = FALSE, bRMPBC = FALSE, bCenter = FALSE, bReadVDW =
FALSE, bCONECT = FALSE;
}
nsteps = fr->nsteps;
nsum = fr_nsum;
- } else if (out_step - *ee_sum_step == nsteps + fr->nsteps) {
+ } else if (out_step + *ee_sum_nsum - *ee_sum_step == nsteps + fr->nsteps) {
if (fr_nsum == 1) {
for(i=0;i<nre;i++) {
ee_sum[i].eav +=
if (ee_sum_nsum <= 1) {
fro->nsum = 0;
} else {
- fro->nsum = ee_sum_nsum;
+ fro->nsum = gmx_large_int_to_int(ee_sum_nsum,
+ "energy average summation");
/* Copy the energy sums */
for(i=0; i<nre; i++) {
fro->ener[i].esum = ee_sum[i].esum;
{ "-skip", FALSE, etINT, {&skip},
"Skip number of frames between data points" },
{ "-mean", FALSE, etBOOL, {&bMeanEmtx},
- "with -groups extracts matrix of mean energies in stead of "
+ "with -groups extracts matrix of mean energies instead of "
"matrix for each timestep" },
{ "-nlevels", FALSE, etINT, {&nlevels},"number of levels for matrix colors"},
{ "-max",FALSE, etREAL, {&cutmax},"max value for energies"},
int nexact,nnotexact;
double x1m,x1mk;
real Temp=-1,Pres=-1,VarV=-1,VarT=-1,VarEtot=-1,AvEtot=0,VarEnthalpy=-1;
- int i,j;
+ int i,j,nout;
real chi2;
char buf[256],eebuf[100];
/* Calculate the time difference */
delta_t = t - start_t;
- fprintf(stdout,"\nStatistics over %s steps [ %.4f thru %.4f ps ], %d data sets\n",
+ fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
gmx_step_str(nsteps,buf),start_t,t,nset);
calc_averages(nset,edat,nbmin,nbmax);
/* Use trapezium rule for integration */
integral = 0;
intBulk = 0;
- for(i=1; (i<edat->nframes/2); i++) {
- integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
- intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
- fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
+ nout = get_acfnout();
+ if ((nout < 2) || (nout >= edat->nframes/2))
+ nout = edat->nframes/2;
+ for(i=1; (i<nout); i++)
+ {
+ integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
+ intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
+ fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
}
ffclose(fp);
}
else if (bCorr) {
if (bFluct)
- strcpy(buf,"Autocorrelation of Energy Fluctuations");
+ strcpy(buf,"Autocorrelation of Energy Fluctuations");
else
- strcpy(buf,"Energy Autocorrelation");
+ strcpy(buf,"Energy Autocorrelation");
#if 0
do_autocorr(corrfn,oenv,buf,edat->nframes,
- bSum ? 1 : nset,
- bSum ? &edat->s[nset-1].ener : eneset,
- (delta_t/edat->nframes),eacNormal,FALSE);
+ bSum ? 1 : nset,
+ bSum ? &edat->s[nset-1].ener : eneset,
+ (delta_t/edat->nframes),eacNormal,FALSE);
#endif
}
}
"difference with an ideal gas state: [BR]",
" Delta A = A(N,V,T) - A_idgas(N,V,T) = kT ln < e^(Upot/kT) >[BR]",
" Delta G = G(N,p,T) - G_idgas(N,p,T) = kT ln < e^(Upot/kT) >[BR]",
- "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and"
+ "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
"the average is over the ensemble (or time in a trajectory).",
"Note that this is in principle",
"only correct when averaging over the whole (Boltzmann) ensemble",
int isize;
atom_id *index;
real *w_rls=NULL;
- int in,outl,outh;
+ t_trxstatus *in;
+ t_trxstatus *outl,*outh;
int nffr,i,fr,nat,j,d,m;
atom_id *ind;
real flen,*filt,sum,*t;
rvec xcmtop,xcm,**x,*ptr,*xf,*xn,*xp,hbox;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
#define NLEG asize(leg)
t_filenm fnm[] = {
topfile = ftp2fn_null(efTPS,NFILE,fnm);
lowfile = opt2fn("-ol",NFILE,fnm);
}
-
if (topfile) {
bTop = read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,
&xtop,NULL,topbox,TRUE);
if (bTop) {
- rm_pbc(&(top.idef),ePBC,top.atoms.nr,topbox,xtop,xtop);
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,topbox);
+ gmx_rmpbc(gpbc,topbox,xtop,xtop);
}
}
}
}
if (bTop) {
- rm_pbc(&(top.idef),ePBC,nat,box[nffr - 1],xn,xn);
+ gmx_rmpbc(gpbc,box[nffr - 1],xn,xn);
}
if (bFit) {
calc_xcm(xn,isize,index,top.atoms.atom,xcm,FALSE);
fr++;
} while (read_next_x(oenv,in,&(t[nffr - 1]),nat,x[nffr - 1],box[nffr - 1]));
+ if (bTop)
+ gmx_rmpbc_done(gpbc);
+
if (outh)
close_trx(outh);
if (outl)
};
const char *bugs[] = {
- "The program should allow for random displacement off lattice points." };
+ "The program should allow for random displacement of lattice points." };
int vol;
t_atoms *atoms; /* list with all atoms */
rvec shift;
int natoms; /* number of atoms in one molecule */
int nres; /* number of molecules? */
- int i,j,k,l,m,ndx,nrdx,nx,ny,nz,status=-1;
+ int i,j,k,l,m,ndx,nrdx,nx,ny,nz;
+ t_trxstatus *status;
bool bTRX;
output_env_t oenv;
"Calculate the 2D radii of gyration of # slices along the z-axis" },
};
FILE *out;
- int status;
+ t_trxstatus *status;
t_topology top;
int ePBC;
rvec *x,*x_s;
int i,j,m,gnx,nam,mol;
atom_id *index;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
char *leg[] = { "Rg", "RgX", "RgY", "RgZ" };
char *legI[] = { "Itot", "I1", "I2", "I3" };
#define NLEG asize(leg)
fprintf(out,"@ subtitle \"Axes are principal component axes\"\n");
xvgr_legend(out,NLEG,leg,oenv);
}
+ if (nz == 0)
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
do {
if (nz == 0)
- rm_pbc(&top.idef,ePBC,natoms,box,x,x_s);
+ gmx_rmpbc(gpbc,box,x,x_s);
gyro = 0;
clear_rvec(gvec);
clear_rvec(d);
j++;
} while(read_next_x(oenv,status,&t,natoms,x,box));
close_trj(status);
+ if (nz == 0)
+ gmx_rmpbc_done(gpbc);
ffclose(out);
com; /* center of mass of micel, with bMicel */
rvec *dip; /* sum of dipoles, unnormalized */
matrix box; /* box (3x3) */
- int status;
+ t_trxstatus *status;
real t, /* time from trajectory */
*sum, /* sum of all cosines of dipoles, per slice */
*frame; /* order over one frame */
i,j,teller = 0,
slice=0, /* current slice number */
*count; /* nr. of atoms in one slice */
-
+ gmx_rmpbc_t gpbc=NULL;
+
if ((natoms = read_first_x(oenv,&status,fn,&t,&x0,box)) == 0)
gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
teller = 0;
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
/*********** Start processing trajectory ***********/
do
{
*slWidth = box[axis][axis]/(*nslices);
teller++;
- rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x0);
+ gmx_rmpbc(gpbc,box,x0,x0);
if (bMicel)
calc_xcm(x0, nmic, micel, top->atoms.atom, com, FALSE);
/*********** done with status file **********/
fprintf(stderr,"\nRead trajectory. Printing parameters to file\n");
+ gmx_rmpbc_done(gpbc);
for (i = 0; i < *nslices; i++) /* average over frames */
{
-/*
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
*
*
* This source code is part of
#endif
#include <math.h>
+/*#define HAVE_NN_LOOPS*/
+/* Set environment variable CFLAGS = "-fopenmp" when running
+ * configure and define DOUSEOPENMP to make use of parallelized
+ * calculation of autocorrelation function.
+ * It also adds a new option -nthreads which sets the number of threads.
+ * */
+/*#define DOUSEOPENMP*/
+
+#ifdef DOUSEOPENMP
+#define HAVE_OPENMP
+#include "omp.h"
+#endif
+
#include "statutil.h"
#include "copyrite.h"
#include "sysstuff.h"
#include "pbc.h"
#include "correl.h"
#include "gmx_ana.h"
+#include "geminate.h"
-
+typedef short int t_E;
+typedef int t_EEst;
#define max_hx 7
typedef int t_hx[max_hx];
#define NRHXTYPES max_hx
{"n-n","n-n+1","n-n+2","n-n+3","n-n+4","n-n+5","n-n>6"};
#define MAXHH 4
+#ifdef HAVE_OPENMP
+#define MASTER_THREAD_ONLY(threadNr) ((threadNr)==0)
+#else
+#define MASTER_THREAD_ONLY(threadNr) ((threadNr)==(threadNr))
+#endif
+
+/* -----------------------------------------*/
+
enum { gr0, gr1, grI, grNR };
enum { hbNo, hbDist, hbHB, hbNR, hbR2};
enum { noDA, ACC, DON, DA, INGROUP};
+enum {NN_NULL, NN_NONE, NN_BINARY, NN_1_over_r3, NN_dipole, NN_NR};
static const char *grpnames[grNR] = {"0","1","I" };
#define ISINGRP(h) (((h) & 4) == 4)
typedef struct {
- int nr;
- int maxnr;
- atom_id *atoms;
+ int nr;
+ int maxnr;
+ atom_id *atoms;
} t_ncell;
typedef struct {
- t_ncell d[grNR];
- t_ncell a[grNR];
+ t_ncell d[grNR];
+ t_ncell a[grNR];
} t_gridcell;
typedef int t_icell[grNR];
typedef atom_id h_id[MAXHYDRO];
typedef struct {
- int history[MAXHYDRO];
- /* Has this hbond existed ever? If so as hbDist or hbHB or both.
- * Result is stored as a bitmap (1 = hbDist) || (2 = hbHB)
- */
- /* Bitmask array which tells whether a hbond is present
- * at a given time. Either of these may be NULL
- */
- int n0; /* First frame a HB was found */
- int nframes,maxframes; /* Amount of frames in this hbond */
- unsigned int **h;
- unsigned int **g;
- /* See Xu and Berne, JPCB 105 (2001), p. 11929. We define the
- * function g(t) = [1-h(t)] H(t) where H(t) is one when the donor-
- * acceptor distance is less than the user-specified distance (typically
- * 0.35 nm).
- */
+ int history[MAXHYDRO];
+ /* Has this hbond existed ever? If so as hbDist or hbHB or both.
+ * Result is stored as a bitmap (1 = hbDist) || (2 = hbHB)
+ */
+ /* Bitmask array which tells whether a hbond is present
+ * at a given time. Either of these may be NULL
+ */
+ int n0; /* First frame a HB was found */
+ int nframes,maxframes; /* Amount of frames in this hbond */
+ unsigned int **h;
+ unsigned int **g;
+ /* See Xu and Berne, JPCB 105 (2001), p. 11929. We define the
+ * function g(t) = [1-h(t)] H(t) where H(t) is one when the donor-
+ * acceptor distance is less than the user-specified distance (typically
+ * 0.35 nm).
+ */
} t_hbond;
typedef struct {
- int nra,max_nra;
- atom_id *acc; /* Atom numbers of the acceptors */
- int *grp; /* Group index */
- int *aptr; /* Map atom number to acceptor index */
+ int nra,max_nra;
+ atom_id *acc; /* Atom numbers of the acceptors */
+ int *grp; /* Group index */
+ int *aptr; /* Map atom number to acceptor index */
} t_acceptors;
typedef struct {
- int nrd,max_nrd;
- int *don; /* Atom numbers of the donors */
- int *grp; /* Group index */
- int *dptr; /* Map atom number to donor index */
- int *nhydro; /* Number of hydrogens for each donor */
- h_id *hydro; /* The atom numbers of the hydrogens */
- h_id *nhbonds; /* The number of HBs per H at current */
+ int nrd,max_nrd;
+ int *don; /* Atom numbers of the donors */
+ int *grp; /* Group index */
+ int *dptr; /* Map atom number to donor index */
+ int *nhydro; /* Number of hydrogens for each donor */
+ h_id *hydro; /* The atom numbers of the hydrogens */
+ h_id *nhbonds; /* The number of HBs per H at current */
} t_donors;
+/* Tune this to match memory requirements. It should be a signed integer type, e.g. signed char.*/
+#define PSTYPE int
+
+typedef struct {
+ int len; /* The length of frame and p. */
+ int *frame; /* The frames at which transitio*/
+ PSTYPE *p;
+} t_pShift;
+
+typedef struct {
+ /* Periodicity history. Used for the reversible geminate recombination. */
+ t_pShift **pHist; /* The periodicity of every hbond in t_hbdata->hbmap:
+ * pHist[d][a]. We can safely assume that the same
+ * periodic shift holds for all hydrogens of a da-pair.
+ *
+ * Nowadays it only stores TRANSITIONS, and not the shift at every frame.
+ * That saves a LOT of memory, an hopefully kills a mysterious bug where
+ * pHist gets contaminated. */
+
+ PSTYPE nper; /* The length of p2i */
+ ivec *p2i; /* Maps integer to periodic shift for a pair.*/
+ matrix P; /* Projection matrix to find the box shifts. */
+ int gemtype; /* enumerated type */
+} t_gemPeriod;
+
+typedef struct {
+ int nframes;
+ int *Etot; /* Total energy for each frame */
+ t_E ****E; /* Energy estimate for [d][a][h][frame-n0] */
+} t_hbEmap;
+
typedef struct {
- bool bHBmap,bDAnr;
- int wordlen;
- /* The following arrays are nframes long */
- int nframes,max_frames,maxhydro;
- int *nhb,*ndist;
- h_id *n_bound;
- real *time;
- t_icell *danr;
- t_hx *nhx;
- /* These structures are initialized from the topology at start up */
- t_donors d;
- t_acceptors a;
- /* This holds a matrix with all possible hydrogen bonds */
- int nrhb,nrdist;
- t_hbond ***hbmap;
+ bool bHBmap,bDAnr,bGem;
+ int wordlen;
+ /* The following arrays are nframes long */
+ int nframes,max_frames,maxhydro;
+ int *nhb,*ndist;
+ h_id *n_bound;
+ real *time;
+ t_icell *danr;
+ t_hx *nhx;
+ /* These structures are initialized from the topology at start up */
+ t_donors d;
+ t_acceptors a;
+ /* This holds a matrix with all possible hydrogen bonds */
+ int nrhb,nrdist;
+ t_hbond ***hbmap;
+#ifdef HAVE_NN_LOOPS
+ t_hbEmap hbE;
+#endif
+ /* For parallelization reasons this will have to be a pointer.
+ * Otherwise discrepancies may arise between the periodicity data
+ * seen by different threads. */
+ t_gemPeriod *per;
} t_hbdata;
+static void clearPshift(t_pShift *pShift)
+{
+ if (pShift->len > 0) {
+ sfree(pShift->p);
+ sfree(pShift->frame);
+ pShift->len = 0;
+ }
+}
+
+static void calcBoxProjection(matrix B, matrix P)
+{
+ const int vp[] = {XX,YY,ZZ};
+ int i,j;
+ int m,n;
+ matrix M, N, U;
+
+ for (i=0; i<3; i++){ m = vp[i];
+ for (j=0; j<3; j++){ n = vp[j];
+ U[m][n] = i==j ? 1:0;
+ }
+ }
+ m_inv(B,M);
+ for (i=0; i<3; i++){ m = vp[i];
+ mvmul(M, U[m], P[m]);
+ }
+ transpose(P,N);
+}
+
+static void calcBoxDistance(matrix P, rvec d, ivec ibd){
+ /* returns integer distance in box coordinates.
+ * P is the projection matrix from cartesian coordinates
+ * obtained with calcBoxProjection(). */
+ int i;
+ rvec bd;
+ mvmul(P, d, bd);
+ /* extend it by 0.5 in all directions since (int) rounds toward 0.*/
+ for (i=0;i<3;i++)
+ bd[i]=bd[i] + (bd[i]<0 ? -0.5 : 0.5);
+ ibd[XX] = (int)bd[XX];
+ ibd[YY] = (int)bd[YY];
+ ibd[ZZ] = (int)bd[ZZ];
+}
/* Changed argument 'bMerge' into 'oneHB' below,
* since -contact should cause maxhydro to be 1,
* not just -merge.
* - Erik Marklund May 29, 2006
*/
-static t_hbdata *mk_hbdata(bool bHBmap,bool bDAnr,bool oneHB)
+
+static PSTYPE periodicIndex(ivec r, t_gemPeriod *per, bool daSwap) {
+ /* Try to merge hbonds on the fly. That means that if the
+ * acceptor and donor are mergable, then:
+ * 1) store the hb-info so that acceptor id > donor id,
+ * 2) add the periodic shift in pairs, so that [-x,-y,-z] is
+ * stored in per.p2i[] whenever acceptor id < donor id.
+ * Note that [0,0,0] should already be the first element of per.p2i
+ * by the time this function is called. */
+
+ /* daSwap is TRUE if the donor and acceptor were swapped.
+ * If so, then the negative vector should be used. */
+ PSTYPE i;
+
+ if (per->p2i == NULL || per->nper == 0)
+ gmx_fatal(FARGS, "'per' not initialized properly.");
+ for (i=0; i<per->nper; i++) {
+ if (r[XX] == per->p2i[i][XX] &&
+ r[YY] == per->p2i[i][YY] &&
+ r[ZZ] == per->p2i[i][ZZ])
+ return i;
+ }
+ /* Not found apparently. Add it to the list! */
+ /* printf("New shift found: %i,%i,%i\n",r[XX],r[YY],r[ZZ]); */
+
+/* Unfortunately this needs to be critical it seems. */
+#ifdef HAVE_OPENMP
+#pragma omp critical
+#endif
+ {
+ if (!per->p2i) {
+ fprintf(stderr, "p2i not initialized. This shouldn't happen!\n");
+ snew(per->p2i, 1);
+ }
+ else
+ srenew(per->p2i, per->nper+2);
+ copy_ivec(r, per->p2i[per->nper]);
+ (per->nper)++;
+
+ /* Add the mirror too. It's rather likely that it'll be needed. */
+ per->p2i[per->nper][XX] = -r[XX];
+ per->p2i[per->nper][YY] = -r[YY];
+ per->p2i[per->nper][ZZ] = -r[ZZ];
+ (per->nper)++;
+ } /* omp critical */
+ return per->nper - 1 - (daSwap ? 0:1);
+}
+
+static t_hbdata *mk_hbdata(bool bHBmap,bool bDAnr,bool oneHB, bool bGem, int gemmode)
{
- t_hbdata *hb;
+ t_hbdata *hb;
- snew(hb,1);
- hb->wordlen = 8*sizeof(unsigned int);
- hb->bHBmap = bHBmap;
- hb->bDAnr = bDAnr;
- if (oneHB)
- hb->maxhydro = 1;
- else
- hb->maxhydro = MAXHYDRO;
+ snew(hb,1);
+ hb->wordlen = 8*sizeof(unsigned int);
+ hb->bHBmap = bHBmap;
+ hb->bDAnr = bDAnr;
+ hb->bGem = bGem;
+ if (oneHB)
+ hb->maxhydro = 1;
+ else
+ hb->maxhydro = MAXHYDRO;
+ snew(hb->per, 1);
+ hb->per->gemtype = bGem ? gemmode : 0;
- return hb;
+ return hb;
}
static void mk_hbmap(t_hbdata *hb,bool bTwo,bool bInsert)
{
- int i,j;
+ int i,j;
+
+ snew(hb->hbmap,hb->d.nrd);
+ for(i=0; (i<hb->d.nrd); i++) {
+ snew(hb->hbmap[i],hb->a.nra);
+ if (hb->hbmap[i] == NULL)
+ gmx_fatal(FARGS,"Could not allocate enough memory for hbmap");
+ for (j=0; (j>hb->a.nra); j++)
+ hb->hbmap[i][j] = NULL;
+ }
+}
+
+/* Consider redoing pHist so that is only stores transitions between
+ * periodicities and not the periodicity for all frames. This eats heaps of memory. */
+static void mk_per(t_hbdata *hb)
+{
+ int i,j;
+ if (hb->bGem) {
+ snew(hb->per->pHist, hb->d.nrd);
+ for (i=0; i<hb->d.nrd; i++) {
+ snew(hb->per->pHist[i], hb->a.nra);
+ if (hb->per->pHist[i]==NULL)
+ gmx_fatal(FARGS,"Could not allocate enough memory for per->pHist");
+ for (j=0; j<hb->a.nra; j++) {
+ clearPshift(&(hb->per->pHist[i][j]));
+ }
+ }
+ /* add the [0,0,0] shift to element 0 of p2i. */
+ snew(hb->per->p2i, 1);
+ clear_ivec(hb->per->p2i[0]);
+ hb->per->nper = 1;
+ }
+}
+
+#ifdef HAVE_NN_LOOPS
+static void mk_hbEmap (t_hbdata *hb, int n0)
+{
+ int i, j, k;
+ hb->hbE.E = NULL;
+ hb->hbE.nframes = 0;
+ snew(hb->hbE.E, hb->d.nrd);
+ for (i=0; i<hb->d.nrd; i++)
+ {
+ snew(hb->hbE.E[i], hb->a.nra);
+ for (j=0; j<hb->a.nra; j++)
+ {
+ snew(hb->hbE.E[i][j], MAXHYDRO);
+ for (k=0; k<MAXHYDRO; k++)
+ hb->hbE.E[i][j][k] = NULL;
+ }
+ }
+ hb->hbE.Etot = NULL;
+}
+
+static void free_hbEmap (t_hbdata *hb)
+{
+ int i, j, k;
+ for (i=0; i<hb->d.nrd; i++)
+ {
+ for (j=0; j<hb->a.nra; j++)
+ {
+ for (k=0; k<MAXHYDRO; k++)
+ sfree(hb->hbE.E[i][j][k]);
+ sfree(hb->hbE.E[i][j]);
+ }
+ sfree(hb->hbE.E[i]);
+ }
+ sfree(hb->hbE.E);
+ sfree(hb->hbE.Etot);
+}
+
+static void addFramesNN(t_hbdata *hb, int frame)
+{
+
+#define DELTAFRAMES_HBE 10
+
+ int d,a,h,nframes;
+
+ if (frame >= hb->hbE.nframes) {
+ nframes = hb->hbE.nframes + DELTAFRAMES_HBE;
+ srenew(hb->hbE.Etot, nframes);
+
+ for (d=0; d<hb->d.nrd; d++)
+ for (a=0; a<hb->a.nra; a++)
+ for (h=0; h<hb->d.nhydro[d]; h++)
+ srenew(hb->hbE.E[d][a][h], nframes);
+
+ hb->hbE.nframes += DELTAFRAMES_HBE;
+ }
+}
+
+static t_E calcHbEnergy(int d, int a, int h, rvec x[], t_EEst EEst,
+ matrix box, rvec hbox, t_donors *donors){
+ /* d - donor atom
+ * a - acceptor atom
+ * h - hydrogen
+ * alpha - angle between dipoles
+ * x[] - atomic positions
+ * EEst - the type of energy estimate (see enum in hbplugin.h)
+ * box - the box vectors \
+ * hbox - half box lengths _These two are only needed for the pbc correction
+ */
+
+ t_E E;
+ rvec dist;
+ rvec dipole[2], xmol[3], xmean[2];
+ int i;
+ real r, realE;
+
+ if (d == a)
+ /* Self-interaction */
+ return NONSENSE_E;
+
+ switch (EEst)
+ {
+ case NN_BINARY:
+ /* This is a simple binary existence function that sets E=1 whenever
+ * the distance between the oxygens is equal too or less than 0.35 nm.
+ */
+ rvec_sub(x[d], x[a], dist);
+ pbc_correct_gem(dist, box, hbox);
+ if (norm(dist) <= 0.35)
+ E = 1;
+ else
+ E = 0;
+ break;
+
+ case NN_1_over_r3:
+ /* Negative potential energy of a dipole.
+ * E = -cos(alpha) * 1/r^3 */
+
+ copy_rvec(x[d], xmol[0]); /* donor */
+ copy_rvec(x[donors->hydro[donors->dptr[d]][0]], xmol[1]); /* hydrogen */
+ copy_rvec(x[donors->hydro[donors->dptr[d]][1]], xmol[2]); /* hydrogen */
+
+ svmul(15.9994*(1/1.008), xmol[0], xmean[0]);
+ rvec_inc(xmean[0], xmol[1]);
+ rvec_inc(xmean[0], xmol[2]);
+ for(i=0; i<3; i++)
+ xmean[0][i] /= (15.9994 + 1.008 + 1.008)/1.008;
+
+ /* Assumes that all acceptors are also donors. */
+ copy_rvec(x[a], xmol[0]); /* acceptor */
+ copy_rvec(x[donors->hydro[donors->dptr[a]][0]], xmol[1]); /* hydrogen */
+ copy_rvec(x[donors->hydro[donors->dptr[a]][1]], xmol[2]); /* hydrogen */
+
+
+ svmul(15.9994*(1/1.008), xmol[0], xmean[1]);
+ rvec_inc(xmean[1], xmol[1]);
+ rvec_inc(xmean[1], xmol[2]);
+ for(i=0; i<3; i++)
+ xmean[1][i] /= (15.9994 + 1.008 + 1.008)/1.008;
+
+ rvec_sub(xmean[0], xmean[1], dist);
+ pbc_correct_gem(dist, box, hbox);
+ r = norm(dist);
+
+ realE = pow(r, -3.0);
+ E = (t_E)(SCALEFACTOR_E * realE);
+ break;
+
+ case NN_dipole:
+ /* Negative potential energy of a (unpolarizable) dipole.
+ * E = -cos(alpha) * 1/r^3 */
+ clear_rvec(dipole[1]);
+ clear_rvec(dipole[0]);
+
+ copy_rvec(x[d], xmol[0]); /* donor */
+ copy_rvec(x[donors->hydro[donors->dptr[d]][0]], xmol[1]); /* hydrogen */
+ copy_rvec(x[donors->hydro[donors->dptr[d]][1]], xmol[2]); /* hydrogen */
+
+ rvec_inc(dipole[0], xmol[1]);
+ rvec_inc(dipole[0], xmol[2]);
+ for (i=0; i<3; i++)
+ dipole[0][i] *= 0.5;
+ rvec_dec(dipole[0], xmol[0]);
+
+ svmul(15.9994*(1/1.008), xmol[0], xmean[0]);
+ rvec_inc(xmean[0], xmol[1]);
+ rvec_inc(xmean[0], xmol[2]);
+ for(i=0; i<3; i++)
+ xmean[0][i] /= (15.9994 + 1.008 + 1.008)/1.008;
+
+ /* Assumes that all acceptors are also donors. */
+ copy_rvec(x[a], xmol[0]); /* acceptor */
+ copy_rvec(x[donors->hydro[donors->dptr[a]][0]], xmol[1]); /* hydrogen */
+ copy_rvec(x[donors->hydro[donors->dptr[a]][2]], xmol[2]); /* hydrogen */
+
+
+ rvec_inc(dipole[1], xmol[1]);
+ rvec_inc(dipole[1], xmol[2]);
+ for (i=0; i<3; i++)
+ dipole[1][i] *= 0.5;
+ rvec_dec(dipole[1], xmol[0]);
+
+ svmul(15.9994*(1/1.008), xmol[0], xmean[1]);
+ rvec_inc(xmean[1], xmol[1]);
+ rvec_inc(xmean[1], xmol[2]);
+ for(i=0; i<3; i++)
+ xmean[1][i] /= (15.9994 + 1.008 + 1.008)/1.008;
+
+ rvec_sub(xmean[0], xmean[1], dist);
+ pbc_correct_gem(dist, box, hbox);
+ r = norm(dist);
+
+ double cosalpha = cos_angle(dipole[0],dipole[1]);
+ realE = cosalpha * pow(r, -3.0);
+ E = (t_E)(SCALEFACTOR_E * realE);
+ break;
+
+ default:
+ printf("Can't do that type of energy estimate: %i\n.", EEst);
+ E = NONSENSE_E;
+ }
+
+ return E;
+}
+
+static void storeHbEnergy(t_hbdata *hb, int d, int a, int h, t_E E, int frame){
+ /* hb - hbond data structure
+ d - donor
+ a - acceptor
+ h - hydrogen
+ E - estimate of the energy
+ frame - the current frame.
+ */
+
+ /* Store the estimated energy */
+ if (E == NONSENSE_E)
+ E = 0;
+
+ hb->hbE.E[d][a][h][frame] = E;
+#ifdef HAVE_OPENMP
+#pragma omp critical
+#endif
+ {
+ hb->hbE.Etot[frame] += E;
+ }
+}
+#endif /* HAVE_NN_LOOPS */
+
- snew(hb->hbmap,hb->d.nrd);
- for(i=0; (i<hb->d.nrd); i++) {
- snew(hb->hbmap[i],hb->a.nra);
- if (hb->hbmap[i] == NULL)
- gmx_fatal(FARGS,"Could not allocate enough memory for hbmap");
- }
+/* Finds -v[] in the periodicity index */
+static int findMirror(PSTYPE p, ivec v[], PSTYPE nper)
+{
+ PSTYPE i;
+ ivec u;
+ for (i=0; i<nper; i++){
+ if (v[i][XX] == -(v[p][XX]) &&
+ v[i][YY] == -(v[p][YY]) &&
+ v[i][ZZ] == -(v[p][ZZ]))
+ return (int)i;
+ }
+ printf("Couldn't find mirror of [%i, %i, %i], index \n",
+ v[p][XX],
+ v[p][YY],
+ v[p][ZZ]);
+ return -1;
}
+
static void add_frames(t_hbdata *hb,int nframes)
{
- int i,j,k,l;
+ int i,j,k,l;
- if (nframes >= hb->max_frames) {
- hb->max_frames += 4096;
- srenew(hb->time,hb->max_frames);
- srenew(hb->nhb,hb->max_frames);
- srenew(hb->ndist,hb->max_frames);
- srenew(hb->n_bound,hb->max_frames);
- srenew(hb->nhx,hb->max_frames);
- if (hb->bDAnr)
- srenew(hb->danr,hb->max_frames);
- }
- hb->nframes=nframes;
+ if (nframes >= hb->max_frames) {
+ hb->max_frames += 4096;
+ srenew(hb->time,hb->max_frames);
+ srenew(hb->nhb,hb->max_frames);
+ srenew(hb->ndist,hb->max_frames);
+ srenew(hb->n_bound,hb->max_frames);
+ srenew(hb->nhx,hb->max_frames);
+ if (hb->bDAnr)
+ srenew(hb->danr,hb->max_frames);
+ }
+ hb->nframes=nframes;
}
#define OFFSET(frame) (frame / 32)
static void _set_hb(unsigned int hbexist[],unsigned int frame,bool bValue)
{
- if (bValue)
- hbexist[OFFSET(frame)] |= MASK(frame);
- else
- hbexist[OFFSET(frame)] &= ~MASK(frame);
+ if (bValue)
+ hbexist[OFFSET(frame)] |= MASK(frame);
+ else
+ hbexist[OFFSET(frame)] &= ~MASK(frame);
}
static bool is_hb(unsigned int hbexist[],int frame)
{
- return ((hbexist[OFFSET(frame)] & MASK(frame)) != 0) ? 1 : 0;
+ return ((hbexist[OFFSET(frame)] & MASK(frame)) != 0) ? 1 : 0;
}
static void set_hb(t_hbdata *hb,int id,int ih, int ia,int frame,int ihb)
{
- unsigned int *ghptr=NULL;
+ unsigned int *ghptr=NULL;
- if (ihb == hbHB)
- ghptr = hb->hbmap[id][ia]->h[ih];
- else if (ihb == hbDist)
- ghptr = hb->hbmap[id][ia]->g[ih];
- else
- gmx_fatal(FARGS,"Incomprehensible iValue %d in set_hb",ihb);
+ if (ihb == hbHB)
+ ghptr = hb->hbmap[id][ia]->h[ih];
+ else if (ihb == hbDist)
+ ghptr = hb->hbmap[id][ia]->g[ih];
+ else
+ gmx_fatal(FARGS,"Incomprehensible iValue %d in set_hb",ihb);
- _set_hb(ghptr,frame-hb->hbmap[id][ia]->n0,TRUE);
+ _set_hb(ghptr,frame-hb->hbmap[id][ia]->n0,TRUE);
}
-static void add_ff(t_hbdata *hbd,int id,int h,int ia,int frame,int ihb)
+static void addPshift(t_pShift *pHist, PSTYPE p, int frame)
{
- int i,j,n;
- t_hbond *hb = hbd->hbmap[id][ia];
- int maxhydro = hbd->d.nhydro[id];
- int wlen = hbd->wordlen;
- int delta = 32*wlen;
-
- if (!hb->h[0]) {
- hb->n0 = frame;
- hb->maxframes = delta;
- for(i=0; (i<maxhydro); i++) {
- snew(hb->h[i],hb->maxframes/wlen);
- snew(hb->g[i],hb->maxframes/wlen);
- }
- }
- else {
- hb->nframes = frame-hb->n0;
- /* We need a while loop here because hbonds may be returning
- * after a long time.
- */
- while (hb->nframes >= hb->maxframes) {
- n = hb->maxframes + delta;
- for(i=0; (i<maxhydro); i++) {
- srenew(hb->h[i],n/wlen);
- srenew(hb->g[i],n/wlen);
- for(j=hb->maxframes/wlen; (j<n/wlen); j++) {
- hb->h[i][j] = 0;
- hb->g[i][j] = 0;
- }
- }
- hb->maxframes = n;
- }
- }
- if (frame >= 0)
- set_hb(hbd,id,h,ia,frame,ihb);
- /*hb->nframes++;*/
+ if (pHist->len == 0) {
+ snew(pHist->frame, 1);
+ snew(pHist->p, 1);
+ pHist->len = 1;
+ pHist->frame[0] = frame;
+ pHist->p[0] = p;
+ return;
+ } else
+ if (pHist->p[pHist->len-1] != p) {
+ pHist->len++;
+ srenew(pHist->frame, pHist->len);
+ srenew(pHist->p, pHist->len);
+ pHist->frame[pHist->len-1] = frame;
+ pHist->p[pHist->len-1] = p;
+ } /* Otherwise, there is no transition. */
+ return;
+}
+
+static PSTYPE getPshift(t_pShift pHist, int frame)
+{
+ int f, i;
+
+ if (pHist.len == 0
+ || (pHist.len > 0 && pHist.frame[0]>frame))
+ return -1;
+
+ for (i=0; i<pHist.len; i++)
+ {
+ f = pHist.frame[i];
+ if (f==frame)
+ return pHist.p[i];
+ if (f>frame)
+ return pHist.p[i-1];
+ }
+
+ /* It seems that frame is after the last periodic transition. Return the last periodicity. */
+ return pHist.p[pHist.len-1];
+}
+
+static void add_ff(t_hbdata *hbd,int id,int h,int ia,int frame,int ihb, PSTYPE p)
+{
+ int i,j,n;
+ t_hbond *hb = hbd->hbmap[id][ia];
+ int maxhydro = min(hbd->maxhydro,hbd->d.nhydro[id]);
+ int wlen = hbd->wordlen;
+ int delta = 32*wlen;
+ bool bGem = hbd->bGem;
+
+ if (!hb->h[0]) {
+ hb->n0 = frame;
+ hb->maxframes = delta;
+ for(i=0; (i<maxhydro); i++) {
+ snew(hb->h[i],hb->maxframes/wlen);
+ snew(hb->g[i],hb->maxframes/wlen);
+ }
+ } else {
+ hb->nframes = frame-hb->n0;
+ /* We need a while loop here because hbonds may be returning
+ * after a long time.
+ */
+ while (hb->nframes >= hb->maxframes) {
+ n = hb->maxframes + delta;
+ for(i=0; (i<maxhydro); i++) {
+ srenew(hb->h[i],n/wlen);
+ srenew(hb->g[i],n/wlen);
+ for(j=hb->maxframes/wlen; (j<n/wlen); j++) {
+ hb->h[i][j] = 0;
+ hb->g[i][j] = 0;
+ }
+ }
+
+ hb->maxframes = n;
+ }
+ }
+ if (frame >= 0) {
+ set_hb(hbd,id,h,ia,frame,ihb);
+ if (bGem) {
+ if (p>=hbd->per->nper)
+ gmx_fatal(FARGS, "invalid shift: p=%u, nper=%u", p, hbd->per->nper);
+ else
+ addPshift(&(hbd->per->pHist[id][ia]), p, frame);
+
+ }
+ }
}
static void inc_nhbonds(t_donors *ddd,int d, int h)
{
- int j;
- int dptr = ddd->dptr[d];
-
- for(j=0; (j<ddd->nhydro[dptr]); j++)
- if (ddd->hydro[dptr][j] == h) {
- ddd->nhbonds[dptr][j]++;
- break;
- }
- if (j == ddd->nhydro[dptr])
- gmx_fatal(FARGS,"No such hydrogen %d on donor %d\n",h+1,d+1);
-}
-/* Added argument bContact. The reason may not be obvious,
- but when using -contacts all contacts are stored in h[],
- while contacts within -r2 (when provided) are stored in g[].
- Therefore bContact needs to be passed in order to prevent
- add_hbond from trying to deal with hydrogens.
- * - Erik Marklund, June 29, 2006
- */
-static void add_hbond(t_hbdata *hb,int d,int a,int h,int grpd,int grpa,
- int frame,bool bInsert,bool bMerge,int ihb,bool bContact)
-{
- int k,id,ia,hh;
-
- if ((id = hb->d.dptr[d]) == NOTSET)
- gmx_fatal(FARGS,"No donor atom %d",d+1);
- else if (grpd != hb->d.grp[id])
- gmx_fatal(FARGS,"Inconsistent donor groups, %d iso %d, atom %d",
- grpd,hb->d.grp[id],d+1);
- if ((ia = hb->a.aptr[a]) == NOTSET)
- gmx_fatal(FARGS,"No acceptor atom %d",a+1);
- else if (grpa != hb->a.grp[ia])
- gmx_fatal(FARGS,"Inconsistent acceptor groups, %d iso %d, atom %d",
- grpa,hb->a.grp[ia],a+1);
-
- if (hb->hbmap) {
- /* Loop over hydrogens to find which hydrogen is in this particular HB */
- if ((ihb == hbHB) && !bMerge && !bContact) {
- for(k=0; (k<hb->d.nhydro[id]); k++)
- if (hb->d.hydro[id][k] == h)
- break;
- if (k == hb->d.nhydro[id])
- gmx_fatal(FARGS,"Donor %d does not have hydrogen %d (a = %d)",
- d+1,h+1,a+1);
+ int j;
+ int dptr = ddd->dptr[d];
+
+ for(j=0; (j<ddd->nhydro[dptr]); j++)
+ if (ddd->hydro[dptr][j] == h) {
+ ddd->nhbonds[dptr][j]++;
+ break;
+ }
+ if (j == ddd->nhydro[dptr])
+ gmx_fatal(FARGS,"No such hydrogen %d on donor %d\n",h+1,d+1);
+}
+
+static int _acceptor_index(t_acceptors *a,int grp,atom_id i,
+ const char *file,int line)
+{
+ int ai = a->aptr[i];
+
+ if (a->grp[ai] != grp) {
+ if (debug && bDebug)
+ fprintf(debug,"Acc. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
+ ai,a->grp[ai],grp,file,line);
+ return NOTSET;
}
else
- k = 0;
-
- if (hb->bHBmap) {
- if (hb->hbmap[id][ia] == NULL) {
- snew(hb->hbmap[id][ia],1);
- snew(hb->hbmap[id][ia]->h,hb->maxhydro);
- snew(hb->hbmap[id][ia]->g,hb->maxhydro);
- }
- add_ff(hb,id,k,ia,frame,ihb);
+ return ai;
+}
+#define acceptor_index(a,grp,i) _acceptor_index(a,grp,i,__FILE__,__LINE__)
+
+static int _donor_index(t_donors *d,int grp,atom_id i,const char *file,int line)
+{
+ int di = d->dptr[i];
+
+ if (di == NOTSET)
+ return NOTSET;
+
+ if (d->grp[di] != grp) {
+ if (debug && bDebug)
+ fprintf(debug,"Don. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
+ di,d->grp[di],grp,file,line);
+ return NOTSET;
}
+ else
+ return di;
+}
+#define donor_index(d,grp,i) _donor_index(d,grp,i,__FILE__,__LINE__)
+
+static bool isInterchangable(t_hbdata *hb, int d, int a, int grpa, int grpd)
+{
+ /* g_hbond doesn't allow overlapping groups */
+ if (grpa!=grpd)
+ return FALSE;
+ return
+ donor_index(&hb->d,grpd,a) != NOTSET
+ && acceptor_index(&hb->a,grpa,d) != NOTSET;
+}
+
+
+static void add_hbond(t_hbdata *hb,int d,int a,int h,int grpd,int grpa,
+ int frame,bool bInsert,bool bMerge,int ihb,bool bContact, PSTYPE p)
+{
+ int k,id,ia,hh;
+ bool daSwap = FALSE;
+
+ if ((id = hb->d.dptr[d]) == NOTSET)
+ gmx_fatal(FARGS,"No donor atom %d",d+1);
+ else if (grpd != hb->d.grp[id])
+ gmx_fatal(FARGS,"Inconsistent donor groups, %d iso %d, atom %d",
+ grpd,hb->d.grp[id],d+1);
+ if ((ia = hb->a.aptr[a]) == NOTSET)
+ gmx_fatal(FARGS,"No acceptor atom %d",a+1);
+ else if (grpa != hb->a.grp[ia])
+ gmx_fatal(FARGS,"Inconsistent acceptor groups, %d iso %d, atom %d",
+ grpa,hb->a.grp[ia],a+1);
+
+ if (bMerge)
+ if ((daSwap = isInterchangable(hb, d, a, grpd, grpa) || bContact) && d>a)
+ /* Then swap identity so that the id of d is lower then that of a.
+ *
+ * This should really be redundant by now, as is_hbond() now ought to return
+ * hbNo in the cases where this conditional is TRUE. */
+ {
+ k = d;
+ d = a;
+ a = k;
+
+ /* Now repeat donor/acc check. */
+ if ((id = hb->d.dptr[d]) == NOTSET)
+ gmx_fatal(FARGS,"No donor atom %d",d+1);
+ else if (grpd != hb->d.grp[id])
+ gmx_fatal(FARGS,"Inconsistent donor groups, %d iso %d, atom %d",
+ grpd,hb->d.grp[id],d+1);
+ if ((ia = hb->a.aptr[a]) == NOTSET)
+ gmx_fatal(FARGS,"No acceptor atom %d",a+1);
+ else if (grpa != hb->a.grp[ia])
+ gmx_fatal(FARGS,"Inconsistent acceptor groups, %d iso %d, atom %d",
+ grpa,hb->a.grp[ia],a+1);
+ }
+
+ if (hb->hbmap) {
+ /* Loop over hydrogens to find which hydrogen is in this particular HB */
+ if ((ihb == hbHB) && !bMerge && !bContact) {
+ for(k=0; (k<hb->d.nhydro[id]); k++)
+ if (hb->d.hydro[id][k] == h)
+ break;
+ if (k == hb->d.nhydro[id])
+ gmx_fatal(FARGS,"Donor %d does not have hydrogen %d (a = %d)",
+ d+1,h+1,a+1);
+ }
+ else
+ k = 0;
- /* Strange construction with frame >=0 is a relic from old code
- * for selected hbond analysis. It may be necessary again if that
- * is made to work again.
- */
- if (frame >= 0) {
- hh = hb->hbmap[id][ia]->history[k];
- if (ihb == hbHB) {
- hb->nhb[frame]++;
- if (!(ISHB(hh))) {
- hb->hbmap[id][ia]->history[k] = hh | 2;
- hb->nrhb++;
- }
- }
- else if (ihb == hbDist) {
- hb->ndist[frame]++;
- if (!(ISDIST(hh))) {
- hb->hbmap[id][ia]->history[k] = hh | 1;
- hb->nrdist++;
- }
- }
- }
- } else {
- if (frame >= 0) {
- if (ihb == hbHB) {
- hb->nhb[frame]++;
- } else if (ihb == hbDist) {
- hb->ndist[frame]++;
- }
+ if (hb->bHBmap) {
+ if (hb->hbmap[id][ia] == NULL) {
+ snew(hb->hbmap[id][ia],1);
+ snew(hb->hbmap[id][ia]->h,hb->maxhydro);
+ snew(hb->hbmap[id][ia]->g,hb->maxhydro);
+ }
+ add_ff(hb,id,k,ia,frame,ihb,p);
+ }
+
+ /* Strange construction with frame >=0 is a relic from old code
+ * for selected hbond analysis. It may be necessary again if that
+ * is made to work again.
+ */
+ if (frame >= 0) {
+ hh = hb->hbmap[id][ia]->history[k];
+ if (ihb == hbHB) {
+ hb->nhb[frame]++;
+ if (!(ISHB(hh))) {
+ hb->hbmap[id][ia]->history[k] = hh | 2;
+ hb->nrhb++;
+ }
+ }
+ else
+ {
+ if (ihb == hbDist) {
+ hb->ndist[frame]++;
+ if (!(ISDIST(hh))) {
+ hb->hbmap[id][ia]->history[k] = hh | 1;
+ hb->nrdist++;
+ }
+ }
+ }
+ }
+ } else {
+ if (frame >= 0) {
+ if (ihb == hbHB) {
+ hb->nhb[frame]++;
+ } else {
+ if (ihb == hbDist) {
+ hb->ndist[frame]++;
+ }
+ }
+ }
}
- }
- /* Increment number if HBonds per H */
- if (ihb == hbHB && !bContact)
- inc_nhbonds(&(hb->d),d,h);
+ if (bMerge && daSwap)
+ h = hb->d.hydro[id][0];
+ /* Increment number if HBonds per H */
+ if (ihb == hbHB && !bContact)
+ inc_nhbonds(&(hb->d),d,h);
}
/* Now a redundant function. It might find use at some point though. */
static bool in_list(atom_id selection,int isize,atom_id *index)
{
- int i;
- bool bFound;
+ int i;
+ bool bFound;
- bFound=FALSE;
- for(i=0; (i<isize) && !bFound; i++)
- if(selection == index[i])
- bFound=TRUE;
+ bFound=FALSE;
+ for(i=0; (i<isize) && !bFound; i++)
+ if(selection == index[i])
+ bFound=TRUE;
- return bFound;
+ return bFound;
}
static char *mkatomname(t_atoms *atoms,int i)
{
- static char buf[32];
- int rnr;
+ static char buf[32];
+ int rnr;
- rnr = atoms->atom[i].resind;
- sprintf(buf,"%4s%d%-4s",
- *atoms->resinfo[rnr].name,atoms->resinfo[rnr].nr,*atoms->atomname[i]);
+ rnr = atoms->atom[i].resind;
+ sprintf(buf,"%4s%d%-4s",
+ *atoms->resinfo[rnr].name,atoms->resinfo[rnr].nr,*atoms->atomname[i]);
- return buf;
+ return buf;
}
static void gen_datable(atom_id *index, int isize, unsigned char *datable, int natoms){
- /* Generates table of all atoms and sets the ingroup bit for atoms in index[] */
- int i;
+ /* Generates table of all atoms and sets the ingroup bit for atoms in index[] */
+ int i;
- for (i=0; i<isize; i++){
- if (index[i] >= natoms)
- gmx_fatal(FARGS,"Atom has index %d larger than number of atoms %d.",index[i],natoms);
- datable[index[i]] |= INGROUP;
- }
+ for (i=0; i<isize; i++){
+ if (index[i] >= natoms)
+ gmx_fatal(FARGS,"Atom has index %d larger than number of atoms %d.",index[i],natoms);
+ datable[index[i]] |= INGROUP;
+ }
}
static void clear_datable_grp(unsigned char *datable, int size){
- /* Clears group information from the table */
- int i;
- const char mask = !(char)INGROUP;
- if (size > 0)
- for (i=0;i<size;i++)
- datable[i] &= mask;
+ /* Clears group information from the table */
+ int i;
+ const char mask = !(char)INGROUP;
+ if (size > 0)
+ for (i=0;i<size;i++)
+ datable[i] &= mask;
}
static void add_acc(t_acceptors *a,int ia,int grp)
{
- if (a->nra >= a->max_nra) {
- a->max_nra += 16;
- srenew(a->acc,a->max_nra);
- srenew(a->grp,a->max_nra);
- }
- a->grp[a->nra] = grp;
- a->acc[a->nra++] = ia;
+ if (a->nra >= a->max_nra) {
+ a->max_nra += 16;
+ srenew(a->acc,a->max_nra);
+ srenew(a->grp,a->max_nra);
+ }
+ a->grp[a->nra] = grp;
+ a->acc[a->nra++] = ia;
}
static void search_acceptors(t_topology *top,int isize,
- atom_id *index,t_acceptors *a,int grp,
- bool bNitAcc,
- bool bContact,bool bDoIt, unsigned char *datable)
-{
- int i,n;
-
- if (bDoIt) {
- for (i=0; (i<isize); i++) {
- n = index[i];
- if ((bContact ||
- (((*top->atoms.atomname[n])[0] == 'O') ||
- (bNitAcc && ((*top->atoms.atomname[n])[0] == 'N')))) &&
- ISINGRP(datable[n])) {
- datable[n] |= ACC; /* set the atom's acceptor flag in datable. */
- add_acc(a,n,grp);
- }
- }
- }
- snew(a->aptr,top->atoms.nr);
- for(i=0; (i<top->atoms.nr); i++)
- a->aptr[i] = NOTSET;
- for(i=0; (i<a->nra); i++)
- a->aptr[a->acc[i]] = i;
-}
-
-static int _acceptor_index(t_acceptors *a,int grp,atom_id i,
- const char *file,int line)
-{
- int ai = a->aptr[i];
-
- if (a->grp[ai] != grp) {
- if (debug && bDebug)
- fprintf(debug,"Acc. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
- ai,a->grp[ai],grp,file,line);
- return NOTSET;
- }
- else
- return ai;
-}
-#define acceptor_index(a,grp,i) _acceptor_index(a,grp,i,__FILE__,__LINE__)
-
-static int _donor_index(t_donors *d,int grp,atom_id i,const char *file,int line)
+ atom_id *index,t_acceptors *a,int grp,
+ bool bNitAcc,
+ bool bContact,bool bDoIt, unsigned char *datable)
{
- int di = d->dptr[i];
+ int i,n;
- if (d->grp[di] != grp) {
- if (debug && bDebug)
- fprintf(debug,"Don. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
- di,d->grp[di],grp,file,line);
- return NOTSET;
- }
- else
- return di;
+ if (bDoIt) {
+ for (i=0; (i<isize); i++) {
+ n = index[i];
+ if ((bContact ||
+ (((*top->atoms.atomname[n])[0] == 'O') ||
+ (bNitAcc && ((*top->atoms.atomname[n])[0] == 'N')))) &&
+ ISINGRP(datable[n])) {
+ datable[n] |= ACC; /* set the atom's acceptor flag in datable. */
+ add_acc(a,n,grp);
+ }
+ }
+ }
+ snew(a->aptr,top->atoms.nr);
+ for(i=0; (i<top->atoms.nr); i++)
+ a->aptr[i] = NOTSET;
+ for(i=0; (i<a->nra); i++)
+ a->aptr[a->acc[i]] = i;
}
-#define donor_index(d,grp,i) _donor_index(d,grp,i,__FILE__,__LINE__)
static void add_h2d(int id,int ih,t_donors *ddd)
{
- int i;
+ int i;
- for(i=0; (i<ddd->nhydro[id]); i++)
- if (ddd->hydro[id][i] == ih) {
- printf("Hm. This isn't first time I find this donor (%d,%d)\n",
- ddd->don[id],ih);
- break;
+ for(i=0; (i<ddd->nhydro[id]); i++)
+ if (ddd->hydro[id][i] == ih) {
+ printf("Hm. This isn't the first time I found this donor (%d,%d)\n",
+ ddd->don[id],ih);
+ break;
+ }
+ if (i == ddd->nhydro[id]) {
+ if (ddd->nhydro[id] >= MAXHYDRO)
+ gmx_fatal(FARGS,"Donor %d has more than %d hydrogens!",
+ ddd->don[id],MAXHYDRO);
+ ddd->hydro[id][i] = ih;
+ ddd->nhydro[id]++;
}
- if (i == ddd->nhydro[id]) {
- if (ddd->nhydro[id] >= MAXHYDRO)
- gmx_fatal(FARGS,"Donor %d has more than %d hydrogens!",
- ddd->don[id],MAXHYDRO);
- ddd->hydro[id][i] = ih;
- ddd->nhydro[id]++;
- }
}
static void add_dh(t_donors *ddd,int id,int ih,int grp, unsigned char *datable)
{
- int i;
-
- if (ISDON(datable[id]) || !datable) {
- if (ddd->dptr[id] == NOTSET) { /* New donor */
- i = ddd->nrd;
- ddd->dptr[id] = i;
- } else
- i = ddd->dptr[id];
-
- if (i == ddd->nrd) {
- if (ddd->nrd >= ddd->max_nrd) {
- ddd->max_nrd += 128;
- srenew(ddd->don,ddd->max_nrd);
- srenew(ddd->nhydro,ddd->max_nrd);
- srenew(ddd->hydro,ddd->max_nrd);
- srenew(ddd->nhbonds,ddd->max_nrd);
- srenew(ddd->grp,ddd->max_nrd);
- }
- ddd->don[ddd->nrd] = id;
- ddd->nhydro[ddd->nrd] = 0;
- ddd->grp[ddd->nrd] = grp;
- ddd->nrd++;
+ int i;
+
+ if (ISDON(datable[id]) || !datable) {
+ if (ddd->dptr[id] == NOTSET) { /* New donor */
+ i = ddd->nrd;
+ ddd->dptr[id] = i;
+ } else
+ i = ddd->dptr[id];
+
+ if (i == ddd->nrd) {
+ if (ddd->nrd >= ddd->max_nrd) {
+ ddd->max_nrd += 128;
+ srenew(ddd->don,ddd->max_nrd);
+ srenew(ddd->nhydro,ddd->max_nrd);
+ srenew(ddd->hydro,ddd->max_nrd);
+ srenew(ddd->nhbonds,ddd->max_nrd);
+ srenew(ddd->grp,ddd->max_nrd);
+ }
+ ddd->don[ddd->nrd] = id;
+ ddd->nhydro[ddd->nrd] = 0;
+ ddd->grp[ddd->nrd] = grp;
+ ddd->nrd++;
+ } else
+ ddd->don[i] = id;
+ add_h2d(i,ih,ddd);
} else
- ddd->don[i] = id;
- add_h2d(i,ih,ddd);
- } else
- if (datable)
- printf("Warning: Atom %d is not in the d/a-table!\n", id);
+ if (datable)
+ printf("Warning: Atom %d is not in the d/a-table!\n", id);
}
static void search_donors(t_topology *top, int isize, atom_id *index,
- t_donors *ddd,int grp,bool bContact,bool bDoIt,
- unsigned char *datable)
+ t_donors *ddd,int grp,bool bContact,bool bDoIt,
+ unsigned char *datable)
{
- int i,j,nra,n;
- t_functype func_type;
- t_ilist *interaction;
- atom_id nr1,nr2;
- bool stop;
-
- if (!ddd->dptr) {
- snew(ddd->dptr,top->atoms.nr);
- for(i=0; (i<top->atoms.nr); i++)
- ddd->dptr[i] = NOTSET;
- }
-
- if (bContact) {
- if (bDoIt)
- for(i=0; (i<isize); i++) {
- datable[index[i]] |= DON;
- add_dh(ddd,index[i],-1,grp,datable);
- }
- }
- else {
- for(func_type=0; (func_type < F_NRE); func_type++) {
- interaction=&(top->idef.il[func_type]);
- for(i=0; i < interaction->nr;
- i+=interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1) {
- /* next function */
- if (func_type != top->idef.functype[interaction->iatoms[i]]) {
- fprintf(stderr,"Error in func_type %s",
- interaction_function[func_type].longname);
- continue;
- }
+ int i,j,nra,n;
+ t_functype func_type;
+ t_ilist *interaction;
+ atom_id nr1,nr2;
+ bool stop;
+
+ if (!ddd->dptr) {
+ snew(ddd->dptr,top->atoms.nr);
+ for(i=0; (i<top->atoms.nr); i++)
+ ddd->dptr[i] = NOTSET;
+ }
+
+ if (bContact) {
+ if (bDoIt)
+ for(i=0; (i<isize); i++) {
+ datable[index[i]] |= DON;
+ add_dh(ddd,index[i],-1,grp,datable);
+ }
+ }
+ else {
+ for(func_type=0; (func_type < F_NRE); func_type++) {
+ interaction=&(top->idef.il[func_type]);
+ if (func_type == F_POSRES)
+ { /* The ilist looks strange for posre. Bug in grompp?
+ * We don't need posre interactions for hbonds anyway.*/
+ continue;
+ }
+ for(i=0; i < interaction->nr;
+ i+=interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1) {
+ /* next function */
+ if (func_type != top->idef.functype[interaction->iatoms[i]]) {
+ fprintf(stderr,"Error in func_type %s",
+ interaction_function[func_type].longname);
+ continue;
+ }
- /* check out this functype */
- if (func_type == F_SETTLE) {
- nr1=interaction->iatoms[i+1];
+ /* check out this functype */
+ if (func_type == F_SETTLE) {
+ nr1=interaction->iatoms[i+1];
- if (ISINGRP(datable[nr1])) {
- if (ISINGRP(datable[nr1+1])) {
- datable[nr1] |= DON;
- add_dh(ddd,nr1,nr1+1,grp,datable);
- }
- if (ISINGRP(datable[nr1+2])) {
- datable[nr1] |= DON;
- add_dh(ddd,nr1,nr1+2,grp,datable);
- }
- }
- }
- else if (IS_CHEMBOND(func_type)) {
- for (j=0; j<2; j++) {
- nr1=interaction->iatoms[i+1+j];
- nr2=interaction->iatoms[i+2-j];
- if ((*top->atoms.atomname[nr1][0] == 'H') &&
- ((*top->atoms.atomname[nr2][0] == 'O') ||
- (*top->atoms.atomname[nr2][0] == 'N')) &&
- ISINGRP(datable[nr1]) && ISINGRP(datable[nr2])) {
- datable[nr2] |= DON;
- add_dh(ddd,nr2,nr1,grp,datable);
- }
- }
- }
- }
- }
+ if (ISINGRP(datable[nr1])) {
+ if (ISINGRP(datable[nr1+1])) {
+ datable[nr1] |= DON;
+ add_dh(ddd,nr1,nr1+1,grp,datable);
+ }
+ if (ISINGRP(datable[nr1+2])) {
+ datable[nr1] |= DON;
+ add_dh(ddd,nr1,nr1+2,grp,datable);
+ }
+ }
+ }
+ else if (IS_CHEMBOND(func_type)) {
+ for (j=0; j<2; j++) {
+ nr1=interaction->iatoms[i+1+j];
+ nr2=interaction->iatoms[i+2-j];
+ if ((*top->atoms.atomname[nr1][0] == 'H') &&
+ ((*top->atoms.atomname[nr2][0] == 'O') ||
+ (*top->atoms.atomname[nr2][0] == 'N')) &&
+ ISINGRP(datable[nr1]) && ISINGRP(datable[nr2])) {
+ datable[nr2] |= DON;
+ add_dh(ddd,nr2,nr1,grp,datable);
+ }
+ }
+ }
+ }
+ }
#ifdef SAFEVSITES
- for(func_type=0; func_type < F_NRE; func_type++) {
- interaction=&top->idef.il[func_type];
- for(i=0; i < interaction->nr;
- i+=interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1) {
- /* next function */
- if (func_type != top->idef.functype[interaction->iatoms[i]])
- gmx_incons("function type in search_donors");
+ for(func_type=0; func_type < F_NRE; func_type++) {
+ interaction=&top->idef.il[func_type];
+ for(i=0; i < interaction->nr;
+ i+=interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1) {
+ /* next function */
+ if (func_type != top->idef.functype[interaction->iatoms[i]])
+ gmx_incons("function type in search_donors");
- if ( interaction_function[func_type].flags & IF_VSITE ) {
- nr1=interaction->iatoms[i+1];
- if ( *top->atoms.atomname[nr1][0] == 'H') {
- nr2=nr1-1;
- stop=FALSE;
- while (!stop && ( *top->atoms.atomname[nr2][0] == 'H'))
- if (nr2)
- nr2--;
- else
- stop=TRUE;
- if ( !stop && ( ( *top->atoms.atomname[nr2][0] == 'O') ||
- ( *top->atoms.atomname[nr2][0] == 'N') ) &&
- ISINGRP(datable[nr1]) && ISINGRP(datable[nr2])) {
- datable[nr2] |= DON;
- add_dh(ddd,nr2,nr1,grp,datable);
- }
- }
- }
- }
- }
+ if ( interaction_function[func_type].flags & IF_VSITE ) {
+ nr1=interaction->iatoms[i+1];
+ if ( *top->atoms.atomname[nr1][0] == 'H') {
+ nr2=nr1-1;
+ stop=FALSE;
+ while (!stop && ( *top->atoms.atomname[nr2][0] == 'H'))
+ if (nr2)
+ nr2--;
+ else
+ stop=TRUE;
+ if ( !stop && ( ( *top->atoms.atomname[nr2][0] == 'O') ||
+ ( *top->atoms.atomname[nr2][0] == 'N') ) &&
+ ISINGRP(datable[nr1]) && ISINGRP(datable[nr2])) {
+ datable[nr2] |= DON;
+ add_dh(ddd,nr2,nr1,grp,datable);
+ }
+ }
+ }
+ }
+ }
#endif
- }
+ }
}
static t_gridcell ***init_grid(bool bBox,rvec box[],real rcut,ivec ngrid)
{
- t_gridcell ***grid;
- int i,y,z;
-
- if (bBox)
- for(i=0; i<DIM; i++)
- ngrid[i]=(box[i][i]/(1.2*rcut));
-
- if ( !bBox || (ngrid[XX]<3) || (ngrid[YY]<3) || (ngrid[ZZ]<3) )
- for(i=0; i<DIM; i++)
- ngrid[i]=1;
- else
- printf("\nWill do grid-seach on %dx%dx%d grid, rcut=%g\n",
- ngrid[XX],ngrid[YY],ngrid[ZZ],rcut);
- snew(grid,ngrid[ZZ]);
- for (z=0; z<ngrid[ZZ]; z++) {
- snew((grid)[z],ngrid[YY]);
- for (y=0; y<ngrid[YY]; y++)
- snew((grid)[z][y],ngrid[XX]);
- }
- return grid;
+ t_gridcell ***grid;
+ int i,y,z;
+
+ if (bBox)
+ for(i=0; i<DIM; i++)
+ ngrid[i]=(box[i][i]/(1.2*rcut));
+
+ if ( !bBox || (ngrid[XX]<3) || (ngrid[YY]<3) || (ngrid[ZZ]<3) )
+ for(i=0; i<DIM; i++)
+ ngrid[i]=1;
+ else
+ printf("\nWill do grid-seach on %dx%dx%d grid, rcut=%g\n",
+ ngrid[XX],ngrid[YY],ngrid[ZZ],rcut);
+ snew(grid,ngrid[ZZ]);
+ for (z=0; z<ngrid[ZZ]; z++) {
+ snew((grid)[z],ngrid[YY]);
+ for (y=0; y<ngrid[YY]; y++)
+ snew((grid)[z][y],ngrid[XX]);
+ }
+ return grid;
+}
+
+static void control_pHist(t_hbdata *hb, int nframes)
+{
+ int i,j,k;
+ PSTYPE p;
+ for (i=0;i<hb->d.nrd;i++)
+ for (j=0;j<hb->a.nra;j++)
+ if (hb->per->pHist[i][j].len != 0)
+ for (k=hb->hbmap[i][j][0].n0; k<nframes; k++) {
+ p = getPshift(hb->per->pHist[i][j], k);
+ if (p>hb->per->nper)
+ fprintf(stderr, "Weird stuff in pHist[%i][%i].p at frame %i: p=%i\n",
+ i,j,k,p);
+ }
}
static void reset_nhbonds(t_donors *ddd)
{
- int i,j;
+ int i,j;
- for(i=0; (i<ddd->nrd); i++)
- for(j=0; (j<MAXHH); j++)
- ddd->nhbonds[i][j] = 0;
+ for(i=0; (i<ddd->nrd); i++)
+ for(j=0; (j<MAXHH); j++)
+ ddd->nhbonds[i][j] = 0;
}
+void pbc_correct_gem(rvec dx,matrix box,rvec hbox);
+
static void build_grid(t_hbdata *hb,rvec x[], rvec xshell,
- bool bBox, matrix box, rvec hbox,
- real rcut, real rshell,
- ivec ngrid, t_gridcell ***grid)
+ bool bBox, matrix box, rvec hbox,
+ real rcut, real rshell,
+ ivec ngrid, t_gridcell ***grid)
{
- int i,m,gr,xi,yi,zi,nr;
- atom_id *ad;
- ivec grididx;
- rvec invdelta,dshell;
- t_ncell *newgrid;
- bool bDoRshell,bInShell,bAcc;
- real rshell2=0;
- int gx,gy,gz;
- int dum = -1;
-
- bDoRshell = (rshell > 0);
- rshell2 = sqr(rshell);
- bInShell = TRUE;
+ int i,m,gr,xi,yi,zi,nr;
+ atom_id *ad;
+ ivec grididx;
+ rvec invdelta,dshell,xtemp={0,0,0};
+ t_ncell *newgrid;
+ bool bDoRshell,bInShell,bAcc;
+ real rshell2=0;
+ int gx,gy,gz;
+ int dum = -1;
+
+ bDoRshell = (rshell > 0);
+ rshell2 = sqr(rshell);
+ bInShell = TRUE;
#define DBB(x) if (debug && bDebug) fprintf(debug,"build_grid, line %d, %s = %d\n",__LINE__,#x,x)
- DBB(dum);
- for(m=0; m<DIM; m++) {
- hbox[m]=box[m][m]*0.5;
- if (bBox) {
- invdelta[m]=ngrid[m]/box[m][m];
- if (1/invdelta[m] < rcut)
- gmx_fatal(FARGS,"Your computational box has shrunk too much.\n"
- "%s can not handle this situation, sorry.\n",
- ShortProgram());
- } else
- invdelta[m]=0;
- }
- grididx[XX]=0;
- grididx[YY]=0;
- grididx[ZZ]=0;
- DBB(dum);
- /* resetting atom counts */
- for(gr=0; (gr<grNR); gr++) {
- for (zi=0; zi<ngrid[ZZ]; zi++)
- for (yi=0; yi<ngrid[YY]; yi++)
- for (xi=0; xi<ngrid[XX]; xi++) {
- grid[zi][yi][xi].d[gr].nr=0;
- grid[zi][yi][xi].a[gr].nr=0;
- }
DBB(dum);
+ for(m=0; m<DIM; m++) {
+ hbox[m]=box[m][m]*0.5;
+ if (bBox) {
+ invdelta[m]=ngrid[m]/box[m][m];
+ if (1/invdelta[m] < rcut)
+ gmx_fatal(FARGS,"Your computational box has shrunk too much.\n"
+ "%s can not handle this situation, sorry.\n",
+ ShortProgram());
+ } else
+ invdelta[m]=0;
+ }
+ grididx[XX]=0;
+ grididx[YY]=0;
+ grididx[ZZ]=0;
+ DBB(dum);
+ /* resetting atom counts */
+ for(gr=0; (gr<grNR); gr++) {
+ for (zi=0; zi<ngrid[ZZ]; zi++)
+ for (yi=0; yi<ngrid[YY]; yi++)
+ for (xi=0; xi<ngrid[XX]; xi++) {
+ grid[zi][yi][xi].d[gr].nr=0;
+ grid[zi][yi][xi].a[gr].nr=0;
+ }
+ DBB(dum);
- /* put atoms in grid cells */
- for(bAcc=FALSE; (bAcc<=TRUE); bAcc++) {
- if (bAcc) {
- nr = hb->a.nra;
- ad = hb->a.acc;
- }
- else {
- nr = hb->d.nrd;
- ad = hb->d.don;
- }
- DBB(bAcc);
- for(i=0; (i<nr); i++) {
- /* check if we are inside the shell */
- /* if bDoRshell=FALSE then bInShell=TRUE always */
- DBB(i);
- if ( bDoRshell ) {
- bInShell=TRUE;
- rvec_sub(x[ad[i]],xshell,dshell);
- if (bBox)
- for(m=DIM-1; m>=0 && bInShell; m--) {
- if ( dshell[m] < -hbox[m] )
- rvec_inc(dshell,box[m]);
- else if ( dshell[m] >= hbox[m] )
- dshell[m] -= 2*hbox[m];
- /* if we're outside the cube, we're outside the sphere also! */
- if ( (dshell[m]>rshell) || (-dshell[m]>rshell) )
- bInShell=FALSE;
- }
- /* if we're inside the cube, check if we're inside the sphere */
- if (bInShell)
- bInShell = norm2(dshell) < rshell2;
- }
- DBB(i);
- if ( bInShell ) {
- if (bBox)
- for(m=DIM-1; m>=0; m--) {
- /* put atom in the box */
- while( x[ad[i]][m] < 0 )
- rvec_inc(x[ad[i]],box[m]);
- while( x[ad[i]][m] >= box[m][m] )
- rvec_dec(x[ad[i]],box[m]);
- /* determine grid index of atom */
- grididx[m]=x[ad[i]][m]*invdelta[m];
- grididx[m] = (grididx[m]+ngrid[m]) % ngrid[m];
- }
- gx = grididx[XX];
- gy = grididx[YY];
- gz = grididx[ZZ];
- range_check(gx,0,ngrid[XX]);
- range_check(gy,0,ngrid[YY]);
- range_check(gz,0,ngrid[ZZ]);
- DBB(gx);
- DBB(gy);
- DBB(gz);
- /* add atom to grid cell */
- if (bAcc)
- newgrid=&(grid[gz][gy][gx].a[gr]);
- else
- newgrid=&(grid[gz][gy][gx].d[gr]);
- if (newgrid->nr >= newgrid->maxnr) {
- newgrid->maxnr+=10;
- DBB(newgrid->maxnr);
- srenew(newgrid->atoms, newgrid->maxnr);
- }
- DBB(newgrid->nr);
- newgrid->atoms[newgrid->nr]=ad[i];
- newgrid->nr++;
- }
- }
- }
- }
+ /* put atoms in grid cells */
+ for(bAcc=FALSE; (bAcc<=TRUE); bAcc++) {
+ if (bAcc) {
+ nr = hb->a.nra;
+ ad = hb->a.acc;
+ }
+ else {
+ nr = hb->d.nrd;
+ ad = hb->d.don;
+ }
+ DBB(bAcc);
+ for(i=0; (i<nr); i++) {
+ /* check if we are inside the shell */
+ /* if bDoRshell=FALSE then bInShell=TRUE always */
+ DBB(i);
+ if ( bDoRshell ) {
+ bInShell=TRUE;
+ rvec_sub(x[ad[i]],xshell,dshell);
+ if (bBox) {
+ if (FALSE && !hb->bGem) {
+ for(m=DIM-1; m>=0 && bInShell; m--) {
+ if ( dshell[m] < -hbox[m] )
+ rvec_inc(dshell,box[m]);
+ else if ( dshell[m] >= hbox[m] )
+ dshell[m] -= 2*hbox[m];
+ /* if we're outside the cube, we're outside the sphere also! */
+ if ( (dshell[m]>rshell) || (-dshell[m]>rshell) )
+ bInShell=FALSE;
+ }
+ } else {
+ bool bDone = FALSE;
+ while (!bDone)
+ {
+ bDone = TRUE;
+ for(m=DIM-1; m>=0 && bInShell; m--) {
+ if ( dshell[m] < -hbox[m] ) {
+ bDone = FALSE;
+ rvec_inc(dshell,box[m]);
+ }
+ if ( dshell[m] >= hbox[m] ) {
+ bDone = FALSE;
+ dshell[m] -= 2*hbox[m];
+ }
+ }
+ }
+ for(m=DIM-1; m>=0 && bInShell; m--) {
+ /* if we're outside the cube, we're outside the sphere also! */
+ if ( (dshell[m]>rshell) || (-dshell[m]>rshell) )
+ bInShell=FALSE;
+ }
+ }
+ }
+ /* if we're inside the cube, check if we're inside the sphere */
+ if (bInShell)
+ bInShell = norm2(dshell) < rshell2;
+ }
+ DBB(i);
+ if ( bInShell ) {
+ if (bBox) {
+ if (hb->bGem)
+ copy_rvec(x[ad[i]], xtemp);
+ pbc_correct_gem(x[ad[i]], box, hbox);
+ }
+ for(m=DIM-1; m>=0; m--) {
+ if (TRUE || !hb->bGem){
+ /* put atom in the box */
+ while( x[ad[i]][m] < 0 )
+ rvec_inc(x[ad[i]],box[m]);
+ while( x[ad[i]][m] >= box[m][m] )
+ rvec_dec(x[ad[i]],box[m]);
+ }
+ /* determine grid index of atom */
+ grididx[m]=x[ad[i]][m]*invdelta[m];
+ grididx[m] = (grididx[m]+ngrid[m]) % ngrid[m];
+ }
+ if (hb->bGem)
+ copy_rvec(xtemp, x[ad[i]]); /* copy back */
+ gx = grididx[XX];
+ gy = grididx[YY];
+ gz = grididx[ZZ];
+ range_check(gx,0,ngrid[XX]);
+ range_check(gy,0,ngrid[YY]);
+ range_check(gz,0,ngrid[ZZ]);
+ DBB(gx);
+ DBB(gy);
+ DBB(gz);
+ /* add atom to grid cell */
+ if (bAcc)
+ newgrid=&(grid[gz][gy][gx].a[gr]);
+ else
+ newgrid=&(grid[gz][gy][gx].d[gr]);
+ if (newgrid->nr >= newgrid->maxnr) {
+ newgrid->maxnr+=10;
+ DBB(newgrid->maxnr);
+ srenew(newgrid->atoms, newgrid->maxnr);
+ }
+ DBB(newgrid->nr);
+ newgrid->atoms[newgrid->nr]=ad[i];
+ newgrid->nr++;
+ }
+ }
+ }
+ }
}
static void count_da_grid(ivec ngrid, t_gridcell ***grid, t_icell danr)
{
- int gr,xi,yi,zi;
+ int gr,xi,yi,zi;
- for(gr=0; (gr<grNR); gr++) {
- danr[gr]=0;
- for (zi=0; zi<ngrid[ZZ]; zi++)
- for (yi=0; yi<ngrid[YY]; yi++)
- for (xi=0; xi<ngrid[XX]; xi++) {
- danr[gr] += grid[zi][yi][xi].d[gr].nr;
- }
- }
+ for(gr=0; (gr<grNR); gr++) {
+ danr[gr]=0;
+ for (zi=0; zi<ngrid[ZZ]; zi++)
+ for (yi=0; yi<ngrid[YY]; yi++)
+ for (xi=0; xi<ngrid[XX]; xi++) {
+ danr[gr] += grid[zi][yi][xi].d[gr].nr;
+ }
+ }
}
/* The grid loop.
#define B(n,x,bTric,bEdge) ((n==1) ? x : bTric&&(bEdge) ? 0 : (x-1))
#define E(n,x,bTric,bEdge) ((n==1) ? x : bTric&&(bEdge) ? n-1 : (x+1))
#define GRIDMOD(j,n) (j+n)%(n)
-#define LOOPGRIDINNER(x,y,z,xx,yy,zz,xo,yo,zo,n,bTric)\
- for(zz=B(n[ZZ],zo,bTric,FALSE); zz<=E(n[ZZ],zo,bTric,FALSE); zz++) {\
- z=GRIDMOD(zz,n[ZZ]);\
- for(yy=B(n[YY],yo,bTric,z==0||z==n[ZZ]-1); \
- yy<=E(n[YY],yo,bTric,z==0||z==n[ZZ]-1); yy++) {\
- y=GRIDMOD(yy,n[YY]);\
- for(xx=B(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1); \
- xx<=E(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1); xx++) {\
- x=GRIDMOD(xx,n[XX]);
-#define ENDLOOPGRIDINNER\
- }\
- }\
- }\
+#define LOOPGRIDINNER(x,y,z,xx,yy,zz,xo,yo,zo,n,bTric) \
+ for(zz=B(n[ZZ],zo,bTric,FALSE); zz<=E(n[ZZ],zo,bTric,FALSE); zz++) { \
+ z=GRIDMOD(zz,n[ZZ]); \
+ for(yy=B(n[YY],yo,bTric,z==0||z==n[ZZ]-1); \
+ yy<=E(n[YY],yo,bTric,z==0||z==n[ZZ]-1); yy++) { \
+ y=GRIDMOD(yy,n[YY]); \
+ for(xx=B(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1); \
+ xx<=E(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1); xx++) { \
+ x=GRIDMOD(xx,n[XX]);
+#define ENDLOOPGRIDINNER \
+ } \
+ } \
+ } \
+ \
static void dump_grid(FILE *fp, ivec ngrid, t_gridcell ***grid)
{
- int gr,x,y,z,sum[grNR];
-
- fprintf(fp,"grid %dx%dx%d\n",ngrid[XX],ngrid[YY],ngrid[ZZ]);
- for (gr=0; gr<grNR; gr++) {
- sum[gr]=0;
- fprintf(fp,"GROUP %d (%s)\n",gr,grpnames[gr]);
- for (z=0; z<ngrid[ZZ]; z+=2) {
- fprintf(fp,"Z=%d,%d\n",z,z+1);
- for (y=0; y<ngrid[YY]; y++) {
- for (x=0; x<ngrid[XX]; x++) {
- fprintf(fp,"%3d",grid[x][y][z].d[gr].nr);
- sum[gr]+=grid[z][y][x].d[gr].nr;
- fprintf(fp,"%3d",grid[x][y][z].a[gr].nr);
- sum[gr]+=grid[z][y][x].a[gr].nr;
+ int gr,x,y,z,sum[grNR];
+
+ fprintf(fp,"grid %dx%dx%d\n",ngrid[XX],ngrid[YY],ngrid[ZZ]);
+ for (gr=0; gr<grNR; gr++) {
+ sum[gr]=0;
+ fprintf(fp,"GROUP %d (%s)\n",gr,grpnames[gr]);
+ for (z=0; z<ngrid[ZZ]; z+=2) {
+ fprintf(fp,"Z=%d,%d\n",z,z+1);
+ for (y=0; y<ngrid[YY]; y++) {
+ for (x=0; x<ngrid[XX]; x++) {
+ fprintf(fp,"%3d",grid[x][y][z].d[gr].nr);
+ sum[gr]+=grid[z][y][x].d[gr].nr;
+ fprintf(fp,"%3d",grid[x][y][z].a[gr].nr);
+ sum[gr]+=grid[z][y][x].a[gr].nr;
- }
- fprintf(fp," | ");
- if ( (z+1) < ngrid[ZZ] )
- for (x=0; x<ngrid[XX]; x++) {
- fprintf(fp,"%3d",grid[z+1][y][x].d[gr].nr);
- sum[gr]+=grid[z+1][y][x].d[gr].nr;
- fprintf(fp,"%3d",grid[z+1][y][x].a[gr].nr);
- sum[gr]+=grid[z+1][y][x].a[gr].nr;
- }
- fprintf(fp,"\n");
- }
- }
- }
- fprintf(fp,"TOTALS:");
- for (gr=0; gr<grNR; gr++)
- fprintf(fp," %d=%d",gr,sum[gr]);
- fprintf(fp,"\n");
+ }
+ fprintf(fp," | ");
+ if ( (z+1) < ngrid[ZZ] )
+ for (x=0; x<ngrid[XX]; x++) {
+ fprintf(fp,"%3d",grid[z+1][y][x].d[gr].nr);
+ sum[gr]+=grid[z+1][y][x].d[gr].nr;
+ fprintf(fp,"%3d",grid[z+1][y][x].a[gr].nr);
+ sum[gr]+=grid[z+1][y][x].a[gr].nr;
+ }
+ fprintf(fp,"\n");
+ }
+ }
+ }
+ fprintf(fp,"TOTALS:");
+ for (gr=0; gr<grNR; gr++)
+ fprintf(fp," %d=%d",gr,sum[gr]);
+ fprintf(fp,"\n");
}
/* New GMX record! 5 * in a row. Congratulations!
*/
static void free_grid(ivec ngrid, t_gridcell ****grid)
{
- int y,z;
- t_gridcell ***g = *grid;
+ int y,z;
+ t_gridcell ***g = *grid;
- for (z=0; z<ngrid[ZZ]; z++) {
- for (y=0; y<ngrid[YY]; y++) {
- sfree(g[z][y]);
+ for (z=0; z<ngrid[ZZ]; z++) {
+ for (y=0; y<ngrid[YY]; y++) {
+ sfree(g[z][y]);
+ }
+ sfree(g[z]);
}
- sfree(g[z]);
- }
- sfree(g);
- g=NULL;
+ sfree(g);
+ g=NULL;
}
static void pbc_correct(rvec dx,matrix box,rvec hbox)
{
- int m;
-
- for(m=DIM-1; m>=0; m--) {
- if ( dx[m] < -hbox[m] )
- rvec_inc(dx,box[m]);
- else if ( dx[m] >= hbox[m] )
- rvec_dec(dx,box[m]);
- }
+ int m;
+ for(m=DIM-1; m>=0; m--) {
+ if ( dx[m] < -hbox[m] )
+ rvec_inc(dx,box[m]);
+ else if ( dx[m] >= hbox[m] )
+ rvec_dec(dx,box[m]);
+ }
+}
+
+void pbc_correct_gem(rvec dx,matrix box,rvec hbox)
+{
+ int m;
+ bool bDone = FALSE;
+ while (!bDone) {
+ bDone = TRUE;
+ for(m=DIM-1; m>=0; m--) {
+ if ( dx[m] < -hbox[m] ) {
+ bDone = FALSE;
+ rvec_inc(dx,box[m]);
+ }
+ if ( dx[m] >= hbox[m] ) {
+ bDone = FALSE;
+ rvec_dec(dx,box[m]);
+ }
+ }
+ }
}
/* Added argument r2cut, changed contact and implemented
* - Erik Marklund, June 29, 2006
*/
static int is_hbond(t_hbdata *hb,int grpd,int grpa,int d,int a,
- real rcut, real r2cut, real ccut,
- rvec x[], bool bBox, matrix box,rvec hbox,
- real *d_ha, real *ang,bool bDA,int *hhh,
- bool bContact)
+ real rcut, real r2cut, real ccut,
+ rvec x[], bool bBox, matrix box,rvec hbox,
+ real *d_ha, real *ang,bool bDA,int *hhh,
+ bool bContact, bool bMerge, PSTYPE *p)
{
- int h,hh,id,ja,ihb;
- rvec r_da,r_ha,r_dh;
- real rc2,r2c2,rda2,rha2,ca;
- bool HAinrange = FALSE; /* If !bDA. Needed for returning hbDist in a correct way. */
-
- if (d == a)
- return hbNo;
-
- if (((id = donor_index(&hb->d,grpd,d)) == NOTSET) ||
- ((ja = acceptor_index(&hb->a,grpa,a)) == NOTSET))
- return hbNo;
-
- rc2 = rcut*rcut;
- r2c2 = r2cut*r2cut;
-
- rvec_sub(x[d],x[a],r_da);
- if (bBox)
- pbc_correct(r_da,box,hbox);
- rda2 = iprod(r_da,r_da);
-
- if (bContact) {
- if (rda2 <= rc2)
- return hbHB;
- else if (rda2 < r2c2)
- return hbDist;
- else
- return hbNo;
- }
- *hhh = NOTSET;
-
- if (bDA && (rda2 > rc2))
- return hbNo;
-
- for(h=0; (h < hb->d.nhydro[id]); h++) {
- hh = hb->d.hydro[id][h];
- rha2 = rc2+1;
- if (!bDA) {
- rvec_sub(x[hh],x[a],r_ha);
- if (bBox)
- pbc_correct(r_ha,box,hbox);
- rha2 = iprod(r_ha,r_ha);
+ int h,hh,id,ja,ihb;
+ rvec r_da,r_ha,r_dh, r={0, 0, 0};
+ ivec ri;
+ real rc2,r2c2,rda2,rha2,ca;
+ bool HAinrange = FALSE; /* If !bDA. Needed for returning hbDist in a correct way. */
+ bool daSwap = FALSE;
+
+ if (d == a)
+ return hbNo;
+
+ if (((id = donor_index(&hb->d,grpd,d)) == NOTSET) ||
+ ((ja = acceptor_index(&hb->a,grpa,a)) == NOTSET))
+ return hbNo;
+
+ rc2 = rcut*rcut;
+ r2c2 = r2cut*r2cut;
+
+ rvec_sub(x[d],x[a],r_da);
+ /* Insert projection code here */
+
+ /* if (d>a && ((isInterchangable(hb, d, a, grpd, grpa) && bMerge) || bContact)) */
+/* /\* Then this hbond will be found again, or it has already been found. *\/ */
+/* return hbNo; */
+
+ if (bBox){
+ if (d>a && bMerge && (bContact || isInterchangable(hb, d, a, grpd, grpa))) { /* acceptor is also a donor and vice versa? */
+ return hbNo;
+ daSwap = TRUE; /* If so, then their history should be filed with donor and acceptor swapped. */
+ }
+ if (hb->bGem) {
+ copy_rvec(r_da, r); /* Save this for later */
+ pbc_correct_gem(r_da,box,hbox);
+ } else {
+ pbc_correct_gem(r_da,box,hbox);
+ }
}
- if (bBox)
- pbc_correct(r_da,box,hbox);
-
- if (bDA || (!bDA && (rha2 <= rc2))) {
- rvec_sub(x[d],x[hh],r_dh);
- if (bBox)
- pbc_correct(r_dh,box,hbox);
- if (!bDA)
- HAinrange = TRUE;
- ca = cos_angle(r_dh,r_da);
- /* if angle is smaller, cos is larger */
- if (ca >= ccut) {
- *hhh = hh;
- *d_ha = sqrt(bDA?rda2:rha2);
- *ang = acos(ca);
- return hbHB;
- }
- }
- }
- if (bDA || (!bDA && HAinrange))
- return hbDist;
- else
- return hbNo;
+ rda2 = iprod(r_da,r_da);
+
+ if (bContact) {
+ if (daSwap)
+ return hbNo;
+ if (rda2 <= rc2){
+ if (hb->bGem){
+ calcBoxDistance(hb->per->P, r, ri);
+ *p = periodicIndex(ri, hb->per, daSwap); /* find (or add) periodicity index. */
+ }
+ return hbHB;
+ }
+ else if (rda2 < r2c2)
+ return hbDist;
+ else
+ return hbNo;
+ }
+ *hhh = NOTSET;
+
+ if (bDA && (rda2 > rc2))
+ return hbNo;
+
+ for(h=0; (h < hb->d.nhydro[id]); h++) {
+ hh = hb->d.hydro[id][h];
+ rha2 = rc2+1;
+ if (!bDA) {
+ rvec_sub(x[hh],x[a],r_ha);
+ if (bBox) {
+ pbc_correct_gem(r_ha,box,hbox);
+ }
+ rha2 = iprod(r_ha,r_ha);
+ }
+
+ if (hb->bGem) {
+ calcBoxDistance(hb->per->P, r, ri);
+ *p = periodicIndex(ri, hb->per, daSwap); /* find periodicity index. */
+ }
+
+ if (bDA || (!bDA && (rha2 <= rc2))) {
+ rvec_sub(x[d],x[hh],r_dh);
+ if (bBox) {
+ if (hb->bGem)
+ pbc_correct_gem(r_dh,box,hbox);
+ else
+ pbc_correct_gem(r_dh,box,hbox);
+ }
+
+ if (!bDA)
+ HAinrange = TRUE;
+ ca = cos_angle(r_dh,r_da);
+ /* if angle is smaller, cos is larger */
+ if (ca >= ccut) {
+ *hhh = hh;
+ *d_ha = sqrt(bDA?rda2:rha2);
+ *ang = acos(ca);
+ return hbHB;
+ }
+ }
+ }
+ if (bDA || (!bDA && HAinrange))
+ return hbDist;
+ else
+ return hbNo;
}
/* Fixed previously undiscovered bug in the merge
code, where the last frame of each hbond disappears.
- Erik Marklund, June 1, 2006 */
+/* Added the following arguments:
+ * ptmp[] - temporary periodicity hisory
+ * a1 - identity of first acceptor/donor
+ * a2 - identity of second acceptor/donor
+ * - Erik Marklund, FEB 20 2010 */
+
+/* Merging is now done on the fly, so do_merge is most likely obsolete now.
+ * Will do some more testing before removing the function entirely.
+ * - Erik Marklund, MAY 10 2010 */
static void do_merge(t_hbdata *hb,int ntmp,
- unsigned int htmp[],unsigned int gtmp[],
- t_hbond *hb0,t_hbond *hb1)
+ unsigned int htmp[],unsigned int gtmp[],PSTYPE ptmp[],
+ t_hbond *hb0,t_hbond *hb1, int a1, int a2)
{
- int m,mm,n00,n01,nn0,nnframes;
- /* Decide where to start from when merging */
- n00 = hb0->n0;
- n01 = hb1->n0;
- nn0 = min(n00,n01);
- nnframes = max(n00 + hb0->nframes,n01 + hb1->nframes) - nn0;
- /* Initiate tmp arrays */
- for(m=0; (m<ntmp); m++) {
- htmp[m] = 0;
- gtmp[m] = 0;
- }
- /* Fill tmp arrays with values due to first HB */
- /* Once again '<' had to be replaced with '<='
- to catch the last frame in which the hbond
- appears.
- - Erik Marklund, June 1, 2006 */
- for(m=0; (m<=hb0->nframes); m++) {
- mm = m+n00-nn0;
- htmp[mm] = is_hb(hb0->h[0],m);
- gtmp[mm] = is_hb(hb0->g[0],m);
- }
- /* Next HB */
- for(m=0; (m<=hb1->nframes); m++) {
- mm = m+n01-nn0;
- htmp[mm] = htmp[mm] || is_hb(hb1->h[0],m);
- gtmp[mm] = gtmp[mm] || is_hb(hb1->g[0],m);
- }
- /* Reallocate target array */
- if (nnframes > hb0->maxframes) {
- srenew(hb0->h[0],4+nnframes/hb->wordlen);
- srenew(hb0->g[0],4+nnframes/hb->wordlen);
- }
- /* Copy temp array to target array */
- for(m=0; (m<=nnframes); m++) {
- _set_hb(hb0->h[0],m,htmp[m]);
- _set_hb(hb0->g[0],m,gtmp[m]);
- }
- /* Set scalar variables */
- hb0->n0 = nn0;
- hb0->maxframes = nnframes;
+ /* Here we need to make sure we're treating periodicity in
+ * the right way for the geminate recombination kinetics. */
+
+ int m,mm,n00,n01,nn0,nnframes;
+ PSTYPE pm;
+ t_pShift *pShift;
+
+ /* Decide where to start from when merging */
+ n00 = hb0->n0;
+ n01 = hb1->n0;
+ nn0 = min(n00,n01);
+ nnframes = max(n00 + hb0->nframes,n01 + hb1->nframes) - nn0;
+ /* Initiate tmp arrays */
+ for(m=0; (m<ntmp); m++) {
+ htmp[m] = 0;
+ gtmp[m] = 0;
+ ptmp[m] = 0;
+ }
+ /* Fill tmp arrays with values due to first HB */
+ /* Once again '<' had to be replaced with '<='
+ to catch the last frame in which the hbond
+ appears.
+ - Erik Marklund, June 1, 2006 */
+ for(m=0; (m<=hb0->nframes); m++) {
+ mm = m+n00-nn0;
+ htmp[mm] = is_hb(hb0->h[0],m);
+ if (hb->bGem) {
+ pm = getPshift(hb->per->pHist[a1][a2], m+hb0->n0);
+ if (pm > hb->per->nper)
+ gmx_fatal(FARGS, "Illegal shift!");
+ else
+ ptmp[mm] = pm; /*hb->per->pHist[a1][a2][m];*/
+ }
+ }
+ /* If we're doing geminate recompbination we usually don't need the distances.
+ * Let's save some memory and time. */
+ if (TRUE || !hb->bGem || hb->per->gemtype == gemAD){
+ for(m=0; (m<=hb0->nframes); m++) {
+ mm = m+n00-nn0;
+ gtmp[mm] = is_hb(hb0->g[0],m);
+ }
+ }
+ /* Next HB */
+ for(m=0; (m<=hb1->nframes); m++) {
+ mm = m+n01-nn0;
+ htmp[mm] = htmp[mm] || is_hb(hb1->h[0],m);
+ gtmp[mm] = gtmp[mm] || is_hb(hb1->g[0],m);
+ if (hb->bGem /* && ptmp[mm] != 0 */) {
+
+ /* If this hbond has been seen before with donor and acceptor swapped,
+ * then we need to find the mirrored (*-1) periodicity vector to truely
+ * merge the hbond history. */
+ pm = findMirror(getPshift(hb->per->pHist[a2][a1],m+hb1->n0), hb->per->p2i, hb->per->nper);
+ /* Store index of mirror */
+ if (pm > hb->per->nper)
+ gmx_fatal(FARGS, "Illegal shift!");
+ ptmp[mm] = pm;
+ }
+ }
+ /* Reallocate target array */
+ if (nnframes > hb0->maxframes) {
+ srenew(hb0->h[0],4+nnframes/hb->wordlen);
+ srenew(hb0->g[0],4+nnframes/hb->wordlen);
+ }
+ clearPshift(&(hb->per->pHist[a1][a2]));
+
+ /* Copy temp array to target array */
+ for(m=0; (m<=nnframes); m++) {
+ _set_hb(hb0->h[0],m,htmp[m]);
+ _set_hb(hb0->g[0],m,gtmp[m]);
+ if (hb->bGem)
+ addPshift(&(hb->per->pHist[a1][a2]), ptmp[m], m+nn0);
+ }
+
+ /* Set scalar variables */
+ hb0->n0 = nn0;
+ hb0->maxframes = nnframes;
}
/* Added argument bContact for nicer output.
* Erik Marklund, June 29, 2006
*/
-static void merge_hb(t_hbdata *hb,bool bTwo, bool bContact)
-{
- int i,inrnew,indnew,j,ii,jj,m,id,ia,grp,ogrp,ntmp;
- unsigned int *htmp,*gtmp;
- t_hbond *hb0,*hb1;
+static void merge_hb(t_hbdata *hb,bool bTwo, bool bContact){
+ int i,inrnew,indnew,j,ii,jj,m,id,ia,grp,ogrp,ntmp;
+ unsigned int *htmp,*gtmp;
+ PSTYPE *ptmp;
+ t_hbond *hb0,*hb1;
- inrnew = hb->nrhb;
- indnew = hb->nrdist;
+ inrnew = hb->nrhb;
+ indnew = hb->nrdist;
- /* Check whether donors are also acceptors */
- printf("Merging hbonds with Acceptor and Donor swapped\n");
-
- ntmp = 2*hb->max_frames;
- snew(gtmp,ntmp);
- snew(htmp,ntmp);
- for(i=0; (i<hb->d.nrd); i++) {
- fprintf(stderr,"\r%d/%d",i+1,hb->d.nrd);
- id = hb->d.don[i];
- ii = hb->a.aptr[id];
- for(j=0; (j<hb->a.nra); j++) {
- ia = hb->a.acc[j];
- jj = hb->d.dptr[ia];
- if ((id != ia) && (ii != NOTSET) && (jj != NOTSET) &&
- (!bTwo || (bTwo && (hb->d.grp[i] != hb->a.grp[j])))) {
- hb0 = hb->hbmap[i][j];
- hb1 = hb->hbmap[jj][ii];
- if (hb0 && hb1 && ISHB(hb0->history[0]) && ISHB(hb1->history[0])) {
- do_merge(hb,ntmp,htmp,gtmp,hb0,hb1);
- if (ISHB(hb1->history[0]))
- inrnew--;
- else if (ISDIST(hb1->history[0]))
- indnew--;
- else
- if (bContact)
- gmx_incons("No contact history");
- else
- gmx_incons("Neither hydrogen bond nor distance");
- sfree(hb1->h[0]);
- sfree(hb1->g[0]);
- hb1->h[0] = NULL;
- hb1->g[0] = NULL;
- hb1->history[0] = hbNo;
- }
- }
- }
- }
- fprintf(stderr,"\n");
- printf("- Reduced number of hbonds from %d to %d\n",hb->nrhb,inrnew);
- printf("- Reduced number of distances from %d to %d\n",hb->nrdist,indnew);
- hb->nrhb = inrnew;
- hb->nrdist = indnew;
- sfree(gtmp);
- sfree(htmp);
+ /* Check whether donors are also acceptors */
+ printf("Merging hbonds with Acceptor and Donor swapped\n");
+
+ ntmp = 2*hb->max_frames;
+ snew(gtmp,ntmp);
+ snew(htmp,ntmp);
+ snew(ptmp,ntmp);
+ for(i=0; (i<hb->d.nrd); i++) {
+ fprintf(stderr,"\r%d/%d",i+1,hb->d.nrd);
+ id = hb->d.don[i];
+ ii = hb->a.aptr[id];
+ for(j=0; (j<hb->a.nra); j++) {
+ ia = hb->a.acc[j];
+ jj = hb->d.dptr[ia];
+ if ((id != ia) && (ii != NOTSET) && (jj != NOTSET) &&
+ (!bTwo || (bTwo && (hb->d.grp[i] != hb->a.grp[j])))) {
+ hb0 = hb->hbmap[i][j];
+ hb1 = hb->hbmap[jj][ii];
+ if (hb0 && hb1 && ISHB(hb0->history[0]) && ISHB(hb1->history[0])) {
+ do_merge(hb,ntmp,htmp,gtmp,ptmp,hb0,hb1,i,j);
+ if (ISHB(hb1->history[0]))
+ inrnew--;
+ else if (ISDIST(hb1->history[0]))
+ indnew--;
+ else
+ if (bContact)
+ gmx_incons("No contact history");
+ else
+ gmx_incons("Neither hydrogen bond nor distance");
+ sfree(hb1->h[0]);
+ sfree(hb1->g[0]);
+ if (hb->bGem) {
+ clearPshift(&(hb->per->pHist[jj][ii]));
+ }
+ hb1->h[0] = NULL;
+ hb1->g[0] = NULL;
+ hb1->history[0] = hbNo;
+ }
+ }
+ }
+ }
+ fprintf(stderr,"\n");
+ printf("- Reduced number of hbonds from %d to %d\n",hb->nrhb,inrnew);
+ printf("- Reduced number of distances from %d to %d\n",hb->nrdist,indnew);
+ hb->nrhb = inrnew;
+ hb->nrdist = indnew;
+ sfree(gtmp);
+ sfree(htmp);
+ sfree(ptmp);
}
static void do_nhb_dist(FILE *fp,t_hbdata *hb,real t)
{
- int i,j,k,n_bound[MAXHH],nbtot;
- h_id nhb;
-
-
- /* Set array to 0 */
- for(k=0; (k<MAXHH); k++)
- n_bound[k] = 0;
- /* Loop over possible donors */
- for(i=0; (i<hb->d.nrd); i++) {
- for(j=0; (j<hb->d.nhydro[i]); j++)
- n_bound[hb->d.nhbonds[i][j]]++;
- }
- fprintf(fp,"%12.5e",t);
- nbtot = 0;
- for(k=0; (k<MAXHH); k++) {
- fprintf(fp," %8d",n_bound[k]);
- nbtot += n_bound[k]*k;
- }
- fprintf(fp," %8d\n",nbtot);
+ int i,j,k,n_bound[MAXHH],nbtot;
+ h_id nhb;
+
+
+ /* Set array to 0 */
+ for(k=0; (k<MAXHH); k++)
+ n_bound[k] = 0;
+ /* Loop over possible donors */
+ for(i=0; (i<hb->d.nrd); i++) {
+ for(j=0; (j<hb->d.nhydro[i]); j++)
+ n_bound[hb->d.nhbonds[i][j]]++;
+ }
+ fprintf(fp,"%12.5e",t);
+ nbtot = 0;
+ for(k=0; (k<MAXHH); k++) {
+ fprintf(fp," %8d",n_bound[k]);
+ nbtot += n_bound[k]*k;
+ }
+ fprintf(fp," %8d\n",nbtot);
}
/* Added argument bContact in do_hblife(...). Also
static void do_hblife(const char *fn,t_hbdata *hb,bool bMerge,bool bContact,
const output_env_t oenv)
{
- FILE *fp;
- char *leg[] = { "p(t)", "t p(t)" };
- int *histo;
- int i,j,j0,k,m,nh,ihb,ohb,nhydro,ndump=0;
- int nframes = hb->nframes;
- unsigned int **h;
- real t,x1,dt;
- double sum,integral;
- t_hbond *hbh;
-
- snew(h,hb->maxhydro);
- snew(histo,nframes+1);
- /* Total number of hbonds analyzed here */
- for(i=0; (i<hb->d.nrd); i++) {
- for(k=0; (k<hb->a.nra); k++) {
- hbh = hb->hbmap[i][k];
- if (hbh) {
- if (bMerge) {
- if (hbh->h[0]) {
- h[0] = hbh->h[0];
- nhydro = 1;
- }
- else
- nhydro = 0;
- }
- else {
- nhydro = 0;
- for(m=0; (m<hb->maxhydro); m++)
- if (hbh->h[m]) {
- h[nhydro++] = bContact ? hbh->g[m] : hbh->h[m];
- }
- }
- for(nh=0; (nh<nhydro); nh++) {
- ohb = 0;
- j0 = 0;
-
- /* Changed '<' into '<=' below, just like I
- did in the hbm-output-loop in the main code.
- - Erik Marklund, May 31, 2006
- */
- for(j=0; (j<=hbh->nframes); j++) {
- ihb = is_hb(h[nh],j);
- if (debug && (ndump < 10))
- fprintf(debug,"%5d %5d\n",j,ihb);
- if (ihb != ohb) {
- if (ihb) {
- j0 = j;
- }
- else {
- histo[j-j0]++;
- }
- ohb = ihb;
- }
- }
- ndump++;
- }
- }
- }
- }
- fprintf(stderr,"\n");
- if (bContact)
- fp = xvgropen(fn,"Uninterrupted contact lifetime","Time (ps)","()",oenv);
- else
- fp = xvgropen(fn,"Uninterrupted hydrogen bond lifetime","Time (ps)","()",
- oenv);
-
- xvgr_legend(fp,asize(leg),leg,oenv);
- j0 = nframes-1;
- while ((j0 > 0) && (histo[j0] == 0))
- j0--;
- sum = 0;
- for(i=0; (i<=j0); i++)
- sum+=histo[i];
- dt = hb->time[1]-hb->time[0];
- sum = dt*sum;
- integral = 0;
- for(i=1; (i<=j0); i++) {
- t = hb->time[i] - hb->time[0] - 0.5*dt;
- x1 = t*histo[i]/sum;
- fprintf(fp,"%8.3f %10.3e %10.3e\n",t,histo[i]/sum,x1);
- integral += x1;
- }
- integral *= dt;
- ffclose(fp);
- printf("%s lifetime = %.2f ps\n", bContact?"Contact":"HB", integral);
- printf("Note that the lifetime obtained in this manner is close to useless\n");
- printf("Use the -ac option instead and check the Forward lifetime\n");
- please_cite(stdout,"Spoel2006b");
- sfree(h);
- sfree(histo);
+ FILE *fp;
+ char *leg[] = { "p(t)", "t p(t)" };
+ int *histo;
+ int i,j,j0,k,m,nh,ihb,ohb,nhydro,ndump=0;
+ int nframes = hb->nframes;
+ unsigned int **h;
+ real t,x1,dt;
+ double sum,integral;
+ t_hbond *hbh;
+
+ snew(h,hb->maxhydro);
+ snew(histo,nframes+1);
+ /* Total number of hbonds analyzed here */
+ for(i=0; (i<hb->d.nrd); i++) {
+ for(k=0; (k<hb->a.nra); k++) {
+ hbh = hb->hbmap[i][k];
+ if (hbh) {
+ if (bMerge) {
+ if (hbh->h[0]) {
+ h[0] = hbh->h[0];
+ nhydro = 1;
+ }
+ else
+ nhydro = 0;
+ }
+ else {
+ nhydro = 0;
+ for(m=0; (m<hb->maxhydro); m++)
+ if (hbh->h[m]) {
+ h[nhydro++] = bContact ? hbh->g[m] : hbh->h[m];
+ }
+ }
+ for(nh=0; (nh<nhydro); nh++) {
+ ohb = 0;
+ j0 = 0;
+
+ /* Changed '<' into '<=' below, just like I
+ did in the hbm-output-loop in the main code.
+ - Erik Marklund, May 31, 2006
+ */
+ for(j=0; (j<=hbh->nframes); j++) {
+ ihb = is_hb(h[nh],j);
+ if (debug && (ndump < 10))
+ fprintf(debug,"%5d %5d\n",j,ihb);
+ if (ihb != ohb) {
+ if (ihb) {
+ j0 = j;
+ }
+ else {
+ histo[j-j0]++;
+ }
+ ohb = ihb;
+ }
+ }
+ ndump++;
+ }
+ }
+ }
+ }
+ fprintf(stderr,"\n");
+ if (bContact)
+ fp = xvgropen(fn,"Uninterrupted contact lifetime","Time (ps)","()",oenv);
+ else
+ fp = xvgropen(fn,"Uninterrupted hydrogen bond lifetime","Time (ps)","()",
+ oenv);
+
+ xvgr_legend(fp,asize(leg),leg,oenv);
+ j0 = nframes-1;
+ while ((j0 > 0) && (histo[j0] == 0))
+ j0--;
+ sum = 0;
+ for(i=0; (i<=j0); i++)
+ sum+=histo[i];
+ dt = hb->time[1]-hb->time[0];
+ sum = dt*sum;
+ integral = 0;
+ for(i=1; (i<=j0); i++) {
+ t = hb->time[i] - hb->time[0] - 0.5*dt;
+ x1 = t*histo[i]/sum;
+ fprintf(fp,"%8.3f %10.3e %10.3e\n",t,histo[i]/sum,x1);
+ integral += x1;
+ }
+ integral *= dt;
+ ffclose(fp);
+ printf("%s lifetime = %.2f ps\n", bContact?"Contact":"HB", integral);
+ printf("Note that the lifetime obtained in this manner is close to useless\n");
+ printf("Use the -ac option instead and check the Forward lifetime\n");
+ please_cite(stdout,"Spoel2006b");
+ sfree(h);
+ sfree(histo);
}
/* Changed argument bMerge into oneHB to handle contacts properly.
*/
static void dump_ac(t_hbdata *hb,bool oneHB,int nDump)
{
- FILE *fp;
- int i,j,k,m,nd,ihb,idist;
- int nframes = hb->nframes;
- bool bPrint;
- t_hbond *hbh;
+ FILE *fp;
+ int i,j,k,m,nd,ihb,idist;
+ int nframes = hb->nframes;
+ bool bPrint;
+ t_hbond *hbh;
- if (nDump <= 0)
- return;
- fp = ffopen("debug-ac.xvg","w");
- for(j=0; (j<nframes); j++) {
- fprintf(fp,"%10.3f",hb->time[j]);
- for(i=nd=0; (i<hb->d.nrd) && (nd < nDump); i++) {
- for(k=0; (k<hb->a.nra) && (nd < nDump); k++) {
- bPrint = FALSE;
- ihb = idist = 0;
- hbh = hb->hbmap[i][k];
- if (oneHB) {
- if (hbh->h[0]) {
- ihb = is_hb(hbh->h[0],j);
- idist = is_hb(hbh->g[0],j);
- bPrint = TRUE;
- }
- }
- else {
- for(m=0; (m<hb->maxhydro) && !ihb ; m++) {
- ihb = ihb || ((hbh->h[m]) && is_hb(hbh->h[m],j));
- idist = idist || ((hbh->g[m]) && is_hb(hbh->g[m],j));
- }
- /* This is not correct! */
- /* What isn't correct? -Erik M */
- bPrint = TRUE;
- }
- if (bPrint) {
- fprintf(fp," %1d-%1d",ihb,idist);
- nd++;
- }
- }
+ if (nDump <= 0)
+ return;
+ fp = ffopen("debug-ac.xvg","w");
+ for(j=0; (j<nframes); j++) {
+ fprintf(fp,"%10.3f",hb->time[j]);
+ for(i=nd=0; (i<hb->d.nrd) && (nd < nDump); i++) {
+ for(k=0; (k<hb->a.nra) && (nd < nDump); k++) {
+ bPrint = FALSE;
+ ihb = idist = 0;
+ hbh = hb->hbmap[i][k];
+ if (oneHB) {
+ if (hbh->h[0]) {
+ ihb = is_hb(hbh->h[0],j);
+ idist = is_hb(hbh->g[0],j);
+ bPrint = TRUE;
+ }
+ }
+ else {
+ for(m=0; (m<hb->maxhydro) && !ihb ; m++) {
+ ihb = ihb || ((hbh->h[m]) && is_hb(hbh->h[m],j));
+ idist = idist || ((hbh->g[m]) && is_hb(hbh->g[m],j));
+ }
+ /* This is not correct! */
+ /* What isn't correct? -Erik M */
+ bPrint = TRUE;
+ }
+ if (bPrint) {
+ fprintf(fp," %1d-%1d",ihb,idist);
+ nd++;
+ }
+ }
+ }
+ fprintf(fp,"\n");
}
- fprintf(fp,"\n");
- }
- ffclose(fp);
+ ffclose(fp);
}
static real calc_dg(real tau,real temp)
{
- real kbt;
+ real kbt;
- kbt = BOLTZ*temp;
- if (tau <= 0)
- return -666;
- else
- return kbt*log(kbt*tau/PLANCK);
+ kbt = BOLTZ*temp;
+ if (tau <= 0)
+ return -666;
+ else
+ return kbt*log(kbt*tau/PLANCK);
}
typedef struct {
- int n0,n1,nparams,ndelta;
- real kkk[2];
- real *t,*ct,*nt,*kt,*sigma_ct,*sigma_nt,*sigma_kt;
+ int n0,n1,nparams,ndelta;
+ real kkk[2];
+ real *t,*ct,*nt,*kt,*sigma_ct,*sigma_nt,*sigma_kt;
} t_luzar;
#ifdef HAVE_LIBGSL
#include <gsl/gsl_multimin.h>
#include <gsl/gsl_sf.h>
+#include <gsl/gsl_version.h>
static double my_f(const gsl_vector *v,void *params)
{
- t_luzar *tl = (t_luzar *)params;
- int i;
- double tol=1e-16,chi2=0;
- double di;
- real k,kp;
-
- for(i=0; (i<tl->nparams); i++) {
- tl->kkk[i] = gsl_vector_get(v, i);
- }
- k = tl->kkk[0];
- kp = tl->kkk[1];
-
- for(i=tl->n0; (i<tl->n1); i+=tl->ndelta) {
- di=sqr(k*tl->sigma_ct[i]) + sqr(kp*tl->sigma_nt[i]) + sqr(tl->sigma_kt[i]);
- /*di = 1;*/
- if (di > tol)
- chi2 += sqr(k*tl->ct[i]-kp*tl->nt[i]-tl->kt[i])/di;
+ t_luzar *tl = (t_luzar *)params;
+ int i;
+ double tol=1e-16,chi2=0;
+ double di;
+ real k,kp;
+
+ for(i=0; (i<tl->nparams); i++) {
+ tl->kkk[i] = gsl_vector_get(v, i);
+ }
+ k = tl->kkk[0];
+ kp = tl->kkk[1];
+
+ for(i=tl->n0; (i<tl->n1); i+=tl->ndelta) {
+ di=sqr(k*tl->sigma_ct[i]) + sqr(kp*tl->sigma_nt[i]) + sqr(tl->sigma_kt[i]);
+ /*di = 1;*/
+ if (di > tol)
+ chi2 += sqr(k*tl->ct[i]-kp*tl->nt[i]-tl->kt[i])/di;
- else
- fprintf(stderr,"WARNING: sigma_ct = %g, sigma_nt = %g, sigma_kt = %g\n"
- "di = %g k = %g kp = %g\n",tl->sigma_ct[i],
- tl->sigma_nt[i],tl->sigma_kt[i],di,k,kp);
- }
+ else
+ fprintf(stderr,"WARNING: sigma_ct = %g, sigma_nt = %g, sigma_kt = %g\n"
+ "di = %g k = %g kp = %g\n",tl->sigma_ct[i],
+ tl->sigma_nt[i],tl->sigma_kt[i],di,k,kp);
+ }
#ifdef DEBUG
- chi2 = 0.3*sqr(k-0.6)+0.7*sqr(kp-1.3);
+ chi2 = 0.3*sqr(k-0.6)+0.7*sqr(kp-1.3);
#endif
- return chi2;
+ return chi2;
}
static real optimize_luzar_parameters(FILE *fp,t_luzar *tl,int maxiter,
- real tol)
+ real tol)
{
- real size,d2;
- int iter = 0;
- int status = 0;
- int i;
+ real size,d2;
+ int iter = 0;
+ int status = 0;
+ int i;
- const gsl_multimin_fminimizer_type *T;
- gsl_multimin_fminimizer *s;
+ const gsl_multimin_fminimizer_type *T;
+ gsl_multimin_fminimizer *s;
- gsl_vector *x,*dx;
- gsl_multimin_function my_func;
+ gsl_vector *x,*dx;
+ gsl_multimin_function my_func;
- my_func.f = &my_f;
- my_func.n = tl->nparams;
- my_func.params = (void *) tl;
+ my_func.f = &my_f;
+ my_func.n = tl->nparams;
+ my_func.params = (void *) tl;
- /* Starting point */
- x = gsl_vector_alloc (my_func.n);
- for(i=0; (i<my_func.n); i++)
- gsl_vector_set (x, i, tl->kkk[i]);
+ /* Starting point */
+ x = gsl_vector_alloc (my_func.n);
+ for(i=0; (i<my_func.n); i++)
+ gsl_vector_set (x, i, tl->kkk[i]);
- /* Step size, different for each of the parameters */
- dx = gsl_vector_alloc (my_func.n);
- for(i=0; (i<my_func.n); i++)
- gsl_vector_set (dx, i, 0.01*tl->kkk[i]);
+ /* Step size, different for each of the parameters */
+ dx = gsl_vector_alloc (my_func.n);
+ for(i=0; (i<my_func.n); i++)
+ gsl_vector_set (dx, i, 0.01*tl->kkk[i]);
- T = gsl_multimin_fminimizer_nmsimplex;
- s = gsl_multimin_fminimizer_alloc (T, my_func.n);
+ T = gsl_multimin_fminimizer_nmsimplex;
+ s = gsl_multimin_fminimizer_alloc (T, my_func.n);
- gsl_multimin_fminimizer_set (s, &my_func, x, dx);
- gsl_vector_free (x);
- gsl_vector_free (dx);
+ gsl_multimin_fminimizer_set (s, &my_func, x, dx);
+ gsl_vector_free (x);
+ gsl_vector_free (dx);
- if (fp)
- fprintf(fp,"%5s %12s %12s %12s %12s\n","Iter","k","kp","NM Size","Chi2");
+ if (fp)
+ fprintf(fp,"%5s %12s %12s %12s %12s\n","Iter","k","kp","NM Size","Chi2");
- do {
- iter++;
- status = gsl_multimin_fminimizer_iterate (s);
+ do {
+ iter++;
+ status = gsl_multimin_fminimizer_iterate (s);
- if (status != 0)
- gmx_fatal(FARGS,"Something went wrong in the iteration in minimizer %s",
- gsl_multimin_fminimizer_name(s));
+ if (status != 0)
+ gmx_fatal(FARGS,"Something went wrong in the iteration in minimizer %s",
+ gsl_multimin_fminimizer_name(s));
- d2 = gsl_multimin_fminimizer_minimum(s);
- size = gsl_multimin_fminimizer_size(s);
- status = gsl_multimin_test_size(size,tol);
+ d2 = gsl_multimin_fminimizer_minimum(s);
+ size = gsl_multimin_fminimizer_size(s);
+ status = gsl_multimin_test_size(size,tol);
- if (status == GSL_SUCCESS)
- if (fp)
- fprintf(fp,"Minimum found using %s at:\n",
- gsl_multimin_fminimizer_name(s));
+ if (status == GSL_SUCCESS)
+ if (fp)
+ fprintf(fp,"Minimum found using %s at:\n",
+ gsl_multimin_fminimizer_name(s));
- if (fp) {
- fprintf(fp,"%5d", iter);
- for(i=0; (i<my_func.n); i++)
- fprintf(fp," %12.4e",gsl_vector_get (s->x,i));
- fprintf (fp," %12.4e %12.4e\n",size,d2);
+ if (fp) {
+ fprintf(fp,"%5d", iter);
+ for(i=0; (i<my_func.n); i++)
+ fprintf(fp," %12.4e",gsl_vector_get (s->x,i));
+ fprintf (fp," %12.4e %12.4e\n",size,d2);
+ }
}
- }
- while ((status == GSL_CONTINUE) && (iter < maxiter));
+ while ((status == GSL_CONTINUE) && (iter < maxiter));
- gsl_multimin_fminimizer_free (s);
+ gsl_multimin_fminimizer_free (s);
- return d2;
+ return d2;
}
static real quality_of_fit(real chi2,int N)
{
- return gsl_sf_gamma_inc_Q((N-2)/2.0,chi2/2.0);
+ return gsl_sf_gamma_inc_Q((N-2)/2.0,chi2/2.0);
}
#else
static real optimize_luzar_parameters(FILE *fp,t_luzar *tl,int maxiter,
- real tol)
+ real tol)
{
- fprintf(stderr,"This program needs the GNU scientific library to work.\n");
+ fprintf(stderr,"This program needs the GNU scientific library to work.\n");
- return -1;
+ return -1;
}
static real quality_of_fit(real chi2,int N)
{
- fprintf(stderr,"This program needs the GNU scientific library to work.\n");
+ fprintf(stderr,"This program needs the GNU scientific library to work.\n");
- return -1;
+ return -1;
}
#endif
static real compute_weighted_rates(int n,real t[],real ct[],real nt[],
- real kt[],real sigma_ct[],real sigma_nt[],
- real sigma_kt[],real *k,real *kp,
- real *sigma_k,real *sigma_kp,
- real fit_start)
+ real kt[],real sigma_ct[],real sigma_nt[],
+ real sigma_kt[],real *k,real *kp,
+ real *sigma_k,real *sigma_kp,
+ real fit_start)
{
#define NK 10
- int i,j;
- t_luzar tl;
- real kkk=0,kkp=0,kk2=0,kp2=0,chi2;
-
- *sigma_k = 0;
- *sigma_kp = 0;
-
- for(i=0; (i<n); i++) {
- if (t[i] >= fit_start)
- break;
- }
- tl.n0 = i;
- tl.n1 = n;
- tl.nparams = 2;
- tl.ndelta = 1;
- tl.t = t;
- tl.ct = ct;
- tl.nt = nt;
- tl.kt = kt;
- tl.sigma_ct = sigma_ct;
- tl.sigma_nt = sigma_nt;
- tl.sigma_kt = sigma_kt;
- tl.kkk[0] = *k;
- tl.kkk[1] = *kp;
-
- chi2 = optimize_luzar_parameters(debug,&tl,1000,1e-3);
- *k = tl.kkk[0];
- *kp = tl.kkk[1] = *kp;
- tl.ndelta = NK;
- for(j=0; (j<NK); j++) {
- (void) optimize_luzar_parameters(debug,&tl,1000,1e-3);
- kkk += tl.kkk[0];
- kkp += tl.kkk[1];
- kk2 += sqr(tl.kkk[0]);
- kp2 += sqr(tl.kkk[1]);
- tl.n0++;
- }
- *sigma_k = sqrt(kk2/NK - sqr(kkk/NK));
- *sigma_kp = sqrt(kp2/NK - sqr(kkp/NK));
-
- return chi2;
+ int i,j;
+ t_luzar tl;
+ real kkk=0,kkp=0,kk2=0,kp2=0,chi2;
+
+ *sigma_k = 0;
+ *sigma_kp = 0;
+
+ for(i=0; (i<n); i++) {
+ if (t[i] >= fit_start)
+ break;
+ }
+ tl.n0 = i;
+ tl.n1 = n;
+ tl.nparams = 2;
+ tl.ndelta = 1;
+ tl.t = t;
+ tl.ct = ct;
+ tl.nt = nt;
+ tl.kt = kt;
+ tl.sigma_ct = sigma_ct;
+ tl.sigma_nt = sigma_nt;
+ tl.sigma_kt = sigma_kt;
+ tl.kkk[0] = *k;
+ tl.kkk[1] = *kp;
+
+ chi2 = optimize_luzar_parameters(debug,&tl,1000,1e-3);
+ *k = tl.kkk[0];
+ *kp = tl.kkk[1] = *kp;
+ tl.ndelta = NK;
+ for(j=0; (j<NK); j++) {
+ (void) optimize_luzar_parameters(debug,&tl,1000,1e-3);
+ kkk += tl.kkk[0];
+ kkp += tl.kkk[1];
+ kk2 += sqr(tl.kkk[0]);
+ kp2 += sqr(tl.kkk[1]);
+ tl.n0++;
+ }
+ *sigma_k = sqrt(kk2/NK - sqr(kkk/NK));
+ *sigma_kp = sqrt(kp2/NK - sqr(kkp/NK));
+
+ return chi2;
}
static void smooth_tail(int n,real t[],real c[],real sigma_c[],real start,
const output_env_t oenv)
{
- FILE *fp;
- real e_1,fitparm[4];
- int i;
-
- e_1 = exp(-1);
- for(i=0; (i<n); i++)
- if (c[i] < e_1)
- break;
- if (i < n)
- fitparm[0] = t[i];
- else
- fitparm[0] = 10;
- fitparm[1] = 0.95;
- do_lmfit(n,c,sigma_c,0,t,start,t[n-1],oenv,bDebugMode(),effnEXP2,fitparm,0);
+ FILE *fp;
+ real e_1,fitparm[4];
+ int i;
+
+ e_1 = exp(-1);
+ for(i=0; (i<n); i++)
+ if (c[i] < e_1)
+ break;
+ if (i < n)
+ fitparm[0] = t[i];
+ else
+ fitparm[0] = 10;
+ fitparm[1] = 0.95;
+ do_lmfit(n,c,sigma_c,0,t,start,t[n-1],oenv,bDebugMode(),effnEXP2,fitparm,0);
}
void analyse_corr(int n,real t[],real ct[],real nt[],real kt[],
- real sigma_ct[],real sigma_nt[],real sigma_kt[],
- real fit_start,real temp,real smooth_tail_start,
+ real sigma_ct[],real sigma_nt[],real sigma_kt[],
+ real fit_start,real temp,real smooth_tail_start,
const output_env_t oenv)
{
- int i0,i;
- real k=1,kp=1,kow=1;
- real Q=0,chi22,chi2,dg,dgp,tau_hb,dtau,tau_rlx,e_1,dt,sigma_k,sigma_kp,ddg;
- double tmp,sn2=0,sc2=0,sk2=0,scn=0,sck=0,snk=0;
- bool bError = (sigma_ct != NULL) && (sigma_nt != NULL) && (sigma_kt != NULL);
-
- if (smooth_tail_start >= 0) {
- smooth_tail(n,t,ct,sigma_ct,smooth_tail_start,oenv);
- smooth_tail(n,t,nt,sigma_nt,smooth_tail_start,oenv);
- smooth_tail(n,t,kt,sigma_kt,smooth_tail_start,oenv);
- }
- for(i0=0; (i0<n-2) && ((t[i0]-t[0]) < fit_start); i0++)
- ;
- if (i0 < n-2) {
- for(i=i0; (i<n); i++) {
- sc2 += sqr(ct[i]);
- sn2 += sqr(nt[i]);
- sk2 += sqr(kt[i]);
- sck += ct[i]*kt[i];
- snk += nt[i]*kt[i];
- scn += ct[i]*nt[i];
- }
- printf("Hydrogen bond thermodynamics at T = %g K\n",temp);
- tmp = (sn2*sc2-sqr(scn));
- if ((tmp > 0) && (sn2 > 0)) {
- k = (sn2*sck-scn*snk)/tmp;
- kp = (k*scn-snk)/sn2;
- if (bError) {
- chi2 = 0;
- for(i=i0; (i<n); i++) {
- chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
- }
- chi22 = compute_weighted_rates(n,t,ct,nt,kt,sigma_ct,sigma_nt,
- sigma_kt,&k,&kp,
- &sigma_k,&sigma_kp,fit_start);
- Q = quality_of_fit(chi2,2);
- ddg = BOLTZ*temp*sigma_k/k;
- printf("Fitting paramaters chi^2 = %10g, Quality of fit = %10g\n",
- chi2,Q);
- printf("The Rate and Delta G are followed by an error estimate\n");
- printf("----------------------------------------------------------\n"
- "Type Rate (1/ps) Sigma Time (ps) DG (kJ/mol) Sigma\n");
- printf("Forward %10.3f %6.2f %8.3f %10.3f %6.2f\n",
- k,sigma_k,1/k,calc_dg(1/k,temp),ddg);
- ddg = BOLTZ*temp*sigma_kp/kp;
- printf("Backward %10.3f %6.2f %8.3f %10.3f %6.2f\n",
- kp,sigma_kp,1/kp,calc_dg(1/kp,temp),ddg);
- }
- else {
- chi2 = 0;
- for(i=i0; (i<n); i++) {
- chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
- }
- printf("Fitting parameters chi^2 = %10g\nQ = %10g\n",
- chi2,Q);
- printf("--------------------------------------------------\n"
- "Type Rate (1/ps) Time (ps) DG (kJ/mol) Chi^2\n");
- printf("Forward %10.3f %8.3f %10.3f %10g\n",
- k,1/k,calc_dg(1/k,temp),chi2);
- printf("Backward %10.3f %8.3f %10.3f\n",
- kp,1/kp,calc_dg(1/kp,temp));
- }
- }
- if (sc2 > 0) {
- kow = 2*sck/sc2;
- printf("One-way %10.3f %s%8.3f %10.3f\n",
- kow,bError ? " " : "",1/kow,calc_dg(1/kow,temp));
- }
- else
- printf(" - Numerical problems computing HB thermodynamics:\n"
- "sc2 = %g sn2 = %g sk2 = %g sck = %g snk = %g scn = %g\n",
- sc2,sn2,sk2,sck,snk,scn);
- /* Determine integral of the correlation function */
- tau_hb = evaluate_integral(n,t,ct,NULL,(t[n-1]-t[0])/2,&dtau);
- printf("Integral %10.3f %s%8.3f %10.3f\n",1/tau_hb,
- bError ? " " : "",tau_hb,calc_dg(tau_hb,temp));
- e_1 = exp(-1);
- for(i=0; (i<n-2); i++) {
- if ((ct[i] > e_1) && (ct[i+1] <= e_1)) {
- break;
- }
+ int i0,i;
+ real k=1,kp=1,kow=1;
+ real Q=0,chi22,chi2,dg,dgp,tau_hb,dtau,tau_rlx,e_1,dt,sigma_k,sigma_kp,ddg;
+ double tmp,sn2=0,sc2=0,sk2=0,scn=0,sck=0,snk=0;
+ bool bError = (sigma_ct != NULL) && (sigma_nt != NULL) && (sigma_kt != NULL);
+
+ if (smooth_tail_start >= 0) {
+ smooth_tail(n,t,ct,sigma_ct,smooth_tail_start,oenv);
+ smooth_tail(n,t,nt,sigma_nt,smooth_tail_start,oenv);
+ smooth_tail(n,t,kt,sigma_kt,smooth_tail_start,oenv);
}
- if (i < n-2) {
- /* Determine tau_relax from linear interpolation */
- tau_rlx = t[i]-t[0] + (e_1-ct[i])*(t[i+1]-t[i])/(ct[i+1]-ct[i]);
- printf("Relaxation %10.3f %8.3f %s%10.3f\n",1/tau_rlx,
- tau_rlx,bError ? " " : "",
- calc_dg(tau_rlx,temp));
+ for(i0=0; (i0<n-2) && ((t[i0]-t[0]) < fit_start); i0++)
+ ;
+ if (i0 < n-2) {
+ for(i=i0; (i<n); i++) {
+ sc2 += sqr(ct[i]);
+ sn2 += sqr(nt[i]);
+ sk2 += sqr(kt[i]);
+ sck += ct[i]*kt[i];
+ snk += nt[i]*kt[i];
+ scn += ct[i]*nt[i];
+ }
+ printf("Hydrogen bond thermodynamics at T = %g K\n",temp);
+ tmp = (sn2*sc2-sqr(scn));
+ if ((tmp > 0) && (sn2 > 0)) {
+ k = (sn2*sck-scn*snk)/tmp;
+ kp = (k*scn-snk)/sn2;
+ if (bError) {
+ chi2 = 0;
+ for(i=i0; (i<n); i++) {
+ chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
+ }
+ chi22 = compute_weighted_rates(n,t,ct,nt,kt,sigma_ct,sigma_nt,
+ sigma_kt,&k,&kp,
+ &sigma_k,&sigma_kp,fit_start);
+ Q = quality_of_fit(chi2,2);
+ ddg = BOLTZ*temp*sigma_k/k;
+ printf("Fitting paramaters chi^2 = %10g, Quality of fit = %10g\n",
+ chi2,Q);
+ printf("The Rate and Delta G are followed by an error estimate\n");
+ printf("----------------------------------------------------------\n"
+ "Type Rate (1/ps) Sigma Time (ps) DG (kJ/mol) Sigma\n");
+ printf("Forward %10.3f %6.2f %8.3f %10.3f %6.2f\n",
+ k,sigma_k,1/k,calc_dg(1/k,temp),ddg);
+ ddg = BOLTZ*temp*sigma_kp/kp;
+ printf("Backward %10.3f %6.2f %8.3f %10.3f %6.2f\n",
+ kp,sigma_kp,1/kp,calc_dg(1/kp,temp),ddg);
+ }
+ else {
+ chi2 = 0;
+ for(i=i0; (i<n); i++) {
+ chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
+ }
+ printf("Fitting parameters chi^2 = %10g\nQ = %10g\n",
+ chi2,Q);
+ printf("--------------------------------------------------\n"
+ "Type Rate (1/ps) Time (ps) DG (kJ/mol) Chi^2\n");
+ printf("Forward %10.3f %8.3f %10.3f %10g\n",
+ k,1/k,calc_dg(1/k,temp),chi2);
+ printf("Backward %10.3f %8.3f %10.3f\n",
+ kp,1/kp,calc_dg(1/kp,temp));
+ }
+ }
+ if (sc2 > 0) {
+ kow = 2*sck/sc2;
+ printf("One-way %10.3f %s%8.3f %10.3f\n",
+ kow,bError ? " " : "",1/kow,calc_dg(1/kow,temp));
+ }
+ else
+ printf(" - Numerical problems computing HB thermodynamics:\n"
+ "sc2 = %g sn2 = %g sk2 = %g sck = %g snk = %g scn = %g\n",
+ sc2,sn2,sk2,sck,snk,scn);
+ /* Determine integral of the correlation function */
+ tau_hb = evaluate_integral(n,t,ct,NULL,(t[n-1]-t[0])/2,&dtau);
+ printf("Integral %10.3f %s%8.3f %10.3f\n",1/tau_hb,
+ bError ? " " : "",tau_hb,calc_dg(tau_hb,temp));
+ e_1 = exp(-1);
+ for(i=0; (i<n-2); i++) {
+ if ((ct[i] > e_1) && (ct[i+1] <= e_1)) {
+ break;
+ }
+ }
+ if (i < n-2) {
+ /* Determine tau_relax from linear interpolation */
+ tau_rlx = t[i]-t[0] + (e_1-ct[i])*(t[i+1]-t[i])/(ct[i+1]-ct[i]);
+ printf("Relaxation %10.3f %8.3f %s%10.3f\n",1/tau_rlx,
+ tau_rlx,bError ? " " : "",
+ calc_dg(tau_rlx,temp));
+ }
}
- }
- else
- printf("Correlation functions too short to compute thermodynamics\n");
+ else
+ printf("Correlation functions too short to compute thermodynamics\n");
}
void compute_derivative(int nn,real x[],real y[],real dydx[])
{
- int j;
+ int j;
- /* Compute k(t) = dc(t)/dt */
- for(j=1; (j<nn-1); j++)
- dydx[j] = (y[j+1]-y[j-1])/(x[j+1]-x[j-1]);
- /* Extrapolate endpoints */
- dydx[0] = 2*dydx[1] - dydx[2];
- dydx[nn-1] = 2*dydx[nn-2] - dydx[nn-3];
+ /* Compute k(t) = dc(t)/dt */
+ for(j=1; (j<nn-1); j++)
+ dydx[j] = (y[j+1]-y[j-1])/(x[j+1]-x[j-1]);
+ /* Extrapolate endpoints */
+ dydx[0] = 2*dydx[1] - dydx[2];
+ dydx[nn-1] = 2*dydx[nn-2] - dydx[nn-3];
+}
+
+static void parallel_print(int *data, int nThreads)
+{
+ /* This prints the donors on which each tread is currently working. */
+ int i;
+
+ fprintf(stderr, "\r");
+ for (i=0; i<nThreads; i++)
+ fprintf(stderr, "%-7i",data[i]);
+}
+
+static void normalizeACF(real *ct, real *gt, int len)
+{
+ real ct_fac, gt_fac;
+ int i;
+
+ /* Xu and Berne use the same normalization constant */
+
+ ct_fac = 1.0/ct[0];
+ gt_fac = (gt!=NULL && gt[0]!=0) ? 1.0/gt[0] : 0;
+ printf("Normalization for c(t) = %g for gh(t) = %g\n",ct_fac,gt_fac);
+ for (i=0; i<len; i++)
+ {
+ ct[i] *= ct_fac;
+ if (gt != NULL)
+ gt[i] *= gt_fac;
+ }
}
/* Added argument bContact in do_hbac(...). Also
* - Erik Marklund, June 29, 2006
*/
static void do_hbac(const char *fn,t_hbdata *hb,real aver_nhb,real aver_dist,
- int nDump,bool bMerge,bool bContact,real fit_start,
- real temp,bool R2,real smooth_tail_start,
- const output_env_t oenv)
+ int nDump,bool bMerge,bool bContact, real fit_start,
+ real temp,bool R2,real smooth_tail_start, const output_env_t oenv,
+ t_gemParams *params, const char *gemType, int nThreads,
+ const int NN, const bool bBallistic, const bool bGemFit)
{
- FILE *fp;
- char *leg[] = { "Ac\\sfin sys\\v{}\\z{}(t)", "Ac(t)", "Cc\\scontact,hb\\v{}\\z{}(t)", "-dAc\\sfs\\v{}\\z{}/dt" };
- int i,j,k,m,n,nd,ihb,idist,n2,nn;
- bool bNorm=FALSE;
- double nhb = 0;
- real *rhbex,*ht,*gt,*ght,*dght,*kt;
- real *ct,tail,tail2,dtail,ct_fac,ght_fac,*cct;
- const real tol = 1e-3;
- int nframes = hb->nframes,nf;
- unsigned int **h,**g;
- int nh,nhbonds,nhydro,ngh;
- t_hbond *hbh;
-
- /* build hbexist matrix in reals for autocorr */
- /* Allocate memory for computing ACF (rhbex) and aggregating the ACF (ct) */
- n2=1;
- while (n2 < nframes)
- n2*=2;
- snew(rhbex,2*n2);
- snew(ct,2*n2);
- snew(gt,2*n2);
- snew(ht,2*n2);
- snew(ght,2*n2);
- snew(dght,2*n2);
-
- nn = nframes/2;
- snew(kt,nn);
- snew(cct,nn);
-
- snew(h,hb->maxhydro);
- snew(g,hb->maxhydro);
-
- /* Dump hbonds for debugging */
- dump_ac(hb,bMerge||bContact,nDump);
-
- /* Total number of hbonds analyzed here */
- nhbonds = 0;
- ngh = 0;
- for(i=0; (i<hb->d.nrd); i++) {
- for(k=0; (k<hb->a.nra); k++) {
- nhydro = 0;
- hbh = hb->hbmap[i][k];
- if (hbh) {
- if (bMerge || bContact) {
- if (ISHB(hbh->history[0])) {
- h[0] = hbh->h[0];
- g[0] = hbh->g[0];
- nhydro = 1;
- }
- }
- else {
- for(m=0; (m<hb->maxhydro); m++)
- if (bContact ? ISDIST(hbh->history[m]) : ISHB(hbh->history[m])) {
- g[nhydro] = hbh->g[m];
- h[nhydro] = hbh->h[m];
- nhydro++;
- }
- }
- nf = hbh->nframes;
- for(nh=0; (nh<nhydro); nh++) {
- int nrint = bContact ? hb->nrdist : hb->nrhb;
- if ((((nhbonds+1) % 10) == 0) || (nhbonds+1 == nrint))
- fprintf(stderr,"\rACF %d/%d",nhbonds+1,nrint);
- nhbonds++;
- for(j=0; (j<nframes); j++) {
- /* Changed '<' into '<=' below, just like I did in
- the hbm-output-loop in the gmx_hbond() block.
- - Erik Marklund, May 31, 2006 */
- if (j <= nf) {
- ihb = is_hb(h[nh],j);
- idist = is_hb(g[nh],j);
- }
- else {
- ihb = idist = 0;
- }
- rhbex[j] = ihb-aver_nhb;
- /* For contacts: if a second cut-off is provided, use it,
- * otherwise use g(t) = 1-h(t) */
- if (!R2 && bContact)
- gt[j] = 1-ihb;
- else
- gt[j] = idist*(1-ihb);
- ht[j] = rhbex[j];
- nhb += ihb;
- }
+ FILE *fp;
+ int i,j,k,m,n,o,nd,ihb,idist,n2,nn,iter,nSets;
+ static char *legNN[] = { "Ac(t)",
+ "Ac'(t)"};
+ static char **legGem;
+
+ static char *legLuzar[] = { "Ac\\sfin sys\\v{}\\z{}(t)",
+ "Ac(t)",
+ "Cc\\scontact,hb\\v{}\\z{}(t)",
+ "-dAc\\sfs\\v{}\\z{}/dt" };
+ bool bNorm=FALSE;
+ double nhb = 0;
+ int nhbi=0;
+ real *rhbex=NULL,*ht,*gt,*ght,*dght,*kt;
+ real *ct,*p_ct,tail,tail2,dtail,ct_fac,ght_fac,*cct;
+ const real tol = 1e-3;
+ int nframes = hb->nframes,nf;
+ unsigned int **h,**g;
+ int nh,nhbonds,nhydro,ngh;
+ t_hbond *hbh;
+ PSTYPE p, *pfound = NULL, np;
+ t_pShift *pHist;
+ int *ptimes=NULL, *poff=NULL, anhb, n0, mMax=INT_MIN;
+ real **rHbExGem = NULL;
+ bool c;
+ int acType;
+ t_E *E;
+ double *ctdouble, *timedouble, *fittedct;
+ double fittolerance=0.1;
+
+ enum {AC_NONE, AC_NN, AC_GEM, AC_LUZAR};
+
+
+#ifdef HAVE_OPENMP
+ int *dondata=NULL, thisThread;
+#endif
+
+
+ printf("Doing autocorrelation ");
+
+ /* Decide what kind of ACF calculations to do. */
+ if (NN > NN_NONE && NN < NN_NR) {
+#ifdef HAVE_NN_LOOPS
+ acType = AC_NN;
+ printf("using the energy estimate.\n");
+#else
+ acType = AC_NONE;
+ printf("Can't do the NN-loop. Yet.\n");
+#endif
+ } else if (hb->bGem) {
+ acType = AC_GEM;
+ printf("according to the reversible geminate recombination model by Omer Markowitch.\n");
+
+ nSets = 1 + (bBallistic ? 1:0) + (bGemFit ? 1:0);
+ snew(legGem, nSets);
+ for (i=0;i<nSets;i++)
+ snew(legGem[i], 128);
+ sprintf(legGem[0], "Ac\\s%s\\v{}\\z{}(t)", gemType);
+ if (bBallistic)
+ sprintf(legGem[1], "Ac'(t)");
+ if (bGemFit)
+ sprintf(legGem[(bBallistic ? 3:2)], "Ac\\s%s,fit\\v{}\\z{}(t)", gemType);
+
+ } else {
+ acType = AC_LUZAR;
+ printf("according to the theory of Luzar and Chandler.\n");
+ }
+ fflush(stdout);
+
+ /* build hbexist matrix in reals for autocorr */
+ /* Allocate memory for computing ACF (rhbex) and aggregating the ACF (ct) */
+ n2=1;
+ while (n2 < nframes)
+ n2*=2;
+
+ nn = nframes/2;
+
+ if (acType != AC_NN ||
+#ifndef HAVE_OPENMP
+ TRUE
+#else
+ FALSE
+#endif
+ ) {
+ snew(h,hb->maxhydro);
+ snew(g,hb->maxhydro);
+ }
+
+ /* Dump hbonds for debugging */
+ dump_ac(hb,bMerge||bContact,nDump);
+
+ /* Total number of hbonds analyzed here */
+ nhbonds = 0;
+ ngh = 0;
+ anhb = 0;
+
+ /* ------------------------------------------------
+ * I got tired of waiting for the acf calculations
+ * and parallelized it with openMP
+ * set environment variable CFLAGS = "-fopenmp" when running
+ * configure and define DOUSEOPENMP to make use of it.
+ */
+
+#ifdef HAVE_OPENMP /* ================================================= \
+ * Set up the OpenMP stuff, |
+ * like the number of threads and such |
+ */
+ if (acType != AC_LUZAR)
+ {
+#if (_OPENMP >= 200805) /* =====================\ */
+ nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_thread_limit());
+#else
+ nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_num_procs());
+#endif /* _OPENMP >= 200805 ====================/ */
+
+ omp_set_num_threads(nThreads);
+ snew(dondata, nThreads);
+ for (i=0; i<nThreads; i++)
+ dondata[i] = -1;
+ printf("ACF calculations parallelized with OpenMP using %i threads.\n"
+ "Expect close to linear scaling over this donor-loop.\n", nThreads);
+ fflush(stdout);
+ fprintf(stderr, "Donors: [thread no]\n");
+ {
+ char tmpstr[7];
+ for (i=0;i<nThreads;i++) {
+ snprintf(tmpstr, 7, "[%i]", i);
+ fprintf(stderr, "%-7s", tmpstr);
+ }
+ }
+ fprintf(stderr, "\n"); /* | */
+ } /* | */
+#endif /* HAVE_OPENMP ===================================================/ */
+
+
+ /* Build the ACF according to acType */
+ switch (acType)
+ {
+
+ case AC_NN:
+#ifdef HAVE_NN_LOOPS
+ /* Here we're using the estimated energy for the hydrogen bonds. */
+ snew(ct,nn);
+#ifdef HAVE_OPENMP /* ==================================\ */
+#pragma omp parallel \
+ private(i, j, k, nh, E, rhbex, thisThread), \
+ default(shared)
+ {
+#pragma omp barrier
+ thisThread = omp_get_thread_num();
+ rhbex = NULL;
+#endif /* ==============================================/ */
+
+ snew(rhbex, n2);
+ memset(rhbex, 0, n2*sizeof(real)); /* Trust no-one, not even malloc()! */
+
+#ifdef HAVE_OPENMP /* ################################################## \
+ * #
+ * #
+ */
+#pragma omp barrier
+#pragma omp for schedule (dynamic)
+#endif
+ for (i=0; i<hb->d.nrd; i++) /* loop over donors */
+ {
+#ifdef HAVE_OPENMP /* ====== Write some output ======\ */
+#pragma omp critical
+ {
+ dondata[thisThread] = i;
+ parallel_print(dondata, nThreads);
+ }
+#else
+ fprintf(stderr, "\r %i", i);
+#endif /* ===========================================/ */
+
+ for (j=0; j<hb->a.nra; j++) /* loop over acceptors */
+ {
+ for (nh=0; nh<hb->d.nhydro[i]; nh++) /* loop over donors' hydrogens */
+ {
+ E = hb->hbE.E[i][j][nh];
+ if (E != NULL)
+ {
+ for (k=0; k<nframes; k++)
+ {
+ if (E[k] != NONSENSE_E)
+ rhbex[k] = (real)E[k];
+ }
+
+ low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&(rhbex),hb->time[1]-hb->time[0],
+ eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
+#ifdef HAVE_OPENMP
+#pragma omp critical
+#endif
+ {
+ for(k=0; (k<nn); k++)
+ ct[k] += rhbex[k];
+ }
+ }
+ } /* k loop */
+ } /* j loop */
+ } /* i loop */
+ sfree(rhbex);
+#pragma omp barrier
+#ifdef HAVE_OPENMP
+ /* # */
+ } /* End of parallel block # */
+ /* ##############################################################/ */
+ sfree(dondata);
+#endif
+ normalizeACF(ct, NULL, nn);
+ snew(ctdouble, nn);
+ snew(timedouble, nn);
+ for (j=0; j<nn; j++)
+ {
+ timedouble[j]=(double)(hb->time[j]);
+ ctdouble[j]=(double)(ct[j]);
+ }
+
+ /* Remove ballistic term */
+ /* Ballistic component removal and fitting to the reversible geminate recombination model
+ * will be taken out for the time being. First of all, one can remove the ballistic
+ * component with g_analyze afterwards. Secondly, and more importantly, there are still
+ * problems with the robustness of the fitting to the model. More work is needed.
+ * A third reason is that we're currently using gsl for this and wish to reduce dependence
+ * on external libraries. There are Levenberg-Marquardt and nsimplex solvers that come with
+ * a BSD-licence that can do the job.
+ *
+ * - Erik Marklund, June 18 2010.
+ */
+/* if (params->ballistic/params->tDelta >= params->nExpFit*2+1) */
+/* takeAwayBallistic(ctdouble, timedouble, nn, params->ballistic, params->nExpFit, params->bDt); */
+/* else */
+/* printf("\nNumber of data points is less than the number of parameters to fit\n." */
+/* "The system is underdetermined, hence no ballistic term can be found.\n\n"); */
+
+ fp = xvgropen(fn, "Hydrogen Bond Autocorrelation","Time (ps)","C(t)");
+ xvgr_legend(fp,asize(legNN),legNN);
+
+ for(j=0; (j<nn); j++)
+ fprintf(fp,"%10g %10g %10g\n",
+ hb->time[j]-hb->time[0],
+ ct[j],
+ ctdouble[j]);
+ fclose(fp);
+ sfree(ct);
+ sfree(ctdouble);
+ sfree(timedouble);
+#endif /* HAVE_NN_LOOPS */
+ break; /* case AC_NN */
+
+ case AC_GEM:
+ snew(ct,2*n2);
+ memset(ct,0,2*n2*sizeof(real));
+#ifndef HAVE_OPENMP
+ fprintf(stderr, "Donor:\n");
+#define __ACDATA ct
+#else
+#define __ACDATA p_ct
+#endif
+
+#ifdef HAVE_OPENMP /* =========================================\
+ * */
+#pragma omp parallel default(none) \
+ private(i, k, nh, hbh, pHist, h, g, n0, nf, np, j, m, \
+ pfound, poff, rHbExGem, p, ihb, mMax, \
+ thisThread, p_ct) \
+ shared(hb, dondata, ct, nn, nThreads, n2, stderr, bNorm, \
+ nframes, bMerge, bContact)
+ { /* ########## THE START OF THE ENORMOUS PARALLELIZED BLOCK! ########## */
+ h = NULL;
+ g = NULL;
+ thisThread = omp_get_thread_num();
+ snew(h,hb->maxhydro);
+ snew(g,hb->maxhydro);
+ mMax = INT_MIN;
+ rHbExGem = NULL;
+ poff = NULL;
+ pfound = NULL;
+ p_ct = NULL;
+ snew(p_ct,2*n2);
+ memset(p_ct,0,2*n2*sizeof(real));
+
+ /* I'm using a chunk size of 1, since I expect \
+ * the overhead to be really small compared \
+ * to the actual calculations \ */
+#pragma omp for schedule(dynamic,1) nowait /* \ */
+#endif /* HAVE_OPENMP =========================================/ */
+
+ for (i=0; i<hb->d.nrd; i++) {
+#ifdef HAVE_OPENMP
+#pragma omp critical
+ {
+ dondata[thisThread] = i;
+ parallel_print(dondata, nThreads);
+ }
+#else
+ fprintf(stderr, "\r %i", i);
+#endif
+
+ for (k=0; k<hb->a.nra; k++) {
+ for (nh=0; nh < ((bMerge || bContact) ? 1 : hb->d.nhydro[i]); nh++) {
+ hbh = hb->hbmap[i][k];
+ if (hbh) {
+ /* Note that if hb->per->gemtype==gemDD, then distances will be stored in
+ * hb->hbmap[d][a].h array anyway, because the contact flag will be set.
+ * hence, it's only with the gemAD mode that hb->hbmap[d][a].g will be used. */
+ pHist = &(hb->per->pHist[i][k]);
+ if (ISHB(hbh->history[nh]) && pHist->len != 0) {
+
+/* No need for a critical section */
+/* #ifdef HAVE_OPENMP */
+/* #pragma omp critical */
+/* #endif */
+ {
+ h[nh] = hbh->h[nh];
+ g[nh] = hb->per->gemtype==gemAD ? hbh->g[nh] : NULL;
+ }
+ n0 = hbh->n0;
+ nf = hbh->nframes;
+ /* count the number of periodic shifts encountered and store
+ * them in separate arrays. */
+ np = 0;
+ for (j=0; j<pHist->len; j++)
+ {
+ p = pHist->p[j];
+ for (m=0; m<=np; m++) {
+ if (m == np) { /* p not recognized in list. Add it and set up new array. */
+ np++;
+ if (np>hb->per->nper)
+ gmx_fatal(FARGS, "Too many pshifts. Something's utterly wrong here.");
+ if (m>=mMax) { /* Extend the arrays.
+ * Doing it like this, using mMax to keep track of the sizes,
+ * eleviates the need for freeing and re-allocating the arrays
+ * when taking on the next donor-acceptor pair */
+ mMax = m;
+ srenew(pfound,np); /* The list of found periodic shifts. */
+ srenew(rHbExGem,np); /* The hb existence functions (-aver_hb). */
+ snew(rHbExGem[m],2*n2);
+ srenew(poff,np);
+ }
+
+/* This shouldn't have to be critical, right? */
+/* #ifdef HAVE_OPENMP */
+/* #pragma omp critical */
+/* #endif */
+ {
+ if (rHbExGem != NULL && rHbExGem[m] != NULL) {
+ /* This must be done, as this array was most likey
+ * used to store stuff in some previous iteration. */
+ memset(rHbExGem[m], 0, (sizeof(real)) * (2*n2));
+ }
+ else
+ fprintf(stderr, "rHbExGem not initialized! m = %i\n", m);
+ }
+ pfound[m] = p;
+ poff[m] = -1;
+
+ break;
+ } /* m==np */
+ if (p == pfound[m])
+ break;
+ } /* m: Loop over found shifts */
+ } /* j: Loop over shifts */
+
+ /* Now unpack and disentangle the existence funtions. */
+ for (j=0; j<nf; j++) {
+ /* i: donor,
+ * k: acceptor
+ * nh: hydrogen
+ * j: time
+ * p: periodic shift
+ * pfound: list of periodic shifts found for this pair.
+ * poff: list of frame offsets; that is, the first
+ * frame a hbond has a particular periodic shift. */
+ p = getPshift(*pHist, j+n0);
+ if (p != -1)
+ {
+ for (m=0; m<np; m++)
+ {
+ if (pfound[m] == p)
+ break;
+ if (m==(np-1))
+ gmx_fatal(FARGS,"Shift not found, but must be there.");
+ }
+
+ ihb = is_hb(h[nh],j) || ((hb->per->gemtype!=gemAD || j==0) ? FALSE : is_hb(g[nh],j));
+ if (ihb)
+ {
+ if (poff[m] == -1)
+ poff[m] = j; /* Here's where the first hbond with shift p is,
+ * relative to the start of h[0].*/
+ if (j<poff[m])
+ gmx_fatal(FARGS, "j<poff[m]");
+ rHbExGem[m][j-poff[m]] += 1;
+ }
+ }
+ }
+
+ /* Now, build ac. */
+ for (m=0; m<np; m++) {
+ if (rHbExGem[m][0]>0 && n0+poff[m]<nn/* && m==0 */) {
+ low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&(rHbExGem[m]),hb->time[1]-hb->time[0],
+ eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
+ for(j=0; (j<nn); j++)
+ __ACDATA[j] += rHbExGem[m][j];
+ }
+ } /* Building of ac. */
+ } /* if (ISHB(...*/
+ } /* if (hbh) */
+ } /* hydrogen loop */
+ } /* acceptor loop */
+ } /* donor loop */
+
+ for (m=0; m<=mMax; m++) {
+ sfree(rHbExGem[m]);
+ }
+ sfree(pfound);
+ sfree(poff);
+ sfree(rHbExGem);
+
+ sfree(h);
+ sfree(g);
+#ifdef HAVE_OPENMP /* =======================================\ */
+#pragma omp critical
+ {
+ for (i=0; i<nn; i++)
+ ct[i] += p_ct[i];
+ }
+ sfree(p_ct);
+
+ } /* ########## THE END OF THE ENORMOUS PARALLELIZED BLOCK ########## */
+ sfree(dondata);
+#endif /* HAVE_OPENMP =======================================/ */
+
+ normalizeACF(ct, NULL, nn);
+
+ fprintf(stderr, "\n\nACF successfully calculated.\n");
+
+ /* Use this part to fit to geminate recombination - JCP 129, 84505 (2008) */
+
+ snew(ctdouble, nn);
+ snew(timedouble, nn);
+ snew(fittedct, nn);
+
+ for (j=0;j<nn;j++){
+ timedouble[j]=(double)(hb->time[j]);
+ ctdouble[j]=(double)(ct[j]);
+ }
+
+ /* Remove ballistic term */
+ /* Ballistic component removal and fitting to the reversible geminate recombination model
+ * will be taken out for the time being. First of all, one can remove the ballistic
+ * component with g_analyze afterwards. Secondly, and more importantly, there are still
+ * problems with the robustness of the fitting to the model. More work is needed.
+ * A third reason is that we're currently using gsl for this and wish to reduce dependence
+ * on external libraries. There are Levenberg-Marquardt and nsimplex solvers that come with
+ * a BSD-licence that can do the job.
+ *
+ * - Erik Marklund, June 18 2010.
+ */
+/* if (bBallistic) { */
+/* if (params->ballistic/params->tDelta >= params->nExpFit*2+1) */
+/* takeAwayBallistic(ctdouble, timedouble, nn, params->ballistic, params->nExpFit, params->bDt); */
+/* else */
+/* printf("\nNumber of data points is less than the number of parameters to fit\n." */
+/* "The system is underdetermined, hence no ballistic term can be found.\n\n"); */
+/* } */
+/* if (bGemFit) */
+/* fitGemRecomb(ctdouble, timedouble, &fittedct, nn, params); */
+
+
+ if (bContact)
+ fp = xvgropen(fn, "Contact Autocorrelation","Time (ps)","C(t)",oenv);
+ else
+ fp = xvgropen(fn, "Hydrogen Bond Autocorrelation","Time (ps)","C(t)",oenv);
+ xvgr_legend(fp,asize(legGem),legGem,oenv);
+
+ for(j=0; (j<nn); j++)
+ {
+ fprintf(fp, "%10g %10g", hb->time[j]-hb->time[0],ct[j]);
+ if (bBallistic)
+ fprintf(fp," %10g", ctdouble[j]);
+ if (bGemFit)
+ fprintf(fp," %10g", fittedct[j]);
+ fprintf(fp,"\n");
+ }
+ fclose(fp);
+
+ sfree(ctdouble);
+ sfree(timedouble);
+ sfree(fittedct);
+ sfree(ct);
+
+ break; /* case AC_GEM */
+
+ case AC_LUZAR:
+ snew(rhbex,2*n2);
+ snew(ct,2*n2);
+ snew(gt,2*n2);
+ snew(ht,2*n2);
+ snew(ght,2*n2);
+ snew(dght,2*n2);
+
+ snew(kt,nn);
+ snew(cct,nn);
+
+ for(i=0; (i<hb->d.nrd); i++) {
+ for(k=0; (k<hb->a.nra); k++) {
+ nhydro = 0;
+ hbh = hb->hbmap[i][k];
+
+ if (hbh) {
+ if (bMerge || bContact) {
+ if (ISHB(hbh->history[0])) {
+ h[0] = hbh->h[0];
+ g[0] = hbh->g[0];
+ nhydro = 1;
+ }
+ }
+ else {
+ for(m=0; (m<hb->maxhydro); m++)
+ if (bContact ? ISDIST(hbh->history[m]) : ISHB(hbh->history[m])) {
+ g[nhydro] = hbh->g[m];
+ h[nhydro] = hbh->h[m];
+ nhydro++;
+ }
+ }
+
+ nf = hbh->nframes;
+ for(nh=0; (nh<nhydro); nh++) {
+ int nrint = bContact ? hb->nrdist : hb->nrhb;
+ if ((((nhbonds+1) % 10) == 0) || (nhbonds+1 == nrint))
+ fprintf(stderr,"\rACF %d/%d",nhbonds+1,nrint);
+ nhbonds++;
+ for(j=0; (j<nframes); j++) {
+ /* Changed '<' into '<=' below, just like I did in
+ the hbm-output-loop in the gmx_hbond() block.
+ - Erik Marklund, May 31, 2006 */
+ if (j <= nf) {
+ ihb = is_hb(h[nh],j);
+ idist = is_hb(g[nh],j);
+ }
+ else {
+ ihb = idist = 0;
+ }
+ rhbex[j] = ihb-aver_nhb;
+ /* For contacts: if a second cut-off is provided, use it,
+ * otherwise use g(t) = 1-h(t) */
+ if (!R2 && bContact)
+ gt[j] = 1-ihb;
+ else
+ gt[j] = idist*(1-ihb);
+ ht[j] = rhbex[j];
+ nhb += ihb;
+ }
- /* The autocorrelation function is normalized after summation only */
- low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&rhbex,
- hb->time[1]-hb->time[0],
- eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
+
+ /* The autocorrelation function is normalized after summation only */
+ low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&rhbex,hb->time[1]-hb->time[0],
+ eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
- /* Cross correlation analysis for thermodynamics */
- for(j=nframes; (j<n2); j++) {
- ht[j] = 0;
- gt[j] = 0;
- }
+ /* Cross correlation analysis for thermodynamics */
+ for(j=nframes; (j<n2); j++) {
+ ht[j] = 0;
+ gt[j] = 0;
+ }
- cross_corr(n2,ht,gt,dght);
+ cross_corr(n2,ht,gt,dght);
- for(j=0; (j<nn); j++) {
- ct[j] += rhbex[j];
- ght[j] += dght[j];
- }
- }
- }
- }
- }
- fprintf(stderr,"\n");
-
- /* Normalize */
- ct_fac = 1.0/ct[0];
- ght_fac = 1.0/nhb;
- printf("Normalization for c(t) = %g for gh(t) = %g\n",ct_fac,ght_fac);
- for(j=0; (j<nn); j++) {
- ct[j] *= ct_fac;
- ght[j] *= ght_fac;
- /* Xu and Berne use the same normalization constant */
- }
-
- /* Determine tail value for statistics */
- tail = 0;
- tail2 = 0;
- for(j=nn/2; (j<nn); j++) {
- tail += ct[j];
- tail2 += ct[j]*ct[j];
- }
- tail /= (nn - nn/2);
- tail2 /= (nn - nn/2);
- dtail = sqrt(tail2-tail*tail);
-
- /* Check whether the ACF is long enough */
- if (dtail > tol) {
- printf("\nWARNING: Correlation function is probably not long enough\n"
- "because the standard deviation in the tail of C(t) > %g\n"
- "Tail value (average C(t) over second half of acf): %g +/- %g\n",
- tol,tail,dtail);
- }
- for(j=0; (j<nn); j++) {
- cct[j] = ct[j];
- ct[j] = (cct[j]-tail)/(1-tail);
- }
- /* Compute negative derivative k(t) = -dc(t)/dt */
- compute_derivative(nn,hb->time,ct,kt);
- for(j=0; (j<nn); j++)
- kt[j] = -kt[j];
-
- if (bContact)
- fp = xvgropen(fn, "Contact Autocorrelation","Time (ps)","C(t)",oenv);
- else
- fp = xvgropen(fn, "Hydrogen Bond Autocorrelation","Time (ps)","C(t)",oenv);
- xvgr_legend(fp,asize(leg),leg,oenv);
-
- for(j=0; (j<nn); j++)
- fprintf(fp,"%10g %10g %10g %10g %10g\n",
- hb->time[j]-hb->time[0],ct[j],cct[j],ght[j],kt[j]);
- ffclose(fp);
-
- analyse_corr(nn,hb->time,ct,ght,kt,NULL,NULL,NULL,
- fit_start,temp,smooth_tail_start,oenv);
-
- do_view(oenv,fn,NULL);
- sfree(rhbex);
- sfree(ct);
- sfree(gt);
- sfree(ht);
- sfree(ght);
- sfree(dght);
- sfree(cct);
- sfree(kt);
- sfree(h);
- sfree(g);
+ for(j=0; (j<nn); j++) {
+ ct[j] += rhbex[j];
+ ght[j] += dght[j];
+ }
+ }
+ }
+ }
+ }
+ fprintf(stderr,"\n");
+ sfree(h);
+ sfree(g);
+ normalizeACF(ct, gt, nn);
+
+ /* Determine tail value for statistics */
+ tail = 0;
+ tail2 = 0;
+ for(j=nn/2; (j<nn); j++) {
+ tail += ct[j];
+ tail2 += ct[j]*ct[j];
+ }
+ tail /= (nn - nn/2);
+ tail2 /= (nn - nn/2);
+ dtail = sqrt(tail2-tail*tail);
+
+ /* Check whether the ACF is long enough */
+ if (dtail > tol) {
+ printf("\nWARNING: Correlation function is probably not long enough\n"
+ "because the standard deviation in the tail of C(t) > %g\n"
+ "Tail value (average C(t) over second half of acf): %g +/- %g\n",
+ tol,tail,dtail);
+ }
+ for(j=0; (j<nn); j++) {
+ cct[j] = ct[j];
+ ct[j] = (cct[j]-tail)/(1-tail);
+ }
+ /* Compute negative derivative k(t) = -dc(t)/dt */
+ compute_derivative(nn,hb->time,ct,kt);
+ for(j=0; (j<nn); j++)
+ kt[j] = -kt[j];
+
+
+ if (bContact)
+ fp = xvgropen(fn, "Contact Autocorrelation","Time (ps)","C(t)",oenv);
+ else
+ fp = xvgropen(fn, "Hydrogen Bond Autocorrelation","Time (ps)","C(t)",oenv);
+ xvgr_legend(fp,asize(legLuzar),legLuzar, oenv);
+
+
+ for(j=0; (j<nn); j++)
+ fprintf(fp,"%10g %10g %10g %10g %10g\n",
+ hb->time[j]-hb->time[0],ct[j],cct[j],ght[j],kt[j]);
+ ffclose(fp);
+
+ analyse_corr(nn,hb->time,ct,ght,kt,NULL,NULL,NULL,
+ fit_start,temp,smooth_tail_start,oenv);
+
+ do_view(oenv,fn,NULL);
+ sfree(rhbex);
+ sfree(ct);
+ sfree(gt);
+ sfree(ht);
+ sfree(ght);
+ sfree(dght);
+ sfree(cct);
+ sfree(kt);
+ /* sfree(h); */
+/* sfree(g); */
+
+ break; /* case AC_LUZAR */
+
+ default:
+ gmx_fatal(FARGS, "Unrecognized type of ACF-calulation. acType = %i.", acType);
+ } /* switch (acType) */
}
static void init_hbframe(t_hbdata *hb,int nframes,real t)
{
- int i,j,m;
-
- hb->time[nframes] = t;
- hb->nhb[nframes] = 0;
- hb->ndist[nframes] = 0;
- for (i=0; (i<max_hx); i++)
- hb->nhx[nframes][i]=0;
- /* Loop invalidated */
- if (hb->bHBmap && 0)
- for (i=0; (i<hb->d.nrd); i++)
- for (j=0; (j<hb->a.nra); j++)
- for (m=0; (m<hb->maxhydro); m++)
- if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[m])
- set_hb(hb,i,m,j,nframes,HB_NO);
- /*set_hb(hb->hbmap[i][j]->h[m],nframes-hb->hbmap[i][j]->n0,HB_NO);*/
+ int i,j,m;
+
+ hb->time[nframes] = t;
+ hb->nhb[nframes] = 0;
+ hb->ndist[nframes] = 0;
+ for (i=0; (i<max_hx); i++)
+ hb->nhx[nframes][i]=0;
+ /* Loop invalidated */
+ if (hb->bHBmap && 0)
+ for (i=0; (i<hb->d.nrd); i++)
+ for (j=0; (j<hb->a.nra); j++)
+ for (m=0; (m<hb->maxhydro); m++)
+ if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[m])
+ set_hb(hb,i,m,j,nframes,HB_NO);
+ /*set_hb(hb->hbmap[i][j]->h[m],nframes-hb->hbmap[i][j]->n0,HB_NO);*/
}
static void analyse_donor_props(const char *fn,t_hbdata *hb,int nframes,real t,
const output_env_t oenv)
{
- static FILE *fp = NULL;
- char *leg[] = { "Nbound", "Nfree" };
- int i,j,k,nbound,nb,nhtot;
+ static FILE *fp = NULL;
+ char *leg[] = { "Nbound", "Nfree" };
+ int i,j,k,nbound,nb,nhtot;
- if (!fn)
- return;
- if (!fp) {
- fp = xvgropen(fn,"Donor properties","Time (ps)","Number",oenv);
- xvgr_legend(fp,asize(leg),leg,oenv);
- }
- nbound = 0;
- nhtot = 0;
- for(i=0; (i<hb->d.nrd); i++) {
- for(k=0; (k<hb->d.nhydro[i]); k++) {
- nb = 0;
- nhtot ++;
- for(j=0; (j<hb->a.nra) && (nb == 0); j++) {
- if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[k] &&
- is_hb(hb->hbmap[i][j]->h[k],nframes))
- nb = 1;
- }
- nbound += nb;
- }
- }
- fprintf(fp,"%10.3e %6d %6d\n",t,nbound,nhtot-nbound);
+ if (!fn)
+ return;
+ if (!fp) {
+ fp = xvgropen(fn,"Donor properties","Time (ps)","Number",oenv);
+ xvgr_legend(fp,asize(leg),leg,oenv);
+ }
+ nbound = 0;
+ nhtot = 0;
+ for(i=0; (i<hb->d.nrd); i++) {
+ for(k=0; (k<hb->d.nhydro[i]); k++) {
+ nb = 0;
+ nhtot ++;
+ for(j=0; (j<hb->a.nra) && (nb == 0); j++) {
+ if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[k] &&
+ is_hb(hb->hbmap[i][j]->h[k],nframes))
+ nb = 1;
+ }
+ nbound += nb;
+ }
+ }
+ fprintf(fp,"%10.3e %6d %6d\n",t,nbound,nhtot-nbound);
}
static void dump_hbmap(t_hbdata *hb,
- int nfile,t_filenm fnm[],bool bTwo,bool bInsert,
- bool bContact, int isize[],int *index[],char *grpnames[],
- t_atoms *atoms)
+ int nfile,t_filenm fnm[],bool bTwo,bool bInsert,
+ bool bContact, int isize[],int *index[],char *grpnames[],
+ t_atoms *atoms)
{
- FILE *fp,*fplog;
- int ddd,hhh,aaa,i,j,k,m,grp;
- char ds[32],hs[32],as[32];
- bool first;
-
- fp = opt2FILE("-hbn",nfile,fnm,"w");
- if (opt2bSet("-g",nfile,fnm)) {
- fplog = ffopen(opt2fn("-g",nfile,fnm),"w");
- if (bContact)
- fprintf(fplog,"# %10s %12s %12s\n","Donor","Hydrogen","Acceptor");
+ FILE *fp,*fplog;
+ int ddd,hhh,aaa,i,j,k,m,grp;
+ char ds[32],hs[32],as[32];
+ bool first;
+
+ fp = opt2FILE("-hbn",nfile,fnm,"w");
+ if (opt2bSet("-g",nfile,fnm)) {
+ fplog = ffopen(opt2fn("-g",nfile,fnm),"w");
+ if (bContact)
+ fprintf(fplog,"# %10s %12s %12s\n","Donor","Hydrogen","Acceptor");
+ else
+ fprintf(fplog,"# %10s %12s %12s\n","Donor","Hydrogen","Acceptor");
+ }
else
- fprintf(fplog,"# %10s %12s %12s\n","Donor","Hydrogen","Acceptor");
- }
- else
- fplog = NULL;
- for (grp=gr0; grp<=(bTwo?gr1:gr0); grp++) {
- fprintf(fp,"[ %s ]",grpnames[grp]);
- for (i=0; i<isize[grp]; i++) {
- fprintf(fp,(i%15)?" ":"\n");
- fprintf(fp," %4u",index[grp][i]+1);
+ fplog = NULL;
+ for (grp=gr0; grp<=(bTwo?gr1:gr0); grp++) {
+ fprintf(fp,"[ %s ]",grpnames[grp]);
+ for (i=0; i<isize[grp]; i++) {
+ fprintf(fp,(i%15)?" ":"\n");
+ fprintf(fp," %4u",index[grp][i]+1);
+ }
+ fprintf(fp,"\n");
+ /*
+ Added -contact support below.
+ - Erik Marklund, May 29, 2006
+ */
+ if (!bContact) {
+ fprintf(fp,"[ donors_hydrogens_%s ]\n",grpnames[grp]);
+ for (i=0; (i<hb->d.nrd); i++) {
+ if (hb->d.grp[i] == grp) {
+ for(j=0; (j<hb->d.nhydro[i]); j++)
+ fprintf(fp," %4u %4u",hb->d.don[i]+1,
+ hb->d.hydro[i][j]+1);
+ fprintf(fp,"\n");
+ }
+ }
+ first = TRUE;
+ fprintf(fp,"[ acceptors_%s ]",grpnames[grp]);
+ for (i=0; (i<hb->a.nra); i++) {
+ if (hb->a.grp[i] == grp) {
+ fprintf(fp,(i%15 && !first)?" ":"\n");
+ fprintf(fp," %4u",hb->a.acc[i]+1);
+ first = FALSE;
+ }
+ }
+ fprintf(fp,"\n");
+ }
}
- fprintf(fp,"\n");
- /*
- Added -contact support below.
- - Erik Marklund, May 29, 2006
- */
- if (!bContact) {
- fprintf(fp,"[ donors_hydrogens_%s ]\n",grpnames[grp]);
- for (i=0; (i<hb->d.nrd); i++) {
- if (hb->d.grp[i] == grp) {
- for(j=0; (j<hb->d.nhydro[i]); j++)
- fprintf(fp," %4u %4u",hb->d.don[i]+1,
- hb->d.hydro[i][j]+1);
- fprintf(fp,"\n");
- }
- }
- first = TRUE;
- fprintf(fp,"[ acceptors_%s ]",grpnames[grp]);
- for (i=0; (i<hb->a.nra); i++) {
- if (hb->a.grp[i] == grp) {
- fprintf(fp,(i%15 && !first)?" ":"\n");
- fprintf(fp," %4u",hb->a.acc[i]+1);
- first = FALSE;
- }
- }
- fprintf(fp,"\n");
- }
- }
- if (bTwo)
- fprintf(fp,bContact ? "[ contacts_%s-%s ]\n" :
- "[ hbonds_%s-%s ]\n",grpnames[0],grpnames[1]);
- else
- fprintf(fp,bContact ? "[ contacts_%s ]" : "[ hbonds_%s ]\n",grpnames[0]);
-
- for(i=0; (i<hb->d.nrd); i++) {
- ddd = hb->d.don[i];
- for(k=0; (k<hb->a.nra); k++) {
- aaa = hb->a.acc[k];
- for(m=0; (m<hb->d.nhydro[i]); m++) {
- if (hb->hbmap[i][k] && ISHB(hb->hbmap[i][k]->history[m])) {
- sprintf(ds,"%s",mkatomname(atoms,ddd));
- sprintf(as,"%s",mkatomname(atoms,aaa));
- if (bContact) {
- fprintf(fp," %6u %6u\n",ddd+1,aaa+1);
- if (fplog)
- fprintf(fplog,"%12s %12s\n",ds,as);
- } else {
- hhh = hb->d.hydro[i][m];
- sprintf(hs,"%s",mkatomname(atoms,hhh));
- fprintf(fp," %6u %6u %6u\n",ddd+1,hhh+1,aaa+1);
- if (fplog)
- fprintf(fplog,"%12s %12s %12s\n",ds,hs,as);
- }
- }
- }
- }
- }
- if (bInsert) {
if (bTwo)
- fprintf(fp,"[ insert_%s->%s-%s ]",
- grpnames[2],grpnames[0],grpnames[1]);
+ fprintf(fp,bContact ? "[ contacts_%s-%s ]\n" :
+ "[ hbonds_%s-%s ]\n",grpnames[0],grpnames[1]);
else
- fprintf(fp,"[ insert_%s->%s ]",grpnames[2],grpnames[0]);
- j=0;
+ fprintf(fp,bContact ? "[ contacts_%s ]" : "[ hbonds_%s ]\n",grpnames[0]);
+
+ for(i=0; (i<hb->d.nrd); i++) {
+ ddd = hb->d.don[i];
+ for(k=0; (k<hb->a.nra); k++) {
+ aaa = hb->a.acc[k];
+ for(m=0; (m<hb->d.nhydro[i]); m++) {
+ if (hb->hbmap[i][k] && ISHB(hb->hbmap[i][k]->history[m])) {
+ sprintf(ds,"%s",mkatomname(atoms,ddd));
+ sprintf(as,"%s",mkatomname(atoms,aaa));
+ if (bContact) {
+ fprintf(fp," %6u %6u\n",ddd+1,aaa+1);
+ if (fplog)
+ fprintf(fplog,"%12s %12s\n",ds,as);
+ } else {
+ hhh = hb->d.hydro[i][m];
+ sprintf(hs,"%s",mkatomname(atoms,hhh));
+ fprintf(fp," %6u %6u %6u\n",ddd+1,hhh+1,aaa+1);
+ if (fplog)
+ fprintf(fplog,"%12s %12s %12s\n",ds,hs,as);
+ }
+ }
+ }
+ }
+ }
+ if (bInsert) {
+ if (bTwo)
+ fprintf(fp,"[ insert_%s->%s-%s ]",
+ grpnames[2],grpnames[0],grpnames[1]);
+ else
+ fprintf(fp,"[ insert_%s->%s ]",grpnames[2],grpnames[0]);
+ j=0;
- /* for(i=0; (i<hb->nrhb); i++) {
- if (hb->hb[i].bInsert) {
- fprintf(fp,(j%15)?" ":"\n");
- fprintf(fp,"%4d",i+1);
- j++;
- }
- }*/
- fprintf(fp,"\n");
- }
- ffclose(fp);
- if (fplog)
- ffclose(fplog);
+ /* for(i=0; (i<hb->nrhb); i++) {
+ if (hb->hb[i].bInsert) {
+ fprintf(fp,(j%15)?" ":"\n");
+ fprintf(fp,"%4d",i+1);
+ j++;
+ }
+ }*/
+ fprintf(fp,"\n");
+ }
+ ffclose(fp);
+ if (fplog)
+ ffclose(fplog);
}
+#ifdef HAVE_OPENMP
+/* sync_hbdata() updates the parallel t_hbdata p_hb using hb as template.
+ * It mimics add_frames() and init_frame() to some extent. */
+static void sync_hbdata(t_hbdata *hb, t_hbdata *p_hb,
+ int nframes, real t)
+{
+ int i;
+ if (nframes >= p_hb->max_frames)
+ {
+ p_hb->max_frames += 4096;
+ srenew(p_hb->nhb, p_hb->max_frames);
+ srenew(p_hb->ndist, p_hb->max_frames);
+ srenew(p_hb->n_bound, p_hb->max_frames);
+ srenew(p_hb->nhx, p_hb->max_frames);
+ if (p_hb->bDAnr)
+ srenew(p_hb->danr, p_hb->max_frames);
+ memset(&(p_hb->nhb[nframes]), 0, sizeof(int) * (p_hb->max_frames-nframes));
+ memset(&(p_hb->ndist[nframes]), 0, sizeof(int) * (p_hb->max_frames-nframes));
+ p_hb->nhb[nframes] = 0;
+ p_hb->ndist[nframes] = 0;
+
+ }
+ p_hb->nframes = nframes;
+/* for (i=0;) */
+/* { */
+/* p_hb->nhx[nframes][i] */
+/* } */
+ memset(&(p_hb->nhx[nframes]), 0 ,sizeof(int)*max_hx); /* zero the helix count for this frame */
+
+ /* hb->per will remain constant througout the frame loop,
+ * even though the data its members point to will change,
+ * hence no need for re-syncing. */
+}
+#endif
+
int gmx_hbond(int argc,char *argv[])
{
- const char *desc[] = {
- "g_hbond computes and analyzes hydrogen bonds. Hydrogen bonds are",
- "determined based on cutoffs for the angle Acceptor - Donor - Hydrogen",
- "(zero is extended) and the distance Hydrogen - Acceptor.",
- "OH and NH groups are regarded as donors, O is an acceptor always,",
- "N is an acceptor by default, but this can be switched using",
- "[TT]-nitacc[tt]. Dummy hydrogen atoms are assumed to be connected",
- "to the first preceding non-hydrogen atom.[PAR]",
+ const char *desc[] = {
+ "g_hbond computes and analyzes hydrogen bonds. Hydrogen bonds are",
+ "determined based on cutoffs for the angle Acceptor - Donor - Hydrogen",
+ "(zero is extended) and the distance Hydrogen - Acceptor.",
+ "OH and NH groups are regarded as donors, O is an acceptor always,",
+ "N is an acceptor by default, but this can be switched using",
+ "[TT]-nitacc[tt]. Dummy hydrogen atoms are assumed to be connected",
+ "to the first preceding non-hydrogen atom.[PAR]",
- "You need to specify two groups for analysis, which must be either",
- "identical or non-overlapping. All hydrogen bonds between the two",
- "groups are analyzed.[PAR]",
+ "You need to specify two groups for analysis, which must be either",
+ "identical or non-overlapping. All hydrogen bonds between the two",
+ "groups are analyzed.[PAR]",
- "If you set -shell, you will be asked for an additional index group",
- "which should contain exactly one atom. In this case, only hydrogen",
- "bonds between atoms within the shell distance from the one atom are",
- "considered.[PAR]"
+ "If you set -shell, you will be asked for an additional index group",
+ "which should contain exactly one atom. In this case, only hydrogen",
+ "bonds between atoms within the shell distance from the one atom are",
+ "considered.[PAR]",
- /* "It is also possible to analyse specific hydrogen bonds with",
- "[TT]-sel[tt]. This index file must contain a group of atom triplets",
- "Donor Hydrogen Acceptor, in the following way:[PAR]",
- */
- "[TT]",
- "[ selected ][BR]",
- " 20 21 24[BR]",
- " 25 26 29[BR]",
- " 1 3 6[BR]",
- "[tt][BR]",
- "Note that the triplets need not be on separate lines.",
- "Each atom triplet specifies a hydrogen bond to be analyzed,",
- "note also that no check is made for the types of atoms.[PAR]",
+ /* "It is also possible to analyse specific hydrogen bonds with",
+ "[TT]-sel[tt]. This index file must contain a group of atom triplets",
+ "Donor Hydrogen Acceptor, in the following way:[PAR]",
+ */
+ "[TT]",
+ "[ selected ][BR]",
+ " 20 21 24[BR]",
+ " 25 26 29[BR]",
+ " 1 3 6[BR]",
+ "[tt][BR]",
+ "Note that the triplets need not be on separate lines.",
+ "Each atom triplet specifies a hydrogen bond to be analyzed,",
+ "note also that no check is made for the types of atoms.[PAR]",
- "[TT]-ins[tt] turns on computing solvent insertion into hydrogen bonds.",
- "In this case an additional group must be selected, specifying the",
- "solvent molecules.[PAR]",
+ "[TT]-ins[tt] turns on computing solvent insertion into hydrogen bonds.",
+ "In this case an additional group must be selected, specifying the",
+ "solvent molecules.[PAR]",
- "[BB]Output:[bb][BR]",
- "[TT]-num[tt]: number of hydrogen bonds as a function of time.[BR]",
- "[TT]-ac[tt]: average over all autocorrelations of the existence",
- "functions (either 0 or 1) of all hydrogen bonds.[BR]",
- "[TT]-dist[tt]: distance distribution of all hydrogen bonds.[BR]",
- "[TT]-ang[tt]: angle distribution of all hydrogen bonds.[BR]",
- "[TT]-hx[tt]: the number of n-n+i hydrogen bonds as a function of time",
- "where n and n+i stand for residue numbers and i ranges from 0 to 6.",
- "This includes the n-n+3, n-n+4 and n-n+5 hydrogen bonds associated",
- "with helices in proteins.[BR]",
- "[TT]-hbn[tt]: all selected groups, donors, hydrogens and acceptors",
- "for selected groups, all hydrogen bonded atoms from all groups and",
- "all solvent atoms involved in insertion.[BR]",
- "[TT]-hbm[tt]: existence matrix for all hydrogen bonds over all",
- "frames, this also contains information on solvent insertion",
- "into hydrogen bonds. Ordering is identical to that in [TT]-hbn[tt]",
- "index file.[BR]",
- "[TT]-dan[tt]: write out the number of donors and acceptors analyzed for",
- "each timeframe. This is especially usefull when using [TT]-shell[tt].[BR]",
- "[TT]-nhbdist[tt]: compute the number of HBonds per hydrogen in order to",
- "compare results to Raman Spectroscopy.",
- "[PAR]",
- "Note: options [TT]-ac[tt], [TT]-life[tt], [TT]-hbn[tt] and [TT]-hbm[tt]",
- "require an amount of memory proportional to the total numbers of donors",
- "times the total number of acceptors in the selected group(s)."
- };
-
- static real acut=30, abin=1, rcut=0.35, r2cut=0, rbin=0.005, rshell=-1;
- static real maxnhb=0,fit_start=1,temp=298.15,smooth_tail_start=-1;
- static bool bNitAcc=TRUE,bInsert=FALSE,bDA=TRUE,bMerge=TRUE;
- static int nDump=0;
- static bool bContact=FALSE;
- /* options */
- t_pargs pa [] = {
- { "-ins", FALSE, etBOOL, {&bInsert},
- "Analyze solvent insertion" },
- { "-a", FALSE, etREAL, {&acut},
- "Cutoff angle (degrees, Acceptor - Donor - Hydrogen)" },
- { "-r", FALSE, etREAL, {&rcut},
- "Cutoff radius (nm, X - Acceptor, see next option)" },
- { "-da", FALSE, etBOOL, {&bDA},
- "Use distance Donor-Acceptor (if TRUE) or Hydrogen-Acceptor (FALSE)" },
- { "-r2", FALSE, etREAL, {&r2cut},
- "Second cutoff radius. Mainly useful with -contact and -ac"},
- { "-abin", FALSE, etREAL, {&abin},
- "Binwidth angle distribution (degrees)" },
- { "-rbin", FALSE, etREAL, {&rbin},
- "Binwidth distance distribution (nm)" },
- { "-nitacc",FALSE, etBOOL, {&bNitAcc},
- "Regard nitrogen atoms as acceptors" },
- { "-contact",FALSE,etBOOL, {&bContact},
- "Do not look for hydrogen bonds, but merely for contacts within the cut-off distance" },
- { "-shell", FALSE, etREAL, {&rshell},
- "when > 0, only calculate hydrogen bonds within # nm shell around "
- "one particle" },
- { "-fitstart", FALSE, etREAL, {&fit_start},
- "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" },
- { "-temp", FALSE, etREAL, {&temp},
- "Temperature (K) for computing the Gibbs energy corresponding to HB breaking and reforming" },
- { "-smooth",FALSE, etREAL, {&smooth_tail_start},
- "If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/tau)" },
- { "-dump", FALSE, etINT, {&nDump},
- "Dump the first N hydrogen bond ACFs in a single xvg file for debugging" },
- { "-max_hb",FALSE, etREAL, {&maxnhb},
- "Theoretical maximum number of hydrogen bonds used for normalizing HB autocorrelation function. Can be useful in case the program estimates it wrongly" },
- { "-merge", FALSE, etBOOL, {&bMerge},
- "H-bonds between the same donor and acceptor, but with different hydrogen are treated as a single H-bond. Mainly important for the ACF." }
- };
- const char *bugs[] = {
- "The option [TT]-sel[tt] that used to work on selected hbonds is out of order, and therefore not available for the time being."
- };
- t_filenm fnm[] = {
- { efTRX, "-f", NULL, ffREAD },
- { efTPX, NULL, NULL, ffREAD },
- { efNDX, NULL, NULL, ffOPTRD },
- /* { efNDX, "-sel", "select", ffOPTRD },*/
- { efXVG, "-num", "hbnum", ffWRITE },
- { efLOG, "-g", "hbond", ffOPTWR },
- { efXVG, "-ac", "hbac", ffOPTWR },
- { efXVG, "-dist","hbdist", ffOPTWR },
- { efXVG, "-ang", "hbang", ffOPTWR },
- { efXVG, "-hx", "hbhelix",ffOPTWR },
- { efNDX, "-hbn", "hbond", ffOPTWR },
- { efXPM, "-hbm", "hbmap", ffOPTWR },
- { efXVG, "-don", "donor", ffOPTWR },
- { efXVG, "-dan", "danum", ffOPTWR },
- { efXVG, "-life","hblife", ffOPTWR },
- { efXVG, "-nhbdist", "nhbdist",ffOPTWR }
+ "[BB]Output:[bb][BR]",
+ "[TT]-num[tt]: number of hydrogen bonds as a function of time.[BR]",
+ "[TT]-ac[tt]: average over all autocorrelations of the existence",
+ "functions (either 0 or 1) of all hydrogen bonds.[BR]",
+ "[TT]-dist[tt]: distance distribution of all hydrogen bonds.[BR]",
+ "[TT]-ang[tt]: angle distribution of all hydrogen bonds.[BR]",
+ "[TT]-hx[tt]: the number of n-n+i hydrogen bonds as a function of time",
+ "where n and n+i stand for residue numbers and i ranges from 0 to 6.",
+ "This includes the n-n+3, n-n+4 and n-n+5 hydrogen bonds associated",
+ "with helices in proteins.[BR]",
+ "[TT]-hbn[tt]: all selected groups, donors, hydrogens and acceptors",
+ "for selected groups, all hydrogen bonded atoms from all groups and",
+ "all solvent atoms involved in insertion.[BR]",
+ "[TT]-hbm[tt]: existence matrix for all hydrogen bonds over all",
+ "frames, this also contains information on solvent insertion",
+ "into hydrogen bonds. Ordering is identical to that in [TT]-hbn[tt]",
+ "index file.[BR]",
+ "[TT]-dan[tt]: write out the number of donors and acceptors analyzed for",
+ "each timeframe. This is especially useful when using [TT]-shell[tt].[BR]",
+ "[TT]-nhbdist[tt]: compute the number of HBonds per hydrogen in order to",
+ "compare results to Raman Spectroscopy.",
+ "[PAR]",
+ "Note: options [TT]-ac[tt], [TT]-life[tt], [TT]-hbn[tt] and [TT]-hbm[tt]",
+ "require an amount of memory proportional to the total numbers of donors",
+ "times the total number of acceptors in the selected group(s)."
+ };
+
+ static real acut=30, abin=1, rcut=0.35, r2cut=0, rbin=0.005, rshell=-1;
+ static real maxnhb=0,fit_start=1,fit_end=60,temp=298.15,smooth_tail_start=-1, D=-1;
+ static bool bNitAcc=TRUE,bInsert=FALSE,bDA=TRUE,bMerge=TRUE;
+ static int nDump=0, nFitPoints=100;
+ static int nThreads = 0, nBalExp=4;
+
+ static bool bContact=FALSE, bBallistic=FALSE, bBallisticDt=FALSE, bGemFit=FALSE;
+ static real logAfterTime = 10, gemBallistic = 0.2; /* ps */
+ static const char *NNtype[] = {NULL, "none", "binary", "oneOverR3", "dipole", NULL};
+
+ /* options */
+ t_pargs pa [] = {
+ { "-ins", FALSE, etBOOL, {&bInsert},
+ "Analyze solvent insertion" },
+ { "-a", FALSE, etREAL, {&acut},
+ "Cutoff angle (degrees, Acceptor - Donor - Hydrogen)" },
+ { "-r", FALSE, etREAL, {&rcut},
+ "Cutoff radius (nm, X - Acceptor, see next option)" },
+ { "-da", FALSE, etBOOL, {&bDA},
+ "Use distance Donor-Acceptor (if TRUE) or Hydrogen-Acceptor (FALSE)" },
+ { "-r2", FALSE, etREAL, {&r2cut},
+ "Second cutoff radius. Mainly useful with -contact and -ac"},
+ { "-abin", FALSE, etREAL, {&abin},
+ "Binwidth angle distribution (degrees)" },
+ { "-rbin", FALSE, etREAL, {&rbin},
+ "Binwidth distance distribution (nm)" },
+ { "-nitacc",FALSE, etBOOL, {&bNitAcc},
+ "Regard nitrogen atoms as acceptors" },
+ { "-contact",FALSE,etBOOL, {&bContact},
+ "Do not look for hydrogen bonds, but merely for contacts within the cut-off distance" },
+ { "-shell", FALSE, etREAL, {&rshell},
+ "when > 0, only calculate hydrogen bonds within # nm shell around "
+ "one particle" },
+ { "-fitstart", FALSE, etREAL, {&fit_start},
+ "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. With -gemfit we suggest -fitstart 0" },
+ { "-fitstart", FALSE, etREAL, {&fit_start},
+ "Time (ps) to which to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation (only with -gemfit)" },
+ { "-temp", FALSE, etREAL, {&temp},
+ "Temperature (K) for computing the Gibbs energy corresponding to HB breaking and reforming" },
+ { "-smooth",FALSE, etREAL, {&smooth_tail_start},
+ "If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/tau)" },
+ { "-dump", FALSE, etINT, {&nDump},
+ "Dump the first N hydrogen bond ACFs in a single xvg file for debugging" },
+ { "-max_hb",FALSE, etREAL, {&maxnhb},
+ "Theoretical maximum number of hydrogen bonds used for normalizing HB autocorrelation function. Can be useful in case the program estimates it wrongly" },
+ { "-merge", FALSE, etBOOL, {&bMerge},
+ "H-bonds between the same donor and acceptor, but with different hydrogen are treated as a single H-bond. Mainly important for the ACF." },
+ { "-geminate", FALSE, etENUM, {gemType},
+ "Use reversible geminate recombination for the kinetics/thermodynamics calclations. See Markovitch et al., J. Chem. Phys 129, 084505 (2008) for details."},
+ { "-diff", FALSE, etREAL, {&D},
+ "Dffusion coefficient to use in the rev. gem. recomb. kinetic model. If non-positive, then it will be fitted to the ACF along with ka and kd."},
+#ifdef HAVE_OPENMP
+ { "-nthreads", FALSE, etINT, {&nThreads},
+ "Number of threads used for the parallel loop over autocorrelations. nThreads <= 0 means maximum number of threads. Requires linking with OpenMP. The number of threads is limited by the number of processors (before OpenMP v.3 ) or environment variable OMP_THREAD_LIMIT (OpenMP v.3)"},
+#endif
+ /* The ballistic/geminate fitting will be taken away temporarily sue to problems with stability. */
+/* { "-NN", FALSE, etENUM, {NNtype}, */
+/* "HIDDENDo a full all vs all loop and estimate the interaction energy instead of having a binary existence function for hydrogen bonds. NOT FULLY TESTED YET! DON'T USE IT!"}, */
+/* { "-gemfit", FALSE, etBOOL, {&bGemFit}, */
+/* "With -gemainate != none: fit ka and kd to the ACF"}, */
+/* { "-gemlogstart", FALSE, etREAL, {&logAfterTime}, */
+/* "HIDDENWith -gemfit: After this time (ps) the data points fitted to will be equidistant in log-time."}, */
+/* { "-gemnp", FALSE, etINT, {&nFitPoints}, */
+/* "HIDDENNuber of points in the ACF used to fit rev. gem. recomb. model"}, */
+/* { "-ballistic", FALSE, etBOOL, {&bBallistic}, */
+/* "Calculate and remove ultrafast \"ballistic\" component in the ACF"}, */
+/* { "-ballisticlen", FALSE, etREAL, {&gemBallistic}, */
+/* "HIDDENFitting interval for the ultrafast \"ballistic\" component in ACF"}, */
+/* { "-nbalexp", FALSE, etINT, {&nBalExp}, */
+/* "HIDDENNumber of exponentials to fit when removing the ballistic component"}, */
+/* { "-ballisticDt", FALSE, etBOOL, {&bBallisticDt}, */
+/* "HIDDENIf TRUE, finding of the fastest ballistic component will be based on the time derivative at t=0, " */
+/* "while if FALSE, it will be based on the exponent alone (like in Markovitch 2008)"} */
+ };
+ const char *bugs[] = {
+ "The option [TT]-sel[tt] that used to work on selected hbonds is out of order, and therefore not available for the time being."
+ };
+ t_filenm fnm[] = {
+ { efTRX, "-f", NULL, ffREAD },
+ { efTPX, NULL, NULL, ffREAD },
+ { efNDX, NULL, NULL, ffOPTRD },
+ /* { efNDX, "-sel", "select", ffOPTRD },*/
+ { efXVG, "-num", "hbnum", ffWRITE },
+ { efLOG, "-g", "hbond", ffOPTWR },
+ { efXVG, "-ac", "hbac", ffOPTWR },
+ { efXVG, "-dist","hbdist", ffOPTWR },
+ { efXVG, "-ang", "hbang", ffOPTWR },
+ { efXVG, "-hx", "hbhelix",ffOPTWR },
+ { efNDX, "-hbn", "hbond", ffOPTWR },
+ { efXPM, "-hbm", "hbmap", ffOPTWR },
+ { efXVG, "-don", "donor", ffOPTWR },
+ { efXVG, "-dan", "danum", ffOPTWR },
+ { efXVG, "-life","hblife", ffOPTWR },
+ { efXVG, "-nhbdist", "nhbdist",ffOPTWR }
- };
+ };
#define NFILE asize(fnm)
- char hbmap [HB_NR]={ ' ', 'o', '-', '*' };
- char *hbdesc[HB_NR]={ "None", "Present", "Inserted", "Present & Inserted" };
- t_rgb hbrgb [HB_NR]={ {1,1,1},{1,0,0}, {0,0,1}, {1,0,1} };
-
- int status;
- t_topology top;
- t_inputrec ir;
- t_pargs *ppa;
- int npargs,natoms,nframes=0,shatom;
- int *isize;
- char **grpnames;
- atom_id **index;
- rvec *x,hbox;
- matrix box;
- real t,ccut,dist,ang;
- double max_nhb,aver_nhb,aver_dist;
- int h,i,j,k,l,start,end,id,ja,ogrp,nsel;
- int xi,yi,zi,ai;
- int xj,yj,zj,aj,xjj,yjj,zjj;
- int xk,yk,zk,ak,xkk,ykk,zkk;
- bool bSelected,bHBmap,bStop,bTwo,was,bBox,bTric;
- int *adist,*rdist;
- int grp,nabin,nrbin,bin,resdist,ihb;
- char **leg;
- t_hbdata *hb;
- FILE *fp,*fpins=NULL,*fpnhb=NULL;
- t_gridcell ***grid;
- t_ncell *icell,*jcell,*kcell;
- ivec ngrid;
- unsigned char *datable;
- output_env_t oenv;
+ char hbmap [HB_NR]={ ' ', 'o', '-', '*' };
+ const char *hbdesc[HB_NR]={ "None", "Present", "Inserted", "Present & Inserted" };
+ t_rgb hbrgb [HB_NR]={ {1,1,1},{1,0,0}, {0,0,1}, {1,0,1} };
+
+ t_trxstatus *status;
+ int trrStatus=1;
+ t_topology top;
+ t_inputrec ir;
+ t_pargs *ppa;
+ int npargs,natoms,nframes=0,shatom;
+ int *isize;
+ char **grpnames;
+ atom_id **index;
+ rvec *x,hbox;
+ matrix box;
+ real t,ccut,dist,ang;
+ double max_nhb,aver_nhb,aver_dist;
+ int h,i,j,k=0,l,start,end,id,ja,ogrp,nsel;
+ int xi,yi,zi,ai;
+ int xj,yj,zj,aj,xjj,yjj,zjj;
+ int xk,yk,zk,ak,xkk,ykk,zkk;
+ bool bSelected,bHBmap,bStop,bTwo,was,bBox,bTric;
+ int *adist,*rdist;
+ int grp,nabin,nrbin,bin,resdist,ihb;
+ char **leg;
+ t_hbdata *hb;
+ FILE *fp,*fpins=NULL,*fpnhb=NULL;
+ t_gridcell ***grid;
+ t_ncell *icell,*jcell,*kcell;
+ ivec ngrid;
+ unsigned char *datable;
+ output_env_t oenv;
+ int gemmode, NN;
+ PSTYPE peri=0;
+ t_E E;
+ int ii, jj, hh, actual_nThreads;
+ int threadNr=0;
+ bool bGem, bNN, bParallel;
+ t_gemParams *params=NULL;
- CopyRight(stdout,argv[0]);
+ CopyRight(stdout,argv[0]);
- npargs = asize(pa);
- ppa = add_acf_pargs(&npargs,pa);
+ npargs = asize(pa);
+ ppa = add_acf_pargs(&npargs,pa);
- parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,NFILE,fnm,npargs,
- ppa,asize(desc),desc,asize(bugs),bugs,&oenv);
+ parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,NFILE,fnm,npargs,
+ ppa,asize(desc),desc,asize(bugs),bugs,&oenv);
+
+ /* NN-loop? If so, what estimator to use ?*/
+ NN = 1;
+ while (NN < NN_NR && strcasecmp(NNtype[0], NNtype[NN])!=0)
+ NN++;
+ if (NN == NN_NR)
+ gmx_fatal(FARGS, "Invalid NN-loop type.");
- /* process input */
- bSelected = opt2bSet("-sel",NFILE,fnm);
- ccut = cos(acut*DEG2RAD);
+ bNN = FALSE;
+ for (i=2; bNN==FALSE && i<NN_NR; i++)
+ bNN = bNN || NN == i;
+
+ if (NN > NN_NONE && bMerge)
+ bMerge = FALSE;
+
+ /* geminate recombination? If so, which flavor? */
+ gemmode = 1;
+ while (gemmode < gemNR && strcasecmp(gemType[0], gemType[gemmode])!=0)
+ gemmode++;
+ if (gemmode == gemNR)
+ gmx_fatal(FARGS, "Invalid recombination type.");
- if (bContact) {
- if (bSelected)
- gmx_fatal(FARGS,"Can not analyze selected contacts: turn off -sel");
- if (bInsert)
- gmx_fatal(FARGS,"Can not analyze inserted contacts: turn off -ins");
- if (!bDA) {
- gmx_fatal(FARGS,"Can not analyze contact between H and A: turn off -noda");
- }
- }
-
- /* Initiate main data structure! */
- bHBmap = (opt2bSet("-ac",NFILE,fnm) ||
- opt2bSet("-life",NFILE,fnm) ||
- opt2bSet("-hbn",NFILE,fnm) ||
- opt2bSet("-hbm",NFILE,fnm));
-
- if (opt2bSet("-nhbdist",NFILE,fnm)) {
- char *leg[MAXHH+1] = { "0 HBs", "1 HB", "2 HBs", "3 HBs", "Total" };
- fpnhb = xvgropen(opt2fn("-nhbdist",NFILE,fnm),
- "Number of donor-H with N HBs","Time (ps)","N",oenv);
- xvgr_legend(fpnhb,asize(leg),leg,oenv);
- }
-
- hb = mk_hbdata(bHBmap,opt2bSet("-dan",NFILE,fnm),bMerge || bContact);
-
- /* get topology */
- read_tpx_top(ftp2fn(efTPX,NFILE,fnm),&ir,box,&natoms,NULL,NULL,NULL,&top);
-
- snew(grpnames,grNR);
- snew(index,grNR);
- snew(isize,grNR);
- /* Make Donor-Acceptor table */
- snew(datable, top.atoms.nr);
- gen_datable(index[0],isize[0],datable,top.atoms.nr);
-
- if (bSelected) {
- /* analyze selected hydrogen bonds */
- printf("Select group with selected atoms:\n");
- get_index(&(top.atoms),opt2fn("-sel",NFILE,fnm),
- 1,&nsel,index,grpnames);
- if (nsel % 3)
- gmx_fatal(FARGS,"Number of atoms in group '%s' not a multiple of 3\n"
- "and therefore cannot contain triplets of "
- "Donor-Hydrogen-Acceptor",grpnames[0]);
- bTwo=FALSE;
+ bGem = FALSE;
+ for (i=2; bGem==FALSE && i<gemNR; i++)
+ bGem = bGem || gemmode == i;
+
+ if (bGem) {
+ printf("Geminate recombination: %s\n" ,gemType[gemmode]);
+#ifndef HAVE_LIBGSL
+ printf("Note that some aspects of reversible geminate recombination won't work without gsl.\n");
+#endif
+ if (bContact) {
+ if (gemmode != gemDD) {
+ printf("Turning off -contact option...\n");
+ bContact = FALSE;
+ }
+ } else {
+ if (gemmode == gemDD) {
+ printf("Turning on -contact option...\n");
+ bContact = TRUE;
+ }
+ }
+ if (bMerge) {
+ if (gemmode == gemAA) {
+ printf("Turning off -merge option...\n");
+ bMerge = FALSE;
+ }
+ } else {
+ if (gemmode != gemAA) {
+ printf("Turning on -merge option...\n");
+ bMerge = TRUE;
+ }
+ }
+ } else
+ printf("No geminate recombination.\n");
+
+ /* process input */
+ bSelected = opt2bSet("-sel",NFILE,fnm);
+ ccut = cos(acut*DEG2RAD);
+
+ if (bContact) {
+ if (bSelected)
+ gmx_fatal(FARGS,"Can not analyze selected contacts: turn off -sel");
+ if (bInsert)
+ gmx_fatal(FARGS,"Can not analyze inserted contacts: turn off -ins");
+ if (!bDA) {
+ gmx_fatal(FARGS,"Can not analyze contact between H and A: turn off -noda");
+ }
+ }
+
+#ifndef HAVE_LIBGSL
+ printf("NO GSL! Can't find and take away ballistic term in ACF without GSL\n.");
+#endif
+
+ /* Initiate main data structure! */
+ bHBmap = (opt2bSet("-ac",NFILE,fnm) ||
+ opt2bSet("-life",NFILE,fnm) ||
+ opt2bSet("-hbn",NFILE,fnm) ||
+ opt2bSet("-hbm",NFILE,fnm) ||
+ bGem);
+
+#ifdef HAVE_OPENMP
+ printf("Compiled with OpenMP (%i)\n", _OPENMP);
+#endif
+
+ /* if (bContact && bGem) */
+ /* gmx_fatal(FARGS, "Can't do reversible geminate recombination with -contact yet."); */
+
+ if (opt2bSet("-nhbdist",NFILE,fnm)) {
+ char *leg[MAXHH+1] = { "0 HBs", "1 HB", "2 HBs", "3 HBs", "Total" };
+ fpnhb = xvgropen(opt2fn("-nhbdist",NFILE,fnm),
+ "Number of donor-H with N HBs","Time (ps)","N",oenv);
+ xvgr_legend(fpnhb,asize(leg),leg,oenv);
+ }
+
+ hb = mk_hbdata(bHBmap,opt2bSet("-dan",NFILE,fnm),bMerge || bContact, bGem, gemmode);
+
+ /* get topology */
+ read_tpx_top(ftp2fn(efTPX,NFILE,fnm),&ir,box,&natoms,NULL,NULL,NULL,&top);
+
+ snew(grpnames,grNR);
+ snew(index,grNR);
+ snew(isize,grNR);
+ /* Make Donor-Acceptor table */
+ snew(datable, top.atoms.nr);
+ gen_datable(index[0],isize[0],datable,top.atoms.nr);
+
+ if (bSelected) {
+ /* analyze selected hydrogen bonds */
+ printf("Select group with selected atoms:\n");
+ get_index(&(top.atoms),opt2fn("-sel",NFILE,fnm),
+ 1,&nsel,index,grpnames);
+ if (nsel % 3)
+ gmx_fatal(FARGS,"Number of atoms in group '%s' not a multiple of 3\n"
+ "and therefore cannot contain triplets of "
+ "Donor-Hydrogen-Acceptor",grpnames[0]);
+ bTwo=FALSE;
- for(i=0; (i<nsel); i+=3) {
- int dd = index[0][i];
- int hh = index[0][i+1];
- int aa = index[0][i+2];
- add_dh (&hb->d,dd,hh,i,datable);
- add_acc(&hb->a,aa,i);
- /* Should this be here ? */
- snew(hb->d.dptr,top.atoms.nr);
- snew(hb->a.aptr,top.atoms.nr);
- add_hbond(hb,dd,aa,hh,gr0,gr0,0,FALSE,bMerge,0,bContact);
- }
- printf("Analyzing %d selected hydrogen bonds from '%s'\n",
- isize[0],grpnames[0]);
- }
- else {
- /* analyze all hydrogen bonds: get group(s) */
- printf("Specify 2 groups to analyze:\n");
- get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
- 2,isize,index,grpnames);
+ for(i=0; (i<nsel); i+=3) {
+ int dd = index[0][i];
+ int aa = index[0][i+2];
+ /* int */ hh = index[0][i+1];
+ add_dh (&hb->d,dd,hh,i,datable);
+ add_acc(&hb->a,aa,i);
+ /* Should this be here ? */
+ snew(hb->d.dptr,top.atoms.nr);
+ snew(hb->a.aptr,top.atoms.nr);
+ add_hbond(hb,dd,aa,hh,gr0,gr0,0,FALSE,bMerge,0,bContact,peri);
+ }
+ printf("Analyzing %d selected hydrogen bonds from '%s'\n",
+ isize[0],grpnames[0]);
+ }
+ else {
+ /* analyze all hydrogen bonds: get group(s) */
+ printf("Specify 2 groups to analyze:\n");
+ get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
+ 2,isize,index,grpnames);
- /* check if we have two identical or two non-overlapping groups */
- bTwo = isize[0] != isize[1];
- for (i=0; (i<isize[0]) && !bTwo; i++)
- bTwo = index[0][i] != index[1][i];
- if (bTwo) {
- printf("Checking for overlap in atoms between %s and %s\n",
- grpnames[0],grpnames[1]);
- for (i=0; i<isize[1];i++)
- if (ISINGRP(datable[index[1][i]]))
- gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
- grpnames[0],grpnames[1]);
- /*
- printf("Checking for overlap in atoms between %s and %s\n",
- grpnames[0],grpnames[1]);
- for (i=0; i<isize[0]; i++)
- for (j=0; j<isize[1]; j++)
- if (index[0][i] == index[1][j])
- gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
- grpnames[0],grpnames[1]);
- */
+ /* check if we have two identical or two non-overlapping groups */
+ bTwo = isize[0] != isize[1];
+ for (i=0; (i<isize[0]) && !bTwo; i++)
+ bTwo = index[0][i] != index[1][i];
+ if (bTwo) {
+ printf("Checking for overlap in atoms between %s and %s\n",
+ grpnames[0],grpnames[1]);
+ for (i=0; i<isize[1];i++)
+ if (ISINGRP(datable[index[1][i]]))
+ gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
+ grpnames[0],grpnames[1]);
+ /*
+ printf("Checking for overlap in atoms between %s and %s\n",
+ grpnames[0],grpnames[1]);
+ for (i=0; i<isize[0]; i++)
+ for (j=0; j<isize[1]; j++)
+ if (index[0][i] == index[1][j])
+ gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
+ grpnames[0],grpnames[1]);
+ */
+ }
+ if (bTwo)
+ printf("Calculating %s "
+ "between %s (%d atoms) and %s (%d atoms)\n",
+ bContact ? "contacts" : "hydrogen bonds",
+ grpnames[0],isize[0],grpnames[1],isize[1]);
+ else
+ fprintf(stderr,"Calculating %s in %s (%d atoms)\n",
+ bContact?"contacts":"hydrogen bonds",grpnames[0],isize[0]);
}
- if (bTwo)
- printf("Calculating %s "
- "between %s (%d atoms) and %s (%d atoms)\n",
- bContact ? "contacts" : "hydrogen bonds",
- grpnames[0],isize[0],grpnames[1],isize[1]);
- else
- fprintf(stderr,"Calculating %s in %s (%d atoms)\n",
- bContact?"contacts":"hydrogen bonds",grpnames[0],isize[0]);
- }
- sfree(datable);
- if (bInsert) {
- printf("Specify group for insertion analysis:\n");
- get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
- 1,&(isize[grI]),&(index[grI]),&(grpnames[grI]));
- printf("Checking for overlap...\n");
- for (i=0; i<isize[grI]; i++)
- for (grp=0; grp<(bTwo?2:1); grp++)
- for (j=0; j<isize[grp]; j++)
- if (index[grI][i] == index[grp][j])
- gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
- grpnames[grp],grpnames[grI]);
- fpins=ffopen("insert.dat","w");
- fprintf(fpins,"%4s: %15s -> %15s (%7s) - %15s (%7s)\n",
- "time","insert","donor","distang","acceptor","distang");
- }
-
- /* search donors and acceptors in groups */
- snew(datable, top.atoms.nr);
- for (i=0; (i<grNR); i++)
- if ( ((i==gr0) && !bSelected ) ||
- ((i==gr1) && bTwo ) ||
- ((i==grI) && bInsert ) ) {
- gen_datable(index[i],isize[i],datable,top.atoms.nr);
- if (bContact) {
- search_acceptors(&top,isize[i],index[i],&hb->a,i,
- bNitAcc,TRUE,(bTwo && (i==gr0)) || !bTwo, datable);
- search_donors (&top,isize[i],index[i],&hb->d,i,
- TRUE,(bTwo && (i==gr1)) || !bTwo, datable);
- }
- else {
- search_acceptors(&top,isize[i],index[i],&hb->a,i,bNitAcc,FALSE,TRUE, datable);
- search_donors (&top,isize[i],index[i],&hb->d,i,FALSE,TRUE, datable);
- }
- if (bTwo)
- clear_datable_grp(datable,top.atoms.nr);
- }
- sfree(datable);
- printf("Found %d donors and %d acceptors\n",hb->d.nrd,hb->a.nra);
- /*if (bSelected)
- snew(donors[gr0D], dons[gr0D].nrd);*/
-
- if (bHBmap) {
- printf("Making hbmap structure...");
- /* Generate hbond data structure */
- mk_hbmap(hb,bTwo,bInsert);
- printf("done.\n");
- }
-
- /* check input */
- bStop=FALSE;
- if (hb->d.nrd + hb->a.nra == 0) {
- printf("No Donors or Acceptors found\n");
- bStop=TRUE;
- }
- if (!bStop) {
- if (hb->d.nrd == 0) {
- printf("No Donors found\n");
- bStop=TRUE;
- }
- if (hb->a.nra == 0) {
- printf("No Acceptors found\n");
- bStop=TRUE;
- }
- }
- if (bStop)
- gmx_fatal(FARGS,"Nothing to be done");
-
- shatom=0;
- if (rshell > 0) {
- int shisz;
- atom_id *shidx;
- char *shgrpnm;
- /* get index group with atom for shell */
- do {
- printf("Select atom for shell (1 atom):\n");
- get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
- 1,&shisz,&shidx,&shgrpnm);
- if (shisz != 1)
- printf("group contains %d atoms, should be 1 (one)\n",shisz);
- } while(shisz != 1);
- shatom = shidx[0];
- printf("Will calculate hydrogen bonds within a shell "
- "of %g nm around atom %i\n",rshell,shatom+1);
- }
-
- /* Analyze trajectory */
- natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
- if ( natoms > top.atoms.nr )
- gmx_fatal(FARGS,"Topology (%d atoms) does not match trajectory (%d atoms)",
- top.atoms.nr,natoms);
+ sfree(datable);
+ if (bInsert) {
+ printf("Specify group for insertion analysis:\n");
+ get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
+ 1,&(isize[grI]),&(index[grI]),&(grpnames[grI]));
+ printf("Checking for overlap...\n");
+ for (i=0; i<isize[grI]; i++)
+ for (grp=0; grp<(bTwo?2:1); grp++)
+ for (j=0; j<isize[grp]; j++)
+ if (index[grI][i] == index[grp][j])
+ gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
+ grpnames[grp],grpnames[grI]);
+ fpins=ffopen("insert.dat","w");
+ fprintf(fpins,"%4s: %15s -> %15s (%7s) - %15s (%7s)\n",
+ "time","insert","donor","distang","acceptor","distang");
+ }
+
+ /* search donors and acceptors in groups */
+ snew(datable, top.atoms.nr);
+ for (i=0; (i<grNR); i++)
+ if ( ((i==gr0) && !bSelected ) ||
+ ((i==gr1) && bTwo ) ||
+ ((i==grI) && bInsert ) ) {
+ gen_datable(index[i],isize[i],datable,top.atoms.nr);
+ if (bContact) {
+ search_acceptors(&top,isize[i],index[i],&hb->a,i,
+ bNitAcc,TRUE,(bTwo && (i==gr0)) || !bTwo, datable);
+ search_donors (&top,isize[i],index[i],&hb->d,i,
+ TRUE,(bTwo && (i==gr1)) || !bTwo, datable);
+ }
+ else {
+ search_acceptors(&top,isize[i],index[i],&hb->a,i,bNitAcc,FALSE,TRUE, datable);
+ search_donors (&top,isize[i],index[i],&hb->d,i,FALSE,TRUE, datable);
+ }
+ if (bTwo)
+ clear_datable_grp(datable,top.atoms.nr);
+ }
+ sfree(datable);
+ printf("Found %d donors and %d acceptors\n",hb->d.nrd,hb->a.nra);
+ /*if (bSelected)
+ snew(donors[gr0D], dons[gr0D].nrd);*/
+
+ if (bHBmap) {
+ printf("Making hbmap structure...");
+ /* Generate hbond data structure */
+ mk_hbmap(hb,bTwo,bInsert);
+ printf("done.\n");
+ }
+
+#ifdef HAVE_NN_LOOPS
+ if (bNN)
+ mk_hbEmap(hb, 0);
+#endif
+
+ if (bGem) {
+ printf("Making per structure...");
+ /* Generate hbond data structure */
+ mk_per(hb);
+ printf("done.\n");
+ }
+
+ /* check input */
+ bStop=FALSE;
+ if (hb->d.nrd + hb->a.nra == 0) {
+ printf("No Donors or Acceptors found\n");
+ bStop=TRUE;
+ }
+ if (!bStop) {
+ if (hb->d.nrd == 0) {
+ printf("No Donors found\n");
+ bStop=TRUE;
+ }
+ if (hb->a.nra == 0) {
+ printf("No Acceptors found\n");
+ bStop=TRUE;
+ }
+ }
+ if (bStop)
+ gmx_fatal(FARGS,"Nothing to be done");
+
+ shatom=0;
+ if (rshell > 0) {
+ int shisz;
+ atom_id *shidx;
+ char *shgrpnm;
+ /* get index group with atom for shell */
+ do {
+ printf("Select atom for shell (1 atom):\n");
+ get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
+ 1,&shisz,&shidx,&shgrpnm);
+ if (shisz != 1)
+ printf("group contains %d atoms, should be 1 (one)\n",shisz);
+ } while(shisz != 1);
+ shatom = shidx[0];
+ printf("Will calculate hydrogen bonds within a shell "
+ "of %g nm around atom %i\n",rshell,shatom+1);
+ }
+
+ /* Analyze trajectory */
+ natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
+ if ( natoms > top.atoms.nr )
+ gmx_fatal(FARGS,"Topology (%d atoms) does not match trajectory (%d atoms)",
+ top.atoms.nr,natoms);
- bBox = ir.ePBC!=epbcNONE;
- grid = init_grid(bBox, box, (rcut>r2cut)?rcut:r2cut, ngrid);
- nabin = acut/abin;
- nrbin = rcut/rbin;
- snew(adist,nabin+1);
- snew(rdist,nrbin+1);
-
- do {
- bTric = bBox && TRICLINIC(box);
- build_grid(hb,x,x[shatom], bBox,box,hbox, (rcut>r2cut)?rcut:r2cut,
- rshell, ngrid,grid);
-
- reset_nhbonds(&(hb->d));
+ bBox = ir.ePBC!=epbcNONE;
+ grid = init_grid(bBox, box, (rcut>r2cut)?rcut:r2cut, ngrid);
+ nabin = acut/abin;
+ nrbin = rcut/rbin;
+ snew(adist,nabin+1);
+ snew(rdist,nrbin+1);
- if (debug && bDebug)
- dump_grid(debug, ngrid, grid);
-
- add_frames(hb,nframes);
- init_hbframe(hb,nframes,t);
+ if (bGem && !bBox)
+ gmx_fatal(FARGS, "Can't do geminate recombination without periodic box.");
- if (hb->bDAnr)
- count_da_grid(ngrid, grid, hb->danr[nframes]);
-
- if (bSelected) {
- int ii;
-
- for(ii=0; (ii<nsel); ii++) {
- int dd = index[0][i];
- int hh = index[0][i+1];
- int aa = index[0][i+2];
- ihb = is_hbond(hb,ii,ii,dd,aa,rcut,r2cut,ccut,x,bBox,box,
- hbox,&dist,&ang,bDA,&h,bContact);
-
- if (ihb) {
- /* add to index if not already there */
- /* Add a hbond */
- add_hbond(hb,dd,aa,hh,ii,ii,nframes,FALSE,bMerge,ihb,bContact);
- }
- }
+ bParallel = FALSE;
+
+#ifndef HAVE_OPENMP
+#define __ADIST adist
+#define __RDIST rdist
+#define __HBDATA hb
+#else /* HAVE_OPENMP ================================================== \
+ * Set up the OpenMP stuff, |
+ * like the number of threads and such |
+ * Also start the parallel loop. |
+ */
+#define __ADIST p_adist[threadNr]
+#define __RDIST p_rdist[threadNr]
+#define __HBDATA p_hb[threadNr]
+
+ bParallel = !bSelected && !bInsert;
+
+ if (bParallel)
+ {
+#if (_OPENMP > 200805)
+ actual_nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_thread_limit());
+#else
+ actual_nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_num_procs());
+#endif
+ omp_set_num_threads(actual_nThreads);
+ printf("Frame loop parallelized with OpenMP using %i threads.\n", actual_nThreads);
+ fflush(stdout);
}
- else {
- /* loop over all gridcells (xi,yi,zi) */
- /* Removed confusing macro, DvdS 27/12/98 */
- for(xi=0; (xi<ngrid[XX]); xi++)
- for(yi=0; (yi<ngrid[YY]); yi++)
- for(zi=0; (zi<ngrid[ZZ]); zi++) {
-
- /* loop over donor groups gr0 (always) and gr1 (if necessary) */
- for (grp=gr0; (grp <= (bTwo?gr1:gr0)); grp++) {
- icell=&(grid[zi][yi][xi].d[grp]);
-
- if (bTwo)
- ogrp = 1-grp;
- else
- ogrp = grp;
+ else
+ {
+ actual_nThreads = 1;
+ }
+
+ t_hbdata **p_hb; /* one per thread, then merge after the frame loop */
+ int **p_adist, **p_rdist; /* a histogram for each thread. */
+ snew(p_hb, actual_nThreads);
+ snew(p_adist, actual_nThreads);
+ snew(p_rdist, actual_nThreads);
+ for (i=0; i<actual_nThreads; i++)
+ {
+ snew(p_hb[i], 1);
+ snew(p_adist[i], nabin+1);
+ snew(p_rdist[i], nrbin+1);
+
+ p_hb[i]->max_frames = 0;
+ p_hb[i]->nhb = NULL;
+ p_hb[i]->ndist = NULL;
+ p_hb[i]->n_bound = NULL;
+ p_hb[i]->time = NULL;
+ p_hb[i]->nhx = NULL;
+
+ p_hb[i]->bHBmap = hb->bHBmap;
+ p_hb[i]->bDAnr = hb->bDAnr;
+ p_hb[i]->bGem = hb->bGem;
+ p_hb[i]->wordlen = hb->wordlen;
+ p_hb[i]->nframes = hb->nframes;
+ p_hb[i]->maxhydro = hb->maxhydro;
+ p_hb[i]->danr = hb->danr;
+ p_hb[i]->d = hb->d;
+ p_hb[i]->a = hb->a;
+ p_hb[i]->hbmap = hb->hbmap;
+ p_hb[i]->time = hb->time; /* This may need re-syncing at every frame. */
+ p_hb[i]->per = hb->per;
+
+#ifdef HAVE_NN_LOOPS
+ p_hb[i]->hbE = hb->hbE;
+#endif
+
+ p_hb[i]->nrhb = 0;
+ p_hb[i]->nrdist = 0;
+ }
+
+ /* Make a thread pool here,
+ * instead of forking anew at every frame. */
+
+#pragma omp parallel \
+ private(i, j, h, ii, jj, hh, E, \
+ xi, yi, zi, xj, yj, zj, threadNr, \
+ dist, ang, peri, icell, jcell, \
+ grp, ogrp, ai, aj, xjj, yjj, zjj, \
+ xk, yk, zk, ihb, id, resdist, \
+ xkk, ykk, zkk, kcell, ak, k, bTric) \
+ default(none) \
+ shared(hb, p_hb, p_adist, p_rdist, actual_nThreads, \
+ x, bBox, box, hbox, rcut, r2cut, rshell, \
+ shatom, ngrid, grid, nframes, t, \
+ bParallel, bNN, index, bMerge, bContact, \
+ bTwo, bDA,ccut, abin, rbin, top, \
+ bInsert, bSelected, bDebug, stderr, nsel, \
+ bGem, oenv, fnm, fpnhb, trrStatus, natoms, \
+ status, nabin, nrbin, adist, rdist, debug)
+ { /* Start of parallel region */
+ threadNr = omp_get_thread_num();
+#endif /* HAVE_OPENMP ================================================= */
+ do
+ {
+ bTric = bBox && TRICLINIC(box);
+
+#ifdef HAVE_OPENMP
+ sync_hbdata(hb, p_hb[threadNr], nframes, t);
+#pragma omp single
+#endif
+ {
+ build_grid(hb,x,x[shatom], bBox,box,hbox, (rcut>r2cut)?rcut:r2cut,
+ rshell, ngrid,grid);
+ reset_nhbonds(&(hb->d));
+
+ if (debug && bDebug)
+ dump_grid(debug, ngrid, grid);
+
+ add_frames(hb,nframes);
+ init_hbframe(hb,nframes,t);
+
+ if (hb->bDAnr)
+ count_da_grid(ngrid, grid, hb->danr[nframes]);
+ } /* omp single */
+
+#ifdef HAVE_OPENMP
+ p_hb[threadNr]->time = hb->time; /* This pointer may have changed. */
+#endif
+ if (bNN)
+ {
+#ifdef HAVE_NN_LOOPS /* Unlock this feature when testing */
+ /* Loop over all atom pairs and estimate interaction energy */
+#ifdef HAVE_OPENMP /* ------- */
+#pragma omp single
+#endif /* HAVE_OPENMP ------- */
+ {
+ addFramesNN(hb, nframes);
+ }
+#ifdef HAVE_OPENMP /* ---------------- */
+#pragma omp barrier
+#pragma omp for schedule(dynamic)
+#endif /* HAVE_OPENMP ---------------- */
+ for (i=0; i<hb->d.nrd; i++)
+ {
+ for(j=0;j<hb->a.nra; j++)
+ {
+ for (h=0;
+ h < (bContact ? 1 : hb->d.nhydro[i]);
+ h++)
+ {
+ if (i==hb->d.nrd || j==hb->a.nra)
+ gmx_fatal(FARGS, "out of bounds");
+
+ /* Get the real atom ids */
+ ii = hb->d.don[i];
+ jj = hb->a.acc[j];
+ hh = hb->d.hydro[i][h];
+
+ /* Estimate the energy from the geometry */
+ E = calcHbEnergy(ii, jj, hh, x, NN, box, hbox, &(hb->d));
+ /* Store the energy */
+ storeHbEnergy(hb, i, j, h, E, nframes);
+ }
+ }
+ }
+#endif /* HAVE_NN_LOOPS */
+ } /* if (bNN)*/
+ else
+ {
+ if (bSelected)
+ {
+#ifdef HAVE_OPENMP
+#pragma omp single
+#endif
+ {
+ /* Do not parallelize this just yet. */
+ /* int ii; */
+ for(ii=0; (ii<nsel); ii++) {
+ int dd = index[0][i];
+ int aa = index[0][i+2];
+ /* int */ hh = index[0][i+1];
+ ihb = is_hbond(hb,ii,ii,dd,aa,rcut,r2cut,ccut,x,bBox,box,
+ hbox,&dist,&ang,bDA,&h,bContact,bMerge,&peri);
+
+ if (ihb) {
+ /* add to index if not already there */
+ /* Add a hbond */
+ add_hbond(hb,dd,aa,hh,ii,ii,nframes,FALSE,bMerge,ihb,bContact,peri);
+ }
+ }
+ } /* omp single */
+ } /* if (bSelected) */
+ else
+ {
+#ifdef HAVE_OPENMP
+#pragma omp single
+ {
+#endif
+ if (bGem)
+ calcBoxProjection(box, hb->per->P);
+
+ /* loop over all gridcells (xi,yi,zi) */
+ /* Removed confusing macro, DvdS 27/12/98 */
+#ifdef HAVE_OPENMP
+ }
+ /* The outer grid loop will have to do for now. */
+#pragma omp for schedule(dynamic)
+#endif
+ for(xi=0; (xi<ngrid[XX]); xi++)
+ for(yi=0; (yi<ngrid[YY]); yi++)
+ for(zi=0; (zi<ngrid[ZZ]); zi++) {
- /* loop over all hydrogen atoms from group (grp)
- * in this gridcell (icell)
- */
- for (ai=0; (ai<icell->nr); ai++) {
- i = icell->atoms[ai];
+ /* loop over donor groups gr0 (always) and gr1 (if necessary) */
+ for (grp=gr0; (grp <= (bTwo?gr1:gr0)); grp++) {
+ icell=&(grid[zi][yi][xi].d[grp]);
+
+ if (bTwo)
+ ogrp = 1-grp;
+ else
+ ogrp = grp;
+
+ /* loop over all hydrogen atoms from group (grp)
+ * in this gridcell (icell)
+ */
+ for (ai=0; (ai<icell->nr); ai++) {
+ i = icell->atoms[ai];
- /* loop over all adjacent gridcells (xj,yj,zj) */
- /* This is a macro!!! */
- LOOPGRIDINNER(xj,yj,zj,xjj,yjj,zjj,xi,yi,zi,ngrid,bTric) {
- jcell=&(grid[zj][yj][xj].a[ogrp]);
- /* loop over acceptor atoms from other group (ogrp)
- * in this adjacent gridcell (jcell)
- */
- for (aj=0; (aj<jcell->nr); aj++) {
- j = jcell->atoms[aj];
+ /* loop over all adjacent gridcells (xj,yj,zj) */
+ /* This is a macro!!! */
+ LOOPGRIDINNER(xj,yj,zj,xjj,yjj,zjj,xi,yi,zi,ngrid,bTric) {
+ jcell=&(grid[zj][yj][xj].a[ogrp]);
+ /* loop over acceptor atoms from other group (ogrp)
+ * in this adjacent gridcell (jcell)
+ */
+ for (aj=0; (aj<jcell->nr); aj++) {
+ j = jcell->atoms[aj];
- /* check if this once was a h-bond */
- ihb = is_hbond(hb,grp,ogrp,i,j,rcut,r2cut,ccut,x,bBox,box,
- hbox,&dist,&ang,bDA,&h,bContact);
+ /* check if this once was a h-bond */
+ peri = -1;
+ ihb = is_hbond(__HBDATA,grp,ogrp,i,j,rcut,r2cut,ccut,x,bBox,box,
+ hbox,&dist,&ang,bDA,&h,bContact,bMerge,&peri);
- if (ihb) {
- /* add to index if not already there */
- /* Add a hbond */
- add_hbond(hb,i,j,h,grp,ogrp,nframes,FALSE,bMerge,ihb,bContact);
+ if (ihb) {
+ /* add to index if not already there */
+ /* Add a hbond */
+ add_hbond(__HBDATA,i,j,h,grp,ogrp,nframes,FALSE,bMerge,ihb,bContact,peri);
- /* make angle and distance distributions */
- if (ihb == hbHB && !bContact) {
- if (dist>rcut)
- gmx_fatal(FARGS,"distance is higher than what is allowed for an hbond: %f",dist);
- ang*=RAD2DEG;
- adist[(int)( ang/abin)]++;
- rdist[(int)(dist/rbin)]++;
-
- if (!bTwo) {
- int id,ia;
- if ((id = donor_index(&hb->d,grp,i)) == NOTSET)
- gmx_fatal(FARGS,"Invalid donor %d",i);
- if ((ia = acceptor_index(&hb->a,ogrp,j)) == NOTSET)
- gmx_fatal(FARGS,"Invalid acceptor %d",j);
- resdist=abs(top.atoms.atom[i].resind-
- top.atoms.atom[j].resind);
- if (resdist >= max_hx)
- resdist = max_hx-1;
- hb->nhx[nframes][resdist]++;
- }
- }
- if (bInsert && bSelected) {
- /* this has been a h-bond, or we are analyzing
- selected bonds: check for inserted */
- bool ins_d, ins_a;
- real ins_d_dist, ins_d_ang, ins_a_dist, ins_a_ang;
- int ins_d_k=0,ins_a_k=0;
+ /* make angle and distance distributions */
+ if (ihb == hbHB && !bContact) {
+ if (dist>rcut)
+ gmx_fatal(FARGS,"distance is higher than what is allowed for an hbond: %f",dist);
+ ang*=RAD2DEG;
+ __ADIST[(int)( ang/abin)]++;
+ __RDIST[(int)(dist/rbin)]++;
+ if (!bTwo) {
+ int id,ia;
+ if ((id = donor_index(&hb->d,grp,i)) == NOTSET)
+ gmx_fatal(FARGS,"Invalid donor %d",i);
+ if ((ia = acceptor_index(&hb->a,ogrp,j)) == NOTSET)
+ gmx_fatal(FARGS,"Invalid acceptor %d",j);
+ resdist=abs(top.atoms.atom[i].resind-
+ top.atoms.atom[j].resind);
+ if (resdist >= max_hx)
+ resdist = max_hx-1;
+ __HBDATA->nhx[nframes][resdist]++;
+ }
+ }
+
+ if (bInsert && bSelected && MASTER_THREAD_ONLY(threadNr)) {
+ /* this has been a h-bond, or we are analyzing
+ selected bonds: check for inserted */
+ bool ins_d, ins_a;
+ real ins_d_dist, ins_d_ang, ins_a_dist, ins_a_ang;
+ int ins_d_k=0,ins_a_k=0;
- ins_d=ins_a=FALSE;
- ins_d_dist=ins_d_ang=ins_a_dist=ins_a_ang=1e6;
+ ins_d=ins_a=FALSE;
+ ins_d_dist=ins_d_ang=ins_a_dist=ins_a_ang=1e6;
- /* loop over gridcells adjacent to i (xk,yk,zk) */
- LOOPGRIDINNER(xk,yk,zk,xkk,ykk,zkk,xi,yi,zi,ngrid,bTric){
- kcell=&(grid[zk][yk][xk].a[grI]);
- /* loop over acceptor atoms from ins group
- in this adjacent gridcell (kcell) */
- for (ak=0; (ak<kcell->nr); ak++) {
- k=kcell->atoms[ak];
- ihb = is_hbond(hb,grp,grI,i,k,rcut,r2cut,ccut,x,
- bBox,box,hbox,&dist,&ang,bDA,&h,
- bContact);
- if (ihb == hbHB) {
- if (dist < ins_d_dist) {
- ins_d=TRUE;
- ins_d_dist=dist;
- ins_d_ang =ang ;
- ins_d_k =k ;
- }
- }
- }
- }
- ENDLOOPGRIDINNER;
- /* loop over gridcells adjacent to j (xk,yk,zk) */
- LOOPGRIDINNER(xk,yk,zk,xkk,ykk,zkk,xj,yj,zj,ngrid,bTric){
- kcell=&grid[zk][yk][xk].d[grI];
- /* loop over hydrogen atoms from ins group
- in this adjacent gridcell (kcell) */
- for (ak=0; ak<kcell->nr; ak++) {
- k = kcell->atoms[ak];
- ihb = is_hbond(hb,grI,ogrp,k,j,rcut,r2cut,ccut,x,
- bBox,box,hbox,&dist,&ang,bDA,&h,
- bContact);
- if (ihb == hbHB) {
- if (dist<ins_a_dist) {
- ins_a=TRUE;
- ins_a_dist=dist;
- ins_a_ang =ang ;
- ins_a_k =k ;
- }
- }
- }
- }
- ENDLOOPGRIDINNER;
+ /* loop over gridcells adjacent to i (xk,yk,zk) */
+ LOOPGRIDINNER(xk,yk,zk,xkk,ykk,zkk,xi,yi,zi,ngrid,bTric){
+ kcell=&(grid[zk][yk][xk].a[grI]);
+ /* loop over acceptor atoms from ins group
+ in this adjacent gridcell (kcell) */
+ for (ak=0; (ak<kcell->nr); ak++) {
+ k=kcell->atoms[ak];
+ ihb = is_hbond(hb,grp,grI,i,k,rcut,r2cut,ccut,x,
+ bBox,box,hbox,&dist,&ang,bDA,&h,
+ bContact,bMerge,&peri);
+ if (ihb == hbHB) {
+ if (dist < ins_d_dist) {
+ ins_d=TRUE;
+ ins_d_dist=dist;
+ ins_d_ang =ang ;
+ ins_d_k =k ;
+ }
+ }
+ }
+ }
+ ENDLOOPGRIDINNER;
+ /* loop over gridcells adjacent to j (xk,yk,zk) */
+ LOOPGRIDINNER(xk,yk,zk,xkk,ykk,zkk,xj,yj,zj,ngrid,bTric){
+ kcell=&grid[zk][yk][xk].d[grI];
+ /* loop over hydrogen atoms from ins group
+ in this adjacent gridcell (kcell) */
+ for (ak=0; ak<kcell->nr; ak++) {
+ k = kcell->atoms[ak];
+ ihb = is_hbond(hb,grI,ogrp,k,j,rcut,r2cut,ccut,x,
+ bBox,box,hbox,&dist,&ang,bDA,&h,
+ bContact,bMerge,&peri);
+ if (ihb == hbHB) {
+ if (dist<ins_a_dist) {
+ ins_a=TRUE;
+ ins_a_dist=dist;
+ ins_a_ang =ang ;
+ ins_a_k =k ;
+ }
+ }
+ }
+ }
+ ENDLOOPGRIDINNER;
- {
- ihb = is_hbond(hb,grI,grI,ins_d_k,ins_a_k,rcut,r2cut,ccut,x,
- bBox,box,hbox,&dist,&ang,bDA,&h,bContact);
- if (ins_d && ins_a && ihb) {
- /* add to hbond index if not already there */
- add_hbond(hb,ins_d_k,ins_a_k,h,grI,ogrp,
- nframes,TRUE,bMerge,ihb,bContact);
+ {
+ ihb = is_hbond(hb,grI,grI,ins_d_k,ins_a_k,rcut,r2cut,ccut,x,
+ bBox,box,hbox,&dist,&ang,bDA,&h,bContact,bMerge,&peri);
+ if (ins_d && ins_a && ihb) {
+ /* add to hbond index if not already there */
+ add_hbond(hb,ins_d_k,ins_a_k,h,grI,ogrp,
+ nframes,TRUE,bMerge,ihb,bContact,peri);
- /* print insertion info to file */
- /*fprintf(fpins,
- "%4g: %4u:%3.3s%4d%3.3s -> "
- "%4u:%3.3s%4d%3.3s (%4.2f,%2.0f) - "
- "%4u:%3.3s%4d%3.3s (%4.2f,%2.0f)\n",t,
- a[grIA][ins_d_k]+1,
- *top.atoms.resname[top.atoms.atom[a[grIA][ins_d_k]].resnr],
- top.atoms.atom[a[grIA][ins_d_k]].resnr+1,
- *top.atoms.atomname[a[grIA][ins_d_k]],
- a[grp+grD][i]+1,
- *top.atoms.resname[top.atoms.atom[a[grp+grD][i]].resnr],
- top.atoms.atom[a[grp+grD][i]].resnr+1,
- *top.atoms.atomname[a[grp+grD][i]],
- ins_d_dist,ins_d_ang*RAD2DEG,
- a[ogrp+grA][j]+1,
- *top.atoms.resname[top.atoms.atom[a[ogrp+grA][j]].resnr],
- top.atoms.atom[a[ogrp+grA][j]].resnr+1,
- *top.atoms.atomname[a[ogrp+grA][j]],
- ins_a_dist,ins_a_ang*RAD2DEG);*/
- }
- }
- }
- }
- } /* for aj */
- }
- ENDLOOPGRIDINNER;
- } /* for ai */
- } /* for grp */
- } /* for xi,yi,zi */
- }
- analyse_donor_props(opt2fn_null("-don",NFILE,fnm),hb,nframes,t,oenv);
- if (fpnhb)
- do_nhb_dist(fpnhb,hb,t);
+ /* print insertion info to file */
+ /*fprintf(fpins,
+ "%4g: %4u:%3.3s%4d%3.3s -> "
+ "%4u:%3.3s%4d%3.3s (%4.2f,%2.0f) - "
+ "%4u:%3.3s%4d%3.3s (%4.2f,%2.0f)\n",t,
+ a[grIA][ins_d_k]+1,
+ *top.atoms.resname[top.atoms.atom[a[grIA][ins_d_k]].resnr],
+ top.atoms.atom[a[grIA][ins_d_k]].resnr+1,
+ *top.atoms.atomname[a[grIA][ins_d_k]],
+ a[grp+grD][i]+1,
+ *top.atoms.resname[top.atoms.atom[a[grp+grD][i]].resnr],
+ top.atoms.atom[a[grp+grD][i]].resnr+1,
+ *top.atoms.atomname[a[grp+grD][i]],
+ ins_d_dist,ins_d_ang*RAD2DEG,
+ a[ogrp+grA][j]+1,
+ *top.atoms.resname[top.atoms.atom[a[ogrp+grA][j]].resnr],
+ top.atoms.atom[a[ogrp+grA][j]].resnr+1,
+ *top.atoms.atomname[a[ogrp+grA][j]],
+ ins_a_dist,ins_a_ang*RAD2DEG);*/
+ }
+ }
+ } /* if (bInsert && bSelected), omp single */
+ }
+ } /* for aj */
+ }
+ ENDLOOPGRIDINNER;
+ } /* for ai */
+ } /* for grp */
+ } /* for xi,yi,zi */
+ } /* if (bSelected) {...} else */
+
+#ifdef HAVE_OPENMP /* ---------------------------- */
+ /* Better wait for all threads to finnish using x[] before updating it. */
+ k = nframes; /* */
+#pragma omp barrier /* */
+#pragma omp critical /* */
+ { /* */
+ /* Sum up histograms and counts from p_hb[] into hb */
+ { /* */
+ hb->nhb[k] += p_hb[threadNr]->nhb[k];
+ hb->ndist[k] += p_hb[threadNr]->ndist[k];
+ for (j=0; j<max_hx; j++) /**/
+ hb->nhx[k][j] += p_hb[threadNr]->nhx[k][j];
+ } /* */
+ } /* */
+ /* */
+ /* Here are a handful of single constructs
+ * to share the workload a bit. The most
+ * important one is of course the last one,
+ * where there's a potential bottleneck in form
+ * of slow I/O. */
+#pragma omp single /* ++++++++++++++++, */
+#endif /* HAVE_OPENMP ----------------+------------*/
+ { /* + */
+ if (hb != NULL) /* */
+ { /* + */
+ analyse_donor_props(opt2fn_null("-don",NFILE,fnm),hb,k,t,oenv);
+ } /* + */
+ } /* + */
+#ifdef HAVE_OPENMP /* + */
+#pragma omp single /* +++ +++ */
+#endif /* + */
+ { /* + */
+ if (fpnhb) /* + */
+ do_nhb_dist(fpnhb,hb,t);
+ } /* + */
+ } /* if (bNN) {...} else + */
+#ifdef HAVE_OPENMP /* + */
+#pragma omp single /* +++ +++ */
+#endif /* + */
+ { /* + */
+ trrStatus = (read_next_x(oenv,status,&t,natoms,x,box));
+ nframes++; /* + */
+ } /* + */
+#ifdef HAVE_OPENMP /* ++++++++++++++++� */
+#pragma omp barrier
+#endif
+ } while (trrStatus);
+
+#ifdef HAVE_OPENMP
+#pragma omp critical
+ {
+ hb->nrhb += p_hb[threadNr]->nrhb;
+ hb->nrdist += p_hb[threadNr]->nrdist;
+ }
+ /* Free parallel datastructures */
+ sfree(p_hb[threadNr]->nhb);
+ sfree(p_hb[threadNr]->ndist);
+ sfree(p_hb[threadNr]->nhx);
+
+#pragma omp for
+ for (i=0; i<nabin; i++)
+ for (j=0; j<actual_nThreads; j++)
+
+ adist[i] += p_adist[j][i];
+#pragma omp for
+ for (i=0; i<=nrbin; i++)
+ for (j=0; j<actual_nThreads; j++)
+ rdist[i] += p_rdist[j][i];
- nframes++;
- } while (read_next_x(oenv,status,&t,natoms,x,box));
+ sfree(p_adist[threadNr]);
+ sfree(p_rdist[threadNr]);
+ } /* End of parallel region */
+ sfree(p_adist);
+ sfree(p_rdist);
+#endif
+
- free_grid(ngrid,&grid);
+ free_grid(ngrid,&grid);
- close_trj(status);
- if (bInsert)
- ffclose(fpins);
- if (fpnhb)
- ffclose(fpnhb);
+ close_trj(status);
+ if (bInsert)
+ ffclose(fpins);
+ if (fpnhb)
+ ffclose(fpnhb);
- /* Compute maximum possible number of different hbonds */
- if (maxnhb > 0)
- max_nhb = maxnhb;
- else {
- max_nhb = 0.5*(hb->d.nrd*hb->a.nra);
- }
- /* Added support for -contact below.
- * - Erik Marklund, May 29-31, 2006 */
- /* Changed contact code.
- * - Erik Marklund, June 29, 2006 */
- if (bHBmap) {
- if (hb->nrhb==0) {
- printf("No %s found!!\n", bContact ? "contacts" : "hydrogen bonds");
- } else {
- printf("Found %d different %s in trajectory\n"
- "Found %d different atom-pairs within %s distance\n",
- hb->nrhb, bContact?"contacts":"hydrogen bonds",
- hb->nrdist,(r2cut>0)?"second cut-off":"hydrogen bonding");
-
- if (bMerge)
- merge_hb(hb,bTwo,bContact);
-
- if (opt2bSet("-hbn",NFILE,fnm))
- dump_hbmap(hb,NFILE,fnm,bTwo,bInsert,bContact,isize,index,grpnames,&top.atoms);
-
- /* Moved the call to merge_hb() to a line BEFORE dump_hbmap
- * to make the -hbn and -hmb output match eachother.
- * - Erik Marklund, May 30, 2006 */
- }
- }
- /* Print out number of hbonds and distances */
- aver_nhb = 0;
- aver_dist = 0;
- fp = xvgropen(opt2fn("-num",NFILE,fnm),bContact ? "Contacts" :
- "Hydrogen Bonds","Time","Number",oenv);
- snew(leg,2);
- snew(leg[0],STRLEN);
- snew(leg[1],STRLEN);
- sprintf(leg[0],"%s",bContact?"Contacts":"Hydrogen bonds");
- sprintf(leg[1],"Pairs within %g nm",(r2cut>0)?r2cut:rcut);
- xvgr_legend(fp,2,leg,oenv);
- sfree(leg[1]);
- sfree(leg[0]);
- sfree(leg);
- for(i=0; (i<nframes); i++) {
- fprintf(fp,"%10g %10d %10d\n",hb->time[i],hb->nhb[i],hb->ndist[i]);
- aver_nhb += hb->nhb[i];
- aver_dist += hb->ndist[i];
- }
- ffclose(fp);
- aver_nhb /= nframes;
- aver_dist /= nframes;
- /* Print HB distance distribution */
- if (opt2bSet("-dist",NFILE,fnm)) {
- long sum;
+ /* Compute maximum possible number of different hbonds */
+ if (maxnhb > 0)
+ max_nhb = maxnhb;
+ else {
+ max_nhb = 0.5*(hb->d.nrd*hb->a.nra);
+ }
+ /* Added support for -contact below.
+ * - Erik Marklund, May 29-31, 2006 */
+ /* Changed contact code.
+ * - Erik Marklund, June 29, 2006 */
+ if (bHBmap && !bNN) {
+ if (hb->nrhb==0) {
+ printf("No %s found!!\n", bContact ? "contacts" : "hydrogen bonds");
+ } else {
+ printf("Found %d different %s in trajectory\n"
+ "Found %d different atom-pairs within %s distance\n",
+ hb->nrhb, bContact?"contacts":"hydrogen bonds",
+ hb->nrdist,(r2cut>0)?"second cut-off":"hydrogen bonding");
+
+ /*Control the pHist.*/
+
+ if (bMerge)
+ merge_hb(hb,bTwo,bContact);
+
+ if (opt2bSet("-hbn",NFILE,fnm))
+ dump_hbmap(hb,NFILE,fnm,bTwo,bInsert,bContact,isize,index,grpnames,&top.atoms);
+
+ /* Moved the call to merge_hb() to a line BEFORE dump_hbmap
+ * to make the -hbn and -hmb output match eachother.
+ * - Erik Marklund, May 30, 2006 */
+ }
+ }
+ /* Print out number of hbonds and distances */
+ aver_nhb = 0;
+ aver_dist = 0;
+ fp = xvgropen(opt2fn("-num",NFILE,fnm),bContact ? "Contacts" :
+ "Hydrogen Bonds","Time","Number",oenv);
+ snew(leg,2);
+ snew(leg[0],STRLEN);
+ snew(leg[1],STRLEN);
+ sprintf(leg[0],"%s",bContact?"Contacts":"Hydrogen bonds");
+ sprintf(leg[1],"Pairs within %g nm",(r2cut>0)?r2cut:rcut);
+ xvgr_legend(fp,2,leg,oenv);
+ sfree(leg[1]);
+ sfree(leg[0]);
+ sfree(leg);
+ for(i=0; (i<nframes); i++) {
+ fprintf(fp,"%10g %10d %10d\n",hb->time[i],hb->nhb[i],hb->ndist[i]);
+ aver_nhb += hb->nhb[i];
+ aver_dist += hb->ndist[i];
+ }
+ ffclose(fp);
+ aver_nhb /= nframes;
+ aver_dist /= nframes;
+ /* Print HB distance distribution */
+ if (opt2bSet("-dist",NFILE,fnm)) {
+ long sum;
- sum=0;
- for(i=0; i<nrbin; i++)
- sum+=rdist[i];
+ sum=0;
+ for(i=0; i<nrbin; i++)
+ sum+=rdist[i];
- fp = xvgropen(opt2fn("-dist",NFILE,fnm),
- "Hydrogen Bond Distribution",
- "Hydrogen - Acceptor Distance (nm)","",oenv);
- for(i=0; i<nrbin; i++)
- fprintf(fp,"%10g %10g\n",(i+0.5)*rbin,rdist[i]/(rbin*(real)sum));
- ffclose(fp);
- }
+ fp = xvgropen(opt2fn("-dist",NFILE,fnm),
+ "Hydrogen Bond Distribution",
+ "Hydrogen - Acceptor Distance (nm)","",oenv);
+ for(i=0; i<nrbin; i++)
+ fprintf(fp,"%10g %10g\n",(i+0.5)*rbin,rdist[i]/(rbin*(real)sum));
+ ffclose(fp);
+ }
- /* Print HB angle distribution */
- if (opt2bSet("-ang",NFILE,fnm)) {
- long sum;
+ /* Print HB angle distribution */
+ if (opt2bSet("-ang",NFILE,fnm)) {
+ long sum;
- sum=0;
- for(i=0; i<nabin; i++)
- sum+=adist[i];
+ sum=0;
+ for(i=0; i<nabin; i++)
+ sum+=adist[i];
- fp = xvgropen(opt2fn("-ang",NFILE,fnm),
- "Hydrogen Bond Distribution",
- "Donor - Hydrogen - Acceptor Angle (\\SO\\N)","",oenv);
- for(i=0; i<nabin; i++)
- fprintf(fp,"%10g %10g\n",(i+0.5)*abin,adist[i]/(abin*(real)sum));
- ffclose(fp);
- }
+ fp = xvgropen(opt2fn("-ang",NFILE,fnm),
+ "Hydrogen Bond Distribution",
+ "Donor - Hydrogen - Acceptor Angle (\\SO\\N)","",oenv);
+ for(i=0; i<nabin; i++)
+ fprintf(fp,"%10g %10g\n",(i+0.5)*abin,adist[i]/(abin*(real)sum));
+ ffclose(fp);
+ }
- /* Print HB in alpha-helix */
- if (opt2bSet("-hx",NFILE,fnm)) {
- fp = xvgropen(opt2fn("-hx",NFILE,fnm),
- "Hydrogen Bonds","Time(ps)","Count",oenv);
- xvgr_legend(fp,NRHXTYPES,hxtypenames,oenv);
- for(i=0; i<nframes; i++) {
- fprintf(fp,"%10g",hb->time[i]);
- for (j=0; j<max_hx; j++)
- fprintf(fp," %6d",hb->nhx[i][j]);
- fprintf(fp,"\n");
+ /* Print HB in alpha-helix */
+ if (opt2bSet("-hx",NFILE,fnm)) {
+ fp = xvgropen(opt2fn("-hx",NFILE,fnm),
+ "Hydrogen Bonds","Time(ps)","Count",oenv);
+ xvgr_legend(fp,NRHXTYPES,hxtypenames,oenv);
+ for(i=0; i<nframes; i++) {
+ fprintf(fp,"%10g",hb->time[i]);
+ for (j=0; j<max_hx; j++)
+ fprintf(fp," %6d",hb->nhx[i][j]);
+ fprintf(fp,"\n");
+ }
+ ffclose(fp);
}
- ffclose(fp);
- }
- printf("Average number of %s per timeframe %.3f out of %g possible\n",
- bContact ? "contacts" : "hbonds",
- bContact ? aver_dist : aver_nhb, max_nhb);
+ if (!bNN)
+ printf("Average number of %s per timeframe %.3f out of %g possible\n",
+ bContact ? "contacts" : "hbonds",
+ bContact ? aver_dist : aver_nhb, max_nhb);
- /* Do Autocorrelation etc. */
- if (hb->bHBmap) {
- /*
- Added support for -contact in ac and hbm calculations below.
- - Erik Marklund, May 29, 2006
- */
+ /* Do Autocorrelation etc. */
+ if (hb->bHBmap) {
+ /*
+ Added support for -contact in ac and hbm calculations below.
+ - Erik Marklund, May 29, 2006
+ */
+ ivec itmp;
+ rvec rtmp;
+ if (opt2bSet("-ac",NFILE,fnm) || opt2bSet("-life",NFILE,fnm))
+ please_cite(stdout,"Spoel2006b");
+ if (opt2bSet("-ac",NFILE,fnm)) {
+ char *gemstring=NULL;
- if (opt2bSet("-ac",NFILE,fnm) || opt2bSet("-life",NFILE,fnm))
- please_cite(stdout,"Spoel2006b");
- if (opt2bSet("-ac",NFILE,fnm))
- do_hbac(opt2fn("-ac",NFILE,fnm),hb,aver_nhb/max_nhb,aver_dist,nDump,
- bMerge,bContact,fit_start,temp,r2cut>0,smooth_tail_start,oenv);
- if (opt2bSet("-life",NFILE,fnm))
- do_hblife(opt2fn("-life",NFILE,fnm),hb,bMerge,bContact,oenv);
- if (opt2bSet("-hbm",NFILE,fnm)) {
- t_matrix mat;
- int id,ia,hh,x,y;
+ if (bGem || bNN) {
+ params = init_gemParams(rcut, D, hb->time, hb->nframes/2, nFitPoints, fit_start, fit_end,
+ gemBallistic, nBalExp, bBallisticDt);
+ if (params == NULL)
+ gmx_fatal(FARGS, "Could not initiate t_gemParams params.");
+ }
+ gemstring = strdup(gemType[hb->per->gemtype]);
+ do_hbac(opt2fn("-ac",NFILE,fnm),hb,aver_nhb/max_nhb,aver_dist,nDump,
+ bMerge,bContact,fit_start,temp,r2cut>0,smooth_tail_start,oenv,
+ params, gemstring, nThreads, NN, bBallistic, bGemFit);
+ }
+ if (opt2bSet("-life",NFILE,fnm))
+ do_hblife(opt2fn("-life",NFILE,fnm),hb,bMerge,bContact,oenv);
+ if (opt2bSet("-hbm",NFILE,fnm)) {
+ t_matrix mat;
+ int id,ia,hh,x,y;
- mat.nx=nframes;
- mat.ny=(bContact ? hb->nrdist : hb->nrhb);
-
- snew(mat.matrix,mat.nx);
- for(x=0; (x<mat.nx); x++)
- snew(mat.matrix[x],mat.ny);
- y=0;
- for(id=0; (id<hb->d.nrd); id++)
- for(ia=0; (ia<hb->a.nra); ia++) {
- for(hh=0; (hh<hb->maxhydro); hh++) {
- if (hb->hbmap[id][ia]) {
- if (ISHB(hb->hbmap[id][ia]->history[hh])) {
- /* Changed '<' into '<=' in the for-statement below.
- * It fixed the previously undiscovered bug that caused
- * the last occurance of an hbond/contact to not be
- * set in mat.matrix. Have a look at any old -hbm-output
- * and you will notice that the last column is allways empty.
- * - Erik Marklund May 30, 2006
- */
- for(x=0; (x<=hb->hbmap[id][ia]->nframes); x++) {
- int nn0 = hb->hbmap[id][ia]->n0;
- range_check(y,0,mat.ny);
- mat.matrix[x+nn0][y] = is_hb(hb->hbmap[id][ia]->h[hh],x);
- }
- y++;
- }
- }
- }
- }
- mat.axis_x=hb->time;
- snew(mat.axis_y,mat.ny);
- for(j=0; j<mat.ny; j++)
- mat.axis_y[j]=j;
- sprintf(mat.title,bContact ? "Contact Existence Map":
- "Hydrogen Bond Existence Map");
- sprintf(mat.legend,bContact ? "Contacts" : "Hydrogen Bonds");
- sprintf(mat.label_x,"Time (ps)");
- sprintf(mat.label_y, bContact ? "Contact Index" : "Hydrogen Bond Index");
- mat.bDiscrete=TRUE;
- if (bInsert)
- mat.nmap=HB_NR;
- else
- mat.nmap=2;
- snew(mat.map,mat.nmap);
- for(i=0; i<mat.nmap; i++) {
- mat.map[i].code.c1=hbmap[i];
- mat.map[i].desc=hbdesc[i];
- mat.map[i].rgb=hbrgb[i];
- }
- fp = opt2FILE("-hbm",NFILE,fnm,"w");
- write_xpm_m(fp, mat);
- ffclose(fp);
- for(x=0; x<mat.nx; x++)
- sfree(mat.matrix[x]);
- sfree(mat.axis_y);
- sfree(mat.matrix);
- sfree(mat.map);
- }
- }
+ mat.nx=nframes;
+ mat.ny=(bContact ? hb->nrdist : hb->nrhb);
+
+ snew(mat.matrix,mat.nx);
+ for(x=0; (x<mat.nx); x++)
+ snew(mat.matrix[x],mat.ny);
+ y=0;
+ for(id=0; (id<hb->d.nrd); id++)
+ for(ia=0; (ia<hb->a.nra); ia++) {
+ for(hh=0; (hh<hb->maxhydro); hh++) {
+ if (hb->hbmap[id][ia]) {
+ if (ISHB(hb->hbmap[id][ia]->history[hh])) {
+ /* Changed '<' into '<=' in the for-statement below.
+ * It fixed the previously undiscovered bug that caused
+ * the last occurance of an hbond/contact to not be
+ * set in mat.matrix. Have a look at any old -hbm-output
+ * and you will notice that the last column is allways empty.
+ * - Erik Marklund May 30, 2006
+ */
+ for(x=0; (x<=hb->hbmap[id][ia]->nframes); x++) {
+ int nn0 = hb->hbmap[id][ia]->n0;
+ range_check(y,0,mat.ny);
+ mat.matrix[x+nn0][y] = is_hb(hb->hbmap[id][ia]->h[hh],x);
+ }
+ y++;
+ }
+ }
+ }
+ }
+ mat.axis_x=hb->time;
+ snew(mat.axis_y,mat.ny);
+ for(j=0; j<mat.ny; j++)
+ mat.axis_y[j]=j;
+ sprintf(mat.title,bContact ? "Contact Existence Map":
+ "Hydrogen Bond Existence Map");
+ sprintf(mat.legend,bContact ? "Contacts" : "Hydrogen Bonds");
+ sprintf(mat.label_x,"Time (ps)");
+ sprintf(mat.label_y, bContact ? "Contact Index" : "Hydrogen Bond Index");
+ mat.bDiscrete=TRUE;
+ if (bInsert)
+ mat.nmap=HB_NR;
+ else
+ mat.nmap=2;
+ snew(mat.map,mat.nmap);
+ for(i=0; i<mat.nmap; i++) {
+ mat.map[i].code.c1=hbmap[i];
+ mat.map[i].desc=hbdesc[i];
+ mat.map[i].rgb=hbrgb[i];
+ }
+ fp = opt2FILE("-hbm",NFILE,fnm,"w");
+ write_xpm_m(fp, mat);
+ ffclose(fp);
+ for(x=0; x<mat.nx; x++)
+ sfree(mat.matrix[x]);
+ sfree(mat.axis_y);
+ sfree(mat.matrix);
+ sfree(mat.map);
+ }
+ }
+
+ if (bGem) {
+ fprintf(stderr, "There were %i periodic shifts\n", hb->per->nper);
+ fprintf(stderr, "Freeing pHist for all donors...\n");
+ for (i=0; i<hb->d.nrd; i++) {
+ fprintf(stderr, "\r%i",i);
+ if (hb->per->pHist[i] != NULL) {
+ for (j=0; j<hb->a.nra; j++)
+ clearPshift(&(hb->per->pHist[i][j]));
+ sfree(hb->per->pHist[i]);
+ }
+ }
+ sfree(hb->per->pHist);
+ sfree(hb->per->p2i);
+ sfree(hb->per);
+ fprintf(stderr, "...done.\n");
+ }
+
+#ifdef HAVE_NN_LOOPS
+ if (bNN)
+ free_hbEmap(hb);
+#endif
- if (hb->bDAnr) {
- int i,j,nleg;
- char **legnames;
- char buf[STRLEN];
+ if (hb->bDAnr) {
+ int i,j,nleg;
+ char **legnames;
+ char buf[STRLEN];
#define USE_THIS_GROUP(j) ( (j == gr0) || (bTwo && (j == gr1)) || (bInsert && (j == grI)) )
- fp = xvgropen(opt2fn("-dan",NFILE,fnm),
- "Donors and Acceptors","Time(ps)","Count",oenv);
- nleg = (bTwo?2:1)*2 + (bInsert?2:0);
- snew(legnames,nleg);
- i=0;
- for(j=0; j<grNR; j++)
- if ( USE_THIS_GROUP(j) ) {
- sprintf(buf,"Donors %s",grpnames[j]);
- legnames[i++] = strdup(buf);
- sprintf(buf,"Acceptors %s",grpnames[j]);
- legnames[i++] = strdup(buf);
- }
- if (i != nleg)
- gmx_incons("number of legend entries");
- xvgr_legend(fp,nleg,legnames,oenv);
- for(i=0; i<nframes; i++) {
- fprintf(fp,"%10g",hb->time[i]);
- for (j=0; (j<grNR); j++)
- if ( USE_THIS_GROUP(j) )
- fprintf(fp," %6d",hb->danr[i][j]);
- fprintf(fp,"\n");
+ fp = xvgropen(opt2fn("-dan",NFILE,fnm),
+ "Donors and Acceptors","Time(ps)","Count",oenv);
+ nleg = (bTwo?2:1)*2 + (bInsert?2:0);
+ snew(legnames,nleg);
+ i=0;
+ for(j=0; j<grNR; j++)
+ if ( USE_THIS_GROUP(j) ) {
+ sprintf(buf,"Donors %s",grpnames[j]);
+ legnames[i++] = strdup(buf);
+ sprintf(buf,"Acceptors %s",grpnames[j]);
+ legnames[i++] = strdup(buf);
+ }
+ if (i != nleg)
+ gmx_incons("number of legend entries");
+ xvgr_legend(fp,nleg,legnames,oenv);
+ for(i=0; i<nframes; i++) {
+ fprintf(fp,"%10g",hb->time[i]);
+ for (j=0; (j<grNR); j++)
+ if ( USE_THIS_GROUP(j) )
+ fprintf(fp," %6d",hb->danr[i][j]);
+ fprintf(fp,"\n");
+ }
+ ffclose(fp);
}
- ffclose(fp);
- }
- thanx(stdout);
+ thanx(stdout);
- return 0;
+ return 0;
}
output_env_t oenv;
FILE *otrj;
char buf[54],prop[256];
- int status;
+ t_trxstatus *status;
int natoms,nre,nres;
t_bb *bb;
int i,j,ai,m,nall,nbb,nca,teller,nSel=0;
real t;
real rms,fac;
matrix box;
+ gmx_rmpbc_t gpbc=NULL;
bool bRange;
t_filenm fnm[] = {
{ efTPX, NULL, NULL, ffREAD },
pr_bb(stdout,nres,bb);
}
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
+
snew(xav,natoms);
teller=0;
do {
if ((teller++ % 10) == 0)
fprintf(stderr,"\rt=%.2f",t);
- rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
+
calc_hxprops(nres,bb,x,box);
if (bCheck)
} while (read_next_x(oenv,status,&t,natoms,x,box));
fprintf(stderr,"\n");
+ gmx_rmpbc_done(gpbc);
+
close_trj(status);
if (otrj) {
int gmx_helixorient(int argc,char *argv[])
{
const char *desc[] = {
- "g_helixorient calculates coordinates and direction of the average",
+ "g_helixorient calculates the coordinates and direction of the average",
"axis inside an alpha helix, and the direction/vectors of both the",
"alpha carbon and (optionally) a sidechain atom relative to the axis.[PAR]",
"As input, you need to specify an index group with alpha carbon atoms",
"corresponding to an alpha helix of continuous residues. Sidechain",
"directions require a second index group of the same size, containing",
- "the heavy atom in each residue that should represent the sidechain.[PAR]"
+ "the heavy atom in each residue that should represent the sidechain.[PAR]",
"Note that this program does not do any fitting of structures.[PAR]",
"We need four Calpha coordinates to define the local direction of the helix",
- "axis.[PAR]"
+ "axis.[PAR]",
"The tilt/rotation is calculated from Euler rotations, where we define",
"the helix axis as the local X axis, the residues/CA-vector as Y, and the",
"Z axis from their cross product. We use the Euler Y-Z-X rotation, meaning",
real t;
rvec *x=NULL,dx;
matrix box;
- int status;
+ t_trxstatus *status;
int natoms;
real theta1,theta2,theta3;
int ePBC;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
static bool bSC=FALSE;
static bool bIncremental = FALSE;
unitaxes[1][1]=1;
unitaxes[2][2]=1;
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
do
{
/* initialisation for correct distance calculations */
set_pbc(&pbc,ePBC,box);
/* make molecules whole again */
- rm_pbc(&top->idef,ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
/* copy coords to our smaller arrays */
for(i=0;i<iCA;i++)
teller++;
} while (read_next_x(oenv,status,&t,natoms,x,box));
-
+
+ gmx_rmpbc_done(gpbc);
+
ffclose(fpaxis);
ffclose(fpcenter);
ffclose(fptilt);
{
const char *desc[] = {
"g_kinetics reads two xvg files, each one containing data for N replicas.",
- "The first file contains the temperature of each replica at each timestep,"
+ "The first file contains the temperature of each replica at each timestep,",
"and the second contains real values that can be interpreted as",
"an indicator for folding. If the value in the file is larger than",
"the cutoff it is taken to be unfolded and the other way around.[PAR]",
"From these data an estimate of the forward and backward rate constants",
- "for folding is made at a reference temperature. In addition,"
- "a theoretical melting curve and free energy as a function of temperature"
+ "for folding is made at a reference temperature. In addition,",
+ "a theoretical melting curve and free energy as a function of temperature",
"are printed in an xvg file.[PAR]",
"The user can give a max value to be regarded as intermediate",
"([TT]-ucut[tt]), which, when given will trigger the use of an intermediate state",
char *grpname;
int *rndx,*natm,prevres,newres;
- int i,j,status,nres,natoms,nframes,it,trxnat;
+ int i,j,nres,natoms,nframes,it,trxnat;
+ t_trxstatus *status;
int nr0;
bool bCalcN,bFrames;
real t,ratio;
int *tot_n;
matrix box;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
CopyRight(stderr,argv[0]);
rlo.r=1.0, rlo.g=1.0, rlo.b=1.0;
rhi.r=0.0, rhi.g=0.0, rhi.b=0.0;
+
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,trxnat,box);
+
if (bFrames)
out=opt2FILE("-frames",NFILE,fnm,"w");
do {
- rm_pbc(&top.idef,ePBC,trxnat,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
nframes++;
calc_mat(nres,natoms,rndx,x,index,truncate,mdmat,nmat,ePBC,box);
for (i=0; (i<nres); i++)
} while (read_next_x(oenv,status,&t,trxnat,x,box));
fprintf(stderr,"\n");
close_trj(status);
+ gmx_rmpbc_done(gpbc);
if (bFrames)
ffclose(out);
--- /dev/null
+/*
+ * $Id: mdrun.c,v 1.139.2.9 2009/05/04 16:13:29 hess Exp $
+ *
+ * This source code is part of
+ *
+ * G R O M A C S
+ *
+ * GROningen MAchine for Chemical Simulations
+ *
+ * VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+#include "typedefs.h"
+#include "smalloc.h"
+#include "sysstuff.h"
+#include "vec.h"
+#include "statutil.h"
+#include "macros.h"
+#include "copyrite.h"
+#include "main.h"
+#include "futil.h"
+#include "edsam.h"
+#include "checkpoint.h"
+#include "vcm.h"
+#include "mdebin.h"
+#include "nrnb.h"
+#include "calcmu.h"
+#include "index.h"
+#include "vsite.h"
+#include "update.h"
+#include "ns.h"
+#include "trnio.h"
+#include "xtcio.h"
+#include "mdrun.h"
+#include "confio.h"
+#include "network.h"
+#include "pull.h"
+#include "xvgr.h"
+#include "physics.h"
+#include "names.h"
+#include "disre.h"
+#include "orires.h"
+#include "dihre.h"
+#include "pppm.h"
+#include "pme.h"
+#include "mdatoms.h"
+#include "qmmm.h"
+#include "mpelogging.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "topsort.h"
+#include "coulomb.h"
+#include "constr.h"
+#include "shellfc.h"
+#include "mvdata.h"
+#include "checkpoint.h"
+#include "mtop_util.h"
+#include "tpxio.h"
+#include "string2.h"
+#include "sighandler.h"
+#include "gmx_ana.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+/* afm stuf */
+#include "pull.h"
+
+/* We use the same defines as in mvdata.c here */
+#define block_bc(cr, d) gmx_bcast( sizeof(d), &(d),(cr))
+#define nblock_bc(cr,nr,d) gmx_bcast((nr)*sizeof((d)[0]), (d),(cr))
+#define snew_bc(cr,d,nr) { if (!MASTER(cr)) snew((d),(nr)); }
+
+/* The following two variables and the signal_handler function
+ * is used from pme.c as well
+ */
+
+typedef struct {
+ t_state s;
+ rvec *f;
+ real epot;
+ real fnorm;
+ real fmax;
+ int a_fmax;
+} em_state_t;
+
+typedef struct {
+ int it_xy;
+ int it_z;
+ int xy_step;
+ int z_step;
+ rvec xmin;
+ rvec xmax;
+ rvec *geom_cent;
+ int pieces;
+ int *nidx;
+ atom_id **subindex;
+} pos_ins_t;
+
+typedef struct {
+ int id;
+ char *name;
+ int nr;
+ int natoms; /*nr of atoms per lipid*/
+ int mol1; /*id of the first lipid molecule*/
+ real area;
+} lip_t;
+
+typedef struct {
+ char *name;
+ t_block mem_at;
+ int *mol_id;
+ int nmol;
+ real lip_area;
+ real zmin;
+ real zmax;
+ real zmed;
+} mem_t;
+
+typedef struct {
+ int *mol;
+ int *block;
+ int nr;
+} rm_t;
+
+int search_string(char *s,int ng,char ***gn)
+{
+ int i;
+
+ for(i=0; (i<ng); i++)
+ if (strcasecmp(s,*gn[i]) == 0)
+ return i;
+
+ gmx_fatal(FARGS,"Group %s not found in indexfile.\nMaybe you have non-default groups in your mdp file, while not using the '-n' option of grompp.\nIn that case use the '-n' option.\n",s);
+
+ return -1;
+}
+
+int get_mol_id(int at,int nmblock,gmx_molblock_t *mblock, int *type, int *block)
+{
+ int mol_id=0;
+ int i;
+
+ for(i=0;i<nmblock;i++)
+ {
+ if(at<(mblock[i].nmol*mblock[i].natoms_mol))
+ {
+ mol_id+=at/mblock[i].natoms_mol;
+ *type = mblock[i].type;
+ *block = i;
+ return mol_id;
+ } else {
+ at-= mblock[i].nmol*mblock[i].natoms_mol;
+ mol_id+=mblock[i].nmol;
+ }
+ }
+
+ gmx_fatal(FARGS,"Something is wrong in mol ids, at %d, mol_id %d",at,mol_id);
+
+ return -1;
+}
+
+int get_block(int mol_id,int nmblock,gmx_molblock_t *mblock)
+{
+ int i;
+ int nmol=0;
+
+ for(i=0;i<nmblock;i++)
+ {
+ nmol+=mblock[i].nmol;
+ if(mol_id<nmol)
+ return i;
+ }
+
+ gmx_fatal(FARGS,"mol_id %d larger than total number of molecules %d.\n",mol_id,nmol);
+
+ return -1;
+}
+
+int get_tpr_version(const char *infile)
+{
+ char buf[STRLEN];
+ bool bDouble;
+ int precision,fver;
+ t_fileio *fio;
+
+ fio = open_tpx(infile,"r");
+ gmx_fio_checktype(fio);
+
+ precision = sizeof(real);
+
+ gmx_fio_do_string(fio,buf);
+ if (strncmp(buf,"VERSION",7))
+ gmx_fatal(FARGS,"Can not read file %s,\n"
+ " this file is from a Gromacs version which is older than 2.0\n"
+ " Make a new one with grompp or use a gro or pdb file, if possible",
+ gmx_fio_getname(fio));
+ gmx_fio_do_int(fio,precision);
+ bDouble = (precision == sizeof(double));
+ if ((precision != sizeof(float)) && !bDouble)
+ gmx_fatal(FARGS,"Unknown precision in file %s: real is %d bytes "
+ "instead of %d or %d",
+ gmx_fio_getname(fio),precision,sizeof(float),sizeof(double));
+ gmx_fio_setprecision(fio,bDouble);
+ fprintf(stderr,"Reading file %s, %s (%s precision)\n",
+ gmx_fio_getname(fio),buf,bDouble ? "double" : "single");
+
+ gmx_fio_do_int(fio,fver);
+
+ close_tpx(fio);
+
+ return fver;
+}
+
+void set_inbox(int natom, rvec *x)
+{
+ rvec tmp;
+ int i;
+
+ tmp[XX]=tmp[YY]=tmp[ZZ]=0.0;
+ for(i=0;i<natom;i++)
+ {
+ if(x[i][XX]<tmp[XX]) tmp[XX]=x[i][XX];
+ if(x[i][YY]<tmp[YY]) tmp[YY]=x[i][YY];
+ if(x[i][ZZ]<tmp[ZZ]) tmp[ZZ]=x[i][ZZ];
+ }
+
+ for(i=0;i<natom;i++)
+ rvec_inc(x[i],tmp);
+}
+
+int get_mtype_list(t_block *at, gmx_mtop_t *mtop, t_block *tlist)
+{
+ int i,j,nr,mol_id;
+ int type=0,block=0;
+ bool bNEW;
+
+ nr=0;
+ snew(tlist->index,at->nr);
+ for (i=0;i<at->nr;i++)
+ {
+ bNEW=TRUE;
+ mol_id = get_mol_id(at->index[i],mtop->nmolblock,mtop->molblock,&type,&block);
+ for(j=0;j<nr;j++)
+ {
+ if(tlist->index[j]==type)
+ bNEW=FALSE;
+ }
+ if(bNEW==TRUE)
+ {
+ tlist->index[nr]=type;
+ nr++;
+ }
+ }
+
+ srenew(tlist->index,nr);
+ return nr;
+}
+
+void check_types(t_block *ins_at,t_block *rest_at,gmx_mtop_t *mtop)
+{
+ t_block *ins_mtype,*rest_mtype;
+ int i,j;
+
+ snew(ins_mtype,1);
+ snew(rest_mtype,1);
+ ins_mtype->nr = get_mtype_list(ins_at , mtop, ins_mtype );
+ rest_mtype->nr = get_mtype_list(rest_at, mtop, rest_mtype);
+
+ for(i=0;i<ins_mtype->nr;i++)
+ {
+ for(j=0;j<rest_mtype->nr;j++)
+ {
+ if(ins_mtype->index[i]==rest_mtype->index[j])
+ gmx_fatal(FARGS,"Moleculetype %s is found both in the group to insert and the rest of the system.\n"
+ "Because we need to exclude all interactions between the atoms in the group to\n"
+ "insert, the same moleculetype can not be used in both groups. Change the\n"
+ "moleculetype of the molecules %s in the inserted group. Do not forget to provide\n"
+ "an appropriate *.itp file",*(mtop->moltype[rest_mtype->index[j]].name),
+ *(mtop->moltype[rest_mtype->index[j]].name));
+ }
+ }
+
+ sfree(ins_mtype->index);
+ sfree(rest_mtype->index);
+ sfree(ins_mtype);
+ sfree(rest_mtype);
+}
+
+int init_ins_at(t_block *ins_at,t_block *rest_at,t_state *state, pos_ins_t *pos_ins,gmx_groups_t *groups,int ins_grp_id, real xy_max)
+{
+ int i,gid,c=0;
+ real x,xmin,xmax,y,ymin,ymax,z,zmin,zmax;
+
+ snew(rest_at->index,state->natoms);
+
+ xmin=xmax=state->x[ins_at->index[0]][XX];
+ ymin=ymax=state->x[ins_at->index[0]][YY];
+ zmin=zmax=state->x[ins_at->index[0]][ZZ];
+
+ for(i=0;i<state->natoms;i++)
+ {
+ gid = groups->grpnr[egcFREEZE][i];
+ if(groups->grps[egcFREEZE].nm_ind[gid]==ins_grp_id)
+ {
+ x=state->x[i][XX];
+ if (x<xmin) xmin=x;
+ if (x>xmax) xmax=x;
+ y=state->x[i][YY];
+ if (y<ymin) ymin=y;
+ if (y>ymax) ymax=y;
+ z=state->x[i][ZZ];
+ if (z<zmin) zmin=z;
+ if (z>zmax) zmax=z;
+ } else {
+ rest_at->index[c]=i;
+ c++;
+ }
+ }
+
+ rest_at->nr=c;
+ srenew(rest_at->index,c);
+
+ if(xy_max>1.000001)
+ {
+ pos_ins->xmin[XX]=xmin-((xmax-xmin)*xy_max-(xmax-xmin))/2;
+ pos_ins->xmin[YY]=ymin-((ymax-ymin)*xy_max-(ymax-ymin))/2;
+
+ pos_ins->xmax[XX]=xmax+((xmax-xmin)*xy_max-(xmax-xmin))/2;
+ pos_ins->xmax[YY]=ymax+((ymax-ymin)*xy_max-(ymax-ymin))/2;
+ } else {
+ pos_ins->xmin[XX]=xmin;
+ pos_ins->xmin[YY]=ymin;
+
+ pos_ins->xmax[XX]=xmax;
+ pos_ins->xmax[YY]=ymax;
+ }
+
+ /* 6.0 is estimated thickness of bilayer */
+ if( (zmax-zmin) < 6.0 )
+ {
+ pos_ins->xmin[ZZ]=zmin+(zmax-zmin)/2.0-3.0;
+ pos_ins->xmax[ZZ]=zmin+(zmax-zmin)/2.0+3.0;
+ } else {
+ pos_ins->xmin[ZZ]=zmin;
+ pos_ins->xmax[ZZ]=zmax;
+ }
+
+ return c;
+}
+
+real est_prot_area(pos_ins_t *pos_ins,rvec *r,t_block *ins_at, mem_t *mem_p)
+{
+ real x,y,dx=0.15,dy=0.15,area=0.0;
+ real add;
+ int c,at;
+
+ for(x=pos_ins->xmin[XX];x<pos_ins->xmax[XX];x+=dx)
+ {
+ for(y=pos_ins->xmin[YY];y<pos_ins->xmax[YY];y+=dy)
+ {
+ c=0;
+ add=0.0;
+ do
+ {
+ at=ins_at->index[c];
+ if ( (r[at][XX]>=x) && (r[at][XX]<x+dx) &&
+ (r[at][YY]>=y) && (r[at][YY]<y+dy) &&
+ (r[at][ZZ]>mem_p->zmin+1.0) && (r[at][ZZ]<mem_p->zmax-1.0) )
+ add=1.0;
+ c++;
+ } while ( (c<ins_at->nr) && (add<0.5) );
+ area+=add;
+ }
+ }
+ area=area*dx*dy;
+
+ return area;
+}
+
+void init_lip(matrix box, gmx_mtop_t *mtop, lip_t *lip)
+{
+ int i;
+ real mem_area;
+ int mol1=0;
+
+ mem_area = box[XX][XX]*box[YY][YY]-box[XX][YY]*box[YY][XX];
+ for(i=0;i<mtop->nmolblock;i++)
+ {
+ if(mtop->molblock[i].type == lip->id)
+ {
+ lip->nr=mtop->molblock[i].nmol;
+ lip->natoms=mtop->molblock[i].natoms_mol;
+ }
+ }
+ lip->area=2.0*mem_area/(double)lip->nr;
+
+ for (i=0;i<lip->id;i++)
+ mol1+=mtop->molblock[i].nmol;
+ lip->mol1=mol1;
+}
+
+int init_mem_at(mem_t *mem_p, gmx_mtop_t *mtop, rvec *r, matrix box, pos_ins_t *pos_ins)
+{
+ int i,j,at,mol,nmol,nmolbox,count;
+ t_block *mem_a;
+ real z,zmin,zmax,mem_area;
+ bool bNew;
+ atom_id *mol_id;
+ int type=0,block=0;
+
+ nmol=count=0;
+ mem_a=&(mem_p->mem_at);
+ snew(mol_id,mem_a->nr);
+/* snew(index,mem_a->nr); */
+ zmin=pos_ins->xmax[ZZ];
+ zmax=pos_ins->xmin[ZZ];
+ for(i=0;i<mem_a->nr;i++)
+ {
+ at=mem_a->index[i];
+ if( (r[at][XX]>pos_ins->xmin[XX]) && (r[at][XX]<pos_ins->xmax[XX]) &&
+ (r[at][YY]>pos_ins->xmin[YY]) && (r[at][YY]<pos_ins->xmax[YY]) &&
+ (r[at][ZZ]>pos_ins->xmin[ZZ]) && (r[at][ZZ]<pos_ins->xmax[ZZ]) )
+ {
+ mol = get_mol_id(at,mtop->nmolblock,mtop->molblock,&type,&block);
+
+ bNew=TRUE;
+ for(j=0;j<nmol;j++)
+ if(mol == mol_id[j])
+ bNew=FALSE;
+
+ if(bNew)
+ {
+ mol_id[nmol]=mol;
+ nmol++;
+ }
+
+ z=r[at][ZZ];
+ if(z<zmin) zmin=z;
+ if(z>zmax) zmax=z;
+
+/* index[count]=at;*/
+ count++;
+ }
+ }
+
+ mem_p->nmol=nmol;
+ srenew(mol_id,nmol);
+ mem_p->mol_id=mol_id;
+/* srenew(index,count);*/
+/* mem_p->mem_at.nr=count;*/
+/* sfree(mem_p->mem_at.index);*/
+/* mem_p->mem_at.index=index;*/
+
+ if((zmax-zmin)>(box[ZZ][ZZ]-0.5))
+ gmx_fatal(FARGS,"Something is wrong with your membrane. Max and min z values are %f and %f.\n"
+ "Maybe your membrane is not centered in the box, but located at the box edge in the z-direction,\n"
+ "so that one membrane is distributed over two periodic box images. Another possibility is that\n"
+ "your water layer is not thick enough.\n",zmax,zmin);
+ mem_p->zmin=zmin;
+ mem_p->zmax=zmax;
+ mem_p->zmed=(zmax-zmin)/2+zmin;
+
+ /*number of membrane molecules in protein box*/
+ nmolbox = count/mtop->molblock[block].natoms_mol;
+ /*mem_area = box[XX][XX]*box[YY][YY]-box[XX][YY]*box[YY][XX];
+ mem_p->lip_area = 2.0*mem_area/(double)mem_p->nmol;*/
+ mem_area = (pos_ins->xmax[XX]-pos_ins->xmin[XX])*(pos_ins->xmax[YY]-pos_ins->xmin[YY]);
+ mem_p->lip_area = 2.0*mem_area/(double)nmolbox;
+
+ return mem_p->mem_at.nr;
+}
+
+void init_resize(t_block *ins_at,rvec *r_ins,pos_ins_t *pos_ins,mem_t *mem_p,rvec *r, bool bALLOW_ASYMMETRY)
+{
+ int i,j,at,c,outsidesum,gctr=0;
+ int idxsum=0;
+
+ /*sanity check*/
+ for (i=0;i<pos_ins->pieces;i++)
+ idxsum+=pos_ins->nidx[i];
+ if (idxsum!=ins_at->nr)
+ gmx_fatal(FARGS,"Piecewise sum of inserted atoms not same as size of group selected to insert.");
+
+ snew(pos_ins->geom_cent,pos_ins->pieces);
+ for (i=0;i<pos_ins->pieces;i++)
+ {
+ c=0;
+ outsidesum=0;
+ for(j=0;j<DIM;j++)
+ pos_ins->geom_cent[i][j]=0;
+
+ for(j=0;j<DIM;j++)
+ pos_ins->geom_cent[i][j]=0;
+ for (j=0;j<pos_ins->nidx[i];j++)
+ {
+ at=pos_ins->subindex[i][j];
+ copy_rvec(r[at],r_ins[gctr]);
+ if( (r_ins[gctr][ZZ]<mem_p->zmax) && (r_ins[gctr][ZZ]>mem_p->zmin) )
+ {
+ rvec_inc(pos_ins->geom_cent[i],r_ins[gctr]);
+ c++;
+ }
+ else
+ outsidesum++;
+ gctr++;
+ }
+ if (c>0)
+ svmul(1/(double)c,pos_ins->geom_cent[i],pos_ins->geom_cent[i]);
+ if (!bALLOW_ASYMMETRY)
+ pos_ins->geom_cent[i][ZZ]=mem_p->zmed;
+
+ fprintf(stderr,"Embedding piece %d with center of geometry: %f %f %f\n",i,pos_ins->geom_cent[i][XX],pos_ins->geom_cent[i][YY],pos_ins->geom_cent[i][ZZ]);
+ }
+ fprintf(stderr,"\n");
+}
+
+void resize(t_block *ins_at, rvec *r_ins, rvec *r, pos_ins_t *pos_ins,rvec fac)
+{
+ int i,j,k,at,c=0;
+ for (k=0;k<pos_ins->pieces;k++)
+ for(i=0;i<pos_ins->nidx[k];i++)
+ {
+ at=pos_ins->subindex[k][i];
+ for(j=0;j<DIM;j++)
+ r[at][j]=pos_ins->geom_cent[k][j]+fac[j]*(r_ins[c][j]-pos_ins->geom_cent[k][j]);
+ c++;
+ }
+}
+
+int gen_rm_list(rm_t *rm_p,t_block *ins_at,t_block *rest_at,t_pbc *pbc, gmx_mtop_t *mtop,
+ rvec *r, rvec *r_ins, mem_t *mem_p, pos_ins_t *pos_ins, real probe_rad, int low_up_rm, bool bALLOW_ASYMMETRY)
+{
+ int i,j,k,l,at,at2,mol_id;
+ int type=0,block=0;
+ int nrm,nupper,nlower;
+ real r_min_rad,z_lip,min_norm;
+ bool bRM;
+ rvec dr,dr_tmp;
+ real *dist;
+ int *order;
+
+ r_min_rad=probe_rad*probe_rad;
+ snew(rm_p->mol,mtop->mols.nr);
+ snew(rm_p->block,mtop->mols.nr);
+ nrm=nupper=0;
+ nlower=low_up_rm;
+ for(i=0;i<ins_at->nr;i++)
+ {
+ at=ins_at->index[i];
+ for(j=0;j<rest_at->nr;j++)
+ {
+ at2=rest_at->index[j];
+ pbc_dx(pbc,r[at],r[at2],dr);
+
+ if(norm2(dr)<r_min_rad)
+ {
+ mol_id = get_mol_id(at2,mtop->nmolblock,mtop->molblock,&type,&block);
+ bRM=TRUE;
+ for(l=0;l<nrm;l++)
+ if(rm_p->mol[l]==mol_id)
+ bRM=FALSE;
+ if(bRM)
+ {
+ /*fprintf(stderr,"%d wordt toegevoegd\n",mol_id);*/
+ rm_p->mol[nrm]=mol_id;
+ rm_p->block[nrm]=block;
+ nrm++;
+ z_lip=0.0;
+ for(l=0;l<mem_p->nmol;l++)
+ {
+ if(mol_id==mem_p->mol_id[l])
+ {
+ for(k=mtop->mols.index[mol_id];k<mtop->mols.index[mol_id+1];k++)
+ z_lip+=r[k][ZZ];
+ z_lip/=mtop->molblock[block].natoms_mol;
+ if(z_lip<mem_p->zmed)
+ nlower++;
+ else
+ nupper++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*make sure equal number of lipids from upper and lower layer are removed */
+ if( (nupper!=nlower) && (!bALLOW_ASYMMETRY) )
+ {
+ snew(dist,mem_p->nmol);
+ snew(order,mem_p->nmol);
+ for(i=0;i<mem_p->nmol;i++)
+ {
+ at = mtop->mols.index[mem_p->mol_id[i]];
+ pbc_dx(pbc,r[at],pos_ins->geom_cent[0],dr);
+ if (pos_ins->pieces>1)
+ {
+ /*minimum dr value*/
+ min_norm=norm2(dr);
+ for (k=1;k<pos_ins->pieces;k++)
+ {
+ pbc_dx(pbc,r[at],pos_ins->geom_cent[k],dr_tmp);
+ if (norm2(dr_tmp) < min_norm)
+ {
+ min_norm=norm2(dr_tmp);
+ copy_rvec(dr_tmp,dr);
+ }
+ }
+ }
+ dist[i]=dr[XX]*dr[XX]+dr[YY]*dr[YY];
+ j=i-1;
+ while (j>=0 && dist[i]<dist[order[j]])
+ {
+ order[j+1]=order[j];
+ j--;
+ }
+ order[j+1]=i;
+ }
+
+ i=0;
+ while(nupper!=nlower)
+ {
+ mol_id=mem_p->mol_id[order[i]];
+ block=get_block(mol_id,mtop->nmolblock,mtop->molblock);
+
+ bRM=TRUE;
+ for(l=0;l<nrm;l++)
+ if(rm_p->mol[l]==mol_id)
+ bRM=FALSE;
+ if(bRM)
+ {
+ z_lip=0;
+ for(k=mtop->mols.index[mol_id];k<mtop->mols.index[mol_id+1];k++)
+ z_lip+=r[k][ZZ];
+ z_lip/=mtop->molblock[block].natoms_mol;
+ if(nupper>nlower && z_lip<mem_p->zmed)
+ {
+ rm_p->mol[nrm]=mol_id;
+ rm_p->block[nrm]=block;
+ nrm++;
+ nlower++;
+ }
+ else if (nupper<nlower && z_lip>mem_p->zmed)
+ {
+ rm_p->mol[nrm]=mol_id;
+ rm_p->block[nrm]=block;
+ nrm++;
+ nupper++;
+ }
+ }
+ i++;
+
+ if(i>mem_p->nmol)
+ gmx_fatal(FARGS,"Trying to remove more lipid molecules than there are in the membrane");
+ }
+ sfree(dist);
+ sfree(order);
+ }
+
+ rm_p->nr=nrm;
+ srenew(rm_p->mol,nrm);
+ srenew(rm_p->block,nrm);
+
+ return nupper+nlower;
+}
+
+void rm_group(t_inputrec *ir, gmx_groups_t *groups, gmx_mtop_t *mtop, rm_t *rm_p, t_state *state, t_block *ins_at, pos_ins_t *pos_ins)
+{
+ int i,j,k,n,rm,mol_id,at,block;
+ rvec *x_tmp,*v_tmp;
+ atom_id *list,*new_mols;
+ unsigned char *new_egrp[egcNR];
+ bool bRM;
+
+ snew(list,state->natoms);
+ n=0;
+ for(i=0;i<rm_p->nr;i++)
+ {
+ mol_id=rm_p->mol[i];
+ at=mtop->mols.index[mol_id];
+ block =rm_p->block[i];
+ mtop->molblock[block].nmol--;
+ for(j=0;j<mtop->molblock[block].natoms_mol;j++)
+ {
+ list[n]=at+j;
+ n++;
+ }
+
+ mtop->mols.index[mol_id]=-1;
+ }
+
+ mtop->mols.nr-=rm_p->nr;
+ mtop->mols.nalloc_index-=rm_p->nr;
+ snew(new_mols,mtop->mols.nr);
+ for(i=0;i<mtop->mols.nr+rm_p->nr;i++)
+ {
+ j=0;
+ if(mtop->mols.index[i]!=-1)
+ {
+ new_mols[j]=mtop->mols.index[i];
+ j++;
+ }
+ }
+ sfree(mtop->mols.index);
+ mtop->mols.index=new_mols;
+
+
+ mtop->natoms-=n;
+ state->natoms-=n;
+ state->nalloc=state->natoms;
+ snew(x_tmp,state->nalloc);
+ snew(v_tmp,state->nalloc);
+
+ for(i=0;i<egcNR;i++)
+ {
+ if(groups->grpnr[i]!=NULL)
+ {
+ groups->ngrpnr[i]=state->natoms;
+ snew(new_egrp[i],state->natoms);
+ }
+ }
+
+ rm=0;
+ for (i=0;i<state->natoms+n;i++)
+ {
+ bRM=FALSE;
+ for(j=0;j<n;j++)
+ {
+ if(i==list[j])
+ {
+ bRM=TRUE;
+ rm++;
+ }
+ }
+
+ if(!bRM)
+ {
+ for(j=0;j<egcNR;j++)
+ {
+ if(groups->grpnr[j]!=NULL)
+ {
+ new_egrp[j][i-rm]=groups->grpnr[j][i];
+ }
+ }
+ copy_rvec(state->x[i],x_tmp[i-rm]);
+ copy_rvec(state->v[i],v_tmp[i-rm]);
+ for(j=0;j<ins_at->nr;j++)
+ {
+ if (i==ins_at->index[j])
+ ins_at->index[j]=i-rm;
+ }
+ for(j=0;j<pos_ins->pieces;j++)
+ {
+ for(k=0;k<pos_ins->nidx[j];k++)
+ {
+ if (i==pos_ins->subindex[j][k])
+ pos_ins->subindex[j][k]=i-rm;
+ }
+ }
+ }
+ }
+ sfree(state->x);
+ state->x=x_tmp;
+ sfree(state->v);
+ state->v=v_tmp;
+
+ for(i=0;i<egcNR;i++)
+ {
+ if(groups->grpnr[i]!=NULL)
+ {
+ sfree(groups->grpnr[i]);
+ groups->grpnr[i]=new_egrp[i];
+ }
+ }
+}
+
+int rm_bonded(t_block *ins_at, gmx_mtop_t *mtop)
+{
+ int i,j,m;
+ int type,natom,nmol,at,atom1=0,rm_at=0;
+ bool *bRM,bINS;
+ /*this routine lives dangerously by assuming that all molecules of a given type are in order in the structure*/
+ /*this routine does not live as dangerously as it seems. There is namely a check in mdrunner_membed to make
+ *sure that g_membed exits with a warning when there are molecules of the same type not in the
+ *ins_at index group. MGWolf 050710 */
+
+
+ snew(bRM,mtop->nmoltype);
+ for (i=0;i<mtop->nmoltype;i++)
+ {
+ bRM[i]=TRUE;
+ }
+
+ for (i=0;i<mtop->nmolblock;i++)
+ {
+ /*loop over molecule blocks*/
+ type =mtop->molblock[i].type;
+ natom =mtop->molblock[i].natoms_mol;
+ nmol =mtop->molblock[i].nmol;
+
+ for(j=0;j<natom*nmol && bRM[type]==TRUE;j++)
+ {
+ /*loop over atoms in the block*/
+ at=j+atom1; /*atom index = block index + offset*/
+ bINS=FALSE;
+
+ for (m=0;(m<ins_at->nr) && (bINS==FALSE);m++)
+ {
+ /*loop over atoms in insertion index group to determine if we're inserting one*/
+ if(at==ins_at->index[m])
+ {
+ bINS=TRUE;
+ }
+ }
+ bRM[type]=bINS;
+ }
+ atom1+=natom*nmol; /*update offset*/
+ if(bRM[type])
+ {
+ rm_at+=natom*nmol; /*increment bonded removal counter by # atoms in block*/
+ }
+ }
+
+ for(i=0;i<mtop->nmoltype;i++)
+ {
+ if(bRM[i])
+ {
+ for(j=0;j<F_LJ;j++)
+ {
+ mtop->moltype[i].ilist[j].nr=0;
+ }
+ for(j=F_POSRES;j<=F_VSITEN;j++)
+ {
+ mtop->moltype[i].ilist[j].nr=0;
+ }
+ }
+ }
+ sfree(bRM);
+
+ return rm_at;
+}
+
+void top_update(const char *topfile, char *ins, rm_t *rm_p, gmx_mtop_t *mtop)
+{
+#define TEMP_FILENM "temp.top"
+ int bMolecules=0;
+ FILE *fpin,*fpout;
+ char buf[STRLEN],buf2[STRLEN],*temp;
+ int i,*nmol_rm,nmol,line;
+
+ fpin = ffopen(topfile,"r");
+ fpout = ffopen(TEMP_FILENM,"w");
+
+ snew(nmol_rm,mtop->nmoltype);
+ for(i=0;i<rm_p->nr;i++)
+ nmol_rm[rm_p->block[i]]++;
+
+ line=0;
+ while(fgets(buf,STRLEN,fpin))
+ {
+ line++;
+ if(buf[0]!=';')
+ {
+ strcpy(buf2,buf);
+ if ((temp=strchr(buf2,'\n')) != NULL)
+ temp[0]='\0';
+ ltrim(buf2);
+
+ if (buf2[0]=='[')
+ {
+ buf2[0]=' ';
+ if ((temp=strchr(buf2,'\n')) != NULL)
+ temp[0]='\0';
+ rtrim(buf2);
+ if (buf2[strlen(buf2)-1]==']')
+ {
+ buf2[strlen(buf2)-1]='\0';
+ ltrim(buf2);
+ rtrim(buf2);
+ if (strcasecmp(buf2,"molecules")==0)
+ bMolecules=1;
+ }
+ fprintf(fpout,"%s",buf);
+ } else if (bMolecules==1)
+ {
+ for(i=0;i<mtop->nmolblock;i++)
+ {
+ nmol=mtop->molblock[i].nmol;
+ sprintf(buf,"%-15s %5d\n",*(mtop->moltype[mtop->molblock[i].type].name),nmol);
+ fprintf(fpout,"%s",buf);
+ }
+ bMolecules=2;
+ } else if (bMolecules==2)
+ {
+ /* print nothing */
+ } else
+ {
+ fprintf(fpout,"%s",buf);
+ }
+ } else
+ {
+ fprintf(fpout,"%s",buf);
+ }
+ }
+
+ fclose(fpout);
+ /* use ffopen to generate backup of topinout */
+ fpout=ffopen(topfile,"w");
+ fclose(fpout);
+ rename(TEMP_FILENM,topfile);
+#undef TEMP_FILENM
+}
+
+void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf)
+{
+ if (MASTER(cr))
+ {
+ fprintf(stderr,"\n%s\n",buf);
+ }
+ if (fplog)
+ {
+ fprintf(fplog,"\n%s\n",buf);
+ }
+}
+
+/* simulation conditions to transmit. Keep in mind that they are
+ transmitted to other nodes through an MPI_Reduce after
+ casting them to a real (so the signals can be sent together with other
+ data). This means that the only meaningful values are positive,
+ negative or zero. */
+enum { eglsNABNSB, eglsCHKPT, eglsSTOPCOND, eglsRESETCOUNTERS, eglsNR };
+/* Is the signal in one simulation independent of other simulations? */
+bool gs_simlocal[eglsNR] = { TRUE, FALSE, FALSE, TRUE };
+
+typedef struct {
+ int nstms; /* The frequency for intersimulation communication */
+ int sig[eglsNR]; /* The signal set by one process in do_md */
+ int set[eglsNR]; /* The communicated signal, equal for all processes */
+} globsig_t;
+
+
+static int multisim_min(const gmx_multisim_t *ms,int nmin,int n)
+{
+ int *buf;
+ bool bPos,bEqual;
+ int s,d;
+
+ snew(buf,ms->nsim);
+ buf[ms->sim] = n;
+ gmx_sumi_sim(ms->nsim,buf,ms);
+ bPos = TRUE;
+ bEqual = TRUE;
+ for(s=0; s<ms->nsim; s++)
+ {
+ bPos = bPos && (buf[s] > 0);
+ bEqual = bEqual && (buf[s] == buf[0]);
+ }
+ if (bPos)
+ {
+ if (bEqual)
+ {
+ nmin = min(nmin,buf[0]);
+ }
+ else
+ {
+ /* Find the least common multiple */
+ for(d=2; d<nmin; d++)
+ {
+ s = 0;
+ while (s < ms->nsim && d % buf[s] == 0)
+ {
+ s++;
+ }
+ if (s == ms->nsim)
+ {
+ /* We found the LCM and it is less than nmin */
+ nmin = d;
+ break;
+ }
+ }
+ }
+ }
+ sfree(buf);
+
+ return nmin;
+}
+
+static int multisim_nstsimsync(const t_commrec *cr,
+ const t_inputrec *ir,int repl_ex_nst)
+{
+ int nmin;
+
+ if (MASTER(cr))
+ {
+ nmin = INT_MAX;
+ nmin = multisim_min(cr->ms,nmin,ir->nstlist);
+ nmin = multisim_min(cr->ms,nmin,ir->nstcalcenergy);
+ nmin = multisim_min(cr->ms,nmin,repl_ex_nst);
+ if (nmin == INT_MAX)
+ {
+ gmx_fatal(FARGS,"Can not find an appropriate interval for inter-simulation communication, since nstlist, nstcalcenergy and -replex are all <= 0");
+ }
+ /* Avoid inter-simulation communication at every (second) step */
+ if (nmin <= 2)
+ {
+ nmin = 10;
+ }
+ }
+
+ gmx_bcast(sizeof(int),&nmin,cr);
+
+ return nmin;
+}
+
+static void init_global_signals(globsig_t *gs,const t_commrec *cr,
+ const t_inputrec *ir,int repl_ex_nst)
+{
+ int i;
+
+ if (MULTISIM(cr))
+ {
+ gs->nstms = multisim_nstsimsync(cr,ir,repl_ex_nst);
+ if (debug)
+ {
+ fprintf(debug,"Syncing simulations for checkpointing and termination every %d steps\n",gs->nstms);
+ }
+ }
+ else
+ {
+ gs->nstms = 1;
+ }
+
+ for(i=0; i<eglsNR; i++)
+ {
+ gs->sig[i] = 0;
+ gs->set[i] = 0;
+ }
+}
+
+static void copy_coupling_state(t_state *statea,t_state *stateb,
+ gmx_ekindata_t *ekinda,gmx_ekindata_t *ekindb, t_grpopts* opts)
+{
+
+ /* MRS note -- might be able to get rid of some of the arguments. Look over it when it's all debugged */
+
+ int i,j,nc;
+
+ /* Make sure we have enough space for x and v */
+ if (statea->nalloc > stateb->nalloc)
+ {
+ stateb->nalloc = statea->nalloc;
+ srenew(stateb->x,stateb->nalloc);
+ srenew(stateb->v,stateb->nalloc);
+ }
+
+ stateb->natoms = statea->natoms;
+ stateb->ngtc = statea->ngtc;
+ stateb->nnhpres = statea->nnhpres;
+ stateb->veta = statea->veta;
+ if (ekinda)
+ {
+ copy_mat(ekinda->ekin,ekindb->ekin);
+ for (i=0; i<stateb->ngtc; i++)
+ {
+ ekindb->tcstat[i].T = ekinda->tcstat[i].T;
+ ekindb->tcstat[i].Th = ekinda->tcstat[i].Th;
+ copy_mat(ekinda->tcstat[i].ekinh,ekindb->tcstat[i].ekinh);
+ copy_mat(ekinda->tcstat[i].ekinf,ekindb->tcstat[i].ekinf);
+ ekindb->tcstat[i].ekinscalef_nhc = ekinda->tcstat[i].ekinscalef_nhc;
+ ekindb->tcstat[i].ekinscaleh_nhc = ekinda->tcstat[i].ekinscaleh_nhc;
+ ekindb->tcstat[i].vscale_nhc = ekinda->tcstat[i].vscale_nhc;
+ }
+ }
+ copy_rvecn(statea->x,stateb->x,0,stateb->natoms);
+ copy_rvecn(statea->v,stateb->v,0,stateb->natoms);
+ copy_mat(statea->box,stateb->box);
+ copy_mat(statea->box_rel,stateb->box_rel);
+ copy_mat(statea->boxv,stateb->boxv);
+
+ for (i = 0; i<stateb->ngtc; i++)
+ {
+ nc = i*opts->nhchainlength;
+ for (j=0; j<opts->nhchainlength; j++)
+ {
+ stateb->nosehoover_xi[nc+j] = statea->nosehoover_xi[nc+j];
+ stateb->nosehoover_vxi[nc+j] = statea->nosehoover_vxi[nc+j];
+ }
+ }
+ if (stateb->nhpres_xi != NULL)
+ {
+ for (i = 0; i<stateb->nnhpres; i++)
+ {
+ nc = i*opts->nhchainlength;
+ for (j=0; j<opts->nhchainlength; j++)
+ {
+ stateb->nhpres_xi[nc+j] = statea->nhpres_xi[nc+j];
+ stateb->nhpres_vxi[nc+j] = statea->nhpres_vxi[nc+j];
+ }
+ }
+ }
+}
+
+static void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inputrec *ir,
+ t_forcerec *fr, gmx_ekindata_t *ekind,
+ t_state *state, t_state *state_global, t_mdatoms *mdatoms,
+ t_nrnb *nrnb, t_vcm *vcm, gmx_wallcycle_t wcycle,
+ gmx_enerdata_t *enerd,tensor force_vir, tensor shake_vir, tensor total_vir,
+ tensor pres, rvec mu_tot, gmx_constr_t constr,
+ globsig_t *gs,bool bInterSimGS,
+ matrix box, gmx_mtop_t *top_global, real *pcurr,
+ int natoms, bool *bSumEkinhOld, int flags)
+{
+ int i,gsi;
+ real gs_buf[eglsNR];
+ tensor corr_vir,corr_pres;
+ bool bEner,bPres,bTemp;
+ bool bRerunMD, bStopCM, bGStat, bNEMD, bIterate,
+ bFirstIterate,bReadEkin,bEkinAveVel,bScaleEkin, bConstrain;
+ real prescorr,enercorr,dvdlcorr;
+
+ /* translate CGLO flags to booleans */
+ bRerunMD = flags & CGLO_RERUNMD;
+ bStopCM = flags & CGLO_STOPCM;
+ bGStat = flags & CGLO_GSTAT;
+ bNEMD = flags & CGLO_NEMD;
+ bReadEkin = flags & CGLO_READEKIN;
+ bScaleEkin = flags & CGLO_SCALEEKIN;
+ bEner = flags & CGLO_ENERGY;
+ bTemp = flags & CGLO_TEMPERATURE;
+ bPres = flags & CGLO_PRESSURE;
+ bConstrain = flags & CGLO_CONSTRAINT;
+ bIterate = flags & CGLO_ITERATE;
+ bFirstIterate = flags & CGLO_FIRSTITERATE;
+
+ /* we calculate a full state kinetic energy either with full-step velocity verlet
+ or half step where we need the pressure */
+ bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir) && bPres) || bReadEkin);
+
+ /* in initalization, it sums the shake virial in vv, and to
+ sums ekinh_old in leapfrog (or if we are calculating ekinh_old for other reasons */
+
+ /* ########## Kinetic energy ############## */
+
+ if (bTemp)
+ {
+ /* Non-equilibrium MD: this is parallellized, but only does communication
+ * when there really is NEMD.
+ */
+
+ if (PAR(cr) && (bNEMD))
+ {
+ accumulate_u(cr,&(ir->opts),ekind);
+ }
+ debug_gmx();
+ if (bReadEkin)
+ {
+ restore_ekinstate_from_state(cr,ekind,&state_global->ekinstate);
+ }
+ else
+ {
+
+ calc_ke_part(state,&(ir->opts),mdatoms,ekind,nrnb,bEkinAveVel,bIterate);
+ }
+
+ debug_gmx();
+
+ /* Calculate center of mass velocity if necessary, also parallellized */
+ if (bStopCM && !bRerunMD && bEner)
+ {
+ calc_vcm_grp(fplog,mdatoms->start,mdatoms->homenr,mdatoms,
+ state->x,state->v,vcm);
+ }
+ }
+
+ if (bTemp || bPres || bEner || bConstrain)
+ {
+ if (!bGStat)
+ {
+ /* We will not sum ekinh_old,
+ * so signal that we still have to do it.
+ */
+ *bSumEkinhOld = TRUE;
+
+ }
+ else
+ {
+ if (gs != NULL)
+ {
+ for(i=0; i<eglsNR; i++)
+ {
+ gs_buf[i] = gs->sig[i];
+ }
+ }
+ if (PAR(cr))
+ {
+ wallcycle_start(wcycle,ewcMoveE);
+ GMX_MPE_LOG(ev_global_stat_start);
+ global_stat(fplog,gstat,cr,enerd,force_vir,shake_vir,mu_tot,
+ ir,ekind,constr,vcm,
+ gs != NULL ? eglsNR : 0,gs_buf,
+ top_global,state,
+ *bSumEkinhOld,flags);
+ GMX_MPE_LOG(ev_global_stat_finish);
+ wallcycle_stop(wcycle,ewcMoveE);
+ }
+ if (gs != NULL)
+ {
+ if (MULTISIM(cr) && bInterSimGS)
+ {
+ if (MASTER(cr))
+ {
+ /* Communicate the signals between the simulations */
+ gmx_sum_sim(eglsNR,gs_buf,cr->ms);
+ }
+ /* Communicate the signals form the master to the others */
+ gmx_bcast(eglsNR*sizeof(gs_buf[0]),gs_buf,cr);
+ }
+ for(i=0; i<eglsNR; i++)
+ {
+ if (bInterSimGS || gs_simlocal[i])
+ {
+ /* Set the communicated signal only when it is non-zero,
+ * since signals might not be processed at each MD step.
+ */
+ gsi = (gs_buf[i] >= 0 ?
+ (int)(gs_buf[i] + 0.5) :
+ (int)(gs_buf[i] - 0.5));
+ if (gsi != 0)
+ {
+ gs->set[i] = gsi;
+ }
+ /* Turn off the local signal */
+ gs->sig[i] = 0;
+ }
+ }
+ }
+ *bSumEkinhOld = FALSE;
+ }
+ }
+
+ if (!bNEMD && debug && bTemp && (vcm->nr > 0))
+ {
+ correct_ekin(debug,
+ mdatoms->start,mdatoms->start+mdatoms->homenr,
+ state->v,vcm->group_p[0],
+ mdatoms->massT,mdatoms->tmass,ekind->ekin);
+ }
+
+ if (bEner) {
+ /* Do center of mass motion removal */
+ if (bStopCM && !bRerunMD) /* is this correct? Does it get called too often with this logic? */
+ {
+ check_cm_grp(fplog,vcm,ir,1);
+ do_stopcm_grp(fplog,mdatoms->start,mdatoms->homenr,mdatoms->cVCM,
+ state->x,state->v,vcm);
+ inc_nrnb(nrnb,eNR_STOPCM,mdatoms->homenr);
+ }
+ }
+
+ if (bTemp)
+ {
+ /* Sum the kinetic energies of the groups & calc temp */
+ /* compute full step kinetic energies if vv, or if vv-avek and we are computing the pressure with IR_NPT_TROTTER */
+ /* three maincase: VV with AveVel (md-vv), vv with AveEkin (md-vv-avek), leap with AveEkin (md).
+ Leap with AveVel is also an option for the future but not supported now.
+ bEkinAveVel: If TRUE, we simply multiply ekin by ekinscale to get a full step kinetic energy.
+ If FALSE, we average ekinh_old and ekinh*ekinscale_nhc to get an averaged half step kinetic energy.
+ bSaveEkinOld: If TRUE (in the case of iteration = bIterate is TRUE), we don't reset the ekinscale_nhc.
+ If FALSE, we go ahead and erase over it.
+ */
+ enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,&(enerd->term[F_DKDL]),
+ bEkinAveVel,bIterate,bScaleEkin);
+
+ enerd->term[F_EKIN] = trace(ekind->ekin);
+ }
+
+ /* ########## Long range energy information ###### */
+
+ if (bEner || bPres || bConstrain)
+ {
+ calc_dispcorr(fplog,ir,fr,0,top_global->natoms,box,state->lambda,
+ corr_pres,corr_vir,&prescorr,&enercorr,&dvdlcorr);
+ }
+
+ if (bEner && bFirstIterate)
+ {
+ enerd->term[F_DISPCORR] = enercorr;
+ enerd->term[F_EPOT] += enercorr;
+ enerd->term[F_DVDL] += dvdlcorr;
+ if (fr->efep != efepNO) {
+ enerd->dvdl_lin += dvdlcorr;
+ }
+ }
+
+ /* ########## Now pressure ############## */
+ if (bPres || bConstrain)
+ {
+
+ m_add(force_vir,shake_vir,total_vir);
+
+ /* Calculate pressure and apply LR correction if PPPM is used.
+ * Use the box from last timestep since we already called update().
+ */
+
+ enerd->term[F_PRES] = calc_pres(fr->ePBC,ir->nwall,box,ekind->ekin,total_vir,pres,
+ (fr->eeltype==eelPPPM)?enerd->term[F_COUL_RECIP]:0.0);
+
+ /* Calculate long range corrections to pressure and energy */
+ /* this adds to enerd->term[F_PRES] and enerd->term[F_ETOT],
+ and computes enerd->term[F_DISPCORR]. Also modifies the
+ total_vir and pres tesors */
+
+ m_add(total_vir,corr_vir,total_vir);
+ m_add(pres,corr_pres,pres);
+ enerd->term[F_PDISPCORR] = prescorr;
+ enerd->term[F_PRES] += prescorr;
+ *pcurr = enerd->term[F_PRES];
+ /* calculate temperature using virial */
+ enerd->term[F_VTEMP] = calc_temp(trace(total_vir),ir->opts.nrdf[0]);
+
+ }
+}
+
+
+/* Definitions for convergence of iterated constraints */
+
+/* iterate constraints up to 50 times */
+#define MAXITERCONST 50
+
+/* data type */
+typedef struct
+{
+ real f,fprev,x,xprev;
+ int iter_i;
+ bool bIterate;
+ real allrelerr[MAXITERCONST+2];
+ int num_close; /* number of "close" violations, caused by limited precision. */
+} gmx_iterate_t;
+
+#ifdef GMX_DOUBLE
+#define CONVERGEITER 0.000000001
+#define CLOSE_ENOUGH 0.000001000
+#else
+#define CONVERGEITER 0.0001
+#define CLOSE_ENOUGH 0.0050
+#endif
+
+/* we want to keep track of the close calls. If there are too many, there might be some other issues.
+ so we make sure that it's either less than some predetermined number, or if more than that number,
+ only some small fraction of the total. */
+#define MAX_NUMBER_CLOSE 50
+#define FRACTION_CLOSE 0.001
+
+/* maximum length of cyclic traps to check, emerging from limited numerical precision */
+#define CYCLEMAX 20
+
+static void gmx_iterate_init(gmx_iterate_t *iterate,bool bIterate)
+{
+ int i;
+
+ iterate->iter_i = 0;
+ iterate->bIterate = bIterate;
+ iterate->num_close = 0;
+ for (i=0;i<MAXITERCONST+2;i++)
+ {
+ iterate->allrelerr[i] = 0;
+ }
+}
+
+static bool done_iterating(const t_commrec *cr,FILE *fplog, int nsteps, gmx_iterate_t *iterate, bool bFirstIterate, real fom, real *newf)
+{
+ /* monitor convergence, and use a secant search to propose new
+ values.
+ x_{i} - x_{i-1}
+ The secant method computes x_{i+1} = x_{i} - f(x_{i}) * ---------------------
+ f(x_{i}) - f(x_{i-1})
+
+ The function we are trying to zero is fom-x, where fom is the
+ "figure of merit" which is the pressure (or the veta value) we
+ would get by putting in an old value of the pressure or veta into
+ the incrementor function for the step or half step. I have
+ verified that this gives the same answer as self consistent
+ iteration, usually in many fewer steps, especially for small tau_p.
+
+ We could possibly eliminate an iteration with proper use
+ of the value from the previous step, but that would take a bit
+ more bookkeeping, especially for veta, since tests indicate the
+ function of veta on the last step is not sufficiently close to
+ guarantee convergence this step. This is
+ good enough for now. On my tests, I could use tau_p down to
+ 0.02, which is smaller that would ever be necessary in
+ practice. Generally, 3-5 iterations will be sufficient */
+
+ real relerr,err;
+ char buf[256];
+ int i;
+ bool incycle;
+
+ if (bFirstIterate)
+ {
+ iterate->x = fom;
+ iterate->f = fom-iterate->x;
+ iterate->xprev = 0;
+ iterate->fprev = 0;
+ *newf = fom;
+ }
+ else
+ {
+ iterate->f = fom-iterate->x; /* we want to zero this difference */
+ if ((iterate->iter_i > 1) && (iterate->iter_i < MAXITERCONST))
+ {
+ if (iterate->f==iterate->fprev)
+ {
+ *newf = iterate->f;
+ }
+ else
+ {
+ *newf = iterate->x - (iterate->x-iterate->xprev)*(iterate->f)/(iterate->f-iterate->fprev);
+ }
+ }
+ else
+ {
+ /* just use self-consistent iteration the first step to initialize, or
+ if it's not converging (which happens occasionally -- need to investigate why) */
+ *newf = fom;
+ }
+ }
+ /* Consider a slight shortcut allowing us to exit one sooner -- we check the
+ difference between the closest of x and xprev to the new
+ value. To be 100% certain, we should check the difference between
+ the last result, and the previous result, or
+
+ relerr = (fabs((x-xprev)/fom));
+
+ but this is pretty much never necessary under typical conditions.
+ Checking numerically, it seems to lead to almost exactly the same
+ trajectories, but there are small differences out a few decimal
+ places in the pressure, and eventually in the v_eta, but it could
+ save an interation.
+
+ if (fabs(*newf-x) < fabs(*newf - xprev)) { xmin = x;} else { xmin = xprev;}
+ relerr = (fabs((*newf-xmin) / *newf));
+ */
+
+ err = fabs((iterate->f-iterate->fprev));
+ relerr = fabs(err/fom);
+
+ iterate->allrelerr[iterate->iter_i] = relerr;
+
+ if (iterate->iter_i > 0)
+ {
+ if (debug)
+ {
+ fprintf(debug,"Iterating NPT constraints: %6i %20.12f%14.6g%20.12f\n",
+ iterate->iter_i,fom,relerr,*newf);
+ }
+
+ if ((relerr < CONVERGEITER) || (err < CONVERGEITER) || (fom==0) || ((iterate->x == iterate->xprev) && iterate->iter_i > 1))
+ {
+ iterate->bIterate = FALSE;
+ if (debug)
+ {
+ fprintf(debug,"Iterating NPT constraints: CONVERGED\n");
+ }
+ return TRUE;
+ }
+ if (iterate->iter_i > MAXITERCONST)
+ {
+ if (relerr < CLOSE_ENOUGH)
+ {
+ incycle = FALSE;
+ for (i=1;i<CYCLEMAX;i++) {
+ if ((iterate->allrelerr[iterate->iter_i-(1+i)] == iterate->allrelerr[iterate->iter_i-1]) &&
+ (iterate->allrelerr[iterate->iter_i-(1+i)] == iterate->allrelerr[iterate->iter_i-(1+2*i)])) {
+ incycle = TRUE;
+ if (debug)
+ {
+ fprintf(debug,"Exiting from an NPT iterating cycle of length %d\n",i);
+ }
+ break;
+ }
+ }
+
+ if (incycle) {
+ /* step 1: trapped in a numerical attractor */
+ /* we are trapped in a numerical attractor, and can't converge any more, and are close to the final result.
+ Better to give up convergence here than have the simulation die.
+ */
+ iterate->num_close++;
+ return TRUE;
+ }
+ else
+ {
+ /* Step #2: test if we are reasonably close for other reasons, then monitor the number. If not, die */
+
+ /* how many close calls have we had? If less than a few, we're OK */
+ if (iterate->num_close < MAX_NUMBER_CLOSE)
+ {
+ sprintf(buf,"Slight numerical convergence deviation with NPT at step %d, relative error only %10.5g, likely not a problem, continuing\n",nsteps,relerr);
+ md_print_warning(cr,fplog,buf);
+ iterate->num_close++;
+ return TRUE;
+ /* if more than a few, check the total fraction. If too high, die. */
+ } else if (iterate->num_close/(double)nsteps > FRACTION_CLOSE) {
+ gmx_fatal(FARGS,"Could not converge NPT constraints, too many exceptions (%d%%\n",iterate->num_close/(double)nsteps);
+ }
+ }
+ }
+ else
+ {
+ gmx_fatal(FARGS,"Could not converge NPT constraints\n");
+ }
+ }
+ }
+
+ iterate->xprev = iterate->x;
+ iterate->x = *newf;
+ iterate->fprev = iterate->f;
+ iterate->iter_i++;
+
+ return FALSE;
+}
+
+static void check_nst_param(FILE *fplog,t_commrec *cr,
+ const char *desc_nst,int nst,
+ const char *desc_p,int *p)
+{
+ char buf[STRLEN];
+
+ if (*p > 0 && *p % nst != 0)
+ {
+ /* Round up to the next multiple of nst */
+ *p = ((*p)/nst + 1)*nst;
+ sprintf(buf,"NOTE: %s changes %s to %d\n",desc_nst,desc_p,*p);
+ md_print_warning(cr,fplog,buf);
+ }
+}
+
+static void reset_all_counters(FILE *fplog,t_commrec *cr,
+ gmx_large_int_t step,
+ gmx_large_int_t *step_rel,t_inputrec *ir,
+ gmx_wallcycle_t wcycle,t_nrnb *nrnb,
+ gmx_runtime_t *runtime)
+{
+ char buf[STRLEN],sbuf[STEPSTRSIZE];
+
+ /* Reset all the counters related to performance over the run */
+ sprintf(buf,"Step %s: resetting all time and cycle counters\n",
+ gmx_step_str(step,sbuf));
+ md_print_warning(cr,fplog,buf);
+
+ wallcycle_stop(wcycle,ewcRUN);
+ wallcycle_reset_all(wcycle);
+ if (DOMAINDECOMP(cr))
+ {
+ reset_dd_statistics_counters(cr->dd);
+ }
+ init_nrnb(nrnb);
+ ir->init_step += *step_rel;
+ ir->nsteps -= *step_rel;
+ *step_rel = 0;
+ wallcycle_start(wcycle,ewcRUN);
+ runtime_start(runtime);
+ print_date_and_time(fplog,cr->nodeid,"Restarted time",runtime);
+}
+
+static int check_nstglobalcomm(FILE *fplog,t_commrec *cr,
+ int nstglobalcomm,t_inputrec *ir)
+{
+ char buf[STRLEN];
+
+ if (!EI_DYNAMICS(ir->eI))
+ {
+ nstglobalcomm = 1;
+ }
+
+ if (nstglobalcomm == -1)
+ {
+ if (ir->nstcalcenergy == 0 && ir->nstlist == 0)
+ {
+ nstglobalcomm = 10;
+ if (ir->nstenergy > 0 && ir->nstenergy < nstglobalcomm)
+ {
+ nstglobalcomm = ir->nstenergy;
+ }
+ }
+ else
+ {
+ /* We assume that if nstcalcenergy > nstlist,
+ * nstcalcenergy is a multiple of nstlist.
+ */
+ if (ir->nstcalcenergy == 0 ||
+ (ir->nstlist > 0 && ir->nstlist < ir->nstcalcenergy))
+ {
+ nstglobalcomm = ir->nstlist;
+ }
+ else
+ {
+ nstglobalcomm = ir->nstcalcenergy;
+ }
+ }
+ }
+ else
+ {
+ if (ir->nstlist > 0 &&
+ nstglobalcomm > ir->nstlist && nstglobalcomm % ir->nstlist != 0)
+ {
+ nstglobalcomm = (nstglobalcomm / ir->nstlist)*ir->nstlist;
+ sprintf(buf,"WARNING: nstglobalcomm is larger than nstlist, but not a multiple, setting it to %d\n",nstglobalcomm);
+ md_print_warning(cr,fplog,buf);
+ }
+ if (nstglobalcomm > ir->nstcalcenergy)
+ {
+ check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+ "nstcalcenergy",&ir->nstcalcenergy);
+ }
+
+ check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+ "nstenergy",&ir->nstenergy);
+
+ check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+ "nstlog",&ir->nstlog);
+ }
+
+ if (ir->comm_mode != ecmNO && ir->nstcomm < nstglobalcomm)
+ {
+ sprintf(buf,"WARNING: Changing nstcomm from %d to %d\n",
+ ir->nstcomm,nstglobalcomm);
+ md_print_warning(cr,fplog,buf);
+ ir->nstcomm = nstglobalcomm;
+ }
+
+ return nstglobalcomm;
+}
+
+void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
+ t_inputrec *ir,gmx_mtop_t *mtop)
+{
+ /* Check required for old tpx files */
+ if (IR_TWINRANGE(*ir) && ir->nstlist > 1 &&
+ ir->nstcalcenergy % ir->nstlist != 0)
+ {
+ md_print_warning(cr,fplog,"Old tpr file with twin-range settings: modifying energy calculation and/or T/P-coupling frequencies");
+
+ if (gmx_mtop_ftype_count(mtop,F_CONSTR) +
+ gmx_mtop_ftype_count(mtop,F_CONSTRNC) > 0 &&
+ ir->eConstrAlg == econtSHAKE)
+ {
+ md_print_warning(cr,fplog,"With twin-range cut-off's and SHAKE the virial and pressure are incorrect");
+ if (ir->epc != epcNO)
+ {
+ gmx_fatal(FARGS,"Can not do pressure coupling with twin-range cut-off's and SHAKE");
+ }
+ }
+ check_nst_param(fplog,cr,"nstlist",ir->nstlist,
+ "nstcalcenergy",&ir->nstcalcenergy);
+ check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+ "nstenergy",&ir->nstenergy);
+ check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+ "nstlog",&ir->nstlog);
+ if (ir->efep != efepNO)
+ {
+ check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+ "nstdhdl",&ir->nstdhdl);
+ }
+ }
+}
+
+typedef struct {
+ bool bGStatEveryStep;
+ gmx_large_int_t step_ns;
+ gmx_large_int_t step_nscheck;
+ gmx_large_int_t nns;
+ matrix scale_tot;
+ int nabnsb;
+ double s1;
+ double s2;
+ double ab;
+ double lt_runav;
+ double lt_runav2;
+} gmx_nlheur_t;
+
+static void reset_nlistheuristics(gmx_nlheur_t *nlh,gmx_large_int_t step)
+{
+ nlh->lt_runav = 0;
+ nlh->lt_runav2 = 0;
+ nlh->step_nscheck = step;
+}
+
+static void init_nlistheuristics(gmx_nlheur_t *nlh,
+ bool bGStatEveryStep,gmx_large_int_t step)
+{
+ nlh->bGStatEveryStep = bGStatEveryStep;
+ nlh->nns = 0;
+ nlh->nabnsb = 0;
+ nlh->s1 = 0;
+ nlh->s2 = 0;
+ nlh->ab = 0;
+
+ reset_nlistheuristics(nlh,step);
+}
+
+static void update_nliststatistics(gmx_nlheur_t *nlh,gmx_large_int_t step)
+{
+ gmx_large_int_t nl_lt;
+ char sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
+
+ /* Determine the neighbor list life time */
+ nl_lt = step - nlh->step_ns;
+ if (debug)
+ {
+ fprintf(debug,"%d atoms beyond ns buffer, updating neighbor list after %s steps\n",nlh->nabnsb,gmx_step_str(nl_lt,sbuf));
+ }
+ nlh->nns++;
+ nlh->s1 += nl_lt;
+ nlh->s2 += nl_lt*nl_lt;
+ nlh->ab += nlh->nabnsb;
+ if (nlh->lt_runav == 0)
+ {
+ nlh->lt_runav = nl_lt;
+ /* Initialize the fluctuation average
+ * such that at startup we check after 0 steps.
+ */
+ nlh->lt_runav2 = sqr(nl_lt/2.0);
+ }
+ /* Running average with 0.9 gives an exp. history of 9.5 */
+ nlh->lt_runav2 = 0.9*nlh->lt_runav2 + 0.1*sqr(nlh->lt_runav - nl_lt);
+ nlh->lt_runav = 0.9*nlh->lt_runav + 0.1*nl_lt;
+ if (nlh->bGStatEveryStep)
+ {
+ /* Always check the nlist validity */
+ nlh->step_nscheck = step;
+ }
+ else
+ {
+ /* We check after: <life time> - 2*sigma
+ * The factor 2 is quite conservative,
+ * but we assume that with nstlist=-1 the user
+ * prefers exact integration over performance.
+ */
+ nlh->step_nscheck = step
+ + (int)(nlh->lt_runav - 2.0*sqrt(nlh->lt_runav2)) - 1;
+ }
+ if (debug)
+ {
+ fprintf(debug,"nlist life time %s run av. %4.1f sig %3.1f check %s check with -gcom %d\n",
+ gmx_step_str(nl_lt,sbuf),nlh->lt_runav,sqrt(nlh->lt_runav2),
+ gmx_step_str(nlh->step_nscheck-step+1,sbuf2),
+ (int)(nlh->lt_runav - 2.0*sqrt(nlh->lt_runav2)));
+ }
+}
+
+static void set_nlistheuristics(gmx_nlheur_t *nlh,bool bReset,gmx_large_int_t step)
+{
+ int d;
+
+ if (bReset)
+ {
+ reset_nlistheuristics(nlh,step);
+ }
+ else
+ {
+ update_nliststatistics(nlh,step);
+ }
+
+ nlh->step_ns = step;
+ /* Initialize the cumulative coordinate scaling matrix */
+ clear_mat(nlh->scale_tot);
+ for(d=0; d<DIM; d++)
+ {
+ nlh->scale_tot[d][d] = 1.0;
+ }
+}
+
+double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
+ const output_env_t oenv, bool bVerbose,bool bCompact,
+ int nstglobalcomm,
+ gmx_vsite_t *vsite,gmx_constr_t constr,
+ int stepout,t_inputrec *ir,
+ gmx_mtop_t *top_global,
+ t_fcdata *fcd,
+ t_state *state_global,
+ t_mdatoms *mdatoms,
+ t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+ gmx_edsam_t ed,t_forcerec *fr,
+ int repl_ex_nst,int repl_ex_seed,
+ real cpt_period,real max_hours,
+ const char *deviceOptions,
+ unsigned long Flags,
+ gmx_runtime_t *runtime,
+ rvec fac, rvec *r_ins, pos_ins_t *pos_ins, t_block *ins_at,
+ real xy_step, real z_step, int it_xy, int it_z)
+{
+ gmx_mdoutf_t *outf;
+ gmx_large_int_t step,step_rel;
+ double run_time;
+ double t,t0,lam0;
+ bool bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres;
+ bool bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
+ bFirstStep,bStateFromTPX,bInitStep,bLastStep,
+ bBornRadii,bStartingFromCpt;
+ bool bDoDHDL=FALSE;
+ bool bNEMD,do_ene,do_log,do_verbose,bRerunWarnNoV=TRUE,
+ bForceUpdate=FALSE,bCPT;
+ int mdof_flags;
+ bool bMasterState;
+ int force_flags,cglo_flags;
+ tensor force_vir,shake_vir,total_vir,tmp_vir,pres;
+ int i,m;
+ t_trxstatus *status;
+ rvec mu_tot;
+ t_vcm *vcm;
+ t_state *bufstate=NULL;
+ matrix *scale_tot,pcoupl_mu,M,ebox;
+ gmx_nlheur_t nlh;
+ t_trxframe rerun_fr;
+/* gmx_repl_ex_t repl_ex=NULL;*/
+ int nchkpt=1;
+
+ gmx_localtop_t *top;
+ t_mdebin *mdebin=NULL;
+ t_state *state=NULL;
+ rvec *f_global=NULL;
+ int n_xtc=-1;
+ rvec *x_xtc=NULL;
+ gmx_enerdata_t *enerd;
+ rvec *f=NULL;
+ gmx_global_stat_t gstat;
+ gmx_update_t upd=NULL;
+ t_graph *graph=NULL;
+ globsig_t gs;
+
+ bool bFFscan;
+ gmx_groups_t *groups;
+ gmx_ekindata_t *ekind, *ekind_save;
+ gmx_shellfc_t shellfc;
+ int count,nconverged=0;
+ real timestep=0;
+ double tcount=0;
+ bool bIonize=FALSE;
+ bool bTCR=FALSE,bConverged=TRUE,bOK,bSumEkinhOld,bExchanged;
+ bool bAppend;
+ bool bResetCountersHalfMaxH=FALSE;
+ bool bVV,bIterations,bIterate,bFirstIterate,bTemp,bPres,bTrotter;
+ real temp0,dvdl;
+ int a0,a1,ii;
+ rvec *xcopy=NULL,*vcopy=NULL,*cbuf=NULL;
+ matrix boxcopy={{0}},lastbox;
+ real veta_save,pcurr,scalevir,tracevir;
+ real vetanew = 0;
+ double cycles;
+ real last_conserved = 0;
+ real last_ekin = 0;
+ t_extmass MassQ;
+ int **trotter_seq;
+ char sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
+ int handled_stop_condition=gmx_stop_cond_none; /* compare to get_stop_condition*/
+ gmx_iterate_t iterate;
+#ifdef GMX_FAHCORE
+ /* Temporary addition for FAHCORE checkpointing */
+ int chkpt_ret;
+#endif
+
+ /* Check for special mdrun options */
+ bRerunMD = (Flags & MD_RERUN);
+ bIonize = (Flags & MD_IONIZE);
+ bFFscan = (Flags & MD_FFSCAN);
+ bAppend = (Flags & MD_APPENDFILES);
+ bGStatEveryStep = FALSE;
+ if (Flags & MD_RESETCOUNTERSHALFWAY)
+ {
+ if (ir->nsteps > 0)
+ {
+ /* Signal to reset the counters half the simulation steps. */
+ wcycle_set_reset_counters(wcycle,ir->nsteps/2);
+ }
+ /* Signal to reset the counters halfway the simulation time. */
+ bResetCountersHalfMaxH = (max_hours > 0);
+ }
+
+ /* md-vv uses averaged full step velocities for T-control
+ md-vv-avek uses averaged half step velocities for T-control (but full step ekin for P control)
+ md uses averaged half step kinetic energies to determine temperature unless defined otherwise by GMX_EKIN_AVE_VEL; */
+ bVV = EI_VV(ir->eI);
+ if (bVV) /* to store the initial velocities while computing virial */
+ {
+ snew(cbuf,top_global->natoms);
+ }
+ /* all the iteratative cases - only if there are constraints */
+ bIterations = ((IR_NPT_TROTTER(ir)) && (constr) && (!bRerunMD));
+ bTrotter = (bVV && (IR_NPT_TROTTER(ir) || (IR_NVT_TROTTER(ir))));
+
+ if (bRerunMD)
+ {
+ /* Since we don't know if the frames read are related in any way,
+ * rebuild the neighborlist at every step.
+ */
+ ir->nstlist = 1;
+ ir->nstcalcenergy = 1;
+ nstglobalcomm = 1;
+ }
+
+ check_ir_old_tpx_versions(cr,fplog,ir,top_global);
+
+ nstglobalcomm = check_nstglobalcomm(fplog,cr,nstglobalcomm,ir);
+ /*bGStatEveryStep = (nstglobalcomm == 1);*/
+ bGStatEveryStep = FALSE;
+
+ if (!bGStatEveryStep && ir->nstlist == -1 && fplog != NULL)
+ {
+ fprintf(fplog,
+ "To reduce the energy communication with nstlist = -1\n"
+ "the neighbor list validity should not be checked at every step,\n"
+ "this means that exact integration is not guaranteed.\n"
+ "The neighbor list validity is checked after:\n"
+ " <n.list life time> - 2*std.dev.(n.list life time) steps.\n"
+ "In most cases this will result in exact integration.\n"
+ "This reduces the energy communication by a factor of 2 to 3.\n"
+ "If you want less energy communication, set nstlist > 3.\n\n");
+ }
+
+ if (bRerunMD || bFFscan)
+ {
+ ir->nstxtcout = 0;
+ }
+ groups = &top_global->groups;
+
+ /* Initial values */
+ init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
+ nrnb,top_global,&upd,
+ nfile,fnm,&outf,&mdebin,
+ force_vir,shake_vir,mu_tot,&bNEMD,&bSimAnn,&vcm,state_global,Flags);
+
+ clear_mat(total_vir);
+ clear_mat(pres);
+ /* Energy terms and groups */
+ snew(enerd,1);
+ init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
+ if (DOMAINDECOMP(cr))
+ {
+ f = NULL;
+ }
+ else
+ {
+ snew(f,top_global->natoms);
+ }
+
+ /* Kinetic energy data */
+ snew(ekind,1);
+ init_ekindata(fplog,top_global,&(ir->opts),ekind);
+ /* needed for iteration of constraints */
+ snew(ekind_save,1);
+ init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
+ /* Copy the cos acceleration to the groups struct */
+ ekind->cosacc.cos_accel = ir->cos_accel;
+
+ gstat = global_stat_init(ir);
+ debug_gmx();
+
+ /* Check for polarizable models and flexible constraints */
+ shellfc = init_shell_flexcon(fplog,
+ top_global,n_flexible_constraints(constr),
+ (ir->bContinuation ||
+ (DOMAINDECOMP(cr) && !MASTER(cr))) ?
+ NULL : state_global->x);
+
+/* if (DEFORM(*ir))
+ {
+#ifdef GMX_THREADS
+ tMPI_Thread_mutex_lock(&deform_init_box_mutex);
+#endif
+ set_deform_reference_box(upd,
+ deform_init_init_step_tpx,
+ deform_init_box_tpx);
+#ifdef GMX_THREADS
+ tMPI_Thread_mutex_unlock(&deform_init_box_mutex);
+#endif
+ }*/
+
+/* {
+ double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1);
+ if ((io > 2000) && MASTER(cr))
+ fprintf(stderr,
+ "\nWARNING: This run will generate roughly %.0f Mb of data\n\n",
+ io);
+ }*/
+
+ if (DOMAINDECOMP(cr)) {
+ top = dd_init_local_top(top_global);
+
+ snew(state,1);
+ dd_init_local_state(cr->dd,state_global,state);
+
+ if (DDMASTER(cr->dd) && ir->nstfout) {
+ snew(f_global,state_global->natoms);
+ }
+ } else {
+ if (PAR(cr)) {
+ /* Initialize the particle decomposition and split the topology */
+ top = split_system(fplog,top_global,ir,cr);
+
+ pd_cg_range(cr,&fr->cg0,&fr->hcg);
+ pd_at_range(cr,&a0,&a1);
+ } else {
+ top = gmx_mtop_generate_local_top(top_global,ir);
+
+ a0 = 0;
+ a1 = top_global->natoms;
+ }
+
+ state = partdec_init_local_state(cr,state_global);
+ f_global = f;
+
+ atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
+
+ if (vsite) {
+ set_vsite_top(vsite,top,mdatoms,cr);
+ }
+
+ if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) {
+ graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
+ }
+
+ if (shellfc) {
+ make_local_shells(cr,mdatoms,shellfc);
+ }
+
+ if (ir->pull && PAR(cr)) {
+ dd_make_local_pull_groups(NULL,ir->pull,mdatoms);
+ }
+ }
+
+ if (DOMAINDECOMP(cr))
+ {
+ /* Distribute the charge groups over the nodes from the master node */
+ dd_partition_system(fplog,ir->init_step,cr,TRUE,1,
+ state_global,top_global,ir,
+ state,&f,mdatoms,top,fr,
+ vsite,shellfc,constr,
+ nrnb,wcycle,FALSE);
+ }
+
+ update_mdatoms(mdatoms,state->lambda);
+
+ if (MASTER(cr))
+ {
+ /* Update mdebin with energy history if appending to output files */
+ if ( Flags & MD_APPENDFILES )
+ {
+ restore_energyhistory_from_state(mdebin,&state_global->enerhist);
+ }
+ /* Set the initial energy history in state to zero by updating once */
+ update_energyhistory(&state_global->enerhist,mdebin);
+ }
+
+ if ((state->flags & (1<<estLD_RNG)) && (Flags & MD_READ_RNG)) {
+ /* Set the random state if we read a checkpoint file */
+ set_stochd_state(upd,state);
+ }
+
+ /* Initialize constraints */
+ if (constr) {
+ if (!DOMAINDECOMP(cr))
+ set_constraints(constr,top,ir,mdatoms,cr);
+ }
+
+ /* Check whether we have to GCT stuff */
+ /* bTCR = ftp2bSet(efGCT,nfile,fnm);
+ if (bTCR) {
+ if (MASTER(cr)) {
+ fprintf(stderr,"Will do General Coupling Theory!\n");
+ }
+ gnx = top_global->mols.nr;
+ snew(grpindex,gnx);
+ for(i=0; (i<gnx); i++) {
+ grpindex[i] = i;
+ }
+ }*/
+
+/* if (repl_ex_nst > 0 && MASTER(cr))
+ repl_ex = init_replica_exchange(fplog,cr->ms,state_global,ir,
+ repl_ex_nst,repl_ex_seed);*/
+
+ if (!ir->bContinuation && !bRerunMD)
+ {
+ if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
+ {
+ /* Set the velocities of frozen particles to zero */
+ for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
+ {
+ for(m=0; m<DIM; m++)
+ {
+ if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
+ {
+ state->v[i][m] = 0;
+ }
+ }
+ }
+ }
+
+ if (constr)
+ {
+ /* Constrain the initial coordinates and velocities */
+ do_constrain_first(fplog,constr,ir,mdatoms,state,f,
+ graph,cr,nrnb,fr,top,shake_vir);
+ }
+ if (vsite)
+ {
+ /* Construct the virtual sites for the initial configuration */
+ construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL,
+ top->idef.iparams,top->idef.il,
+ fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+ }
+ }
+
+ debug_gmx();
+
+ /* I'm assuming we need global communication the first time! MRS */
+ cglo_flags = (CGLO_TEMPERATURE | CGLO_GSTAT
+ | (bVV ? CGLO_PRESSURE:0)
+ | (bVV ? CGLO_CONSTRAINT:0)
+ | (bRerunMD ? CGLO_RERUNMD:0)
+ | ((Flags & MD_READ_EKIN) ? CGLO_READEKIN:0));
+
+ bSumEkinhOld = FALSE;
+ compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+ wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+ constr,NULL,FALSE,state->box,
+ top_global,&pcurr,top_global->natoms,&bSumEkinhOld,cglo_flags);
+ if (ir->eI == eiVVAK) {
+ /* a second call to get the half step temperature initialized as well */
+ /* we do the same call as above, but turn the pressure off -- internally, this
+ is recognized as a velocity verlet half-step kinetic energy calculation.
+ This minimized excess variables, but perhaps loses some logic?*/
+
+ compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+ wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+ constr,NULL,FALSE,state->box,
+ top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+ cglo_flags &~ CGLO_PRESSURE);
+ }
+
+ /* Calculate the initial half step temperature, and save the ekinh_old */
+ if (!(Flags & MD_STARTFROMCPT))
+ {
+ for(i=0; (i<ir->opts.ngtc); i++)
+ {
+ copy_mat(ekind->tcstat[i].ekinh,ekind->tcstat[i].ekinh_old);
+ }
+ }
+ temp0 = enerd->term[F_TEMP];
+
+ /* if using an iterative algorithm, we need to create a working directory for the state. */
+ if (bIterations)
+ {
+ bufstate = init_bufstate(state);
+ }
+ if (bFFscan)
+ {
+ snew(xcopy,state->natoms);
+ snew(vcopy,state->natoms);
+ copy_rvecn(state->x,xcopy,0,state->natoms);
+ copy_rvecn(state->v,vcopy,0,state->natoms);
+ copy_mat(state->box,boxcopy);
+ }
+
+ /* need to make an initiation call to get the Trotter variables set, as well as other constants for non-trotter
+ temperature control */
+ trotter_seq = init_npt_vars(ir,state,&MassQ,bTrotter);
+
+ if (MASTER(cr))
+ {
+ if (constr && !ir->bContinuation && ir->eConstrAlg == econtLINCS)
+ {
+ fprintf(fplog,
+ "RMS relative constraint deviation after constraining: %.2e\n",
+ constr_rmsd(constr,FALSE));
+ }
+ if (bVV)
+ {
+ enerd->term[F_TEMP] *= 2; /* result of averages being done over previous and current step,
+ and there is no previous step */
+ }
+ fprintf(fplog,"Initial temperature: %g K\n",enerd->term[F_TEMP]);
+ if (bRerunMD)
+ {
+ fprintf(stderr,"starting md rerun '%s', reading coordinates from"
+ " input trajectory '%s'\n\n",
+ *(top_global->name),opt2fn("-rerun",nfile,fnm));
+ if (bVerbose)
+ {
+ fprintf(stderr,"Calculated time to finish depends on nsteps from "
+ "run input file,\nwhich may not correspond to the time "
+ "needed to process input trajectory.\n\n");
+ }
+ }
+ else
+ {
+ char tbuf[20];
+ fprintf(stderr,"starting mdrun '%s'\n",
+ *(top_global->name));
+ if (ir->nsteps >= 0)
+ {
+ sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t);
+ }
+ else
+ {
+ sprintf(tbuf,"%s","infinite");
+ }
+ if (ir->init_step > 0)
+ {
+ fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
+ gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf,
+ gmx_step_str(ir->init_step,sbuf2),
+ ir->init_step*ir->delta_t);
+ }
+ else
+ {
+ fprintf(stderr,"%s steps, %s ps.\n",
+ gmx_step_str(ir->nsteps,sbuf),tbuf);
+ }
+ }
+ fprintf(fplog,"\n");
+ }
+
+ /* Set and write start time */
+ runtime_start(runtime);
+ print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
+ wallcycle_start(wcycle,ewcRUN);
+ if (fplog)
+ fprintf(fplog,"\n");
+
+ /* safest point to do file checkpointing is here. More general point would be immediately before integrator call */
+/*#ifdef GMX_FAHCORE
+ chkpt_ret=fcCheckPointParallel( cr->nodeid,
+ NULL,0);
+ if ( chkpt_ret == 0 )
+ gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", 0 );
+#endif*/
+
+ debug_gmx();
+ /***********************************************************
+ *
+ * Loop over MD steps
+ *
+ ************************************************************/
+
+ /* if rerunMD then read coordinates and velocities from input trajectory */
+ if (bRerunMD)
+ {
+ if (getenv("GMX_FORCE_UPDATE"))
+ {
+ bForceUpdate = TRUE;
+ }
+
+ bNotLastFrame = read_first_frame(oenv,&status,
+ opt2fn("-rerun",nfile,fnm),
+ &rerun_fr,TRX_NEED_X | TRX_READ_V);
+ if (rerun_fr.natoms != top_global->natoms)
+ {
+ gmx_fatal(FARGS,
+ "Number of atoms in trajectory (%d) does not match the "
+ "run input file (%d)\n",
+ rerun_fr.natoms,top_global->natoms);
+ }
+ if (ir->ePBC != epbcNONE)
+ {
+ if (!rerun_fr.bBox)
+ {
+ gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
+ }
+ if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
+ {
+ gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
+ }
+
+ /* Set the shift vectors.
+ * Necessary here when have a static box different from the tpr box.
+ */
+ calc_shifts(rerun_fr.box,fr->shift_vec);
+ }
+ }
+
+ /* loop over MD steps or if rerunMD to end of input trajectory */
+ bFirstStep = TRUE;
+ /* Skip the first Nose-Hoover integration when we get the state from tpx */
+ bStateFromTPX = !opt2bSet("-cpi",nfile,fnm);
+ bInitStep = bFirstStep && (bStateFromTPX || bVV);
+ bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
+ bLastStep = FALSE;
+ bSumEkinhOld = FALSE;
+ bExchanged = FALSE;
+
+ init_global_signals(&gs,cr,ir,repl_ex_nst);
+
+ step = ir->init_step;
+ step_rel = 0;
+
+ if (ir->nstlist == -1)
+ {
+ init_nlistheuristics(&nlh,bGStatEveryStep,step);
+ }
+
+ bLastStep = (bRerunMD || (ir->nsteps >= 0 && step_rel > ir->nsteps));
+ while (!bLastStep || (bRerunMD && bNotLastFrame)) {
+
+ wallcycle_start(wcycle,ewcSTEP);
+
+ GMX_MPE_LOG(ev_timestep1);
+
+ if (bRerunMD) {
+ if (rerun_fr.bStep) {
+ step = rerun_fr.step;
+ step_rel = step - ir->init_step;
+ }
+ if (rerun_fr.bTime) {
+ t = rerun_fr.time;
+ }
+ else
+ {
+ t = step;
+ }
+ }
+ else
+ {
+ bLastStep = (step_rel == ir->nsteps);
+ t = t0 + step*ir->delta_t;
+ }
+
+ if (ir->efep != efepNO)
+ {
+ if (bRerunMD && rerun_fr.bLambda && (ir->delta_lambda!=0))
+ {
+ state_global->lambda = rerun_fr.lambda;
+ }
+ else
+ {
+ state_global->lambda = lam0 + step*ir->delta_lambda;
+ }
+ state->lambda = state_global->lambda;
+ bDoDHDL = do_per_step(step,ir->nstdhdl);
+ }
+
+ if (bSimAnn)
+ {
+ update_annealing_target_temp(&(ir->opts),t);
+ }
+
+ if (bRerunMD)
+ {
+ if (!(DOMAINDECOMP(cr) && !MASTER(cr)))
+ {
+ for(i=0; i<state_global->natoms; i++)
+ {
+ copy_rvec(rerun_fr.x[i],state_global->x[i]);
+ }
+ if (rerun_fr.bV)
+ {
+ for(i=0; i<state_global->natoms; i++)
+ {
+ copy_rvec(rerun_fr.v[i],state_global->v[i]);
+ }
+ }
+ else
+ {
+ for(i=0; i<state_global->natoms; i++)
+ {
+ clear_rvec(state_global->v[i]);
+ }
+ if (bRerunWarnNoV)
+ {
+ fprintf(stderr,"\nWARNING: Some frames do not contain velocities.\n"
+ " Ekin, temperature and pressure are incorrect,\n"
+ " the virial will be incorrect when constraints are present.\n"
+ "\n");
+ bRerunWarnNoV = FALSE;
+ }
+ }
+ }
+ copy_mat(rerun_fr.box,state_global->box);
+ copy_mat(state_global->box,state->box);
+
+ if (vsite && (Flags & MD_RERUN_VSITE))
+ {
+ if (DOMAINDECOMP(cr))
+ {
+ gmx_fatal(FARGS,"Vsite recalculation with -rerun is not implemented for domain decomposition, use particle decomposition");
+ }
+ if (graph)
+ {
+ /* Following is necessary because the graph may get out of sync
+ * with the coordinates if we only have every N'th coordinate set
+ */
+ mk_mshift(fplog,graph,fr->ePBC,state->box,state->x);
+ shift_self(graph,state->box,state->x);
+ }
+ construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
+ top->idef.iparams,top->idef.il,
+ fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+ if (graph)
+ {
+ unshift_self(graph,state->box,state->x);
+ }
+ }
+ }
+
+ /* Stop Center of Mass motion */
+ bStopCM = (ir->comm_mode != ecmNO && do_per_step(step,ir->nstcomm));
+
+ /* Copy back starting coordinates in case we're doing a forcefield scan */
+ if (bFFscan)
+ {
+ for(ii=0; (ii<state->natoms); ii++)
+ {
+ copy_rvec(xcopy[ii],state->x[ii]);
+ copy_rvec(vcopy[ii],state->v[ii]);
+ }
+ copy_mat(boxcopy,state->box);
+ }
+
+ if (bRerunMD)
+ {
+ /* for rerun MD always do Neighbour Searching */
+ bNS = (bFirstStep || ir->nstlist != 0);
+ bNStList = bNS;
+ }
+ else
+ {
+ /* Determine whether or not to do Neighbour Searching and LR */
+ bNStList = (ir->nstlist > 0 && step % ir->nstlist == 0);
+
+ bNS = (bFirstStep || bExchanged || bNStList ||
+ (ir->nstlist == -1 && nlh.nabnsb > 0));
+
+ if (bNS && ir->nstlist == -1)
+ {
+ set_nlistheuristics(&nlh,bFirstStep || bExchanged,step);
+ }
+ }
+
+ /* < 0 means stop at next step, > 0 means stop at next NS step */
+ if ( (gs.set[eglsSTOPCOND] < 0 ) ||
+ ( (gs.set[eglsSTOPCOND] > 0 ) && ( bNS || ir->nstlist==0)) )
+ {
+ bLastStep = TRUE;
+ }
+
+ /* Determine whether or not to update the Born radii if doing GB */
+ bBornRadii=bFirstStep;
+ if (ir->implicit_solvent && (step % ir->nstgbradii==0))
+ {
+ bBornRadii=TRUE;
+ }
+
+ do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
+ do_verbose = bVerbose &&
+ (step % stepout == 0 || bFirstStep || bLastStep);
+
+ if (bNS && !(bFirstStep && ir->bContinuation && !bRerunMD))
+ {
+ if (bRerunMD)
+ {
+ bMasterState = TRUE;
+ }
+ else
+ {
+ bMasterState = FALSE;
+ /* Correct the new box if it is too skewed */
+ if (DYNAMIC_BOX(*ir))
+ {
+ if (correct_box(fplog,step,state->box,graph))
+ {
+ bMasterState = TRUE;
+ }
+ }
+ if (DOMAINDECOMP(cr) && bMasterState)
+ {
+ dd_collect_state(cr->dd,state,state_global);
+ }
+ }
+
+ if (DOMAINDECOMP(cr))
+ {
+ /* Repartition the domain decomposition */
+ wallcycle_start(wcycle,ewcDOMDEC);
+ dd_partition_system(fplog,step,cr,
+ bMasterState,nstglobalcomm,
+ state_global,top_global,ir,
+ state,&f,mdatoms,top,fr,
+ vsite,shellfc,constr,
+ nrnb,wcycle,do_verbose);
+ wallcycle_stop(wcycle,ewcDOMDEC);
+ /* If using an iterative integrator, reallocate space to match the decomposition */
+ }
+ }
+
+ if (MASTER(cr) && do_log && !bFFscan)
+ {
+ print_ebin_header(fplog,step,t,state->lambda);
+ }
+
+ if (ir->efep != efepNO)
+ {
+ update_mdatoms(mdatoms,state->lambda);
+ }
+
+ if (bRerunMD && rerun_fr.bV)
+ {
+
+ /* We need the kinetic energy at minus the half step for determining
+ * the full step kinetic energy and possibly for T-coupling.*/
+ /* This may not be quite working correctly yet . . . . */
+ compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+ wcycle,enerd,NULL,NULL,NULL,NULL,mu_tot,
+ constr,NULL,FALSE,state->box,
+ top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+ CGLO_RERUNMD | CGLO_GSTAT | CGLO_TEMPERATURE);
+ }
+ clear_mat(force_vir);
+
+ /* Ionize the atoms if necessary */
+/* if (bIonize)
+ {
+ ionize(fplog,oenv,mdatoms,top_global,t,ir,state->x,state->v,
+ mdatoms->start,mdatoms->start+mdatoms->homenr,state->box,cr);
+ }*/
+
+ /* Update force field in ffscan program */
+/* if (bFFscan)
+ {
+ if (update_forcefield(fplog,
+ nfile,fnm,fr,
+ mdatoms->nr,state->x,state->box)) {
+ if (gmx_parallel_env_initialized())
+ {
+ gmx_finalize();
+ }
+ exit(0);
+ }
+ }*/
+
+ GMX_MPE_LOG(ev_timestep2);
+
+ /* We write a checkpoint at this MD step when:
+ * either at an NS step when we signalled through gs,
+ * or at the last step (but not when we do not want confout),
+ * but never at the first step or with rerun.
+ */
+/* bCPT = (((gs.set[eglsCHKPT] && bNS) ||
+ (bLastStep && (Flags & MD_CONFOUT))) &&
+ step > ir->init_step && !bRerunMD);
+ if (bCPT)
+ {
+ gs.set[eglsCHKPT] = 0;
+ }*/
+
+ /* Determine the energy and pressure:
+ * at nstcalcenergy steps and at energy output steps (set below).
+ */
+ bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
+ bCalcEnerPres = bNstEner;
+
+ /* Do we need global communication ? */
+ bGStat = (bCalcEnerPres || bStopCM ||
+ (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
+
+ do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+ if (do_ene || do_log)
+ {
+ bCalcEnerPres = TRUE;
+ bGStat = TRUE;
+ }
+
+ /* these CGLO_ options remain the same throughout the iteration */
+ cglo_flags = ((bRerunMD ? CGLO_RERUNMD : 0) |
+ (bStopCM ? CGLO_STOPCM : 0) |
+ (bGStat ? CGLO_GSTAT : 0) |
+ (bNEMD ? CGLO_NEMD : 0)
+ );
+
+ force_flags = (GMX_FORCE_STATECHANGED |
+ ((DYNAMIC_BOX(*ir) || bRerunMD) ? GMX_FORCE_DYNAMICBOX : 0) |
+ GMX_FORCE_ALLFORCES |
+ (bNStList ? GMX_FORCE_DOLR : 0) |
+ GMX_FORCE_SEPLRF |
+ (bCalcEnerPres ? GMX_FORCE_VIRIAL : 0) |
+ (bDoDHDL ? GMX_FORCE_DHDL : 0)
+ );
+
+ if (shellfc)
+ {
+ /* Now is the time to relax the shells */
+ count=relax_shell_flexcon(fplog,cr,bVerbose,bFFscan ? step+1 : step,
+ ir,bNS,force_flags,
+ bStopCM,top,top_global,
+ constr,enerd,fcd,
+ state,f,force_vir,mdatoms,
+ nrnb,wcycle,graph,groups,
+ shellfc,fr,bBornRadii,t,mu_tot,
+ state->natoms,&bConverged,vsite,
+ outf->fp_field);
+ tcount+=count;
+
+ if (bConverged)
+ {
+ nconverged++;
+ }
+ }
+ else
+ {
+ /* The coordinates (x) are shifted (to get whole molecules)
+ * in do_force.
+ * This is parallellized as well, and does communication too.
+ * Check comments in sim_util.c
+ */
+
+ do_force(fplog,cr,ir,step,nrnb,wcycle,top,top_global,groups,
+ state->box,state->x,&state->hist,
+ f,force_vir,mdatoms,enerd,fcd,
+ state->lambda,graph,
+ fr,vsite,mu_tot,t,outf->fp_field,ed,bBornRadii,
+ (bNS ? GMX_FORCE_NS : 0) | force_flags);
+ }
+
+ GMX_BARRIER(cr->mpi_comm_mygroup);
+
+ /* if (bTCR)
+ {
+ mu_aver = calc_mu_aver(cr,state->x,mdatoms->chargeA,
+ mu_tot,&top_global->mols,mdatoms,gnx,grpindex);
+ }
+
+ if (bTCR && bFirstStep)
+ {
+ tcr=init_coupling(fplog,nfile,fnm,cr,fr,mdatoms,&(top->idef));
+ fprintf(fplog,"Done init_coupling\n");
+ fflush(fplog);
+ }*/
+
+ /* ############### START FIRST UPDATE HALF-STEP ############### */
+
+ if (!bStartingFromCpt && !bRerunMD)
+ {
+ if (ir->eI == eiVV)
+ {
+ if (bInitStep)
+ {
+ /* if using velocity verlet with full time step Ekin,
+ * take the first half step only to compute the
+ * virial for the first step. From there,
+ * revert back to the initial coordinates
+ * so that the input is actually the initial step.
+ */
+ copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
+ }
+
+ /* this is for NHC in the Ekin(t+dt/2) version of vv */
+ if (!bInitStep)
+ {
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[1]);
+ }
+
+ update_coords(fplog,step,ir,mdatoms,state,
+ f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+ ekind,M,wcycle,upd,bInitStep,etrtVELOCITY,
+ cr,nrnb,constr,&top->idef);
+
+ if (bIterations)
+ {
+ gmx_iterate_init(&iterate,bIterations && !bInitStep);
+ }
+ /* for iterations, we save these vectors, as we will be self-consistently iterating
+ the calculations */
+ /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
+
+ /* save the state */
+ if (bIterations && iterate.bIterate) {
+ copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
+ }
+ }
+
+ bFirstIterate = TRUE;
+ while (bFirstIterate || (bIterations && iterate.bIterate))
+ {
+ if (bIterations && iterate.bIterate)
+ {
+ copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
+ if (bFirstIterate && bTrotter)
+ {
+ /* The first time through, we need a decent first estimate
+ of veta(t+dt) to compute the constraints. Do
+ this by computing the box volume part of the
+ trotter integration at this time. Nothing else
+ should be changed by this routine here. If
+ !(first time), we start with the previous value
+ of veta. */
+
+ veta_save = state->veta;
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[0]);
+ vetanew = state->veta;
+ state->veta = veta_save;
+ }
+ }
+
+ bOK = TRUE;
+ if ( !bRerunMD || rerun_fr.bV || bForceUpdate) { /* Why is rerun_fr.bV here? Unclear. */
+ dvdl = 0;
+
+ update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+ &top->idef,shake_vir,NULL,
+ cr,nrnb,wcycle,upd,constr,
+ bInitStep,TRUE,bCalcEnerPres,vetanew);
+
+ if (!bOK && !bFFscan)
+ {
+ gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
+ }
+
+ }
+ else if (graph)
+ { /* Need to unshift here if a do_force has been
+ called in the previous step */
+ unshift_self(graph,state->box,state->x);
+ }
+
+
+ if (bVV) {
+ /* if VV, compute the pressure and constraints */
+ /* if VV2, the pressure and constraints only if using pressure control.*/
+ bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir));
+ bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));
+ compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+ wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+ constr,NULL,FALSE,state->box,
+ top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+ cglo_flags
+ | CGLO_ENERGY
+ | (bTemp ? CGLO_TEMPERATURE:0)
+ | (bPres ? CGLO_PRESSURE : 0)
+ | (bPres ? CGLO_CONSTRAINT : 0)
+ | (iterate.bIterate ? CGLO_ITERATE : 0)
+ | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
+ | CGLO_SCALEEKIN
+ );
+ }
+ /* explanation of above:
+ a) We compute Ekin at the full time step
+ if 1) we are using the AveVel Ekin, and it's not the
+ initial step, or 2) if we are using AveEkin, but need the full
+ time step kinetic energy for the pressure.
+ b) If we are using EkinAveEkin for the kinetic energy for the temperture control, we still feed in
+ EkinAveVel because it's needed for the pressure */
+
+ /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
+ if (bVV && !bInitStep)
+ {
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[2]);
+ }
+
+ if (bIterations &&
+ done_iterating(cr,fplog,step,&iterate,bFirstIterate,
+ state->veta,&vetanew))
+ {
+ break;
+ }
+ bFirstIterate = FALSE;
+ }
+
+ if (bTrotter && !bInitStep) {
+ copy_mat(shake_vir,state->svir_prev);
+ copy_mat(force_vir,state->fvir_prev);
+ if (IR_NVT_TROTTER(ir) && ir->eI==eiVV) {
+ /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
+ enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,NULL,(ir->eI==eiVV),FALSE,FALSE);
+ enerd->term[F_EKIN] = trace(ekind->ekin);
+ }
+ }
+ /* if it's the initial step, we performed this first step just to get the constraint virial */
+ if (bInitStep && ir->eI==eiVV) {
+ copy_rvecn(cbuf,state->v,0,state->natoms);
+ }
+
+ if (fr->bSepDVDL && fplog && do_log)
+ {
+ fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
+ }
+ enerd->term[F_DHDL_CON] += dvdl;
+
+ GMX_MPE_LOG(ev_timestep1);
+
+ }
+
+ /* MRS -- now done iterating -- compute the conserved quantity */
+ if (bVV) {
+ last_conserved = 0;
+ if (IR_NVT_TROTTER(ir) || IR_NPT_TROTTER(ir))
+ {
+ last_conserved =
+ NPT_energy(ir,state,&MassQ);
+ if ((ir->eDispCorr != edispcEnerPres) && (ir->eDispCorr != edispcAllEnerPres))
+ {
+ last_conserved -= enerd->term[F_DISPCORR];
+ }
+ }
+ if (ir->eI==eiVV) {
+ last_ekin = enerd->term[F_EKIN]; /* does this get preserved through checkpointing? */
+ }
+ }
+
+ /* ######## END FIRST UPDATE STEP ############## */
+ /* ######## If doing VV, we now have v(dt) ###### */
+
+ /* ################## START TRAJECTORY OUTPUT ################# */
+
+ /* Now we have the energies and forces corresponding to the
+ * coordinates at time t. We must output all of this before
+ * the update.
+ * for RerunMD t is read from input trajectory
+ */
+ GMX_MPE_LOG(ev_output_start);
+
+ mdof_flags = 0;
+ if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; }
+ if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; }
+ if (do_per_step(step,ir->nstfout)) { mdof_flags |= MDOF_F; }
+ if (do_per_step(step,ir->nstxtcout)) { mdof_flags |= MDOF_XTC; }
+/* if (bCPT) { mdof_flags |= MDOF_CPT; };*/
+
+#ifdef GMX_FAHCORE
+ if (MASTER(cr))
+ fcReportProgress( ir->nsteps, step );
+
+ if (bLastStep)
+ {
+ /* Enforce writing positions and velocities at end of run */
+ mdof_flags |= (MDOF_X | MDOF_V);
+ }
+ {
+ int nthreads=(cr->nthreads==0 ? 1 : cr->nthreads);
+ int nnodes=(cr->nnodes==0 ? 1 : cr->nnodes);
+
+ /*Gromacs drives checkpointing; no ||
+ fcCheckPointPendingThreads(cr->nodeid,
+ nthreads*nnodes);*/
+ /* sync bCPT and fc record-keeping */
+/* if (bCPT && MASTER(cr))
+ fcRequestCheckPoint();*/
+ }
+#endif
+
+ if (mdof_flags != 0)
+ {
+ wallcycle_start(wcycle,ewcTRAJ);
+/* if (bCPT)
+ {
+ if (state->flags & (1<<estLD_RNG))
+ {
+ get_stochd_state(upd,state);
+ }
+ if (MASTER(cr))
+ {
+ if (bSumEkinhOld)
+ {
+ state_global->ekinstate.bUpToDate = FALSE;
+ }
+ else
+ {
+ update_ekinstate(&state_global->ekinstate,ekind);
+ state_global->ekinstate.bUpToDate = TRUE;
+ }
+ update_energyhistory(&state_global->enerhist,mdebin);
+ }
+ }*/
+ write_traj(fplog,cr,outf,mdof_flags,top_global,
+ step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
+/* if (bCPT)
+ {
+ nchkpt++;
+ bCPT = FALSE;
+ }*/
+ debug_gmx();
+ if (bLastStep && step_rel == ir->nsteps &&
+ (Flags & MD_CONFOUT) && MASTER(cr) &&
+ !bRerunMD && !bFFscan)
+ {
+ /* x and v have been collected in write_traj,
+ * because a checkpoint file will always be written
+ * at the last step.
+ */
+ fprintf(stderr,"\nWriting final coordinates.\n");
+ if (ir->ePBC != epbcNONE && !ir->bPeriodicMols &&
+ DOMAINDECOMP(cr))
+ {
+ /* Make molecules whole only for confout writing */
+ do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x);
+ }
+/* write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
+ *top_global->name,top_global,
+ state_global->x,state_global->v,
+ ir->ePBC,state->box);*/
+ debug_gmx();
+ }
+ wallcycle_stop(wcycle,ewcTRAJ);
+ }
+ GMX_MPE_LOG(ev_output_finish);
+
+ /* kludge -- virial is lost with restart for NPT control. Must restart */
+ if (bStartingFromCpt && bVV)
+ {
+ copy_mat(state->svir_prev,shake_vir);
+ copy_mat(state->fvir_prev,force_vir);
+ }
+ /* ################## END TRAJECTORY OUTPUT ################ */
+
+ /* Determine the pressure:
+ * always when we want exact averages in the energy file,
+ * at ns steps when we have pressure coupling,
+ * otherwise only at energy output steps (set below).
+ */
+
+ bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
+ bCalcEnerPres = bNstEner;
+
+ /* Do we need global communication ? */
+ bGStat = (bGStatEveryStep || bStopCM || bNS ||
+ (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
+
+ do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+ if (do_ene || do_log)
+ {
+ bCalcEnerPres = TRUE;
+ bGStat = TRUE;
+ }
+
+ /* Determine the wallclock run time up till now */
+ run_time = gmx_gettime() - (double)runtime->real;
+
+ /* Check whether everything is still allright */
+ if (((int)gmx_get_stop_condition() > handled_stop_condition) &&
+ MASTERTHREAD(cr))
+ {
+ /* this is just make gs.sig compatible with the hack
+ of sending signals around by MPI_Reduce with together with
+ other floats */
+ if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
+ gs.sig[eglsSTOPCOND]=1;
+ if ( gmx_get_stop_condition() == gmx_stop_cond_next )
+ gs.sig[eglsSTOPCOND]=-1;
+ /* < 0 means stop at next step, > 0 means stop at next NS step */
+ if (fplog)
+ {
+ fprintf(fplog,
+ "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
+ gmx_get_signal_name(),
+ gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
+ fflush(fplog);
+ }
+ fprintf(stderr,
+ "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
+ gmx_get_signal_name(),
+ gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
+ fflush(stderr);
+ handled_stop_condition=(int)gmx_get_stop_condition();
+ }
+ else if (MASTER(cr) && (bNS || ir->nstlist <= 0) &&
+ (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
+ gs.sig[eglsSTOPCOND] == 0 && gs.set[eglsSTOPCOND] == 0)
+ {
+ /* Signal to terminate the run */
+ gs.sig[eglsSTOPCOND] = 1;
+ if (fplog)
+ {
+ fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
+ }
+ fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
+ }
+
+ if (bResetCountersHalfMaxH && MASTER(cr) &&
+ run_time > max_hours*60.0*60.0*0.495)
+ {
+ gs.sig[eglsRESETCOUNTERS] = 1;
+ }
+
+ if (ir->nstlist == -1 && !bRerunMD)
+ {
+ /* When bGStatEveryStep=FALSE, global_stat is only called
+ * when we check the atom displacements, not at NS steps.
+ * This means that also the bonded interaction count check is not
+ * performed immediately after NS. Therefore a few MD steps could
+ * be performed with missing interactions.
+ * But wrong energies are never written to file,
+ * since energies are only written after global_stat
+ * has been called.
+ */
+ if (step >= nlh.step_nscheck)
+ {
+ nlh.nabnsb = natoms_beyond_ns_buffer(ir,fr,&top->cgs,
+ nlh.scale_tot,state->x);
+ }
+ else
+ {
+ /* This is not necessarily true,
+ * but step_nscheck is determined quite conservatively.
+ */
+ nlh.nabnsb = 0;
+ }
+ }
+
+ /* In parallel we only have to check for checkpointing in steps
+ * where we do global communication,
+ * otherwise the other nodes don't know.
+ */
+ if (MASTER(cr) && ((bGStat || !PAR(cr)) &&
+ cpt_period >= 0 &&
+ (cpt_period == 0 ||
+ run_time >= nchkpt*cpt_period*60.0)) &&
+ gs.set[eglsCHKPT] == 0)
+ {
+ gs.sig[eglsCHKPT] = 1;
+ }
+
+ if (bIterations)
+ {
+ gmx_iterate_init(&iterate,bIterations);
+ }
+
+ /* for iterations, we save these vectors, as we will be redoing the calculations */
+ if (bIterations && iterate.bIterate)
+ {
+ copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
+ }
+ bFirstIterate = TRUE;
+ while (bFirstIterate || (bIterations && iterate.bIterate))
+ {
+ /* We now restore these vectors to redo the calculation with improved extended variables */
+ if (bIterations)
+ {
+ copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
+ }
+
+ /* We make the decision to break or not -after- the calculation of Ekin and Pressure,
+ so scroll down for that logic */
+
+ /* ######### START SECOND UPDATE STEP ################# */
+ GMX_MPE_LOG(ev_update_start);
+ bOK = TRUE;
+ if (!bRerunMD || rerun_fr.bV || bForceUpdate)
+ {
+ wallcycle_start(wcycle,ewcUPDATE);
+ dvdl = 0;
+ /* Box is changed in update() when we do pressure coupling,
+ * but we should still use the old box for energy corrections and when
+ * writing it to the energy file, so it matches the trajectory files for
+ * the same timestep above. Make a copy in a separate array.
+ */
+ copy_mat(state->box,lastbox);
+ /* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
+ if (bTrotter)
+ {
+ if (bIterations && iterate.bIterate)
+ {
+ if (bFirstIterate)
+ {
+ scalevir = 1;
+ }
+ else
+ {
+ /* we use a new value of scalevir to converge the iterations faster */
+ scalevir = tracevir/trace(shake_vir);
+ }
+ msmul(shake_vir,scalevir,shake_vir);
+ m_add(force_vir,shake_vir,total_vir);
+ clear_mat(shake_vir);
+ }
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[3]);
+ }
+ /* We can only do Berendsen coupling after we have summed
+ * the kinetic energy or virial. Since the happens
+ * in global_state after update, we should only do it at
+ * step % nstlist = 1 with bGStatEveryStep=FALSE.
+ */
+
+ update_extended(fplog,step,ir,mdatoms,state,ekind,pcoupl_mu,M,wcycle,
+ upd,bInitStep,FALSE,&MassQ);
+
+ /* velocity (for VV) */
+ update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+ ekind,M,wcycle,upd,FALSE,etrtVELOCITY,cr,nrnb,constr,&top->idef);
+
+ /* Above, initialize just copies ekinh into ekin,
+ * it doesn't copy position (for VV),
+ * and entire integrator for MD.
+ */
+
+ if (ir->eI==eiVVAK)
+ {
+ copy_rvecn(state->x,cbuf,0,state->natoms);
+ }
+
+ update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+ ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
+ wallcycle_stop(wcycle,ewcUPDATE);
+
+ update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+ &top->idef,shake_vir,force_vir,
+ cr,nrnb,wcycle,upd,constr,
+ bInitStep,FALSE,bCalcEnerPres,state->veta);
+
+ if (ir->eI==eiVVAK)
+ {
+ /* erase F_EKIN and F_TEMP here? */
+ /* just compute the kinetic energy at the half step to perform a trotter step */
+ compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+ wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+ constr,NULL,FALSE,lastbox,
+ top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+ cglo_flags | CGLO_TEMPERATURE | CGLO_CONSTRAINT
+ );
+ wallcycle_start(wcycle,ewcUPDATE);
+ trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[4]);
+ /* now we know the scaling, we can compute the positions again again */
+ copy_rvecn(cbuf,state->x,0,state->natoms);
+
+ update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+ ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
+ wallcycle_stop(wcycle,ewcUPDATE);
+
+ /* do we need an extra constraint here? just need to copy out of state->v to upd->xp? */
+ /* are the small terms in the shake_vir here due
+ * to numerical errors, or are they important
+ * physically? I'm thinking they are just errors, but not completely sure.
+ * For now, will call without actually constraining, constr=NULL*/
+ update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+ &top->idef,tmp_vir,force_vir,
+ cr,nrnb,wcycle,upd,NULL,
+ bInitStep,FALSE,bCalcEnerPres,state->veta);
+ }
+ if (!bOK && !bFFscan)
+ {
+ gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
+ }
+
+ if (fr->bSepDVDL && fplog && do_log)
+ {
+ fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
+ }
+ enerd->term[F_DHDL_CON] += dvdl;
+ }
+ else if (graph)
+ {
+ /* Need to unshift here */
+ unshift_self(graph,state->box,state->x);
+ }
+
+ GMX_BARRIER(cr->mpi_comm_mygroup);
+ GMX_MPE_LOG(ev_update_finish);
+
+ if (vsite != NULL)
+ {
+ wallcycle_start(wcycle,ewcVSITECONSTR);
+ if (graph != NULL)
+ {
+ shift_self(graph,state->box,state->x);
+ }
+ construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
+ top->idef.iparams,top->idef.il,
+ fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+
+ if (graph != NULL)
+ {
+ unshift_self(graph,state->box,state->x);
+ }
+ wallcycle_stop(wcycle,ewcVSITECONSTR);
+ }
+
+ /* ############## IF NOT VV, Calculate globals HERE, also iterate constraints ############ */
+ if (ir->nstlist == -1 && bFirstIterate)
+ {
+ gs.sig[eglsNABNSB] = nlh.nabnsb;
+ }
+ compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+ wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+ constr,
+ bFirstIterate ? &gs : NULL,(step % gs.nstms == 0),
+ lastbox,
+ top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+ cglo_flags
+ | (!EI_VV(ir->eI) ? CGLO_ENERGY : 0)
+ | (!EI_VV(ir->eI) ? CGLO_TEMPERATURE : 0)
+ | (!EI_VV(ir->eI) || bRerunMD ? CGLO_PRESSURE : 0)
+ | (bIterations && iterate.bIterate ? CGLO_ITERATE : 0)
+ | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
+ | CGLO_CONSTRAINT
+ );
+ if (ir->nstlist == -1 && bFirstIterate)
+ {
+ nlh.nabnsb = gs.set[eglsNABNSB];
+ gs.set[eglsNABNSB] = 0;
+ }
+ /* bIterate is set to keep it from eliminating the old ekin kinetic energy terms */
+ /* ############# END CALC EKIN AND PRESSURE ################# */
+
+ /* Note: this is OK, but there are some numerical precision issues with using the convergence of
+ the virial that should probably be addressed eventually. state->veta has better properies,
+ but what we actually need entering the new cycle is the new shake_vir value. Ideally, we could
+ generate the new shake_vir, but test the veta value for convergence. This will take some thought. */
+
+ if (bIterations &&
+ done_iterating(cr,fplog,step,&iterate,bFirstIterate,
+ trace(shake_vir),&tracevir))
+ {
+ break;
+ }
+ bFirstIterate = FALSE;
+ }
+
+ update_box(fplog,step,ir,mdatoms,state,graph,f,
+ ir->nstlist==-1 ? &nlh.scale_tot : NULL,pcoupl_mu,nrnb,wcycle,upd,bInitStep,FALSE);
+
+ /* ################# END UPDATE STEP 2 ################# */
+ /* #### We now have r(t+dt) and v(t+dt/2) ############# */
+
+ /* The coordinates (x) were unshifted in update */
+/* if (bFFscan && (shellfc==NULL || bConverged))
+ {
+ if (print_forcefield(fplog,enerd->term,mdatoms->homenr,
+ f,NULL,xcopy,
+ &(top_global->mols),mdatoms->massT,pres))
+ {
+ if (gmx_parallel_env_initialized())
+ {
+ gmx_finalize();
+ }
+ fprintf(stderr,"\n");
+ exit(0);
+ }
+ }*/
+ if (!bGStat)
+ {
+ /* We will not sum ekinh_old,
+ * so signal that we still have to do it.
+ */
+ bSumEkinhOld = TRUE;
+ }
+
+/* if (bTCR)
+ {*/
+ /* Only do GCT when the relaxation of shells (minimization) has converged,
+ * otherwise we might be coupling to bogus energies.
+ * In parallel we must always do this, because the other sims might
+ * update the FF.
+ */
+
+ /* Since this is called with the new coordinates state->x, I assume
+ * we want the new box state->box too. / EL 20040121
+ */
+/* do_coupling(fplog,oenv,nfile,fnm,tcr,t,step,enerd->term,fr,
+ ir,MASTER(cr),
+ mdatoms,&(top->idef),mu_aver,
+ top_global->mols.nr,cr,
+ state->box,total_vir,pres,
+ mu_tot,state->x,f,bConverged);
+ debug_gmx();
+ }*/
+
+ /* ######### BEGIN PREPARING EDR OUTPUT ########### */
+
+ sum_dhdl(enerd,state->lambda,ir);
+ /* use the directly determined last velocity, not actually the averaged half steps */
+ if (bTrotter && ir->eI==eiVV)
+ {
+ enerd->term[F_EKIN] = last_ekin;
+ }
+ enerd->term[F_ETOT] = enerd->term[F_EPOT] + enerd->term[F_EKIN];
+
+ switch (ir->etc)
+ {
+ case etcNO:
+ break;
+ case etcBERENDSEN:
+ break;
+ case etcNOSEHOOVER:
+ if (IR_NVT_TROTTER(ir)) {
+ enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + last_conserved;
+ } else {
+ enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] +
+ NPT_energy(ir,state,&MassQ);
+ }
+ break;
+ case etcVRESCALE:
+ enerd->term[F_ECONSERVED] =
+ enerd->term[F_ETOT] + vrescale_energy(&(ir->opts),
+ state->therm_integral);
+ break;
+ default:
+ break;
+ }
+
+ /* Check for excessively large energies */
+/* if (bIonize)
+ {
+#ifdef GMX_DOUBLE
+ real etot_max = 1e200;
+#else
+ real etot_max = 1e30;
+#endif
+ if (fabs(enerd->term[F_ETOT]) > etot_max)
+ {
+ fprintf(stderr,"Energy too large (%g), giving up\n",
+ enerd->term[F_ETOT]);
+ }
+ }*/
+ /* ######### END PREPARING EDR OUTPUT ########### */
+
+ /* Time for performance */
+ if (((step % stepout) == 0) || bLastStep)
+ {
+ runtime_upd_proc(runtime);
+ }
+
+ /* Output stuff */
+ if (MASTER(cr))
+ {
+ bool do_dr,do_or;
+
+ if (!(bStartingFromCpt && (EI_VV(ir->eI))))
+ {
+ if (bNstEner)
+ {
+ upd_mdebin(mdebin,bDoDHDL ? outf->fp_dhdl : NULL,TRUE,
+ t,mdatoms->tmass,enerd,state,lastbox,
+ shake_vir,force_vir,total_vir,pres,
+ ekind,mu_tot,constr);
+ }
+ else
+ {
+ upd_mdebin_step(mdebin);
+ }
+
+ do_dr = do_per_step(step,ir->nstdisreout);
+ do_or = do_per_step(step,ir->nstorireout);
+
+ print_ebin(outf->fp_ene,do_ene,do_dr,do_or,do_log?fplog:NULL,
+ step,t,
+ eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
+ }
+ if (ir->ePull != epullNO)
+ {
+ pull_print_output(ir->pull,step,t);
+ }
+
+ if (do_per_step(step,ir->nstlog))
+ {
+ if(fflush(fplog) != 0)
+ {
+ gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
+ }
+ }
+ }
+
+
+ /* Remaining runtime */
+ if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
+ {
+ if (shellfc)
+ {
+ fprintf(stderr,"\n");
+ }
+ print_time(stderr,runtime,step,ir,cr);
+ }
+
+ /* Set new positions for the group to embed */
+ if(!bLastStep){
+ if(step_rel<=it_xy)
+ {
+ fac[0]+=xy_step;
+ fac[1]+=xy_step;
+ } else if (step_rel<=(it_xy+it_z))
+ {
+ fac[2]+=z_step;
+ }
+ resize(ins_at,r_ins,state_global->x,pos_ins,fac);
+ }
+
+ /* Replica exchange */
+/* bExchanged = FALSE;
+ if ((repl_ex_nst > 0) && (step > 0) && !bLastStep &&
+ do_per_step(step,repl_ex_nst))
+ {
+ bExchanged = replica_exchange(fplog,cr,repl_ex,
+ state_global,enerd->term,
+ state,step,t);
+ }
+ if (bExchanged && PAR(cr))
+ {
+ if (DOMAINDECOMP(cr))
+ {
+ dd_partition_system(fplog,step,cr,TRUE,1,
+ state_global,top_global,ir,
+ state,&f,mdatoms,top,fr,
+ vsite,shellfc,constr,
+ nrnb,wcycle,FALSE);
+ }
+ else
+ {
+ bcast_state(cr,state,FALSE);
+ }
+ }*/
+
+ bFirstStep = FALSE;
+ bInitStep = FALSE;
+ bStartingFromCpt = FALSE;
+
+ /* ####### SET VARIABLES FOR NEXT ITERATION IF THEY STILL NEED IT ###### */
+ /* Complicated conditional when bGStatEveryStep=FALSE.
+ * We can not just use bGStat, since then the simulation results
+ * would depend on nstenergy and nstlog or step_nscheck.
+ */
+ if (((state->flags & (1<<estPRES_PREV)) ||
+ (state->flags & (1<<estSVIR_PREV)) ||
+ (state->flags & (1<<estFVIR_PREV))) &&
+ (bGStatEveryStep ||
+ (ir->nstlist > 0 && step % ir->nstlist == 0) ||
+ (ir->nstlist < 0 && nlh.nabnsb > 0) ||
+ (ir->nstlist == 0 && bGStat)))
+ {
+ /* Store the pressure in t_state for pressure coupling
+ * at the next MD step.
+ */
+ if (state->flags & (1<<estPRES_PREV))
+ {
+ copy_mat(pres,state->pres_prev);
+ }
+ }
+
+ /* ####### END SET VARIABLES FOR NEXT ITERATION ###### */
+
+ if (bRerunMD)
+ {
+ /* read next frame from input trajectory */
+ bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
+ }
+
+ if (!bRerunMD || !rerun_fr.bStep)
+ {
+ /* increase the MD step number */
+ step++;
+ step_rel++;
+ }
+
+ cycles = wallcycle_stop(wcycle,ewcSTEP);
+ if (DOMAINDECOMP(cr) && wcycle)
+ {
+ dd_cycles_add(cr->dd,cycles,ddCyclStep);
+ }
+
+ if (step_rel == wcycle_get_reset_counters(wcycle) ||
+ gs.set[eglsRESETCOUNTERS] != 0)
+ {
+ /* Reset all the counters related to performance over the run */
+ reset_all_counters(fplog,cr,step,&step_rel,ir,wcycle,nrnb,runtime);
+ wcycle_set_reset_counters(wcycle,-1);
+ bResetCountersHalfMaxH = FALSE;
+ gs.set[eglsRESETCOUNTERS] = 0;
+ }
+ }
+ /* End of main MD loop */
+ debug_gmx();
+ write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
+ *top_global->name,top_global,
+ state_global->x,state_global->v,
+ ir->ePBC,state->box);
+
+ /* Stop the time */
+ runtime_end(runtime);
+
+ if (bRerunMD)
+ {
+ close_trj(status);
+ }
+
+ if (!(cr->duty & DUTY_PME))
+ {
+ /* Tell the PME only node to finish */
+ gmx_pme_finish(cr);
+ }
+
+ if (MASTER(cr))
+ {
+ if (ir->nstcalcenergy > 0 && !bRerunMD)
+ {
+ print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
+ eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+ }
+ }
+
+ done_mdoutf(outf);
+
+ debug_gmx();
+
+ if (ir->nstlist == -1 && nlh.nns > 0 && fplog)
+ {
+ fprintf(fplog,"Average neighborlist lifetime: %.1f steps, std.dev.: %.1f steps\n",nlh.s1/nlh.nns,sqrt(nlh.s2/nlh.nns - sqr(nlh.s1/nlh.nns)));
+ fprintf(fplog,"Average number of atoms that crossed the half buffer length: %.1f\n\n",nlh.ab/nlh.nns);
+ }
+
+ if (shellfc && fplog)
+ {
+ fprintf(fplog,"Fraction of iterations that converged: %.2f %%\n",
+ (nconverged*100.0)/step_rel);
+ fprintf(fplog,"Average number of force evaluations per MD step: %.2f\n\n",
+ tcount/step_rel);
+ }
+
+/* if (repl_ex_nst > 0 && MASTER(cr))
+ {
+ print_replica_exchange_statistics(fplog,repl_ex);
+ }*/
+
+ runtime->nsteps_done = step_rel;
+
+ return 0;
+}
+
+
+int mdrunner_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
+ const output_env_t oenv, bool bVerbose,bool bCompact,
+ int nstglobalcomm,
+ ivec ddxyz,int dd_node_order,real rdd,real rconstr,
+ const char *dddlb_opt,real dlb_scale,
+ const char *ddcsx,const char *ddcsy,const char *ddcsz,
+ int nstepout,int resetstep,int nmultisim,int repl_ex_nst,int repl_ex_seed,
+ real pforce,real cpt_period,real max_hours,
+ const char *deviceOptions,
+ unsigned long Flags,
+ real xy_fac, real xy_max, real z_fac, real z_max,
+ int it_xy, int it_z, real probe_rad, int low_up_rm,
+ int pieces, bool bALLOW_ASYMMETRY, int maxwarn)
+{
+ double nodetime=0,realtime;
+ t_inputrec *inputrec;
+ t_state *state=NULL;
+ matrix box;
+ gmx_ddbox_t ddbox;
+ int npme_major,npme_minor;
+ real tmpr1,tmpr2;
+ t_nrnb *nrnb;
+ gmx_mtop_t *mtop=NULL;
+ t_mdatoms *mdatoms=NULL;
+ t_forcerec *fr=NULL;
+ t_fcdata *fcd=NULL;
+ real ewaldcoeff=0;
+ gmx_pme_t *pmedata=NULL;
+ gmx_vsite_t *vsite=NULL;
+ gmx_constr_t constr;
+ int i,m,nChargePerturbed=-1,status,nalloc;
+ char *gro;
+ gmx_wallcycle_t wcycle;
+ bool bReadRNG,bReadEkin;
+ int list;
+ gmx_runtime_t runtime;
+ int rc;
+ gmx_large_int_t reset_counters;
+ gmx_edsam_t ed=NULL;
+ t_commrec *cr_old=cr;
+ int nthreads=1,nthreads_requested=1;
+
+
+ char *ins;
+ int rm_bonded_at,fr_id,fr_i=0,tmp_id,warn=0;
+ int ng,j,max_lip_rm,ins_grp_id,ins_nat,mem_nat,ntype,lip_rm,tpr_version;
+ real xy_step=0,z_step=0;
+ real prot_area;
+ rvec *r_ins=NULL,fac;
+ t_block *ins_at,*rest_at;
+ pos_ins_t *pos_ins;
+ mem_t *mem_p;
+ rm_t *rm_p;
+ gmx_groups_t *groups;
+ bool bExcl=FALSE;
+ t_atoms atoms;
+ t_pbc *pbc;
+ char **piecename=NULL;
+
+ /* CAUTION: threads may be started later on in this function, so
+ cr doesn't reflect the final parallel state right now */
+ snew(inputrec,1);
+ snew(mtop,1);
+
+ if (bVerbose && SIMMASTER(cr))
+ {
+ fprintf(stderr,"Getting Loaded...\n");
+ }
+
+ if (Flags & MD_APPENDFILES)
+ {
+ fplog = NULL;
+ }
+
+ snew(state,1);
+ if (MASTER(cr))
+ {
+ /* Read (nearly) all data required for the simulation */
+ read_tpx_state(ftp2fn(efTPX,nfile,fnm),inputrec,state,NULL,mtop);
+
+ /* NOW the threads will be started: */
+#ifdef GMX_THREADS
+#endif
+ }
+ /* END OF CAUTION: cr is now reliable */
+
+ /* now make sure the state is initialized and propagated */
+ set_state_entries(state,inputrec,cr->nnodes);
+ if (PAR(cr))
+ {
+ /* now broadcast everything to the non-master nodes/threads: */
+ init_parallel(fplog, cr, inputrec, mtop, state);
+ }
+
+ if (can_use_allvsall(inputrec,mtop,TRUE,cr,fplog))
+ {
+ /* All-vs-all loops do not work with domain decomposition */
+ Flags |= MD_PARTDEC;
+ }
+
+ if (!EEL_PME(inputrec->coulombtype) || (Flags & MD_PARTDEC))
+ {
+ cr->npmenodes = 0;
+ }
+
+ snew(ins_at,1);
+ snew(pos_ins,1);
+ if(MASTER(cr))
+ {
+ tpr_version = get_tpr_version(ftp2fn(efTPX,nfile,fnm));
+ if (tpr_version<58)
+ gmx_fatal(FARGS,"Version of *.tpr file to old (%d). Rerun grompp with gromacs VERSION 4.0.3 or newer.\n",tpr_version);
+
+ if( inputrec->eI != eiMD )
+ gmx_input("Change integrator to md in mdp file.");
+
+ if(PAR(cr))
+ gmx_input("Sorry, parallel g_membed is not yet fully functrional.");
+
+ groups=&(mtop->groups);
+
+ atoms=gmx_mtop_global_atoms(mtop);
+ snew(mem_p,1);
+ fprintf(stderr,"\nSelect a group to embed in the membrane:\n");
+ get_index(&atoms,ftp2fn_null(efNDX,nfile,fnm),1,&(ins_at->nr),&(ins_at->index),&ins);
+ ins_grp_id = search_string(ins,groups->ngrpname,(groups->grpname));
+ fprintf(stderr,"\nSelect a group to embed %s into (e.g. the membrane):\n",ins);
+ get_index(&atoms,ftp2fn_null(efNDX,nfile,fnm),1,&(mem_p->mem_at.nr),&(mem_p->mem_at.index),&(mem_p->name));
+
+ pos_ins->pieces=pieces;
+ snew(pos_ins->nidx,pieces);
+ snew(pos_ins->subindex,pieces);
+ snew(piecename,pieces);
+ if (pieces>1)
+ {
+ fprintf(stderr,"\nSelect pieces to embed:\n");
+ get_index(&atoms,ftp2fn_null(efNDX,nfile,fnm),pieces,pos_ins->nidx,pos_ins->subindex,piecename);
+ }
+ else
+ {
+ /*use whole embedded group*/
+ snew(pos_ins->nidx,1);
+ snew(pos_ins->subindex,1);
+ pos_ins->nidx[0]=ins_at->nr;
+ pos_ins->subindex[0]=ins_at->index;
+ }
+
+ if(probe_rad<0.2199999)
+ {
+ warn++;
+ fprintf(stderr,"\nWarning %d:\nA probe radius (-rad) smaller than 0.2 can result in overlap between waters "
+ "and the group to embed, which will result in Lincs errors etc.\nIf you are sure, you can increase maxwarn.\n\n",warn);
+ }
+
+ if(xy_fac<0.09999999)
+ {
+ warn++;
+ fprintf(stderr,"\nWarning %d:\nThe initial size of %s is probably too smal.\n"
+ "If you are sure, you can increase maxwarn.\n\n",warn,ins);
+ }
+
+ if(it_xy<1000)
+ {
+ warn++;
+ fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the xy-coordinates of %s (%d) is probably too small.\n"
+ "Increase -nxy or, if you are sure, you can increase maxwarn.\n\n",warn,ins,it_xy);
+ }
+
+ if( (it_z<100) && ( z_fac<0.99999999 || z_fac>1.0000001) )
+ {
+ warn++;
+ fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the z-coordinate of %s (%d) is probably too small.\n"
+ "Increase -nz or, if you are sure, you can increase maxwarn.\n\n",warn,ins,it_z);
+ }
+
+ if(it_xy+it_z>inputrec->nsteps)
+ {
+ warn++;
+ fprintf(stderr,"\nWarning %d:\nThe number of growth steps (-nxy + -nz) is larger than the number of steps in the tpr.\n"
+ "If you are sure, you can increase maxwarn.\n\n",warn);
+ }
+
+ fr_id=-1;
+ if( inputrec->opts.ngfrz==1)
+ gmx_fatal(FARGS,"You did not specify \"%s\" as a freezegroup.",ins);
+ for(i=0;i<inputrec->opts.ngfrz;i++)
+ {
+ tmp_id = mtop->groups.grps[egcFREEZE].nm_ind[i];
+ if(ins_grp_id==tmp_id)
+ {
+ fr_id=tmp_id;
+ fr_i=i;
+ }
+ }
+ if (fr_id == -1 )
+ gmx_fatal(FARGS,"\"%s\" not as freezegroup defined in the mdp-file.",ins);
+
+ for(i=0;i<DIM;i++)
+ if( inputrec->opts.nFreeze[fr_i][i] != 1)
+ gmx_fatal(FARGS,"freeze dimensions for %s are not Y Y Y\n",ins);
+
+ ng = groups->grps[egcENER].nr;
+ if (ng == 1)
+ gmx_input("No energy groups defined. This is necessary for energy exclusion in the freeze group");
+
+ for(i=0;i<ng;i++)
+ {
+ for(j=0;j<ng;j++)
+ {
+ if (inputrec->opts.egp_flags[ng*i+j] == EGP_EXCL)
+ {
+ bExcl = TRUE;
+ if ( (groups->grps[egcENER].nm_ind[i] != ins_grp_id) || (groups->grps[egcENER].nm_ind[j] != ins_grp_id) )
+ gmx_fatal(FARGS,"Energy exclusions \"%s\" and \"%s\" do not match the group to embed \"%s\"",
+ *groups->grpname[groups->grps[egcENER].nm_ind[i]],
+ *groups->grpname[groups->grps[egcENER].nm_ind[j]],ins);
+ }
+ }
+ }
+ if (!bExcl)
+ gmx_input("No energy exclusion groups defined. This is necessary for energy exclusion in the freeze group");
+
+ /* Set all atoms in box*/
+ /*set_inbox(state->natoms,state->x);*/
+
+ /* Guess the area the protein will occupy in the membrane plane Calculate area per lipid*/
+ snew(rest_at,1);
+ ins_nat = init_ins_at(ins_at,rest_at,state,pos_ins,groups,ins_grp_id,xy_max);
+ /* Check moleculetypes in insertion group */
+ check_types(ins_at,rest_at,mtop);
+
+ mem_nat = init_mem_at(mem_p,mtop,state->x,state->box,pos_ins);
+
+ prot_area = est_prot_area(pos_ins,state->x,ins_at,mem_p);
+ if ( (prot_area>7.5) && ( (state->box[XX][XX]*state->box[YY][YY]-state->box[XX][YY]*state->box[YY][XX])<50) )
+ {
+ warn++;
+ fprintf(stderr,"\nWarning %d:\nThe xy-area is very small compared to the area of the protein.\n"
+ "This might cause pressure problems during the growth phase. Just try with\n"
+ "current setup (-maxwarn + 1), but if pressure problems occur, lower the\n"
+ "compressibility in the mdp-file or use no pressure coupling at all.\n\n",warn);
+ }
+ if(warn>maxwarn)
+ gmx_fatal(FARGS,"Too many warnings.\n");
+
+ printf("The estimated area of the protein in the membrane is %.3f nm^2\n",prot_area);
+ printf("\nThere are %d lipids in the membrane part that overlaps the protein.\nThe area per lipid is %.4f nm^2.\n",mem_p->nmol,mem_p->lip_area);
+
+ /* Maximum number of lipids to be removed*/
+ max_lip_rm=(int)(2*prot_area/mem_p->lip_area);
+ printf("Maximum number of lipids that will be removed is %d.\n",max_lip_rm);
+
+ printf("\nWill resize the protein by a factor of %.3f in the xy plane and %.3f in the z direction.\n"
+ "This resizing will be done with respect to the geometrical center of all protein atoms\n"
+ "that span the membrane region, i.e. z between %.3f and %.3f\n\n",xy_fac,z_fac,mem_p->zmin,mem_p->zmax);
+
+ /* resize the protein by xy and by z if necessary*/
+ snew(r_ins,ins_at->nr);
+ init_resize(ins_at,r_ins,pos_ins,mem_p,state->x,bALLOW_ASYMMETRY);
+ fac[0]=fac[1]=xy_fac;
+ fac[2]=z_fac;
+
+ xy_step =(xy_max-xy_fac)/(double)(it_xy);
+ z_step =(z_max-z_fac)/(double)(it_z-1);
+
+ resize(ins_at,r_ins,state->x,pos_ins,fac);
+
+ /* remove overlapping lipids and water from the membrane box*/
+ /*mark molecules to be removed*/
+ snew(pbc,1);
+ set_pbc(pbc,inputrec->ePBC,state->box);
+
+ snew(rm_p,1);
+ lip_rm = gen_rm_list(rm_p,ins_at,rest_at,pbc,mtop,state->x, r_ins, mem_p,pos_ins,probe_rad,low_up_rm,bALLOW_ASYMMETRY);
+ lip_rm -= low_up_rm;
+
+ if(fplog)
+ for(i=0;i<rm_p->nr;i++)
+ fprintf(fplog,"rm mol %d\n",rm_p->mol[i]);
+
+ for(i=0;i<mtop->nmolblock;i++)
+ {
+ ntype=0;
+ for(j=0;j<rm_p->nr;j++)
+ if(rm_p->block[j]==i)
+ ntype++;
+ printf("Will remove %d %s molecules\n",ntype,*(mtop->moltype[mtop->molblock[i].type].name));
+ }
+
+ if(lip_rm>max_lip_rm)
+ {
+ warn++;
+ fprintf(stderr,"\nWarning %d:\nTrying to remove a larger lipid area than the estimated protein area\n"
+ "Try making the -xyinit resize factor smaller. If you are sure about this increase maxwarn.\n\n",warn);
+ }
+
+ /*remove all lipids and waters overlapping and update all important structures*/
+ rm_group(inputrec,groups,mtop,rm_p,state,ins_at,pos_ins);
+
+ rm_bonded_at = rm_bonded(ins_at,mtop);
+ if (rm_bonded_at != ins_at->nr)
+ {
+ fprintf(stderr,"Warning: The number of atoms for which the bonded interactions are removed is %d, "
+ "while %d atoms are embedded. Make sure that the atoms to be embedded are not in the same"
+ "molecule type as atoms that are not to be embedded.\n",rm_bonded_at,ins_at->nr);
+ }
+
+ if(warn>maxwarn)
+ gmx_fatal(FARGS,"Too many warnings.\nIf you are sure these warnings are harmless, you can increase -maxwarn");
+
+ if (MASTER(cr))
+ {
+ if (ftp2bSet(efTOP,nfile,fnm))
+ top_update(opt2fn("-p",nfile,fnm),ins,rm_p,mtop);
+ }
+
+ sfree(pbc);
+ sfree(rest_at);
+ }
+
+#ifdef GMX_FAHCORE
+ fcRegisterSteps(inputrec->nsteps,inputrec->init_step);
+#endif
+
+ /* NMR restraints must be initialized before load_checkpoint,
+ * since with time averaging the history is added to t_state.
+ * For proper consistency check we therefore need to extend
+ * t_state here.
+ * So the PME-only nodes (if present) will also initialize
+ * the distance restraints.
+ */
+ snew(fcd,1);
+
+ /* This needs to be called before read_checkpoint to extend the state */
+ init_disres(fplog,mtop,inputrec,cr,Flags & MD_PARTDEC,fcd,state);
+
+ if (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0)
+ {
+ if (PAR(cr) && !(Flags & MD_PARTDEC))
+ {
+ gmx_fatal(FARGS,"Orientation restraints do not work (yet) with domain decomposition, use particle decomposition (mdrun option -pd)");
+ }
+ /* Orientation restraints */
+ if (MASTER(cr))
+ {
+ init_orires(fplog,mtop,state->x,inputrec,cr->ms,&(fcd->orires),
+ state);
+ }
+ }
+
+ if (DEFORM(*inputrec))
+ {
+ /* Store the deform reference box before reading the checkpoint */
+ if (SIMMASTER(cr))
+ {
+ copy_mat(state->box,box);
+ }
+ if (PAR(cr))
+ {
+ gmx_bcast(sizeof(box),box,cr);
+ }
+ /* Because we do not have the update struct available yet
+ * in which the reference values should be stored,
+ * we store them temporarily in static variables.
+ * This should be thread safe, since they are only written once
+ * and with identical values.
+ */
+/* deform_init_init_step_tpx = inputrec->init_step;*/
+/* copy_mat(box,deform_init_box_tpx);*/
+ }
+
+ if (opt2bSet("-cpi",nfile,fnm))
+ {
+ /* Check if checkpoint file exists before doing continuation.
+ * This way we can use identical input options for the first and subsequent runs...
+ */
+ if( gmx_fexist_master(opt2fn_master("-cpi",nfile,fnm,cr),cr) )
+ {
+ load_checkpoint(opt2fn_master("-cpi",nfile,fnm,cr),&fplog,
+ cr,Flags & MD_PARTDEC,ddxyz,
+ inputrec,state,&bReadRNG,&bReadEkin,
+ (Flags & MD_APPENDFILES));
+
+ if (bReadRNG)
+ {
+ Flags |= MD_READ_RNG;
+ }
+ if (bReadEkin)
+ {
+ Flags |= MD_READ_EKIN;
+ }
+ }
+ }
+
+ if ((MASTER(cr) || (Flags & MD_SEPPOT)) && (Flags & MD_APPENDFILES))
+ {
+ gmx_log_open(ftp2fn(efLOG,nfile,fnm),cr,!(Flags & MD_SEPPOT),
+ Flags,&fplog);
+ }
+
+ if (SIMMASTER(cr))
+ {
+ copy_mat(state->box,box);
+ }
+
+ if (PAR(cr))
+ {
+ gmx_bcast(sizeof(box),box,cr);
+ }
+
+ if (bVerbose && SIMMASTER(cr))
+ {
+ fprintf(stderr,"Loaded with Money\n\n");
+ }
+
+ if (PAR(cr) && !((Flags & MD_PARTDEC) || EI_TPI(inputrec->eI)))
+ {
+ cr->dd = init_domain_decomposition(fplog,cr,Flags,ddxyz,rdd,rconstr,
+ dddlb_opt,dlb_scale,
+ ddcsx,ddcsy,ddcsz,
+ mtop,inputrec,
+ box,state->x,
+ &ddbox,&npme_major,&npme_minor);
+
+ make_dd_communicators(fplog,cr,dd_node_order);
+
+ /* Set overallocation to avoid frequent reallocation of arrays */
+ set_over_alloc_dd(TRUE);
+ }
+ else
+ {
+ /* PME, if used, is done on all nodes with 1D decomposition */
+ cr->npmenodes = 0;
+ cr->duty = (DUTY_PP | DUTY_PME);
+ npme_major = cr->nnodes;
+ npme_minor = 1;
+
+ if (inputrec->ePBC == epbcSCREW)
+ {
+ gmx_fatal(FARGS,
+ "pbc=%s is only implemented with domain decomposition",
+ epbc_names[inputrec->ePBC]);
+ }
+ }
+
+ if (PAR(cr))
+ {
+ /* After possible communicator splitting in make_dd_communicators.
+ * we can set up the intra/inter node communication.
+ */
+ gmx_setup_nodecomm(fplog,cr);
+ }
+
+ wcycle = wallcycle_init(fplog,resetstep,cr);
+ if (PAR(cr))
+ {
+ /* Master synchronizes its value of reset_counters with all nodes
+ * including PME only nodes */
+ reset_counters = wcycle_get_reset_counters(wcycle);
+ gmx_bcast_sim(sizeof(reset_counters),&reset_counters,cr);
+ wcycle_set_reset_counters(wcycle, reset_counters);
+ }
+
+
+ snew(nrnb,1);
+ if (cr->duty & DUTY_PP)
+ {
+ /* For domain decomposition we allocate dynamically
+ * in dd_partition_system.
+ */
+ if (DOMAINDECOMP(cr))
+ {
+ bcast_state_setup(cr,state);
+ }
+ else
+ {
+ if (PAR(cr))
+ {
+ if (!MASTER(cr))
+ {
+ snew(state,1);
+ }
+ bcast_state(cr,state,TRUE);
+ }
+ }
+
+ /* Dihedral Restraints */
+ if (gmx_mtop_ftype_count(mtop,F_DIHRES) > 0)
+ {
+ init_dihres(fplog,mtop,inputrec,fcd);
+ }
+
+ /* Initiate forcerecord */
+ fr = mk_forcerec();
+ init_forcerec(fplog,oenv,fr,fcd,inputrec,mtop,cr,box,FALSE,
+ opt2fn("-table",nfile,fnm),
+ opt2fn("-tablep",nfile,fnm),
+ opt2fn("-tableb",nfile,fnm),FALSE,pforce);
+
+ /* version for PCA_NOT_READ_NODE (see md.c) */
+ /*init_forcerec(fplog,fr,fcd,inputrec,mtop,cr,box,FALSE,
+ "nofile","nofile","nofile",FALSE,pforce);
+ */
+ fr->bSepDVDL = ((Flags & MD_SEPPOT) == MD_SEPPOT);
+
+ /* Initialize QM-MM */
+ if(fr->bQMMM)
+ {
+ init_QMMMrec(cr,box,mtop,inputrec,fr);
+ }
+
+ /* Initialize the mdatoms structure.
+ * mdatoms is not filled with atom data,
+ * as this can not be done now with domain decomposition.
+ */
+ mdatoms = init_mdatoms(fplog,mtop,inputrec->efep!=efepNO);
+
+ /* Initialize the virtual site communication */
+ vsite = init_vsite(mtop,cr);
+
+ calc_shifts(box,fr->shift_vec);
+
+ /* With periodic molecules the charge groups should be whole at start up
+ * and the virtual sites should not be far from their proper positions.
+ */
+ if (!inputrec->bContinuation && MASTER(cr) &&
+ !(inputrec->ePBC != epbcNONE && inputrec->bPeriodicMols))
+ {
+ /* Make molecules whole at start of run */
+ if (fr->ePBC != epbcNONE)
+ {
+ do_pbc_first_mtop(fplog,inputrec->ePBC,box,mtop,state->x);
+ }
+ if (vsite)
+ {
+ /* Correct initial vsite positions are required
+ * for the initial distribution in the domain decomposition
+ * and for the initial shell prediction.
+ */
+ construct_vsites_mtop(fplog,vsite,mtop,state->x);
+ }
+ }
+
+ /* Initiate PPPM if necessary */
+ if (fr->eeltype == eelPPPM)
+ {
+ if (mdatoms->nChargePerturbed)
+ {
+ gmx_fatal(FARGS,"Free energy with %s is not implemented",
+ eel_names[fr->eeltype]);
+ }
+ status = gmx_pppm_init(fplog,cr,oenv,FALSE,TRUE,box,
+ getenv("GMXGHAT"),inputrec, (Flags & MD_REPRODUCIBLE));
+ if (status != 0)
+ {
+ gmx_fatal(FARGS,"Error %d initializing PPPM",status);
+ }
+ }
+
+ if (EEL_PME(fr->eeltype))
+ {
+ ewaldcoeff = fr->ewaldcoeff;
+ pmedata = &fr->pmedata;
+ }
+ else
+ {
+ pmedata = NULL;
+ }
+ }
+ else
+ {
+ /* This is a PME only node */
+
+ /* We don't need the state */
+ done_state(state);
+
+ ewaldcoeff = calc_ewaldcoeff(inputrec->rcoulomb, inputrec->ewald_rtol);
+ snew(pmedata,1);
+ }
+
+ /* Initiate PME if necessary,
+ * either on all nodes or on dedicated PME nodes only. */
+ if (EEL_PME(inputrec->coulombtype))
+ {
+ if (mdatoms)
+ {
+ nChargePerturbed = mdatoms->nChargePerturbed;
+ }
+ if (cr->npmenodes > 0)
+ {
+ /* The PME only nodes need to know nChargePerturbed */
+ gmx_bcast_sim(sizeof(nChargePerturbed),&nChargePerturbed,cr);
+ }
+ if (cr->duty & DUTY_PME)
+ {
+ status = gmx_pme_init(pmedata,cr,npme_major,npme_minor,inputrec,
+ mtop ? mtop->natoms : 0,nChargePerturbed,
+ (Flags & MD_REPRODUCIBLE));
+ if (status != 0)
+ {
+ gmx_fatal(FARGS,"Error %d initializing PME",status);
+ }
+ }
+ }
+
+
+/* if (integrator[inputrec->eI].func == do_md
+#ifdef GMX_OPENMM
+ ||
+ integrator[inputrec->eI].func == do_md_openmm
+#endif
+ )
+ {*/
+ /* Turn on signal handling on all nodes */
+ /*
+ * (A user signal from the PME nodes (if any)
+ * is communicated to the PP nodes.
+ */
+ signal_handler_install();
+/* }*/
+
+ if (cr->duty & DUTY_PP)
+ {
+ if (inputrec->ePull != epullNO)
+ {
+ /* Initialize pull code */
+ init_pull(fplog,inputrec,nfile,fnm,mtop,cr,oenv,
+ EI_DYNAMICS(inputrec->eI) && MASTER(cr),Flags);
+ }
+
+ constr = init_constraints(fplog,mtop,inputrec,ed,state,cr);
+
+ if (DOMAINDECOMP(cr))
+ {
+ dd_init_bondeds(fplog,cr->dd,mtop,vsite,constr,inputrec,
+ Flags & MD_DDBONDCHECK,fr->cginfo_mb);
+
+ set_dd_parameters(fplog,cr->dd,dlb_scale,inputrec,fr,&ddbox);
+
+ setup_dd_grid(fplog,cr->dd);
+ }
+
+ /* Now do whatever the user wants us to do (how flexible...) */
+ do_md_membed(fplog,cr,nfile,fnm,
+ oenv,bVerbose,bCompact,
+ nstglobalcomm,
+ vsite,constr,
+ nstepout,inputrec,mtop,
+ fcd,state,
+ mdatoms,nrnb,wcycle,ed,fr,
+ repl_ex_nst,repl_ex_seed,
+ cpt_period,max_hours,
+ deviceOptions,
+ Flags,
+ &runtime,
+ fac, r_ins, pos_ins, ins_at,
+ xy_step, z_step, it_xy, it_z);
+
+ if (inputrec->ePull != epullNO)
+ {
+ finish_pull(fplog,inputrec->pull);
+ }
+ }
+ else
+ {
+ /* do PME only */
+ gmx_pmeonly(*pmedata,cr,nrnb,wcycle,ewaldcoeff,FALSE,inputrec);
+ }
+
+ if (EI_DYNAMICS(inputrec->eI) || EI_TPI(inputrec->eI))
+ {
+ /* Some timing stats */
+ if (MASTER(cr))
+ {
+ if (runtime.proc == 0)
+ {
+ runtime.proc = runtime.real;
+ }
+ }
+ else
+ {
+ runtime.real = 0;
+ }
+ }
+
+ wallcycle_stop(wcycle,ewcRUN);
+
+ /* Finish up, write some stuff
+ * if rerunMD, don't write last frame again
+ */
+ finish_run(fplog,cr,ftp2fn(efSTO,nfile,fnm),
+ inputrec,nrnb,wcycle,&runtime,
+ EI_DYNAMICS(inputrec->eI) && !MULTISIM(cr));
+
+ /* Does what it says */
+ print_date_and_time(fplog,cr->nodeid,"Finished mdrun",&runtime);
+
+ /* Close logfile already here if we were appending to it */
+ if (MASTER(cr) && (Flags & MD_APPENDFILES))
+ {
+ gmx_log_close(fplog);
+ }
+
+ if (pieces>1)
+ {
+ sfree(piecename);
+ }
+
+ rc=(int)gmx_get_stop_condition();
+
+ return rc;
+}
+
+int gmx_membed(int argc,char *argv[])
+{
+ const char *desc[] = {
+ "g_membed embeds a membrane protein into an equilibrated lipid bilayer at the position",
+ "and orientation specified by the user.\n",
+ "\n",
+ "SHORT MANUAL\n------------\n",
+ "The user should merge the structure files of the protein and membrane (+solvent), creating a",
+ "single structure file with the protein overlapping the membrane at the desired position and",
+ "orientation. Box size should be taken from the membrane structure file. The corresponding topology",
+ "files should also be merged. Consecutively, create a tpr file (input for g_membed) from these files,"
+ "with the following options included in the mdp file.\n",
+ " - integrator = md\n",
+ " - energygrp = Protein (or other group that you want to insert)\n",
+ " - freezegrps = Protein\n",
+ " - freezedim = Y Y Y\n",
+ " - energygrp_excl = Protein Protein\n",
+ "The output is a structure file containing the protein embedded in the membrane. If a topology",
+ "file is provided, the number of lipid and ",
+ "solvent molecules will be updated to match the new structure file.\n",
+ "For a more extensive manual see Wolf et al, J Comp Chem 31 (2010) 2169-2174, Appendix.\n",
+ "\n",
+ "SHORT METHOD DESCRIPTION\n",
+ "------------------------\n",
+ "1. The protein is resized around its center of mass by a factor -xy in the xy-plane",
+ "(the membrane plane) and a factor -z in the z-direction (if the size of the",
+ "protein in the z-direction is the same or smaller than the width of the membrane, a",
+ "-z value larger than 1 can prevent that the protein will be enveloped by the lipids).\n",
+ "2. All lipid and solvent molecules overlapping with the resized protein are removed. All",
+ "intraprotein interactions are turned off to prevent numerical issues for small values of -xy",
+ " or -z\n",
+ "3. One md step is performed.\n",
+ "4. The resize factor (-xy or -z) is incremented by a small amount ((1-xy)/nxy or (1-z)/nz) and the",
+ "protein is resized again around its center of mass. The resize factor for the xy-plane",
+ "is incremented first. The resize factor for the z-direction is not changed until the -xy factor",
+ "is 1 (thus after -nxy iteration).\n",
+ "5. Repeat step 3 and 4 until the protein reaches its original size (-nxy + -nz iterations).\n",
+ "For a more extensive method descrition see Wolf et al, J Comp Chem, 31 (2010) 2169-2174.\n",
+ "\n",
+ "NOTE\n----\n",
+ " - Protein can be any molecule you want to insert in the membrane.\n",
+ " - It is recommended to perform a short equilibration run after the embedding",
+ "(see Wolf et al, J Comp Chem 31 (2010) 2169-2174, to re-equilibrate the membrane. Clearly",
+ "protein equilibration might require longer.\n",
+ "\n"
+ };
+ t_commrec *cr;
+ t_filenm fnm[] = {
+ { efTPX, "-f", "into_mem", ffREAD },
+ { efNDX, "-n", "index", ffOPTRD },
+ { efTOP, "-p", "topol", ffOPTRW },
+ { efTRN, "-o", NULL, ffWRITE },
+ { efXTC, "-x", NULL, ffOPTWR },
+ { efCPT, "-cpi", NULL, ffOPTRD },
+ { efCPT, "-cpo", NULL, ffOPTWR },
+ { efSTO, "-c", "membedded", ffWRITE },
+ { efEDR, "-e", "ener", ffWRITE },
+ { efLOG, "-g", "md", ffWRITE },
+ { efEDI, "-ei", "sam", ffOPTRD },
+ { efTRX, "-rerun", "rerun", ffOPTRD },
+ { efXVG, "-table", "table", ffOPTRD },
+ { efXVG, "-tablep", "tablep", ffOPTRD },
+ { efXVG, "-tableb", "table", ffOPTRD },
+ { efXVG, "-dhdl", "dhdl", ffOPTWR },
+ { efXVG, "-field", "field", ffOPTWR },
+ { efXVG, "-table", "table", ffOPTRD },
+ { efXVG, "-tablep", "tablep", ffOPTRD },
+ { efXVG, "-tableb", "table", ffOPTRD },
+ { efTRX, "-rerun", "rerun", ffOPTRD },
+ { efXVG, "-tpi", "tpi", ffOPTWR },
+ { efXVG, "-tpid", "tpidist", ffOPTWR },
+ { efEDI, "-ei", "sam", ffOPTRD },
+ { efEDO, "-eo", "sam", ffOPTWR },
+ { efGCT, "-j", "wham", ffOPTRD },
+ { efGCT, "-jo", "bam", ffOPTWR },
+ { efXVG, "-ffout", "gct", ffOPTWR },
+ { efXVG, "-devout", "deviatie", ffOPTWR },
+ { efXVG, "-runav", "runaver", ffOPTWR },
+ { efXVG, "-px", "pullx", ffOPTWR },
+ { efXVG, "-pf", "pullf", ffOPTWR },
+ { efMTX, "-mtx", "nm", ffOPTWR },
+ { efNDX, "-dn", "dipole", ffOPTWR }
+ };
+#define NFILE asize(fnm)
+
+ /* Command line options ! */
+ bool bCart = FALSE;
+ bool bPPPME = FALSE;
+ bool bPartDec = FALSE;
+ bool bDDBondCheck = TRUE;
+ bool bDDBondComm = TRUE;
+ bool bVerbose = FALSE;
+ bool bCompact = TRUE;
+ bool bSepPot = FALSE;
+ bool bRerunVSite = FALSE;
+ bool bIonize = FALSE;
+ bool bConfout = TRUE;
+ bool bReproducible = FALSE;
+
+ int npme=-1;
+ int nmultisim=0;
+ int nstglobalcomm=-1;
+ int repl_ex_nst=0;
+ int repl_ex_seed=-1;
+ int nstepout=100;
+ int nthreads=0; /* set to determine # of threads automatically */
+ int resetstep=-1;
+
+ rvec realddxyz={0,0,0};
+ const char *ddno_opt[ddnoNR+1] =
+ { NULL, "interleave", "pp_pme", "cartesian", NULL };
+ const char *dddlb_opt[] =
+ { NULL, "auto", "no", "yes", NULL };
+ real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
+ char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
+ real cpt_period=15.0,max_hours=-1;
+ bool bAppendFiles=TRUE,bAddPart=TRUE;
+ bool bResetCountersHalfWay=FALSE;
+ output_env_t oenv=NULL;
+ const char *deviceOptions = "";
+
+ real xy_fac = 0.5;
+ real xy_max = 1.0;
+ real z_fac = 1.0;
+ real z_max = 1.0;
+ int it_xy = 1000;
+ int it_z = 0;
+ real probe_rad = 0.22;
+ int low_up_rm = 0;
+ int maxwarn=0;
+ int pieces=1;
+ bool bALLOW_ASYMMETRY=FALSE;
+
+
+/* arguments relevant to OPENMM only*/
+#ifdef GMX_OPENMM
+ gmx_input("g_membed not functional in openmm");
+#endif
+
+ t_pargs pa[] = {
+ { "-xyinit", FALSE, etREAL, {&xy_fac}, "Resize factor for the protein in the xy dimension before starting embedding" },
+ { "-xyend", FALSE, etREAL, {&xy_max}, "Final resize factor in the xy dimension" },
+ { "-zinit", FALSE, etREAL, {&z_fac}, "Resize factor for the protein in the z dimension before starting embedding" },
+ { "-zend", FALSE, etREAL, {&z_max}, "Final resize faction in the z dimension" },
+ { "-nxy", FALSE, etINT, {&it_xy}, "Number of iteration for the xy dimension" },
+ { "-nz", FALSE, etINT, {&it_z}, "Number of iterations for the z dimension" },
+ { "-rad", FALSE, etREAL, {&probe_rad}, "Probe radius to check for overlap between the group to embed and the membrane"},
+ { "-pieces", FALSE, etINT, {&pieces}, "Perform piecewise resize. Select parts of the group to insert and resize these with respect to their own geometrical center." },
+ { "-asymmetry",FALSE, etBOOL,{&bALLOW_ASYMMETRY}, "Allow asymmetric insertion, i.e. the number of lipids removed from the upper and lower leaflet will not be checked." },
+ { "-ndiff" , FALSE, etINT, {&low_up_rm}, "Number of lipids that will additionally be removed from the lower (negative number) or upper (positive number) membrane leaflet." },
+ { "-maxwarn", FALSE, etINT, {&maxwarn}, "Maximum number of warning allowed" },
+ { "-pd", FALSE, etBOOL,{&bPartDec},
+ "HIDDENUse particle decompostion" },
+ { "-dd", FALSE, etRVEC,{&realddxyz},
+ "HIDDENDomain decomposition grid, 0 is optimize" },
+ { "-nt", FALSE, etINT, {&nthreads},
+ "HIDDENNumber of threads to start (0 is guess)" },
+ { "-npme", FALSE, etINT, {&npme},
+ "HIDDENNumber of separate nodes to be used for PME, -1 is guess" },
+ { "-ddorder", FALSE, etENUM, {ddno_opt},
+ "HIDDENDD node order" },
+ { "-ddcheck", FALSE, etBOOL, {&bDDBondCheck},
+ "HIDDENCheck for all bonded interactions with DD" },
+ { "-ddbondcomm", FALSE, etBOOL, {&bDDBondComm},
+ "HIDDENUse special bonded atom communication when -rdd > cut-off" },
+ { "-rdd", FALSE, etREAL, {&rdd},
+ "HIDDENThe maximum distance for bonded interactions with DD (nm), 0 is determine from initial coordinates" },
+ { "-rcon", FALSE, etREAL, {&rconstr},
+ "HIDDENMaximum distance for P-LINCS (nm), 0 is estimate" },
+ { "-dlb", FALSE, etENUM, {dddlb_opt},
+ "HIDDENDynamic load balancing (with DD)" },
+ { "-dds", FALSE, etREAL, {&dlb_scale},
+ "HIDDENMinimum allowed dlb scaling of the DD cell size" },
+ { "-ddcsx", FALSE, etSTR, {&ddcsx},
+ "HIDDENThe DD cell sizes in x" },
+ { "-ddcsy", FALSE, etSTR, {&ddcsy},
+ "HIDDENThe DD cell sizes in y" },
+ { "-ddcsz", FALSE, etSTR, {&ddcsz},
+ "HIDDENThe DD cell sizes in z" },
+ { "-gcom", FALSE, etINT,{&nstglobalcomm},
+ "HIDDENGlobal communication frequency" },
+ { "-compact", FALSE, etBOOL,{&bCompact},
+ "Write a compact log file" },
+ { "-seppot", FALSE, etBOOL, {&bSepPot},
+ "HIDDENWrite separate V and dVdl terms for each interaction type and node to the log file(s)" },
+ { "-pforce", FALSE, etREAL, {&pforce},
+ "HIDDENPrint all forces larger than this (kJ/mol nm)" },
+ { "-reprod", FALSE, etBOOL,{&bReproducible},
+ "HIDDENTry to avoid optimizations that affect binary reproducibility" },
+ { "-multi", FALSE, etINT,{&nmultisim},
+ "HIDDENDo multiple simulations in parallel" },
+ { "-replex", FALSE, etINT, {&repl_ex_nst},
+ "HIDDENAttempt replica exchange every # steps" },
+ { "-reseed", FALSE, etINT, {&repl_ex_seed},
+ "HIDDENSeed for replica exchange, -1 is generate a seed" },
+ { "-rerunvsite", FALSE, etBOOL, {&bRerunVSite},
+ "HIDDENRecalculate virtual site coordinates with -rerun" },
+ { "-ionize", FALSE, etBOOL,{&bIonize},
+ "HIDDENDo a simulation including the effect of an X-Ray bombardment on your system" },
+ { "-confout", TRUE, etBOOL, {&bConfout},
+ "HIDDENWrite the last configuration with -c and force checkpointing at the last step" },
+ { "-stepout", FALSE, etINT, {&nstepout},
+ "HIDDENFrequency of writing the remaining runtime" },
+ { "-resetstep", FALSE, etINT, {&resetstep},
+ "HIDDENReset cycle counters after these many time steps" },
+ { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
+ "HIDDENReset the cycle counters after half the number of steps or halfway -maxh" },
+ { "-v", FALSE, etBOOL,{&bVerbose},
+ "Be loud and noisy" },
+ { "-maxh", FALSE, etREAL, {&max_hours},
+ "HIDDENTerminate after 0.99 times this time (hours)" },
+ { "-cpt", FALSE, etREAL, {&cpt_period},
+ "HIDDENCheckpoint interval (minutes)" },
+ { "-append", FALSE, etBOOL, {&bAppendFiles},
+ "HIDDENAppend to previous output files when continuing from checkpoint" },
+ { "-addpart", FALSE, etBOOL, {&bAddPart},
+ "HIDDENAdd the simulation part number to all output files when continuing from checkpoint" },
+ };
+ gmx_edsam_t ed;
+ unsigned long Flags, PCA_Flags;
+ ivec ddxyz;
+ int dd_node_order;
+ bool HaveCheckpoint;
+ FILE *fplog,*fptest;
+ int sim_part,sim_part_fn;
+ const char *part_suffix=".part";
+ char suffix[STRLEN];
+ int rc;
+
+
+ cr = init_par(&argc,&argv);
+
+ PCA_Flags = (PCA_KEEP_ARGS | PCA_NOEXIT_ON_ARGS | PCA_CAN_SET_DEFFNM
+ | (MASTER(cr) ? 0 : PCA_QUIET));
+
+
+ /* Comment this in to do fexist calls only on master
+ * works not with rerun or tables at the moment
+ * also comment out the version of init_forcerec in md.c
+ * with NULL instead of opt2fn
+ */
+ /*
+ if (!MASTER(cr))
+ {
+ PCA_Flags |= PCA_NOT_READ_NODE;
+ }
+ */
+
+ parse_common_args(&argc,argv,PCA_Flags, NFILE,fnm,asize(pa),pa,
+ asize(desc),desc,0,NULL, &oenv);
+
+ /* we set these early because they might be used in init_multisystem()
+ Note that there is the potential for npme>nnodes until the number of
+ threads is set later on, if there's thread parallelization. That shouldn't
+ lead to problems. */
+ dd_node_order = nenum(ddno_opt);
+ cr->npmenodes = npme;
+
+#ifdef GMX_THREADS
+ /* now determine the number of threads automatically. The threads are
+ only started at mdrunner_threads, though. */
+ if (nthreads<1)
+ {
+ nthreads=tMPI_Get_recommended_nthreads();
+ }
+#else
+ nthreads=1;
+#endif
+
+
+ if (repl_ex_nst != 0 && nmultisim < 2)
+ gmx_fatal(FARGS,"Need at least two replicas for replica exchange (option -multi)");
+
+ if (nmultisim > 1) {
+#ifndef GMX_THREADS
+ init_multisystem(cr,nmultisim,NFILE,fnm,TRUE);
+#else
+ gmx_fatal(FARGS,"mdrun -multi is not supported with the thread library.Please compile GROMACS with MPI support");
+#endif
+ }
+
+ /* Check if there is ANY checkpoint file available */
+ sim_part = 1;
+ sim_part_fn = sim_part;
+ if (opt2bSet("-cpi",NFILE,fnm))
+ {
+ bAppendFiles =
+ read_checkpoint_simulation_part(opt2fn_master("-cpi", NFILE,
+ fnm,cr),
+ &sim_part_fn,NULL,cr,
+ bAppendFiles,
+ part_suffix,&bAddPart);
+ if (sim_part_fn==0 && MASTER(cr))
+ {
+ fprintf(stdout,"No previous checkpoint file present, assuming this is a new run.\n");
+ }
+ else
+ {
+ sim_part = sim_part_fn + 1;
+ }
+ }
+ else
+ {
+ bAppendFiles = FALSE;
+ }
+
+ if (!bAppendFiles)
+ {
+ sim_part_fn = sim_part;
+ }
+
+ if (bAddPart && sim_part_fn > 1)
+ {
+ /* This is a continuation run, rename trajectory output files
+ (except checkpoint files) */
+ /* create new part name first (zero-filled) */
+ sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
+
+ add_suffix_to_output_names(fnm,NFILE,suffix);
+ fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
+ }
+
+ Flags = opt2bSet("-rerun",NFILE,fnm) ? MD_RERUN : 0;
+ Flags = Flags | (bSepPot ? MD_SEPPOT : 0);
+ Flags = Flags | (bIonize ? MD_IONIZE : 0);
+ Flags = Flags | (bPartDec ? MD_PARTDEC : 0);
+ Flags = Flags | (bDDBondCheck ? MD_DDBONDCHECK : 0);
+ Flags = Flags | (bDDBondComm ? MD_DDBONDCOMM : 0);
+ Flags = Flags | (bConfout ? MD_CONFOUT : 0);
+ Flags = Flags | (bRerunVSite ? MD_RERUN_VSITE : 0);
+ Flags = Flags | (bReproducible ? MD_REPRODUCIBLE : 0);
+ Flags = Flags | (bAppendFiles ? MD_APPENDFILES : 0);
+ Flags = Flags | (sim_part>1 ? MD_STARTFROMCPT : 0);
+ Flags = Flags | (bResetCountersHalfWay ? MD_RESETCOUNTERSHALFWAY : 0);
+
+
+ /* We postpone opening the log file if we are appending, so we can
+ first truncate the old log file and append to the correct position
+ there instead. */
+ if ((MASTER(cr) || bSepPot) && !bAppendFiles)
+ {
+ gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,!bSepPot,Flags,&fplog);
+ CopyRight(fplog,argv[0]);
+ please_cite(fplog,"Hess2008b");
+ please_cite(fplog,"Spoel2005a");
+ please_cite(fplog,"Lindahl2001a");
+ please_cite(fplog,"Berendsen95a");
+ }
+ else
+ {
+ fplog = NULL;
+ }
+
+ ddxyz[XX] = (int)(realddxyz[XX] + 0.5);
+ ddxyz[YY] = (int)(realddxyz[YY] + 0.5);
+ ddxyz[ZZ] = (int)(realddxyz[ZZ] + 0.5);
+
+ /* even if nthreads = 1, we still call this one */
+
+ rc = mdrunner_membed(fplog, cr, NFILE, fnm, oenv, bVerbose, bCompact,
+ nstglobalcomm,
+ ddxyz, dd_node_order, rdd, rconstr, dddlb_opt[0], dlb_scale,
+ ddcsx, ddcsy, ddcsz, nstepout, resetstep, nmultisim, repl_ex_nst,
+ repl_ex_seed, pforce, cpt_period, max_hours, deviceOptions, Flags,
+ xy_fac,xy_max,z_fac,z_max,
+ it_xy,it_z,probe_rad,low_up_rm,
+ pieces,bALLOW_ASYMMETRY,maxwarn);
+
+ if (gmx_parallel_env_initialized())
+ gmx_finalize();
+
+ if (MULTIMASTER(cr)) {
+ thanx(stderr);
+ }
+
+ /* Log file has to be closed in mdrunner if we are appending to it
+ (fplog not set here) */
+ fprintf(stderr,"Please cite:\nWolf et al, J Comp Chem 31 (2010) 2169-2174.\n");
+
+ if (MASTER(cr) && !bAppendFiles)
+ {
+ gmx_log_close(fplog);
+ }
+
+ return rc;
+}
{
FILE *out;
char *leg[5] = { "min per.","max int.","box1","box2","box3" };
- int status;
+ t_trxstatus *status;
real t;
rvec *x;
matrix box;
int natoms,ind_min[2]={0,0},ind_mini=0,ind_minj=0;
real r,rmin,rmax,rmint,tmint;
bool bFirst;
-
+ gmx_rmpbc_t gpbc=NULL;
+
natoms=read_first_x(oenv,&status,trxfn,&t,&x,box);
check_index(NULL,n,index,NULL,natoms);
rmint = box[XX][XX];
tmint = 0;
+ if (NULL != top)
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
bFirst=TRUE;
do {
- if (top) {
- rm_pbc(&(top->idef),ePBC,natoms,box,x,x);
- }
+ if (NULL != top)
+ gmx_rmpbc(gpbc,box,x,x);
+
periodic_dist(box,x,n,index,&rmin,&rmax,ind_min);
if (rmin < rmint) {
rmint = rmin;
output_env_conv_time(oenv,t),rmin,rmax,norm(box[0]),norm(box[1]),norm(box[2]));
bFirst=FALSE;
} while(read_next_x(oenv,status,&t,natoms,x,box));
+
+ if (NULL != top)
+ gmx_rmpbc_done(gpbc);
ffclose(out);
const output_env_t oenv)
{
FILE *atm,*dist,*num;
- int trxout;
+ t_trxstatus *trxout;
char buf[256];
char **leg;
real t,dmin,dmax,**mindres=NULL,**maxdres=NULL;
- int nmin,nmax,status;
+ int nmin,nmax;
+ t_trxstatus *status;
int i=-1,j,k,natoms;
int min1,min2,max1,max2;
atom_id oindex[2];
sprintf(buf,"Number of Contacts %s %g nm",bMin ? "<" : ">",rcut);
num = nfile ? xvgropen(nfile,buf,output_env_get_time_label(oenv),"Number",oenv) : NULL;
atm = afile ? ffopen(afile,"w") : NULL;
- trxout = xfile ? open_trx(xfile,"w") : NOTSET;
+ trxout = xfile ? open_trx(xfile,"w") : NULL;
if (bMat) {
if (ng == 1) {
output_env_conv_time(oenv,t),1+(bMin ? min1 : max1),
1+(bMin ? min2 : max2));
- if (trxout>=0) {
+ if (trxout) {
oindex[0]=bMin?min1:max1;
oindex[1]=bMin?min2:max2;
write_trx(trxout,2,oindex,atoms,i,t,box,x0,NULL,NULL);
ffclose(dist);
if (num) ffclose(num);
if (atm) ffclose(atm);
- if (trxout>=0) close_xtc(trxout);
+ if (trxout) close_trx(trxout);
if(nres && !bEachResEachTime) {
FILE *res;
"with multiple atoms in the first group is counted as one contact",
"instead of as multiple contacts.",
"With [TT]-or[tt], minimum distances to each residue in the first",
- "group are determined and plotted as a function of reisdue number.[PAR]",
+ "group are determined and plotted as a function of residue number.[PAR]",
"With option [TT]-pi[tt] the minimum distance of a group to its",
"periodic image is plotted. This is useful for checking if a protein",
"has seen its periodic image during a simulation. Only one shift in",
"generic trajectory. The number of intermediates can be controlled with",
"the -ninterm flag. The first and last flag correspond to the way of",
"interpolating: 0 corresponds to input structure 1 while",
- "1 corresponds to input strucutre 2.",
+ "1 corresponds to input structure 2.",
"If you specify first < 0 or last > 1 extrapolation will be",
"on the path from input structure x1 to x2. In general the coordinates",
"of the intermediate x(i) out of N total intermidates correspond to:[PAR]",
t_filenm fnm[] = {
{ efSTX, "-f1", "conf1", ffREAD },
{ efSTX, "-f2", "conf2", ffREAD },
- { efTRO, "-o", "interm", ffWRITE },
+ { efTRX, "-o", "interm", ffWRITE },
{ efXVG, "-or", "rms-interm", ffOPTWR },
{ efNDX, "-n", "index", ffOPTRD }
};
};
char *leg[] = { "Ref = 1\\Sst\\N conf", "Ref = 2\\Snd\\N conf" };
FILE *fp=NULL;
- int i,isize,is_lsq,status,nat1,nat2;
+ int i,isize,is_lsq,nat1,nat2;
+ t_trxstatus *status;
atom_id *index,*index_lsq,*index_all,*dummy;
t_atoms atoms;
rvec *x1,*x2,*xx,*v;
coefficient in X,Y,Z direction. LATERAL is diffusion coefficient in
plane perpendicular to axis
*/
-enum { NOT_USED, NORMAL, X, Y, Z, LATERAL };
+typedef enum { NOT_USED, NORMAL, X, Y, Z, LATERAL } msd_type;
typedef struct {
- real t0,delta_t,beginfit,endfit,dim_factor;
- real **data,*time,*data_x,*data_y,*data_z,*data_xy,*mass;
+ real t0; /* start time and time increment between */
+ real delta_t; /* time between restart points */
+ real beginfit, /* the begin/end time for fits as reals between */
+ endfit; /* 0 and 1 */
+ real dim_factor; /* the dimensionality factor for the diffusion
+ constant */
+ real **data; /* the displacement data. First index is the group
+ number, second is frame number */
+ real *time; /* frame time */
+ real *mass; /* masses for mass-weighted msd */
matrix **datam;
- rvec **x0;
- rvec *com;
- gmx_stats_t **lsq;
- int type,axis,ncoords,nrestart,nmol,nframes,nlast,ngrp;
- int *n_offs;
- int **ndata;
+ rvec **x0; /* original positions */
+ rvec *com; /* center of mass correction for each frame */
+ gmx_stats_t **lsq; /* fitting stats for individual molecule msds */
+ msd_type type; /* the type of msd to calculate (lateral, etc.)*/
+ int axis; /* the axis along which to calculate */
+ int ncoords;
+ int nrestart; /* number of restart points */
+ int nmol; /* number of molecules (for bMol) */
+ int nframes; /* number of frames */
+ int nlast;
+ int ngrp; /* number of groups to use for msd calculation */
+ int *n_offs;
+ int **ndata; /* the number of msds (particles/mols) per data
+ point. */
} t_corr;
typedef real t_calc_func(t_corr *,int,atom_id[],int,rvec[],rvec,bool,matrix,
int i;
snew(curr,1);
- curr->type = type;
+ curr->type = (msd_type)type;
curr->axis = axis;
curr->ngrp = nrgrp;
curr->nrestart = 0;
*/
for(nx0=0; (nx0<curr->nlast); nx0++) {
if (bRmCOMM) {
- rvec_sub(curr->com[nx0],com,dcom);
+ rvec_sub(com,curr->com[nx0],dcom);
} else {
clear_rvec(dcom);
}
}
}
+/* the non-mass-weighted mean-squared displacement calcuation */
static real calc1_norm(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
rvec dcom,bool bTen,matrix mat, const output_env_t oenv)
{
switch (curr->type) {
case NORMAL:
for(m=0; (m<DIM); m++) {
- rv[m] = curr->x0[nx0][ix][m] - xc[ix][m] - dcom[m];
+ rv[m] = xc[ix][m] - curr->x0[nx0][ix][m] - dcom[m];
r2 += rv[m]*rv[m];
if (bTen) {
for(m2=0; m2<=m; m2++)
case X:
case Y:
case Z:
- r = curr->x0[nx0][ix][curr->type-X] - xc[ix][curr->type-X]
- - dcom[curr->type-X];
+ r = xc[ix][curr->type-X] - curr->x0[nx0][ix][curr->type-X] -
+ dcom[curr->type-X];
r2 += r*r;
break;
case LATERAL:
for(m=0; (m<DIM); m++) {
if (m != curr->axis) {
- r = curr->x0[nx0][ix][m] - xc[ix][m] - dcom[m];
+ r = xc[ix][m] - curr->x0[nx0][ix][m] - dcom[m];
r2 += r*r;
}
}
return g;
}
+/* calculate the com of molecules in x and put it into xa */
static void calc_mol_com(int nmol,int *molindex,t_block *mols,t_atoms *atoms,
rvec *x,rvec *xa)
{
switch (curr->type) {
case NORMAL:
for(m=0; (m<DIM); m++) {
- rv[m] = curr->x0[nx0][ix][m] - xc[ix][m] - dcom[m];
+ rv[m] = xc[ix][m] - curr->x0[nx0][ix][m] - dcom[m];
r2 += mm*rv[m]*rv[m];
if (bTen) {
for(m2=0; m2<=m; m2++)
case X:
case Y:
case Z:
- r = curr->x0[nx0][ix][curr->type-X] - xc[ix][curr->type-X]
- - dcom[curr->type-X];
+ r = xc[ix][curr->type-X] - curr->x0[nx0][ix][curr->type-X] -
+ dcom[curr->type-X];
r2 = mm*r*r;
break;
case LATERAL:
for(m=0; (m<DIM); m++) {
if (m != curr->axis) {
- r = curr->x0[nx0][ix][m] - xc[ix][m] - dcom[m];
+ r = xc[ix][m] - curr->x0[nx0][ix][m] - dcom[m];
r2 += mm*r*r;
}
}
return r2;
}
+/* the normal, mass-weighted mean-squared displacement calcuation */
static real calc1_mw(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
rvec dcom,bool bTen,matrix mat,const output_env_t oenv)
{
return g;
}
-static void remove_pbc(bool bMol,int nmol,int natoms,t_atoms *atoms,
- rvec xcur[],rvec xprev[],matrix box,
- rvec com)
+/* prepare the coordinates by removing periodic boundary crossings.
+ gnx = the number of atoms/molecules
+ index = the indices
+ xcur = the current coordinates
+ xprev = the previous coordinates
+ box = the box matrix */
+static void prep_data(bool bMol,int gnx,atom_id index[],
+ rvec xcur[],rvec xprev[],matrix box)
{
- int n,i,m;
- rvec hbox;
- real mass;
- dvec sx;
- double tmass;
+ int i,m,ind;
+ rvec hbox;
- if (bMol)
- n = nmol;
- else
- n = natoms;
-
- /* Remove periodicity */
- for(m=0; (m<DIM); m++)
- hbox[m] = 0.5*box[m][m];
- clear_dvec(sx);
- tmass = 0;
- mass = 1;
- for(i=0; i<n; i++) {
- for(m=DIM-1; m>=0; m--) {
- while(xcur[i][m]-xprev[i][m] <= -hbox[m])
- rvec_inc(xcur[i],box[m]);
- while(xcur[i][m]-xprev[i][m] > hbox[m])
- rvec_dec(xcur[i],box[m]);
+ /* Remove periodicity */
+ for(m=0; (m<DIM); m++)
+ hbox[m]=0.5*box[m][m];
+
+ for(i=0; (i<gnx); i++) {
+ if (bMol)
+ ind = i;
+ else
+ ind = index[i];
+
+ for(m=DIM-1; m>=0; m--)
+ {
+ while(xcur[ind][m]-xprev[ind][m] <= -hbox[m])
+ rvec_inc(xcur[ind],box[m]);
+ while(xcur[ind][m]-xprev[ind][m] > hbox[m])
+ rvec_dec(xcur[ind],box[m]);
+ }
}
- if (!bMol)
- mass = atoms->atom[i].m;
- for(m=0; m<DIM; m++)
- sx[m] += mass*xcur[i][m];
- tmass += mass;
- }
- for(m=0; m<DIM; m++)
- com[m] = sx[m]/tmass;
}
-static void prep_data(bool bMol,int gnx,atom_id index[],
- rvec xcur[],rvec xprev[],matrix box)
+/* calculate the center of mass for a group
+ gnx = the number of atoms/molecules
+ index = the indices
+ xcur = the current coordinates
+ xprev = the previous coordinates
+ box = the box matrix
+ atoms = atom data (for mass)
+ com(output) = center of mass */
+static void calc_com(bool bMol, int gnx, atom_id index[],
+ rvec xcur[],rvec xprev[],matrix box, t_atoms *atoms,
+ rvec com)
{
- int i,m,ind;
- rvec hbox;
-
- /* Remove periodicity */
- for(m=0; (m<DIM); m++)
- hbox[m]=0.5*box[m][m];
- for(i=0; (i<gnx); i++) {
- if (bMol)
- ind = i;
- else
- ind = index[i];
- for(m=DIM-1; m>=0; m--) {
- while(xcur[ind][m]-xprev[ind][m] <= -hbox[m])
- rvec_inc(xcur[ind],box[m]);
- while(xcur[ind][m]-xprev[ind][m] > hbox[m])
- rvec_dec(xcur[ind],box[m]);
- }
- }
+ int i,m,ind;
+ real mass;
+ double tmass;
+ dvec sx;
+
+ clear_dvec(sx);
+ tmass = 0;
+ mass = 1;
+
+ prep_data(bMol, gnx, index, xcur, xprev, box);
+ for(i=0; (i<gnx); i++)
+ {
+ if (bMol)
+ ind = i;
+ else
+ ind = index[i];
+
+
+ mass = atoms->atom[ind].m;
+ for(m=0; m<DIM; m++)
+ sx[m] += mass*xcur[ind][m];
+ tmass += mass;
+ }
+ for(m=0; m<DIM; m++)
+ com[m] = sx[m]/tmass;
}
+
static real calc1_mol(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
rvec dcom,bool bTen,matrix mat, const output_env_t oenv)
{
int i;
- real g,mm,gtot,tt;
+ real g,tm,gtot,tt;
tt = curr->time[in_data(curr,nx0)];
gtot = 0;
+ tm = 0;
clear_mat(mat);
for(i=0; (i<nx); i++) {
- mm = 0;
- g = calc_one_mw(curr,i,nx0,xc,&mm,dcom,bTen,mat);
+ g = calc_one_mw(curr,i,nx0,xc,&tm,dcom,bTen,mat);
/* We don't need to normalize as the mass was set to 1 */
gtot += g;
if (tt >= curr->beginfit && (curr->endfit < 0 || tt <= curr->endfit))
rvec *x,int ePBC,matrix box, const output_env_t oenv)
{
#define NDIST 100
- FILE *out,out_pdb;
+ FILE *out;
gmx_stats_t lsq1;
int i,j;
- real a,b,r,D,Dav,D2av,VarD,sqrtD,sqrtD_max,scale;
+ real a,b,D,Dav,D2av,VarD,sqrtD,sqrtD_max,scale;
t_pdbinfo *pdbinfo=NULL;
int *mol2a=NULL;
real xx,yy,dx,dy;
while(gmx_stats_get_point(curr->lsq[j][i],&xx,&yy,&dx,&dy) == estatsOK)
- gmx_stats_add_point(lsq1,xx,yy,dx,dy);
- /* lsq1.sx+=curr->lsq[j][i].sx;
- lsq1.sy+=curr->lsq[j][i].sy;
- lsq1.xx+=curr->lsq[j][i].xx;
- lsq1.yx+=curr->lsq[j][i].yx;
- lsq1.np+=curr->lsq[j][i].np; */
+ gmx_stats_add_point(lsq1,xx,yy,dx,dy);
}
gmx_stats_get_ab(lsq1,elsqWEIGHT_NONE,&a,&b,NULL,NULL,NULL,NULL);
gmx_stats_done(lsq1);
*/
int corr_loop(t_corr *curr,const char *fn,t_topology *top,int ePBC,
bool bMol,int gnx[],atom_id *index[],
- t_calc_func *calc1,bool bTen,bool bRmCOMM,real dt,
- real t_pdb,rvec **x_pdb,matrix box_pdb, const output_env_t oenv)
+ t_calc_func *calc1,bool bTen, int *gnx_com, atom_id *index_com[],
+ real dt, real t_pdb,rvec **x_pdb,matrix box_pdb,
+ const output_env_t oenv)
{
- rvec *x[2],*xa[2],com={0};
+ rvec *x[2]; /* the coordinates to read */
+ rvec *xa[2]; /* the coordinates to calculate displacements for */
+ rvec com={0};
real t,t_prev=0;
- int natoms,i,j,status,cur=0,maxframes=0;
+ int natoms,i,j,cur=0,maxframes=0;
+ t_trxstatus *status;
#define prev (1-cur)
matrix box;
bool bFirst;
+ gmx_rmpbc_t gpbc=NULL;
natoms = read_first_x(oenv,&status,fn,&curr->t0,&(x[cur]),box);
#ifdef DEBUG
fprintf(stderr,"Read %d atoms for first frame\n",natoms);
#endif
- if (bRmCOMM && natoms < top->atoms.nr) {
+ if ((gnx_com!=NULL) && natoms < top->atoms.nr) {
fprintf(stderr,"WARNING: The trajectory only contains part of the system (%d of %d atoms) and therefore the COM motion of only this part of the system will be removed\n",natoms,top->atoms.nr);
}
t=curr->t0;
if (x_pdb)
*x_pdb = NULL;
- do {
+
+ if (bMol)
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
+ /* the loop over all frames */
+ do
+ {
if (x_pdb && ((bFirst && t_pdb < t) ||
(!bFirst &&
t_pdb > t - 0.5*(t - t_prev) &&
- t_pdb < t + 0.5*(t - t_prev)))) {
- if (*x_pdb == NULL)
- snew(*x_pdb,natoms);
- for(i=0; i<natoms; i++)
- copy_rvec(x[cur][i],(*x_pdb)[i]);
- copy_mat(box,box_pdb);
+ t_pdb < t + 0.5*(t - t_prev))))
+ {
+ if (*x_pdb == NULL)
+ snew(*x_pdb,natoms);
+ for(i=0; i<natoms; i++)
+ copy_rvec(x[cur][i],(*x_pdb)[i]);
+ copy_mat(box,box_pdb);
}
+ /* check whether we've reached a restart point */
if (bRmod(t,curr->t0,dt)) {
curr->nrestart++;
srenew(curr->n_offs,curr->nrestart);
srenew(curr->lsq,curr->nrestart);
snew(curr->lsq[curr->nrestart-1],curr->nmol);
+ for(i=0;i<curr->nmol;i++)
+ curr->lsq[curr->nrestart-1][i] = gmx_stats_init();
+
if (debug)
fprintf(debug,"Extended data structures because of new restart %d\n",
curr->nrestart);
}
+ /* create or extend the frame-based arrays */
if (curr->nframes >= maxframes-1) {
if (maxframes==0) {
for(i=0; (i<curr->ngrp); i++) {
srenew(curr->time,maxframes);
}
+ /* set the time */
curr->time[curr->nframes] = t - curr->t0;
+ /* for the first frame, the previous frame is a copy of the first frame */
if (bFirst) {
memcpy(xa[prev],xa[cur],curr->ncoords*sizeof(xa[prev][0]));
bFirst = FALSE;
}
+ /* make the molecules whole */
if (bMol)
- rm_pbc(&top->idef,ePBC,natoms,box,x[cur],x[cur]);
+ gmx_rmpbc(gpbc,box,x[cur],x[cur]);
+
+ /* first remove the periodic boundary condition crossings */
+ for(i=0;i<curr->ngrp;i++)
+ {
+ prep_data(bMol, gnx[i], index[i], xa[cur], xa[prev], box);
+ }
- if (bRmCOMM)
- remove_pbc(bMol,curr->nmol,natoms,&top->atoms,xa[cur],xa[prev],box,com);
+ /* calculate the center of mass */
+ if (gnx_com)
+ {
+ prep_data(bMol, gnx_com[0], index_com[0], xa[cur], xa[prev], box);
+ calc_com(bMol, gnx_com[0], index_com[0], xa[cur], xa[prev], box,
+ &top->atoms, com);
+ }
+ /* calculate the molecules' centers of masses and put them into xa */
if (bMol)
- calc_mol_com(gnx[0],index[0],&top->mols,&top->atoms,
- x[cur],xa[cur]);
+ calc_mol_com(gnx[0],index[0],&top->mols,&top->atoms, x[cur],xa[cur]);
/* loop over all groups in index file */
- for(i=0; (i<curr->ngrp); i++) {
- /* nice for putting things in boxes and such */
- if (!bRmCOMM)
- prep_data(bMol,gnx[i],index[i],xa[cur],xa[prev],box);
+ for(i=0; (i<curr->ngrp); i++)
+ {
/* calculate something useful, like mean square displacements */
- calc_corr(curr,i,gnx[i],index[i],xa[cur],bRmCOMM,com,calc1,bTen,oenv);
+ calc_corr(curr,i,gnx[i],index[i],xa[cur], (gnx_com!=NULL),com,
+ calc1,bTen,oenv);
}
cur=prev;
t_prev = t;
fprintf(stderr,"\nUsed %d restart points spaced %g %s over %g %s\n\n",
curr->nrestart,
output_env_conv_time(oenv,dt), output_env_get_time_unit(oenv),
- output_env_conv_time(oenv,curr->time[curr->nframes-1]), output_env_get_time_unit(oenv) );
+ output_env_conv_time(oenv,curr->time[curr->nframes-1]),
+ output_env_get_time_unit(oenv) );
+ if (bMol)
+ gmx_rmpbc_done(gpbc);
+
close_trj(status);
return natoms;
real dt,real beginfit,real endfit,const output_env_t oenv)
{
t_corr *msd;
- int *gnx;
- atom_id **index;
- char **grpname;
+ int *gnx; /* the selected groups' sizes */
+ atom_id **index; /* selected groups' indices */
+ char **grpname;
int i,i0,i1,j,N,nat_trx;
real *DD,*SigmaD,a,a2,b,r,chi2;
rvec *x;
matrix box;
-
+ int *gnx_com=NULL; /* the COM removal group size */
+ atom_id **index_com=NULL; /* the COM removal group atom indices */
+ char **grpname_com=NULL; /* the COM removal group name */
+
snew(gnx,nrgrp);
snew(index,nrgrp);
snew(grpname,nrgrp);
-
+
+ fprintf(stderr, "\nSelect a group to calculate mean squared displacement for:\n");
get_index(&top->atoms,ndx_file,nrgrp,gnx,index,grpname);
+ if (bRmCOMM)
+ {
+ snew(gnx_com,1);
+ snew(index_com,1);
+ snew(grpname_com,1);
+
+ fprintf(stderr, "\nNow select a group for center of mass removal:\n");
+ get_index(&top->atoms, ndx_file, 1, gnx_com, index_com, grpname_com);
+ }
+
if (mol_file)
index_atom2mol(&gnx[0],index[0],&top->mols);
nat_trx =
corr_loop(msd,trx_file,top,ePBC,mol_file ? gnx[0] : 0,gnx,index,
(mol_file!=NULL) ? calc1_mol : (bMW ? calc1_mw : calc1_norm),
- bTen,bRmCOMM,dt,t_pdb,pdb_file ? &x : NULL,box,oenv);
-
+ bTen, gnx_com, index_com, dt,t_pdb,
+ pdb_file ? &x : NULL,box,oenv);
+
/* Correct for the number of points */
for(j=0; (j<msd->ngrp); j++) {
for(i=0; (i<msd->nframes); i++) {
lsq_y_ax_b(N,&(msd->time[i0]),&(msd->data[j][i0]),&(DD[j]),&b,&r,&chi2);
DD[j] *= FACTOR/msd->dim_factor;
SigmaD[j] *= FACTOR/msd->dim_factor;
- fprintf(stdout,"D[%10s] %.4f (+/- %.4f) 1e-5 cm^2/s\n",
- grpname[j],DD[j],SigmaD[j]);
+ if (DD[j] > 0.01 && DD[j] < 1e4)
+ fprintf(stdout,"D[%10s] %.4f (+/- %.4f) 1e-5 cm^2/s\n",
+ grpname[j],DD[j],SigmaD[j]);
+ else
+ fprintf(stdout,"D[%10s] %.4g (+/- %.4g) 1e-5 cm^2/s\n",
+ grpname[j],DD[j], SigmaD[j]);
}
}
/* Print mean square displacement */
"types of mean square displacement: [TT]-type[tt], [TT]-lateral[tt]",
"and [TT]-ten[tt]. Option [TT]-ten[tt] writes the full MSD tensor for",
"each group, the order in the output is: trace xx yy zz yx zx zy.[PAR]",
- "Option [TT]-mol[tt] plots the MSD for molecules, this implies",
- "With option [TT]-rmcomm[tt] center of mass motion can be removed.",
- "For trajectories produced with GROMACS this is usually not necessary",
+ "If [TT]-mol[tt] is set, g_msd plots the MSD for individual molecules: ",
+ "for each individual molecule a diffusion constant is computed for ",
+ "its center of mass. The chosen index group will be split into ",
+ "molecules.[PAR]",
+ "The default way to calculate a MSD is by using mass-weighted averages.",
+ "This can be turned off with [TT]-nomw[tt].[PAR]",
+ "With the option [TT]-rmcomm[tt], the center of mass motion of a ",
+ "specific group can be removed. For trajectories produced with ",
+ "GROMACS this is usually not necessary, ",
"as mdrun usually already removes the center of mass motion.",
"When you use this option be sure that the whole system is stored",
"in the trajectory file.[PAR]",
- "[TT]-mw[tt], i.e. for each individual molecule an diffusion constant",
- "is computed for its center of mass. The chosen index group will",
- "be split into molecules.",
"The diffusion coefficient is determined by linear regression of the MSD,",
"where, unlike for the normal output of D, the times are weighted",
"according to the number of reference points, i.e. short times have",
CopyRight(stderr,argv[0]);
parse_common_args(&argc,argv,
- PCA_CAN_VIEW | PCA_CAN_TIME | PCA_TIME_UNIT | PCA_BE_NICE,
+ PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_TIME_UNIT | PCA_BE_NICE,
NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
trx_file = ftp2fn_null(efTRX,NFILE,fnm);
tps_file = ftp2fn_null(efTPS,NFILE,fnm);
tensor3 *m3;
tensor4 *m4;
matrix trans;
+ gmx_rmpbc_t gpbc=NULL;
top = read_top(topfn);
rd_index(molndxfn,1,&gnx,&grpindex,&grpname);
snew(m2,gnx);
snew(m3,gnx);
snew(m4,gnx);
-
+
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
+
/* Start while loop over frames */
do {
/* PvM, bug in rm_pbc??? Does not work for virtual sites ...
- rm_pbc(&(top->idef),top->atoms.nr,box,x,x_s); */
-
+ gmx_rmpbc(gpbc,box,x,x_s); */
/* Begin loop of all molecules in index file */
for(i=0; (i<gnx); i++) {
bCont = read_next_x(status,&t,natoms,x,box);
} while(bCont);
+ gmx_rmpbc_done(gpbc);
+
+
}
};
#define NPA asize(pa)
- int out;
+ t_trxstatus *out;
int status,trjout;
t_topology top;
int ePBC;
#define NPA asize(pa)
- int out;
+ t_trxstatus *out;
t_topology top;
int ePBC;
t_atoms *atoms;
real time,
real *sgmean, real *skmean,
int nslice,int slice_dim,
- real sgslice[],real skslice[])
+ real sgslice[],real skslice[],
+ gmx_rmpbc_t gpbc)
{
FILE *fpoutdist;
char fnsgdist[32];
int m1,mm,sl_index;
int **nnb,*sl_count;
real onethird=1.0/3.0;
-
/* dmat = init_mat(maxidx, FALSE); */
-
box2 = box[XX][XX] * box[XX][XX];
snew(sl_count,nslice);
for (i=0; (i<4); i++) {
/* Must init pbc every step because of pressure coupling */
set_pbc(&pbc,ePBC,box);
- rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+
+ gmx_rmpbc(gpbc,box,x,x);
nsgbin = 1 + 1/0.0005;
snew(sgbin,nsgbin);
t_topology top;
int ePBC;
char title[STRLEN],fn[STRLEN],subtitle[STRLEN];
- int status;
+ t_trxstatus *status;
int natoms;
real t;
rvec *xtop,*x;
char **grpname;
int i,*isize,ng,nframes;
real *sg_slice,*sg_slice_tot,*sk_slice,*sk_slice_tot;
-
+ gmx_rmpbc_t gpbc=NULL;
+
+
read_tps_conf(fnTPS,title,&top,&ePBC,&xtop,NULL,box,FALSE);
snew(sg_slice,nslice);
oenv);
/* loop over frames */
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
nframes = 0;
do {
find_nearest_neighbours(top,ePBC,natoms,box,x,isize[0],index[0],t,
- &sg,&sk,nslice,slice_dim,sg_slice,sk_slice);
+ &sg,&sk,nslice,slice_dim,sg_slice,sk_slice,gpbc);
for(i=0; (i<nslice); i++) {
sg_slice_tot[i] += sg_slice[i];
sk_slice_tot[i] += sk_slice[i];
nframes++;
} while (read_next_x(oenv,status,&t,natoms,x,box));
close_trj(status);
-
+ gmx_rmpbc_done(gpbc);
+
sfree(grpname);
sfree(index);
sfree(isize);
*x1, /* coordinates without pbc */
dist; /* vector between two atoms */
matrix box; /* box (3x3) */
- int status;
+ t_trxstatus *status;
rvec cossum, /* sum of vector angles for three axes */
Sx, Sy, Sz, /* the three molecular axes */
tmp1, tmp2, /* temp. rvecs for calculating dot products */
char *grpname=NULL;
t_pbc pbc;
real arcdist;
+ gmx_rmpbc_t gpbc=NULL;
/* PBC added for center-of-mass vector*/
/* Initiate the pbc structure */
teller = 0;
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
/*********** Start processing trajectory ***********/
do {
if (bSliced)
*slWidth = box[axis][axis]/nslices;
teller++;
- set_pbc(&pbc,ePBC,box);
- rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x1);
+ set_pbc(&pbc,ePBC,box);
+ gmx_rmpbc(gpbc,box,x0,x1);
/* Now loop over all groups. There are ngrps groups, the order parameter can
be calculated for grp 1 to grp ngrps - 1. For each group, loop over all
/*********** done with status file **********/
fprintf(stderr,"\nRead trajectory. Printing parameters to file\n");
-
+ gmx_rmpbc_done(gpbc);
+
/* average over frames */
for (i = 1; i < ngrps - 1; i++) {
svmul(1.0/nr_frames, (*order)[i], (*order)[i]);
{
/*function to write order parameters as B factors in PDB file using
first frame of trajectory*/
- int status;
+ t_trxstatus *status;
int natoms;
t_trxframe fr, frout;
t_atoms useatoms;
"gyration tensors are written.",
"With option [TT]-i[tt] the mean square internal distances are",
"written.[PAR]",
- "With option [TT]-p[tt] the presistence length is determined.",
+ "With option [TT]-p[tt] the persistence length is determined.",
"The chosen index group should consist of atoms that are",
"consecutively bonded in the polymer mainchains.",
- "The presistence length is then determined from the cosine of",
+ "The persistence length is then determined from the cosine of",
"the angles between bonds with an index difference that is even,",
"the odd pairs are not used, because straight polymer backbones",
"are usually all trans and therefore only every second bond aligns.",
int ePBC;
int isize,*index,nmol,*molind,mol,nat_min=0,nat_max=0;
char *grpname;
- int status;
+ t_trxstatus *status;
real t;
rvec *x,*bond=NULL;
matrix box;
"<R\\sg\\N> eig1", "<R\\sg\\N> eig2", "<R\\sg\\N> eig3",
"<R\\sg\\N eig1>", "<R\\sg\\N eig2>", "<R\\sg\\N eig3>" };
char **legp,buf[STRLEN];
+ gmx_rmpbc_t gpbc=NULL;
CopyRight(stderr,argv[0]);
parse_common_args(&argc,argv,
sum_eed2_tot = 0;
sum_gyro_tot = 0;
sum_pers_tot = 0;
+
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
do {
- rm_pbc(&(top->idef),ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
sum_eed2 = 0;
for(d=0; d<DIM; d++)
frame++;
} while (read_next_x(oenv,status,&t,natoms,x,box));
+
+ gmx_rmpbc_done(gpbc);
close_trx(status);
{
rvec *x0; /* coordinates without pbc */
matrix box; /* box (3x3) */
- int natoms, /* nr. atoms in trj */
- status,
- **slCount, /* nr. of atoms in one slice for a group */
+ int natoms; /* nr. atoms in trj */
+ t_trxstatus *status;
+ int **slCount, /* nr. of atoms in one slice for a group */
i,j,n, /* loop indices */
teller = 0,
ax1=0, ax2=0,
real t;
double z;
rvec xcm;
-
+ gmx_rmpbc_t gpbc=NULL;
+
switch(axis)
{
case 0:
snew((*slPotential)[i], *nslices);
}
+
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
+
/*********** Start processing trajectory ***********/
do
{
*slWidth = box[axis][axis]/(*nslices);
teller++;
-
- rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x0);
+ gmx_rmpbc(gpbc,box,x0,x0);
/* calculate position of center of mass based on group 1 */
calc_xcm(x0, gnx[0], index[0], top->atoms.atom, xcm, FALSE);
nr_frames++;
} while (read_next_x(oenv,status,&t,natoms,x0,box));
+ gmx_rmpbc_done(gpbc);
+
/*********** done with status file **********/
close_trj(status);
int gmx_potential(int argc,char *argv[])
{
const char *desc[] = {
- "Compute the electrostatical potential across the box. The potential is"
- "calculated by first summing the charges per slice and then integrating"
- "twice of this charge distribution. Periodic boundaries are not taken "
- "into account. Reference of potential is taken to be the left side of"
- "the box. It's also possible to calculate the potential in spherical"
- "coordinates as function of r by calculating a charge distribution in"
- "spherical slices and twice integrating them. epsilon_r is taken as 1,"
- "2 is more appropriate in many cases"
+ "Compute the electrostatical potential across the box. The potential is",
+ "calculated by first summing the charges per slice and then integrating",
+ "twice of this charge distribution. Periodic boundaries are not taken",
+ "into account. Reference of potential is taken to be the left side of",
+ "the box. It's also possible to calculate the potential in spherical",
+ "coordinates as function of r by calculating a charge distribution in",
+ "spherical slices and twice integrating them. epsilon_r is taken as 1,",
+ "2 is more appropriate in many cases."
};
output_env_t oenv;
static int axis = 2; /* normal to memb. default z */
t_pargs pa[] = {
{ "-foo", FALSE, etBOOL, {&foo}, "Dummy option to avoid empty array" }
};
- int status;
+ t_trxstatus *status;
t_topology top;
int ePBC;
real t;
FILE * fmoi;
matrix axes,box;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
+
t_filenm fnm[] = {
{ efTRX, "-f", NULL, ffREAD },
natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
+
do
{
- rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
+
calc_principal_axes(&top,x,index,gnx,axes,moi);
fprintf(axis1,"%15.10f %15.10f %15.10f %15.10f\n",t,axes[XX][XX],axes[YY][XX],axes[ZZ][XX]);
}
while(read_next_x(oenv,status,&t,natoms,x,box));
+ gmx_rmpbc_done(gpbc);
+
+
close_trj(status);
ffclose(axis1);
ffclose(axis2);
#include "physics.h"
#include "index.h"
#include "smalloc.h"
-#include "fftgrid.h"
#include "calcgrid.h"
#include "nrnb.h"
#include "coulomb.h"
#include "matio.h"
#include "gmx_ana.h"
#include "names.h"
+#include "sfactor.h"
-typedef struct
-{
- const char *label;
- int elem,mass;
- real a[4], b[4], c;
-} t_CM_table;
-
-/*
- *
- * f0[k] = c + [SUM a_i*EXP(-b_i*(k^2)) ]
- * i=1,4
- */
-
-const t_CM_table CM_t[] =
-{
-
- { "H", 1, 1, { 0.489918, 0.262003, 0.196767, 0.049879 },
- { 20.6593, 7.74039, 49.5519, 2.20159 },
- 0.001305 },
- { "C", 6, 12, { 2.26069, 1.56165, 1.05075, 0.839259 },
- { 22.6907, 0.656665, 9.75618, 55.5949 },
- 0.286977 },
- { "N", 7, 14, { 12.2126, 3.13220, 2.01250, 1.16630 },
- { 0.005700, 9.89330, 28.9975, 0.582600 },
- -11.529 },
- { "O", 8, 16, { 3.04850, 2.28680, 1.54630, 0.867000 },
- { 13.2771, 5.70110, 0.323900, 32.9089 },
- 0.250800 },
- { "Na", 11, 23, { 3.25650, 3.93620, 1.39980, 1.00320 }, /* Na 1+ */
- { 2.66710, 6.11530, 0.200100, 14.0390 },
- 0.404000 }
-};
-
-#define NCMT asize(CM_t)
-
-typedef struct
-{
- int n_angles;
- int n_groups;
- double lambda;
- double energy;
- double momentum;
- double ref_k;
- double **F;
- int nSteps;
- int total_n_atoms;
-} structure_factor;
-
-typedef struct
-{
- rvec x;
- int t;
-} reduced_atom;
-
static void check_box_c(matrix box)
{
if (fabs(box[ZZ][XX]) > GMX_REAL_EPS*box[ZZ][ZZ] ||
const output_env_t oenv)
{
FILE *fp;
- int status;
+ t_trxstatus *status;
char outf1[STRLEN],outf2[STRLEN];
char title[STRLEN],gtitle[STRLEN],refgt[30];
int g,natoms,i,ii,j,k,nbin,j0,j1,n,nframes;
t_blocka *excl;
t_atom *atom=NULL;
t_pbc pbc;
-
+ gmx_rmpbc_t gpbc=NULL;
int *is=NULL,**coi=NULL,cur,mol,i1,res,a;
excl=NULL;
snew(x_i1,max_i);
nframes = 0;
invvol_sum = 0;
+ if (bPBC && (NULL != top))
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
do {
/* Must init pbc every step because of pressure coupling */
copy_mat(box,box_pbc);
if (bPBC) {
if (top != NULL)
- rm_pbc(&top->idef,ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
if (bXY) {
check_box_c(box);
clear_rvec(box_pbc[ZZ]);
} while (read_next_x(oenv,status,&t,natoms,x,box));
fprintf(stderr,"\n");
+ if (bPBC && (NULL != top))
+ gmx_rmpbc_done(gpbc);
+
close_trj(status);
sfree(x);
sfree(rdf);
}
-t_complex *** rc_tensor_allocation(int x, int y, int z)
-{
- t_complex ***t;
- int i,j;
-
- snew(t,x);
- t = (t_complex ***)calloc(x,sizeof(t_complex**));
- if(!t) exit(fprintf(stderr,"\nallocation error"));
- t[0] = (t_complex **)calloc(x*y,sizeof(t_complex*));
- if(!t[0]) exit(fprintf(stderr,"\nallocation error"));
- t[0][0] = (t_complex *)calloc(x*y*z,sizeof(t_complex));
- if(!t[0][0]) exit(fprintf(stderr,"\nallocation error"));
-
- for( j = 1 ; j < y ; j++)
- t[0][j] = t[0][j-1] + z;
- for( i = 1 ; i < x ; i++) {
- t[i] = t[i-1] + y;
- t[i][0] = t[i-1][0] + y*z;
- for( j = 1 ; j < y ; j++)
- t[i][j] = t[i][j-1] + z;
- }
- return t;
-}
-
-int return_atom_type (const char *name)
-{
- typedef struct {
- const char *name;
- int nh;
- } t_united_h;
- t_united_h uh[] = {
- { "CH1", 1 }, { "CH2", 2 }, { "CH3", 3 },
- { "CS1", 1 }, { "CS2", 2 }, { "CS3", 3 },
- { "CP1", 1 }, { "CP2", 2 }, { "CP3", 3 }
- };
- int i;
-
- for(i=0; (i<asize(uh)); i++)
- if (strcmp(name,uh[i].name) == 0)
- return NCMT-1+uh[i].nh;
-
- for(i=0; (i<NCMT); i++)
- if (strncmp (name, CM_t[i].label,strlen(CM_t[i].label)) == 0)
- return i;
- gmx_fatal(FARGS,"\nError: atom (%s) not in list (%d types checked)!\n",
- name,i);
-
- return 0;
-}
-
-double CMSF (int type,int nh,double lambda, double sin_theta)
-/*
- * return Cromer-Mann fit for the atomic scattering factor:
- * sin_theta is the sine of half the angle between incoming and scattered
- * vectors. See g_sq.h for a short description of CM fit.
- */
-{
- int i;
- double tmp = 0.0, k2;
-
- /*
- * united atoms case
- * CH2 / CH3 groups
- */
- if (nh > 0) {
- tmp = (CMSF (return_atom_type ("C"),0,lambda, sin_theta) +
- nh*CMSF (return_atom_type ("H"),0,lambda, sin_theta));
- }
- /* all atom case */
- else {
- k2 = (sqr (sin_theta) / sqr (10.0 * lambda));
- tmp = CM_t[type].c;
- for (i = 0; (i < 4); i++)
- tmp += CM_t[type].a[i] * exp (-CM_t[type].b[i] * k2);
- }
- return tmp;
-}
-
-real **compute_scattering_factor_table (structure_factor * sf,int *nsftable)
-{
-/*
- * this function build up a table of scattering factors for every atom
- * type and for every scattering angle.
- */
- int i, j;
- double sin_theta,q,hc=1239.842;
- real ** sf_table;
-
- /* \hbar \omega \lambda = hc = 1239.842 eV * nm */
- sf->momentum = ((double) (2. * 1000.0 * M_PI * sf->energy) / hc);
- sf->lambda = hc / (1000.0 * sf->energy);
- fprintf (stderr, "\nwavelenght = %f nm\n", sf->lambda);
- *nsftable = NCMT+3;
- snew (sf_table,*nsftable);
- for (i = 0; (i < *nsftable); i++) {
- snew (sf_table[i], sf->n_angles);
- for (j = 0; j < sf->n_angles; j++) {
- q = ((double) j * sf->ref_k);
- /* theta is half the angle between incoming
- and scattered wavevectors. */
- sin_theta = q / (2.0 * sf->momentum);
- if (i < NCMT)
- sf_table[i][j] = CMSF (i,0,sf->lambda, sin_theta);
- else
- sf_table[i][j] = CMSF (i,i-NCMT+1,sf->lambda, sin_theta);
- }
- }
- return sf_table;
-}
-
-int * create_indexed_atom_type (reduced_atom * atm, int size)
-{
-/*
- * create an index of the atom types found in a group
- * i.e.: for water index_atp[0]=type_number_of_O and
- * index_atp[1]=type_number_of_H
- *
- * the last element is set to 0
- */
- int *index_atp, i, i_tmp, j;
-
- snew (index_atp, 1);
- i_tmp = 1;
- index_atp[0] = atm[0].t;
- for (i = 1; i < size; i++) {
- for (j = 0; j < i_tmp; j++)
- if (atm[i].t == index_atp[j])
- break;
- if (j == i_tmp) { /* i.e. no indexed atom type is == to atm[i].t */
- i_tmp++;
- srenew (index_atp, i_tmp * sizeof (int));
- index_atp[i_tmp - 1] = atm[i].t;
- }
- }
- i_tmp++;
- srenew (index_atp, i_tmp * sizeof (int));
- index_atp[i_tmp - 1] = 0;
- return index_atp;
-}
-
-void rearrange_atoms (reduced_atom * positions, t_trxframe *fr, atom_id * index,
- int isize, t_topology * top, bool flag)
-/* given the group's index, return the (continuous) array of atoms */
-{
- int i;
-
- if (flag)
- for (i = 0; i < isize; i++)
- positions[i].t =
- return_atom_type (*(top->atoms.atomname[index[i]]));
- for (i = 0; i < isize; i++)
- copy_rvec (fr->x[index[i]], positions[i].x);
-}
-
-
-int atp_size (int *index_atp)
-{
- int i = 0;
-
- while (index_atp[i])
- i++;
- return i;
-}
-
-void compute_structure_factor (structure_factor * sf, matrix box,
- reduced_atom * red, int isize, real start_q,
- real end_q, int group,real **sf_table)
-{
- t_complex ***tmpSF;
- rvec k_factor;
- real kdotx, asf, kx, ky, kz, krr;
- int kr, maxkx, maxky, maxkz, i, j, k, p, *counter;
-
-
- k_factor[XX] = 2 * M_PI / box[XX][XX];
- k_factor[YY] = 2 * M_PI / box[YY][YY];
- k_factor[ZZ] = 2 * M_PI / box[ZZ][ZZ];
-
- maxkx = (int) (end_q / k_factor[XX] + 0.5);
- maxky = (int) (end_q / k_factor[YY] + 0.5);
- maxkz = (int) (end_q / k_factor[ZZ] + 0.5);
-
- snew (counter, sf->n_angles);
-
- tmpSF = rc_tensor_allocation(maxkx,maxky,maxkz);
-/*
- * The big loop...
- * compute real and imaginary part of the structure factor for every
- * (kx,ky,kz))
- */
- fprintf(stderr,"\n");
- for (i = 0; i < maxkx; i++) {
- fprintf (stderr,"\rdone %3.1f%% ", (double)(100.0*(i+1))/maxkx);
- kx = i * k_factor[XX];
- for (j = 0; j < maxky; j++) {
- ky = j * k_factor[YY];
- for (k = 0; k < maxkz; k++)
- if (i != 0 || j != 0 || k != 0) {
- kz = k * k_factor[ZZ];
- krr = sqrt (sqr (kx) + sqr (ky) + sqr (kz));
- if (krr >= start_q && krr <= end_q) {
- kr = (int) (krr/sf->ref_k + 0.5);
- if (kr < sf->n_angles) {
- counter[kr]++; /* will be used for the copmutation
- of the average*/
- for (p = 0; p < isize; p++) {
-
- asf = sf_table[red[p].t][kr];
-
- kdotx = kx * red[p].x[XX] +
- ky * red[p].x[YY] + kz * red[p].x[ZZ];
-
- tmpSF[i][j][k].re += cos (kdotx) * asf;
- tmpSF[i][j][k].im += sin (kdotx) * asf;
- }
- }
- }
- }
- }
- } /* end loop on i */
-/*
- * compute the square modulus of the structure factor, averaging on the surface
- * kx*kx + ky*ky + kz*kz = krr*krr
- * note that this is correct only for a (on the macroscopic scale)
- * isotropic system.
- */
- for (i = 0; i < maxkx; i++) {
- kx = i * k_factor[XX]; for (j = 0; j < maxky; j++) {
- ky = j * k_factor[YY]; for (k = 0; k < maxkz; k++) {
- kz = k * k_factor[ZZ]; krr = sqrt (sqr (kx) + sqr (ky)
- + sqr (kz)); if (krr >= start_q && krr <= end_q) {
- kr = (int) (krr / sf->ref_k + 0.5);
- if (kr < sf->n_angles && counter[kr] != 0)
- sf->F[group][kr] +=
- (sqr (tmpSF[i][j][k].re) +
- sqr (tmpSF[i][j][k].im))/ counter[kr];
- }
- }
- }
- } sfree (counter); free(tmpSF[0][0]); free(tmpSF[0]); free(tmpSF);
-}
-
-void save_data (structure_factor * sf, const char *file, int ngrps,
- real start_q, real end_q, const output_env_t oenv)
-{
-
- FILE *fp;
- int i, g = 0;
- double *tmp, polarization_factor, A;
-
- fp = xvgropen (file, "Scattering Intensity", "q (1/nm)",
- "Intensity (a.u.)",oenv);
-
- snew (tmp, ngrps);
-
- for (g = 0; g < ngrps; g++)
- for (i = 0; i < sf->n_angles; i++) {
-/*
- * theta is half the angle between incoming and scattered vectors.
- *
- * polar. fact. = 0.5*(1+cos^2(2*theta)) = 1 - 0.5 * sin^2(2*theta)
- *
- * sin(theta) = q/(2k) := A -> sin^2(theta) = 4*A^2 (1-A^2) ->
- * -> 0.5*(1+cos^2(2*theta)) = 1 - 2 A^2 (1-A^2)
- */
- A = (double) (i * sf->ref_k) / (2.0 * sf->momentum);
- polarization_factor = 1 - 2.0 * sqr (A) * (1 - sqr (A));
- sf->F[g][i] *= polarization_factor;
- }
- for (i = 0; i < sf->n_angles; i++) {
- if (i * sf->ref_k >= start_q && i * sf->ref_k <= end_q) {
- fprintf (fp, "%10.5f ", i * sf->ref_k);
- for (g = 0; g < ngrps; g++)
- fprintf (fp, " %10.5f ", (sf->F[g][i]) /( sf->total_n_atoms*
- sf->nSteps));
- fprintf (fp, "\n");
- }
- }
- ffclose (fp);
-}
-
-int do_scattering_intensity (const char* fnTPS, const char* fnNDX,
- const char* fnXVG, const char *fnTRX,
- real start_q,real end_q,
- real energy,int ng,const output_env_t oenv)
-{
- int i,*isize,status,flags = TRX_READ_X,**index_atp;
- char **grpname,title[STRLEN];
- atom_id **index;
- t_topology top;
- int ePBC;
- t_trxframe fr;
- reduced_atom **red;
- structure_factor *sf;
- rvec *xtop;
- real **sf_table;
- int nsftable;
- matrix box;
- double r_tmp;
-
- snew (sf, 1);
- sf->energy = energy;
-
- /* Read the topology informations */
- read_tps_conf (fnTPS, title, &top, &ePBC, &xtop, NULL, box, TRUE);
- sfree (xtop);
-
- /* groups stuff... */
- snew (isize, ng);
- snew (index, ng);
- snew (grpname, ng);
-
- fprintf (stderr, "\nSelect %d group%s\n", ng,
- ng == 1 ? "" : "s");
- if (fnTPS)
- get_index (&top.atoms, fnNDX, ng, isize, index, grpname);
- else
- rd_index (fnNDX, ng, isize, index, grpname);
-
- /* The first time we read data is a little special */
- read_first_frame (oenv,&status, fnTRX, &fr, flags);
-
- sf->total_n_atoms = fr.natoms;
-
- snew (red, ng);
- snew (index_atp, ng);
-
- r_tmp = max (box[XX][XX], box[YY][YY]);
- r_tmp = (double) max (box[ZZ][ZZ], r_tmp);
-
- sf->ref_k = (2.0 * M_PI) / (r_tmp);
- /* ref_k will be the reference momentum unit */
- sf->n_angles = (int) (end_q / sf->ref_k + 0.5);
-
- snew (sf->F, ng);
- for (i = 0; i < ng; i++)
- snew (sf->F[i], sf->n_angles);
- for (i = 0; i < ng; i++) {
- snew (red[i], isize[i]);
- rearrange_atoms (red[i], &fr, index[i], isize[i], &top, TRUE);
- index_atp[i] = create_indexed_atom_type (red[i], isize[i]);
- }
- sf_table = compute_scattering_factor_table (sf,&nsftable);
- /* This is the main loop over frames */
-
- do {
- sf->nSteps++;
- for (i = 0; i < ng; i++) {
- rearrange_atoms (red[i], &fr, index[i], isize[i], &top,FALSE);
-
- compute_structure_factor (sf, box, red[i], isize[i],
- start_q, end_q, i, sf_table);
- }
- }
- while (read_next_frame (oenv,status, &fr));
-
- save_data (sf, fnXVG, ng, start_q, end_q,oenv);
-
- return 0;
-}
int gmx_rdf(int argc,char *argv[])
{
"or to the closest particle in a set ([TT]-surf[tt]).",
"With all methods rdf's can also be calculated around axes parallel",
"to the z-axis with option [TT]-xy[tt].",
- "With option [TT]-surf[tt] normalization can not be used.[PAR]"
+ "With option [TT]-surf[tt] normalization can not be used.[PAR]",
"The option [TT]-rdf[tt] sets the type of rdf to be computed.",
"Default is for atoms or particles, but one can also select center",
"of mass or geometry of molecules or residues. In all cases only",
"Option [TT]-cn[tt] produces the cumulative number rdf,",
"i.e. the average number of particles within a distance r.[PAR]",
"To bridge the gap between theory and experiment structure factors can",
- "be computed (option [TT]-sq[tt]). The algorithm uses FFT, the grid"
+ "be computed (option [TT]-sq[tt]). The algorithm uses FFT, the grid",
"spacing of which is determined by option [TT]-grid[tt]."
};
static bool bCM=FALSE,bXY=FALSE,bPBC=TRUE,bNormalize=TRUE;
"Energy of the incoming X-ray (keV) "}
};
#define NPA asize(pa)
- const char *fnTPS,*fnNDX;
+ const char *fnTPS,*fnNDX,*fnDAT=NULL;
bool bSQ,bRDF;
output_env_t oenv;
{ efTRX, "-f", NULL, ffREAD },
{ efTPS, NULL, NULL, ffOPTRD },
{ efNDX, NULL, NULL, ffOPTRD },
+ { efDAT, "-d", "sfactor", ffOPTRD },
{ efXVG, "-o", "rdf", ffOPTWR },
{ efXVG, "-sq", "sq", ffOPTWR },
{ efXVG, "-cn", "rdf_cn", ffOPTWR },
bRDF = opt2bSet("-o",NFILE,fnm) || !bSQ;
if (bSQ || bCM || closet[0][0]!='n' || rdft[0][0]=='m' || rdft[0][6]=='m') {
fnTPS = ftp2fn(efTPS,NFILE,fnm);
+ fnDAT = ftp2fn(efDAT,NFILE,fnm);
} else {
fnTPS = ftp2fn_null(efTPS,NFILE,fnm);
}
if (bSQ)
do_scattering_intensity(fnTPS,fnNDX,opt2fn("-sq",NFILE,fnm),
- ftp2fn(efTRX,NFILE,fnm),
+ ftp2fn(efTRX,NFILE,fnm),fnDAT,
start_q, end_q, energy, ngroups,oenv);
if (bRDF)
rvec **corr;
real **Corr;
t_sij *spec;
+ gmx_rmpbc_t gpbc=NULL;
snew(spec,npair);
natoms = read_first_x(&status,trj,&t0,&x,box);
if (natoms > nat)
gmx_fatal(FARGS,"Not enough atoms in trajectory");
+ gpbc = gmx_rmpbc_init(idef,ePBC,natoms,box);
+
do {
if (nframes >= maxframes) {
fprintf(stderr,"\nThere are more than the %d frames you told me!",
t1 = t;
if (bVerbose)
fprintf(stderr,"\rframe: %d",nframes);
- rm_pbc(idef,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
if (bFit)
do_fit(natoms,w_rls,xp,x);
if (bVerbose)
fprintf(stderr,"\n");
+ gmx_rmpbc_done(gpbc);
+
fp=ffopen("ylm.out","w");
calc_aver(fp,nframes,npair,pair,spec,maxdist);
ffclose(fp);
matrix box;
rvec *x, *xp, *xm = NULL, **mat_x = NULL, **mat_x2, *mat_x2_j = NULL, vec1,
vec2;
- int status;
+ t_trxstatus *status;
char buf[256], buf2[256];
int ncons = 0;
FILE *fp;
char *gn_fit, **gn_rms;
t_rgb rlo, rhi;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
+
t_filenm fnm[] =
{
{ efTPS, NULL, NULL, ffREAD },
}
}
/* Prepare reference frame */
- if (bPBC)
- rm_pbc(&(top.idef),ePBC,top.atoms.nr,box,xp,xp);
+ if (bPBC) {
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box);
+ gmx_rmpbc(gpbc,box,xp,xp);
+ }
if (bReset)
reset_x(ifit,ind_fit,top.atoms.nr,NULL,xp,w_rls);
if (bMirror) {
teller = 0;
do {
if (bPBC)
- rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
if (bReset)
reset_x(ifit,ind_fit,natoms,NULL,x,w_rls);
teller2 = 0;
do {
if (bPBC)
- rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
if (bReset)
reset_x(ifit,ind_fit,natoms,NULL,x,w_rls);
tel_mat2=tel_mat;
freq2=freq;
}
+ gmx_rmpbc_done(gpbc);
if (bMat || bBond) {
/* calculate RMS matrix */
rvec *x;
FILE *fp;
- int status,isize,gnr=0;
+ t_trxstatus *status;
+ int isize,gnr=0;
atom_id *index, *noe_index;
char *grpname;
real **d_r,**d,**dtot,**dtot2,**mean,**rms,**rmsc,*resnr;
static int nlevels=40;
static real scalemax=-1.0;
static bool bSumH=TRUE;
-
+ static bool bPBC=TRUE;
output_env_t oenv;
t_pargs pa[] = {
{ "-max", FALSE, etREAL, {&scalemax},
"Maximum level in matrices" },
{ "-sumh", FALSE, etBOOL, {&bSumH},
- "average distance over equivalent hydrogens" }
+ "average distance over equivalent hydrogens" },
+ { "-pbc", FALSE, etBOOL, {&bPBC},
+ "Use periodic boundary conditions when computing distances" }
};
t_filenm fnm[] = {
{ efTRX, "-f", NULL, ffREAD },
/* get topology and index */
read_tps_conf(ftp2fn(efTPS,NFILE,fnm),buf,&top,&ePBC,&x,NULL,box,FALSE);
+
+ if (!bPBC)
+ ePBC = epbcNONE;
atoms=&(top.atoms);
get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
ffclose(fp);
close_trj(status);
- teller = nframes_read();
+ teller = nframes_read(status);
calc_rms(isize,teller,dtot,dtot2,mean,&meanmax,rms,&rmsmax,rmsc,&rmscmax);
fprintf(stderr,"rmsmax = %g, rmscmax = %g\n",rmsmax,rmscmax);
{ "-fit", FALSE, etBOOL, {&bFit},
"Do a least squares superposition before computing RMSF. Without this you must make sure that the reference structure and the trajectory match." }
};
- int step,nre,natom,natoms,i,g,m,teller=0;
+ int natom=0;
+ int step,nre,natoms,i,g,m,teller=0;
real t,lambda,*w_rls,*w_rms;
t_tpxheader header;
matrix box,pdbbox;
rvec *x,*pdbx,*xref;
- int status,npdbatoms,res0;
+ t_trxstatus *status;
+ int npdbatoms,res0;
char buf[256];
const char *label;
char title[STRLEN];
int d;
real count=0;
rvec xcm;
+ gmx_rmpbc_t gpbc=NULL;
output_env_t oenv;
copy_mat(box,pdbbox);
}
- if (bFit)
+ if (bFit) {
sub_xcm(xref,isize,index,top.atoms.atom,xcm,FALSE);
-
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natom,box);
+ }
+
natom = read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
/* Now read the trj again to compute fluctuations */
do {
if (bFit) {
/* Remove periodic boundary */
- rm_pbc(&(top.idef),ePBC,natom,box,x,x);
-
+ gmx_rmpbc(gpbc,box,x,x);
+
/* Set center of mass to zero */
sub_xcm(x,isize,index,top.atoms.atom,xcm,FALSE);
} while(read_next_x(oenv,status,&t,natom,x,box));
close_trj(status);
+ if (bFit)
+ gmx_rmpbc_done(gpbc);
+
+
invcount = 1.0/count;
snew(Uaver,DIM*DIM);
totmass = 0;
"This will calculate the rotational correlation function using a first",
"order Legendre polynomial of the angle of a vector defined by the index",
"file. The correlation function will be fitted from 2.5 ps till 20.0 ps",
- "to a two parameter exponential",
+ "to a two parameter exponential.",
""
"Average over molecules" }
};
- int status,isize;
+ t_trxstatus *status;
+ int isize;
atom_id *index;
char *grpname;
rvec *x,*x_s;
int i,m,teller,n_alloc,natoms,nvec,ai,aj,ak;
unsigned long mode;
real t,t0,t1,dt;
+ gmx_rmpbc_t gpbc=NULL;
t_topology *top;
int ePBC;
t_filenm fnm[] = {
natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
snew(x_s,natoms);
+ gpbc = gmx_rmpbc_init(&(top->idef),ePBC,natoms,box);
+
/* Start the loop over frames */
t1 = t0 = t;
teller = 0;
t1 = t;
/* Remove periodicity */
- rm_pbc(&(top->idef),ePBC,natoms,box,x,x_s);
-
+ gmx_rmpbc(gpbc,box,x,x_s);
+
/* Compute crossproducts for all vectors, if triplets.
* else, just get the vectors in case of doublets.
*/
close_trj(status);
fprintf(stderr,"\nDone with trajectory\n");
+ gmx_rmpbc_done(gpbc);
+
+
/* Autocorrelation function */
if (teller < 2)
fprintf(stderr,"Not enough frames for correlation function\n");
bool bMW,t_topology *top,int ePBC,rvec *x_ref)
{
int natoms,nfr_all,nfr,i,j,a,r,c,min_fr;
- int status;
+ t_trxstatus *status;
real *ti,min_t;
double tot_mass,msd,*srmsd,min_srmsd,srmsd_tot;
rvec *x,**xi;
real xf;
matrix box,R;
real *w_rls;
+ gmx_rmpbc_t gpbc=NULL;
+
nfr_all = 0;
nfr = 0;
w_rls[a] = (bMW ? top->atoms.atom[index[a]].m : 1.0);
tot_mass += w_rls[a];
}
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
do
{
if (nfr_all % skip == 0)
{
- rm_pbc(&top->idef,ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
snew(xi[nfr],gnx);
for(i=0; i<gnx; i++)
{
close_trj(status);
sfree(x);
+ gmx_rmpbc_done(gpbc);
+
snew(srmsd,nfr);
for(i=0; i<nfr; i++)
{
"Use mass weighted fitting" }
};
FILE *out;
- int status;
+ t_trxstatus *status;
t_topology top;
int ePBC;
rvec *x_ref,*x;
int natoms,i;
char *grpname,title[256];
int gnx;
+ gmx_rmpbc_t gpbc=NULL;
atom_id *index;
output_env_t oenv;
real *w_rls;
read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x_ref,NULL,box,bMW);
- rm_pbc(&top.idef,ePBC,top.atoms.nr,box,x_ref,x_ref);
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box);
+
+ gmx_rmpbc(gpbc,box,x_ref,x_ref);
+
get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&gnx,&index,&grpname);
if (reffit[0][0] != 'n')
do
{
- rm_pbc(&top.idef,ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
reset_x(gnx,index,natoms,NULL,x,w_rls);
}
while(read_next_x(oenv,status,&t,natoms,x,box));
+ gmx_rmpbc_done(gpbc);
+
close_trj(status);
ffclose(out);
cg[ncg].cg=i;
anr=cgs->index[i];
resnr=atoms->atom[anr].resind;
- sprintf(buf,"%s%d",
+ sprintf(buf,"%s%d-%d",
*(atoms->resinfo[resnr].name),
- atoms->resinfo[resnr].nr);
+ atoms->resinfo[resnr].nr,
+ anr+1);
cg[ncg].label=strdup(buf);
ncg++;
}
{
const char *desc[] = {
"g_saltbr plots the distance between all combination of charged groups",
- "as a function of time. The groups are combined in different ways."
+ "as a function of time. The groups are combined in different ways.",
"A minimum distance can be given, (eg. the cut-off), then groups",
"that are never closer than that distance will not be plotted.[BR]",
"Output will be in a number of fixed filenames, min-min.xvg, plus-min.xvg",
- "and plus-plus.xvg, or files for every individual ion-pair if selected"
+ "and plus-plus.xvg, or files for every individual ion-pair if the [TT]-sep[tt]",
+ "option is selected. In this case files are named as [TT]sb-ResnameResnr-Atomnr[tt].",
+ "There may be many such files."
};
static bool bSep=FALSE;
static real truncate=1000.0;
t_topology *top;
int ePBC;
char *buf;
- int status,i,j,k,m,nnn,teller,ncg,n1,n2,n3,natoms;
+ t_trxstatus *status;
+ int i,j,k,m,nnn,teller,ncg,n1,n2,n3,natoms;
real t,*time,qi,qj;
t_charge *cg;
real ***cgdist;
const char *vfile;
real t;
gmx_atomprop_t aps=NULL;
- int status,ndefault;
+ gmx_rmpbc_t gpbc=NULL;
+ t_trxstatus *status;
+ int ndefault;
int i,j,ii,nfr,natoms,flag,nsurfacedots,res;
rvec *xtop,*x;
matrix topbox,box;
gmx_atomprop_destroy(aps);
+ if (bPBC)
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
+
nfr=0;
do {
if (bPBC)
- rm_pbc(&top.idef,ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
bConnelly = (nfr==0 && opt2bSet("-q",nfile,fnm));
if (bConnelly) {
}
nfr++;
} while (read_next_x(oenv,status,&t,natoms,x,box));
-
+
+ if (bPBC)
+ gmx_rmpbc_done(gpbc);
+
fprintf(stderr,"\n");
close_trj(status);
ffclose(fp);
rvec dtri, const output_env_t oenv)
{
FILE *fp;
- int status;
+ t_trxstatus *status;
int ng,natoms,i,j,k,l,X,Y,Z,lc,dest;
ivec nbin;
int ***count;
real delta;
atom_id ix,jx;
t_topology top;
+ gmx_rmpbc_t gpbc=NULL;
int ePBC=-1;
t_pbc pbc;
bool bTop=FALSE,bRefDone=FALSE,bInGroup=FALSE;
normfac = 0;
-
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
+
do {
/* Must init pbc every step because of pressure coupling */
set_pbc(&pbc,ePBC,box);
- rm_pbc(&top.idef,ePBC,natoms,box,x,x);
-
-
- /* Dynamically build the ref tripels */
+ gmx_rmpbc(gpbc,box,x,x);
+
+ /* Dynamically build the ref triples */
if ( mode == 2 )
{
isize[NDX_REF1]=0;
} while (read_next_x(oenv,status,&t,natoms,x,box));
fprintf(stderr,"\n");
+ gmx_rmpbc_done(gpbc);
+
+
close_trj(status);
sfree(x);
/* Calculate the mean probability density */
- fprintf(stderr,"\nNumber of configuations used for SDF: %d\n",(int)normfac);
+ fprintf(stderr,"\nNumber of configurations used for SDF: %d\n",(int)normfac);
normfac = nbin[0]*nbin[1]*nbin[2] / normfac;
"file to work. ",
"You have to setup 4 groups in the index file before using g_sdf: [PAR]",
"The first three groups are used to define the SDF coordinate system.",
- "The programm will dynamically generate the atom tripels according to ",
+ "The program will dynamically generate the atom triples according to ",
"the selected -mode: ",
"In -mode 1 the triples will be just the 1st, 2nd, 3rd, ... atoms from ",
"groups 1, 2 and 3. Hence the nth entries in groups 1, 2 and 3 must be from the",
"meeting the further conditions. The triple will only be used if all three atoms",
"have different res-id's.[PAR]",
"The local coordinate system is always defined using the following scheme:",
- "Atom 1 will be used as the point of origin for the SDF. "
+ "Atom 1 will be used as the point of origin for the SDF. ",
"Atom 1 and 2 will define the principle axis (Z) of the coordinate system.",
"The other two axis will be defined inplane (Y) and normal (X) to the plane through",
- "Atoms 1, 2 and 3. "
+ "Atoms 1, 2 and 3. ",
"The fourth group",
"contains the atoms for which the SDF will be evaluated.[PAR]",
"For -mode 2 and 3 you have to define the distance conditions for the ",
"The SDF will be sampled in cartesian coordinates.",
"Use '-grid x y z' to define the size of the SDF grid around the ",
"reference molecule. ",
- "The Volume of the SDF grid will be V=x*y*z (nm^3). "
+ "The Volume of the SDF grid will be V=x*y*z (nm^3). ",
"Use -bin to set the binwidth for grid.[PAR]",
"The output will be a binary 3D-grid file (gom_plt.dat) in the .plt format that can be be",
"read directly by gOpenMol. ",
- "The option -r will generate a .gro file with the reference molecule(s) transfered to",
+ "The option -r will generate a .gro file with the reference molecule(s) transferred to",
"the SDF coordinate system. Load this file into gOpenMol and display the",
"SDF as a contour plot (see http://www.csc.fi/gopenmol/index.phtml for ",
"further documentation). [PAR]",
" Nothing to do!");
- if ( bRef && fn2ftp(fnREF) != efGRO)
+ if ( bRef && (fn2ftp(fnREF) != efGRO))
{
fprintf(stderr,"\nOnly GROMACS format is supported for reference structures.\n");
fprintf(stderr,"Option -r will be ignored!\n");
}
- if (mode < 1 || mode > 3)
- gmx_fatal(FARGS,"Wrong -mode selection. Chose 1-, 2- oder 3-praticle mode.\n");
+ if ((mode < 1) || (mode > 3))
+ gmx_fatal(FARGS,"Wrong -mode selection. Chose 1-, 2- oder 3-particle mode.\n");
do_sdf(fnNDX,fnTPS,ftp2fn(efTRX,NFILE,fnm),opt2fn("-o",NFILE,fnm),
distance, /* distance between two groups. */
distance1, /* distance between plane and one of two atoms */
distance2; /* same for second of two atoms */
- int status,natoms,teller=0;
+ t_trxstatus *status;
+ int natoms,teller=0;
rvec *x0; /* coordinates, and coordinates corrected for pb */
matrix box;
char buf[256]; /* for xvgr title */
+ gmx_rmpbc_t gpbc=NULL;
+
if ((natoms = read_first_x(oenv,&status,fn,&t,&x0,box)) == 0)
gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
sg_distance2 = xvgropen(d2file,buf,"Time (ps","Distance (nm)",oenv);
}
+ gpbc = gmx_rmpbc_init(&(top->idef),ePBC,natoms,box);
+
do
{
teller++;
- rm_pbc(&(top->idef),ePBC,natoms,box,x0,x0);
+ gmx_rmpbc(gpbc,box,x0,x0);
calc_angle(ePBC,box,x0,index1,index2,gnx1,gnx2,&angle,
&distance,&distance1,&distance2);
fprintf(sg_distance2,"%12g %12g\n",t,distance1);
} while (read_next_x(oenv,status,&t,natoms,x0,box));
-
+
+ gmx_rmpbc_done(gpbc);
+
fprintf(stderr,"\n");
close_trj(status);
ffclose(sg_angle);
distance, /* distance between two groups. */
distance1, /* distance between plane and one of two atoms */
distance2; /* same for second of two atoms */
- int status,natoms,teller=0;
+ t_trxstatus *status;
+ int natoms,teller=0;
int i;
rvec *x0; /* coordinates, and coordinates corrected for pb */
rvec *xzero;
matrix box;
char buf[256]; /* for xvgr title */
+ gmx_rmpbc_t gpbc=NULL;
+
if ((natoms = read_first_x(oenv,&status,fn,&t,&x0,box)) == 0)
gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
}
snew(xzero,natoms);
+ gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
do {
teller++;
- rm_pbc(&(top->idef),ePBC,natoms,box,x0,x0);
+ gmx_rmpbc(gpbc,box,x0,x0);
if (teller==1) {
for(i=0;i<natoms;i++)
copy_rvec(x0[i],xzero[i]);
fprintf(sg_distance2,"%12g %12g\n",t,distance1);
} while (read_next_x(oenv,status,&t,natoms,x0,box));
+ gmx_rmpbc_done(gpbc);
fprintf(stderr,"\n");
close_trj(status);
"Here is what some of the file options do:[BR]",
"-oa: Angle between the two groups specified in the index file. If a group contains three atoms the normal to the plane defined by those three atoms will be used. If a group contains two atoms, the vector defined by those two atoms will be used.[BR]",
"-od: Distance between two groups. Distance is taken from the center of one group to the center of the other group.[BR]",
- "-od1: If one plane and one vector is given, the distances for each of the atoms from the center of the plane is given seperately.[BR]",
+ "-od1: If one plane and one vector is given, the distances for each of the atoms from the center of the plane is given separately.[BR]",
"-od2: For two planes this option has no meaning."
};
"A line in the input file may start with a time",
"(see option [TT]-time[tt]) and any number of y values may follow.",
"Multiple sets can also be",
- "read when they are seperated by & (option [TT]-n[tt]),",
+ "read when they are separated by & (option [TT]-n[tt]),",
"in this case only one y value is read from each line.",
"All lines starting with # and @ are skipped.",
"[PAR]",
{ "-ttol", FALSE, etREAL, {&ttol},
"Tolerance on time in appropriate units (usually ps)" },
{ "-n", FALSE, etINT, {&nsets_in},
- "Read # sets seperated by &" },
+ "Read # sets separated by &" },
{ "-d", FALSE, etBOOL, {&bDer},
"Use the derivative" },
{ "-bw", FALSE, etREAL, {&binwidth},
t_topology top;
int ePBC;
char title[STRLEN];
- int status;
+ t_trxstatus *status;
int natoms;
real t;
rvec *xtop,*x;
char str[STRLEN];
bool bTPS;
rvec xref,dx,dxh1,dxh2,outer;
+ gmx_rmpbc_t gpbc=NULL;
t_pbc pbc;
char *legr[] = { "<cos(\\8q\\4\\s1\\N)>",
"<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>" };
const char *desc[] = {
"g_sorient analyzes solvent orientation around solutes.",
"It calculates two angles between the vector from one or more",
- "reference positions to the first atom of each solvent molecule:[BR]"
+ "reference positions to the first atom of each solvent molecule:[BR]",
"theta1: the angle with the vector from the first atom of the solvent",
"molecule to the midpoint between atoms 2 and 3.[BR]",
"theta2: the angle with the normal of the solvent plane, defined by the",
rcut2 = sqr(rcut);
invbw = 1/binwidth;
- nbin1 = (int)(2*invbw + 0.5);
- nbin2 = (int)(invbw + 0.5);
+ nbin1 = 1+(int)(2*invbw + 0.5);
+ nbin2 = 1+(int)(invbw + 0.5);
invrbw = 1/rbinw;
- snew(hist1,nbin1+1);
- snew(hist2,nbin2+1);
- nrbin = rcut/rbinw;
+ snew(hist1,nbin1);
+ snew(hist2,nbin2);
+ nrbin = 1+(int)(rcut/rbinw);
if (nrbin == 0)
nrbin = 1;
snew(histi1,nrbin);
sum1 = 0;
sum2 = 0;
+ if (bTPS) {
+ /* make molecules whole again */
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
+ }
/* start analysis of trajectory */
do {
if (bTPS) {
/* make molecules whole again */
- rm_pbc(&top.idef,ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
}
set_pbc(&pbc,ePBC,box);
sa0 = index[1][m];
sa1 = index[1][m+1];
sa2 = index[1][m+2];
+ range_check(sa0,0,natoms);
+ range_check(sa1,0,natoms);
+ range_check(sa2,0,natoms);
pbc_dx(&pbc,x[sa0],xref,dx);
r2 = norm2(dx);
if (r2 < rcut2) {
unitv(dxh2,dxh2);
outp = iprod(dx,dxh2)/r;
}
- (histi1[(int)(invrbw*r)]) += inp;
- (histi2[(int)(invrbw*r)]) += 3*sqr(outp) - 1;
- (histn[(int)(invrbw*r)])++;
- if (r2>=rmin2 && r2<rmax2) {
- (hist1[(int)(invbw*(inp + 1))])++;
- (hist2[(int)(invbw*fabs(outp))])++;
+ {
+ int ii = (int)(invrbw*r);
+ range_check(ii,0,nrbin);
+ histi1[ii] += inp;
+ histi2[ii] += 3*sqr(outp) - 1;
+ histn[ii]++;
+ }
+ if ((r2>=rmin2) && (r2<rmax2)) {
+ int ii1 = (int)(invbw*(inp + 1));
+ int ii2 = (int)(invbw*fabs(outp));
+
+ range_check(ii1,0,nbin1);
+ range_check(ii2,0,nbin2);
+ hist1[ii1]++;
+ hist2[ii2]++;
sum1 += inp;
sum2 += outp;
- n++;
+ n++;
}
}
}
/* clean up */
sfree(x);
close_trj(status);
-
+ gmx_rmpbc_done(gpbc);
+
/* Add the bin for the exact maximum to the previous bin */
hist1[nbin1-1] += hist1[nbin1];
hist2[nbin2-1] += hist2[nbin2];
t_trxframe fr;
rvec *xtop,*shx[26];
matrix box,box_pbc;
- int status;
+ t_trxstatus *status;
int flags = TRX_READ_X;
t_pbc pbc;
t_atoms *atoms;
long tot,max,min;
double norm;
output_env_t oenv;
+ gmx_rmpbc_t gpbc=NULL;
t_filenm fnm[] = {
{ efTPS, NULL, NULL, ffREAD }, /* this is for the topology */
numfr=0;
minx=miny=minz=999;
maxx=maxy=maxz=0;
+
+ if (bPBC)
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
/* This is the main loop over frames */
do {
/* Must init pbc every step because of pressure coupling */
copy_mat(box,box_pbc);
if (bPBC) {
- rm_pbc(&top.idef,ePBC,natoms,box,fr.x,fr.x);
+ gmx_rmpbc(gpbc,box,fr.x,fr.x);
set_pbc(&pbc,ePBC,box_pbc);
}
} while(read_next_frame(oenv,status,&fr));
+ if (bPBC)
+ gmx_rmpbc_done(gpbc);
+
if(!bCUTDOWN){
minx=miny=minz=0;
maxx=nbin[XX];
t_inputrec *ir;
t_atom *atom;
char title[STRLEN];
- int status;
+ t_trxstatus *status;
int nrefat,natoms,nf,ntot;
real t;
rvec *xtop,*x,xref,trial,dx={0},dip,dir;
double sdip,sdip2,sinp,sdinp,nmol;
int *hist;
t_pbc pbc;
+ gmx_rmpbc_t gpbc=NULL;
+
const char *desc[] = {
"g_spol analyzes dipoles around a solute; it is especially useful",
molindex = top->mols.index;
atom = top->atoms.atom;
+
+ gpbc = gmx_rmpbc_init(&top->idef,ir->ePBC,natoms,box);
/* start analysis of trajectory */
do {
/* make molecules whole again */
- rm_pbc(&top->idef,ir->ePBC,natoms,box,x,x);
-
+ gmx_rmpbc(gpbc,box,x,x);
+
set_pbc(&pbc,ir->ePBC,box);
if (bCom)
calc_com_pbc(nrefat,top,x,&pbc,index[0],xref,ir->ePBC,box);
nf++;
} while (read_next_x(oenv,status,&t,natoms,x,box));
+
+ gmx_rmpbc_done(gpbc);
/* clean up */
sfree(x);
char *grpname;
char title[256];
real t0,t1,dt,m,mtot,sysmass,rho,sx,cx;
- int status,nframes,n_alloc,i,j,k,d;
+ t_trxstatus *status;
+ int nframes,n_alloc,i,j,k,d;
rvec mv_mol,cm_mol,kfac[NK];
int nkc,nk,ntc;
real **c1,**tc;
low_print_data(fp,time,x,isize[0],index[0],bDim);
}
-static void write_trx_x(int status,t_trxframe *fr,real *mass,bool bCom,
+static void write_trx_x(t_trxstatus *status,t_trxframe *fr,real *mass,bool bCom,
int ngrps,int isize[],atom_id **index)
{
static rvec *xav=NULL;
rvec *xtop,*xp=NULL;
rvec *sumxv=NULL,*sumv=NULL,*sumxf=NULL,*sumf=NULL;
matrix topbox;
- int status,status_out=-1;
+ t_trxstatus *status;
+ t_trxstatus *status_out=NULL;
+ gmx_rmpbc_t gpbc=NULL;
int i,j,n;
int nr_xfr,nr_vfr,nr_ffr;
char **grpname;
nr_xfr = 0;
nr_vfr = 0;
nr_ffr = 0;
+
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box);
do {
time = output_env_conv_time(oenv,fr.time);
}
if (fr.bX && bCom)
- rm_pbc(&(top.idef),ePBC,fr.natoms,fr.box,fr.x,fr.x);
+ gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
if (bVD && fr.bV)
update_histo(isize[0],index[0],fr.v,&nvhisto,&vhisto,binwidth);
} while(read_next_frame(oenv,status,&fr));
+ gmx_rmpbc_done(gpbc);
/* clean up a bit */
close_trj(status);
const output_env_t oenv)
{
/* Check start time of all files */
- int i, status, natoms = 0;
+ int i, natoms = 0;
+ t_trxstatus *status;
real t;
t_trxframe fr;
bool ok;
atom_id index[], real dt, const output_env_t oenv)
{
int i, j, k, natoms, nnn;
- int *fp_in, *fp_out;
+ t_trxstatus **fp_in, **fp_out;
bool bCont, *bSet;
real t, first_time = 0;
t_trxframe *trx;
"Obviously the file to append to has to be the one with lowest starting",
"time since one can only append at the end of a file.[PAR]",
"If the [TT]-demux[tt] option is given, the N trajectories that are",
- "read, are written in another order as specified in the xvg file."
+ "read, are written in another order as specified in the xvg file.",
"The xvg file should contain something like:[PAR]",
"0 0 1 2 3 4 5[BR]",
"2 1 0 2 3 5 4[BR]",
{ "-cat", FALSE, etBOOL,
{ &bCat }, "do not discard double time frames" } };
#define npargs asize(pa)
- int status, ftpin, i, frame, frame_out, step = 0, trjout = 0;
+ int ftpin, i, frame, frame_out, step = 0, trjout = 0;
+ t_trxstatus *status;
rvec *x, *v;
real xtcpr, t_corr;
t_trxframe fr, frout;
char **fnms, **fnms_out, *in_file, *out_file;
int n_append;
- int trxout = -1;
+ t_trxstatus *trxout = NULL;
bool bNewFile, bIndex, bWrite;
int earliersteps, nfile_in, nfile_out, *cont_type, last_ok_step;
real *readtime, *timest, *settime;
}
else
{
+ t_fileio *stfio;
+
if (!read_first_frame(oenv,&status,out_file,&fr,FLAGS))
gmx_fatal(FARGS,"Reading first frame from %s",out_file);
+
+ stfio=trx_get_fileio(status);
if (!bKeepLast && !bOverwrite)
{
fprintf(stderr, "\n\nWARNING: Appending without -overwrite implies -keeplast "
/* Fails if last frame is incomplete
* We can't do anything about it without overwriting
* */
- if (gmx_fio_getftp(status) == efXTC)
+ if (gmx_fio_getftp(stfio) == efXTC)
{
- lasttime = xdr_xtc_get_last_frame_time(gmx_fio_getfp(status),gmx_fio_getxdr(status),fr.natoms,&bOK);
+ lasttime =
+ xdr_xtc_get_last_frame_time(gmx_fio_getfp(stfio),
+ gmx_fio_getxdr(stfio),
+ fr.natoms,&bOK);
fr.time = lasttime;
if (!bOK)
{
}
else if (bOverwrite)
{
- if (gmx_fio_getftp(status) != efXTC) {
+ if (gmx_fio_getftp(stfio) != efXTC) {
gmx_fatal(FARGS,"Overwrite only supported for XTC." );
}
- last_frame_time = xdr_xtc_get_last_frame_time(gmx_fio_getfp(status),gmx_fio_getxdr(status),fr.natoms,&bOK);
+ last_frame_time =
+ xdr_xtc_get_last_frame_time(gmx_fio_getfp(stfio),
+ gmx_fio_getxdr(stfio),
+ fr.natoms,&bOK);
if (!bOK)
{
gmx_fatal(FARGS,"Error reading last frame. Maybe seek not supported." );
{
searchtime = last_frame_time;
}
- if (xtc_seek_time(searchtime,status,fr.natoms))
+ if (xtc_seek_time(stfio,searchtime,fr.natoms))
{
gmx_fatal(FARGS,"Error seeking to append position.");
}
searchtime,fr.time);
}
lasttime = fr.time;
- fpos = gmx_fio_ftell(status);
+ fpos = gmx_fio_ftell(stfio);
close_trj(status);
trxout = open_trx(out_file,"r+");
- if (gmx_fio_seek(trxout,fpos)) {
+ if (gmx_fio_seek(trx_get_fileio(trxout),fpos)) {
gmx_fatal(FARGS,"Error seeking to append position.");
}
}
if (bIndex)
{
- write_trxframe_indexed(trxout,&frout,isize,index,NULL);
+ write_trxframe_indexed(trxout,&frout,isize,index,
+ NULL);
}
else
{
earliersteps+=step;
}
- if (trxout >= 0)
+ if (trxout)
{
close_trx(trxout);
}
#if (!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64)
void do_trunc(const char *fn, real t0)
{
- int in;
+ t_fileio *in;
FILE *fp;
bool bStop,bOK;
t_trnheader sh;
const char *desc[] = {
"trjconv can convert trajectory files in many ways:[BR]",
"[BB]1.[bb] from one format to another[BR]",
- "[BB]2.[bb] select a subset of atoms[BR]"
+ "[BB]2.[bb] select a subset of atoms[BR]",
"[BB]3.[bb] change the periodicity representation[BR]",
"[BB]4.[bb] keep multimeric molecules together[BR]",
"[BB]5.[bb] center atoms in the box[BR]",
"append output to an existing trajectory file.",
"No checks are performed to ensure integrity",
"of the resulting combined trajectory file.[PAR]",
- "Option [TT]-sep[tt] can be used to write every frame to a seperate",
+ "Option [TT]-sep[tt] can be used to write every frame to a separate",
".gro, .g96 or .pdb file, default all frames all written to one file.",
"[TT].pdb[tt] files with all frames concatenated can be viewed with",
"[TT]rasmol -nmrpdb[tt].[PAR]",
"* [TT]whole[tt] only makes broken molecules whole.[PAR]",
"Option [TT]-ur[tt] sets the unit cell representation for options",
"[TT]mol[tt], [TT]res[tt] and [TT]atom[tt] of [TT]-pbc[tt].",
- "All three options give different results for triclinc boxes and",
+ "All three options give different results for triclinic boxes and",
"identical results for rectangular boxes.",
"[TT]rect[tt] is the ordinary brick shape.",
"[TT]tric[tt] is the triclinic unit cell.",
#define NPA asize(pa)
FILE *out=NULL;
- int trxout=NOTSET;
- int status,ftp,ftpin=0,file_nr;
+ t_trxstatus *trxout=NULL;
+ t_trxstatus *status;
+ int ftp,ftpin=0,file_nr;
t_trxframe fr,frout;
int flags;
rvec *xmem=NULL,*vmem=NULL,*fmem=NULL;
atom_id *ind_fit,*ind_rms;
char *gn_fit,*gn_rms;
t_cluster_ndx *clust=NULL;
- int *clust_status=NULL;
+ t_trxstatus **clust_status=NULL;
+ int *clust_status_id=NULL;
int ntrxopen=0;
int *nfwritten=NULL;
int ndrop=0,ncol,drop0=0,drop1=0,dropuse=0;
real tshift=0,t0=-1,dt=0.001,prec;
bool bFit,bFitXY,bPFit,bReset;
int nfitdim;
+ gmx_rmpbc_t gpbc=NULL;
bool bRmPBC,bPBCWhole,bPBCcomRes,bPBCcomMol,bPBCcomAtom,bPBC,bNoJump,bCluster;
bool bCopy,bDoIt,bIndex,bTDump,bSetTime,bTPS=FALSE,bDTset=FALSE;
bool bExec,bTimeStep=FALSE,bDumpFrame=FALSE,bSetPrec,bNeedPrec;
if (bFit || bReset)
nfitdim = (fit_enum==efFitXY || fit_enum==efResetXY) ? 2 : 3;
bRmPBC = bFit || bPBCWhole || bPBCcomRes || bPBCcomMol;
+
if (bSetUR) {
if (!(bPBCcomRes || bPBCcomMol || bPBCcomAtom)) {
fprintf(stderr,
clust->clust->nr,1+clust->clust->nr/FOPEN_MAX,FOPEN_MAX);
snew(clust_status,clust->clust->nr);
+ snew(clust_status_id,clust->clust->nr);
snew(nfwritten,clust->clust->nr);
for(i=0; (i<clust->clust->nr); i++)
- clust_status[i] = -1;
+ {
+ clust_status[i] = NULL;
+ clust_status_id[i] = -1;
+ }
bSeparate = bSplit = FALSE;
}
/* skipping */
if (bCONECT)
gc = gmx_conect_generate(&top);
+ if (bRmPBC)
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,top_box);
}
/* get frame number index */
/* Restore reference structure and set to origin,
store original location (to put structure back) */
if (bRmPBC)
- rm_pbc(&(top.idef),ePBC,atoms->nr,top_box,xp,xp);
+ gmx_rmpbc(gpbc,top_box,xp,xp);
copy_rvec(xp[index[0]],x_shift);
reset_x_ndim(nfitdim,ifit,ind_fit,atoms->nr,NULL,xp,w_rls);
rvec_dec(x_shift,xp[index[0]]);
}
if (ftp == efG87)
- fprintf(gmx_fio_getfp(trxout),"Generated by %s. #atoms=%d, a BOX is"
+ fprintf(gmx_fio_getfp(trx_get_fileio(trxout)),
+ "Generated by %s. #atoms=%d, a BOX is"
" stored in this file.\n",Program(),nout);
/* Start the big loop over frames */
/* Now modify the coords according to the flags,
for normal fit, this is only done for output frames */
if (bRmPBC)
- rm_pbc(&(top.idef),ePBC,natoms,fr.box,fr.x,fr.x);
+ gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
reset_x_ndim(nfitdim,ifit,ind_fit,natoms,NULL,fr.x,w_rls);
do_fit(natoms,w_rls,xp,fr.x);
for PFit we did this already! */
if (bRmPBC)
- rm_pbc(&(top.idef),ePBC,natoms,fr.box,fr.x,fr.x);
+ gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
if (bReset) {
reset_x_ndim(nfitdim,ifit,ind_fit,natoms,NULL,fr.x,w_rls);
case efG87:
case efXTC:
if ( bSplitHere ) {
- if ( trxout >= 0 )
+ if ( trxout )
close_trx(trxout);
trxout = open_trx(out_file2,filemode);
}
if (bSubTraj) {
if (my_clust != -1) {
char buf[STRLEN];
- if (clust_status[my_clust] == -1) {
+ if (clust_status_id[my_clust] == -1) {
sprintf(buf,"%s.%s",clust->grpname[my_clust],ftp2ext(ftp));
clust_status[my_clust] = open_trx(buf,"w");
+ clust_status_id[my_clust] = 1;
ntrxopen++;
}
- else if (clust_status[my_clust] == -2)
+ else if (clust_status_id[my_clust] == -2)
gmx_fatal(FARGS,"File %s.xtc should still be open (%d open xtc files)\n""in order to write frame %d. my_clust = %d",
clust->grpname[my_clust],ntrxopen,frame,
my_clust);
(clust->clust->index[my_clust+1]-
clust->clust->index[my_clust])) {
close_trx(clust_status[my_clust]);
- clust_status[my_clust] = -2;
+ clust_status_id[my_clust] = -2;
ntrxopen--;
if (ntrxopen < 0)
gmx_fatal(FARGS,"Less than zero open xtc files!");
if (!bHaveFirstFrame || (bTDump && !bDumpFrame))
fprintf(stderr,"\nWARNING no output, "
- "trajectory ended at %g\n",fr.time);
+ "last frame read at t=%g\n",fr.time);
fprintf(stderr,"\n");
close_trj(status);
-
- if (trxout >= 0)
+ if (bRmPBC)
+ gmx_rmpbc_done(gpbc);
+
+ if (trxout)
close_trx(trxout);
else if (out != NULL)
ffclose(out);
if (bSubTraj) {
for(i=0; (i<clust->clust->nr); i++)
- if (clust_status[i] >= 0)
+ if (clust_status[i] )
close_trx(clust_status[i]);
}
}
"will be stored in the B-factor field in order to color with e.g. rasmol.",
"[PAR]",
"With option [TT]-nshell[tt] the number of molecules within a shell",
- "of radius [TT]-r[tt] around the refernce group are printed."
+ "of radius [TT]-r[tt] around the reference group are printed."
};
static int na=3,ref_a=1;
static real rcut=0;
"Order molecules on z-coordinate" }
};
FILE *fp;
- int status,out;
+ t_trxstatus *out;
+ t_trxstatus *status;
bool bNShell,bPDBout;
t_topology top;
int ePBC;
rvec *x,*xsol,xcom,dx;
matrix box;
t_pbc pbc;
+ gmx_rmpbc_t gpbc;
real t,totmass,mass,rcut2=0,n2;
int natoms,nwat,ncut;
char **grpname,title[256];
for(i=0; (i<natoms); i++)
swi[i] = i;
- out = -1;
+ out = NULL;
fp = NULL;
bNShell = ((opt2bSet("-nshell",NFILE,fnm)) ||
(opt2parg_bSet("-r",asize(pa),pa)));
}
out = open_trx(opt2fn("-o",NFILE,fnm),"w");
}
+ gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
do {
- rm_pbc(&top.idef,ePBC,natoms,box,x,x);
+ gmx_rmpbc(gpbc,box,x,x);
set_pbc(&pbc,ePBC,box);
if (ref_a == -1) {
ncut++;
fprintf(fp,"%10.3f %8d\n",t,ncut);
}
- if (out != -1) {
+ if (out) {
qsort(order,nwat,sizeof(*order),ocomp);
for(i=0; (i<nwat); i++)
for(j=0; (j<na); j++)
}
} while(read_next_x(oenv,status,&t,natoms,x,box));
close_trj(status);
- if (out != -1)
+ if (out)
close_trx(out);
if (fp)
ffclose(fp);
-
+ gmx_rmpbc_done(gpbc);
+
thanx(stderr);
return 0;
#include "calcgrid.h"
#include "checkpoint.h"
#include "gmx_ana.h"
+#include "names.h"
ddnoSEL, ddnoINTERLEAVE, ddnoPP_PME, ddnoCARTESIAN, ddnoNR
};
-/* Enum for situations that can occur during log file parsing */
+/* Enum for situations that can occur during log file parsing, the
+ * corresponding string entries can be found in do_the_tests() in
+ * const char* ParseLog[] */
enum {
eParselogOK,
eParselogNotFound,
eParselogNoPerfData,
eParselogTerm,
eParselogResetProblem,
+ eParselogNoDDGrid,
+ eParselogTPXVersion,
+ eParselogNotParallel,
+ eParselogFatal,
eParselogNr
};
int nr_inputfiles; /* The number of tpr and mdp input files */
gmx_large_int_t orig_sim_steps; /* Number of steps to be done in the real simulation */
real *r_coulomb; /* The coulomb radii [0...nr_inputfiles] */
- real *r_vdW; /* The vdW radii */
+ real *r_vdw; /* The vdW radii */
+ real *rlist; /* Neighbourlist cutoff radius */
+ real *rlistlong;
int *fourier_nx, *fourier_ny, *fourier_nz;
real *fourier_sp; /* Fourierspacing */
+
+ /* Original values as in inputfile: */
+ real orig_rcoulomb;
+ real orig_rvdw;
+ real orig_rlist, orig_rlistlong;
+ int orig_nk[DIM];
+ real orig_fs[DIM];
} t_inputinfo;
}
+static bool is_equal(real a, real b)
+{
+ real diff, eps=1.0e-6;
+
+
+ diff = a - b;
+
+ if (diff < 0.0) diff = -diff;
+
+ if (diff < eps)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static void finalize(const char *fn_out)
+{
+ char buf[STRLEN];
+ FILE *fp;
+
+
+ fp = fopen(fn_out,"r");
+ fprintf(stdout,"\n\n");
+
+ while( fgets(buf,STRLEN-1,fp) != NULL )
+ {
+ fprintf(stdout,"%s",buf);
+ }
+ fclose(fp);
+ fprintf(stdout,"\n\n");
+ thanx(stderr);
+}
+
+
enum {eFoundNothing, eFoundDDStr, eFoundAccountingStr, eFoundCycleStr};
-static int parse_logfile(const char *logfile, t_perf *perfdata, int test_nr,
- int presteps, gmx_large_int_t cpt_steps, int nnodes)
+static int parse_logfile(const char *logfile, const char *errfile,
+ t_perf *perfdata, int test_nr, int presteps, gmx_large_int_t cpt_steps,
+ int nnodes)
{
FILE *fp;
char line[STRLEN], dumstring[STRLEN], dumstring2[STRLEN];
gmx_fatal(FARGS, "PME nodes from command line and output file are not identical");
iFound = eFoundDDStr;
}
+ /* Catch a few errors that might have occured: */
+ else if (str_starts(line, "There is no domain decomposition for"))
+ {
+ return eParselogNoDDGrid;
+ }
+ else if (str_starts(line, "reading tpx file"))
+ {
+ return eParselogTPXVersion;
+ }
+ else if (str_starts(line, "The -dd or -npme option request a parallel simulation"))
+ {
+ return eParselogNotParallel;
+ }
break;
case eFoundDDStr:
/* Look for PME mesh/force balance (not necessarily present, though) */
break;
}
} /* while */
+
+ /* Check why there is no performance data in the log file.
+ * Did a fatal errors occur? */
+ if (gmx_fexist(errfile))
+ {
+ fp = fopen(errfile, "r");
+ while (fgets(line, STRLEN, fp) != NULL)
+ {
+ if ( str_starts(line, "Fatal error:") )
+ {
+ if (fgets(line, STRLEN, fp) != NULL)
+ fprintf(stderr, "\nWARNING: A fatal error has occured during this benchmark:\n"
+ "%s\n", line);
+ fclose(fp);
+ cleandata(perfdata, test_nr);
+ return eParselogFatal;
+ }
+ }
+ fclose(fp);
+ }
+ else
+ {
+ fprintf(stderr, "WARNING: Could not find stderr file %s.\n", errfile);
+ }
+
+ /* Giving up ... we could not find out why there is no performance data in
+ * the log file. */
fprintf(stdout, "No performance data in log file.\n");
fclose(fp);
cleandata(perfdata, test_nr);
}
-static int analyze_data(
+static bool analyze_data(
FILE *fp,
+ const char *fn,
t_perf **perfdata,
int nnodes,
int ntprs,
t_perf *pd;
char strbuf[STRLEN];
char str_PME_f_load[13];
+ bool bCanUseOrigTPR;
if (nrepeats > 1)
}
if (k_win == -1)
- gmx_fatal(FARGS, "None of the runs was successful! Exiting.");
+ gmx_fatal(FARGS, "None of the runs was successful! Check %s for problems.", fn);
sep_line(fp);
sprintf(strbuf, "%d", winPME);
fprintf(fp, "Best performance was achieved with %s PME nodes", strbuf);
if (nrepeats > 1)
- fprintf(fp, " (see line %d) ", line_win);
- if (ntprs > 1)
- fprintf(fp, "\nand %s PME settings. ", (k_win ? "optimized" : "original"));
+ fprintf(fp, " (see line %d)", line_win);
fprintf(fp, "\n");
- /* Only mention settings if rcoulomb, rvdv, nkx, nky, or nkz was modified: */
- if (k_win)
+ /* Only mention settings if they were modified: */
+ bCanUseOrigTPR = TRUE;
+ if ( !is_equal(info->r_coulomb[k_win], info->orig_rcoulomb) )
+ {
+ fprintf(fp, "Optimized PME settings:\n"
+ " New Coulomb radius: %f nm (was %f nm)\n",
+ info->r_coulomb[k_win], info->orig_rcoulomb);
+ bCanUseOrigTPR = FALSE;
+ }
+
+ if ( !is_equal(info->r_vdw[k_win], info->orig_rvdw) )
{
- fprintf(fp, "Optimized PME settings:\n");
- fprintf(fp, "r_coulomb = %f, r_vdW = %f, nx,ny,nz = %d %d %d\n",
- info->r_coulomb[k_win], info->r_vdW[k_win],
- info->fourier_nx[k_win], info->fourier_ny[k_win], info->fourier_nz[k_win]);
+ fprintf(fp, " New Van der Waals radius: %f nm (was %f nm)\n",
+ info->r_vdw[k_win], info->orig_rvdw);
+ bCanUseOrigTPR = FALSE;
}
+
+ if ( ! (info->fourier_nx[k_win]==info->orig_nk[XX] &&
+ info->fourier_ny[k_win]==info->orig_nk[YY] &&
+ info->fourier_nz[k_win]==info->orig_nk[ZZ] ) )
+ {
+ fprintf(fp, " New Fourier grid xyz: %d %d %d (was %d %d %d)\n",
+ info->fourier_nx[k_win], info->fourier_ny[k_win], info->fourier_nz[k_win],
+ info->orig_nk[XX], info->orig_nk[YY], info->orig_nk[ZZ]);
+ bCanUseOrigTPR = FALSE;
+ }
+ if (bCanUseOrigTPR && ntprs > 1)
+ fprintf(fp, "and original PME settings.\n");
+
fflush(fp);
/* Return the index of the mdp file that showed the highest performance
*index_tpr = k_win;
*npme_optimal = winPME;
- return 0;
+ return bCanUseOrigTPR;
}
/* Get the commands we need to set up the runs from environment variables */
-static void get_program_paths(char *cmd_mpirun[], char *cmd_mdrun[], int repeats)
+static void get_program_paths(bool bThreads, char *cmd_mpirun[], char cmd_np[],
+ char *cmd_mdrun[], int repeats)
{
char *command=NULL;
char *cp;
FILE *fp;
const char def_mpirun[] = "mpirun";
const char def_mdrun[] = "mdrun";
- const char filename[] = "testrun.log";
- const char match_mdrun[]= "NNODES=";
- bool bFound = FALSE;
+ const char filename[] = "benchtest.log";
+ const char match_mpi[] = "NNODES=";
+ const char match_mdrun[]= "Program: ";
+ const char empty_mpirun[] = "";
+ bool bMdrun = FALSE;
+ bool bMPI = FALSE;
/* Get the commands we need to set up the runs from environment variables */
- if ( (cp = getenv("MPIRUN")) != NULL)
- *cmd_mpirun = strdup(cp);
- else
- *cmd_mpirun = strdup(def_mpirun);
-
- if ( (cp = getenv("MDRUN" )) != NULL )
- *cmd_mdrun = strdup(cp);
- else
- *cmd_mdrun = strdup(def_mdrun);
-
-
- /* If no simulations have to be performed, we are done here */
- if (repeats <= 0)
- return;
-
- /* Run a small test to see if mpirun and mdrun work if we intend to execute mdrun! */
- fprintf(stdout, "Making shure that mdrun can be executed. ");
-
- snew(command, strlen(*cmd_mpirun) + strlen(*cmd_mdrun) + strlen(filename) + 30);
- sprintf(command, "%s -np 1 %s -h -quiet >& %s", *cmd_mpirun, *cmd_mdrun, filename);
- fprintf(stdout, "Trying '%s' ... ", command);
-
- gmx_system_call(command);
+ if (!bThreads)
+ {
+ if ( (cp = getenv("MPIRUN")) != NULL)
+ *cmd_mpirun = strdup(cp);
+ else
+ *cmd_mpirun = strdup(def_mpirun);
+ }
+ else
+ {
+ *cmd_mpirun = strdup(empty_mpirun);
+ }
- /* Check if we find the gromacs header in the log file: */
- fp = fopen(filename, "r");
- while ( (!feof(fp)) && (bFound==FALSE) )
- {
- cp2=fgets(line, STRLEN, fp);
- if (cp2!=NULL && str_starts(line, match_mdrun))
- bFound = TRUE;
- }
-
- if (!bFound)
- gmx_fatal(FARGS, "Cannot execute mdrun. Please check %s for problems!", filename);
-
- fclose(fp);
- fprintf(stdout, "passed.\n");
-
- /* Clean up ... */
- remove(filename);
+ if ( (cp = getenv("MDRUN" )) != NULL )
+ *cmd_mdrun = strdup(cp);
+ else
+ *cmd_mdrun = strdup(def_mdrun);
+
+
+ /* If no simulations have to be performed, we are done here */
+ if (repeats <= 0)
+ return;
+
+ /* Run a small test to see whether mpirun + mdrun work */
+ fprintf(stdout, "Making sure that mdrun can be executed. ");
+ if (bThreads)
+ {
+ snew(command, strlen(*cmd_mdrun) + strlen(cmd_np) + strlen(filename) + 50);
+ sprintf(command, "%s%s-version -maxh 0.001 1> %s 2>&1", *cmd_mdrun, cmd_np, filename);
+ }
+ else
+ {
+ snew(command, strlen(*cmd_mpirun) + strlen(cmd_np) + strlen(*cmd_mdrun) + strlen(filename) + 50);
+ sprintf(command, "%s%s%s -version -maxh 0.001 1> %s 2>&1", *cmd_mpirun, cmd_np, *cmd_mdrun, filename);
+ }
+ fprintf(stdout, "Trying '%s' ... ", command);
+ make_backup(filename);
+ gmx_system_call(command);
+
+ /* Check if we find the characteristic string in the output: */
+ if (!gmx_fexist(filename))
+ gmx_fatal(FARGS, "Output from test run could not be found.");
+
+ fp = fopen(filename, "r");
+ /* We need to scan the whole output file, since sometimes the queuing system
+ * also writes stuff to stdout/err */
+ while ( !feof(fp) )
+ {
+ cp2=fgets(line, STRLEN, fp);
+ if (cp2!=NULL)
+ {
+ if ( str_starts(line, match_mdrun) )
+ bMdrun = TRUE;
+ if ( str_starts(line, match_mpi) )
+ bMPI = TRUE;
+ }
+ }
+ fclose(fp);
+
+ if (bThreads)
+ {
+ if (bMPI)
+ {
+ gmx_fatal(FARGS, "Need a threaded version of mdrun. This one\n"
+ "(%s)\n"
+ "seems to have been compiled with MPI instead.",
+ *cmd_mdrun);
+ }
+ }
+ else
+ {
+ if (bMdrun && !bMPI)
+ {
+ gmx_fatal(FARGS, "Need an MPI-enabled version of mdrun. This one\n"
+ "(%s)\n"
+ "seems to have been compiled without MPI support.",
+ *cmd_mdrun);
+ }
+ }
+
+ if (!bMdrun)
+ {
+ gmx_fatal(FARGS, "Cannot execute mdrun. Please check %s for problems!",
+ filename);
+ }
+
+ fprintf(stdout, "passed.\n");
+
+ /* Clean up ... */
+ remove(filename);
+ sfree(command);
}
static void launch_simulation(
bool bLaunch, /* Should the simulation be launched? */
FILE *fp, /* General log file */
+ bool bThreads, /* whether to use threads */
char *cmd_mpirun, /* Command for mpirun */
+ char *cmd_np, /* Switch for -np or -nt or empty */
char *cmd_mdrun, /* Command for mdrun */
char *args_for_mdrun, /* Arguments for mdrun */
const char *simulation_tpr, /* This tpr will be simulated */
/* Make enough space for the system call command,
- * (100 extra chars for -np ... etc. options should suffice): */
- snew(command, strlen(cmd_mpirun)+strlen(cmd_mdrun)+strlen(args_for_mdrun)+strlen(simulation_tpr)+100);
-
- sprintf(command, "%s -np %d %s %s-npme %d -s %s",
- cmd_mpirun, nnodes, cmd_mdrun, args_for_mdrun, nPMEnodes, simulation_tpr);
+ * (100 extra chars for -npme ... etc. options should suffice): */
+ snew(command, strlen(cmd_mpirun)+strlen(cmd_mdrun)+strlen(cmd_np)+strlen(args_for_mdrun)+strlen(simulation_tpr)+100);
+
+ /* Note that the -passall options requires args_for_mdrun to be at the end
+ * of the command line string */
+ if (bThreads)
+ {
+ sprintf(command, "%s%s-npme %d -s %s %s",
+ cmd_mdrun, cmd_np, nPMEnodes, simulation_tpr, args_for_mdrun);
+ }
+ else
+ {
+ sprintf(command, "%s%s%s -npme %d -s %s %s",
+ cmd_mpirun, cmd_np, cmd_mdrun, nPMEnodes, simulation_tpr, args_for_mdrun);
+ }
fprintf(fp, "%s this command line to launch the simulation:\n\n%s", bLaunch? "Using":"Please use", command);
sep_line(fp);
static void modify_PMEsettings(
- gmx_large_int_t simsteps, /* Set this value as number of time steps */
+ gmx_large_int_t simsteps, /* Set this value as number of time steps */
const char *fn_best_tpr, /* tpr file with the best performance */
const char *fn_sim_tpr) /* name of tpr file to be launched */
{
}
+#define EPME_SWITCHED(e) ((e) == eelPMESWITCH || (e) == eelPMEUSERSWITCH)
+
/* Make additional TPR files with more computational load for the
* direct space processors: */
static void make_benchmark_tprs(
char *fn_bench_tprs[], /* WRITE: Names of benchmark tpr files */
gmx_large_int_t benchsteps, /* Number of time steps for benchmark runs */
gmx_large_int_t statesteps, /* Step counter in checkpoint file */
- real maxfac, /* Max scaling factor for rcoulomb and fourierspacing */
+ real upfac, /* Scale rcoulomb inbetween downfac and upfac */
+ real downfac,
int ntprs, /* No. of TPRs to write, each with a different rcoulomb and fourierspacing */
real fourierspacing, /* Basic fourierspacing from tpr input file */
t_inputinfo *info, /* Contains information about mdp file options */
t_state state;
gmx_mtop_t mtop;
real fac;
- real orig_rcoulomb, orig_rvdw, orig_rlist;
- rvec orig_fs; /* original fourierspacing per dimension */
- ivec orig_nk; /* original number of grid points per dimension */
+ real nlist_buffer; /* Thickness of the buffer regions for PME-switch potentials: */
char buf[200];
rvec box_size;
+ bool bNote = FALSE;
sprintf(buf, "Making benchmark tpr file%s with %s time steps", ntprs>1? "s":"", gmx_large_int_pfmt);
snew(ir,1);
read_tpx_state(fn_sim_tpr,ir,&state,NULL,&mtop);
- /* Check if PME was chosen */
+ /* Check if some kind of PME was chosen */
if (EEL_PME(ir->coulombtype) == FALSE)
- gmx_fatal(FARGS, "Can only do optimizations for simulations with PME");
+ gmx_fatal(FARGS, "Can only do optimizations for simulations with %s electrostatics.",
+ EELTYPE(eelPME));
- /* Check if rcoulomb == rlist, which is necessary for PME */
- if (!(ir->rcoulomb == ir->rlist))
- gmx_fatal(FARGS, "PME requires rcoulomb (%f) to be equal to rlist (%f).", ir->rcoulomb, ir->rlist);
+ /* Check if rcoulomb == rlist, which is necessary for plain PME. */
+ if ( (eelPME == ir->coulombtype) && !(ir->rcoulomb == ir->rlist) )
+ {
+ gmx_fatal(FARGS, "%s requires rcoulomb (%f) to be equal to rlist (%f).",
+ EELTYPE(eelPME), ir->rcoulomb, ir->rlist);
+ }
+ /* For other PME types, rcoulomb is allowed to be smaller than rlist */
+ else if (ir->rcoulomb > ir->rlist)
+ {
+ gmx_fatal(FARGS, "%s requires rcoulomb (%f) to be equal to or smaller than rlist (%f)",
+ EELTYPE(ir->coulombtype), ir->rcoulomb, ir->rlist);
+ }
/* Reduce the number of steps for the benchmarks */
info->orig_sim_steps = ir->nsteps;
ir->nsteps = benchsteps;
- /* Determine lenght of triclinic box vectors */
+ /* Determine length of triclinic box vectors */
for(d=0; d<DIM; d++)
{
box_size[d] = 0;
}
/* Remember the original values: */
- orig_rvdw = ir->rvdw;
- orig_rcoulomb = ir->rcoulomb;
- orig_rlist = ir->rlist;
- orig_nk[XX] = ir->nkx;
- orig_nk[YY] = ir->nky;
- orig_nk[ZZ] = ir->nkz;
- orig_fs[XX] = box_size[XX]/ir->nkx; /* fourierspacing in x direction */
- orig_fs[YY] = box_size[YY]/ir->nky;
- orig_fs[ZZ] = box_size[ZZ]/ir->nkz;
-
- fprintf(fp, "Input file fourier grid : %dx%dx%d\n", orig_nk[XX], orig_nk[YY], orig_nk[ZZ]);
+ info->orig_rvdw = ir->rvdw;
+ info->orig_rcoulomb = ir->rcoulomb;
+ info->orig_rlist = ir->rlist;
+ info->orig_rlistlong = ir->rlistlong;
+ info->orig_nk[XX] = ir->nkx;
+ info->orig_nk[YY] = ir->nky;
+ info->orig_nk[ZZ] = ir->nkz;
+ info->orig_fs[XX] = box_size[XX]/ir->nkx; /* fourierspacing in x direction */
+ info->orig_fs[YY] = box_size[YY]/ir->nky;
+ info->orig_fs[ZZ] = box_size[ZZ]/ir->nkz;
+
+ /* For PME-switch potentials, keep the radial distance of the buffer region */
+ nlist_buffer = info->orig_rlist - info->orig_rcoulomb;
+
+ /* Print information about settings of which some are potentially modified: */
+ fprintf(fp, " Coulomb type : %s\n", EELTYPE(ir->coulombtype));
+ fprintf(fp, " Fourier nkx nky nkz : %d %d %d\n",
+ info->orig_nk[XX], info->orig_nk[YY], info->orig_nk[ZZ]);
+ fprintf(fp, " rcoulomb : %f nm\n", info->orig_rcoulomb);
+ fprintf(fp, " Van der Waals type : %s\n", EVDWTYPE(ir->vdwtype));
+ fprintf(fp, " rvdw : %f nm\n", info->orig_rvdw);
+ if (EVDW_SWITCHED(ir->vdwtype))
+ fprintf(fp, " rvdw_switch : %f nm\n", ir->rvdw_switch);
+ if (EPME_SWITCHED(ir->coulombtype))
+ fprintf(fp, " rlist : %f nm\n", info->orig_rlist);
+ if (info->orig_rlistlong != max_cutoff(ir->rvdw,ir->rcoulomb))
+ fprintf(fp, " rlistlong : %f nm\n", info->orig_rlistlong);
+
+ /* Print a descriptive line about the tpr settings tested */
fprintf(fp, "\nWill try these real/reciprocal workload settings:\n");
- fprintf(fp, " No. scaling r_coul (r_vdW) nkx nky nkz (spacing) tpr file\n");
+ fprintf(fp, " No. scaling rcoulomb");
+ fprintf(fp, " nkx nky nkz");
+ if (fourierspacing > 0)
+ fprintf(fp, " spacing");
+ if (evdwCUT == ir->vdwtype)
+ fprintf(fp, " rvdw");
+ if (EPME_SWITCHED(ir->coulombtype))
+ fprintf(fp, " rlist");
+ if ( info->orig_rlistlong != max_cutoff(info->orig_rlist,max_cutoff(info->orig_rvdw,info->orig_rcoulomb)) )
+ fprintf(fp, " rlistlong");
+ fprintf(fp, " tpr file\n");
if (ntprs > 1)
{
{
/* Rcoulomb scaling factor for this file: */
if (ntprs == 1)
- fac = 1.0;
+ fac = downfac;
else
- fac = (maxfac-1.0f)/(ntprs-1) * j +1;
+ fac = (upfac-downfac)/(ntprs-1) * j + downfac;
fprintf(stdout, "--- Scaling factor %f ---\n", fac);
- ir->rcoulomb = orig_rcoulomb*fac;
- ir->rlist = orig_rlist *fac;
- ir->rvdw = orig_rvdw *fac;
-
+ /* Scale the Coulomb radius */
+ ir->rcoulomb = info->orig_rcoulomb*fac;
+
+ /* Adjust other radii since various conditions neet to be fulfilled */
+ if (eelPME == ir->coulombtype)
+ {
+ /* plain PME, rcoulomb must be equal to rlist */
+ ir->rlist = ir->rcoulomb;
+ }
+ else
+ {
+ /* rlist must be >= rcoulomb, we keep the size of the buffer region */
+ ir->rlist = ir->rcoulomb + nlist_buffer;
+ }
+
+ if (evdwCUT == ir->vdwtype)
+ {
+ /* For vdw cutoff, rvdw >= rlist */
+ ir->rvdw = max(info->orig_rvdw, ir->rlist);
+ }
+
+ ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
+
/* Try to reduce the number of reciprocal grid points in a smart way */
/* Did the user supply a value for fourierspacing on the command line? */
if (fourierspacing > 0)
ir->nkx = 0;
ir->nky = 0;
ir->nkz = 0;
- calc_grid(stdout,state.box,info->fourier_sp[j],&(ir->nkx),&(ir->nky),&(ir->nkz),1);
+ calc_grid(stdout,state.box,info->fourier_sp[j],
+ &(ir->nkx),&(ir->nky),&(ir->nkz));
/* Check consistency */
if (0 == j)
- if ((ir->nkx != orig_nk[XX]) || (ir->nky != orig_nk[YY]) || (ir->nkz != orig_nk[ZZ]))
+ if ((ir->nkx != info->orig_nk[XX]) || (ir->nky != info->orig_nk[YY]) || (ir->nkz != info->orig_nk[ZZ]))
{
fprintf(stderr, "WARNING: Original grid was %dx%dx%d. The fourierspacing of %f nm does not reproduce the grid\n"
" found in the tpr input file! Will use the new settings.\n",
- orig_nk[XX],orig_nk[YY],orig_nk[ZZ],fourierspacing);
+ info->orig_nk[XX],info->orig_nk[YY],info->orig_nk[ZZ],fourierspacing);
+ bNote = TRUE;
}
}
else
if (0 == j)
{
/* Print out fourierspacing from input tpr */
- fprintf(stdout, "Input file fourier grid is %dx%dx%d\n", orig_nk[XX], orig_nk[YY], orig_nk[ZZ]);
+ fprintf(stdout, "Input file fourier grid is %dx%dx%d\n",
+ info->orig_nk[XX], info->orig_nk[YY], info->orig_nk[ZZ]);
}
- else
- {
- /* Reconstruct fourierspacing for each dimension from the input file */
- ir->nkx=0;
- calc_grid(stdout,state.box,orig_fs[XX]*fac,&(ir->nkx),&(ir->nky),&(ir->nkz),1);
- ir->nky=0;
- calc_grid(stdout,state.box,orig_fs[YY]*fac,&(ir->nkx),&(ir->nky),&(ir->nkz),1);
- ir->nkz=0;
- calc_grid(stdout,state.box,orig_fs[ZZ]*fac,&(ir->nkx),&(ir->nky),&(ir->nkz),1);
- }
- }
- /* r_vdw should only grow if necessary! */
- if (j > 0)
- {
- ir->rvdw = min(ir->rvdw, orig_rcoulomb*fac);
- ir->rvdw = max(ir->rvdw, orig_rvdw);
+ /* Reconstruct fourierspacing for each dimension from the input file */
+ ir->nkx=0;
+ calc_grid(stdout,state.box,info->orig_fs[XX]*fac,
+ &(ir->nkx),&(ir->nky),&(ir->nkz));
+ ir->nky=0;
+ calc_grid(stdout,state.box,info->orig_fs[YY]*fac,
+ &(ir->nkx),&(ir->nky),&(ir->nkz));
+ ir->nkz=0;
+ calc_grid(stdout,state.box,info->orig_fs[ZZ]*fac,
+ &(ir->nkx),&(ir->nky),&(ir->nkz));
}
+
/* Save modified radii and fourier grid components for later output: */
- info->r_coulomb[j] = ir->rcoulomb;
- info->r_vdW[j] = ir->rvdw;
- info->fourier_nx[j]= ir->nkx;
- info->fourier_ny[j]= ir->nky;
- info->fourier_nz[j]= ir->nkz;
+ info->r_coulomb[j] = ir->rcoulomb;
+ info->r_vdw[j] = ir->rvdw;
+ info->fourier_nx[j] = ir->nkx;
+ info->fourier_ny[j] = ir->nky;
+ info->fourier_nz[j] = ir->nkz;
+ info->rlist[j] = ir->rlist;
+ info->rlistlong[j] = ir->rlistlong;
/* Write the benchmark tpr file */
strncpy(fn_bench_tprs[j],fn_sim_tpr,strlen(fn_sim_tpr)-strlen(".tpr"));
fprintf(stdout,", scaling factor %f\n", fac);
write_tpx_state(fn_bench_tprs[j],ir,&state,&mtop);
- /* Write some info to log file */
- fprintf(fp, "%3d %9f %9f (%7f) %4d %4d %4d %9f %-14s\n",
- j, fac, ir->rcoulomb, ir->rvdw, ir->nkx, ir->nky, ir->nkz, info->fourier_sp[j],fn_bench_tprs[j]);
+ /* Write information about modified tpr settings to log file */
+ fprintf(fp, "%4d%10f%10f", j, fac, ir->rcoulomb);
+ fprintf(fp, "%5d%5d%5d", ir->nkx, ir->nky, ir->nkz);
+ if (fourierspacing > 0)
+ fprintf(fp, "%9f ", info->fourier_sp[j]);
+ if (evdwCUT == ir->vdwtype)
+ fprintf(fp, "%10f", ir->rvdw);
+ if (EPME_SWITCHED(ir->coulombtype))
+ fprintf(fp, "%10f", ir->rlist);
+ if ( info->orig_rlistlong != max_cutoff(info->orig_rlist,max_cutoff(info->orig_rvdw,info->orig_rcoulomb)) )
+ fprintf(fp, "%10f", ir->rlistlong);
+ fprintf(fp, " %-14s\n",fn_bench_tprs[j]);
+
+ /* Make it clear to the user that some additional settings were modified */
+ if ( !is_equal(ir->rvdw , info->orig_rvdw)
+ || !is_equal(ir->rlistlong , info->orig_rlistlong) )
+ {
+ bNote = TRUE;
+ }
}
+ if (bNote)
+ fprintf(fp, "\nNote that in addition to rcoulomb and the fourier grid\n"
+ "also other input settings were changed (see table above).\n"
+ "Please check if the modified settings are appropriate.\n");
fflush(stdout);
fflush(fp);
-
sfree(ir);
}
/* Rename the files we want to keep to some meaningful filename and
* delete the rest */
static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes,
- int nPMEnodes, int nr)
+ int nPMEnodes, int nr, bool bKeepStderr)
{
char numstring[STRLEN];
char newfilename[STRLEN];
rename(opt2fn("-bg",nfile,fnm), newfilename);
}
}
+ else if (strcmp(opt, "-err") == 0)
+ {
+ /* This file contains the output of stderr. We want to keep it in
+ * cases where there have been problems. */
+ fn = opt2fn(opt, nfile, fnm);
+ numstring[0] = '\0';
+ if (nr > 0)
+ sprintf(numstring, "_%d", nr);
+ sprintf(newfilename, "%s_no%d_np%d_npme%d%s", fn, k, nnodes, nPMEnodes, numstring);
+ if (gmx_fexist(fn))
+ {
+ if (bKeepStderr)
+ {
+ fprintf(stdout, "Saving stderr output in %s\n", newfilename);
+ make_backup(newfilename);
+ rename(fn, newfilename);
+ }
+ else
+ {
+ fprintf(stdout, "Deleting %s\n", fn);
+ remove(fn);
+ }
+ }
+ }
/* Delete the files which are created for each benchmark run: (options -b*) */
else if ( ( (0 == strncmp(opt, "-b", 2)) && (opt2bSet(opt,nfile,fnm) || !is_optional(&fnm[i])) )
|| tpr_triggers_file(opt) )
}
-static void do_the_tests(FILE *fp, char **tpr_names, int maxPMEnodes,
- int minPMEnodes,
- int datasets, t_perf **perfdata, int repeats, int nnodes, int nr_tprs,
- char *cmd_mpirun, char *cmd_mdrun,
- char *args_for_mdrun,
- const t_filenm *fnm, int nfile, int sim_part, int presteps,
- gmx_large_int_t cpt_steps)
+/* Returns the largest common factor of n1 and n2 */
+static int largest_common_factor(int n1, int n2)
{
- int i,nr,k,ret;
- int nPMEnodes;
+ int factor, nmax;
+
+ nmax = min(n1, n2);
+ for (factor=nmax; factor > 0; factor--)
+ {
+ if ( 0==(n1 % factor) && 0==(n2 % factor) )
+ {
+ return(factor);
+ }
+ }
+ return 0; /* one for the compiler */
+}
+
+enum {eNpmeAuto, eNpmeAll, eNpmeReduced, eNpmeSubset, eNpmeNr};
+
+/* Create a list of numbers of PME nodes to test */
+static void make_npme_list(
+ const char *npmevalues_opt, /* Make a complete list with all
+ * possibilities or a short list that keeps only
+ * reasonable numbers of PME nodes */
+ int *nentries, /* Number of entries we put in the nPMEnodes list */
+ int *nPMEnodes[], /* Each entry contains the value for -npme */
+ int nnodes, /* Total number of nodes to do the tests on */
+ int minPMEnodes, /* Minimum number of PME nodes */
+ int maxPMEnodes) /* Maximum number of PME nodes */
+{
+ int i,npme,npp;
+ int min_factor=1; /* We request that npp and npme have this minimal
+ * largest common factor (depends on npp) */
+ int nlistmax; /* Max. list size */
+ int nlist; /* Actual number of entries in list */
+ int eNPME=0;
+
+
+ /* Do we need to check all possible values for -npme or is a reduced list enough? */
+ if ( 0 == strcmp(npmevalues_opt, "all") )
+ {
+ eNPME = eNpmeAll;
+ }
+ else if ( 0 == strcmp(npmevalues_opt, "subset") )
+ {
+ eNPME = eNpmeSubset;
+ }
+ else if ( 0 == strcmp(npmevalues_opt, "auto") )
+ {
+ if (nnodes <= 64)
+ eNPME = eNpmeAll;
+ else if (nnodes < 128)
+ eNPME = eNpmeReduced;
+ else
+ eNPME = eNpmeSubset;
+ }
+ else
+ {
+ gmx_fatal(FARGS, "Unknown option for -npme in make_npme_list");
+ }
+
+ /* Calculate how many entries we could possibly have (in case of -npme all) */
+ if (nnodes > 2)
+ {
+ nlistmax = maxPMEnodes - minPMEnodes + 3;
+ if (0 == minPMEnodes)
+ nlistmax--;
+ }
+ else
+ nlistmax = 1;
+
+ /* Now make the actual list which is at most of size nlist */
+ snew(*nPMEnodes, nlistmax);
+ nlist = 0; /* start counting again, now the real entries in the list */
+ for (i = 0; i < nlistmax - 2; i++)
+ {
+ npme = maxPMEnodes - i;
+ npp = nnodes-npme;
+ switch (eNPME)
+ {
+ case eNpmeAll:
+ min_factor = 1;
+ break;
+ case eNpmeReduced:
+ min_factor = 2;
+ break;
+ case eNpmeSubset:
+ /* For 2d PME we want a common largest factor of at least the cube
+ * root of the number of PP nodes */
+ min_factor = (int) pow(npp, 1.0/3.0);
+ break;
+ default:
+ gmx_fatal(FARGS, "Unknown option for eNPME in make_npme_list");
+ break;
+ }
+ if (largest_common_factor(npp, npme) >= min_factor)
+ {
+ (*nPMEnodes)[nlist] = npme;
+ nlist++;
+ }
+ }
+ /* We always test 0 PME nodes and the automatic number */
+ *nentries = nlist + 2;
+ (*nPMEnodes)[nlist ] = 0;
+ (*nPMEnodes)[nlist+1] = -1;
+
+ fprintf(stderr, "Will try the following %d different values for -npme:\n", *nentries);
+ for (i=0; i<*nentries-1; i++)
+ fprintf(stderr, "%d, ", (*nPMEnodes)[i]);
+ fprintf(stderr, "and %d (auto).\n", (*nPMEnodes)[*nentries-1]);
+}
+
+
+/* Allocate memory to store the performance data */
+static void init_perfdata(t_perf *perfdata[], int ntprs, int datasets, int repeats)
+{
+ int i, j, k;
+
+
+ for (k=0; k<ntprs; k++)
+ {
+ snew(perfdata[k], datasets);
+ for (i=0; i<datasets; i++)
+ {
+ for (j=0; j<repeats; j++)
+ {
+ snew(perfdata[k][i].Gcycles , repeats);
+ snew(perfdata[k][i].ns_per_day, repeats);
+ snew(perfdata[k][i].PME_f_load, repeats);
+ }
+ }
+ }
+}
+
+
+static void do_the_tests(
+ FILE *fp, /* General g_tune_pme output file */
+ char **tpr_names, /* Filenames of the input files to test */
+ int maxPMEnodes, /* Max fraction of nodes to use for PME */
+ int minPMEnodes, /* Min fraction of nodes to use for PME */
+ const char *npmevalues_opt, /* Which -npme values should be tested */
+ t_perf **perfdata, /* Here the performace data is stored */
+ int *pmeentries, /* Entries in the nPMEnodes list */
+ int repeats, /* Repeat each test this often */
+ int nnodes, /* Total number of nodes = nPP + nPME */
+ int nr_tprs, /* Total number of tpr files to test */
+ bool bThreads, /* Threads or MPI? */
+ char *cmd_mpirun, /* mpirun command string */
+ char *cmd_np, /* "-np", "-n", whatever mpirun needs */
+ char *cmd_mdrun, /* mdrun command string */
+ char *cmd_args_bench, /* arguments for mdrun in a string */
+ const t_filenm *fnm, /* List of filenames from command line */
+ int nfile, /* Number of files specified on the cmdl. */
+ int sim_part, /* For checkpointing */
+ int presteps, /* DLB equilibration steps, is checked */
+ gmx_large_int_t cpt_steps) /* Time step counter in the checkpoint */
+{
+ int i,nr,k,ret,count=0,totaltests;
+ int *nPMEnodes=NULL;
t_perf *pd=NULL;
int cmdline_length;
- char *command;
+ char *command, *cmd_stub;
char buf[STRLEN];
- char *opt_noaddpart;
bool bResetProblem=FALSE;
-
- /* This string array corresponds to the eParselog enum type from above */
- const char* ParseLog[] = {"OK",
- "Logfile not found",
- "No timings in log file",
- "Run was terminated",
- "Counters were not reset properly"};
+
+ /* This string array corresponds to the eParselog enum type at the start
+ * of this file */
+ const char* ParseLog[] = {"OK.",
+ "Logfile not found!",
+ "No timings, logfile truncated?",
+ "Run was terminated.",
+ "Counters were not reset properly.",
+ "No DD grid found for these settings.",
+ "TPX version conflict!",
+ "mdrun was not started in parallel!",
+ "A fatal error occured!" };
char str_PME_f_load[13];
- /* The -noaddpart option is needed so that the md.log files do not
- * get renamed if checkpoints are used!
- */
- if (sim_part > 1)
- opt_noaddpart=" -noaddpart";
- else
- opt_noaddpart="";
- /* Allocate space for the mdrun command line. 100 extra characters should be more than enough
- * for the -npme etcetera arguments */
+ /* Allocate space for the mdrun command line. 100 extra characters should
+ be more than enough for the -npme etcetera arguments */
cmdline_length = strlen(cmd_mpirun)
+ + strlen(cmd_np)
+ strlen(cmd_mdrun)
- + strlen(args_for_mdrun)
+ + strlen(cmd_args_bench)
+ strlen(tpr_names[0]) + 100;
- snew(command, cmdline_length);
+ snew(command , cmdline_length);
+ snew(cmd_stub, cmdline_length);
+
+ /* Construct the part of the command line that stays the same for all tests: */
+ if (bThreads)
+ {
+ sprintf(cmd_stub, "%s%s", cmd_mdrun, cmd_np);
+ }
+ else
+ {
+ sprintf(cmd_stub, "%s%s%s ", cmd_mpirun, cmd_np, cmd_mdrun);
+ }
+
+ /* Create a list of numbers of PME nodes to test */
+ make_npme_list(npmevalues_opt, pmeentries, &nPMEnodes,
+ nnodes, minPMEnodes, maxPMEnodes);
+
+ if (0 == repeats)
+ {
+ fprintf(fp, "\nNo benchmarks done since number of repeats (-r) is 0.\n");
+ fclose(fp);
+ finalize(opt2fn("-p", nfile, fnm));
+ exit(0);
+ }
+
+ /* Allocate one dataset for each tpr input file: */
+ init_perfdata(perfdata, nr_tprs, *pmeentries, repeats);
- /* Loop over all tpr files to test: */
+ /*****************************************/
+ /* Main loop over all tpr files to test: */
+ /*****************************************/
+ totaltests = nr_tprs*(*pmeentries)*repeats;
for (k=0; k<nr_tprs;k++)
{
fprintf(fp, "\nIndividual timings for input file %d (%s):\n", k, tpr_names[k]);
fprintf(fp, "PME nodes Gcycles ns/day PME/f Remark\n");
- i=0;
- /* Start with the maximum number of PME only nodes: */
- nPMEnodes = maxPMEnodes;
-
/* Loop over various numbers of PME nodes: */
- for (i = 0; i<datasets; i++)
+ for (i = 0; i < *pmeentries; i++)
{
pd = &perfdata[k][i];
/* Loop over the repeats for each scenario: */
for (nr = 0; nr < repeats; nr++)
{
- pd->nPMEnodes = nPMEnodes;
+ pd->nPMEnodes = nPMEnodes[i];
- /* Construct the command line to call mdrun (and save it): */
+ /* Add -npme and -s to the command line and save it. Note that
+ * the -passall (if set) options requires cmd_args_bench to be
+ * at the end of the command line string */
snew(pd->mdrun_cmd_line, cmdline_length);
- sprintf(pd->mdrun_cmd_line, "%s -np %d %s %s-npme %d -s %s%s",
- cmd_mpirun, nnodes, cmd_mdrun, args_for_mdrun, nPMEnodes, tpr_names[k], opt_noaddpart);
+ sprintf(pd->mdrun_cmd_line, "%s-npme %d -s %s %s",
+ cmd_stub, pd->nPMEnodes, tpr_names[k], cmd_args_bench);
/* Do a benchmark simulation: */
if (repeats > 1)
sprintf(buf, ", pass %d/%d", nr+1, repeats);
else
buf[0]='\0';
- fprintf(stdout, "\n=== tpr %d/%d, run %d/%d%s:\n", k+1, nr_tprs, i+1, datasets, buf);
- sprintf(command, "%s -noaddpart >& /dev/null", pd->mdrun_cmd_line);
+ fprintf(stdout, "\n=== Progress %2.0f%%, tpr %d/%d, run %d/%d%s:\n",
+ (100.0*count)/totaltests,
+ k+1, nr_tprs, i+1, *pmeentries, buf);
+ make_backup(opt2fn("-err",nfile,fnm));
+ sprintf(command, "%s 1> /dev/null 2>%s", pd->mdrun_cmd_line, opt2fn("-err",nfile,fnm));
fprintf(stdout, "%s\n", pd->mdrun_cmd_line);
gmx_system_call(command);
- /* Collect the performance data from the log file */
- ret = parse_logfile(opt2fn("-bg",nfile,fnm), pd, nr, presteps, cpt_steps, nnodes);
+ /* Collect the performance data from the log file; also check stderr
+ * for fatal errors */
+ ret = parse_logfile(opt2fn("-bg",nfile,fnm), opt2fn("-err",nfile,fnm),
+ pd, nr, presteps, cpt_steps, nnodes);
if ((presteps > 0) && (ret == eParselogResetProblem))
bResetProblem = TRUE;
- if (nPMEnodes == -1)
+ if (-1 == pd->nPMEnodes)
sprintf(buf, "(%3d)", pd->guessPME);
else
sprintf(buf, " ");
sprintf(str_PME_f_load, "%s", " - ");
/* Write the data we got to disk */
- fprintf(fp, "%4d%s %12.3f %12.3f %s %s\n", pd->nPMEnodes, buf, pd->Gcycles[nr], pd->ns_per_day[nr], str_PME_f_load, ParseLog[ret]);
+ fprintf(fp, "%4d%s %12.3f %12.3f %s %s", pd->nPMEnodes,
+ buf, pd->Gcycles[nr], pd->ns_per_day[nr], str_PME_f_load, ParseLog[ret]);
+ if (! (ret==eParselogOK || ret==eParselogNoDDGrid || ret==eParselogNotFound) )
+ fprintf(fp, " Check %s file for problems.", ret==eParselogFatal? "err":"log");
+ fprintf(fp, "\n");
fflush(fp);
+ count++;
/* Do some cleaning up and delete the files we do not need any more */
- cleanup(fnm, nfile, k, nnodes, nPMEnodes, nr);
+ cleanup(fnm, nfile, k, nnodes, pd->nPMEnodes, nr, ret==eParselogFatal);
/* If the first run with this number of processors already failed, do not try again: */
if (pd->Gcycles[0] <= 0.0 && repeats > 1)
{
fprintf(stdout, "Skipping remaining passes of unsuccessful setting, see log file for details.\n");
+ count += repeats-(nr+1);
break;
}
- }
- /* Prepare for the next number of PME only nodes */
- /* The last but one check is always without MPMD PME ... */
- if ((nPMEnodes == minPMEnodes) && (0 != minPMEnodes))
- nPMEnodes = 0;
- /* ... and the last check with the guessed settings */
- else if (nPMEnodes == 0)
- nPMEnodes = -1;
- else
- nPMEnodes--;
- }
- }
+ } /* end of repeats loop */
+ } /* end of -npme loop */
+ } /* end of tpr file loop */
if (bResetProblem)
{
sep_line(fp);
"value normally provided by -presteps.");
sep_line(fp);
}
-}
-
-
-static bool is_equal(real a, real b)
-{
- real diff, eps=1.0e-6;
-
-
- diff = a - b;
-
- if (diff < 0.0) diff = -diff;
-
- if (diff < eps)
- return TRUE;
- else
- return FALSE;
+ sfree(command);
+ sfree(cmd_stub);
}
int nnodes,
int repeats,
int *ntprs,
- real maxfac,
+ real *upfac,
+ real *downfac,
real maxPMEfraction,
real minPMEfraction,
real fourierspacing,
const t_filenm *fnm,
int nfile,
int sim_part,
- int presteps)
+ int presteps,
+ int npargs,
+ t_pargs *pa)
{
- /* Make shure the input file exists */
+ /* Make sure the input file exists */
if (!gmx_fexist(opt2fn("-s",nfile,fnm)))
gmx_fatal(FARGS, "File %s not found.", opt2fn("-s",nfile,fnm));
- /* Make shure that the checkpoint file is not overwritten by the benchmark runs */
+ /* Make sure that the checkpoint file is not overwritten by the benchmark runs */
if ( (0 == strcmp(opt2fn("-cpi",nfile,fnm), opt2fn("-cpo",nfile,fnm)) ) && (sim_part > 1) )
gmx_fatal(FARGS, "Checkpoint input and output file must not be identical,\nbecause then the input file might change during the benchmarks.");
- /* Make shure that repeats is >= 0 (if == 0, only write tpr files) */
+ /* Make sure that repeats is >= 0 (if == 0, only write tpr files) */
if (repeats < 0)
gmx_fatal(FARGS, "Number of repeats < 0!");
/* Check number of nodes */
if (nnodes < 1)
- gmx_fatal(FARGS, "Number of nodes must be a positive integer.");
+ gmx_fatal(FARGS, "Number of nodes/threads must be a positive integer.");
/* Automatically choose -ntpr if not set */
if (*ntprs < 1)
}
else
{
- if ( (1 == *ntprs) && !is_equal(maxfac,1.0) )
- fprintf(stderr, "Note: Choose ntpr>1 to shift PME load to real space.\n");
+ if (1 == *ntprs)
+ fprintf(stderr, "Note: Choose ntpr>1 to shift PME load between real and reciprocal space.\n");
}
- if ( is_equal(1.0,maxfac) && (*ntprs > 1) )
+ if ( is_equal(*downfac,*upfac) && (*ntprs > 1) )
{
- fprintf(stderr, "WARNING: Resetting -ntpr to 1 since upscaling factor equals unity.\n Please select -fac>1 if you want to test various PME grid settings\n");
+ fprintf(stderr, "WARNING: Resetting -ntpr to 1 since both scaling factors are the same.\n"
+ "Please choose upfac unequal to downfac to test various PME grid settings\n");
*ntprs = 1;
}
{
fprintf(stderr, "WARNING: steps=");
fprintf(stderr, gmx_large_int_pfmt, bench_nsteps);
- fprintf(stderr, ". Are you shure you want to perform so %s steps for each benchmark?\n", (bench_nsteps < 100)? "few" : "many");
+ fprintf(stderr, ". Are you sure you want to perform so %s steps for each benchmark?\n", (bench_nsteps < 100)? "few" : "many");
}
if (presteps < 0)
gmx_fatal(FARGS, "Cannot have a negative number of presteps.\n");
}
- if (maxfac <= 0.0)
- gmx_fatal(FARGS, "Scaling factor must be larger than zero.");
-
- if (maxfac < 1.0)
- fprintf(stderr, "WARNING: A scaling factor smaller than one means that load will be shifted to reciprocal space. Are you shure you want that?\n");
+ if (*upfac <= 0.0 || *downfac <= 0.0 || *downfac > *upfac)
+ gmx_fatal(FARGS, "Both scaling factors must be larger than zero and upper\n"
+ "scaling limit (%f) must be larger than lower limit (%f).",
+ *upfac, *downfac);
- if (maxfac < 0.75 || maxfac > 1.5)
+ if (*downfac < 0.75 || *upfac > 1.5)
fprintf(stderr, "WARNING: Applying extreme scaling factor. I hope you know what you are doing.\n");
if (fourierspacing < 0)
gmx_fatal(FARGS, "Please choose a positive value for fourierspacing.");
+
+ /* Make shure that the scaling factor options are compatible with the number of tprs */
+ if ( (1 == *ntprs) && ( opt2parg_bSet("-upfac",npargs,pa) || opt2parg_bSet("-downfac",npargs,pa) ) )
+ {
+ if (opt2parg_bSet("-upfac",npargs,pa) && opt2parg_bSet("-downfac",npargs,pa) && !is_equal(*upfac,*downfac))
+ {
+ gmx_fatal(FARGS, "Please specify -ntpr > 1 for both scaling factors to take effect.\n"
+ "(upfac=%f, downfac=%f)\n", *upfac, *downfac);
+ }
+ if (opt2parg_bSet("-upfac",npargs,pa))
+ *downfac = *upfac;
+ if (opt2parg_bSet("-downfac",npargs,pa))
+ *upfac = *downfac;
+ if (!is_equal(*upfac, 1.0))
+ {
+ fprintf(stderr, "WARNING: Using a scaling factor of %f with -ntpr 1, thus not testing the original tpr settings.\n",
+ *upfac);
+ }
+ }
}
|| (0 == strcmp(opt,"-ntpr" ))
|| (0 == strcmp(opt,"-max" ))
|| (0 == strcmp(opt,"-min" ))
- || (0 == strcmp(opt,"-fac" ))
+ || (0 == strcmp(opt,"-upfac" ))
+ || (0 == strcmp(opt,"-downfac" ))
|| (0 == strcmp(opt,"-four" ))
|| (0 == strcmp(opt,"-steps" ))
|| (0 == strcmp(opt,"-simsteps" ))
|| (0 == strcmp(opt,"-resetstep"))
- || (0 == strcmp(opt,"-so" )) )
+ || (0 == strcmp(opt,"-so" ))
+ || (0 == strcmp(opt,"-npstring" ))
+ || (0 == strcmp(opt,"-npme" ))
+ || (0 == strcmp(opt,"-passall" )) )
return TRUE;
return FALSE;
* This includes -cpi */
if (bSet)
{
- if ( (0 == strcmp(opt, "-append" ))
- || (0 == strcmp(opt, "-addpart"))
- || (0 == strcmp(opt, "-maxh" )) )
+ if ( (0 == strcmp(opt, "-append" ))
+ || (0 == strcmp(opt, "-maxh" ))
+ || (0 == strcmp(opt, "-deffnm" ))
+ || (0 == strcmp(opt, "-resethway"))
+ || (0 == strcmp(opt, "-cpnum" )) )
return FALSE;
else
return TRUE;
}
-/* Adds 'buf' to 'cmd_args' */
-static void add_to_command_line(char **cmd_args, char *buf)
+/* Adds 'buf' to 'str' */
+static void add_to_string(char **str, char *buf)
{
int len;
- len = strlen(*cmd_args) + strlen(buf) + 1;
- srenew(*cmd_args, len);
- strcat(*cmd_args, buf);
+ len = strlen(*str) + strlen(buf) + 1;
+ srenew(*str, len);
+ strcat(*str, buf);
}
/* Create the command line for the benchmark as well as for the real run */
static void create_command_line_snippets(
+ bool bThreads,
int presteps,
int nfile,
t_filenm fnm[],
int npargs,
t_pargs *pa,
- char *cmd_np[], /* -np string */
+ const char *procstring, /* How to pass the number of processors to $MPIRUN */
+ char *cmd_np[], /* Actual command line snippet, e.g. '-np <N>' */
char *cmd_args_bench[], /* command line arguments for benchmark runs */
- char *cmd_args_launch[]) /* command line arguments for simulation run */
+ char *cmd_args_launch[], /* command line arguments for simulation run */
+ char extra_args[]) /* Add this to the end of the command line */
{
int i;
char *opt;
const char *name;
+ char *np_or_nt;
#define BUFLENGTH 255
char buf[BUFLENGTH];
char strbuf[BUFLENGTH];
char strbuf2[BUFLENGTH];
+
+ if (bThreads)
+ np_or_nt=strdup("-nt");
+ else
+ np_or_nt=strdup("-np");
/* strlen needs at least '\0' as a string: */
snew(*cmd_args_bench ,1);
{
/* What command line switch are we currently processing: */
opt = (char *)pa[i].option;
-
/* Skip options not meant for mdrun */
if (!is_main_switch(opt))
{
sprintf(strbuf2, "%s", pa_val(&pa[i],buf,BUFLENGTH));
rtrim(strbuf2);
sprintf(strbuf, "%s %s ", opt, strbuf2);
- /* We need the -np switch in an extra buffer - whether or not it was set! */
- if (0 == strcmp(opt,"-np"))
+ /* We need the -np (or -nt) switch in a separate buffer - whether or not it was set! */
+ if (0 == strcmp(opt,np_or_nt))
{
- snew(*cmd_np, strlen(strbuf)+1);
- sprintf(*cmd_np, " %s", strbuf);
+ if (strcmp(procstring, "none")==0 && !bThreads)
+ {
+ /* Omit -np <N> entirely */
+ snew(*cmd_np, 2);
+ sprintf(*cmd_np, " ");
+ }
+ else
+ {
+ /* This is the normal case with -np <N> */
+ snew(*cmd_np, strlen(procstring)+strlen(strbuf2)+4);
+ sprintf(*cmd_np, " %s %s ", bThreads? "-nt" : procstring, strbuf2);
+ }
}
else
{
if (is_bench_option(opt,pa[i].bSet))
- add_to_command_line(cmd_args_bench, strbuf);
+ add_to_string(cmd_args_bench, strbuf);
if (is_launch_option(opt,pa[i].bSet))
- add_to_command_line(cmd_args_launch, strbuf);
+ add_to_string(cmd_args_launch, strbuf);
}
}
}
{
/* Add equilibration steps to benchmark options */
sprintf(strbuf, "-resetstep %d ", presteps);
- add_to_command_line(cmd_args_bench, strbuf);
+ add_to_string(cmd_args_bench, strbuf);
}
/********************/
if ( is_bench_file(opt, opt2bSet(opt,nfile,fnm), is_optional(&fnm[i]), is_output(&fnm[i])) )
{
- /* All options starting with -b* need th 'b' removed,
+ /* All options starting with -b* need the 'b' removed,
* therefore overwrite strbuf */
if (0 == strncmp(opt, "-b", 2))
sprintf(strbuf, "-%s %s ", &opt[2], name);
- add_to_command_line(cmd_args_bench, strbuf);
+ add_to_string(cmd_args_bench, strbuf);
}
if ( is_launch_file(opt,opt2bSet(opt,nfile,fnm)) )
- add_to_command_line(cmd_args_launch, strbuf);
+ add_to_string(cmd_args_launch, strbuf);
}
}
-#undef BUFLENGTH
+
+ add_to_string(cmd_args_bench , extra_args);
+ add_to_string(cmd_args_launch, extra_args);
+#undef BUFLENGTH
}
int gmx_tune_pme(int argc,char *argv[])
{
const char *desc[] = {
- "For a given number [TT]-np[tt] of processors this program systematically",
+ "For a given number [TT]-np[tt] or [TT]-nt[tt] of processors/threads, this program systematically",
"times mdrun with various numbers of PME-only nodes and determines",
"which setting is fastest. It will also test whether performance can",
"be enhanced by shifting load from the reciprocal to the real space",
- "part of the Ewald sum. "
+ "part of the Ewald sum. ",
"Simply pass your [TT].tpr[tt] file to g_tune_pme together with other options",
"for mdrun as needed.[PAR]",
"Which executables are used can be set in the environment variables",
"'export MPIRUN=\"/usr/local/mpirun -machinefile hosts\"'[PAR]",
"Please call g_tune_pme with the normal options you would pass to",
"mdrun and add [TT]-np[tt] for the number of processors to perform the",
- "tests on. You can also add [TT]-r[tt] to repeat each test several times",
- "to get better statistics. [PAR]",
+ "tests on, or [TT]-nt[tt] for the number of threads. You can also add [TT]-r[tt]",
+ "to repeat each test several times to get better statistics. [PAR]",
"g_tune_pme can test various real space / reciprocal space workloads",
"for you. With [TT]-ntpr[tt] you control how many extra [TT].tpr[tt] files will be",
"written with enlarged cutoffs and smaller fourier grids respectively.",
- "The first test (no. 0) will be with the settings from the input",
+ "Typically, the first test (no. 0) will be with the settings from the input",
"[TT].tpr[tt] file; the last test (no. [TT]ntpr[tt]) will have cutoffs multiplied",
"by (and at the same time fourier grid dimensions divided by) the scaling",
"factor [TT]-fac[tt] (default 1.2). The remaining [TT].tpr[tt] files will have equally",
"spaced values inbetween these extremes. Note that you can set [TT]-ntpr[tt] to 1",
"if you just want to find the optimal number of PME-only nodes; in that case",
- "your input [TT].tpr[tt] file will remain unchanged[PAR]",
- "For the benchmark runs, 2500 time steps should suffice for most MD",
- "systems. Note that dynamic load balancing needs about 100 time steps",
- "to adapt to local load imbalances. To get clean benchmark numbers,",
- "[TT]-steps[tt] should therefore always be much larger than 100![PAR]",
+ "your input [TT].tpr[tt] file will remain unchanged.[PAR]",
+ "For the benchmark runs, the default of 1000 time steps should suffice for most",
+ "MD systems. The dynamic load balancing needs about 100 time steps",
+ "to adapt to local load imbalances, therefore the time step counters",
+ "are by default reset after 100 steps. For large systems",
+ "(>1M atoms) you may have to set [TT]-resetstep[tt] to a higher value.",
+ "From the 'DD' load imbalance entries in the md.log output file you",
+ "can tell after how many steps the load is sufficiently balanced.[PAR]"
"Example call: [TT]g_tune_pme -np 64 -s protein.tpr -launch[tt][PAR]",
"After calling mdrun several times, detailed performance information",
- "is available in the output file perf.out. "
+ "is available in the output file perf.out. ",
"Note that during the benchmarks a couple of temporary files are written",
- "(options -b*), these will be automatically deleted after each test.[PAR]"
+ "(options -b*), these will be automatically deleted after each test.[PAR]",
"If you want the simulation to be started automatically with the",
"optimized parameters, use the command line option [TT]-launch[tt].[PAR]",
};
- int nnodes =3;
+ int nnodes =1;
int repeats=2;
+ int pmeentries=0; /* How many values for -npme do we actually test for each tpr file */
real maxPMEfraction=0.50;
real minPMEfraction=0.25;
int maxPMEnodes, minPMEnodes;
- real maxfac=1.2;
+ real downfac=1.0,upfac=1.2;
int ntprs=0;
- real fs=0.0; /* 0 indicates: not set by the user */
+ real fs=0.0; /* 0 indicates: not set by the user */
gmx_large_int_t bench_nsteps=BENCHSTEPS;
- gmx_large_int_t new_sim_nsteps=-1; /* -1 indicates: not set by the user */
- gmx_large_int_t cpt_steps=0; /* Step counter in .cpt input file */
- int presteps=100; /* Do a full cycle reset after presteps steps */
- bool bOverwrite=FALSE;
+ gmx_large_int_t new_sim_nsteps=-1; /* -1 indicates: not set by the user */
+ gmx_large_int_t cpt_steps=0; /* Step counter in .cpt input file */
+ int presteps=100; /* Do a full cycle reset after presteps steps */
+ bool bOverwrite=FALSE, bKeepTPR;
bool bLaunch=FALSE;
+ bool bPassAll=FALSE;
+ char *ExtraArgs=NULL;
char **tpr_names=NULL;
const char *simulation_tpr=NULL;
int best_npme, best_tpr;
/* Default program names if nothing else is found */
char *cmd_mpirun=NULL, *cmd_mdrun=NULL;
- char *cmd_args_bench, *cmd_args_launch, *cmd_np;
+ char *cmd_args_bench, *cmd_args_launch;
+ char *cmd_np=NULL;
- t_perf **perfdata;
+ t_perf **perfdata=NULL;
t_inputinfo *info;
- int datasets;
- int i,j,k;
+ int i;
FILE *fp;
t_commrec *cr;
static t_filenm fnm[] = {
/* g_tune_pme */
{ efOUT, "-p", "perf", ffWRITE },
+ { efLOG, "-err", "errors", ffWRITE },
{ efTPX, "-so", "tuned", ffWRITE },
/* mdrun: */
{ efTPX, NULL, NULL, ffREAD },
bool bIonize = FALSE;
bool bConfout = TRUE;
bool bReproducible = FALSE;
+ bool bThreads = FALSE;
int nmultisim=0;
int nstglobalcomm=-1;
{ NULL, "interleave", "pp_pme", "cartesian", NULL };
const char *dddlb_opt[] =
{ NULL, "auto", "no", "yes", NULL };
+ const char *procstring[] =
+ { NULL, "-np", "-n", "none", NULL };
+ const char *npmevalues_opt[] =
+ { NULL, "auto", "all", "subset", NULL };
real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
+ char *deffnm=NULL;
#define STD_CPT_PERIOD (15.0)
real cpt_period=STD_CPT_PERIOD,max_hours=-1;
- bool bAppendFiles=FALSE,bAddPart=TRUE;
- output_env_t oenv;
+ bool bAppendFiles=TRUE;
+ bool bKeepAndNumCPT=FALSE;
+ bool bResetCountersHalfWay=FALSE;
+ output_env_t oenv=NULL;
t_pargs pa[] = {
/***********************/
/***********************/
{ "-np", FALSE, etINT, {&nnodes},
"Number of nodes to run the tests on (must be > 2 for separate PME nodes)" },
+ { "-npstring", FALSE, etENUM, {procstring},
+ "Specify the number of processors to $MPIRUN using this string"},
+ { "-passall", FALSE, etBOOL, {&bPassAll},
+ "HIDDENPut arguments unknown to mdrun at the end of the command line. Can e.g. be used for debugging purposes. "},
+ { "-nt", FALSE, etINT, {&nthreads},
+ "Number of threads to run the tests on (turns MPI & mpirun off)"},
{ "-r", FALSE, etINT, {&repeats},
"Repeat each test this often" },
{ "-max", FALSE, etREAL, {&maxPMEfraction},
"Max fraction of PME nodes to test with" },
{ "-min", FALSE, etREAL, {&minPMEfraction},
"Min fraction of PME nodes to test with" },
- { "-fac", FALSE, etREAL, {&maxfac},
- "Max upscaling factor for rcoulomb (= downscaling factor for the fourier grid)" },
+ { "-npme", FALSE, etENUM, {npmevalues_opt},
+ "Benchmark all possible values for -npme or just the subset that is expected to perform well"},
+ { "-upfac", FALSE, etREAL, {&upfac},
+ "Upper limit for rcoulomb scaling factor (Note that rcoulomb upscaling results in fourier grid downscaling)" },
+ { "-downfac", FALSE, etREAL, {&downfac},
+ "Lower limit for rcoulomb scaling factor" },
{ "-ntpr", FALSE, etINT, {&ntprs},
"Number of tpr files to benchmark. Create these many files with scaling factors ranging from 1.0 to fac. If < 1, automatically choose the number of tpr files to test" },
{ "-four", FALSE, etREAL, {&fs},
- "Use this fourierspacing value instead of the grid found in the tpr input file" },
+ "Use this fourierspacing value instead of the grid found in the tpr input file. (Spacing applies to a scaling factor of 1.0 if multiple tpr files are written)" },
{ "-steps", FALSE, etGMX_LARGE_INT, {&bench_nsteps},
"Take timings for these many steps in the benchmark runs" },
{ "-resetstep",FALSE, etINT, {&presteps},
- "Let dlb equilibrate these many steps before timings are taken" },
+ "Let dlb equilibrate these many steps before timings are taken (reset cycle counters after these many steps)" },
{ "-simsteps", FALSE, etGMX_LARGE_INT, {&new_sim_nsteps},
"If non-negative, perform these many steps in the real run (overwrite nsteps from tpr, add cpt steps)" },
{ "-launch", FALSE, etBOOL, {&bLaunch},
/******************/
/* mdrun options: */
/******************/
- { "-nt", FALSE, etINT, {&nthreads},
- "HIDDENNumber of threads to start on each node" },
+ { "-deffnm", FALSE, etSTR, {&deffnm},
+ "Set the default filename for all file options at launch time" },
{ "-ddorder", FALSE, etENUM, {ddno_opt},
"DD node order" },
{ "-ddcheck", FALSE, etBOOL, {&bDDBondCheck},
"Try to avoid optimizations that affect binary reproducibility" },
{ "-cpt", FALSE, etREAL, {&cpt_period},
"Checkpoint interval (minutes)" },
+ { "-cpnum", FALSE, etBOOL, {&bKeepAndNumCPT},
+ "Keep and number checkpoint files" },
{ "-append", FALSE, etBOOL, {&bAppendFiles},
- "Append to previous output files when continuing from checkpoint" },
- { "-addpart", FALSE, etBOOL, {&bAddPart},
- "Add the simulation part number to all output files when continuing from checkpoint" },
+ "Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names (for launch only)" },
{ "-maxh", FALSE, etREAL, {&max_hours},
"Terminate after 0.99 times this time (hours)" },
{ "-multi", FALSE, etINT, {&nmultisim},
{ "-confout", FALSE, etBOOL, {&bConfout},
"HIDDENWrite the last configuration with -c and force checkpointing at the last step" },
{ "-stepout", FALSE, etINT, {&nstepout},
- "HIDDENFrequency of writing the remaining runtime" }
+ "HIDDENFrequency of writing the remaining runtime" },
+ { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
+ "HIDDENReset the cycle counters after half the number of steps or halfway -maxh (launch only)" }
};
NFILE,fnm,asize(pa),pa,asize(desc),desc,
0,NULL,&oenv);
+ /* Store the remaining unparsed command line entries in a string */
+ snew(ExtraArgs, 1);
+ ExtraArgs[0] = '\0';
+ for (i=1; i<argc; i++) /* argc will now be 1 if everything was understood */
+ {
+ add_to_string(&ExtraArgs, argv[i]);
+ add_to_string(&ExtraArgs, " ");
+ }
+ if ( !bPassAll && (ExtraArgs[0] != '\0') )
+ {
+ fprintf(stderr, "\nWARNING: The following arguments you provided have no effect:\n"
+ "%s\n"
+ "Use the -passall option to force them to appear on the command lines\n"
+ "for the benchmark simulations%s.\n\n",
+ ExtraArgs, bLaunch? " and at launch time" : "");
+ }
+
+ if (opt2parg_bSet("-nt",asize(pa),pa))
+ {
+ bThreads=TRUE;
+ if (opt2parg_bSet("-npstring",asize(pa),pa))
+ fprintf(stderr, "WARNING: -npstring has no effect when using threads.\n");
+
+ if (nnodes > 1)
+ gmx_fatal(FARGS, "Can't run multi-threaded MPI simulation yet!");
+ /* and now we just set this; a bit of an ugly hack*/
+ nnodes=nthreads;
+ }
/* Automatically set -beo options if -eo is set etc. */
couple_files_options(NFILE,fnm);
/* Construct the command line arguments for benchmark runs
* as well as for the simulation run
*/
- create_command_line_snippets(presteps,NFILE,fnm,asize(pa),pa,
- &cmd_np, &cmd_args_bench, &cmd_args_launch);
+ create_command_line_snippets(bThreads,presteps,NFILE,fnm,asize(pa),pa,procstring[0],
+ &cmd_np, &cmd_args_bench, &cmd_args_launch,
+ bPassAll? ExtraArgs : (char *)"");
/* Read in checkpoint file if requested */
sim_part = 1;
sim_part++;
/* sim_part will now be 1 if no checkpoint file was found */
if (sim_part<=1)
- gmx_fatal(FARGS, "Checkpoint file %s not found!", opt2fn("-cpi",NFILE,fnm));
+ gmx_fatal(FARGS, "Checkpoint file %s not found!", opt2fn("-cpi",
+ NFILE,
+ fnm));
}
/* Open performance output file and write header info */
fp = ffopen(opt2fn("-p",NFILE,fnm),"w");
/* Make a quick consistency check of command line parameters */
- check_input(nnodes, repeats, &ntprs, maxfac, maxPMEfraction, minPMEfraction,
- fs, bench_nsteps, fnm, NFILE, sim_part, presteps);
+ check_input(nnodes, repeats, &ntprs, &upfac, &downfac, maxPMEfraction,
+ minPMEfraction, fs, bench_nsteps, fnm, NFILE, sim_part, presteps,
+ asize(pa),pa);
/* Determine max and min number of PME nodes to test: */
if (nnodes > 2)
}
/* Get the commands we need to set up the runs from environment variables */
- get_program_paths(&cmd_mpirun, &cmd_mdrun, repeats);
+ get_program_paths(bThreads, &cmd_mpirun, cmd_np, &cmd_mdrun, repeats);
/* Print some header info to file */
sep_line(fp);
fprintf(fp, "\n P E R F O R M A N C E R E S U L T S\n");
sep_line(fp);
fprintf(fp, "%s for Gromacs %s\n", ShortProgram(),GromacsVersion());
- fprintf(fp, "Number of nodes : %d\n", nnodes);
- fprintf(fp, "The mpirun command is : %s\n", cmd_mpirun);
+ if (!bThreads)
+ {
+ fprintf(fp, "Number of nodes : %d\n", nnodes);
+ fprintf(fp, "The mpirun command is : %s\n", cmd_mpirun);
+ if ( strcmp(procstring[0], "none") != 0)
+ fprintf(fp, "Passing # of nodes via : %s\n", procstring[0]);
+ else
+ fprintf(fp, "Not setting number of nodes in system call\n");
+ }
+ else
+ fprintf(fp, "Number of threads : %d\n", nnodes);
+
fprintf(fp, "The mdrun command is : %s\n", cmd_mdrun);
- fprintf(fp, "Input file is : %s\n", opt2fn("-s",NFILE,fnm));
fprintf(fp, "mdrun args benchmarks : %s\n", cmd_args_bench);
fprintf(fp, "Benchmark steps : ");
fprintf(fp, gmx_large_int_pfmt, bench_nsteps);
}
if (bLaunch)
fprintf(fp, "mdrun args at launchtime: %s\n", cmd_args_launch);
+ if (!bPassAll && ExtraArgs[0] != '\0')
+ fprintf(fp, "Unused arguments : %s\n", ExtraArgs);
if (new_sim_nsteps >= 0)
{
bOverwrite = TRUE;
fprintf(fp, "Repeats for each test : %d\n", repeats);
if (fs > 0.0)
+ {
fprintf(fp, "Requested grid spacing : %f (tpr file will be changed accordingly)\n", fs);
+ fprintf(fp, " This will be the grid spacing at a scaling factor of 1.0\n");
+ }
+ fprintf(fp, "Input file : %s\n", opt2fn("-s",NFILE,fnm));
+
/* Allocate memory for the inputinfo struct: */
snew(info, 1);
info->nr_inputfiles = ntprs;
for (i=0; i<ntprs; i++)
{
snew(info->r_coulomb , ntprs);
- snew(info->r_vdW , ntprs);
+ snew(info->r_vdw , ntprs);
+ snew(info->rlist , ntprs);
+ snew(info->rlistlong , ntprs);
snew(info->fourier_nx, ntprs);
snew(info->fourier_ny, ntprs);
snew(info->fourier_nz, ntprs);
for (i=0; i<ntprs; i++)
snew(tpr_names[i], STRLEN);
- make_benchmark_tprs(opt2fn("-s",NFILE,fnm), tpr_names, bench_nsteps+presteps, cpt_steps, maxfac, ntprs, fs, info, fp);
+ make_benchmark_tprs(opt2fn("-s",NFILE,fnm), tpr_names, bench_nsteps+presteps,
+ cpt_steps, upfac, downfac, ntprs, fs, info, fp);
- if (repeats == 0)
- {
- fprintf(stderr, "Nothing more to do.\n");
- fprintf(fp, "\nNo benchmarks done since number of repeats (-r) is 0.\n");
- thanx(stderr);
- return 0;
- }
-
- /* Memory allocation for performance data */
- if (nnodes > 2)
- {
- datasets = maxPMEnodes - minPMEnodes + 3;
- if (0 == minPMEnodes)
- datasets--;
- }
- else
- datasets = 1;
-
- /* Allocate one dataset for each tpr input file: */
- snew(perfdata, ntprs);
-
- /* Allocate a subset for each test with a given number of PME nodes */
- for (k=0; k<ntprs; k++)
- {
- snew(perfdata[k], datasets);
- for (i=0; i<datasets; i++)
- {
- for (j=0; j<repeats; j++)
- {
- snew(perfdata[k][i].Gcycles , repeats);
- snew(perfdata[k][i].ns_per_day, repeats);
- snew(perfdata[k][i].PME_f_load, repeats);
- }
- }
- }
/********************************************************************************/
/* Main loop over all scenarios we need to test: tpr files, PME nodes, repeats */
/********************************************************************************/
- do_the_tests(fp, tpr_names, maxPMEnodes, minPMEnodes, datasets, perfdata, repeats, nnodes, ntprs,
- cmd_mpirun, cmd_mdrun, cmd_args_bench, fnm, NFILE, sim_part, presteps, cpt_steps);
+ snew(perfdata, ntprs);
+ do_the_tests(fp, tpr_names, maxPMEnodes, minPMEnodes, npmevalues_opt[0], perfdata, &pmeentries,
+ repeats, nnodes, ntprs, bThreads, cmd_mpirun, cmd_np, cmd_mdrun,
+ cmd_args_bench, fnm, NFILE, sim_part, presteps, cpt_steps);
fprintf(fp, "\nTuning took%8.1f minutes.\n", (gettime()-seconds)/60.0);
/* Analyse the results and give a suggestion for optimal settings: */
- analyze_data(fp, perfdata, nnodes, ntprs, datasets, repeats, info, &best_tpr, &best_npme);
+ bKeepTPR = analyze_data(fp, opt2fn("-p", NFILE, fnm), perfdata, nnodes, ntprs, pmeentries,
+ repeats, info, &best_tpr, &best_npme);
/* Take the best-performing tpr file and enlarge nsteps to original value */
- if ((best_tpr > 0) || bOverwrite || (fs > 0.0))
+ if ( bKeepTPR && !bOverwrite && !(fs > 0.0) )
{
- simulation_tpr = opt2fn("-so",NFILE,fnm);
- modify_PMEsettings(bOverwrite? (new_sim_nsteps+cpt_steps):info->orig_sim_steps, tpr_names[best_tpr], simulation_tpr);
+ simulation_tpr = opt2fn("-s",NFILE,fnm);
}
else
- simulation_tpr = opt2fn("-s",NFILE,fnm);
+ {
+ simulation_tpr = opt2fn("-so",NFILE,fnm);
+ modify_PMEsettings(bOverwrite? (new_sim_nsteps+cpt_steps) :
+ info->orig_sim_steps, tpr_names[best_tpr],
+ simulation_tpr);
+ }
/* Now start the real simulation if the user requested it ... */
- launch_simulation(bLaunch, fp, cmd_mpirun, cmd_mdrun, cmd_args_launch,
- simulation_tpr, nnodes, best_npme);
+ launch_simulation(bLaunch, fp, bThreads, cmd_mpirun, cmd_np, cmd_mdrun,
+ cmd_args_launch, simulation_tpr, nnodes, best_npme);
ffclose(fp);
/* ... or simply print the performance results to screen: */
if (!bLaunch)
- {
- char buf[STRLEN];
-
- fp = fopen(opt2fn("-p", NFILE, fnm),"r");
- fprintf(stdout,"\n\n");
-
- while( fgets(buf,STRLEN-1,fp) != NULL )
- {
- fprintf(stdout,"%s",buf);
- }
- fclose(fp);
- fprintf(stdout,"\n\n");
- thanx(stderr);
- }
+ finalize(opt2fn("-p", NFILE, fnm));
return 0;
}
int ePBC;
matrix boxtop,box,*sbox,avbox,corr;
rvec *xtop,*x,**sx;
- int status,isize,nalloc,nallocn,natom;
+ int isize,nalloc,nallocn,natom;
+ t_trxstatus *status;
atom_id *index;
char *grpname;
int nfr,f,ff,i,m,mat_nx=0,nbin=0,bin,mbin,fbin;
char *grpname;
char title[256];
real t0,t1,m;
- int status,teller,n_alloc,i,j,tel3,k,l;
+ t_trxstatus *status;
+ int teller,n_alloc,i,j,tel3,k,l;
rvec mv_mol;
real **c1;
real *normm=NULL;
if (ir.ePull != epullUMBRELLA)
gmx_fatal(FARGS,"This is not a tpr of an umbrella simulation. Found ir.ePull = %s\n",
- epullg_names[ir.ePull]);
+ epull_names[ir.ePull]);
/* nr of pull groups */
ngrp=ir.pull->ngrp;
"[TT]*[tt] Same as the previous input mode, except that the the user",
" provides the pull force ouput file names (pullf.xvg) with option -if.",
" From the pull force the position in the ubrella potential is",
- " computed. This does not work with tabulated umbrella potentials."
+ " computed. This does not work with tabulated umbrella potentials.",
"[TT]*[tt] With option [TT]-ip[tt], the user provides filenames of (gzipped) pdo files, i.e.",
- " the gromacs 3.3 umbrella output files. If you have some unusual"
+ " the gromacs 3.3 umbrella output files. If you have some unusual",
" reaction coordinate you may also generate your own pdo files and",
" feed them with the -ip option into to g_wham. The pdo file header",
" must be similar to the folowing:[BR]",
"position to be zero, choose with -zprof0 (useful with bootstrapping, see below).[PAR]",
"For cyclic (or periodic) reaction coordinates (dihedral angle, channel PMF",
"without osmotic gradient), -cycl is useful.[BR]",
- "[TT]-cycl yes[tt] min and max are assumed to "
+ "[TT]-cycl yes[tt] min and max are assumed to",
"be neighboring points and histogram points outside min and max are mapped into ",
"the interval [min,max] (compare histogram output). [BR]",
"[TT]-cycl weighted[tt] First, a non-cyclic profile is computed. Subsequently, ",
{ "-bs-seed", FALSE, etINT, {&opt.bsSeed},
"seed for bootstrapping. (-1 = use time)"},
{ "-histbs", FALSE, etBOOL, {&opt.bHistBootStrap},
- "In bootstrapping, consider complete histograms as one data point."
+ "In bootstrapping, consider complete histograms as one data point. "
"Accounts better for long autocorrelations."},
{ "-histbs-block", FALSE, etINT, {&opt.histBootStrapBlockLength},
"when mixin histograms only mix within blocks of -histBS_block."},
int gmx_wheel(int argc,char *argv[])
{
const char *desc[] = {
- "wheel plots a helical wheel representation of your sequence."
+ "wheel plots a helical wheel representation of your sequence.",
"The input sequence is in the .dat file where the first line contains",
"the number of residues and each consecutive line contains a residue"
"name."
/* Find start and end of longest helix fragment */
check_ahx(nres,bb,x,&hstart,&hend);
}
- fprintf(stderr,"helix from: %d thru %d\n",
+ fprintf(stderr,"helix from: %d through %d\n",
bb[hstart].resno,bb[hend].resno);
for(j=0,i=hstart; (i<=hend); i++) {
if (bHesse)
for (i=0; vecs[i]; i++) {
if (vecs[i]<7)
- gmx_fatal(FARGS,"ERROR: You have choosen one of the first 6 eigenvectors of the HESSE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
+ gmx_fatal(FARGS,"ERROR: You have chosen one of the first 6 eigenvectors of the HESSE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
values[i]=eigval[1][vecs[i]-1]/kT;
}
else
for (i=0; vecs[i]; i++) {
if (vecs[i]>(neig-6))
- gmx_fatal(FARGS,"ERROR: You have choosen one of the last 6 eigenvectors of the COVARIANCE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
+ gmx_fatal(FARGS,"ERROR: You have chosen one of the last 6 eigenvectors of the COVARIANCE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
values[i]=1/eigval[1][vecs[i]-1];
}
/* free memory */
"([TT]-linfix[tt], [TT]-linacc[tt], [TT]-radfix[tt], [TT]-radacc[tt], [TT]-radcon[tt]),",
"to keep the position along a certain (set of) coordinate(s) fixed ([TT]-linfix[tt]),",
"or to only monitor the projections of the positions onto",
- "these coordinates ([TT]-mon[tt]).[PAR]"
+ "these coordinates ([TT]-mon[tt]).[PAR]",
"References:[BR]",
"A. Amadei, A.B.M. Linssen, B.L. de Groot, D.M.F. van Aalten and ",
"H.J.C. Berendsen; An efficient method for sampling the essential subspace ",
"of proteins., J. Biomol. Struct. Dyn. 13:615-626 (1996)[BR]",
"B.L. de Groot, A. Amadei, D.M.F. van Aalten and H.J.C. Berendsen; ",
"Towards an exhaustive sampling of the configurational spaces of the ",
- "two forms of the peptide hormone guanylin,"
+ "two forms of the peptide hormone guanylin,",
"J. Biomol. Struct. Dyn. 13 : 741-751 (1996)[BR]",
"B.L. de Groot, A.Amadei, R.M. Scheek, N.A.J. van Nuland and H.J.C. Berendsen; ",
"An extended sampling of the configurational space of HPr from E. coli",
"(steps in the desired direction will be accepted, others will be rejected).",
"Note: by default the starting MD structure will be taken as origin of the first",
"expansion cycle for radius expansion. If [TT]-ori[tt] is specified, you will be able",
- "to read in a structure file that defines an external origin.[PAR]"
+ "to read in a structure file that defines an external origin.[PAR]",
"[TT]-radcon[tt]: perform acceptance radius contraction along selected eigenvectors",
- "towards a target structure specified with [TT]-tar[tt].[PAR]"
- "NOTE: each eigenvector can be selected only once. [PAR]"
+ "towards a target structure specified with [TT]-tar[tt].[PAR]",
+ "NOTE: each eigenvector can be selected only once. [PAR]",
"[TT]-outfrq[tt]: frequency (in steps) of writing out projections etc. to .edo file[PAR]",
"[TT]-slope[tt]: minimal slope in acceptance radius expansion. A new expansion",
"cycle will be started if the spontaneous increase of the radius (in nm/step)",
- "is less than the value specified.[PAR]"
+ "is less than the value specified.[PAR]",
"[TT]-maxedsteps[tt]: maximum number of steps per cycle in radius expansion",
- "before a new cycle is started.[PAR]"
+ "before a new cycle is started.[PAR]",
"Note on the parallel implementation: since ED sampling is a 'global' thing",
"(collective coordinates etc.), at least on the 'protein' side, ED sampling",
"is not very parallel-friendly from an implentation point of view. Because",
"have to use make_ndx when you need SPECIAL index groups.",
"There is a default index group for the whole system, 9 default",
"index groups are generated for proteins, a default index group",
- "is generated for every other residue name.[PAR]"
+ "is generated for every other residue name.[PAR]",
"When no index file is supplied, also make_ndx will generate the",
"default groups.",
"With the index editor you can select on atom, residue and chain names",
snew(xav,natoms);
snew(vav,natoms);
read_conf(fngro,buf,&natoms,xav,vav,box);
- fprintf(stderr,"Succesfully read average positions (%s)\n",buf);
+ fprintf(stderr,"Successfully read average positions (%s)\n",buf);
EV=read_ev(fndat,natoms);
- fprintf(stderr,"Succesfully read eigenvectors\n");
+ fprintf(stderr,"Successfully read eigenvectors\n");
snew(index,nev);
for(i=0; (i<nev); i++)
}
ffclose(in);
}
- fprintf(stderr,"\rSuccesfully read eigenvector projections\n");
+ fprintf(stderr,"\rSuccessfully read eigenvector projections\n");
return evprj;
}
gf[i]=y;
}
ffclose(in);
- fprintf(stderr,"Succesfully read gamma\n");
+ fprintf(stderr,"Successfully read gamma\n");
return gf;
}
--- /dev/null
+enable_testing()
+add_test(TestExec_mdrun-h ../src/kernel/mdrun -h)