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 : #ifndef __PLUMED_multicolvar_MultiColvarBase_h
23 : #define __PLUMED_multicolvar_MultiColvarBase_h
24 :
25 : #include "core/ActionAtomistic.h"
26 : #include "core/ActionWithValue.h"
27 : #include "tools/DynamicList.h"
28 : #include "tools/LinkCells.h"
29 : #include "vesselbase/StoreDataVessel.h"
30 : #include "vesselbase/ActionWithVessel.h"
31 : #include <vector>
32 :
33 : namespace PLMD {
34 : namespace multicolvar {
35 :
36 : class AtomValuePack;
37 : class CatomPack;
38 : class BridgedMultiColvarFunction;
39 : class ActionVolume;
40 :
41 : class MultiColvarBase :
42 : public ActionAtomistic,
43 : public ActionWithValue,
44 : public vesselbase::ActionWithVessel
45 : {
46 : friend class BridgedMultiColvarFunction;
47 : friend class VolumeGradientBase;
48 : friend class MultiColvarFilter;
49 : friend class AtomValuePack;
50 : private:
51 : /// Use periodic boundary conditions
52 : bool usepbc;
53 : /// The forces we are going to apply to things
54 : std::vector<double> forcesToApply;
55 : /// We use this to say that all the atoms in the third block should are in the tasks
56 : bool allthirdblockintasks;
57 : /// In certain cases we can make three atom link cells faster
58 : bool uselinkforthree;
59 : /// Number of atoms that are active on this step
60 : unsigned nactive_atoms;
61 : /// Stuff for link cells - this is used to make coordination number like variables faster
62 : LinkCells linkcells;
63 : /// Link cells for third block of atoms
64 : LinkCells threecells;
65 : /// Number of atoms that are being used for central atom position
66 : unsigned ncentral;
67 : /// Bool vector telling us which atoms are required to calculate central atom position
68 : std::vector<bool> use_for_central_atom;
69 : /// 1/number of atoms involved in central atoms
70 : double numberForCentralAtom;
71 : /// Ensures that setup is only performed once per loop
72 : bool setup_completed;
73 : /// Ensures that retrieving of atoms is only done once per calculation loop
74 : bool atomsWereRetrieved;
75 : /// Add derivatives of center of mass position
76 : void addComDerivatives( const int& ival, const unsigned& iatom, const Vector& der, multicolvar::AtomValuePack& myatoms ) const ;
77 : protected:
78 : /// This is used to keep track of what is calculated where
79 : std::vector< std::pair<unsigned,unsigned> > atom_lab;
80 : /// The vessels in these multicolvars in which the data is stored
81 : std::vector<vesselbase::StoreDataVessel*> mybasedata;
82 : /// The multicolvars from which we construct these quantities
83 : std::vector<MultiColvarBase*> mybasemulticolvars;
84 : /// This remembers where the boundaries are for the tasks. It makes link cells work fast
85 : Matrix<std::pair<unsigned,unsigned> > bookeeping;
86 : /// Function that recursively checks if filters have been used in the input to a multicolvar
87 : /// we need this to ensure that setupLinkCells is run in calculate with some actions
88 : bool filtersUsedAsInput();
89 : /// This resizes the arrays that are used for link cell update
90 : void resizeBookeepingArray( const unsigned& num1, const unsigned& num2 );
91 : /// Are we doing sums of matrix rows
92 : bool matsums;
93 : /// Using the species keyword to read in atoms
94 : bool usespecies;
95 : /// Number of atoms in each block
96 : unsigned nblock;
97 : /// This is used when turning cvcodes into atom numbers
98 : std::vector<unsigned> decoder;
99 : /// Blocks of atom numbers
100 : std::vector< std::vector<unsigned> > ablocks;
101 : /// Add a task to the list of tasks
102 : void addTaskToList( const unsigned& taskCode );
103 : /// Finish setting up the multicolvar base
104 : void setupMultiColvarBase( const std::vector<AtomNumber>& atoms );
105 : /// Add some derivatives to a particular component of a particular atom
106 : void addAtomDerivatives( const int&, const unsigned&, const Vector&, multicolvar::AtomValuePack& ) const ;
107 : /// Add derivative of the input value
108 : void mergeInputDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, const unsigned& jatom,
109 : const std::vector<double>& der, MultiValue& myder, AtomValuePack& myatoms ) const ;
110 : /// This is used to accumulate functions of the coordination sphere. Ensures weights are taken into account
111 : void accumulateSymmetryFunction( const int& ival, const unsigned& iatom, const double& val, const Vector& der, const Tensor& vir, multicolvar::AtomValuePack& myatoms ) const ;
112 : /// Set which atoms are to be used to calculate the central atom position
113 : void setAtomsForCentralAtom( const std::vector<bool>& catom_ind );
114 : /// Set the value of the cutoff for the link cells
115 : void setLinkCellCutoff( const double& lcut, double tcut=-1.0 );
116 : /// Setup the link cells and neighbour list stuff
117 : void setupActiveTaskSet( std::vector<unsigned>& active_tasks, const std::string& input_label );
118 : /// Setup link cells in order to make this calculation faster
119 : void setupLinkCells();
120 : /// Get the cutoff for the link cells
121 : double getLinkCellCutoff() const ;
122 : /// This does setup of link cell stuff that is specific to the non-use of the usespecies keyword
123 : void setupNonUseSpeciesLinkCells( const unsigned& );
124 : /// Get the separation between a pair of vectors
125 : Vector getSeparation( const Vector& vec1, const Vector& vec2 ) const ;
126 : /// This sets up the list of atoms that are involved in this colvar
127 : bool setupCurrentAtomList( const unsigned& taskCode, AtomValuePack& myatoms ) const ;
128 : /// Decode indices if there are 2 or 3 atoms involved
129 : void decodeIndexToAtoms( const unsigned& taskCode, std::vector<unsigned>& atoms ) const ;
130 : /// Read in some atoms
131 : bool parseMultiColvarAtomList(const std::string& key, const int& num, std::vector<AtomNumber>& t);
132 : /// Read in two groups of atoms and setup multicolvars to calculate
133 : void readTwoGroups( const std::string& key0, const std::string& key1, const std::string& key2, std::vector<AtomNumber>& all_atoms );
134 : /// Read in three groups of atoms
135 : void readGroupKeywords( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& key3,
136 : const bool& no_third_dim_accum, const bool& symmetric, std::vector<AtomNumber>& all_atoms );
137 : /// Read in three groups of atoms and construct CVs involving at least one
138 : void readThreeGroups( const std::string& key1, const std::string& key2, const std::string& key3,
139 : const bool& allow2, const bool& no_third_dim_accum, std::vector<AtomNumber>& all_atoms );
140 : public:
141 : explicit MultiColvarBase(const ActionOptions&);
142 264 : ~MultiColvarBase() {}
143 : static void registerKeywords( Keywords& keys );
144 : /// Turn on the derivatives
145 : virtual void turnOnDerivatives();
146 : /// Do we use pbc to calculate this quantity
147 : bool usesPbc() const ;
148 : /// Apply PBCs over a set of distance vectors
149 : void applyPbc(std::vector<Vector>& dlist, unsigned max_index=0) const;
150 : /// Is it safe to use multithreading
151 4114 : bool threadSafe() const { return !(mybasemulticolvars.size()>0); }
152 : /// Do some setup before the calculation
153 : void prepare();
154 : /// This is overwritten here in order to make sure that we do not retrieve atoms multiple times
155 : void retrieveAtoms();
156 : /// Do the calculation
157 : virtual void calculate();
158 : /// Calculate numerical derivatives
159 : virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL );
160 : /// Perform one of the tasks
161 : virtual void performTask( const unsigned&, const unsigned&, MultiValue& ) const ;
162 : /// Update the active atoms
163 : virtual void updateActiveAtoms( AtomValuePack& myatoms ) const ;
164 : /// This gets the position of an atom for the link cell setup
165 : virtual Vector getPositionOfAtomForLinkCells( const unsigned& iatom ) const ;
166 : /// Returns the position where we should assume the center is for link cell calculations
167 : virtual Vector getLinkCellPosition( const std::vector<unsigned>& atoms ) const ;
168 : /// And a virtual function which actually computes the colvar
169 : virtual double doCalculation( const unsigned& tindex, AtomValuePack& myatoms ) const ;
170 : /// Get the absolute index of the central atom
171 : virtual AtomNumber getAbsoluteIndexOfCentralAtom( const unsigned& i ) const ;
172 : /// This is replaced once we have a function to calculate the cv
173 : virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const=0;
174 : /// Apply the forces from this action
175 : virtual void apply();
176 : /// Get the number of derivatives for this action
177 : virtual unsigned getNumberOfDerivatives(); // N.B. This is replacing the virtual function in ActionWithValue
178 : /// Checks if an task is being performed at the present time
179 : virtual bool isCurrentlyActive( const unsigned& code );
180 : ///
181 : virtual CatomPack getCentralAtomPack( const unsigned& basn, const unsigned& curr );
182 : /// Get the index where the central atom is stored
183 : virtual Vector getCentralAtomPos( const unsigned& curr );
184 : /// You can use this to screen contributions that are very small so we can avoid expensive (and pointless) calculations
185 : virtual double calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& myatoms ) const ;
186 : /// Is this a density?
187 1786529 : virtual bool isDensity() const { return false; }
188 : /// Is the iatom'th stored value currently active
189 : bool storedValueIsActive( const unsigned& iatom );
190 : /// This is true if multicolvar is calculating a vector or if the multicolvar is the density
191 0 : virtual bool hasDifferentiableOrientation() const { return false; }
192 : /// This makes sure we are not calculating the director when we do LocalAverage
193 0 : virtual void doNotCalculateDirector() {}
194 : /// Ensure that derivatives are only calculated when needed
195 : bool doNotCalculateDerivatives() const ;
196 : /// Get the icolv th base multicolvar
197 : MultiColvarBase* getBaseMultiColvar( const unsigned& icolv ) const ;
198 : /// Get the number of base multicolvars
199 : unsigned getNumberOfBaseMultiColvars() const ;
200 : /// Get an input data
201 : virtual void getInputData( const unsigned& ind, const bool& normed, const multicolvar::AtomValuePack& myatoms, std::vector<double>& orient ) const ;
202 : /// Retrieve the input derivatives
203 : virtual MultiValue& getInputDerivatives( const unsigned& iatom, const bool& normed, const multicolvar::AtomValuePack& myatoms ) const ;
204 : };
205 :
206 : inline
207 450734 : bool MultiColvarBase::isCurrentlyActive( const unsigned& code ) {
208 450734 : if( setup_completed && atom_lab[code].first>0 ) {
209 17628 : unsigned mmc=atom_lab[code].first - 1;
210 17628 : return mybasedata[mmc]->storedValueIsActive( atom_lab[code].second );
211 : }
212 433106 : return true;
213 : }
214 :
215 : inline
216 156 : AtomNumber MultiColvarBase::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) const {
217 : plumed_dbg_assert( iatom<atom_lab.size() );
218 156 : if( atom_lab[iatom].first>0 ) {
219 0 : unsigned mmc=atom_lab[iatom].first - 1;
220 0 : return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second );
221 : }
222 : plumed_dbg_assert( usespecies );
223 156 : return ActionAtomistic::getAbsoluteIndex( atom_lab[getTaskCode(iatom)].second );
224 : }
225 :
226 : inline
227 16752585 : Vector MultiColvarBase::getPositionOfAtomForLinkCells( const unsigned& iatom ) const {
228 : plumed_dbg_assert( iatom<atom_lab.size() );
229 16752585 : if( atom_lab[iatom].first>0 ) {
230 2028377 : unsigned mmc=atom_lab[iatom].first - 1;
231 2028377 : return mybasemulticolvars[mmc]->getCentralAtomPos( atom_lab[iatom].second );
232 : }
233 14729701 : return ActionAtomistic::getPosition( atom_lab[iatom].second );
234 : }
235 :
236 : inline
237 191434 : Vector MultiColvarBase::getLinkCellPosition( const std::vector<unsigned>& atoms ) const {
238 191434 : return getPositionOfAtomForLinkCells( atoms[0] );
239 : }
240 :
241 : inline
242 5505989 : unsigned MultiColvarBase::getNumberOfDerivatives() {
243 5505989 : return 3*getNumberOfAtoms()+9;
244 : }
245 :
246 : inline
247 191424 : bool MultiColvarBase::usesPbc() const {
248 191424 : return usepbc;
249 : }
250 :
251 : inline
252 62755853 : bool MultiColvarBase::doNotCalculateDerivatives() const {
253 62755853 : if( !dertime ) return true;
254 62494223 : return ActionWithValue::doNotCalculateDerivatives();
255 : }
256 :
257 : inline
258 33 : unsigned MultiColvarBase::getNumberOfBaseMultiColvars() const {
259 33 : return mybasemulticolvars.size();
260 : }
261 :
262 : inline
263 23965 : MultiColvarBase* MultiColvarBase::getBaseMultiColvar( const unsigned& icolv ) const {
264 : plumed_dbg_assert( icolv<mybasemulticolvars.size() );
265 23965 : return mybasemulticolvars[icolv];
266 : }
267 :
268 :
269 : }
270 : }
271 :
272 : #endif
|