Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2013-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 : #include "StoreDataVessel.h" 23 : 24 : namespace PLMD { 25 : namespace vesselbase { 26 : 27 26 : void StoreDataVessel::registerKeywords( Keywords& keys ) { 28 26 : Vessel::registerKeywords(keys); 29 26 : keys.remove("LABEL"); 30 26 : } 31 : 32 131 : StoreDataVessel::StoreDataVessel( const VesselOptions& da ): 33 : Vessel(da), 34 131 : max_lowmem_stash(3), 35 131 : vecsize(0), 36 131 : nspace(0) { 37 131 : ActionWithValue* myval=dynamic_cast<ActionWithValue*>( getAction() ); 38 131 : if( !myval ) { 39 0 : hasderiv=false; 40 : } else { 41 131 : hasderiv=!myval->doNotCalculateDerivatives(); 42 : } 43 131 : } 44 : 45 127 : void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ) { 46 127 : userActions.push_back( actionThatUses ); 47 127 : } 48 : 49 1643 : void StoreDataVessel::resize() { 50 1643 : if( getAction()->lowmem || !getAction()->derivativesAreRequired() ) { 51 1066 : nspace = 1; 52 1066 : active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); 53 : } else { 54 577 : if( getAction()->getNumberOfDerivatives()>getAction()->maxderivatives ) { 55 0 : error("not enough memory to store derivatives for action " + getAction()->getLabel() + " use LOWMEM option"); 56 : } 57 577 : nspace = 1 + getAction()->maxderivatives; 58 577 : active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) ); 59 : } 60 1643 : vecsize=getAction()->getNumberOfQuantities(); 61 : plumed_dbg_assert( vecsize>0 ); 62 1643 : resizeBuffer( getNumberOfStoredValues()*vecsize*nspace ); 63 1643 : local_buffer.resize( getNumberOfStoredValues()*vecsize*nspace ); 64 1643 : } 65 : 66 148022 : void StoreDataVessel::storeValues( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer ) const { 67 : plumed_dbg_assert( vecsize>0 ); 68 148022 : unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); 69 : plumed_dbg_assert( jelem<getNumberOfStoredValues() ); 70 148022 : unsigned ibuf = bufstart + jelem * vecsize * nspace; 71 898572 : for(unsigned icomp=0; icomp<vecsize; ++icomp) { 72 750550 : buffer[ibuf] += myvals.get(icomp); 73 750550 : ibuf+=nspace; 74 : } 75 148022 : } 76 : 77 5321 : void StoreDataVessel::storeDerivatives( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const { 78 : plumed_dbg_assert( vecsize>0 && getAction()->derivativesAreRequired() && myelem<getAction()->getFullNumberOfTasks() ); 79 5321 : unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); 80 : 81 5321 : if( getAction()->getFullNumberOfTasks()==getNumberOfStoredValues() ) { 82 5321 : der_list[jelem]=myvals.getNumberActive(); 83 5321 : unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); 84 193658 : for(unsigned j=0; j<myvals.getNumberActive(); ++j) { 85 188337 : der_list[kder] = myvals.getActiveIndex(j); 86 188337 : kder++; 87 : } 88 : } else { 89 : // This ensures that active indices are gathered correctly if 90 : // we have multiple tasks contributing to a stored quantity 91 0 : unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); 92 0 : for(unsigned j=0; j<myvals.getNumberActive(); ++j) { 93 : bool found=false; 94 : unsigned jder = myvals.getActiveIndex(j); 95 0 : for(unsigned k=0; k<der_list[jelem]; ++k) { 96 0 : if( der_list[kder+k]==jder ) { 97 : found=true; 98 : break; 99 : } 100 : } 101 0 : if(!found) { 102 0 : der_list[kder+der_list[jelem]]=jder; 103 0 : der_list[jelem]++; 104 : } 105 : } 106 : } 107 : 108 : // Store the values of the components and the derivatives 109 16071 : for(unsigned icomp=0; icomp<vecsize; ++icomp) { 110 10750 : unsigned ibuf = bufstart + jelem * ( vecsize*nspace ) + icomp*nspace + 1; 111 391636 : for(unsigned j=0; j<myvals.getNumberActive(); ++j) { 112 : unsigned jder=myvals.getActiveIndex(j); 113 380886 : buffer[ibuf] += myvals.getDerivative( icomp, jder ); 114 380886 : ibuf++; 115 : } 116 : } 117 5321 : } 118 : 119 1611191 : void StoreDataVessel::retrieveSequentialValue( const unsigned& jelem, const bool& normed, std::vector<double>& values ) const { 120 : plumed_dbg_assert( values.size()==vecsize ); 121 1611191 : unsigned ibuf = jelem * vecsize * nspace; 122 11257662 : for(unsigned i=0; i<vecsize; ++i) { 123 9646471 : values[i]=local_buffer[ibuf]; 124 9646471 : ibuf+=nspace; 125 : } 126 1611191 : if( normed && values.size()>2 ) { 127 1105384 : getAction()->normalizeVector( values ); 128 : } 129 1611191 : } 130 : 131 1149404 : void StoreDataVessel::retrieveValueWithIndex( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const { 132 : plumed_dbg_assert( values.size()==vecsize ); 133 1149404 : unsigned jelem = getStoreIndex( myelem ); 134 1149404 : retrieveSequentialValue( jelem, normed, values ); 135 1149404 : } 136 : 137 330385 : double StoreDataVessel::retrieveWeightWithIndex( const unsigned& myelem ) const { 138 : plumed_dbg_assert( vecsize>0 ); 139 330385 : unsigned jelem = getStoreIndex( myelem ); 140 330385 : unsigned ibuf = jelem * vecsize * nspace; 141 330385 : return local_buffer[ibuf]; 142 : } 143 : 144 159369 : void StoreDataVessel::retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ) { 145 : plumed_dbg_assert( myvals.getNumberOfValues()==vecsize && myvals.getNumberOfDerivatives()==getAction()->getNumberOfDerivatives() ); 146 : 147 159369 : myvals.clearAll(); 148 159369 : if( getAction()->lowmem ) { 149 103064 : recalculateStoredQuantity( myelem, myvals ); 150 103064 : if( normed ) { 151 34187 : getAction()->normalizeVectorDerivatives( myvals ); 152 : } 153 : } else { 154 56305 : unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); 155 : // Retrieve the derivatives for elements 0 and 1 - weight and norm 156 169383 : for(unsigned icomp=0; icomp<vecsize; ++icomp) { 157 113078 : unsigned ibuf = jelem * ( vecsize*nspace ) + icomp*nspace + 1; 158 113078 : unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); 159 580640 : for(unsigned j=0; j<active_der[jelem]; ++j) { 160 467562 : myvals.addDerivative( icomp, active_der[kder], local_buffer[ibuf] ); 161 467562 : kder++; 162 467562 : ibuf++; 163 : } 164 : } 165 56305 : if( normed ) { 166 0 : getAction()->normalizeVectorDerivatives( myvals ); 167 : } 168 : // Now ensure appropriate parts of list are activated 169 : myvals.emptyActiveMembers(); 170 56305 : unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); 171 280933 : for(unsigned j=0; j<active_der[jelem]; ++j) { 172 224628 : myvals.putIndexInActiveArray( active_der[kder] ); 173 224628 : kder++; 174 : } 175 : myvals.sortActiveList(); 176 : } 177 159369 : } 178 : 179 148022 : void StoreDataVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const { 180 : 181 148022 : if( myvals.get(0)>epsilon ) { 182 148022 : storeValues( current, myvals, buffer ); 183 148022 : if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) { 184 5321 : storeDerivatives( current, myvals, buffer, der_list ); 185 : } 186 : } 187 : 188 148022 : return; 189 : } 190 : 191 2542 : void StoreDataVessel::finish( const std::vector<double>& buffer ) { 192 : // Store the buffer locally 193 2186582 : for(unsigned i=0; i<local_buffer.size(); ++i) { 194 2184040 : local_buffer[i]=buffer[bufstart+i]; 195 : } 196 2542 : } 197 : 198 : 199 690 : void StoreDataVessel::setActiveValsAndDerivatives( const std::vector<unsigned>& der_index ) { 200 690 : if( !getAction()->lowmem && getAction()->derivativesAreRequired() ) { 201 228266 : for(unsigned i=0; i<der_index.size(); ++i) { 202 227576 : active_der[i]=der_index[i]; 203 : } 204 : } 205 690 : } 206 : 207 143 : void StoreDataVessel::resizeTemporyMultiValues( const unsigned& nvals ) { 208 416 : for(unsigned i=0; i<nvals; ++i) { 209 546 : my_tmp_vals.push_back( MultiValue(0,0) ); 210 : } 211 143 : } 212 : 213 56449 : MultiValue& StoreDataVessel::getTemporyMultiValue( const unsigned& ind ) { 214 : plumed_dbg_assert( ind<my_tmp_vals.size() ); 215 56449 : return my_tmp_vals[ind]; 216 : } 217 : 218 : } 219 : }