Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2014-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_MultiValue_h 23 : #define __PLUMED_tools_MultiValue_h 24 : 25 : #include "Exception.h" 26 : #include "Vector.h" 27 : #include "Tensor.h" 28 : #include <vector> 29 : #include <cstddef> 30 : 31 : namespace PLMD { 32 : 33 : class MultiValue { 34 : friend class ActionWithVector; 35 : private: 36 : /// The index of the task we are currently performing 37 : std::size_t task_index, task2_index; 38 : /// Values of quantities 39 : std::vector<double> values; 40 : /// Number of derivatives per value 41 : unsigned nderivatives; 42 : /// Derivatives 43 : std::vector<double> derivatives; 44 : /// Matrix asserting which values have derivatives 45 : std::vector<bool> hasderiv; 46 : /// Tempory value 47 : double tmpval; 48 : /// Lists of active variables 49 : std::vector<unsigned> nactive, active_list; 50 : /// Tempory vector of derivatives (used for calculating quotients 51 : std::vector<double> tmpder; 52 : /// Logical to check if any derivatives were set 53 : bool atLeastOneSet; 54 : /// Are we in this for a call on vectors 55 : bool vector_call; 56 : unsigned nindices, nsplit; 57 : /// This allows us to store matrix elements 58 : unsigned nmatrix_cols; 59 : std::vector<double> matrix_row_stash; 60 : std::vector<double> matrix_force_stash; 61 : std::vector<unsigned> matrix_bookeeping; 62 : /// These are used to store the indices that have derivatives wrt to at least one 63 : /// of the elements in a matrix 64 : std::vector<unsigned> matrix_row_nderivatives; 65 : std::vector<std::vector<unsigned> > matrix_row_derivative_indices; 66 : /// This is a fudge to save on vector resizing in MultiColvar 67 : std::vector<unsigned> indices; 68 : std::vector<Vector> tmp_atoms; 69 : std::vector<std::vector<Vector> > tmp_atom_der; 70 : std::vector<Tensor> tmp_atom_virial; 71 : std::vector<std::vector<double> > tmp_vectors; 72 : public: 73 26332 : MultiValue( const std::size_t& nvals, const std::size_t& nder, const std::size_t& nmat=0, const std::size_t& maxcol=0, const std::size_t& nbook=0 ); 74 36 : void resize( const std::size_t& nvals, const std::size_t& nder, const std::size_t& nmat=0, const std::size_t& maxcol=0, const std::size_t& nbook=0 ); 75 : /// Set the task index prior to the loop 76 : void setTaskIndex( const std::size_t& tindex ); 77 : /// 78 : std::size_t getTaskIndex() const ; 79 : /// 80 : void setSecondTaskIndex( const std::size_t& tindex ); 81 : /// Get the task index 82 : std::size_t getSecondTaskIndex() const ; 83 : /// 84 : void setSplitIndex( const std::size_t& nat ); 85 : std::size_t getSplitIndex() const ; 86 : /// 87 : void setNumberOfIndices( const std::size_t& nat ); 88 : std::size_t getNumberOfIndices() const ; 89 : /// 90 : std::vector<unsigned>& getIndices(); 91 : std::vector<Vector>& getAtomVector(); 92 : /// Get the number of values in the stash 93 : unsigned getNumberOfValues() const ; 94 : /// Get the number of derivatives in the stash 95 : unsigned getNumberOfDerivatives() const ; 96 : /// Get references to some memory. These vectors allow us to 97 : /// avoid doing lots of resizing of vectors in MultiColvarTemplate 98 : std::vector<Vector>& getFirstAtomVector(); 99 : std::vector<std::vector<Vector> >& getFirstAtomDerivativeVector(); 100 : const std::vector<std::vector<Vector> >& getConstFirstAtomDerivativeVector() const ; 101 : std::vector<Tensor>& getFirstAtomVirialVector(); 102 : void resizeTemporyVector(const unsigned& n ); 103 : std::vector<double>& getTemporyVector(const unsigned& ind ); 104 : /// 105 : bool inVectorCall() const ; 106 : /// Set value numbered 107 : void setValue( const std::size_t&, const double& ); 108 : /// Add value numbered 109 : void addValue( const std::size_t&, const double& ); 110 : /// Add derivative 111 : void addDerivative( const std::size_t&, const std::size_t&, const double& ); 112 : /// Set the value of the derivative 113 : void setDerivative( const std::size_t& ival, const std::size_t& jder, const double& der); 114 : /// Return the ith value 115 : double get( const std::size_t& ) const ; 116 : /// Return a derivative value 117 : double getDerivative( const std::size_t&, const std::size_t& ) const ; 118 : /// Clear all values 119 : void clearAll(); 120 : /// Clear the derivatives 121 : void clearDerivatives( const unsigned& ); 122 : /// Clear a value 123 : void clear( const unsigned& ); 124 : /// Functions for accessing active list 125 : bool updateComplete(); 126 : void emptyActiveMembers(); 127 : void putIndexInActiveArray( const unsigned & ); 128 : void updateIndex( const unsigned& ); 129 : /// 130 : void updateIndex( const std::size_t&, const std::size_t& ); 131 : /// 132 : unsigned getActiveIndex( const std::size_t&, const std::size_t& ) const ; 133 : /// 134 : void clearActiveMembers( const std::size_t& ival ); 135 : /// 136 : unsigned getNumberActive( const std::size_t& ival ) const ; 137 : /// 138 : unsigned getActiveIndex( const unsigned& ) const ; 139 : /// Get the matrix bookeeping array 140 : const std::vector<unsigned> & getMatrixBookeeping() const ; 141 : void stashMatrixElement( const unsigned& nmat, const unsigned& rowstart, const unsigned& jcol, const double& val ); 142 : double getStashedMatrixElement( const unsigned& nmat, const unsigned& jcol ) const ; 143 : /// Get the bookeeping stuff for the derivatives wrt to rows of matrix 144 : void setNumberOfMatrixRowDerivatives( const unsigned& nmat, const unsigned& nind ); 145 : unsigned getNumberOfMatrixRowDerivatives( const unsigned& nmat ) const ; 146 : std::vector<unsigned>& getMatrixRowDerivativeIndices( const unsigned& nmat ); 147 : /// Stash the forces on the matrix 148 : void addMatrixForce( const unsigned& imat, const unsigned& jind, const double& f ); 149 : double getStashedMatrixForce( const unsigned& imat, const unsigned& jind ) const ; 150 : }; 151 : 152 : inline 153 : unsigned MultiValue::getNumberOfValues() const { 154 : return values.size(); 155 : } 156 : 157 : inline 158 : unsigned MultiValue::getNumberOfDerivatives() const { 159 163849 : return nderivatives; //derivatives.ncols(); 160 : } 161 : 162 : inline 163 : double MultiValue::get( const std::size_t& ival ) const { 164 : plumed_dbg_assert( ival<=values.size() ); 165 291523266 : return values[ival]; 166 : } 167 : 168 : inline 169 : void MultiValue::setValue( const std::size_t& ival, const double& val) { 170 : plumed_dbg_assert( ival<=values.size() ); 171 25017068 : values[ival]=val; 172 : } 173 : 174 : inline 175 : void MultiValue::addValue( const std::size_t& ival, const double& val) { 176 : plumed_dbg_assert( ival<=values.size() ); 177 187549828 : values[ival]+=val; 178 : } 179 : 180 : inline 181 1064975746 : void MultiValue::addDerivative( const std::size_t& ival, const std::size_t& jder, const double& der) { 182 1064975746 : plumed_dbg_assert( ival<=values.size() && jder<nderivatives ); atLeastOneSet=true; 183 1064975746 : hasderiv[nderivatives*ival+jder]=true; derivatives[nderivatives*ival+jder] += der; 184 1064975746 : } 185 : 186 : inline 187 : void MultiValue::setDerivative( const std::size_t& ival, const std::size_t& jder, const double& der) { 188 : plumed_dbg_assert( ival<=values.size() && jder<nderivatives ); atLeastOneSet=true; 189 : hasderiv[nderivatives*ival+jder]=true; derivatives[nderivatives*ival+jder]=der; 190 : } 191 : 192 : 193 : inline 194 : double MultiValue::getDerivative( const std::size_t& ival, const std::size_t& jder ) const { 195 : plumed_dbg_assert( ival<values.size() && jder<nderivatives ); 196 888496226 : return derivatives[nderivatives*ival+jder]; 197 : } 198 : 199 : inline 200 1951191120 : void MultiValue::updateIndex( const std::size_t& ival, const std::size_t& jder ) { 201 : plumed_dbg_assert( ival<values.size() && jder<nderivatives ); 202 : #ifdef DNDEBUG 203 : for(unsigned i=0; i<nactive[ival]; ++i) plumed_dbg_assert( active_list[nderivatives*ival+nactive[ival]]!=jder ); 204 : #endif 205 1951191120 : if( hasderiv[nderivatives*ival+jder] ) { 206 : plumed_dbg_assert( nactive[ival]<nderivatives); 207 557035706 : active_list[nderivatives*ival+nactive[ival]]=jder; 208 557035706 : nactive[ival]++; 209 : } 210 1951191120 : } 211 : 212 : inline 213 : unsigned MultiValue::getNumberActive( const std::size_t& ival ) const { 214 : plumed_dbg_assert( ival<nactive.size() ); 215 1299330336 : return nactive[ival]; 216 : } 217 : 218 : inline 219 : unsigned MultiValue::getActiveIndex( const std::size_t& ival, const std::size_t& ind ) const { 220 : plumed_dbg_assert( ind<nactive[ival] ); 221 1100607420 : return active_list[nderivatives*ival+ind]; 222 : } 223 : 224 : inline 225 : void MultiValue::setSplitIndex( const std::size_t& nat ) { 226 663993 : nsplit = nat; 227 : } 228 : 229 : inline 230 : std::size_t MultiValue::getSplitIndex() const { 231 246931070 : return nsplit; 232 : } 233 : 234 : inline 235 : void MultiValue::setNumberOfIndices( const std::size_t& nat ) { 236 405876 : nindices = nat; 237 : } 238 : 239 : inline 240 : std::size_t MultiValue::getNumberOfIndices() const { 241 28540953 : return nindices; 242 : } 243 : 244 : 245 : inline 246 : bool MultiValue::inVectorCall() const { 247 : return (matrix_row_nderivatives.size()>0 && vector_call); 248 : } 249 : 250 : inline 251 : void MultiValue::clearActiveMembers( const std::size_t& ival ) { 252 : nactive[ival]=0; 253 : } 254 : 255 : inline 256 : void MultiValue::setTaskIndex( const std::size_t& tindex ) { 257 98355224 : task_index = tindex; 258 : } 259 : 260 : inline 261 : std::size_t MultiValue::getTaskIndex() const { 262 17449808 : return task_index; 263 : } 264 : 265 : inline 266 : void MultiValue::setSecondTaskIndex( const std::size_t& tindex ) { 267 88130811 : task2_index = tindex; 268 : } 269 : 270 : inline 271 : std::size_t MultiValue::getSecondTaskIndex() const { 272 6403164 : return task2_index; 273 : } 274 : 275 : inline 276 : std::vector<unsigned>& MultiValue::getIndices() { 277 1379763 : return indices; 278 : } 279 : 280 : inline 281 : std::vector<Vector>& MultiValue::getAtomVector() { 282 405876 : return tmp_atoms; 283 : } 284 : 285 : inline 286 : std::vector<Vector>& MultiValue::getFirstAtomVector() { 287 670728 : return tmp_atoms; 288 : } 289 : 290 : inline 291 : std::vector<std::vector<Vector> >& MultiValue::getFirstAtomDerivativeVector() { 292 1076604 : return tmp_atom_der; 293 : } 294 : 295 : inline 296 : const std::vector<std::vector<Vector> >& MultiValue::getConstFirstAtomDerivativeVector() const { 297 : return tmp_atom_der; 298 : } 299 : 300 : inline 301 : std::vector<Tensor>& MultiValue::getFirstAtomVirialVector() { 302 490140 : return tmp_atom_virial; 303 : } 304 : 305 : inline 306 8598870 : void MultiValue::stashMatrixElement( const unsigned& nmat, const unsigned& rowstart, const unsigned& jcol, const double& val ) { 307 : plumed_dbg_assert( jcol<nmatrix_cols && rowstart + matrix_bookeeping[rowstart]<matrix_bookeeping.size() && nmatrix_cols*nmat + matrix_bookeeping[rowstart]<matrix_row_stash.size() ); 308 8598870 : matrix_bookeeping[rowstart]++; matrix_bookeeping[rowstart + matrix_bookeeping[rowstart]]=jcol; matrix_row_stash[ nmatrix_cols*nmat + jcol] = val; 309 8598870 : } 310 : 311 : inline 312 : double MultiValue::getStashedMatrixElement( const unsigned& nmat, const unsigned& jcol ) const { 313 : plumed_dbg_assert( nmatrix_cols*nmat + jcol<matrix_row_stash.size() ); 314 7206015 : return matrix_row_stash[ nmatrix_cols*nmat + jcol ]; 315 : } 316 : 317 : inline 318 : const std::vector<unsigned> & MultiValue::getMatrixBookeeping() const { 319 : return matrix_bookeeping; 320 : } 321 : 322 : inline 323 : void MultiValue::setNumberOfMatrixRowDerivatives( const unsigned& nmat, const unsigned& nind ) { 324 : plumed_dbg_assert( nmat<matrix_row_nderivatives.size() && nind<=matrix_row_derivative_indices[nmat].size() ); 325 12992400 : matrix_row_nderivatives[nmat]=nind; 326 : } 327 : 328 : inline 329 : unsigned MultiValue::getNumberOfMatrixRowDerivatives( const unsigned& nmat ) const { 330 108296955 : plumed_dbg_assert( nmat<matrix_row_nderivatives.size() ); return matrix_row_nderivatives[nmat]; 331 : } 332 : 333 : inline 334 : std::vector<unsigned>& MultiValue::getMatrixRowDerivativeIndices( const unsigned& nmat ) { 335 1978950 : plumed_dbg_assert( nmat<matrix_row_nderivatives.size() ); return matrix_row_derivative_indices[nmat]; 336 : } 337 : 338 : inline 339 : void MultiValue::addMatrixForce( const unsigned& imat, const unsigned& jind, const double& f ) { 340 19244157 : matrix_force_stash[imat*nderivatives + jind]+=f; 341 : } 342 : 343 : inline 344 : double MultiValue::getStashedMatrixForce( const unsigned& imat, const unsigned& jind ) const { 345 842633458 : return matrix_force_stash[imat*nderivatives + jind]; 346 : } 347 : 348 : inline 349 490140 : void MultiValue::resizeTemporyVector(const unsigned& n ) { 350 490140 : if( n>tmp_vectors.size() ) tmp_vectors.resize(n); 351 490140 : } 352 : 353 : inline 354 : std::vector<double>& MultiValue::getTemporyVector(const unsigned& ind ) { 355 : plumed_dbg_assert( ind<tmp_vectors.size() ); 356 : return tmp_vectors[ind]; 357 : } 358 : 359 : } 360 : #endif