LCOV - code coverage report
Current view: top level - multicolvar - MultiColvarBase.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 23 27 85.2 %
Date: 2024-10-11 08:09:47 Functions: 8 10 80.0 %

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

Generated by: LCOV version 1.15