Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2012-2023 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_vesselbase_ActionWithVessel_h 23 : #define __PLUMED_vesselbase_ActionWithVessel_h 24 : 25 : #include "core/ActionWithValue.h" 26 : #include "core/ActionAtomistic.h" 27 : #include "tools/Exception.h" 28 : #include "tools/DynamicList.h" 29 : #include "tools/MultiValue.h" 30 : #include <vector> 31 : #include "tools/ForwardDecl.h" 32 : 33 : namespace PLMD { 34 : class Value; 35 : class Stopwatch; 36 : 37 : namespace vesselbase { 38 : 39 : class Vessel; 40 : class BridgeVessel; 41 : class StoreDataVessel; 42 : 43 : /** 44 : \ingroup MULTIINHERIT 45 : This is used to create PLMD::Action objects that are computed by calculating the same function multiple 46 : times. This is used in PLMD::MultiColvar. 47 : */ 48 : 49 : class ActionWithVessel : public virtual Action { 50 : friend class Vessel; 51 : friend class ShortcutVessel; 52 : friend class FunctionVessel; 53 : friend class StoreDataVessel; 54 : friend class BridgeVessel; 55 : friend class ActionWithInputVessel; 56 : friend class OrderingVessel; 57 : private: 58 : /// Do all calculations in serial 59 : bool serial; 60 : /// Lower memory requirements 61 : bool lowmem; 62 : /// Are we skipping the calculation of the derivatives 63 : bool noderiv; 64 : /// This tells plumed that this is used in a bridge 65 : bool actionIsBridged; 66 : /// The maximum number of derivatives we can use before we need to invoke lowmem 67 : unsigned maxderivatives; 68 : /// The tolerance on the accumulators 69 : double tolerance; 70 : /// Tolerance for quantities being put in neighbor lists 71 : double nl_tolerance; 72 : /// Pointers to the functions we are using on each value 73 : std::vector<std::unique_ptr<Vessel>> functions; 74 : /// Tempory storage for forces 75 : std::vector<double> tmpforces; 76 : /// Ths full list of tasks we have to perform 77 : std::vector<unsigned> fullTaskList; 78 : /// The current number of active tasks 79 : unsigned nactive_tasks; 80 : /// The indices of the tasks in the full list of tasks 81 : std::vector<unsigned> indexOfTaskInFullList; 82 : /// The list of currently active tasks 83 : std::vector<unsigned> partialTaskList; 84 : /// The list of atoms involved in derivatives (we keep a copy here to avoid resizing) 85 : std::vector<unsigned> der_list; 86 : /// The buffer that we use (we keep a copy here to avoid resizing) 87 : std::vector<double> buffer; 88 : /// Do we want to output information on the timings of different parts of the calculation 89 : bool timers; 90 : ForwardDecl<Stopwatch> stopwatch_fwd; 91 : /// The stopwatch that times the different parts of the calculation 92 : Stopwatch& stopwatch=*stopwatch_fwd; 93 : /// These are used to minmise computational expense in complex functions 94 : bool dertime_can_be_off; 95 : protected: 96 : /// This is also used to minimise computational expense in complex functions 97 : bool dertime; 98 : /// The terms in the series are locked 99 : bool contributorsAreUnlocked; 100 : /// Does the weight have derivatives 101 : bool weightHasDerivatives; 102 : /// This is used for numerical derivatives of bridge variables 103 : unsigned bridgeVariable; 104 : /// A pointer to the object that stores data 105 : StoreDataVessel* mydata; 106 : /// This list is used to update the neighbor list 107 : std::vector<unsigned> taskFlags; 108 : /// Add a vessel to the list of vessels 109 : void addVessel( const std::string& name, const std::string& input, const int numlab=0 ); 110 : void addVessel( std::unique_ptr<Vessel> vv ); 111 : /// Add a bridging vessel to the list of vessels 112 : BridgeVessel* addBridgingVessel( ActionWithVessel* tome ); 113 : /// Complete the setup of this object (this routine must be called after construction of ActionWithValue) 114 : void readVesselKeywords(); 115 : /// Turn on the derivatives in the vessel 116 : void needsDerivatives(); 117 : /// Return the value of the tolerance 118 : double getTolerance() const ; 119 : /// Return the value for the neighbor list tolerance 120 : double getNLTolerance() const ; 121 : /// Calculate the values of all the vessels 122 : void runAllTasks(); 123 : /// Resize all the functions when the number of derivatives change 124 : void resizeFunctions(); 125 : /// This loops over all the vessels calculating them and also 126 : /// sets all the element derivatives equal to zero 127 : void calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ); 128 : /// Retrieve the forces from all the vessels (used in apply) 129 : bool getForcesFromVessels( std::vector<double>& forcesToApply ); 130 : /// Is the calculation being done in serial 131 : bool serialCalculation() const; 132 : /// Are we using low memory 133 : bool usingLowMem() const ; 134 : /// Set that we are using low memory 135 : void setLowMemOption(const bool& ); 136 : /// Deactivate all the tasks in the task list 137 : void deactivateAllTasks(); 138 : /// Get the size of the buffer 139 : unsigned getSizeOfBuffer( unsigned& bufsize ); 140 : /// Add a task to the full list 141 : void addTaskToList( const unsigned& taskCode ); 142 : public: 143 : static void registerKeywords(Keywords& keys); 144 : explicit ActionWithVessel(const ActionOptions&ao); 145 : ~ActionWithVessel(); 146 : void lockContributors(); 147 : /// Get the number of tasks that are currently active 148 : unsigned getCurrentNumberOfActiveTasks() const ; 149 : /// Check whether or not a particular task is currently active 150 : bool taskIsCurrentlyActive( const unsigned& index ) const ; 151 : /// Are derivatives required for this quantity 152 : bool derivativesAreRequired() const ; 153 : /// Is this action thread safe 154 5214 : virtual bool threadSafe() const { return true; } 155 : /// Finish running all the calculations 156 : virtual void finishComputations( const std::vector<double>& buffer ); 157 : /// Are the base quantities periodic 158 : virtual bool isPeriodic()=0; 159 : /// What are the domains of the base quantities 160 : virtual void retrieveDomain( std::string& min, std::string& max); 161 : /// Get the number of derivatives for final calculated quantity 162 : virtual unsigned getNumberOfDerivatives()=0; 163 : /// Get the number of quantities that are calculated during each task 164 : virtual unsigned getNumberOfQuantities() const ; 165 : /// Get the number of vessels 166 : unsigned getNumberOfVessels() const; 167 : /// Get a pointer to the ith vessel 168 : Vessel* getPntrToVessel( const unsigned& i ); 169 : /// Do any jobs that are required before the task list is undertaken 170 : virtual void doJobsRequiredBeforeTaskList(); 171 : /// Get the full size of the taskList dynamic list 172 : unsigned getFullNumberOfTasks() const ; 173 : /// Get the position of the ith active task in the full list 174 : unsigned getPositionInFullTaskList( const unsigned& ii ) const ; 175 : /// Get the code for the ii th task in the list 176 : unsigned getTaskCode( const unsigned& ii ) const ; 177 : /// Get the ith of the currently active tasks 178 : unsigned getActiveTask( const unsigned& ii ) const ; 179 : /// Calculate one of the functions in the distribution 180 : virtual void performTask( const unsigned&, const unsigned&, MultiValue& ) const=0; 181 : /// Do the task if we have a bridge 182 : virtual void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const; 183 : /// Ensure that data required in other vessels is stored 184 : StoreDataVessel* buildDataStashes( ActionWithVessel* actionThatUses ); 185 : /// Apply forces from bridge vessel - this is rarely used - currently only in ActionVolume 186 0 : virtual void applyBridgeForces( const std::vector<double>& bb ) { plumed_error(); } 187 : /// These are overwritten in MultiColvarFunction 188 : // virtual void activateIndexes( const unsigned&, const unsigned&, const std::vector<unsigned>& ){} 189 : /// Return a particular named vessel 190 : Vessel* getVesselWithName( const std::string& mynam ); 191 : /// Does the weight have derivatives 192 : bool weightWithDerivatives() const ; 193 : /// Return the position in the current task list 194 : unsigned getPositionInCurrentTaskList( const unsigned& myind ) const ; 195 : /// These normalizes vectors and is used in StoreDataVessel 196 0 : virtual void normalizeVector( std::vector<double>& vals ) const { plumed_error(); } 197 0 : virtual void normalizeVectorDerivatives( MultiValue& myvals ) const { plumed_error(); } 198 : }; 199 : 200 : inline 201 : double ActionWithVessel::getTolerance() const { 202 698630 : return tolerance; 203 : } 204 : 205 : inline 206 : double ActionWithVessel::getNLTolerance() const { 207 : return nl_tolerance; 208 : } 209 : 210 : inline 211 : unsigned ActionWithVessel::getNumberOfVessels() const { 212 12537362 : return functions.size(); 213 : } 214 : 215 : inline 216 196787 : unsigned ActionWithVessel::getNumberOfQuantities() const { 217 196787 : return 2; 218 : } 219 : 220 : inline 221 : Vessel* ActionWithVessel::getPntrToVessel( const unsigned& i ) { 222 : plumed_dbg_assert( i<functions.size() ); 223 2501 : return functions[i].get(); 224 : } 225 : 226 : inline 227 : unsigned ActionWithVessel::getFullNumberOfTasks() const { 228 15830229 : return fullTaskList.size(); 229 : } 230 : 231 : inline 232 : unsigned ActionWithVessel::getTaskCode( const unsigned& ii ) const { 233 : plumed_dbg_assert( ii<fullTaskList.size() ); 234 3509797 : return fullTaskList[ii]; 235 : } 236 : 237 : inline 238 : unsigned ActionWithVessel::getCurrentNumberOfActiveTasks() const { 239 29023 : return nactive_tasks; 240 : } 241 : 242 : inline 243 : unsigned ActionWithVessel::getActiveTask( const unsigned& ii ) const { 244 : plumed_dbg_assert( ii<nactive_tasks ); 245 54936 : return partialTaskList[ii]; 246 : } 247 : 248 : inline 249 : unsigned ActionWithVessel::getPositionInFullTaskList( const unsigned& ii ) const { 250 : plumed_dbg_assert( ii<nactive_tasks ); 251 62238 : return indexOfTaskInFullList[ii]; 252 : } 253 : 254 : inline 255 : bool ActionWithVessel::serialCalculation() const { 256 454 : return serial; 257 : } 258 : 259 : inline 260 : bool ActionWithVessel::usingLowMem() const { 261 867292 : return lowmem; 262 : } 263 : 264 : inline 265 : void ActionWithVessel::setLowMemOption(const bool& l) { 266 42 : lowmem=l; 267 : } 268 : 269 : inline 270 : bool ActionWithVessel::derivativesAreRequired() const { 271 714510 : return !noderiv; 272 : } 273 : 274 : inline 275 : bool ActionWithVessel::weightWithDerivatives() const { 276 13904 : return weightHasDerivatives; 277 : } 278 : 279 : inline 280 224556 : unsigned ActionWithVessel::getPositionInCurrentTaskList( const unsigned& myind ) const { 281 224556 : if( nactive_tasks==fullTaskList.size() ) return myind; 282 : 283 253764165 : for(unsigned i=0; i<nactive_tasks; ++i) { 284 253764165 : if( myind==indexOfTaskInFullList[i] ) return i; 285 : } 286 0 : plumed_merror("requested task is not active"); 287 : } 288 : 289 : } 290 : } 291 : #endif