Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2011-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_core_ActionWithVector_h 23 : #define __PLUMED_core_ActionWithVector_h 24 : 25 : #include "ActionWithValue.h" 26 : #include "ActionAtomistic.h" 27 : #include "ActionWithArguments.h" 28 : #include "tools/MultiValue.h" 29 : #include <vector> 30 : 31 : namespace PLMD { 32 : 33 : class ActionWithVector: 34 : public ActionAtomistic, 35 : public ActionWithValue, 36 : public ActionWithArguments { 37 : friend class Value; 38 : private: 39 : /// Is the calculation to be done in serial 40 : bool serial; 41 : /// The buffer that we use (we keep a copy here to avoid resizing) 42 : std::vector<double> buffer; 43 : /// The list of active tasks 44 : std::vector<unsigned> active_tasks; 45 : /// Action that must be done before this one 46 : ActionWithVector* action_to_do_before; 47 : /// Actions that must be done after this one 48 : ActionWithVector* action_to_do_after; 49 : /// This is the list of actions that control the tasks that we do here 50 : std::vector<ActionWithVector*> task_control_list; 51 : /// Work backwards through the chain to find an action that has either stored arguments or derivatives 52 : ActionWithVector* getActionWithDerivatives( ActionWithVector* depaction ); 53 : /// Check if there are any grids in the stream 54 : bool checkForGrids(unsigned& nder) const ; 55 : /// Run the task 56 : void runTask( const unsigned& taskno, MultiValue& myvals ) const ; 57 : /// Gather the values that we intend to store in the buffer 58 : void gatherAccumulators( const unsigned& taskCode, const MultiValue& myvals, std::vector<double>& buffer ) const ; 59 : /// Gather the forces on non-scalar quantities 60 : void gatherForces( const unsigned& i, const MultiValue& myvals, std::vector<double>& forces ) const ; 61 : /// Get the size of the buffer array that holds the data we are gathering over the MPI loop 62 : void getSizeOfBuffer( const unsigned& nactive_tasks, unsigned& bufsize ); 63 : /// Get the number of quantities in the stream 64 : void getNumberOfStreamedQuantities( const std::string& headstr, unsigned& nquants, unsigned& nmat, unsigned& maxcol, unsigned& nbookeeping ); 65 : /// Get the number of stored values in the stream 66 : bool getNumberOfStoredValues( Value* startat, unsigned& nvals, const unsigned& astart, const std::vector<Value*>& stopat ); 67 : /// Add this action to the recursive chain 68 : bool addActionToChain( const std::vector<std::string>& alabels, ActionWithVector* act ); 69 : /// Check the chain for non scalar forces 70 : bool checkChainForNonScalarForces() const ; 71 : /// Check if a force has been added on one of the components of this action 72 : bool checkComponentsForForce() const ; 73 : /// Get the tasks that we need for forces 74 : void getForceTasks( std::vector<unsigned>& force_tasks ) const ; 75 : /// Add the gathered forces to the inputs across the whole chain 76 : void addForcesToInput( const std::vector<double>& forcesToApply, unsigned& ind ); 77 : /// Check if this ation can reduce the number of tasks we perform 78 : void canReduceTasks( std::vector<ActionWithVector*>& task_reducing_actions ); 79 : /// Send information to arguments that tasks are reduced in depedent actions 80 : void broadcastThatTasksAreReduced( ActionWithVector* aselect ); 81 : /// Turn on task reduction flag in dependent actions 82 : void updateTaskReductionFlag( bool& head_reduce_tasks ); 83 : /// Check if a particular task is active at this time 84 : void taskIsActive( const unsigned& current, int& flag ) const ; 85 : /// This is turned on if there is some action that needs all the tasks 86 : bool never_reduce_tasks; 87 : /// Are we allowed to reduce the number of tasks being performed 88 : bool reduce_tasks; 89 : /// Were the atoms retrieved in some earlier action 90 : bool atomsWereRetrieved; 91 : /// This is used to build the argument store when we cannot use the chain 92 : unsigned reallyBuildArgumentStore( const unsigned& argstart ); 93 : protected: 94 : /// A vector that contains the start point for the argument derivatives 95 : std::vector<unsigned> arg_deriv_starts; 96 : /// Assert if this action is part of a chain 97 : bool done_in_chain; 98 : /// This updates whether or not we are using all the task reduction stuff 99 : void updateTaskListReductionStatus(); 100 : /// Run all calculations in serial 101 : bool runInSerial() const ; 102 : /// Get the list of tasks that are active 103 : std::vector<unsigned>& getListOfActiveTasks( ActionWithVector* action ); 104 : /// Check if the arguments of this action depend on thearg 105 : bool argumentDependsOn( const std::string& headstr, ActionWithVector* faction, Value* thearg ); 106 : /// This sets up the arguments at the start of the calculation 107 : unsigned buildArgumentStore( const unsigned& argstart ); 108 : /// Run all the tasks in the list 109 : void runAllTasks(); 110 : /// Accumulate the forces from the Values 111 : bool checkForForces(); 112 : public: 113 : static void registerKeywords( Keywords& keys ); 114 : explicit ActionWithVector(const ActionOptions&); 115 : virtual ~ActionWithVector(); 116 : void lockRequests() override; 117 : void unlockRequests() override; 118 : virtual void prepare() override; 119 : void retrieveAtoms( const bool& force=false ) override; 120 : void calculateNumericalDerivatives(ActionWithValue* av) override; 121 : /// Are we running this command in a chain 122 : bool actionInChain() const ; 123 : /// This is overwritten within ActionWithMatrix and is used to build the chain of just matrix actions 124 : virtual void finishChainBuild( ActionWithVector* act ); 125 : /// Check if there are any stored values in arguments 126 : bool hasStoredArguments() const ; 127 : /// Return a pointer to the first action in the chain 128 : const ActionWithVector* getFirstActionInChain() const ; 129 : ActionWithVector* getFirstActionInChain(); 130 : /// This is overridden in ActionWithMatrix 131 22 : virtual void getAllActionLabelsInMatrixChain( std::vector<std::string>& matchain ) const {} 132 : /// Get the number of derivatives in the stream 133 : void getNumberOfStreamedDerivatives( unsigned& nderivatives, Value* stopat ); 134 : /// Get every the label of every value that is calculated in this chain 135 : void getAllActionLabelsInChain( std::vector<std::string>& mylabels ) const ; 136 : /// We override clearInputForces here to ensure that forces are deleted from all values 137 : void clearInputForces( const bool& force=false ) override; 138 : /// We override clearDerivatives here to prevent data in streams from being deleted 139 : void clearDerivatives( const bool& force=false ) override; 140 : /// Check if we can be after another ActionWithVector 141 158477 : virtual bool canBeAfterInChain( ActionWithVector* av ) { 142 158477 : return true; 143 : } 144 : /// Do we always need to do all the tasks for this action 145 7699 : virtual void areAllTasksRequired( std::vector<ActionWithVector*>& task_reducing_actions ) {} 146 : /// Find out how many tasks we need to perform in this loop 147 : virtual void getNumberOfTasks( unsigned& ntasks ); 148 : /// Check the status of the ith task 149 4611685 : virtual int checkTaskStatus( const unsigned& taskno, int& flag ) const { 150 4611685 : return flag; 151 : } 152 : /// Check if we are in a subchain 153 3240 : virtual bool isInSubChain( unsigned& nder ) { 154 3240 : return false; 155 : } 156 : /// Get the additional tasks that are required here 157 : virtual void getAdditionalTasksRequired( ActionWithVector* action, std::vector<unsigned>& atasks ); 158 : /// setup the streamed quantities 159 : virtual void setupStreamedComponents( const std::string& headstr, unsigned& nquants, unsigned& nmat, unsigned& maxcol, unsigned& nbookeeping ); 160 : /// This we override to perform each individual task 161 : virtual void performTask( const unsigned& current, MultiValue& myvals ) const = 0; 162 : /// This is used to ensure that all indices are updated when you do local average 163 13807 : virtual void updateAdditionalIndices( const unsigned& ostrn, MultiValue& myvals ) const {} 164 : /// Gather the data from all the OpenMP threads 165 : virtual void gatherThreads( const unsigned& nt, const unsigned& bufsize, const std::vector<double>& omp_buffer, std::vector<double>& buffer, MultiValue& myvals ); 166 : /// Can be used to reduce the number of tasks that are performed when you use an ation from elsewhere 167 0 : virtual void switchTaskReduction( const bool& task_reduction, ActionWithVector* aselect ) {} 168 : /// Gather all the data from the MPI processes 169 : virtual void gatherProcesses( std::vector<double>& buffer ); 170 : /// Gather the values that we intend to store in the buffer 171 : virtual void gatherStoredValue( const unsigned& valindex, const unsigned& code, const MultiValue& myvals, const unsigned& bufstart, std::vector<double>& buffer ) const ; 172 : /// Get the force tasks that are active for this action 173 : virtual void updateForceTasksFromValue( const Value* myval, std::vector<unsigned>& force_tasks ) const ; 174 : /// Check if there is a force that needs to be accumulated on the ith task 175 : virtual bool checkForTaskForce( const unsigned& itask, const Value* myval ) const ; 176 : /// Gather the forces on a particular value 177 : virtual void gatherForcesOnStoredValue( const Value* myval, const unsigned& itask, const MultiValue& myvals, std::vector<double>& forces ) const ; 178 : /// This is to transfer data from the buffer to the final value 179 : void finishComputations( const std::vector<double>& buf ); 180 : /// Apply the forces on this data 181 : virtual void apply(); 182 : }; 183 : 184 : inline 185 : bool ActionWithVector::actionInChain() const { 186 257560075 : return (action_to_do_before!=NULL); 187 : } 188 : 189 : inline 190 : bool ActionWithVector::runInSerial() const { 191 27747 : return serial; 192 : } 193 : 194 : } 195 : 196 : #endif