Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2018 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 : #include "ActionWithVirtualAtom.h"
23 : #include "ActionRegister.h"
24 : #include "core/PlumedMain.h"
25 : #include "core/Atoms.h"
26 :
27 : using namespace std;
28 :
29 : namespace PLMD {
30 : namespace vatom {
31 :
32 : //+PLUMEDOC VATOM COM
33 : /*
34 : Calculate the center of mass for a group of atoms.
35 :
36 : The computed
37 : center of mass is stored as a virtual atom that can be accessed in
38 : an atom list through the label for the COM action that creates it.
39 :
40 : For arbitrary weights (e.g. geometric center) see \ref CENTER.
41 :
42 : When running with periodic boundary conditions, the atoms should be
43 : in the proper periodic image. This is done automatically since PLUMED 2.2,
44 : by considering the ordered list of atoms and rebuilding PBCs with a procedure
45 : that is equivalent to that done in \ref WHOLEMOLECULES . Notice that
46 : rebuilding is local to this action. This is different from \ref WHOLEMOLECULES
47 : which actually modifies the coordinates stored in PLUMED.
48 :
49 : In case you want to recover the old behavior you should use the NOPBC flag.
50 : In that case you need to take care that atoms are in the correct
51 : periodic image.
52 :
53 : \par Examples
54 :
55 : The following input instructs plumed to print the distance between the
56 : center of mass for atoms 1,2,3,4,5,6,7 and that for atoms 15,20:
57 : \verbatim
58 : COM ATOMS=1-7 LABEL=c1
59 : COM ATOMS=15,20 LABEL=c2
60 : DISTANCE ATOMS=c1,c2 LABEL=d1
61 : PRINT ARG=d1
62 : \endverbatim
63 : (See also \ref DISTANCE and \ref PRINT).
64 :
65 : */
66 : //+ENDPLUMEDOC
67 :
68 :
69 76 : class COM:
70 : public ActionWithVirtualAtom
71 : {
72 : bool nopbc;
73 : public:
74 : explicit COM(const ActionOptions&ao);
75 : void calculate();
76 : static void registerKeywords( Keywords& keys );
77 : };
78 :
79 2561 : PLUMED_REGISTER_ACTION(COM,"COM")
80 :
81 39 : void COM::registerKeywords(Keywords& keys) {
82 39 : ActionWithVirtualAtom::registerKeywords(keys);
83 39 : keys.addFlag("NOPBC",false,"ignore the periodic boundary conditions when calculating distances");
84 39 : }
85 :
86 38 : COM::COM(const ActionOptions&ao):
87 : Action(ao),
88 : ActionWithVirtualAtom(ao),
89 38 : nopbc(false)
90 : {
91 38 : vector<AtomNumber> atoms;
92 38 : parseAtomList("ATOMS",atoms);
93 38 : if(atoms.size()==0) error("at least one atom should be specified");
94 38 : parseFlag("NOPBC",nopbc);
95 38 : checkRead();
96 38 : log.printf(" of atoms");
97 38 : for(unsigned i=0; i<atoms.size(); ++i) log.printf(" %d",atoms[i].serial());
98 38 : log.printf("\n");
99 38 : if(nopbc) {
100 17 : log<<" PBC will be ignored\n";
101 : } else {
102 21 : log<<" broken molecules will be rebuilt assuming atoms are in the proper order\n";
103 : }
104 38 : requestAtoms(atoms);
105 38 : }
106 :
107 2355 : void COM::calculate() {
108 2355 : Vector pos;
109 2355 : if(!nopbc) makeWhole();
110 2355 : double mass(0.0);
111 2355 : vector<Tensor> deriv(getNumberOfAtoms());
112 2355 : for(unsigned i=0; i<getNumberOfAtoms(); i++) mass+=getMass(i);
113 2355 : if( plumed.getAtoms().chargesWereSet() ) {
114 300 : double charge(0.0);
115 300 : for(unsigned i=0; i<getNumberOfAtoms(); i++) charge+=getCharge(i);
116 300 : setCharge(charge);
117 : } else {
118 2055 : setCharge(0.0);
119 : }
120 19926 : for(unsigned i=0; i<getNumberOfAtoms(); i++) {
121 17571 : pos+=(getMass(i)/mass)*getPosition(i);
122 17571 : deriv[i]=(getMass(i)/mass)*Tensor::identity();
123 : }
124 2355 : setPosition(pos);
125 2355 : setMass(mass);
126 2355 : setAtomsDerivatives(deriv);
127 2355 : }
128 :
129 : }
130 2523 : }
|