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