Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2016-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 "ActionWithAveraging.h"
23 : #include "core/PlumedMain.h"
24 : #include "core/ActionSet.h"
25 :
26 : namespace PLMD {
27 : namespace vesselbase {
28 :
29 54 : void ActionWithAveraging::registerKeywords( Keywords& keys ) {
30 54 : Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys );
31 54 : ActionWithArguments::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionWithVessel::registerKeywords( keys );
32 54 : keys.add("compulsory","STRIDE","1","the frequency with which the data should be collected and added to the quantity being averaged");
33 : keys.add("compulsory","CLEAR","0","the frequency with which to clear all the accumulated data. The default value "
34 54 : "of 0 implies that all the data will be used and that the grid will never be cleared");
35 54 : keys.add("optional","LOGWEIGHTS","list of actions that calculates log weights that should be used to weight configurations when calculating averages");
36 54 : keys.addFlag("UNORMALIZED",false,"output the unaveraged quantity/quantities."); keys.remove("NUMERICAL_DERIVATIVES");
37 54 : }
38 :
39 43 : ActionWithAveraging::ActionWithAveraging( const ActionOptions& ao ):
40 : Action(ao),
41 : ActionPilot(ao),
42 : ActionAtomistic(ao),
43 : ActionWithArguments(ao),
44 : ActionWithValue(ao),
45 : ActionWithVessel(ao),
46 : lweight(0),cweight(0),
47 : myaverage(NULL),
48 : useRunAllTasks(false),
49 43 : clearstride(0)
50 : {
51 43 : if( keywords.exists("CLEAR") ) {
52 37 : parse("CLEAR",clearstride);
53 37 : if( clearstride>0 ) {
54 8 : if( clearstride%getStride()!=0 ) error("CLEAR parameter must be a multiple of STRIDE");
55 8 : log.printf(" clearing grid every %u steps \n",clearstride);
56 : }
57 : }
58 43 : if( keywords.exists("LOGWEIGHTS") ) {
59 38 : std::vector<std::string> wwstr; parseVector("LOGWEIGHTS",wwstr);
60 38 : if( wwstr.size()>0 ) log.printf(" reweighting using weights from ");
61 76 : std::vector<Value*> arg( getArguments() );
62 44 : for(unsigned i=0; i<wwstr.size(); ++i) {
63 6 : ActionWithValue* val = plumed.getActionSet().selectWithLabel<ActionWithValue*>(wwstr[i]);
64 6 : if( !val ) error("could not find value named");
65 6 : weights.push_back( val->copyOutput(val->getLabel()) );
66 6 : arg.push_back( val->copyOutput(val->getLabel()) );
67 6 : log.printf("%s ",wwstr[i].c_str() );
68 : }
69 38 : if( wwstr.size()>0 ) log.printf("\n");
70 32 : else log.printf(" weights are all equal to one\n");
71 76 : requestArguments( arg );
72 : }
73 43 : if( keywords.exists("UNORMALIZED") ) parseFlag("UNORMALIZED",unormalised);
74 43 : }
75 :
76 38 : void ActionWithAveraging::setAveragingAction( AveragingVessel* av_vessel, const bool& usetasks ) {
77 38 : myaverage=av_vessel; addVessel( myaverage );
78 38 : useRunAllTasks=usetasks; resizeFunctions();
79 38 : }
80 :
81 1428 : void ActionWithAveraging::lockRequests() {
82 1428 : ActionAtomistic::lockRequests();
83 1428 : ActionWithArguments::lockRequests();
84 1428 : }
85 :
86 1428 : void ActionWithAveraging::unlockRequests() {
87 1428 : ActionAtomistic::unlockRequests();
88 1428 : ActionWithArguments::unlockRequests();
89 1428 : }
90 :
91 0 : void ActionWithAveraging::calculateNumericalDerivatives(PLMD::ActionWithValue*) {
92 0 : error("not possible to compute numerical derivatives for this action");
93 0 : }
94 :
95 1429 : void ActionWithAveraging::update() {
96 2858 : if( getStep()==0 || !onStep() ) return;
97 : // Clear if it is time to reset
98 1389 : if( myaverage ) {
99 95 : if( myaverage->wasreset() ) clearAverage();
100 : }
101 : // Calculate the weight for all reweighting
102 1389 : if ( weights.size()>0 ) {
103 207 : double sum=0; for(unsigned i=0; i<weights.size(); ++i) sum+=weights[i]->get();
104 207 : lweight=sum; cweight = exp( sum );
105 : } else {
106 1182 : lweight=0; cweight=1.0;
107 : }
108 : // Prepare to do the averaging
109 1389 : prepareForAveraging();
110 : // Run all the tasks (if required
111 1389 : if( useRunAllTasks ) runAllTasks();
112 : // This the averaging if it is not done using task list
113 1321 : else performOperations( true );
114 : // Update the norm
115 1389 : if( myaverage ) myaverage->setNorm( cweight + myaverage->getNorm() );
116 : // Finish the averaging
117 1389 : finishAveraging();
118 : // By resetting here we are ensuring that the grid will be cleared at the start of the next step
119 1389 : if( myaverage ) {
120 95 : if( getStride()==0 || (clearstride>0 && getStep()%clearstride==0) ) myaverage->reset();
121 : }
122 : }
123 :
124 51 : void ActionWithAveraging::clearAverage() { plumed_assert( myaverage->wasreset() ); myaverage->clear(); }
125 :
126 0 : void ActionWithAveraging::performOperations( const bool& from_update ) { plumed_error(); }
127 :
128 :
129 : }
130 2523 : }
|