ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/applications/staticProps/SpatialStatistics.cpp
Revision: 1865
Committed: Wed Apr 17 18:24:08 2013 UTC (12 years ago) by gezelter
File size: 12478 byte(s)
Log Message:
Adding spatial statistics analysers.

File Contents

# Content
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 #include "applications/staticProps/SpatialStatistics.hpp"
44 #include "io/DumpReader.hpp"
45 #include "primitives/Molecule.hpp"
46
47 namespace OpenMD {
48
49 SpatialStatistics::SpatialStatistics(SimInfo* info, const string& filename,
50 const string& sele, int nbins)
51 : StaticAnalyser(info, filename), selectionScript_(sele), evaluator_(info),
52 seleMan_(info), nBins_(nbins){
53
54 evaluator_.loadScriptString(sele);
55 if (!evaluator_.isDynamic()) {
56 seleMan_.setSelectionSet(evaluator_.evaluate());
57 }
58
59 // Pre-load an OutputData for the count of objects:
60 counts_ = new OutputData;
61 counts_->units = "objects";
62 counts_->title = "Objects";
63 counts_->dataType = odtReal;
64 counts_->dataHandling = odhTotal;
65 counts_->accumulator.reserve(nBins_);
66 for (int i = 0; i < nBins_; i++)
67 counts_->accumulator.push_back( new Accumulator() );
68
69 setOutputName(getPrefix(filename) + ".spst");
70 }
71
72 SpatialStatistics::~SpatialStatistics() {
73 vector<OutputData*>::iterator i;
74 OutputData* outputData;
75
76 for(outputData = beginOutputData(i); outputData;
77 outputData = nextOutputData(i)) {
78 delete outputData;
79 }
80 data_.clear();
81
82 delete counts_;
83 }
84
85
86 void SpatialStatistics::process() {
87
88 DumpReader reader(info_, dumpFilename_);
89 int nFrames = reader.getNFrames();
90 nProcessed_ = nFrames/step_;
91
92 for (int istep = 0; istep < nFrames; istep += step_) {
93 reader.readFrame(istep);
94 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
95 processFrame(istep);
96 }
97 writeOutput();
98 }
99
100
101 void SpatialStatistics::processFrame(int istep) {
102 Molecule* mol;
103 RigidBody* rb;
104 StuntDouble* sd;
105 SimInfo::MoleculeIterator mi;
106 Molecule::RigidBodyIterator rbIter;
107 int i;
108
109 for (mol = info_->beginMolecule(mi); mol != NULL;
110 mol = info_->nextMolecule(mi)) {
111
112 // change the positions of atoms which belong to the rigidbodies
113
114 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
115 rb = mol->nextRigidBody(rbIter)) {
116 rb->updateAtoms();
117 }
118 }
119
120 if (evaluator_.isDynamic()) {
121 seleMan_.setSelectionSet(evaluator_.evaluate());
122 }
123
124 // loop over the selected atoms:
125
126 for (sd = seleMan_.beginSelected(i); sd != NULL;
127 sd = seleMan_.nextSelected(i)) {
128
129 // figure out where that object is:
130
131 Vector3d pos = sd->getPos();
132
133 int bin = getBin(pos);
134
135 // forward the work of statistics on to the subclass:
136
137 processStuntDouble( sd, bin );
138
139 dynamic_cast<Accumulator *>(counts_->accumulator[bin])->add(1);
140 }
141 }
142
143
144 void SpatialStatistics::writeOutput() {
145
146 vector<OutputData*>::iterator i;
147 OutputData* outputData;
148
149 ofstream outStream(outputFilename_.c_str());
150 if (outStream.is_open()) {
151
152 //write title
153 outStream << "# SPATIAL STATISTICS\n";
154 outStream << "#";
155
156 for(outputData = beginOutputData(i); outputData;
157 outputData = nextOutputData(i)) {
158 outStream << "\t" << outputData->title <<
159 "(" << outputData->units << ")";
160 // add some extra tabs for column alignment
161 if (outputData->dataType == odtVector3) outStream << "\t\t";
162 }
163
164 outStream << std::endl;
165
166 outStream.precision(8);
167
168 for (int j = 0; j < nBins_; j++) {
169
170 int counts = counts_->accumulator[j]->count();
171
172 if (counts > 0) {
173 for(outputData = beginOutputData(i); outputData;
174 outputData = nextOutputData(i)) {
175
176 int n = outputData->accumulator[j]->count();
177 if (n != 0) {
178 writeData( outStream, outputData, j );
179 }
180 }
181 outStream << std::endl;
182 }
183 }
184
185 outStream << "#######################################################\n";
186 outStream << "# Standard Deviations in those quantities follow:\n";
187 outStream << "#######################################################\n";
188
189 for (int j = 0; j < nBins_; j++) {
190 int counts = counts_->accumulator[j]->count();
191 if (counts > 0) {
192
193 outStream << "#";
194 for(outputData = beginOutputData(i); outputData;
195 outputData = nextOutputData(i)) {
196
197 int n = outputData->accumulator[j]->count();
198 if (n != 0) {
199 writeStdDev( outStream, outputData, j );
200 }
201 }
202 outStream << std::endl;
203 }
204 }
205
206 outStream.flush();
207 outStream.close();
208
209 } else {
210 sprintf(painCave.errMsg, "SpatialStatistics: unable to open %s\n",
211 outputFilename_.c_str());
212 painCave.isFatal = 1;
213 simError();
214 }
215 }
216
217
218 void SpatialStatistics::writeData(ostream& os, OutputData* dat,
219 unsigned int bin) {
220 assert(int(bin) < nBins_);
221 int n = dat->accumulator[bin]->count();
222 if (n == 0) return;
223
224 RealType r;
225 Vector3d v;
226
227 if( dat->dataType == odtReal ) {
228 dynamic_cast<Accumulator*>(dat->accumulator[bin])->getAverage(r);
229 if (isinf(r) || isnan(r) ) {
230 sprintf( painCave.errMsg,
231 "SpatialStatistics detected a numerical error writing:\n"
232 "\t%s for bin %d",
233 dat->title.c_str(), bin);
234 painCave.isFatal = 1;
235 simError();
236 }
237 if (dat->dataHandling == odhTotal) r *= dat->accumulator[bin]->count();
238 os << "\t" << r;
239
240 } else if ( dat->dataType == odtVector3 ) {
241 dynamic_cast<VectorAccumulator*>(dat->accumulator[bin])->getAverage(v);
242 if (isinf(v[0]) || isnan(v[0]) ||
243 isinf(v[1]) || isnan(v[1]) ||
244 isinf(v[2]) || isnan(v[2]) ) {
245 sprintf( painCave.errMsg,
246 "SpatialStatistics detected a numerical error writing:\n"
247 "\t%s for bin %d",
248 dat->title.c_str(), bin);
249 painCave.isFatal = 1;
250 simError();
251 }
252 if (dat->dataHandling == odhTotal) v *= dat->accumulator[bin]->count();
253 os << "\t" << v[0] << "\t" << v[1] << "\t" << v[2];
254 }
255 }
256
257 void SpatialStatistics::writeStdDev(ostream& os, OutputData* dat,
258 unsigned int bin) {
259 assert(int(bin) < nBins_);
260 int n = dat->accumulator[bin]->count();
261 if (n == 0) return;
262
263 RealType r;
264 Vector3d v;
265
266 if( dat->dataType == odtReal ) {
267 dynamic_cast<Accumulator*>(dat->accumulator[bin])->getStdDev(r);
268 if (isinf(r) || isnan(r) ) {
269 sprintf( painCave.errMsg,
270 "SpatialStatistics detected a numerical error writing:\n"
271 "\tstandard deviation of %s for bin %d",
272 dat->title.c_str(), bin);
273 painCave.isFatal = 1;
274 simError();
275 }
276 if (dat->dataHandling == odhTotal) r *= dat->accumulator[bin]->count();
277 os << "\t" << r;
278
279 } else if ( dat->dataType == odtVector3 ) {
280 dynamic_cast<VectorAccumulator*>(dat->accumulator[bin])->getStdDev(v);
281 if (isinf(v[0]) || isnan(v[0]) ||
282 isinf(v[1]) || isnan(v[1]) ||
283 isinf(v[2]) || isnan(v[2]) ) {
284 sprintf( painCave.errMsg,
285 "SpatialStatistics detected a numerical error writing:\n"
286 "\tstandard deviation of %s for bin %d",
287 dat->title.c_str(), bin);
288 painCave.isFatal = 1;
289 simError();
290 }
291 if (dat->dataHandling == odhTotal) v *= dat->accumulator[bin]->count();
292 os << "\t" << v[0] << "\t" << v[1] << "\t" << v[2];
293 }
294 }
295
296
297 OutputData* SpatialStatistics::beginOutputData(vector<OutputData*>::iterator& i) {
298 i = data_.begin();
299 return i != data_.end()? *i : NULL;
300 }
301
302 OutputData* SpatialStatistics::nextOutputData(vector<OutputData*>::iterator& i){
303 ++i;
304 return i != data_.end()? *i: NULL;
305 }
306
307
308 SlabStatistics::SlabStatistics(SimInfo* info, const string& filename,
309 const string& sele, int nbins) :
310 SpatialStatistics(info, filename, sele, nbins) {
311
312 z_ = new OutputData;
313 z_->units = "Angstroms";
314 z_->title = "Z";
315 z_->dataType = odtReal;
316 z_->dataHandling = odhAverage;
317 z_->accumulator.reserve(nbins);
318 for (int i = 0; i < nbins; i++)
319 z_->accumulator.push_back( new Accumulator() );
320 data_.push_back(z_);
321 }
322
323 void SlabStatistics::processFrame(int istep) {
324 RealType z;
325 hmat_ = currentSnapshot_->getHmat();
326 for (int i = 0; i < nBins_; i++) {
327 z = (((RealType)i + 0.5) / (RealType)nBins_) * hmat_(2,2);
328 dynamic_cast<Accumulator*>(z_->accumulator[i])->add(z);
329 }
330 volume_ = currentSnapshot_->getVolume();
331
332 SpatialStatistics::processFrame(istep);
333 }
334
335 int SlabStatistics::getBin(Vector3d pos) {
336 currentSnapshot_->wrapVector(pos);
337 // which bin is this stuntdouble in?
338 // wrapped positions are in the range [-0.5*hmat(2,2), +0.5*hmat(2,2)]
339 // Shift molecules by half a box to have bins start at 0
340 // The modulo operator is used to wrap the case when we are
341 // beyond the end of the bins back to the beginning.
342 return int(nBins_ * (pos.z() / hmat_(2,2) + 0.5)) % nBins_;
343 }
344
345
346 ShellStatistics::ShellStatistics(SimInfo* info, const string& filename,
347 const string& sele, int nbins) :
348 SpatialStatistics(info, filename, sele, nbins){
349
350 coordinateOrigin_ = V3Zero;
351 binWidth_ = 1.0;
352
353 r_ = new OutputData;
354 r_->units = "Angstroms";
355 r_->title = "R";
356 r_->dataType = odtReal;
357 r_->dataHandling = odhAverage;
358 r_->accumulator.reserve(nbins);
359 for (int i = 0; i < nbins; i++)
360 r_->accumulator.push_back( new Accumulator() );
361 data_.push_back(r_);
362
363 for (int i = 0; i < nbins; i++) {
364 RealType r = (((RealType)i + 0.5) * binWidth_);
365 dynamic_cast<Accumulator*>(r_->accumulator[i])->add(r);
366 }
367 }
368
369 int ShellStatistics::getBin(Vector3d pos) {
370 Vector3d rPos = pos - coordinateOrigin_;
371 return int(rPos.length() / binWidth_);
372 }
373 }
374

Properties

Name Value
svn:eol-style native