1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2    Copyright (c) 2014-2021 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_AtomValuePack_h
23 #define __PLUMED_multicolvar_AtomValuePack_h
24 
25 #include "tools/MultiValue.h"
26 #include "MultiColvarBase.h"
27 
28 namespace PLMD {
29 
30 class LinkCells;
31 
32 namespace multicolvar {
33 
34 class CatomPack;
35 
36 class AtomValuePack {
37   friend class MultiColvarBase;
38   friend class LocalAverage;
39 private:
40 /// Copy of the values that we are adding to
41   MultiValue& myvals;
42 /// Copy of the underlying multicolvar
43   MultiColvarBase const * mycolv;
44 /// Number of atoms at the moment
45   unsigned natoms;
46 /// Atom indices
47   std::vector<unsigned>& indices;
48 /// This is used to sort the atom indices
49   std::vector<unsigned>& sort_vector;
50 /// This holds atom positions
51   std::vector<Vector>& myatoms;
52 /// This is stuff for link cells
53   std::vector<unsigned> cells_required;
54 ///
55   void addAtomsDerivatives( const unsigned&, const unsigned&, const Vector& );
56 ///
57   void addTemporyAtomsDerivatives( const unsigned& jder, const Vector& der );
58 public:
59   AtomValuePack( MultiValue& vals, MultiColvarBase const * mcolv );
60 /// Set the number of atoms
61   void setNumberOfAtoms( const unsigned& );
62 /// Set the index for one of the atoms
63   void setIndex( const unsigned&, const unsigned& );
64 ///
65   void setAtomIndex( const unsigned& j, const unsigned& ind );
66 ///
67   void setAtom( const unsigned& j, const unsigned& ind );
68 ///
69   unsigned setupAtomsFromLinkCells( const std::vector<unsigned>& cind, const Vector& cpos, const LinkCells& linkcells );
70 ///
71   unsigned getIndex( const unsigned& j ) const ;
72 ///
73   unsigned getNumberOfAtoms() const ;
74 ///
75   unsigned getNumberOfDerivatives() const ;
76 /// Get the position of the ith atom
77   Vector& getPosition( const unsigned& );
78 /// Get the absolute index of the ith atom in the list
79   AtomNumber getAbsoluteIndex( const unsigned& j ) const ;
80 ///
81   void setValue( const unsigned&, const double& );
82 ///
83   void addValue( const unsigned& ival, const double& vv );
84 ///
85   double getValue( const unsigned& ) const ;
86 ///
87   void addBoxDerivatives( const unsigned&, const Tensor& );
88 ///
89   void addTemporyBoxDerivatives( const Tensor& vir );
90 ///
91   void updateUsingIndices();
92 ///
93   void updateDynamicList();
94 ///
95   void addComDerivatives( const int&, const Vector&, CatomPack& );
96 ///
97   MultiValue& getUnderlyingMultiValue();
98 ///
99   void addDerivative( const unsigned&, const unsigned&, const double& );
100 };
101 
102 inline
setNumberOfAtoms(const unsigned & nat)103 void AtomValuePack::setNumberOfAtoms( const unsigned& nat ) {
104   natoms=nat;
105 }
106 
107 inline
getNumberOfAtoms()108 unsigned AtomValuePack::getNumberOfAtoms() const {
109   return natoms;
110 }
111 
112 inline
getNumberOfDerivatives()113 unsigned AtomValuePack::getNumberOfDerivatives() const {
114   return myvals.getNumberOfDerivatives();
115 }
116 
117 inline
setIndex(const unsigned & j,const unsigned & ind)118 void AtomValuePack::setIndex( const unsigned& j, const unsigned& ind ) {
119   plumed_dbg_assert( j<natoms ); indices[j]=ind;
120 }
121 
122 inline
setAtomIndex(const unsigned & j,const unsigned & ind)123 void AtomValuePack::setAtomIndex( const unsigned& j, const unsigned& ind ) {
124   plumed_dbg_assert( j<natoms ); indices[j]=ind;
125 }
126 
127 inline
setAtom(const unsigned & j,const unsigned & ind)128 void AtomValuePack::setAtom( const unsigned& j, const unsigned& ind ) {
129   setAtomIndex( j, ind ); myatoms[j]=mycolv->getPositionOfAtomForLinkCells( ind );
130 }
131 
132 inline
getIndex(const unsigned & j)133 unsigned AtomValuePack::getIndex( const unsigned& j ) const {
134   plumed_dbg_assert( j<natoms ); return indices[j];
135 }
136 
137 inline
getAbsoluteIndex(const unsigned & j)138 AtomNumber AtomValuePack::getAbsoluteIndex( const unsigned& j ) const {
139   plumed_dbg_assert( j<natoms ); unsigned jatom=indices[j];
140   if( mycolv->atom_lab[jatom].first>0 ) {
141     unsigned mmc=mycolv->atom_lab[jatom].first - 1;
142     return (mycolv->mybasemulticolvars[mmc])->getAbsoluteIndexOfCentralAtom( mycolv->atom_lab[jatom].second );
143   }
144   return mycolv->getAbsoluteIndex( mycolv->atom_lab[jatom].second );
145 }
146 
147 inline
getPosition(const unsigned & iatom)148 Vector& AtomValuePack::getPosition( const unsigned& iatom ) {
149   plumed_dbg_assert( iatom<natoms );
150   return myatoms[iatom];
151 }
152 
153 inline
setValue(const unsigned & ival,const double & vv)154 void AtomValuePack::setValue( const unsigned& ival, const double& vv ) {
155   myvals.setValue( ival, vv );
156 }
157 
158 inline
addValue(const unsigned & ival,const double & vv)159 void AtomValuePack::addValue( const unsigned& ival, const double& vv ) {
160   myvals.addValue( ival, vv );
161 }
162 
163 inline
getValue(const unsigned & ival)164 double AtomValuePack::getValue( const unsigned& ival ) const {
165   return myvals.get( ival );
166 }
167 
168 inline
addDerivative(const unsigned & ival,const unsigned & jder,const double & der)169 void AtomValuePack::addDerivative( const unsigned& ival, const unsigned& jder, const double& der ) {
170   myvals.addDerivative( ival, jder, der );
171 }
172 
173 inline
addAtomsDerivatives(const unsigned & ival,const unsigned & jder,const Vector & der)174 void AtomValuePack::addAtomsDerivatives( const unsigned& ival, const unsigned& jder, const Vector& der ) {
175   plumed_dbg_assert( jder<natoms );
176   myvals.addDerivative( ival, 3*indices[jder] + 0, der[0] );
177   myvals.addDerivative( ival, 3*indices[jder] + 1, der[1] );
178   myvals.addDerivative( ival, 3*indices[jder] + 2, der[2] );
179 }
180 
181 inline
addTemporyAtomsDerivatives(const unsigned & jder,const Vector & der)182 void AtomValuePack::addTemporyAtomsDerivatives( const unsigned& jder, const Vector& der ) {
183   plumed_dbg_assert( jder<natoms );
184   myvals.addTemporyDerivative( 3*indices[jder] + 0, der[0] );
185   myvals.addTemporyDerivative( 3*indices[jder] + 1, der[1] );
186   myvals.addTemporyDerivative( 3*indices[jder] + 2, der[2] );
187 }
188 
189 inline
addTemporyBoxDerivatives(const Tensor & vir)190 void AtomValuePack::addTemporyBoxDerivatives( const Tensor& vir ) {
191   unsigned nvir=3*mycolv->getNumberOfAtoms();
192   for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) myvals.addTemporyDerivative( nvir + 3*i+j, vir(i,j) );
193 }
194 
195 inline
addBoxDerivatives(const unsigned & ival,const Tensor & vir)196 void AtomValuePack::addBoxDerivatives( const unsigned& ival, const Tensor& vir ) {
197   unsigned nvir=3*mycolv->getNumberOfAtoms();
198   for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) myvals.addDerivative( ival, nvir + 3*i+j, vir(i,j) );
199 }
200 
201 inline
updateDynamicList()202 void AtomValuePack::updateDynamicList() {
203   if( myvals.updateComplete() ) return;
204   myvals.updateDynamicList();
205 }
206 
207 inline
getUnderlyingMultiValue()208 MultiValue& AtomValuePack::getUnderlyingMultiValue() {
209   return myvals;
210 }
211 
212 }
213 }
214 #endif
215 
216