├── src ├── coords_file │ ├── xdrfile │ │ ├── CMakeLists.txt │ │ ├── xdrfile_xtc.h │ │ ├── xdrfile_trr.h │ │ ├── xdrfile_xtc.c │ │ ├── trr2xtc.c │ │ ├── xdrfile_c_test.c │ │ └── xdrfile_trr.c │ ├── CMakeLists.txt │ ├── coords_file.hpp │ └── coords_file.cpp ├── create_header_hpp.sh ├── make_version.sh ├── density_clustering_cuda_kernels.hpp ├── logger.cpp ├── lts_cuda_kernels.cuh ├── logger.hpp ├── density_clustering_opencl.hpp ├── state_filter.hpp ├── density_clustering_cuda.hpp ├── network_builder.hpp ├── density_clustering_common.hpp ├── noise.hpp ├── coring.hpp ├── density_clustering_mpi.hpp ├── density_clustering_common.cpp ├── density_clustering_opencl.cpp ├── mpp.hpp ├── density_clustering_cuda_kernels.cu ├── tools.hpp ├── tools.hxx ├── tools.cpp ├── density_clustering.hpp ├── noise.cpp ├── state_filter.cpp └── coring.cpp ├── config.hpp.cmake.in ├── generate_header.py ├── LICENSE.txt ├── bash_completion_clustering.sh ├── FindOpenCL.cmake ├── CMakeLists.txt └── README.md /src/coords_file/xdrfile/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(xdrfile xdrfile.c xdrfile_xtc.c) 3 | 4 | -------------------------------------------------------------------------------- /config.hpp.cmake.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define DC_MEM_ALIGNMENT @DC_MEM_ALIGNMENT@ 4 | 5 | //@USE_MPI@ 6 | //@USE_OPENCL@ 7 | 8 | -------------------------------------------------------------------------------- /generate_header.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import os 5 | 6 | fh_in = open(sys.argv[1], 'r') 7 | fh_out = open(sys.argv[2], 'w') 8 | 9 | for line in fh_in: 10 | fh_out.write(r'"' + line[:-1] + r'\n"' + "\n") 11 | 12 | fh_in.close() 13 | fh_out.close() 14 | 15 | -------------------------------------------------------------------------------- /src/create_header_hpp.sh: -------------------------------------------------------------------------------- 1 | 2 | if [ -f embedded_cytoscape.hpp ]; then 3 | cp embedded_cytoscape.hpp embedded_cytoscape.hpp.bak 4 | fi 5 | 6 | echo "#pragma once" > embedded_cytoscape.hpp 7 | echo "namespace Clustering {" >> embedded_cytoscape.hpp 8 | echo "namespace Network {" >> embedded_cytoscape.hpp 9 | echo "unsigned char viewer_header[] = {" >> embedded_cytoscape.hpp 10 | 11 | xxd -i header.html | sed s/unsigned.*// >> embedded_cytoscape.hpp 12 | 13 | echo 'const char* viewer_footer = "}); }); ";' >> embedded_cytoscape.hpp 14 | 15 | echo '} // end namespace Network' >> embedded_cytoscape.hpp 16 | echo '} // end namespace Clustering' >> embedded_cytoscape.hpp 17 | 18 | -------------------------------------------------------------------------------- /src/make_version.sh: -------------------------------------------------------------------------------- 1 | 2 | v_dir=$1 3 | 4 | if [ ! -d $v_dir ]; then 5 | echo "$v_dir does not exist. will create it." 6 | mkdir $v_dir 7 | fi 8 | 9 | cp -r clustering.cpp\ 10 | CMakeLists.txt\ 11 | config.hpp.cmake.in\ 12 | density_clustering.cpp\ 13 | density_clustering.hpp\ 14 | density_clustering_mpi.cpp\ 15 | density_clustering_mpi.hpp\ 16 | density_clustering_common.hpp\ 17 | density_clustering_common.cpp\ 18 | FindOpenCL.cmake\ 19 | cl.hpp\ 20 | density_clustering_opencl.hpp\ 21 | density_clustering_opencl.cpp\ 22 | pops.cl\ 23 | generate_header.py\ 24 | logger.cpp\ 25 | logger.hpp\ 26 | mpp.cpp\ 27 | mpp.hpp\ 28 | network_builder.cpp\ 29 | network_builder.hpp\ 30 | README.md\ 31 | state_filter.cpp\ 32 | state_filter.hpp\ 33 | tools.cpp\ 34 | tools.hpp\ 35 | tools.hxx\ 36 | coring.cpp\ 37 | coring.hpp\ 38 | noise.cpp\ 39 | noise.hpp\ 40 | embedded_cytoscape.hpp\ 41 | doc\ 42 | doxygen.config\ 43 | coords_file\ 44 | $v_dir/ 45 | 46 | tar cf $v_dir.tar $v_dir/ 47 | gzip $v_dir.tar 48 | 49 | -------------------------------------------------------------------------------- /src/coords_file/xdrfile/xdrfile_xtc.h: -------------------------------------------------------------------------------- 1 | /* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- 2 | * 3 | * $Id: xdrfile_xtc.h,v 1.5 2009/05/18 09:06:38 spoel Exp $ 4 | * 5 | * Copyright (c) Erik Lindahl, David van der Spoel 2003,2004. 6 | * Coordinate compression (c) by Frans van Hoesel. 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public License 10 | * as published by the Free Software Foundation; either version 3 11 | * of the License, or (at your option) any later version. 12 | */ 13 | 14 | #ifndef _xdrfile_xtc_h 15 | #define _xdrfile_xtc_h 16 | 17 | #ifdef CPLUSPLUS 18 | extern "C" { 19 | #endif 20 | 21 | #include "xdrfile.h" 22 | 23 | /* All functions return exdrOK if succesfull. 24 | * (error codes defined in xdrfile.h). 25 | */ 26 | 27 | /* This function returns the number of atoms in the xtc file in *natoms */ 28 | extern int read_xtc_natoms(const char *fn,int *natoms); 29 | 30 | /* Read one frame of an open xtc file */ 31 | extern int read_xtc(XDRFILE *xd,int natoms,int *step,float *time, 32 | matrix box,rvec *x,float *prec); 33 | 34 | /* Write a frame to xtc file */ 35 | extern int write_xtc(XDRFILE *xd, 36 | int natoms,int step,float time, 37 | matrix box,rvec *x,float prec); 38 | 39 | #ifdef CPLUSPLUS 40 | } 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2018, Florian Sittel (www.lettis.net) 2 | Copyright (c) 2018-2019, Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /src/coords_file/xdrfile/xdrfile_trr.h: -------------------------------------------------------------------------------- 1 | /* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- 2 | * 3 | * $Id: xdrfile_trr.h,v 1.2 2009/05/18 09:06:38 spoel Exp $ 4 | * 5 | * Copyright (c) Erik Lindahl, David van der Spoel 2003,2004. 6 | * Coordinate compression (c) by Frans van Hoesel. 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public License 10 | * as published by the Free Software Foundation; either version 3 11 | * of the License, or (at your option) any later version. 12 | */ 13 | 14 | #ifndef _xdrfile_trr_h 15 | #define _xdrfile_trr_h 16 | 17 | #ifdef CPLUSPLUS 18 | extern "C" { 19 | #endif 20 | 21 | #include "xdrfile.h" 22 | 23 | /* All functions return exdrOK if succesfull. 24 | * (error codes defined in xdrfile.h). 25 | */ 26 | 27 | /* This function returns the number of atoms in the xtc file in *natoms */ 28 | extern int read_trr_natoms(char *fn,int *natoms); 29 | 30 | /* Read one frame of an open xtc file. If either of x,v,f,box are 31 | NULL the arrays will be read from the file but not used. */ 32 | extern int read_trr(XDRFILE *xd,int natoms,int *step,float *t,float *lambda, 33 | matrix box,rvec *x,rvec *v,rvec *f); 34 | 35 | /* Write a frame to xtc file */ 36 | extern int write_trr(XDRFILE *xd,int natoms,int step,float t,float lambda, 37 | matrix box,rvec *x,rvec *v,rvec *f); 38 | 39 | 40 | #ifdef CPLUSPLUS 41 | } 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/coords_file/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Florian Sittel (www.lettis.net) 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 15 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 17 | # SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 19 | # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 21 | # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 22 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | add_subdirectory(xdrfile) 25 | 26 | add_library(coords_file coords_file.cpp) 27 | target_link_libraries(coords_file xdrfile) 28 | 29 | -------------------------------------------------------------------------------- /src/density_clustering_cuda_kernels.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //// hard-coded settings 4 | 5 | // for pops 6 | #define BSIZE_POPS 512 7 | 8 | // for neighborhood search 9 | #define BSIZE_NH 128 10 | 11 | // for screening 12 | #define BSIZE_SCR 256 13 | 14 | //// 15 | 16 | 17 | namespace Clustering { 18 | namespace Density { 19 | namespace CUDA { 20 | namespace Kernel { 21 | 22 | __global__ void 23 | population_count(unsigned int offset 24 | , float* coords 25 | , unsigned int n_rows 26 | , unsigned int n_cols 27 | , float* radii2 28 | , unsigned int n_radii 29 | , unsigned int* pops 30 | , unsigned int i_from 31 | , unsigned int i_to); 32 | 33 | __global__ void 34 | nearest_neighbor_search(unsigned int offset 35 | , float* coords 36 | , unsigned int n_rows 37 | , unsigned int n_cols 38 | , float* fe 39 | , unsigned int* nh_nhhd_ndx 40 | , float* nh_nhhd_dist 41 | , unsigned int i_from 42 | , unsigned int i_to); 43 | 44 | 45 | __global__ void 46 | screening(unsigned int offset 47 | , float* sorted_coords 48 | , unsigned int n_rows 49 | , unsigned int n_cols 50 | , float max_dist2 51 | , unsigned int* clustering 52 | , unsigned int i_from 53 | , unsigned int i_to); 54 | 55 | }}}} // end Clustering::Density::CUDA::Kernel 56 | 57 | -------------------------------------------------------------------------------- /src/logger.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "logger.hpp" 27 | 28 | namespace Clustering { 29 | bool verbose = false; 30 | std::ostream devnull(0); 31 | 32 | std::ostream& logger(std::ostream& s) { 33 | if (verbose) { 34 | return s; 35 | } else { 36 | return devnull; 37 | } 38 | } 39 | 40 | std::ostream& debug() { 41 | std::cout << "DEBUG: "; 42 | return std::cout; 43 | } 44 | } // end namespace Clustering 45 | 46 | -------------------------------------------------------------------------------- /src/lts_cuda_kernels.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /** 6 | * perform reduction (sum) on given values. 7 | * stores result to results-array at index i_result. 8 | * 9 | * implicit first reduction on call, so run with half the total range 10 | * 11 | * begin reduction at offset. 12 | */ 13 | template 14 | __global__ void 15 | reduce_sum(unsigned int offset 16 | , float* vals 17 | , unsigned int n_vals 18 | , float* results 19 | , unsigned int i_result) { 20 | __shared__ float sum_block[_BLOCKSIZE]; 21 | unsigned int stride; 22 | unsigned int bid = blockIdx.x; 23 | unsigned int tid = threadIdx.x; 24 | unsigned int gid = bid*_BLOCKSIZE+tid; 25 | unsigned int gid2 = gid + _BLOCKSIZE*gridDim.x; 26 | // store probs locally for reduction 27 | if (gid2 < n_vals) { 28 | // initial double load and first reduction 29 | sum_block[tid] = vals[gid+offset] + vals[gid2+offset]; 30 | } else if (gid < n_vals) { 31 | sum_block[tid] = vals[gid+offset]; 32 | } else { 33 | sum_block[tid] = 0.0f; 34 | } 35 | //TODO ifdef to set intrinsic sync mode for specific architectures (e.g. Tesla K40) 36 | // for (stride=_BLOCKSIZE/2; stride > 32; stride /= 2) { 37 | // __syncthreads(); 38 | // if (tid < stride) { 39 | // sum_block[tid] += sum_block[tid+stride]; 40 | // } 41 | // } 42 | // // unroll loop inside warp (intrinsic sync!) 43 | // __syncthreads(); 44 | // if (tid < 32) { 45 | // sum_block[tid] += sum_block[tid+32]; 46 | // sum_block[tid] += sum_block[tid+16]; 47 | // sum_block[tid] += sum_block[tid+8]; 48 | // sum_block[tid] += sum_block[tid+4]; 49 | // sum_block[tid] += sum_block[tid+2]; 50 | // sum_block[tid] += sum_block[tid+1]; 51 | // } 52 | for (stride=_BLOCKSIZE/2; stride > 0; stride /= 2) { 53 | __syncthreads(); 54 | if (tid < stride) { 55 | sum_block[tid] += sum_block[tid+stride]; 56 | } 57 | } 58 | if (tid == 0) { 59 | atomicAdd(&results[i_result], sum_block[0]); 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /src/logger.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include 28 | /*! \file 29 | * \brief Define global logger 30 | */ 31 | 32 | /*! 33 | * \brief functions related to verbose/output mode 34 | * 35 | * This namespace contains all functions related to the verbose mode. 36 | */ 37 | namespace Clustering { 38 | //! global flag: use verbose output? 39 | extern bool verbose; 40 | //! fake-stream used as output if nothing should be printed to stdout/stderr. 41 | extern std::ostream devnull; 42 | //! logger, use like logger(std::cout) << ...; 43 | //! will print to given stream if global 'verbose' is set to true. 44 | std::ostream& logger(std::ostream& s); 45 | //! print formatted debug output to std::cerr. 46 | std::ostream& debug(); 47 | } // end namespace Clustering 48 | 49 | -------------------------------------------------------------------------------- /src/density_clustering_opencl.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include "config.hpp" 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | 35 | namespace Clustering { 36 | namespace Density { 37 | //! OpenCL implementations of compute intensive functions 38 | namespace OpenCL { 39 | //! OpenCL implementation of 40 | //! \link Clustering::Density::calculate_populations(const float* coords, const std::size_t n_rows, const std::size_t n_cols, std::vector radii); 41 | //! 42 | //! **ATTENTION**: OpenCL support is unfinished and not expected to return sound results. 43 | std::map> 44 | calculate_populations(const float* coords, const std::size_t n_rows, const std::size_t n_cols, std::vector radii); 45 | } // end namespace OpenCL 46 | } // end namespace Density 47 | } // end namespace Clustering 48 | -------------------------------------------------------------------------------- /src/state_filter.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Florian Sittel (www.lettis.net) 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include 28 | 29 | namespace Clustering { 30 | //! functionality for filtering coordinates or order parameters (ASCII or GROMACS' .xtc) based on state trajectory. 31 | namespace Filter { 32 | void 33 | //! print with fixed precision and width 34 | fixedprint(double num, std::size_t prec, std::size_t width); 35 | /*! 36 | * controlling function and user interface for state filtering. 37 | * 38 | * *parsed arguments*: 39 | * - **states**: input file with state trajectory 40 | * - **coords**: ASCII or .xtc file with coordinates or order parameters 41 | * - **output**: filtered coordinates 42 | * - **state**: selected state that should be filtered from full data set 43 | */ 44 | void 45 | main(boost::program_options::variables_map args); 46 | } // end namespace Filter 47 | } // end namespace Clustering 48 | -------------------------------------------------------------------------------- /src/density_clustering_cuda.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "config.hpp" 4 | #include "density_clustering_common.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace Clustering { 10 | namespace Density { 11 | namespace CUDA { 12 | 13 | void 14 | check_error(std::string msg=""); 15 | 16 | int 17 | get_num_gpus(); 18 | 19 | using Neighborhood = Clustering::Tools::Neighborhood; 20 | 21 | Pops 22 | calculate_populations_partial(const float* coords 23 | , const std::vector& sorted_coords 24 | , const std::vector& blimits 25 | , std::size_t n_rows 26 | , std::size_t n_cols 27 | , std::vector radii 28 | , std::size_t i_from 29 | , std::size_t i_to 30 | , int i_gpu); 31 | 32 | Pops 33 | calculate_populations(const float* coords 34 | , const std::size_t n_rows 35 | , const std::size_t n_cols 36 | , std::vector radii); 37 | 38 | std::tuple 39 | nearest_neighbors(const float* coords, 40 | const std::size_t n_rows, 41 | const std::size_t n_cols, 42 | const std::vector& free_energy); 43 | 44 | std::vector 45 | sanitize_state_names(std::vector clustering); 46 | 47 | std::vector 48 | screening(const std::vector& free_energy 49 | , const Neighborhood& nh 50 | , const float free_energy_threshold 51 | , const float* coords 52 | , const std::size_t n_rows 53 | , const std::size_t n_cols 54 | , const std::vector initial_clusters); 55 | 56 | std::set 57 | high_density_neighborhood(const float* coords, 58 | const std::size_t n_cols, 59 | const std::vector& sorted_fe, 60 | const std::size_t i_frame, 61 | const std::size_t limit, 62 | const float max_dist); 63 | 64 | }}} // end Clustering::Density::CUDA 65 | 66 | -------------------------------------------------------------------------------- /src/network_builder.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | /*! \file 32 | * \brief Network Builder 33 | * 34 | * \sa \link Clustering::NetworkBuilder 35 | */ 36 | namespace Clustering { 37 | /*! 38 | * \brief functions for network creation from free energy screening 39 | * 40 | * This module finds local minimas in the free energy landscape. Therefore, 41 | * it build a network from the previously determined clusters. 42 | */ 43 | namespace NetworkBuilder { 44 | /*! 45 | * controlling function and user interface for network creation 46 | * 47 | * \param min min. free energy to take into account 48 | * \param max max. free energy to take into account 49 | * \param step free energy stepping 50 | * \param basename basic input file format 51 | * \param minpop min. population per microstate, discard states with lower population 52 | * \param network-html generate an html representation of the network 53 | */ 54 | void 55 | main(boost::program_options::variables_map args); 56 | } // end namespace Clustering 57 | } // end namespace NetworkBuilder 58 | 59 | -------------------------------------------------------------------------------- /src/density_clustering_common.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include "config.hpp" 28 | #include "density_clustering.hpp" 29 | 30 | /*! \file 31 | * this module holds common implementations for both, single-node and MPI code. 32 | * it is used for functions that are too similar for both versions and have 33 | * only slight variations that can be implemented by 'ifdef'-guards. 34 | */ 35 | 36 | namespace Clustering { 37 | namespace Density { 38 | // radius -> pops 39 | typedef std::map> Pops; 40 | 41 | //! returns state trajectory for clusters given by a free energy threshold. 42 | //! frames with a local free energy estimate higher than the given threshold 43 | //! will not be clustered and remain in 'state 0'. 44 | std::vector 45 | screening(const std::vector& free_energy 46 | , const Neighborhood& nh 47 | , const float free_energy_threshold 48 | , const float* coords 49 | , const std::size_t n_rows 50 | , const std::size_t n_cols 51 | , const std::vector initial_clusters 52 | #ifdef DC_USE_MPI 53 | , const int mpi_n_nodes 54 | , const int mpi_node_id 55 | #endif 56 | ); 57 | }} // end namespace Clustering::Density 58 | 59 | -------------------------------------------------------------------------------- /src/coords_file/coords_file.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Florian Sittel (www.lettis.net) 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | extern "C" { 34 | // use xdrfile library to read/write xtc and trr files from gromacs 35 | #include "xdrfile/xdrfile.h" 36 | #include "xdrfile/xdrfile_xtc.h" 37 | #include "xdrfile/xdrfile_trr.h" 38 | } 39 | 40 | namespace CoordsFile { 41 | 42 | class Handler { 43 | public: 44 | virtual std::vector next() = 0; 45 | virtual void write(std::vector row) = 0; 46 | virtual bool eof() = 0; 47 | }; 48 | 49 | class AsciiHandler : public Handler { 50 | public: 51 | AsciiHandler(std::string fname, std::string mode); 52 | std::vector next(); 53 | void write(std::vector row); 54 | bool eof(); 55 | protected: 56 | std::ifstream _ifs; 57 | std::ofstream _ofs; 58 | bool _eof; 59 | std::string _mode; 60 | }; 61 | 62 | class XtcHandler : public Handler { 63 | public: 64 | XtcHandler(std::string fname, std::string mode); 65 | ~XtcHandler(); 66 | std::vector next(); 67 | void write(std::vector row); 68 | bool eof(); 69 | protected: 70 | bool _eof; 71 | std::string _mode; 72 | int _natoms; 73 | int _nrow; 74 | XDRFILE* _xdr; 75 | rvec* _coord_buf; 76 | }; 77 | 78 | typedef std::unique_ptr FilePointer; 79 | 80 | template std::vector 81 | split(std::string s); 82 | 83 | FilePointer 84 | open(std::string fname, std::string mode); 85 | 86 | } // end namespace 'CoordsFile' 87 | 88 | -------------------------------------------------------------------------------- /bash_completion_clustering.sh: -------------------------------------------------------------------------------- 1 | # add completion for clustering 2 | _clustering() 3 | { 4 | local cur prev opts 5 | COMPREPLY=() 6 | cur="${COMP_WORDS[COMP_CWORD]}" 7 | prev="${COMP_WORDS[COMP_CWORD-1]}" 8 | mode="${COMP_WORDS[1]}" 9 | # opts for single file argument 10 | # nopts for no options 11 | # fopts for no autocompleion option (for numbers) 12 | 13 | # mode completion 14 | if [[ ${prev} == "clustering" ]]; then 15 | nopts="density network mpp coring noise filter stats" 16 | else 17 | # mode specific completion 18 | case "${mode}" in 19 | density) 20 | opts="--file --output --input --population --free-energy --free-energy-input --nearest-neighbors --nearest-neighbors-input" 21 | nopts="--help --nthreads --verbose" 22 | fopts="--radius --radii --threshold-screening" 23 | ;; 24 | network) 25 | opts="--minpop --basename --output" 26 | nopts="--help --network-html --verbose" 27 | fopts="--min --max --step" 28 | ;; 29 | mpp) 30 | opts="--states --free-energy-input --concat-limits --tprob --output" 31 | nopts="--help --verbose" 32 | fopts="--lagtime --qmin-from --qmin-to --qmin-step --concat-nframes --nthreads" 33 | ;; 34 | coring) 35 | opts="--states --windows --output --distrubtion --cores--concat-limits" 36 | nopts="--help --verbose --iterative" 37 | fopts="--concat-nframes" 38 | ;; 39 | noise) 40 | opts="--states --output --basename --cores --concat-limits" 41 | nopts="--help --verbose" 42 | fopts="--concat-nframes --cmin" 43 | ;; 44 | filter) 45 | opts="--states --coords --output" 46 | nopts="--help --verbose" 47 | fopts="--selected-states --every-nth --nRandom" 48 | ;; 49 | stats) 50 | opts="--states --concat-limits" 51 | nopts="--help" 52 | fopts="--concat-nframes" 53 | ;; 54 | *) 55 | ;; 56 | esac 57 | fi 58 | # if opts was parsed 59 | if [[ " ${opts} " == *" ${prev} "* ]]; then 60 | COMPREPLY=( $(compgen -f -- ${cur}) ) 61 | # if fopts was parse, no completion is returned 62 | elif [[ " ${fopts} " == *" ${prev} "* ]]; then 63 | COMPREPLY=() 64 | # complete one of the given options 65 | elif [[ "${opts} ${nopts} ${fopts}" == *"${cur}"* ]]; then 66 | COMPREPLY=( $(compgen -W "${opts} ${nopts} ${fopts}" -- ${cur}) ) 67 | # return fallback file-directory completion 68 | else 69 | COMPREPLY=( $(compgen -df -- ${cur}) ) 70 | fi 71 | return 0 72 | } 73 | complete -o filenames -F _clustering clustering 74 | 75 | -------------------------------------------------------------------------------- /src/coords_file/xdrfile/xdrfile_xtc.c: -------------------------------------------------------------------------------- 1 | /* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- 2 | * 3 | * $Id: xdrfile_xtc.c,v 1.5 2009/05/18 09:06:38 spoel Exp $ 4 | * 5 | * Copyright (c) Erik Lindahl, David van der Spoel 2003,2004. 6 | * Coordinate compression (c) by Frans van Hoesel. 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public License 10 | * as published by the Free Software Foundation; either version 3 11 | * of the License, or (at your option) any later version. 12 | */ 13 | 14 | #include 15 | #include "xdrfile.h" 16 | #include "xdrfile_xtc.h" 17 | 18 | #define MAGIC 1995 19 | 20 | enum { FALSE, TRUE }; 21 | 22 | static int xtc_header(XDRFILE *xd,int *natoms,int *step,float *time,mybool bRead) 23 | { 24 | int result,magic,n=1; 25 | 26 | /* Note: read is same as write. He he he */ 27 | magic = MAGIC; 28 | if ((result = xdrfile_write_int(&magic,n,xd)) != n) 29 | { 30 | if (bRead) 31 | return exdrENDOFFILE; 32 | else 33 | return exdrINT; 34 | } 35 | if (magic != MAGIC) 36 | return exdrMAGIC; 37 | if ((result = xdrfile_write_int(natoms,n,xd)) != n) 38 | return exdrINT; 39 | if ((result = xdrfile_write_int(step,n,xd)) != n) 40 | return exdrINT; 41 | if ((result = xdrfile_write_float(time,n,xd)) != n) 42 | return exdrFLOAT; 43 | 44 | return exdrOK; 45 | } 46 | 47 | static int xtc_coord(XDRFILE *xd,int *natoms,matrix box,rvec *x,float *prec, 48 | mybool bRead) 49 | { 50 | int i,j,result; 51 | 52 | /* box */ 53 | result = xdrfile_read_float(box[0],DIM*DIM,xd); 54 | if (DIM*DIM != result) 55 | return exdrFLOAT; 56 | else 57 | { 58 | if (bRead) 59 | { 60 | result = xdrfile_decompress_coord_float(x[0],natoms,prec,xd); 61 | if (result != *natoms) 62 | return exdr3DX; 63 | } 64 | else 65 | { 66 | result = xdrfile_compress_coord_float(x[0],*natoms,*prec,xd); 67 | if (result != *natoms) 68 | return exdr3DX; 69 | } 70 | } 71 | return exdrOK; 72 | } 73 | 74 | int read_xtc_natoms(const char *fn,int *natoms) 75 | { 76 | XDRFILE *xd; 77 | int step,result; 78 | float time; 79 | 80 | xd = xdrfile_open(fn,"r"); 81 | if (NULL == xd) 82 | return exdrFILENOTFOUND; 83 | result = xtc_header(xd,natoms,&step,&time,TRUE); 84 | xdrfile_close(xd); 85 | 86 | return result; 87 | } 88 | 89 | int read_xtc(XDRFILE *xd, 90 | int natoms,int *step,float *time, 91 | matrix box,rvec *x,float *prec) 92 | /* Read subsequent frames */ 93 | { 94 | int result; 95 | 96 | if ((result = xtc_header(xd,&natoms,step,time,TRUE)) != exdrOK) 97 | return result; 98 | 99 | if ((result = xtc_coord(xd,&natoms,box,x,prec,1)) != exdrOK) 100 | return result; 101 | 102 | return exdrOK; 103 | } 104 | 105 | int write_xtc(XDRFILE *xd, 106 | int natoms,int step,float time, 107 | matrix box,rvec *x,float prec) 108 | /* Write a frame to xtc file */ 109 | { 110 | int result; 111 | 112 | if ((result = xtc_header(xd,&natoms,&step,&time,FALSE)) != exdrOK) 113 | return result; 114 | 115 | if ((result = xtc_coord(xd,&natoms,box,x,&prec,0)) != exdrOK) 116 | return result; 117 | 118 | return exdrOK; 119 | } 120 | -------------------------------------------------------------------------------- /src/noise.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | /*! \file 32 | * \brief Noise Assignment 33 | * 34 | * \sa \link Clustering::Noise 35 | */ 36 | namespace Clustering { 37 | /*! 38 | * \brief functions related to noise assignment 39 | * 40 | * This module contains all function for identifying and dynamically 41 | * reassigning noise. The underlaying principal is to assign low populated 42 | * regions dynamically to the previous state, to improve the meta-stability 43 | * of the resulting states. 44 | * In Nagel19 it was shown that this works better than coring in case of low 45 | * dimensional input. I.e., if the input is not homogeniously distributed in 46 | * the input coordinates. 47 | */ 48 | namespace Noise { 49 | //! map for sorting clusters by population 50 | typedef std::map CounterClustMap; 51 | 52 | /*! 53 | * \brief controlling function and user interface for noise assignment 54 | * 55 | * \param states single column file with state information. 56 | * \param basename basename used in 'clustering network' (def.: 'clust.'). 57 | * \param cmin population threshold in percent below which an geometrically 58 | * isolated cluster gets assigned as noise. 59 | * \param concat-nframes no. of frames per trajectory. 60 | * \param concat-limits length of concated trajectories. 61 | * \param output file name to store resulting trajectory. 62 | * \param cores file name to store resulting cores. 63 | * \return void 64 | * \note This code needs to be executed from the same directory as clustering 65 | * density 66 | * \warning This function is still in beta. 67 | */ 68 | void 69 | main(boost::program_options::variables_map args); 70 | } // end namespace Noise 71 | } // end namespace Clustering 72 | 73 | -------------------------------------------------------------------------------- /FindOpenCL.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find OpenCL 2 | # This module tries to find an OpenCL implementation on your system. It supports 3 | # AMD / ATI, Apple and NVIDIA implementations, but should work, too. 4 | # 5 | # To set manually the paths, define these environment variables: 6 | # OpenCL_INCPATH - Include path (e.g. OpenCL_INCPATH=/opt/cuda/4.0/cuda/include) 7 | # OpenCL_LIBPATH - Library path (e.h. OpenCL_LIBPATH=/usr/lib64/nvidia) 8 | # 9 | # Once done this will define 10 | # OPENCL_FOUND - system has OpenCL 11 | # OPENCL_INCLUDE_DIRS - the OpenCL include directory 12 | # OPENCL_LIBRARIES - link these to use OpenCL 13 | # 14 | # WIN32 should work, but is untested 15 | 16 | FIND_PACKAGE(PackageHandleStandardArgs) 17 | 18 | SET (OPENCL_VERSION_STRING "0.1.0") 19 | SET (OPENCL_VERSION_MAJOR 0) 20 | SET (OPENCL_VERSION_MINOR 1) 21 | SET (OPENCL_VERSION_PATCH 0) 22 | 23 | IF (APPLE) 24 | 25 | FIND_LIBRARY(OPENCL_LIBRARIES OpenCL DOC "OpenCL lib for OSX") 26 | FIND_PATH(OPENCL_INCLUDE_DIRS OpenCL/cl.h DOC "Include for OpenCL on OSX") 27 | FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS OpenCL/cl.hpp DOC "Include for OpenCL CPP bindings on OSX") 28 | 29 | ELSE (APPLE) 30 | 31 | IF (WIN32) 32 | 33 | FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h) 34 | FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp) 35 | 36 | # The AMD SDK currently installs both x86 and x86_64 libraries 37 | # This is only a hack to find out architecture 38 | IF( ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64" ) 39 | SET(OPENCL_LIB_DIR "$ENV{ATISTREAMSDKROOT}/lib/x86_64") 40 | ELSE (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") 41 | SET(OPENCL_LIB_DIR "$ENV{ATISTREAMSDKROOT}/lib/x86") 42 | ENDIF( ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64" ) 43 | FIND_LIBRARY(OPENCL_LIBRARIES OpenCL.lib PATHS ${OPENCL_LIB_DIR} ENV OpenCL_LIBPATH) 44 | 45 | GET_FILENAME_COMPONENT(_OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE) 46 | 47 | # On Win32 search relative to the library 48 | FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS "${_OPENCL_INC_CAND}" ENV OpenCL_INCPATH) 49 | FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS "${_OPENCL_INC_CAND}" ENV OpenCL_INCPATH) 50 | 51 | ELSE (WIN32) 52 | 53 | # Unix style platforms 54 | FIND_LIBRARY(OPENCL_LIBRARIES OpenCL 55 | PATHS ENV LD_LIBRARY_PATH ENV OpenCL_LIBPATH 56 | ) 57 | 58 | GET_FILENAME_COMPONENT(OPENCL_LIB_DIR ${OPENCL_LIBRARIES} PATH) 59 | GET_FILENAME_COMPONENT(_OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE) 60 | 61 | # The AMD SDK currently does not place its headers 62 | # in /usr/include, therefore also search relative 63 | # to the library 64 | FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH) 65 | FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH) 66 | 67 | ENDIF (WIN32) 68 | 69 | ENDIF (APPLE) 70 | 71 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenCL DEFAULT_MSG OPENCL_LIBRARIES OPENCL_INCLUDE_DIRS) 72 | 73 | IF(_OPENCL_CPP_INCLUDE_DIRS) 74 | SET( OPENCL_HAS_CPP_BINDINGS TRUE ) 75 | LIST( APPEND OPENCL_INCLUDE_DIRS ${_OPENCL_CPP_INCLUDE_DIRS} ) 76 | # This is often the same, so clean up 77 | LIST( REMOVE_DUPLICATES OPENCL_INCLUDE_DIRS ) 78 | ENDIF(_OPENCL_CPP_INCLUDE_DIRS) 79 | 80 | MARK_AS_ADVANCED( 81 | OPENCL_INCLUDE_DIRS 82 | ) 83 | 84 | -------------------------------------------------------------------------------- /src/coring.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | /*! \file 32 | * \brief Dynamical Coring 33 | * 34 | * \sa \link Clustering::Coring 35 | */ 36 | 37 | namespace Clustering { 38 | /*! 39 | * \brief functions related to dynamical coring 40 | * 41 | * This module contains all functions for finding the optimal coring time and 42 | * dynamical coring. The underlaying principal is to define dynamical cores. 43 | * In contrast to geometrical cores, this algorithm scales linear with the 44 | * the number of frames. The idea is to require after a transition to stay 45 | * at least for a certain time (coring time) in the new state, otherwise 46 | * the transition is identified as intrastate fluctuation and the frames are 47 | * are assigned to the previous state. A more in detail discussion can be 48 | * found in Nagel19. 49 | */ 50 | namespace Coring { 51 | //! store the waiting time distribution for each state with time vs count. 52 | typedef std::map WTDMap; 53 | 54 | /*! 55 | * \brief compute the waiting time distribution for single state 56 | * 57 | * \param streaks array with all wainting times 58 | */ 59 | WTDMap 60 | compute_wtd(std::list streaks); 61 | 62 | /*! 63 | * \brief controlling function and user interface for boundary corrections 64 | * 65 | * \param states single column file with state information. 66 | * \param windows double column file with states and their coring time 67 | * \param distribution generate and write waiting time distributions to file. 68 | * \param output file name to store resulting trajectory. 69 | * \param concat-nframes no. of frames per trajectory. 70 | * \param concat-limits length of concated trajectories. 71 | * \param cores file name to store resulting cores. 72 | * \return void 73 | */ 74 | void 75 | main(boost::program_options::variables_map args); 76 | } // end namespace Coring 77 | } // end namespace Clustering 78 | 79 | -------------------------------------------------------------------------------- /src/density_clustering_mpi.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #pragma once 26 | 27 | #include "config.hpp" 28 | #include "density_clustering.hpp" 29 | 30 | #include 31 | 32 | #include 33 | 34 | namespace Clustering { 35 | namespace Density { 36 | //! MPI implementations of compute intensive functions. 37 | namespace MPI { 38 | //! identify MPI process 0 as main process 39 | const int MAIN_PROCESS = 0; 40 | //! MPI implementation of 41 | //! \link Clustering::Density::calculate_populations(const float* coords, const std::size_t n_rows, const std::size_t n_cols, const float radius) 42 | std::vector 43 | calculate_populations(const float* coords, 44 | const std::size_t n_rows, 45 | const std::size_t n_cols, 46 | const float radius, 47 | const int mpi_n_nodes, 48 | const int mpi_node_id); 49 | //! MPI implementation of 50 | //! \link Clustering::Density::calculate_populations(const float* coords, const std::size_t n_rows, const std::size_t n_cols, const std::vector radii) 51 | std::map> 52 | calculate_populations(const float* coords, 53 | const std::size_t n_rows, 54 | const std::size_t n_cols, 55 | std::vector radii, 56 | const int mpi_n_nodes, 57 | const int mpi_node_id); 58 | //! MPI implementation of 59 | //! \link Clustering::Density::nearest_neighbors 60 | std::tuple 61 | nearest_neighbors(const float* coords, 62 | const std::size_t n_rows, 63 | const std::size_t n_cols, 64 | const std::vector& free_energy, 65 | const int mpi_n_nodes, 66 | const int mpi_node_id); 67 | //! MPI implementation of 68 | //! \link Clustering::Density::high_density_neighborhood 69 | std::set 70 | high_density_neighborhood(const float* coords, 71 | const std::size_t n_cols, 72 | const std::vector& sorted_fe, 73 | const std::size_t i_frame, 74 | const std::size_t limit, 75 | const float max_dist, 76 | const int mpi_n_nodes, 77 | const int mpi_node_id); 78 | //! MPI implementation of 79 | //! \link Clustering::Density::main 80 | void 81 | main(boost::program_options::variables_map args); 82 | } // end namespace MPI 83 | } // end namespace Density 84 | } // end namespace Clustering 85 | 86 | -------------------------------------------------------------------------------- /src/coords_file/coords_file.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Florian Sittel (www.lettis.net) 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #include "coords_file.hpp" 26 | 27 | #include 28 | 29 | namespace CoordsFile { 30 | 31 | template 32 | std::vector 33 | split(std::string s) { 34 | std::vector v; 35 | std::istringstream iss(s); 36 | while(iss.good()) { 37 | T buf; 38 | iss >> buf; 39 | v.push_back(buf); 40 | } 41 | return v; 42 | } 43 | 44 | //// ASCII handler 45 | 46 | AsciiHandler::AsciiHandler(std::string fname, std::string mode) 47 | : _eof(false) 48 | , _mode(mode) { 49 | if (mode == "r") { 50 | this->_ifs.open(fname); 51 | } else if (mode == "w") { 52 | this->_ofs.open(fname); 53 | } else { 54 | std::cerr << "unknown mode: " << mode << std::endl; 55 | exit(EXIT_FAILURE); 56 | } 57 | } 58 | 59 | std::vector 60 | AsciiHandler::next() { 61 | if (_ifs.is_open() && _ifs.good()) { 62 | std::string s; 63 | std::getline(_ifs, s); 64 | if (_ifs.good()) { 65 | if (s == "") { 66 | // skip empty lines 67 | return this->next(); 68 | } else { 69 | return split(s); 70 | } 71 | } 72 | } 73 | _eof = true; 74 | return {}; 75 | } 76 | 77 | void 78 | AsciiHandler::write(std::vector row) { 79 | if (_ofs.is_open() && _ofs.good()) { 80 | for (float f: row) { 81 | _ofs << " " << f; 82 | } 83 | _ofs << std::endl; 84 | } 85 | } 86 | 87 | bool 88 | AsciiHandler::eof() { 89 | return _eof; 90 | } 91 | 92 | 93 | //// XTC handler 94 | 95 | XtcHandler::XtcHandler(std::string fname, std::string mode) 96 | : _eof(false) 97 | , _mode(mode) 98 | , _nrow(0) { 99 | if (_mode == "r") { 100 | read_xtc_natoms(fname.c_str(), &_natoms); 101 | _coord_buf = static_cast(calloc(_natoms, sizeof(_coord_buf[0]))); 102 | } 103 | _xdr = xdrfile_open(fname.c_str(), mode.c_str()); 104 | } 105 | 106 | XtcHandler::~XtcHandler() { 107 | xdrfile_close(_xdr); 108 | if (_mode == "r") { 109 | free(_coord_buf); 110 | } 111 | } 112 | 113 | std::vector 114 | XtcHandler::next() { 115 | if (_mode == "r") { 116 | int step; 117 | float time_step; 118 | float prec; 119 | matrix box; 120 | int err = read_xtc(_xdr, _natoms, &step, &time_step, box, _coord_buf, &prec); 121 | if (err == exdrOK) { 122 | std::vector v(_natoms*3); 123 | for (int i=0; i < _natoms; ++i) { 124 | v[3*i] = _coord_buf[i][0]; 125 | v[3*i+1] = _coord_buf[i][1]; 126 | v[3*i+2] = _coord_buf[i][2]; 127 | } 128 | return v; 129 | } 130 | } 131 | _eof = true; 132 | return {}; 133 | } 134 | 135 | void 136 | XtcHandler::write(std::vector row) { 137 | if (_mode == "w") { 138 | float fake_box_matrix[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; 139 | int natoms = row.size() / 3; 140 | rvec* x = static_cast(calloc(natoms, sizeof(rvec))); 141 | for (int i=0; i < natoms; ++i) { 142 | x[i][0] = row[3*i]; 143 | x[i][1] = row[3*i+1]; 144 | x[i][2] = row[3*i+2]; 145 | } 146 | write_xtc(_xdr, natoms, _nrow, _nrow*1.0f, fake_box_matrix, x, 1000.0f); 147 | free(x); 148 | ++_nrow; 149 | } 150 | } 151 | 152 | bool 153 | XtcHandler::eof() { 154 | return _eof; 155 | } 156 | 157 | 158 | //// unifying interface 159 | 160 | FilePointer 161 | open(std::string fname, std::string mode) { 162 | if ((fname.size() > 4) 163 | && (fname.compare(fname.size()-4, 4, ".xtc") == 0)) { 164 | return FilePointer(new XtcHandler(fname, mode)); 165 | } else { 166 | return FilePointer(new AsciiHandler(fname, mode)); 167 | } 168 | } 169 | 170 | } // end namespace 'CoordsFile' 171 | 172 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Florian Sittel (www.lettis.net) 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 15 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 17 | # SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 19 | # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 21 | # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 22 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | cmake_minimum_required (VERSION 2.8) 25 | project (clustering) 26 | 27 | # do we want static libraries? 28 | # When STATIC_LINKING is set, cmake looks for libraries called *.a. 29 | if(STATIC_LINKING) 30 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 31 | endif(STATIC_LINKING) 32 | 33 | # Gnu compiler setup 34 | if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") 35 | message("using Gnu compiler") 36 | # use C++ 2011 standard 37 | set (CMAKE_CXX_FLAGS "-std=c++11") 38 | # profiling 39 | #set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -pg") 40 | # optimization 41 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") 42 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftree-vectorize") 43 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math") 44 | # parallelization 45 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") 46 | # warnings 47 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 48 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") 49 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas") 50 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-declarations") 51 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-gpu-targets") 52 | 53 | if (NATIVE_COMPILATION) 54 | message("native compilation: this code will ONLY run on THIS machine") 55 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") 56 | endif() 57 | set (DC_MEM_ALIGNMENT 32) 58 | if (CPU_ACCELERATION) 59 | if (${CPU_ACCELERATION} STREQUAL "SSE2") 60 | message("using SSE2") 61 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2") 62 | set (DC_MEM_ALIGNMENT 16) 63 | 64 | elseif (${CPU_ACCELERATION} STREQUAL "SSE4_1") 65 | message("using SSE4_1") 66 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1") 67 | set (DC_MEM_ALIGNMENT 16) 68 | 69 | elseif (${CPU_ACCELERATION} STREQUAL "SSE4_2") 70 | message("using SSE4_2") 71 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2") 72 | set (DC_MEM_ALIGNMENT 16) 73 | 74 | elseif (${CPU_ACCELERATION} STREQUAL "AVX") 75 | message("using AVX") 76 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx") 77 | set (DC_MEM_ALIGNMENT 32) 78 | else() 79 | message(SEND_ERROR "unknown instruction set: ${CPU_ACCELERATION}") 80 | endif() 81 | else() 82 | message("using standard CPU acceleration with memory aligned at ${DC_MEM_ALIGNMENT} bytes") 83 | endif() 84 | else() 85 | message(SEND_ERROR "currently no other compiler than the GCC is supported. sorry.") 86 | endif() 87 | 88 | configure_file(config.hpp.cmake.in ${CMAKE_BINARY_DIR}/generated/config.hpp) 89 | include_directories(${CMAKE_BINARY_DIR}/generated/) 90 | 91 | find_package (Boost 1.49 COMPONENTS program_options system filesystem REQUIRED) 92 | include_directories (${Boost_INCLUDE_DIR}) 93 | 94 | add_subdirectory(src/coords_file) 95 | 96 | 97 | set(CLUSTERING_SRCS src/clustering.cpp 98 | src/density_clustering.cpp 99 | src/density_clustering_common.cpp 100 | src/mpp.cpp 101 | src/network_builder.cpp 102 | src/state_filter.cpp 103 | src/coring.cpp 104 | src/noise.cpp 105 | src/tools.cpp 106 | src/logger.cpp) 107 | 108 | set(CLUSTERING_LIBS ${Boost_LIBRARIES} coords_file) 109 | 110 | if(${USE_CUDA}) 111 | message(STATUS "using CUDA") 112 | find_package(CUDA REQUIRED) 113 | set(CUDA_PROPAGATE_HOST_FLAGS OFF) 114 | set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-std=c++11;-O3;-DVERBOSE;-Xcompiler -fopenmp") 115 | set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-arch=compute_30") 116 | # debugging 117 | #set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-g -G") 118 | 119 | set (CLUSTERING_SRCS ${CLUSTERING_SRCS} 120 | src/density_clustering_cuda.cu 121 | src/density_clustering_cuda_kernels.cu) 122 | 123 | set (CLUSTERING_LIBS ${CLUSTERING_LIBS} ${CUDA_LIBRARIES}) 124 | include_directories (${CUDA_INCLUDE_DIRS}) 125 | add_definitions(-DUSE_CUDA) 126 | endif() 127 | 128 | 129 | set (PROGNAME clustering) 130 | 131 | 132 | if (${USE_CUDA}) 133 | # set (PROGNAME ${PROGNAME}.cuda) 134 | cuda_add_executable(${PROGNAME} ${CLUSTERING_SRCS}) 135 | else() 136 | add_executable(${PROGNAME} ${CLUSTERING_SRCS}) 137 | endif() 138 | 139 | target_link_libraries(${PROGNAME} ${CLUSTERING_LIBS}) 140 | 141 | 142 | # set -static, when STATIC_LINKING is TRUE and set LINK_SEARCH_END_STATIC 143 | # to remove the additional -bdynamic from the linker line. 144 | if(STATIC_LINKING) 145 | set(CMAKE_EXE_LINKER_FLAGS "-static") 146 | set_target_properties(${PROGNAME} PROPERTIES LINK_SEARCH_END_STATIC 1) 147 | endif(STATIC_LINKING) 148 | 149 | 150 | install(TARGETS ${PROGNAME} RUNTIME DESTINATION .) 151 | 152 | # create source-doc with doxygen 153 | add_custom_target(doc 154 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 155 | COMMAND doxygen doxygen.config) 156 | 157 | -------------------------------------------------------------------------------- /src/density_clustering_common.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "logger.hpp" 27 | #include "density_clustering_common.hpp" 28 | #include 29 | 30 | #ifdef DC_USE_MPI 31 | #include "density_clustering_mpi.hpp" 32 | #endif 33 | 34 | namespace Clustering { 35 | namespace Density { 36 | 37 | std::vector 38 | screening(const std::vector& free_energy 39 | , const Neighborhood& nh 40 | , const float free_energy_threshold 41 | , const float* coords 42 | , const std::size_t n_rows 43 | , const std::size_t n_cols 44 | , const std::vector initial_clusters 45 | #ifdef DC_USE_MPI 46 | , const int mpi_n_nodes 47 | , const int mpi_node_id 48 | #endif 49 | ) { 50 | #ifdef DC_USE_MPI 51 | using namespace Clustering::Density::MPI; 52 | #endif 53 | std::vector clustering; 54 | std::size_t first_frame_above_threshold; 55 | double sigma2; 56 | std::vector fe_sorted; 57 | std::set visited_frames; 58 | std::size_t distinct_name; 59 | // data preparation 60 | std::tie(clustering 61 | , first_frame_above_threshold 62 | , sigma2 63 | , fe_sorted 64 | , visited_frames 65 | , distinct_name) = prepare_initial_clustering(free_energy 66 | , nh 67 | , free_energy_threshold 68 | , n_rows 69 | , initial_clusters); 70 | Clustering::logger(std::cout) << " " << std::setw(6) 71 | << Clustering::Tools::stringprintf("%.2f", free_energy_threshold) 72 | << " " << std::setw(9) 73 | << Clustering::Tools::stringprintf("%i", first_frame_above_threshold) 74 | << std::endl; 75 | #ifdef DC_USE_MPI 76 | if (mpi_node_id == MAIN_PROCESS) { 77 | #endif 78 | screening_log(sigma2 79 | , first_frame_above_threshold 80 | , fe_sorted); 81 | #ifdef DC_USE_MPI 82 | } 83 | #endif 84 | // indices inside this loop are in order of sorted(!) free energies 85 | bool neighboring_clusters_merged = false; 86 | //TODO: this while loop shouldn't be necessary, resp. 87 | // will always finish trivially after 2 runs, since nothing will 88 | // happen as all frames will have been visitied... 89 | while ( ! neighboring_clusters_merged) { 90 | neighboring_clusters_merged = true; 91 | #ifdef DC_USE_MPI 92 | if (mpi_node_id == MAIN_PROCESS) { 93 | #endif 94 | // logger(std::cout) << "initial merge iteration" << std::endl; 95 | #ifdef DC_USE_MPI 96 | } 97 | #endif 98 | for (std::size_t i=0; i < first_frame_above_threshold; ++i) { 99 | if (visited_frames.count(i) == 0) { 100 | visited_frames.insert(i); 101 | // all frames/clusters in local neighborhood should be merged ... 102 | #ifdef DC_USE_MPI 103 | using hdn_mpi = Clustering::Density::MPI::high_density_neighborhood; 104 | std::set local_nh = hdn_mpi(coords, 105 | n_cols, 106 | fe_sorted, 107 | i, 108 | first_frame_above_threshold, 109 | 4*sigma2, 110 | mpi_n_nodes, 111 | mpi_node_id); 112 | #else 113 | //TODO use box-assisted search on 114 | // fe_sorted coords for 'high_density_neighborhood' 115 | std::set local_nh = high_density_neighborhood(coords, 116 | n_cols, 117 | fe_sorted, 118 | i, 119 | first_frame_above_threshold, 120 | 4*sigma2); 121 | #endif 122 | neighboring_clusters_merged = lump_initial_clusters(local_nh 123 | , distinct_name 124 | , clustering 125 | , fe_sorted 126 | , first_frame_above_threshold) 127 | && neighboring_clusters_merged; 128 | } 129 | } // end for 130 | } // end while 131 | return normalized_cluster_names(first_frame_above_threshold 132 | , clustering 133 | , fe_sorted); 134 | } 135 | 136 | } // end namespace Density 137 | } // end namespace Clustering 138 | 139 | -------------------------------------------------------------------------------- /src/density_clustering_opencl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #define __CL_ENABLE_EXCEPTIONS 27 | 28 | #include "density_clustering_opencl.hpp" 29 | 30 | #include 31 | 32 | namespace Clustering { 33 | namespace Density { 34 | namespace OpenCL { 35 | 36 | std::map> 37 | calculate_populations(const float* coords, 38 | const std::size_t n_rows, 39 | const std::size_t n_cols, 40 | std::vector radii) { 41 | unsigned int uint_n_rows = (unsigned int) n_rows; 42 | unsigned int uint_n_cols = (unsigned int) n_cols; 43 | try { 44 | std::vector platforms; 45 | cl::Platform::get(&platforms); 46 | cl_context_properties cps[3] = { 47 | CL_CONTEXT_PLATFORM, 48 | (cl_context_properties) (platforms[0])(), 49 | 0 50 | }; 51 | cl::Context context(CL_DEVICE_TYPE_GPU, cps); 52 | std::vector devices = context.getInfo(); 53 | std::vector queues; 54 | for (cl::Device dev: devices) { 55 | queues.push_back(cl::CommandQueue(context, dev)); 56 | } 57 | std::size_t n_queues = queues.size(); 58 | // compute needed/avail mem sizes 59 | std::size_t n_bytes_per_row; 60 | std::size_t n_bytes_global_mem; 61 | n_bytes_per_row = n_cols * sizeof(float); 62 | n_bytes_global_mem = devices[0].getInfo(); 63 | // do devices have enough memory for full data set? 64 | if (n_bytes_per_row * n_rows + (sizeof(unsigned int)*n_rows) > n_bytes_global_mem) { 65 | // TODO compute in chunks 66 | std::cerr << "error: not enough memory on device for full data set.\n" 67 | << " will support memory-size independet computation in a later release.\n" 68 | << " please check for updates." << std::endl; 69 | exit(EXIT_FAILURE); 70 | } 71 | // create buffers and copy data to device(s) 72 | cl::Buffer buf_coords = cl::Buffer(context, CL_MEM_READ_ONLY, n_rows*n_cols*sizeof(float)); 73 | std::vector buf_pops(n_queues); 74 | for (int iq=0; iq < n_queues; ++iq) { 75 | queues[iq].enqueueWriteBuffer(buf_coords, CL_TRUE, 0, n_rows*n_cols*sizeof(float), coords); 76 | buf_pops[iq] = cl::Buffer(context, CL_MEM_WRITE_ONLY, n_rows*sizeof(unsigned int)); 77 | } 78 | //TODO: fix 79 | // load kernel source 80 | // std::string kernel_src = 81 | // #include "kernel/pops.h" 82 | // ; 83 | cl::Program::Sources src(1, {kernel_src.c_str(), kernel_src.length()+1}); 84 | cl::Program prog = cl::Program(context, src); 85 | int err = prog.build(devices); 86 | if (err != CL_SUCCESS) { 87 | std::cerr << "error during kernel compilation" << std::endl; 88 | std::cerr << prog.getBuildInfo(devices[0]) << std::endl; 89 | exit(EXIT_FAILURE); 90 | } 91 | // initialize pops for every queue to zero 92 | cl::Kernel krnl_init_pops(prog, "init_pops"); 93 | for (int iq=0; iq < n_queues; ++iq) { 94 | krnl_init_pops.setArg(0, buf_pops[iq]); 95 | cl::NDRange full_global_range(n_rows); 96 | cl::Event event; 97 | queues[iq].enqueueNDRangeKernel(krnl_init_pops, cl::NullRange, full_global_range, cl::NullRange, NULL, &event); 98 | // very short and simple kernel: just do a blocking call 99 | event.wait(); 100 | } 101 | cl::Kernel krnl_pops(prog, "pops"); 102 | // set kernel args 103 | float rad2 = radii[0]*radii[0]; 104 | // TODO play with workgroup sizes 105 | const unsigned int GLOBAL_SIZE = 1024; 106 | const unsigned int WORKGROUP_SIZE = 128; 107 | krnl_pops.setArg(2, sizeof(unsigned int), &uint_n_rows); 108 | krnl_pops.setArg(3, sizeof(unsigned int), &uint_n_cols); 109 | krnl_pops.setArg(4, buf_coords); 110 | krnl_pops.setArg(5, sizeof(float), &rad2); 111 | krnl_pops.setArg(7, sizeof(float)*WORKGROUP_SIZE*n_cols, NULL); 112 | //// run kernel 113 | // extend range to a size that is evenly divisible by the workgroup size. 114 | // the kernel will ignore all workitems with index >= n_cols. 115 | unsigned int range_length = n_rows; 116 | while (range_length % WORKGROUP_SIZE != 0) { 117 | ++range_length; 118 | } 119 | cl::NDRange global(GLOBAL_SIZE); 120 | cl::NDRange local(WORKGROUP_SIZE); 121 | // run pops kernel repeatedly, until the full range has been sampled 122 | for (unsigned int i_block_ref=0; i_block_ref < range_length; i_block_ref += WORKGROUP_SIZE) { 123 | krnl_pops.setArg(1, sizeof(unsigned int), &i_block_ref); 124 | for (unsigned int i_block=0; i_block < range_length; i_block += n_queues*GLOBAL_SIZE) { 125 | std::vector events(n_queues); 126 | for (unsigned int iq=0; iq < n_queues; ++iq) { 127 | unsigned int q_block = i_block + iq*GLOBAL_SIZE; 128 | krnl_pops.setArg(0, sizeof(unsigned int), &q_block); 129 | krnl_pops.setArg(6, buf_pops[iq]); 130 | queues[iq].enqueueNDRangeKernel(kernel, cl::NullRange, global, local, NULL, &events[iq]); 131 | } 132 | cl::Event::waitForEvents(events); 133 | } 134 | } 135 | // retrieve results from all devices 136 | std::vector pops(n_rows, 0); 137 | for (int iq=0; iq < n_queues; ++iq) { 138 | std::vector partial_pops(n_rows); 139 | queues[iq].enqueueReadBuffer(buf_pops[iq], CL_TRUE, 0, n_rows*sizeof(unsigned int), partial_pops.data()); 140 | for (std::size_t i=0; i < n_rows; ++i) { 141 | pops[i] += partial_pops[i]; 142 | } 143 | } 144 | return {{radii[0], pops}}; 145 | } catch(cl::Error error) { 146 | std::cerr << "error in OpenCL call: " << error.what() << "(" << error.err() << ")" << std::endl; 147 | exit(EXIT_FAILURE); 148 | } 149 | } 150 | 151 | } // end namespace OpenCL 152 | } // end namespace Density 153 | } // end namespace Clustering 154 | 155 | -------------------------------------------------------------------------------- /src/mpp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015-2019, Florian Sittel (www.lettis.net) and Daniel Nagel 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "tools.hpp" 39 | /*! \file 40 | * \brief Most Probable Path Clustering 41 | * 42 | * \sa \link Clustering::MPP 43 | */ 44 | 45 | namespace Clustering { 46 | /*! 47 | * \brief functions related to "Most Probable Path"-clustering 48 | * 49 | * This module contains all function for dynamical clustering. In contrast to 50 | * density-based clustering, can it only be applied to previously clustered 51 | * trajectories. The idea is to create, based on a microstate input, a 52 | * coarse-grained model (macrostates). 53 | * The most probable path depends strongly on the selected timescale (mpp 54 | * time). If the input was dynamically cored, the mpp time needs to be 55 | * greater than the coring time. 56 | */ 57 | namespace MPP { 58 | //! BOOST implementation of a sparse matrix for floats 59 | using SparseMatrixF = boost::numeric::ublas::mapped_matrix; 60 | //! Neighborhood per frame 61 | using Neighborhood = Clustering::Tools::Neighborhood; 62 | //! read (row-normalized) transition matrix from file 63 | SparseMatrixF 64 | read_transition_probabilities(std::string fname); 65 | //! count transitions from one to the other cluster with certain lag 66 | //! and return as count matrix (row/col := from/to) 67 | SparseMatrixF 68 | transition_counts(std::vector trajectory 69 | , std::vector concat_limits 70 | , std::size_t n_lag_steps 71 | , std::size_t i_max = 0); 72 | //! same as 'transition_counts', but with reweighting account for 73 | //! differently sized trajectory chunks (as given by concat_limits) 74 | SparseMatrixF 75 | weighted_transition_counts(std::vector trajectory 76 | , std::vector concat_limits 77 | , std::size_t n_lag_steps); 78 | //! compute transition matrix from counts by normalization of rows 79 | SparseMatrixF 80 | row_normalized_transition_probabilities(SparseMatrixF count_matrix 81 | , std::set microstate_names); 82 | //! update transition matrix after lumping states into sinks 83 | SparseMatrixF 84 | updated_transition_probabilities(SparseMatrixF transition_matrix 85 | , std::map sinks 86 | , std::map pops); 87 | //! compute immediate future (i.e. without lag) of every state from highest probable transitions; 88 | //! exclude self-transitions. 89 | std::map 90 | single_step_future_state(SparseMatrixF transition_matrix, 91 | std::set cluster_names, 92 | float q_min, 93 | std::map min_free_energy); 94 | //! for every state, compute most probable path by following 95 | //! the 'future_state'-mapping recursively 96 | std::map> 97 | most_probable_path(std::map future_state, std::set cluster_names); 98 | //! compute cluster populations 99 | std::map 100 | microstate_populations(std::vector clusters, std::set cluster_names); 101 | //! assign every state the lowest free energy value 102 | //! of all of its frames. 103 | std::map 104 | microstate_min_free_energy(const std::vector& clustering, 105 | const std::vector& free_energy); 106 | //! compute path sinks, i.e. states of highest metastability, 107 | //! and lowest free energy per path. these sinks will be states all other 108 | //! states of the given path will be lumped into. 109 | std::map 110 | path_sinks(std::vector clusters, 111 | std::map> mpp, 112 | SparseMatrixF transition_matrix, 113 | std::set cluster_names, 114 | float q_min, 115 | std::vector free_energy); 116 | //! lump states based on path sinks and return new trajectory. 117 | //! new microstates will have IDs of sinks. 118 | std::vector 119 | lumped_trajectory(std::vector trajectory, 120 | std::map sinks); 121 | //! run clustering for given Q_min value 122 | std::tuple 123 | , std::map 124 | , SparseMatrixF> 125 | fixed_metastability_clustering(std::vector initial_trajectory, 126 | SparseMatrixF trans_prob, 127 | float q_min, 128 | std::vector free_energy); 129 | /*! 130 | * \brief MPP clustering control function and user interface 131 | * 132 | * \param input input file with microstate trajectory 133 | * \param basename name format for output files 134 | * \param lagtime lag for transition estimation in units of frame numbers 135 | * \param qmin-from lower limit for metastability (Q_min) 136 | * \param qmin-to upper limit for metastability (Q_min) 137 | * \param qmin-step stepping for metastability (Q_min) 138 | * \param concat-nframes no. of frames per trajectory. 139 | * \param concat-limits length of concated trajectories. 140 | * \return void 141 | * \note Lagtime should be greater than the coring time/ smallest 142 | * timescale. 143 | */ 144 | void 145 | main(boost::program_options::variables_map args); 146 | } // end namespace Clustering::MPP 147 | } // end namespace Clustering 148 | 149 | -------------------------------------------------------------------------------- /src/density_clustering_cuda_kernels.cu: -------------------------------------------------------------------------------- 1 | 2 | #include "density_clustering_cuda_kernels.hpp" 3 | 4 | namespace Clustering { 5 | namespace Density { 6 | namespace CUDA { 7 | namespace Kernel { 8 | 9 | __global__ void 10 | population_count(unsigned int offset 11 | , float* coords 12 | , unsigned int n_rows 13 | , unsigned int n_cols 14 | , float* radii2 15 | , unsigned int n_radii 16 | , unsigned int* pops 17 | , unsigned int i_from 18 | , unsigned int i_to) { 19 | extern __shared__ float smem[]; 20 | unsigned int bid = blockIdx.x; 21 | unsigned int tid = threadIdx.x; 22 | unsigned int bsize = blockDim.x; 23 | unsigned int gid = bid * bsize + tid + i_from; 24 | // load frames for comparison into shared memory 25 | int comp_size = min(bsize, n_rows - offset); 26 | if (tid < comp_size) { 27 | for (unsigned int j=0; j < n_cols; ++j) { 28 | smem[tid*n_cols+j] = coords[(tid+offset)*n_cols+j]; 29 | } 30 | } 31 | __syncthreads(); 32 | // count neighbors 33 | if (gid < i_to) { 34 | unsigned int ref_id = tid+bsize; 35 | // load reference coordinates for re-use into shared memory 36 | for (unsigned int j=0; j < n_cols; ++j) { 37 | smem[ref_id*n_cols+j] = coords[gid*n_cols+j]; 38 | } 39 | for (unsigned int r=0; r < n_radii; ++r) { 40 | unsigned int local_pop = 0; 41 | float rad2 = radii2[r]; 42 | for (unsigned int i=0; i < comp_size; ++i) { 43 | float dist2 = 0.0f; 44 | for (unsigned int j=0; j < n_cols; ++j) { 45 | float c = smem[ref_id*n_cols+j] - smem[i*n_cols+j]; 46 | dist2 = fma(c, c, dist2); 47 | } 48 | if (dist2 <= rad2) { 49 | ++local_pop; 50 | } 51 | } 52 | // update frame populations (per radius) 53 | pops[r*n_rows+gid] += local_pop; 54 | } 55 | } 56 | } 57 | 58 | __global__ void 59 | nearest_neighbor_search(unsigned int offset 60 | , float* coords 61 | , unsigned int n_rows 62 | , unsigned int n_cols 63 | , float* fe 64 | , unsigned int* nh_nhhd_ndx 65 | , float* nh_nhhd_dist 66 | , unsigned int i_from 67 | , unsigned int i_to) { 68 | // grid ids 69 | unsigned int bid = blockIdx.x; 70 | unsigned int tid = threadIdx.x; 71 | unsigned int bsize = blockDim.x; 72 | unsigned int gid = bid * bsize + tid + i_from; 73 | // free energy and local id for this frame 74 | float ref_fe; 75 | unsigned int ref_id; 76 | // shared memory for fast free energy / coordinate retrieval 77 | int comp_size = min(bsize, n_rows - offset); 78 | extern __shared__ float smem[]; 79 | float* smem_fe = (float*) smem; 80 | float* smem_coords = (float*) &smem[comp_size]; 81 | // load data of current block to compare with into shared memory 82 | if (tid < comp_size) { 83 | for (unsigned int j=0; j < n_cols; ++j) { 84 | smem_coords[tid*n_cols+j] = coords[(tid+offset)*n_cols+j]; 85 | } 86 | smem_fe[tid] = fe[tid+offset]; 87 | } 88 | __syncthreads(); 89 | if (gid < i_to) { 90 | ref_id = tid+bsize; 91 | // load reference coordinates for re-use into shared memory 92 | for (unsigned int j=0; j < n_cols; ++j) { 93 | smem_coords[ref_id*n_cols+j] = coords[gid*n_cols+j]; 94 | } 95 | // reference free energy 96 | ref_fe = fe[gid]; 97 | // load current best mindists for this frame into registers 98 | float nh_mindist = nh_nhhd_dist[gid]; 99 | float nhhd_mindist = nh_nhhd_dist[gid+n_rows]; 100 | unsigned int nh_minndx = nh_nhhd_ndx[gid]; 101 | unsigned int nhhd_minndx = nh_nhhd_ndx[gid+n_rows]; 102 | // compare squared distances of reference 103 | // to (other) frames in shared mem 104 | for (unsigned int i=0; i < comp_size; ++i) { 105 | float dist2=0.0f; 106 | for (unsigned int j=0; j < n_cols; ++j) { 107 | float c = smem_coords[ref_id*n_cols+j] - smem_coords[i*n_cols+j]; 108 | dist2 = fma(c, c, dist2); 109 | } 110 | // frame with min distance (i.e. nearest neighbor) 111 | if ((nh_mindist == 0) 112 | || (dist2 < nh_mindist && dist2 != 0)) { 113 | nh_mindist = dist2; 114 | nh_minndx = i+offset; 115 | } 116 | // frame with min distance and lower energy 117 | if ((nhhd_mindist == 0 && smem_fe[i] < ref_fe) 118 | || (dist2 < nhhd_mindist 119 | && smem_fe[i] < ref_fe && dist2 != 0)) { 120 | nhhd_mindist = dist2; 121 | nhhd_minndx = i+offset; 122 | } 123 | } 124 | // write results (ndx & dist) to global buffers 125 | nh_nhhd_ndx[gid] = nh_minndx; 126 | nh_nhhd_ndx[n_rows+gid] = nhhd_minndx; 127 | nh_nhhd_dist[gid] = nh_mindist; 128 | nh_nhhd_dist[n_rows+gid] = nhhd_mindist; 129 | } 130 | } 131 | 132 | __global__ void 133 | screening(unsigned int offset 134 | , float* sorted_coords 135 | , unsigned int n_rows 136 | , unsigned int n_cols 137 | , float max_dist2 138 | , unsigned int* clustering 139 | , unsigned int i_from 140 | , unsigned int i_to) { 141 | // dynamic shared mem for ref coords 142 | extern __shared__ float smem_coords[]; 143 | __shared__ unsigned int smem_states[BSIZE_SCR]; 144 | // thread dimensions 145 | unsigned int bid = blockIdx.x; 146 | unsigned int tid = threadIdx.x; 147 | unsigned int bsize = blockDim.x; 148 | unsigned int gid = bid * bsize + tid + i_from; 149 | int comp_size = min(bsize, n_rows - offset); 150 | if (tid < comp_size) { 151 | // load reference coordinates to cache 152 | for (unsigned int j=0; j < n_cols; ++j) { 153 | smem_coords[tid*n_cols+j] = sorted_coords[(tid+offset)*n_cols+j]; 154 | } 155 | // load reference state information to cache 156 | smem_states[tid] = clustering[tid+offset]; 157 | } 158 | __syncthreads(); 159 | if (gid < i_to) { 160 | for (unsigned int j=0; j < n_cols; ++j) { 161 | // load coordinates of current frame for re-use into shared memory 162 | smem_coords[(tid+bsize)*n_cols+j] = sorted_coords[gid*n_cols+j]; 163 | } 164 | // load previous state information to cache 165 | unsigned int tmp_result = clustering[gid]; 166 | // compare current frame (tid) against reference block (k) 167 | for (unsigned int k=0; k < comp_size; ++k) { 168 | unsigned int tmp_state = smem_states[k]; 169 | if (tmp_state != tmp_result) { 170 | float dist2 = 0.0f; 171 | for (unsigned int j=0; j < n_cols; ++j) { 172 | float c = smem_coords[(tid+bsize)*n_cols+j] 173 | - smem_coords[ k*n_cols+j]; 174 | dist2 = fma(c, c, dist2); 175 | } 176 | // update intermediate results 177 | if (dist2 < max_dist2) { 178 | tmp_result = min(tmp_state 179 | , tmp_result); 180 | smem_states[k] = tmp_result; 181 | } 182 | } 183 | } 184 | clustering[gid] = tmp_result; 185 | } 186 | __syncthreads(); 187 | // update reference states 188 | if (tid < comp_size) { 189 | atomicMin(&clustering[tid+offset] 190 | , smem_states[tid]); 191 | } 192 | } 193 | 194 | }}}} // end Clustering::Density::CUDA::Kernel 195 | 196 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This software package provides extensive tools for fast, robust and stable 5 | clustering of molecular dynamics trajectories. 6 | The essential functions are: 7 | - density-based geometric clustering for microstate generation 8 | - dynamic clustering based on the Most-Probable-Path algorithm (MPP) 9 | - variable dynamic coring for boundary corrections 10 | - dynamic noise assignment. 11 | 12 | Additionally, the package includes tools to efficiently filter original 13 | coordinates or order parameters based on a discrete state definition 14 | to identify representative structures and variables of clusters. 15 | 16 | 23 | Computationally demanding functions are parallelized using CUDA or OpenMP. 24 | 25 | # Documentation 26 | All options are well documented and may be viewed by 'clustering -h'. 27 | 28 | A documentation can be found on the project [page](https://moldyn.github.io/Clustering/docIndex.html), including an extensive [tutorial](https://moldyn.github.io/Clustering/docTutorial.html) which describes all technical 29 | details in performing a complete clustering run from trajectory to markov state model. 30 | 31 | The source code itself is additionally documented via doxygen. Run 'make doc' in 32 | the build directory (see below for installation intructions) to compile the source 33 | code documentation in html. Otherwise, it can be viewed [here](https://moldyn.github.io/Clustering/doxygen/index.html). 34 | 35 | 36 | # Citations 37 | The underlying methods are based on the following articles: 38 | - F. Sittel and G. Stock, *Robust Density-Based Clustering to Identify 39 | Metastable Conformational States of Proteins*, 40 | J. Chem. Theory Comput., 12, 2426; DOI: [10.1021/acs.jctc.5b01233](https://pubs.acs.org/doi/abs/10.1021/acs.jctc.5b01233) 41 | - A. Jain and G. Stock, *Hierarchical folding free energy landscape of HP35 42 | revealed by most probable path clustering*, 43 | J. of Phys. Chem. B, 118, 7750 - 7760, 2014; DOI: [10.1021/jp410398a](https://pubs.acs.org/doi/abs/10.1021/jp410398a) 44 | - D. Nagel, A. Weber, B. Lickert and G. Stock, *Dynamical coring of Markov state models*, 45 | J. Chem. Phys., 150, 094111, 2019; DOI: [10.1063/1.5081767](https://aip.scitation.org/doi/10.1063/1.5081767) 46 | 47 | We kindly ask you to cite these articles if you use this software package for 48 | published works. 49 | 50 | 51 | # Licensing 52 | This project was created by [lettis](http://www.lettis.net) and is currently maintained by [moldyn-nagel](https://github.com/moldyn-nagel). 53 | 54 | Copyright (c) 2015-2019, [Florian Sittel](http://www.lettis.net) and Daniel Nagel 55 | All rights reserved. 56 | 57 | Redistribution and use in source and binary forms, with or without 58 | modification, are permitted provided that the following conditions are met: 59 | 60 | 1. Redistributions of source code must retain the above copyright notice, 61 | this list of conditions and the following disclaimer. 62 | 63 | 2. Redistributions in binary form must reproduce the above copyright notice, 64 | this list of conditions and the following disclaimer in the documentation 65 | and/or other materials provided with the distribution. 66 | 67 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 68 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 69 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 70 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 71 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 72 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 73 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 74 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 75 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 76 | 77 | 78 | # Installation 79 | This package can be installed with conda via 80 | ``` 81 | conda install moldyn-clustering -c conda-forge 82 | ``` 83 | If conda is not available, it can be compiled as well. 84 | 85 | # Compilation 86 | ## Requirements 87 | required: 88 | - **BOOST >= 1.49** 89 | - **cmake >= 2.8** 90 | - a **recent** C++ compiler (e.g. GNU g++ >= 4.9, must 91 | support C++11 standard) 92 | 93 | optional: 94 | - **CUDA >= 9.1** 95 | - doxygen (to build the API docs) 96 | 97 | 98 | ## Quick-Start 99 | 100 | To quickly get a working (but possibly underperforming) binary 101 | 102 | - unpack the code ... 103 | ``` 104 | # tar xfz clustering_VERSION.tar.gz 105 | ``` 106 | - create a build folder inside the code directory ... 107 | ``` 108 | # cd clustering_VERSION 109 | # mkdir build 110 | ``` 111 | - change to the build directory ... 112 | ``` 113 | # cd build 114 | ``` 115 | - ... and run cmake 116 | ``` 117 | # cmake .. -DCMAKE_INSTALL_PREFIX=/my/installation/path 118 | ``` 119 | - then compile and install the package to /my/installation/path (or any other 120 | path you chose above) by invoking 121 | ``` 122 | # make 123 | # make install 124 | ``` 125 | 126 | If you want to have bash completion enabled, you need to add following line to your `.bashrc` 127 | ```bash 128 | # in file .bashrc 129 | source /my/installation/path/bash_completion_clustering.sh 130 | ``` 131 | 132 | ## Optimized Binaries and Custom Build Options 133 | 134 | ### CUDA 135 | If you have an Nvidia graphic card it can be used to significantly speed up the 136 | *clustering density* method, by setting the following **cmake-option**: 137 | -DUSE_CUDA=1 138 | 139 | ### Vectorization 140 | If you have a modern computer with vectorizing instruction sets (SSE2, SSE4_2, 141 | AVX, ...), set the following **cmake-option**: -DCPU_ACCELERATION=