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