1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2013-2021 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
registerKeywords(Keywords & keys)27 void StoreDataVessel::registerKeywords( Keywords& keys ) {
28 Vessel::registerKeywords(keys); keys.remove("LABEL");
29 }
30
StoreDataVessel(const VesselOptions & da)31 StoreDataVessel::StoreDataVessel( const VesselOptions& da ):
32 Vessel(da),
33 max_lowmem_stash(3),
34 vecsize(0),
35 nspace(0)
36 {
37 ActionWithValue* myval=dynamic_cast<ActionWithValue*>( getAction() );
38 if( !myval ) hasderiv=false;
39 else hasderiv=!myval->doNotCalculateDerivatives();
40 }
41
addActionThatUses(ActionWithVessel * actionThatUses)42 void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ) {
43 userActions.push_back( actionThatUses );
44 }
45
resize()46 void StoreDataVessel::resize() {
47 if( getAction()->lowmem || !getAction()->derivativesAreRequired() ) {
48 nspace = 1;
49 active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) );
50 } else {
51 if( getAction()->getNumberOfDerivatives()>getAction()->maxderivatives ) {
52 error("not enough memory to store derivatives for action " + getAction()->getLabel() + " use LOWMEM option");
53 }
54 nspace = 1 + getAction()->maxderivatives;
55 active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) );
56 }
57 vecsize=getAction()->getNumberOfQuantities();
58 plumed_dbg_assert( vecsize>0 );
59 resizeBuffer( getNumberOfStoredValues()*vecsize*nspace );
60 local_buffer.resize( getNumberOfStoredValues()*vecsize*nspace );
61 }
62
storeValues(const unsigned & myelem,MultiValue & myvals,std::vector<double> & buffer) const63 void StoreDataVessel::storeValues( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer ) const {
64 plumed_dbg_assert( vecsize>0 );
65 unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); plumed_dbg_assert( jelem<getNumberOfStoredValues() );
66 unsigned ibuf = bufstart + jelem * vecsize * nspace;
67 for(unsigned icomp=0; icomp<vecsize; ++icomp) {
68 buffer[ibuf] += myvals.get(icomp); ibuf+=nspace;
69 }
70 }
71
storeDerivatives(const unsigned & myelem,MultiValue & myvals,std::vector<double> & buffer,std::vector<unsigned> & der_list) const72 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 unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem );
75
76 if( getAction()->getFullNumberOfTasks()==getNumberOfStoredValues() ) {
77 der_list[jelem]=myvals.getNumberActive();
78 unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 );
79 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 unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 );
84 for(unsigned j=0; j<myvals.getNumberActive(); ++j) {
85 bool found=false; unsigned jder = myvals.getActiveIndex(j);
86 for(unsigned k=0; k<der_list[jelem]; ++k) {
87 if( der_list[kder+k]==jder ) { found=true; break; }
88 }
89 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 for(unsigned icomp=0; icomp<vecsize; ++icomp) {
95 unsigned ibuf = bufstart + jelem * ( vecsize*nspace ) + icomp*nspace + 1;
96 for(unsigned j=0; j<myvals.getNumberActive(); ++j) {
97 unsigned jder=myvals.getActiveIndex(j);
98 buffer[ibuf] += myvals.getDerivative( icomp, jder ); ibuf++;
99 }
100 }
101 }
102
retrieveSequentialValue(const unsigned & jelem,const bool & normed,std::vector<double> & values) const103 void StoreDataVessel::retrieveSequentialValue( const unsigned& jelem, const bool& normed, std::vector<double>& values ) const {
104 plumed_dbg_assert( values.size()==vecsize );
105 unsigned ibuf = jelem * vecsize * nspace;
106 for(unsigned i=0; i<vecsize; ++i) { values[i]=local_buffer[ibuf]; ibuf+=nspace; }
107 if( normed && values.size()>2 ) getAction()->normalizeVector( values );
108 }
109
retrieveValueWithIndex(const unsigned & myelem,const bool & normed,std::vector<double> & values) const110 void StoreDataVessel::retrieveValueWithIndex( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const {
111 plumed_dbg_assert( values.size()==vecsize );
112 unsigned jelem = getStoreIndex( myelem );
113 retrieveSequentialValue( jelem, normed, values );
114 }
115
retrieveWeightWithIndex(const unsigned & myelem) const116 double StoreDataVessel::retrieveWeightWithIndex( const unsigned& myelem ) const {
117 plumed_dbg_assert( vecsize>0 );
118 unsigned jelem = getStoreIndex( myelem ); unsigned ibuf = jelem * vecsize * nspace; return local_buffer[ibuf];
119 }
120
retrieveDerivatives(const unsigned & myelem,const bool & normed,MultiValue & myvals)121 void StoreDataVessel::retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ) {
122 plumed_dbg_assert( myvals.getNumberOfValues()==vecsize && myvals.getNumberOfDerivatives()==getAction()->getNumberOfDerivatives() );
123
124 myvals.clearAll();
125 if( getAction()->lowmem ) {
126 recalculateStoredQuantity( myelem, myvals );
127 if( normed ) getAction()->normalizeVectorDerivatives( myvals );
128 } else {
129 unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem );
130 // Retrieve the derivatives for elements 0 and 1 - weight and norm
131 for(unsigned icomp=0; icomp<vecsize; ++icomp) {
132 unsigned ibuf = jelem * ( vecsize*nspace ) + icomp*nspace + 1;
133 unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 );
134 for(unsigned j=0; j<active_der[jelem]; ++j) {
135 myvals.addDerivative( icomp, active_der[kder], local_buffer[ibuf] );
136 kder++; ibuf++;
137 }
138 }
139 if( normed ) getAction()->normalizeVectorDerivatives( myvals );
140 // Now ensure appropriate parts of list are activated
141 myvals.emptyActiveMembers();
142 unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 );
143 for(unsigned j=0; j<active_der[jelem]; ++j) { myvals.putIndexInActiveArray( active_der[kder] ); kder++; }
144 myvals.sortActiveList();
145 }
146 }
147
calculate(const unsigned & current,MultiValue & myvals,std::vector<double> & buffer,std::vector<unsigned> & der_list) const148 void StoreDataVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
149
150 if( myvals.get(0)>epsilon ) {
151 storeValues( current, myvals, buffer );
152 if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivatives( current, myvals, buffer, der_list );
153 }
154
155 return;
156 }
157
finish(const std::vector<double> & buffer)158 void StoreDataVessel::finish( const std::vector<double>& buffer ) {
159 // Store the buffer locally
160 for(unsigned i=0; i<local_buffer.size(); ++i) local_buffer[i]=buffer[bufstart+i];
161 }
162
163
setActiveValsAndDerivatives(const std::vector<unsigned> & der_index)164 void StoreDataVessel::setActiveValsAndDerivatives( const std::vector<unsigned>& der_index ) {
165 if( !getAction()->lowmem && getAction()->derivativesAreRequired() ) {
166 for(unsigned i=0; i<der_index.size(); ++i) active_der[i]=der_index[i];
167 }
168 }
169
resizeTemporyMultiValues(const unsigned & nvals)170 void StoreDataVessel::resizeTemporyMultiValues( const unsigned& nvals ) {
171 for(unsigned i=0; i<nvals; ++i) my_tmp_vals.push_back( MultiValue(0,0) );
172 }
173
getTemporyMultiValue(const unsigned & ind)174 MultiValue& StoreDataVessel::getTemporyMultiValue( const unsigned& ind ) {
175 plumed_dbg_assert( ind<my_tmp_vals.size() ); return my_tmp_vals[ind];
176 }
177
178 }
179 }
180