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_ActionWithVirtualAtom_h 23 : #define __PLUMED_core_ActionWithVirtualAtom_h 24 : 25 : #include "ActionAtomistic.h" 26 : #include "tools/AtomNumber.h" 27 : #include "tools/Vector.h" 28 : #include "tools/Tensor.h" 29 : #include "Atoms.h" 30 : #include <array> 31 : 32 : namespace PLMD { 33 : 34 : /** 35 : \ingroup INHERIT 36 : Inherit from here if you are calculating the position of a virtual atom (eg a center of mass) 37 : */ 38 : 39 : /// Class to add a single virtual atom to the system. 40 : /// (it might be extended to add multiple virtual atoms). 41 : class ActionWithVirtualAtom: 42 : public ActionAtomistic 43 : { 44 : const AtomNumber index; 45 : std::vector<Tensor> derivatives; 46 : std::array<Tensor,3> boxDerivatives; 47 : std::map<AtomNumber,Tensor> gradients; 48 : void apply() override; 49 : protected: 50 : /// Set position of the virtual atom 51 : void setPosition(const Vector &); 52 : /// Set its mass 53 : void setMass(double); 54 : /// Set its charge 55 : void setCharge(double); 56 : /// Request atoms on which the calculation depends 57 : void requestAtoms(const std::vector<AtomNumber> & a); 58 : /// Set the derivatives of virtual atom coordinate wrt atoms on which it dependes 59 : void setAtomsDerivatives(const std::vector<Tensor> &d); 60 : /// Set the box derivatives. 61 : /// This should be an array of size 3. First index corresponds 62 : /// to the components of the virtual atom. 63 : /// Notice that this routine subtract the trivial term coming from cell deformation 64 : /// since this term is already implicitly included. Indeed, if the vatom 65 : /// position is a linear function of atomic coordinates it is not necessary 66 : /// to call this function (implicit term is fine) (e.g. vatom::COM and vatom::Center). 67 : /// On the other hand if the vatom position is a non-linear function of atomic coordinates this 68 : /// should be called (see vatom::Ghost). 69 : void setBoxDerivatives(const std::array<Tensor,3> &d); 70 : /// Set box derivatives automatically. 71 : /// It should be called after the settomsDerivatives has been used for all 72 : /// single atoms. 73 : /// \warning It only works for virtual atoms NOT using PBCs! 74 : /// This implies that all atoms used + the new virtual atom should be 75 : /// in the same periodic image. 76 : void setBoxDerivativesNoPbc(); 77 : public: 78 : void setGradients(); 79 : const std::map<AtomNumber,Tensor> & getGradients()const; 80 : /// Return the atom id of the corresponding virtual atom 81 : AtomNumber getIndex()const; 82 : explicit ActionWithVirtualAtom(const ActionOptions&ao); 83 : ~ActionWithVirtualAtom(); 84 : static void registerKeywords(Keywords& keys); 85 : void setGradientsIfNeeded(); 86 : }; 87 : 88 : inline 89 : AtomNumber ActionWithVirtualAtom::getIndex()const { 90 7215 : return index; 91 : } 92 : 93 : inline 94 : void ActionWithVirtualAtom::setPosition(const Vector & pos) { 95 14412 : atoms.positions[index.index()]=pos; 96 598 : } 97 : 98 : inline 99 : void ActionWithVirtualAtom::setMass(double m) { 100 854 : atoms.masses[index.index()]=m; 101 : } 102 : 103 : inline 104 : void ActionWithVirtualAtom::setCharge(double c) { 105 14408 : atoms.charges[index.index()]=c; 106 13798 : } 107 : 108 : inline 109 : void ActionWithVirtualAtom::setAtomsDerivatives(const std::vector<Tensor> &d) { 110 14412 : derivatives=d; 111 14412 : } 112 : 113 : inline 114 : const std::map<AtomNumber,Tensor> & ActionWithVirtualAtom::getGradients()const { 115 : return gradients; 116 : } 117 : 118 : } 119 : 120 : #endif