set(CMAKE_INSTALL_PREFIX "/usr/local/gromacs" CACHE STRING "Installation prefix (installation will need write permissions here)" FORCE)
endif()
-set(GMX_INSTALL_PREFIX "" CACHE STRING "Prefix gets appended to CMAKE_INSTALL_PREFIX. For cpack it sets the root folder of the archive.")
-mark_as_advanced(GMX_INSTALL_PREFIX)
-
include(gmxBuildTypeReference)
include(gmxBuildTypeProfile)
include(gmxBuildTypeTSAN)
"version of Boost included with Gromacs.")
endif()
+if(NOT DEFINED GMX_BUILD_UNITTESTS AND NOT HAVE_LIBXML2)
+ message(WARNING "libxml2 not found. Will build GROMACS without unit-tests. This is not recommended, because the unit-tests help to verify that GROMACS functions correctly. Most likely you are missing the libxml2-dev(el) package. After you installed it, set GMX_BUILD_UNITTESTS=ON.")
+endif()
option(GMX_BUILD_UNITTESTS "Build unit tests with BUILD_TESTING (uses Google C++ Testing and Mocking Frameworks, requires libxml2)" ${HAVE_LIBXML2})
mark_as_advanced(GMX_BUILD_UNITTESTS)
gmx_add_cache_dependency(GMX_BUILD_UNITTESTS BOOL BUILD_TESTING OFF)
########################################################################
add_definitions( -DHAVE_CONFIG_H )
-include_directories(${CMAKE_SOURCE_DIR}/src)
-include_directories(${CMAKE_SOURCE_DIR}/src/external/thread_mpi/include)
+include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src)
+include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/thread_mpi/include)
# Required for config.h, maybe should only be set in src/CMakeLists.txt
-include_directories(${CMAKE_BINARY_DIR}/src)
+include_directories(BEFORE ${CMAKE_BINARY_DIR}/src)
# Required for gmx_header_config_gen.h to be found before installation
-include_directories(${CMAKE_BINARY_DIR}/src/gromacs/utility)
+include_directories(BEFORE ${CMAKE_BINARY_DIR}/src/gromacs/utility)
# Required for now to make old code compile
-include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/legacyheaders)
+include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/gromacs/legacyheaders)
include(gmxTestInlineASM)
gmx_test_inline_asm_gcc_x86(GMX_X86_GCC_INLINE_ASM)
########################################################################
# Specify install locations
########################################################################
-# Use GNUInstallDirst to set paths on multiarch systems
+# Use GNUInstallDirs to set paths on multiarch systems.
include(GNUInstallDirs)
+# Customization for the installation tree paths.
set(GMX_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING
"Library installation directory (default: ${CMAKE_INSTALL_LIBDIR})")
set(GMX_DATA_INSTALL_DIR gromacs CACHE STRING
"Data installation directory under share/ (default: gromacs)")
mark_as_advanced(GMX_LIB_INSTALL_DIR GMX_DATA_INSTALL_DIR)
-set(LIB_INSTALL_DIR ${GMX_INSTALL_PREFIX}${GMX_LIB_INSTALL_DIR})
-set(BIN_INSTALL_DIR ${GMX_INSTALL_PREFIX}bin)
-set(DATA_INSTALL_DIR ${GMX_INSTALL_PREFIX}share/${GMX_DATA_INSTALL_DIR})
-set(MAN_INSTALL_DIR ${GMX_INSTALL_PREFIX}share/man)
-set(INCL_INSTALL_DIR ${GMX_INSTALL_PREFIX}include)
+# These variables are used internally to provide a central location for
+# customizing the install locations.
+set(LIB_INSTALL_DIR ${GMX_LIB_INSTALL_DIR})
+set(BIN_INSTALL_DIR bin)
+set(DATA_INSTALL_DIR share/${GMX_DATA_INSTALL_DIR})
+set(MAN_INSTALL_DIR share/man)
+set(INCL_INSTALL_DIR include)
+# These variables get written into config.h for use in finding the data
+# directories.
set(GMXLIB_SEARCH_DIR share/${GMX_DATA_INSTALL_DIR}/top)
set(GMXLIB_FALLBACK ${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/top)
include(gmxManageSuffixes)
################################################################
-# Shared library settings
+# Shared library load path settings
################################################################
-if((NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") OR ((CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0) AND (NOT CMAKE_VERSION VERSION_LESS 2.8.12)))
+# CMake supports RPATH on OS X only from 2.8.12 upwards.
+# CMAKE_SYSTEM_VERSION > 8.0 matches OS X 10.5 and above, where RPATH support
+# was added.
+if((NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") OR
+ ((CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0) AND (NOT CMAKE_VERSION VERSION_LESS 2.8.12)))
+ # The build folder always has bin/ and lib/; if we are also going to
+ # install to lib/, then the installation RPATH works also in the build
+ # tree. This makes installation slightly faster (no need to rewrite the
+ # RPATHs), and makes the binaries in the build tree relocatable.
if(GMX_LIB_INSTALL_DIR STREQUAL "lib")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
endif()
+ # Set the RPATH as relative to the executable location to make the
+ # binaries relocatable.
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${GMX_LIB_INSTALL_DIR}")
else()
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_MACOSX_RPATH 1)
else()
- # We are on Darwin/OSX, and cmake cannot handle proper RPATHs
- if(CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0) #rpath supported for >10.4
+ # We are on Darwin/OSX, and CMake cannot handle RPATHs automatically.
+ if(CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0)
+ # Set the RPATH options manually.
set(CMAKE_INSTALL_NAME_DIR "@rpath")
set(GMX_EXE_LINKER_FLAGS ${GMX_EXE_LINKER_FLAGS} "-Wl,-rpath,@executable_path/../${GMX_LIB_INSTALL_DIR}")
else()
+ # Use the old INSTALL_NAME_DIR mechanism if RPATH is not supported.
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}")
endif()
endif()
include_directories(${Boost_INCLUDE_DIRS})
set(PKG_CFLAGS "${PKG_CFLAGS} -I${Boost_INCLUDE_DIRS}")
else()
- include_directories(${CMAKE_SOURCE_DIR}/src/external/boost)
+ include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/boost)
# typeid not supported for minimal internal version
# (would add significant amount of code)
add_definitions(-DBOOST_NO_TYPEID)
--- /dev/null
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2014, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# If you want to redistribute modifications to GROMACS, 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 http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+# GMock uses tuples extensively, and MSVC bundles a tuple library that
+# is not compatible with the standard. r675 of googletest works around
+# this properly, but that's not in GMock 1.7.0. That logic is
+# duplicated here. See
+# https://code.google.com/p/googletest/source/detail?r=675#, but note
+# that its summary does not represent its code correctly.
+#
+# This function should be called to get the compile definitions
+# suitable for working around MSVC to compile GMock, if any.
+# Returns a string of options in VARIABLE
+function(GET_MSVC_TUPLE_WORKAROUND_DEFINITIONS VARIABLE)
+ set(${VARIABLE} "")
+ if(MSVC AND MSVC_VERSION VERSION_EQUAL 1700)
+ # Fixes Visual Studio 2012
+ set(${VARIABLE} "_VARIADIC_MAX=10")
+ endif()
+ set(${VARIABLE} ${${VARIABLE}} PARENT_SCOPE)
+endfunction()
endif()
set(PKG_FFT "${${FFTW}_PKG}")
- include_directories(${${FFTW}_INCLUDE_DIRS})
+ if (GMX_BUILD_OWN_FFTW)
+ include_directories(BEFORE ${${FFTW}_INCLUDE_DIRS})
+ else()
+ include_directories(${${FFTW}_INCLUDE_DIRS})
+ endif()
set(FFT_LIBRARIES ${${FFTW}_LIBRARIES})
set(GMX_FFT_FFTW3 1)
3. Get and unpack the latest version of the GROMACS tarball.
4. Make a separate build directory and change to it.
5. Run `cmake` with the path to the source as an argument
-6. Run `make` and `make install`
+6. Run `make`, `make test`, and `make install`
Or, as a sequence of commands to execute:
cd gromacs-@PROJECT_VERSION@
mkdir build
cd build
- cmake .. -DGMX_BUILD_OWN_FFTW=ON
+ cmake .. -DGMX_BUILD_OWN_FFTW=ON -DREGRESSIONTEST_DOWNLOAD=ON
make
+ make test
sudo make install
source /usr/local/gromacs/bin/GMXRC
things. The settings you might normally want to change are already
presented. You may make changes, then re-configure (using `c`), so that it
gets a chance to make changes that depend on yours and perform more
-checking. This might require several configuration stages when you are
-using `ccmake` - when you are using `cmake` the
-iteration is done behind the scenes.
+checking. It may take several configuration passes to reach the desired
+configuration, in particular if you need to resolve errors.
A key thing to consider here is the setting of
`CMAKE_INSTALL_PREFIX`. You will need to be able to write to this
super-user privileges, you should use them only for the installation
phase, and never for configuring, building, or running GROMACS!
-When `cmake` or `ccmake` have completed iterating, the
-cache is stable and a build tree can be generated, with `g` in
-`ccmake` or automatically with `cmake`.
+When you have reached the desired configuration with `ccmake`, the
+build system can be generated by pressing `g`. This requires that the previous
+configuration pass did not reveal any additional settings (if it did, you need
+to configure once more with `c`). With `cmake`, the build system is generated
+after each pass that does not produce errors.
You cannot attempt to change compilers after the initial run of
`cmake`. If you need to change, clean up, and start again.
Thus the names of all programs and libraries will be appended with
`_mod`.
+### Changing installation tree structure ###
+
+By default, a few different directories under `CMAKE_INSTALL_PREFIX` are used
+when when GROMACS is installed. Some of these can be changed, which is mainly
+useful for packaging GROMACS for various distributions. The directories are
+listed below, with additional notes about some of them. Unless otherwise noted,
+the directories can be renamed by editing the installation paths in the main
+CMakeLists.txt.
+
+`bin/`
+ : The standard location for executables, some scripts, and some symlinks.
+ Some of the scripts hardcode the absolute installation prefix, which needs
+ to be changed if the scripts are relocated.
+`include/gromacs/`
+ : The standard location for installed headers.
+`lib/`
+ : The standard location for libraries. The default depends on the system, and
+ is determined by CMake.
+ The name of the directory can be changed using `GMX_LIB_INSTALL_DIR` CMake
+ variable.
+`share/gromacs/`
+ : Various data files and some documentation go here.
+ The `gromacs` part can be changed using `GMX_DATA_INSTALL_DIR`. Using this
+ CMake variable is the preferred way of changing the installation path for
+ `share/gromacs/top/`, since the path to this directory is built into
+ `libgromacs` as well as some scripts, both as a relative and as an absolute
+ path (the latter as a fallback if everything else fails).
+`share/man/`
+ : Installed man pages go here.
+
## Building GROMACS ##
Once you have configured with `cmake`, you can build GROMACS. It is
# As stated in README.Gromacs, this file is not part of GMock, but is written
# specifically for the GROMACS build system from scratch.
+include(gmxGetMsvcTupleWorkaround)
+get_msvc_tuple_workaround_definitions(GMOCK_COMPILE_DEFINITIONS)
+set(GMOCK_COMPILE_DEFINITIONS ${GMOCK_COMPILE_DEFINITIONS} PARENT_SCOPE)
+
# GTest/GMock suggest linking with pthreads when available for thread safety
set(CMAKE_THREAD_PREFER_PTHREAD 1)
find_package(Threads)
set(GTEST_INCLUDE_DIRS ${GTEST_DIR}/include)
set(GMOCK_INCLUDE_DIRS ${GMOCK_DIR}/include ${GTEST_INCLUDE_DIRS})
-include_directories(${GTEST_INCLUDE_DIRS})
-include_directories(${GTEST_DIR})
-include_directories(${GMOCK_INCLUDE_DIRS})
-include_directories(${GMOCK_DIR})
+include_directories(BEFORE ${GTEST_INCLUDE_DIRS})
+include_directories(BEFORE ${GTEST_DIR})
+include_directories(BEFORE ${GMOCK_INCLUDE_DIRS})
+include_directories(BEFORE ${GMOCK_DIR})
add_library(gmock STATIC ${GMOCK_SOURCES} ${GTEST_SOURCES})
+set_property(TARGET gmock APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
set(GMOCK_LIBRARIES gmock ${PTHREADS_LIBRARIES} PARENT_SCOPE)
set(GTEST_LIBRARIES ${GMOCK_LIBRARIES} PARENT_SCOPE)
function (TNG_GENERATE_VERSION_H)
set(TNG_MAJOR_VERSION "1")
set(TNG_MINOR_VERSION "6")
- set(TNG_VERSION_PATCH_LEVEL "0")
+ set(TNG_VERSION_PATCH_LEVEL "1")
set(TNG_IO_VERSION "${TNG_MAJOR_VERSION}.${TNG_MINOR_VERSION}.${TNG_VERSION_PATCH_LEVEL}")
set(TNG_API_VERSION "6")
configure_file(${TNG_ROOT_SOURCE_DIR}/include/tng/version.h.in
check_include_file(inttypes.h TNG_HAVE_INTTYPES_H)
macro(TNG_GET_SOURCE_LIST TNG_SOURCELIST TNG_COMPILEDEFS)
- include_directories(${TNG_ROOT_SOURCE_DIR}/include)
- include_directories(${TNG_ROOT_BINARY_DIR}/include)
+ include_directories(BEFORE ${TNG_ROOT_SOURCE_DIR}/include)
+ include_directories(BEFORE ${TNG_ROOT_BINARY_DIR}/include)
set(_tng_compression_sources bwlzh.c bwt.c coder.c dict.c fixpoint.c huffman.c huffmem.c lz77.c merge_sort.c mtf.c rle.c tng_compress.c vals16.c warnmalloc.c widemuldiv.c xtc2.c xtc3.c)
set(_tng_io_sources tng_io.c md5.c)
set(${TNG_SOURCELIST})
int64_t long_stride_length, medium_stride_length;
long file_pos, orig_frame_set_file_pos;
tng_trajectory_frame_set_t frame_set;
- struct tng_trajectory_frame_set orig_frame_set;
+ struct tng_trajectory_frame_set orig_frame_set;
tng_gen_block_t block;
tng_function_status stat;
int64_t cnt = 0;
orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
+ if(file_pos < 0)
+ {
+ *n = tng_data->n_trajectory_frame_sets = cnt;
+ return(TNG_SUCCESS);
+ }
+
tng_block_init(&block);
fseek(tng_data->input_file,
file_pos,
/* Read the file headers */
tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
- tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
+ stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
+
+ if(stat != TNG_SUCCESS)
+ {
+ return(stat);
+ }
}
if(mode == 'w')
{
return(stat);
}
+ if(frame_set->first_frame + frame_set->n_frames - 1 < i)
+ {
+ return(TNG_FAILURE);
+ }
i = frame_set->first_frame;
}
}
{
return(stat);
}
+ if(frame_set->first_frame + frame_set->n_frames - 1 < i)
+ {
+ return(TNG_FAILURE);
+ }
i = frame_set->first_frame;
}
}
endif()
else()
# We still need to get tng/tng_io_fwd.h from somewhere!
- include_directories(${CMAKE_SOURCE_DIR}/src/external/tng_io/include)
+ include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/tng_io/include)
endif()
add_subdirectory(gmxlib)
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(nonbonded)
}
/* Update the flags */
_gmx_selelem_update_flags(root);
+ gmx::ExceptionInitializer errors("Invalid index group reference(s)");
+ root->checkUnsortedAtoms(true, &errors);
+ if (errors.hasNestedExceptions())
+ {
+ GMX_THROW(gmx::InconsistentInputError(errors));
+ }
root->fillNameIfMissing(_gmx_sel_lexer_pselstr(scanner));
{
/* If so, just assign the constant value to the variable */
sc->symtab->addVariable(name, expr);
- goto finish;
}
/* Check if we are assigning a variable to another variable */
- if (expr->type == SEL_SUBEXPRREF)
+ else if (expr->type == SEL_SUBEXPRREF)
{
/* If so, make a simple alias */
sc->symtab->addVariable(name, expr->child);
- goto finish;
}
- /* Create the root element */
- root.reset(new SelectionTreeElement(SEL_ROOT));
- root->setName(name);
- /* Create the subexpression element */
- root->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
- root->child->setName(name);
- _gmx_selelem_set_vtype(root->child, expr->v.type);
- root->child->child = expr;
- /* Update flags */
- _gmx_selelem_update_flags(root);
- /* Add the variable to the symbol table */
- sc->symtab->addVariable(name, root->child);
-finish:
+ else
+ {
+ /* Create the root element */
+ root.reset(new SelectionTreeElement(SEL_ROOT));
+ root->setName(name);
+ /* Create the subexpression element */
+ root->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
+ root->child->setName(name);
+ _gmx_selelem_set_vtype(root->child, expr->v.type);
+ root->child->child = expr;
+ /* Update flags */
+ _gmx_selelem_update_flags(root);
+ gmx::ExceptionInitializer errors("Invalid index group reference(s)");
+ root->checkUnsortedAtoms(true, &errors);
+ if (errors.hasNestedExceptions())
+ {
+ GMX_THROW(gmx::InconsistentInputError(errors));
+ }
+ /* Add the variable to the symbol table */
+ sc->symtab->addVariable(name, root->child);
+ }
srenew(sc->varstrs, sc->nvars + 1);
sc->varstrs[sc->nvars] = strdup(pselstr);
++sc->nvars;
impl_->grps_ = grps;
impl_->bExternalGroupsSet_ = true;
- ExceptionInitializer errors("Unknown index group references encountered");
+ ExceptionInitializer errors("Invalid index group reference(s)");
SelectionTreeElementPointer root = impl_->sc_.root;
while (root)
{
impl_->resolveExternalGroups(root, &errors);
+ root->checkUnsortedAtoms(true, &errors);
root = root->next;
}
if (errors.hasNestedExceptions())
#include "keywords.h"
#include "mempool.h"
#include "selelem.h"
+#include "selmethod.h"
/*!
* \param[in] sel Selection for which the string is requested
}
}
+void SelectionTreeElement::checkUnsortedAtoms(
+ bool bUnsortedAllowed, ExceptionInitializer *errors) const
+{
+ const bool bUnsortedSupported
+ = (type == SEL_CONST && v.type == GROUP_VALUE)
+ || type == SEL_ROOT || type == SEL_SUBEXPR || type == SEL_SUBEXPRREF
+ // TODO: Consolidate.
+ || type == SEL_MODIFIER
+ || (type == SEL_EXPRESSION && (u.expr.method->flags & SMETH_ALLOW_UNSORTED));
+
+ // TODO: For some complicated selections, this may result in the same
+ // index group reference being flagged as an error multiple times for the
+ // same selection.
+ SelectionTreeElementPointer child = this->child;
+ while (child)
+ {
+ child->checkUnsortedAtoms(bUnsortedAllowed && bUnsortedSupported,
+ errors);
+ child = child->next;
+ }
+
+ // The logic here is simplified by the fact that only constant groups can
+ // currently be the root cause of SEL_UNSORTED being set, so only those
+ // need to be considered in triggering the error.
+ if (!bUnsortedAllowed && (flags & SEL_UNSORTED)
+ && type == SEL_CONST && v.type == GROUP_VALUE)
+ {
+ std::string message = formatString(
+ "Group '%s' cannot be used in selections except "
+ "as a full value of the selection, "
+ "because atom indices in it are not sorted and/or "
+ "it contains duplicate atoms.",
+ name().c_str());
+ errors->addNested(InconsistentInputError(message));
+ }
+}
+
void SelectionTreeElement::resolveIndexGroupReference(gmx_ana_indexgrps_t *grps)
{
GMX_RELEASE_ASSERT(type == SEL_GROUPREF,
if (!gmx_ana_index_check_sorted(&foundGroup))
{
flags |= SEL_UNSORTED;
- // TODO: Add this test elsewhere, where it does not break valid use cases.
-#if 0
- gmx_ana_index_deinit(&foundGroup);
- std::string message = formatString(
- "Group '%s' ('%s') cannot be used in selections, "
- "because atom indices in it are not sorted and/or "
- "it contains duplicate atoms.",
- foundName.c_str(), name().c_str());
- GMX_THROW(InconsistentInputError(message));
-#endif
}
sfree(u.gref.name);
namespace gmx
{
+class ExceptionInitializer;
+
/*! \brief
* Function pointer for evaluating a gmx::SelectionTreeElement.
*/
*/
void fillNameIfMissing(const char *selectionText);
+ /*! \brief
+ * Checks that this element and its children do not contain unsupported
+ * elements with unsorted atoms.
+ *
+ * \param[in] bUnsortedAllowed Whether this element's parents allow it
+ * to have unsorted atoms.
+ * \param errors Object for reporting any error messages.
+ * \throws std::bad_alloc if out of memory.
+ *
+ * Errors are reported as nested exceptions in \p errors.
+ */
+ void checkUnsortedAtoms(bool bUnsortedAllowed,
+ ExceptionInitializer *errors) const;
/*! \brief
* Resolved an unresolved reference to an index group.
*
* - \ref SMETH_MODIFIER : If set, the method is a selection modifier and
* not an actual selection method.
* For more details, see \ref selmethods_modifiers.
+ * - \ref SMETH_ALLOW_UNSORTED : If set, the method supports unsorted atoms
+ * in its input parameters. \ref SMETH_MODIFIER methods are assumed to always
+ * support unsorted atoms, as their purpose is to affect the ordering.
*
* There are two additional flags that specify the number of values the
* method returns. Only one of them can be set at a time.
* the string pointers.
*/
#define SMETH_CHARVAL 64
+/*! \brief
+ * If set, the method accepts unsorted atoms in its input parameters.
+ *
+ * Currently, the support for this functionality is fairly limited, and only
+ * static index group references can actually contain unsorted atoms.
+ * But to make this single case work, the position evaluation must support
+ * unsorted atoms as well.
+ */
+#define SMETH_ALLOW_UNSORTED 128
/*! \brief
* If set, the method is a selection modifier.
*
/** Selection method data for position keyword evaluation. */
gmx_ana_selmethod_t sm_keyword_pos = {
- "kw_pos", POS_VALUE, SMETH_DYNAMIC | SMETH_VARNUMVAL,
+ "kw_pos", POS_VALUE, SMETH_DYNAMIC | SMETH_VARNUMVAL | SMETH_ALLOW_UNSORTED,
asize(smparams_keyword_pos), smparams_keyword_pos,
&init_data_pos,
&set_poscoll_pos,
<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
<ReferenceData>
<ParsedSelections Name="Parsed">
+ <ParsedVariable Name="Variable1">
+ <String Name="Input">foo = group "GrpUnsorted"</String>
+ </ParsedVariable>
<ParsedSelection Name="Selection1">
<String Name="Input">group "GrpUnsorted"</String>
<String Name="Name">GrpUnsorted</String>
<String Name="Text">group "GrpUnsorted" permute 2 1</String>
<Bool Name="Dynamic">false</Bool>
</ParsedSelection>
+ <ParsedSelection Name="Selection6">
+ <String Name="Input">foo</String>
+ <String Name="Name">foo</String>
+ <String Name="Text">foo</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
</ParsedSelections>
<CompiledSelections Name="Compiled">
<Selection Name="Selection1">
</Position>
</Sequence>
</Selection>
+ <Selection Name="Selection6">
+ <String Name="Name">foo</String>
+ <Sequence Name="Atoms">
+ <Int Name="Length">8</Int>
+ <Int>0</Int>
+ <Int>2</Int>
+ <Int>1</Int>
+ <Int>8</Int>
+ <Int>6</Int>
+ <Int>4</Int>
+ <Int>2</Int>
+ <Int>11</Int>
+ </Sequence>
+ <Sequence Name="Positions">
+ <Int Name="Length">8</Int>
+ <Position>
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>0</Int>
+ </Sequence>
+ <Int Name="RefId">0</Int>
+ <Int Name="MappedId">0</Int>
+ </Position>
+ <Position>
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>2</Int>
+ </Sequence>
+ <Int Name="RefId">1</Int>
+ <Int Name="MappedId">2</Int>
+ </Position>
+ <Position>
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>1</Int>
+ </Sequence>
+ <Int Name="RefId">2</Int>
+ <Int Name="MappedId">1</Int>
+ </Position>
+ <Position>
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>8</Int>
+ </Sequence>
+ <Int Name="RefId">3</Int>
+ <Int Name="MappedId">8</Int>
+ </Position>
+ <Position>
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>6</Int>
+ </Sequence>
+ <Int Name="RefId">4</Int>
+ <Int Name="MappedId">6</Int>
+ </Position>
+ <Position>
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>4</Int>
+ </Sequence>
+ <Int Name="RefId">5</Int>
+ <Int Name="MappedId">4</Int>
+ </Position>
+ <Position>
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>2</Int>
+ </Sequence>
+ <Int Name="RefId">6</Int>
+ <Int Name="MappedId">2</Int>
+ </Position>
+ <Position>
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>11</Int>
+ </Sequence>
+ <Int Name="RefId">7</Int>
+ <Int Name="MappedId">11</Int>
+ </Position>
+ </Sequence>
+ </Selection>
</CompiledSelections>
</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <ParsedSelections Name="Parsed">
+ <ParsedVariable Name="Variable1">
+ <String Name="Input">foo = group "GrpUnsorted"</String>
+ </ParsedVariable>
+ <ParsedSelection Name="Selection1">
+ <String Name="Input">group "GrpUnsorted"</String>
+ <String Name="Text">group "GrpUnsorted"</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ <ParsedSelection Name="Selection2">
+ <String Name="Input">GrpUnsorted</String>
+ <String Name="Text">GrpUnsorted</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ <ParsedSelection Name="Selection3">
+ <String Name="Input">2</String>
+ <String Name="Text">2</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ <ParsedSelection Name="Selection4">
+ <String Name="Input">res_cog of group "GrpUnsorted"</String>
+ <String Name="Text">res_cog of group "GrpUnsorted"</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ <ParsedSelection Name="Selection5">
+ <String Name="Input">group "GrpUnsorted" permute 2 1</String>
+ <String Name="Text">group "GrpUnsorted" permute 2 1</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ <ParsedSelection Name="Selection6">
+ <String Name="Input">foo</String>
+ <String Name="Text">foo</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ </ParsedSelections>
+ <CompiledSelections Name="Compiled">
+ <Selection Name="Selection1">
+ <Sequence Name="Atoms">
+ <Int Name="Length">8</Int>
+ <Int>0</Int>
+ <Int>2</Int>
+ <Int>1</Int>
+ <Int>8</Int>
+ <Int>6</Int>
+ <Int>4</Int>
+ <Int>2</Int>
+ <Int>11</Int>
+ </Sequence>
+ </Selection>
+ <Selection Name="Selection2">
+ <Sequence Name="Atoms">
+ <Int Name="Length">8</Int>
+ <Int>0</Int>
+ <Int>2</Int>
+ <Int>1</Int>
+ <Int>8</Int>
+ <Int>6</Int>
+ <Int>4</Int>
+ <Int>2</Int>
+ <Int>11</Int>
+ </Sequence>
+ </Selection>
+ <Selection Name="Selection3">
+ <Sequence Name="Atoms">
+ <Int Name="Length">8</Int>
+ <Int>0</Int>
+ <Int>2</Int>
+ <Int>1</Int>
+ <Int>8</Int>
+ <Int>6</Int>
+ <Int>4</Int>
+ <Int>2</Int>
+ <Int>11</Int>
+ </Sequence>
+ </Selection>
+ <Selection Name="Selection4">
+ <Sequence Name="Atoms">
+ <Int Name="Length">8</Int>
+ <Int>0</Int>
+ <Int>2</Int>
+ <Int>1</Int>
+ <Int>8</Int>
+ <Int>6</Int>
+ <Int>4</Int>
+ <Int>2</Int>
+ <Int>11</Int>
+ </Sequence>
+ </Selection>
+ <Selection Name="Selection5">
+ <Sequence Name="Atoms">
+ <Int Name="Length">8</Int>
+ <Int>2</Int>
+ <Int>0</Int>
+ <Int>8</Int>
+ <Int>1</Int>
+ <Int>4</Int>
+ <Int>6</Int>
+ <Int>11</Int>
+ <Int>2</Int>
+ </Sequence>
+ </Selection>
+ <Selection Name="Selection6">
+ <Sequence Name="Atoms">
+ <Int Name="Length">8</Int>
+ <Int>0</Int>
+ <Int>2</Int>
+ <Int>1</Int>
+ <Int>8</Int>
+ <Int>6</Int>
+ <Int>4</Int>
+ <Int>2</Int>
+ <Int>11</Int>
+ </Sequence>
+ </Selection>
+ </CompiledSelections>
+</ReferenceData>
EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
}
-// TODO: Make the check less eager so that it doesn't break other tests, and
-// adapt these tests accordingly.
-TEST_F(SelectionCollectionTest, DISABLED_HandlesUnsortedGroupReference)
+TEST_F(SelectionCollectionTest, HandlesUnsortedGroupReference)
{
ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
- EXPECT_THROW_GMX(sc_.parseFromString("group \"GrpUnsorted\""),
+ EXPECT_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group \"GrpUnsorted\""),
+ gmx::InconsistentInputError);
+ EXPECT_THROW_GMX(sc_.parseFromString("group 2 or atomnr 2 to 5"),
+ gmx::InconsistentInputError);
+ EXPECT_THROW_GMX(sc_.parseFromString("within 1 of group 2"),
gmx::InconsistentInputError);
- EXPECT_THROW_GMX(sc_.parseFromString("2"), gmx::InconsistentInputError);
}
-TEST_F(SelectionCollectionTest, DISABLED_HandlesUnsortedGroupReferenceDelayed)
+TEST_F(SelectionCollectionTest, HandlesUnsortedGroupReferenceDelayed)
{
- ASSERT_NO_THROW_GMX(sc_.parseFromString("group 2; group \"GrpUnsorted\""));
+ ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group \"GrpUnsorted\""));
+ ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group 2"));
EXPECT_THROW_GMX(loadIndexGroups("simple.ndx"), gmx::InconsistentInputError);
- EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
+ // TODO: Add a separate check in the selection compiler for a safer API
+ // (makes sense in the future if the compiler needs the information for
+ // other purposes as well).
+ // EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
}
TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelections)
{
static const char * const selections[] = {
+ "foo = group \"GrpUnsorted\"",
"group \"GrpUnsorted\"",
"GrpUnsorted",
"2",
"res_cog of group \"GrpUnsorted\"",
- "group \"GrpUnsorted\" permute 2 1"
+ "group \"GrpUnsorted\" permute 2 1",
+ "foo"
};
setFlags(TestFlags() | efTestPositionAtoms | efTestPositionMapping
| efTestSelectionNames);
runTest("simple.gro", selections);
}
+TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelectionsDelayed)
+{
+ static const char * const selections[] = {
+ "foo = group \"GrpUnsorted\"",
+ "group \"GrpUnsorted\"",
+ "GrpUnsorted",
+ "2",
+ "res_cog of group \"GrpUnsorted\"",
+ "group \"GrpUnsorted\" permute 2 1",
+ "foo"
+ };
+ ASSERT_NO_FATAL_FAILURE(runParser(selections));
+ ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+ ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
+ ASSERT_NO_FATAL_FAILURE(runCompiler());
+}
+
TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
{
static const char * const selections[] = {
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
nested_.push_back(boost::current_exception());
}
+ /*! \brief
+ * Adds the specified exception as a nested exception.
+ *
+ * May be called multiple times; all provided exceptions will be added
+ * in a list of nested exceptions.
+ *
+ * This is equivalent to throwing \p ex and calling
+ * addCurrentExceptionAsNested() in the catch block, but potentially
+ * more efficient.
+ */
+ template <class Exception>
+ void addNested(const Exception &ex)
+ {
+ nested_.push_back(boost::copy_exception(ex));
+ }
private:
std::string reason_;
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2011,2012,2013, by the GROMACS development team, led by
+# Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-include_directories(${GMOCK_INCLUDE_DIRS})
+include_directories(BEFORE ${GMOCK_INCLUDE_DIRS})
include_directories(${LIBXML2_INCLUDE_DIR})
file(GLOB TESTUTILS_SOURCES *.cpp)
add_library(testutils STATIC ${TESTUTILS_SOURCES})
set(TESTUTILS_LIBS testutils ${GMOCK_LIBRARIES} ${LIBXML2_LIBRARIES})
+set_property(TARGET testutils APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
target_link_libraries(testutils libgromacs ${GMOCK_LIBRARIES} ${LIBXML2_LIBRARIES})
set(TESTUTILS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
function (gmx_add_unit_test_object_library NAME)
if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
- include_directories(${GMOCK_INCLUDE_DIRS})
+ include_directories(BEFORE ${GMOCK_INCLUDE_DIRS})
add_library(${NAME} OBJECT ${ARGN})
+ set_property(TARGET ${NAME} APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
endif()
endfunction ()
function (gmx_build_unit_test NAME EXENAME)
if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
- include_directories(${GMOCK_INCLUDE_DIRS})
+ include_directories(BEFORE ${GMOCK_INCLUDE_DIRS})
add_executable(${EXENAME} ${ARGN} ${TESTUTILS_DIR}/unittest_main.cpp)
+ set_property(TARGET ${EXENAME} APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
target_link_libraries(${EXENAME} libgromacs ${TESTUTILS_LIBS} ${GMOCK_LIBRARIES} ${GMX_EXE_LINKER_FLAGS})
set(_temporary_files_path "${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary")
file(MAKE_DIRECTORY ${_temporary_files_path})