Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2011-2023 The plumed team 3 : (see the PEOPLE file at the root of the distribution for a list of names) 4 : 5 : See http://www.plumed.org for more information. 6 : 7 : This file is part of plumed, version 2. 8 : 9 : plumed is free software: you can redistribute it and/or modify 10 : it under the terms of the GNU Lesser General Public License as published by 11 : the Free Software Foundation, either version 3 of the License, or 12 : (at your option) any later version. 13 : 14 : plumed is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU Lesser General Public License for more details. 18 : 19 : You should have received a copy of the GNU Lesser General Public License 20 : along with plumed. If not, see <http://www.gnu.org/licenses/>. 21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 22 : #ifndef __PLUMED_tools_Pbc_h 23 : #define __PLUMED_tools_Pbc_h 24 : 25 : #include "Vector.h" 26 : #include "Tensor.h" 27 : #include "small_vector/small_vector.h" 28 : #include <vector> 29 : #include <cstddef> 30 : 31 : namespace PLMD { 32 : 33 : //this more or less mocks c++20 span with fixed size 34 : template < std::size_t N=3> 35 : class MemoryView { 36 : double *ptr_; 37 : public: 38 : MemoryView(double* p) :ptr_(p) {} 39 : constexpr size_t size()const {return N;} 40 : static constexpr size_t extent = N; 41 77398443 : double & operator[](size_t i) { return ptr_[i];} 42 : const double & operator[](size_t i) const { return ptr_[i];} 43 : }; 44 : 45 : namespace helpers { 46 : inline constexpr std::size_t dynamic_extent = -1; 47 : } 48 : //this more or less mocks c++23 mdspan without the fancy multi-indexed operator[] 49 : //the idea is to take an address that you know to be strided in a certain way and 50 : //make it avaiable to any interface (like using the data from a nunmpy.ndarray in 51 : //a function thought for a std::vector<PLMD::Vector> ) 52 : //the N=-1 is there for mocking the run time size from the span (where a 53 : //dynamic extent is size_t(-)) 54 : template < std::size_t N=helpers::dynamic_extent, std::size_t STRIDE=3> 55 : class mdMemoryView { 56 : double *ptr_; 57 : size_t size_; 58 : public: 59 405876 : mdMemoryView(double* p, size_t s) :ptr_(p), size_(s) {} 60 0 : size_t size()const {return size_;} 61 : static constexpr size_t extent = N; 62 : static constexpr size_t stride = STRIDE; 63 77419321 : MemoryView<STRIDE> operator[](size_t i) { return MemoryView<STRIDE>(ptr_ + i * STRIDE);} 64 : }; 65 : 66 : using VectorView = mdMemoryView<helpers::dynamic_extent, 3>; 67 : 68 : /* 69 : Tool to deal with periodic boundary conditions. 70 : 71 : This class is useful to apply periodic boundary conditions on interatomic 72 : distances. It stores privately information about reduced lattice vectors 73 : */ 74 3006 : class Pbc { 75 : /// Type of box 76 : enum {unset,orthorombic,generic} type; 77 : /// This is the maximum expected size for general boxes. 78 : /// I found this empirically by manually modifying regtest basic/rt-make-1 79 : /// Since it uses randomly generated boxes it should be correct. 80 : /// In any case, this is just used as a hint for small_vector, 81 : /// which will then switch to heap allocations if more shifts are needed 82 : static constexpr unsigned maxshiftsize=6; 83 : /// Box 84 : Tensor box; 85 : /// Inverse box 86 : Tensor invBox; 87 : /// Reduced box. 88 : /// This is a set of lattice vectors generating the same lattice 89 : /// but "minimally skewed". Useful to optimize image search. 90 : Tensor reduced; 91 : /// Inverse of the reduced box 92 : Tensor invReduced; 93 : /// List of shifts that should be attempted. 94 : /// Depending on the sign of the scaled coordinates representing 95 : /// a distance vector, a different set of shifts must be tried. 96 : gch::small_vector<Vector,maxshiftsize> shifts[2][2][2]; 97 : /// Alternative representation for orthorombic cells. 98 : /// Not really used, but could be used to optimize search in 99 : /// orthorombic cells. 100 : Vector diag,hdiag,mdiag; 101 : /// Build list of shifts. 102 : /// This is expensive, and must be called only when box is 103 : /// reset. It allows building a minimal set of shifts 104 : /// depending on the sign of the scaled coordinates representing 105 : /// a distance vector. 106 : void buildShifts(gch::small_vector<Vector,maxshiftsize> shifts[2][2][2])const; 107 : public: 108 : /// Constructor 109 : Pbc(); 110 : /// Compute modulo of (v2-v1), using or not pbc depending on bool pbc. 111 : double distance( const bool pbc, const Vector& v1, const Vector& v2 ) const; 112 : /// Computes v2-v1, using minimal image convention 113 : /// if specified, also returns the number of attempted shifts 114 : Vector distance(const Vector&, const Vector&,int*nshifts=nullptr)const; 115 : /// Apply PBC to a set of positions or distance vectors 116 : void apply(VectorView dlist, unsigned max_index=0) const; 117 : void apply(std::vector<Vector>&dlist, unsigned max_index=0) const; 118 : /// Set the lattice vectors. 119 : /// b[i][j] is the j-th component of the i-th vector 120 : void setBox(const Tensor&b); 121 : /// Returns the box 122 : const Tensor& getBox()const; 123 : /// Returns the inverse matrix of box. 124 : /// Thus: pbc.getInvBox() == inverse(pbc.getBox()). 125 : const Tensor& getInvBox()const; 126 : /// Transform a vector in real space to a vector in scaled coordinates. 127 : /// Thus:pbc.realToScaled(v) == matmul(transpose(inverse(pbc.getBox(),v))); 128 : Vector realToScaled(const Vector&)const; 129 : /// Transform a vector in scaled coordinates to a vector in real space. 130 : /// Thus:pbc.scaledToRead(v) == matmul(transpose(pbc.getBox()),v); 131 : Vector scaledToReal(const Vector&)const; 132 : /// Returns true if the box vectors are orthogonal 133 : bool isOrthorombic()const; 134 : /// Full search (for testing). 135 : /// Perform a full search on vector 136 : void fullSearch(Vector&)const; 137 : /// Returns true if box is set and non zero 138 : bool isSet()const; 139 : }; 140 : 141 : inline 142 : bool Pbc::isSet()const { 143 33420 : return type!=unset; 144 : } 145 : 146 : } 147 : 148 : #endif