Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2013-2018 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 20 : void StoreDataVessel::registerKeywords( Keywords& keys ) {
28 20 : Vessel::registerKeywords(keys); keys.remove("LABEL");
29 20 : }
30 :
31 89 : StoreDataVessel::StoreDataVessel( const VesselOptions& da ):
32 : Vessel(da),
33 : max_lowmem_stash(3),
34 : vecsize(0),
35 89 : nspace(0)
36 : {
37 89 : ActionWithValue* myval=dynamic_cast<ActionWithValue*>( getAction() );
38 89 : if( !myval ) hasderiv=false;
39 89 : else hasderiv=!myval->doNotCalculateDerivatives();
40 89 : }
41 :
42 83 : void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ) {
43 83 : userActions.push_back( actionThatUses );
44 83 : }
45 :
46 1051 : void StoreDataVessel::resize() {
47 1051 : if( getAction()->lowmem || !getAction()->derivativesAreRequired() ) {
48 641 : nspace = 1;
49 641 : active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) );
50 : } else {
51 410 : if( getAction()->getNumberOfDerivatives()>getAction()->maxderivatives ) {
52 0 : error("not enough memory to store derivatives for action " + getAction()->getLabel() + " use LOWMEM option");
53 : }
54 410 : nspace = 1 + getAction()->maxderivatives;
55 410 : active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) );
56 : }
57 1051 : vecsize=getAction()->getNumberOfQuantities();
58 1051 : resizeBuffer( getNumberOfStoredValues()*vecsize*nspace );
59 1051 : local_buffer.resize( getNumberOfStoredValues()*vecsize*nspace );
60 1051 : }
61 :
62 70568 : void StoreDataVessel::storeValues( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer ) const {
63 70568 : unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); plumed_dbg_assert( jelem<getNumberOfStoredValues() );
64 70584 : unsigned ibuf = bufstart + jelem * vecsize * nspace;
65 512210 : for(unsigned icomp=0; icomp<vecsize; ++icomp) {
66 441603 : buffer[ibuf] += myvals.get(icomp); ibuf+=nspace;
67 : }
68 70607 : }
69 :
70 5091 : void StoreDataVessel::storeDerivatives( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
71 : plumed_dbg_assert( getAction()->derivativesAreRequired() && myelem<getAction()->getFullNumberOfTasks() );
72 5091 : unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem );
73 :
74 5116 : if( getAction()->getFullNumberOfTasks()==getNumberOfStoredValues() ) {
75 5117 : der_list[jelem]=myvals.getNumberActive();
76 5114 : unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 );
77 5116 : for(unsigned j=0; j<myvals.getNumberActive(); ++j) { der_list[kder] = myvals.getActiveIndex(j); kder++; }
78 : } else {
79 : // This ensures that active indices are gathered correctly if
80 : // we have multiple tasks contributing to a stored quantity
81 0 : unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 );
82 0 : for(unsigned j=0; j<myvals.getNumberActive(); ++j) {
83 0 : bool found=false; unsigned jder = myvals.getActiveIndex(j);
84 0 : for(unsigned k=0; k<der_list[jelem]; ++k) {
85 0 : if( der_list[kder+k]==jder ) { found=true; break; }
86 : }
87 0 : if(!found) { der_list[kder+der_list[jelem]]=jder; der_list[jelem]++; }
88 : }
89 : }
90 :
91 : // Store the values of the components and the derivatives
92 15319 : for(unsigned icomp=0; icomp<vecsize; ++icomp) {
93 10202 : unsigned ibuf = bufstart + jelem * ( vecsize*nspace ) + icomp*nspace + 1;
94 340779 : for(unsigned j=0; j<myvals.getNumberActive(); ++j) {
95 333858 : unsigned jder=myvals.getActiveIndex(j);
96 331241 : buffer[ibuf] += myvals.getDerivative( icomp, jder ); ibuf++;
97 : }
98 : }
99 5117 : }
100 :
101 1252568 : void StoreDataVessel::retrieveSequentialValue( const unsigned& jelem, const bool& normed, std::vector<double>& values ) const {
102 : plumed_dbg_assert( values.size()==vecsize );
103 1252568 : unsigned ibuf = jelem * vecsize * nspace;
104 1252568 : for(unsigned i=0; i<vecsize; ++i) { values[i]=local_buffer[ibuf]; ibuf+=nspace; }
105 1252568 : if( normed && values.size()>2 ) getAction()->normalizeVector( values );
106 1252568 : }
107 :
108 1125231 : void StoreDataVessel::retrieveValueWithIndex( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const {
109 : plumed_dbg_assert( values.size()==vecsize );
110 1125231 : unsigned jelem = getStoreIndex( myelem );
111 1125231 : retrieveSequentialValue( jelem, normed, values );
112 1125231 : }
113 :
114 325520 : double StoreDataVessel::retrieveWeightWithIndex( const unsigned& myelem ) const {
115 325520 : unsigned jelem = getStoreIndex( myelem ); unsigned ibuf = jelem * vecsize * nspace; return local_buffer[ibuf];
116 : }
117 :
118 154648 : void StoreDataVessel::retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ) {
119 : plumed_dbg_assert( myvals.getNumberOfValues()==vecsize && myvals.getNumberOfDerivatives()==getAction()->getNumberOfDerivatives() );
120 :
121 154648 : myvals.clearAll();
122 154648 : if( getAction()->lowmem ) {
123 100660 : recalculateStoredQuantity( myelem, myvals );
124 100660 : if( normed ) getAction()->normalizeVectorDerivatives( myvals );
125 : } else {
126 53988 : unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem );
127 : // Retrieve the derivatives for elements 0 and 1 - weight and norm
128 161964 : for(unsigned icomp=0; icomp<vecsize; ++icomp) {
129 107976 : unsigned ibuf = jelem * ( vecsize*nspace ) + icomp*nspace + 1;
130 107976 : unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 );
131 471426 : for(unsigned j=0; j<active_der[jelem]; ++j) {
132 363450 : myvals.addDerivative( icomp, active_der[kder], local_buffer[ibuf] );
133 363450 : kder++; ibuf++;
134 : }
135 : }
136 53988 : if( normed ) getAction()->normalizeVectorDerivatives( myvals );
137 : // Now ensure appropriate parts of list are activated
138 53988 : myvals.emptyActiveMembers();
139 53988 : unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 );
140 53988 : for(unsigned j=0; j<active_der[jelem]; ++j) { myvals.putIndexInActiveArray( active_der[kder] ); kder++; }
141 53988 : myvals.sortActiveList();
142 : }
143 154648 : }
144 :
145 70548 : void StoreDataVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
146 :
147 70548 : if( myvals.get(0)>epsilon ) {
148 70563 : storeValues( current, myvals, buffer );
149 70608 : if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivatives( current, myvals, buffer, der_list );
150 : }
151 :
152 70609 : return;
153 : }
154 :
155 1000 : void StoreDataVessel::finish( const std::vector<double>& buffer ) {
156 : // Store the buffer locally
157 1000 : for(unsigned i=0; i<local_buffer.size(); ++i) local_buffer[i]=buffer[bufstart+i];
158 1000 : }
159 :
160 :
161 631 : void StoreDataVessel::setActiveValsAndDerivatives( const std::vector<unsigned>& der_index ) {
162 631 : if( !getAction()->lowmem && getAction()->derivativesAreRequired() ) {
163 631 : for(unsigned i=0; i<der_index.size(); ++i) active_der[i]=der_index[i];
164 : }
165 631 : }
166 :
167 83 : void StoreDataVessel::resizeTemporyMultiValues( const unsigned& nvals ) {
168 83 : for(unsigned i=0; i<nvals; ++i) my_tmp_vals.push_back( MultiValue(0,0) );
169 83 : }
170 :
171 52863 : MultiValue& StoreDataVessel::getTemporyMultiValue( const unsigned& ind ) {
172 52863 : plumed_dbg_assert( ind<my_tmp_vals.size() ); return my_tmp_vals[ind];
173 : }
174 :
175 : }
176 2523 : }
|