All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ActionVolume.cpp
Go to the documentation of this file.
1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2  Copyright (c) 2013 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-code.org for more information.
6 
7  This file is part of plumed, version 2.0.
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 "core/PlumedMain.h"
23 #include "core/ActionSet.h"
24 #include "ActionVolume.h"
25 
26 namespace PLMD {
27 namespace multicolvar {
28 
33  ActionWithVessel::registerKeywords( keys );
34  keys.setComponentsIntroduction("This Action can be used to calculate the following quantities by employing the keywords listed below. "
35  "You must select which from amongst these quantities you wish to calculate - this command cannot be run "
36  "unless one of the quantities below is being calculated."
37  "These quantities can then be referenced elsewhere in the input file by using this Action's label "
38  "followed by a dot and the name of the quantity. Some amongst them can be calculated multiple times "
39  "with different parameters. In this case the quantities calculated can be referenced elsewhere in the "
40  "input by using the name of the quantity followed by a numerical identifier "
41  "e.g. <em>label</em>.less_than-1, <em>label</em>.less_than-2 etc.");
42  keys.use("MEAN"); keys.use("LESS_THAN"); keys.use("MORE_THAN");
43  keys.use("BETWEEN"); keys.use("HISTOGRAM");
44  keys.add("compulsory","ARG","the label of the action that calculates the multicolvar we are interested in");
45  keys.add("compulsory","SIGMA","the width of the function to be used for kernel density estimation");
46  keys.add("compulsory","KERNEL","gaussian","the type of kernel function to be used");
47  keys.addFlag("OUTSIDE",false,"calculate quantities for colvars that are on atoms outside the region of interest");
48  keys.use("NL_TOL");
49  keys.add("hidden","NL_STRIDE","the frequency with which the neighbor list should be updated. Between neighbour list update steps all quantities "
50  "that contributed less than TOL at the previous neighbor list update step are ignored.");
51 }
52 
54 Action(ao),
55 ActionAtomistic(ao),
56 ActionWithValue(ao),
57 ActionWithVessel(ao),
58 updateFreq(0),
59 lastUpdate(0)
60 {
61  std::string mlab; parse("ARG",mlab);
62  mycolv = plumed.getActionSet().selectWithLabel<multicolvar::MultiColvarBase*>(mlab);
63  if(!mycolv) error("action labeled " + mlab + " does not exist or is not a multicolvar");
64  std::string functype=mycolv->getName();
65  std::transform( functype.begin(), functype.end(), functype.begin(), tolower );
66  log.printf(" calculating %s inside region of insterest\n",functype.c_str() );
67 
69  // If we use numerical derivatives we have to force the base
70  // multicolvar to also use numerical derivatives
71  ActionWithValue* vv=dynamic_cast<ActionWithValue*>( mycolv );
72  plumed_assert( vv ); vv->useNumericalDerivatives();
73  }
74 
75  // Neighbor list readin
76  parse("NL_STRIDE",updateFreq);
77  if(updateFreq>0){
78  if( !mycolv->isDensity() && updateFreq%mycolv->updateFreq!=0 ){
79  error("update frequency must be a multiple of update frequency for base multicolvar");
80  }
81  log.printf(" Updating contributors every %d steps.\n",updateFreq);
82  } else {
83  log.printf(" Updating contributors every step.\n");
84  }
85 
86  parseFlag("OUTSIDE",not_in); parse("SIGMA",sigma);
88  std::string kerneltype; parse("KERNEL",kerneltype);
89  bead.setKernelType( kerneltype );
91 
92  if( mycolv->isDensity() ){
93  std::string input;
94  addVessel( "SUM", input, -1 ); // -1 here means that this value will be named getLabel()
96  } else {
98  }
99 
100  // Now set up the bridging vessel (has to be done this way for internal arrays to be resized properly)
102  // Setup a dynamic list
104 }
105 
106 void ActionVolume::requestAtoms( const std::vector<AtomNumber>& atoms ){
107  ActionAtomistic::requestAtoms(atoms); bridgeVariable=3*atoms.size();
109  tmpforces.resize( 3*atoms.size()+9 );
110 }
111 
115  ActionWithVessel::doJobsRequiredBeforeTaskList();
116 }
117 
119  bool updatetime=false;
120  if( contributorsAreUnlocked ){ updatetime=true; lockContributors(); }
121  if( updateFreq>0 && (getStep()-lastUpdate)>=updateFreq ){
122  if( !mycolv->isDensity() ){
124  for(unsigned i=0;i<mycolv->taskList.getNumberActive();++i) mycolv->colvar_atoms[i].activateAll();
126  plumed_dbg_assert( mycolv->getNumberOfVessels()==0 );
127  } else {
128  plumed_massert( mycolv->contributorsAreUnlocked, "contributors are not unlocked in base multicolvar" );
129  }
131  updatetime=true;
132  }
133  if( updatetime ) resizeLocalArrays();
134 }
135 
137  activeAtoms.clear();
138  for(unsigned i=0;i<mycolv->getNumberOfAtoms();++i) activeAtoms.addIndexToList(i);
140 }
141 
142 void ActionVolume::performTask( const unsigned& j ){
143  activeAtoms.deactivateAll(); // Currently no atoms are active so deactivate them all
144  Vector catom_pos=mycolv->retrieveCentralAtomPos();
145 
146  double weight; Vector wdf;
147  weight=calculateNumberInside( catom_pos, bead, wdf );
148  if( not_in ){ weight = 1.0 - weight; wdf *= -1.; }
149 
150  if( mycolv->isDensity() ){
151  unsigned nder=getNumberOfDerivatives();
152  setElementValue( 1, weight ); setElementValue( 0, 1.0 );
153  for(unsigned i=0;i<mycolv->atomsWithCatomDer.getNumberActive();++i){
154  unsigned n=mycolv->atomsWithCatomDer[i], nx=nder + 3*n;
159  }
160  } else {
161  // Copy derivatives of the colvar and the value of the colvar
162  double colv=mycolv->getElementValue(0); setElementValue( 0, colv );
163  for(unsigned i=0;i<mycolv->atoms_with_derivatives.getNumberActive();++i){
164  unsigned n=mycolv->atoms_with_derivatives[i], nx=3*n;
169  }
170  unsigned nvir=3*mycolv->getNumberOfAtoms();
171  for(unsigned i=0;i<9;++i){
172  addElementDerivative( nvir, mycolv->getElementDerivative(nvir) ); nvir++;
173  }
174 
175  double ww=mycolv->getElementValue(1);
176  setElementValue( 1, ww*weight );
177  unsigned nder=getNumberOfDerivatives();
178 
179  // Add derivatives of weight if we have a weight
181  for(unsigned i=0;i<mycolv->atoms_with_derivatives.getNumberActive();++i){
182  unsigned n=mycolv->atoms_with_derivatives[i], nx=nder + 3*n;
183  activeAtoms.activate(n);
184  addElementDerivative( nx+0, weight*mycolv->getElementDerivative(nx+0) );
185  addElementDerivative( nx+1, weight*mycolv->getElementDerivative(nx+1) );
186  addElementDerivative( nx+2, weight*mycolv->getElementDerivative(nx+2) );
187  }
188  unsigned nwvir=3*mycolv->getNumberOfAtoms();
189  for(unsigned i=0;i<9;++i){
190  addElementDerivative( nwvir, mycolv->getElementDerivative(nwvir) ); nwvir++;
191  }
192  }
193 
194  // Add derivatives of central atoms
195  for(unsigned i=0;i<mycolv->atomsWithCatomDer.getNumberActive();++i){
196  unsigned n=mycolv->atomsWithCatomDer[i], nx=nder+3*n;
197  activeAtoms.activate(n);
198  addElementDerivative( nx+0, ww*mycolv->getCentralAtomDerivative(n, 0, wdf ) );
199  addElementDerivative( nx+1, ww*mycolv->getCentralAtomDerivative(n, 1, wdf ) );
200  addElementDerivative( nx+2, ww*mycolv->getCentralAtomDerivative(n, 2, wdf ) );
201  }
202  }
204 }
205 
206 void ActionVolume::mergeDerivatives( const unsigned& ider, const double& df ){
207  unsigned vstart=getNumberOfDerivatives()*ider;
208  // Merge atom derivatives
209  for(unsigned i=0;i<activeAtoms.getNumberActive();++i){
210  unsigned iatom=3*activeAtoms[i];
211  accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) ); iatom++;
212  accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) ); iatom++;
213  accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) );
214  }
215  // Merge virial derivatives
216  unsigned nvir=3*mycolv->getNumberOfAtoms();
217  for(unsigned j=0;j<9;++j){
218  accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++;
219  }
220  // Merge local atom derivatives
221  for(unsigned j=0;j<getNumberOfAtoms();++j){
222  accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++;
223  accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++;
224  accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++;
225  }
226  plumed_dbg_assert( nvir==getNumberOfDerivatives() );
227 }
228 
229 void ActionVolume::clearDerivativesAfterTask( const unsigned& ider ){
230  unsigned vstart=getNumberOfDerivatives()*ider;
231  // Clear atom derivatives
232  for(unsigned i=0;i<activeAtoms.getNumberActive();++i){
233  unsigned iatom=vstart+3*activeAtoms[i];
234  setElementDerivative( iatom, 0.0 ); iatom++;
235  setElementDerivative( iatom, 0.0 ); iatom++;
236  setElementDerivative( iatom, 0.0 );
237  }
238  // Clear virial contribution
239  unsigned nvir=vstart+3*mycolv->getNumberOfAtoms();
240  for(unsigned j=0;j<9;++j){
241  setElementDerivative( nvir, 0.0 ); nvir++;
242  }
243  // Clear derivatives of local atoms
244  for(unsigned j=0;j<getNumberOfAtoms();++j){
245  setElementDerivative( nvir, 0.0 ); nvir++;
246  setElementDerivative( nvir, 0.0 ); nvir++;
247  setElementDerivative( nvir, 0.0 ); nvir++;
248  }
249  plumed_dbg_assert( (nvir-vstart)==getNumberOfDerivatives() );
250 }
251 
254 }
255 
257  return mycolv->isPeriodic();
258 }
259 
261  plumed_merror("This should never be called");
262 }
263 
264 void ActionVolume::applyBridgeForces( const std::vector<double>& bb ){
265  plumed_dbg_assert( bb.size()==tmpforces.size()-9 );
266  // Forces on local atoms
267  for(unsigned i=0;i<bb.size();++i) tmpforces[i]=bb[i];
268  // Virial contribution is zero
269  for(unsigned i=bb.size();i<bb.size()+9;++i) tmpforces[i]=0.0;
271 }
272 
273 }
274 }
BridgeVessel * addBridgingVessel(ActionWithVessel *tome)
Add a bridging vessel to the list of vessels.
void setComponentsIntroduction(const std::string &instr)
Set the text that introduces how the components for this action are introduced.
Definition: Keywords.cpp:561
void doJobsRequiredBeforeTaskList()
Do jobs required before tasks are undertaken.
static void registerKeywords(Keywords &keys)
Register all the relevant keywords for the action.
void parseFlag(const std::string &key, bool &t)
Parse one keyword as boolean flag.
Definition: Action.cpp:104
Log & log
Reference to the log stream.
Definition: Action.h:93
static void registerKeywords(Keywords &keys)
double sigma
The value of sigma.
Definition: ActionVolume.h:51
void applyBridgeForces(const std::vector< double > &bb)
Forces here are applied through the bridge.
Class implementing fixed size vectors of doubles.
Definition: Vector.h:74
void setKernelType(const std::string &ktype)
void setElementDerivative(const unsigned &, const double &)
Set the derivative of the jth element wrt to a numbered element.
void addElementDerivative(const unsigned &, const double &)
Add some derivative of the quantity in the sum wrt to a numbered element.
DynamicList< unsigned > activeAtoms
Fast merging of derivatives (automatic skips of zero contributions)
Definition: ActionVolume.h:66
void error(const std::string &msg) const
Crash calculation and print documentation.
Definition: Action.cpp:195
double getElementDerivative(const unsigned &) const
Retrieve the derivative of the quantity in the sum wrt to a numbered element.
void add(const std::string &t, const std::string &k, const std::string &d)
Add a new keyword of type t with name k and description d.
Definition: Keywords.cpp:167
void addVessel(const std::string &name, const std::string &input, const int numlab=0, const std::string thislab="")
Add a vessel to the list of vessels.
void activate(const unsigned ii)
Make something active.
Definition: DynamicList.h:263
void calculateNumericalDerivatives(ActionWithValue *a=NULL)
We need our own calculate numerical derivatives here.
void prepare()
Jobs to be done when the action is activated.
void updateActiveMembers()
Get the list of active members.
Definition: DynamicList.h:285
unsigned bridgeVariable
This is used for numerical derivatives of bridge variables.
void const char const char int * n
Definition: Matrix.h:42
bool not_in
Are we interested in the area outside the colvar.
Definition: ActionVolume.h:53
void mergeDerivatives(const unsigned &ider, const double &df)
These routines replace the virtual routines in ActionWithVessel for code optimization.
void readVesselKeywords()
Complete the setup of this object (this routine must be called after construction of ActionWithValue)...
bool weightHasDerivatives
Does the weight have derivatives.
void addDependency(Action *)
Specify that this Action depends on another one.
Definition: Action.cpp:123
Used to create a PLMD::Action that has some scalar or vectorial output that may or may not have some ...
DynamicList< unsigned > atomsWithCatomDer
void parse(const std::string &key, T &t)
Parse one keyword as generic type.
Definition: Action.h:273
unsigned getNumberOfDerivatives()
Get the number of derivatives for this action.
Definition: ActionVolume.h:160
This class holds the keywords and their documentation.
Definition: Keywords.h:36
void clear()
Clear the list.
Definition: DynamicList.h:214
bool isPeriodic()
Is the output quantity periodic.
std::vector< DynamicList< unsigned > > colvar_atoms
The lists of the atoms involved in each of the individual colvars note these refer to the atoms in al...
This class is used to bring the relevant information to the Action constructor.
Definition: Action.h:41
virtual bool isDensity()
Is this a density?
Action used to create objects that access the positions of the atoms from the MD code.
void addIndexToList(const T &ii)
Add something to the active list.
Definition: DynamicList.h:235
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
Definition: OFile.cpp:82
void setElementValue(const unsigned &, const double &)
Set the value of the element.
const std::string & getName() const
Returns the name.
Definition: Action.h:268
Base class for all the input Actions.
Definition: Action.h:60
static void registerKeywords(Keywords &keys)
Register all the relevant keywords for the action.
Definition: Action.cpp:49
ActionVolume(const ActionOptions &)
virtual void unlockContributors()
Used to make sure we are calculating everything during neighbor list update step. ...
void accumulateDerivative(const unsigned &ider, const double &df)
This is used to accumulate the derivatives when we merge using chainRuleForElementDerivatives.
void deactivate_task()
Routines that have to be defined so as not to have problems with virtual methods. ...
void use(const std::string &k)
Use one of the reserved keywords.
Definition: Keywords.cpp:154
DynamicList< unsigned > taskList
The list of tasks we have to perform.
Vector retrieveCentralAtomPos()
Retrieve the position of the central atom.
MultiColvarBase * mycolv
The action that is calculating the colvars of interest.
Definition: ActionVolume.h:59
void resizeLocalArrays()
This sets up array above.
bool checkNumericalDerivatives() const
Check if numerical derivatives should be used.
unsigned getNumberOfVessels() const
Get the number of vessels.
int updateFreq
Everything for controlling the updating of neighbor lists.
Definition: ActionVolume.h:63
void performTask(const unsigned &i)
This calculates all the vessels and is called from within a bridge vessel.
long int getStep() const
Return the present timestep.
Definition: Action.cpp:169
HistogramBead bead
The bead for the histogram.
Definition: ActionVolume.h:57
virtual double calculateNumberInside(const Vector &cpos, HistogramBead &bead, Vector &derivatives)=0
virtual bool isPeriodic()=0
Are the base quantities periodic.
void clearDerivativesAfterTask(const unsigned &ider)
virtual void clearDerivatives()
Clear the derivatives of values wrt parameters.
void requestAtoms(const std::vector< AtomNumber > &a)
Request an array of atoms.
Main plumed object.
Definition: Plumed.h:201
void useNumericalDerivatives()
This forces the class to use numerical derivatives.
DynamicList< unsigned > atoms_with_derivatives
A dynamic list containing those atoms with derivatives.
void completeNumericalDerivatives()
Calculate numerical derivatives.
void setForcesOnAtoms(const std::vector< double > &forcesToApply, unsigned ind=0)
Add the forces to the atoms.
unsigned getNumberOfAtoms() const
Get number of available atoms.
static void registerKeywords(Keywords &keys)
vesselbase::BridgeVessel * myBridgeVessel
The vessel that bridges.
Definition: ActionVolume.h:61
void const char const char int double * a
Definition: Matrix.h:42
double getCentralAtomDerivative(const unsigned &iatom, const unsigned jcomp, const Vector &df) const
Retrieve derivative of central atom position wrt jcomp'th component of position of iatom'th atom...
void deactivateAll()
Make everything in the list inactive.
Definition: DynamicList.h:255
bool contributorsAreUnlocked
The terms in the series are locked.
std::vector< double > tmpforces
This is used to store forces temporarily in apply.
Definition: ActionVolume.h:68
void resizeFunctions()
Resize all the functions when the number of derivatives change.
void activateAll()
Make everything in the list active.
Definition: DynamicList.h:270
int updateFreq
Everything for controlling the updating of neighbor lists.
unsigned getNumberActive() const
Return the number of elements that are currently active.
Definition: DynamicList.h:230
void addFlag(const std::string &k, const bool def, const std::string &d)
Add a falg with name k that is by default on if def is true and off if def is false. d should provide a description of the flag.
Definition: Keywords.cpp:193
double getElementValue(const unsigned &ival) const
Get the value of this element.
void requestAtoms(const std::vector< AtomNumber > &atoms)
Request the atoms.