OpenMD 3.1
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
EnergyCorrFunc.cpp
1/*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * This software is provided "AS IS," without a warranty of any
18 * kind. All express or implied conditions, representations and
19 * warranties, including any implied warranty of merchantability,
20 * fitness for a particular purpose or non-infringement, are hereby
21 * excluded. The University of Notre Dame and its licensors shall not
22 * be liable for any damages suffered by licensee as a result of
23 * using, modifying or distributing the software or its
24 * derivatives. In no event will the University of Notre Dame or its
25 * licensors be liable for any lost revenue, profit or data, or for
26 * direct, indirect, special, consequential, incidental or punitive
27 * damages, however caused and regardless of the theory of liability,
28 * arising out of the use of or inability to use software, even if the
29 * University of Notre Dame has been advised of the possibility of
30 * such damages.
31 *
32 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33 * research, please cite the appropriate papers when you publish your
34 * work. Good starting points are:
35 *
36 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 */
42
43 /* Uses the Helfand-moment method for calculating thermal
44 * conductivity using the relation kappa = (N,V)lim(t)->inf 1/(2*k_B*T^2*V*t) <[G_K(t)-G_K(0)]^2>
45 * where G_K is the Helfand moment for thermal conductivity definded as
46 * G_K(t) = sum_{a=1}{^N} x_a(E_a-<E_a>) and E_a is defined to be
47 * E_a = p_2^2/(2*m)+1/2 sum_{b.ne.a} u(r_ab) where p is momentum and u is pot energy for the
48 * particle pair a-b. This routine calculates E_a, <E_a> and does the correlation
49 * <[G_K(t)-G_K(0)]^2>.
50 * See Viscardy et al. JCP 126, 184513 (2007)
51 */
52
53
54
55#include "applications/dynamicProps/EnergyCorrFunc.hpp"
56#include "utils/Constants.hpp"
57#include "utils/Revision.hpp"
59#include "brains/Thermo.hpp"
60
61namespace OpenMD {
62
63 // We need all of the positions, velocities, etc. so that we can
64 // recalculate pressures and actions on the fly:
65 EnergyCorrFunc::EnergyCorrFunc(SimInfo* info, const std::string& filename,
66 const std::string& sele1,
67 const std::string& sele2,
68 long long int memSize)
69 : FrameTimeCorrFunc(info, filename, sele1, sele2,
70 DataStorage::dslPosition |
71 DataStorage::dslVelocity |
72 DataStorage::dslForce |
73 DataStorage::dslTorque |
74 DataStorage::dslParticlePot,
75 memSize){
76
77 setCorrFuncType("EnergyCorrFunc");
78 setOutputName(getPrefix(dumpFilename_) + ".moment");
79 histogram_.resize(nTimeBins_);
80 count_.resize(nTimeBins_);
81 }
82
83 void EnergyCorrFunc::correlateFrames(int frame1, int frame2) {
84 SimInfo::MoleculeIterator mi1;
85 SimInfo::MoleculeIterator mi2;
86 Molecule* mol1;
87 Molecule* mol2;
88 Molecule::AtomIterator ai1;
89 Molecule::AtomIterator ai2;
90 Atom* atom1;
91 Atom* atom2;
92 std::vector<RealType> particleEnergies1;
93 std::vector<RealType> particleEnergies2;
94 std::vector<Vector3d> atomPositions1;
95 std::vector<Vector3d> atomPositions2;
96 int thisAtom1, thisAtom2;
97
98 Snapshot* snapshot1 = bsMan_->getSnapshot(frame1);
99 Snapshot* snapshot2 = bsMan_->getSnapshot(frame2);
100 assert(snapshot1 && snapshot2);
101
102 RealType time1 = snapshot1->getTime();
103 RealType time2 = snapshot2->getTime();
104
105 int timeBin = int ((time2 - time1) /deltaTime_ + 0.5);
106
107 // now do the correlation
108
109 particleEnergies1 = E_a_[frame1];
110 particleEnergies2 = E_a_[frame2];
111
112 atomPositions1.clear();
113 for (mol1 = info_->beginMolecule(mi1); mol1 != NULL;
114 mol1 = info_->nextMolecule(mi1)) {
115 for(atom1 = mol1->beginAtom(ai1); atom1 != NULL;
116 atom1 = mol1->nextAtom(ai1)) {
117 atomPositions1.push_back(atom1->getPos(frame1));
118 }
119 }
120
121 atomPositions2.clear();
122 for (mol2 = info_->beginMolecule(mi2); mol2 != NULL;
123 mol2 = info_->nextMolecule(mi2)) {
124 for(atom2 = mol2->beginAtom(ai2); atom2 != NULL;
125 atom2 = mol2->nextAtom(ai2)) {
126 atomPositions2.push_back(atom2->getPos(frame2));
127 }
128 }
129
130 thisAtom1 = 0;
131
132 for (mol1 = info_->beginMolecule(mi1); mol1 != NULL;
133 mol1 = info_->nextMolecule(mi1)) {
134 for(atom1 = mol1->beginAtom(ai1); atom1 != NULL;
135 atom1 = mol1->nextAtom(ai1)) {
136
137 Vector3d r1 = atomPositions1[thisAtom1];
138 RealType energy1 = particleEnergies1[thisAtom1] - AvgE_a_[thisAtom1];
139
140 thisAtom2 = 0;
141
142 for (mol2 = info_->beginMolecule(mi2); mol2 != NULL;
143 mol2 = info_->nextMolecule(mi2)) {
144 for(atom2 = mol2->beginAtom(ai2); atom2 != NULL;
145 atom2 = mol2->nextAtom(ai2)) {
146
147 Vector3d r2 = atomPositions2[thisAtom2];
148 RealType energy2 = particleEnergies2[thisAtom2] - AvgE_a_[thisAtom2];
149
150 Vector3d deltaPos = (r2-r1);
151 RealType Eprod = energy2*energy1;
152
153 histogram_[timeBin][0] += deltaPos.x()*deltaPos.x() * Eprod;
154 histogram_[timeBin][1] += deltaPos.y()*deltaPos.y() * Eprod;
155 histogram_[timeBin][2] += deltaPos.z()*deltaPos.z() * Eprod;
156
157 thisAtom2++;
158 }
159 }
160
161 thisAtom1++;
162 }
163 }
164
165 count_[timeBin]++;
166
167 }
168
169 void EnergyCorrFunc::postCorrelate() {
170 for (unsigned int i =0 ; i < nTimeBins_; ++i) {
171 if (count_[i] > 0) {
172 histogram_[i] /= count_[i];
173 }
174 }
175 }
176
177 void EnergyCorrFunc::preCorrelate() {
178 // Fill the histogram with empty 3x3 matrices:
179 std::fill(histogram_.begin(), histogram_.end(), 0.0);
180 // count array set to zero
181 std::fill(count_.begin(), count_.end(), 0);
182
183 SimInfo::MoleculeIterator mi;
184 Molecule* mol;
185 Molecule::AtomIterator ai;
186 Atom* atom;
187 std::vector<RealType > particleEnergies;
188
189 // We'll need the force manager to compute forces for the average pressure
190 ForceManager* forceMan = new ForceManager(info_);
191
192 // dump files can be enormous, so read them in block-by-block:
193 int nblocks = bsMan_->getNBlocks();
194 bool firsttime = true;
195 for (int i = 0; i < nblocks; ++i) {
196 bsMan_->loadBlock(i);
197 assert(bsMan_->isBlockActive(i));
198 SnapshotBlock block1 = bsMan_->getSnapshotBlock(i);
199 for (int j = block1.first; j < block1.second; ++j) {
200
201 // do the forces:
202
203 forceMan->calcForces();
204
205 int index = 0;
206
207 for (mol = info_->beginMolecule(mi); mol != NULL;
208 mol = info_->nextMolecule(mi)) {
209 for(atom = mol->beginAtom(ai); atom != NULL;
210 atom = mol->nextAtom(ai)) {
211 RealType mass = atom->getMass();
212 Vector3d vel = atom->getVel(j);
213 RealType kinetic = mass * (vel[0]*vel[0] + vel[1]*vel[1] +
214 vel[2]*vel[2]) / Constants::energyConvert;
215 RealType potential = atom->getParticlePot(j);
216 RealType eatom = (kinetic + potential)/2.0;
217 particleEnergies.push_back(eatom);
218 if(firsttime)
219 {
220 AvgE_a_.push_back(eatom);
221 } else {
222 /* We assume the the number of atoms does not change.*/
223 AvgE_a_[index] += eatom;
224 }
225 index++;
226 }
227 }
228 firsttime = false;
229 E_a_.push_back(particleEnergies);
230 }
231
232 bsMan_->unloadBlock(i);
233 }
234
235 int nframes = bsMan_->getNFrames();
236 for (unsigned int i = 0; i < AvgE_a_.size(); i++){
237 AvgE_a_[i] /= nframes;
238 }
239
240 }
241
242 void EnergyCorrFunc::writeCorrelate() {
243 std::ofstream ofs(getOutputFileName().c_str());
244
245 if (ofs.is_open()) {
246 Revision r;
247
248 ofs << "# " << getCorrFuncType() << "\n";
249 ofs << "# OpenMD " << r.getFullRevision() << "\n";
250 ofs << "# " << r.getBuildDate() << "\n";
251 ofs << "# selection script1: \"" << selectionScript1_ ;
252 ofs << "\"\tselection script2: \"" << selectionScript2_ << "\"\n";
253 if (!paramString_.empty())
254 ofs << "# parameters: " << paramString_ << "\n";
255 ofs << "#time\tK_x\tK_y\tK_z\n";
256
257 for (unsigned int i = 0; i < nTimeBins_; ++i) {
258 ofs << time_[i] << "\t" <<
259 histogram_[i].x() << "\t" <<
260 histogram_[i].y() << "\t" <<
261 histogram_[i].z() << "\t" << "\n";
262 }
263
264 } else {
265 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
266 "EnergyCorrFunc::writeCorrelate Error: fail to open %s\n",
267 getOutputFileName().c_str());
268 painCave.isFatal = 1;
269 simError();
270 }
271
272 ofs.close();
273
274 }
275}
ForceManager is responsible for calculating both the short range (bonded) interactions and long range...
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:93
The Snapshot class is a repository storing dynamic data during a Simulation.
Definition Snapshot.hpp:147
Vector3d getVel()
Returns the current velocity of this stuntDouble.
RealType getMass()
Returns the mass of this stuntDouble.
Vector3d getPos()
Returns the current position of this stuntDouble.
RealType getParticlePot()
Returns the current particlePot of this stuntDouble.
Real & z()
Returns reference of the third element of Vector3.
Definition Vector3.hpp:120
Real & x()
Returns reference of the first element of Vector3.
Definition Vector3.hpp:96
Real & y()
Returns reference of the second element of Vector3.
Definition Vector3.hpp:108
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)