ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/staticProps/GofRAngle.cpp
Revision: 2023
Committed: Thu Oct 2 14:35:14 2014 UTC (10 years, 7 months ago) by gezelter
File size: 13552 byte(s)
Log Message:
Added 3rd selection option for the 2d g(r) analyzers

File Contents

# User Rev Content
1 tim 309 /*
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 gezelter 1390 * 1. Redistributions of source code must retain the above copyright
10 tim 309 * notice, this list of conditions and the following disclaimer.
11     *
12 gezelter 1390 * 2. Redistributions in binary form must reproduce the above copyright
13 tim 309 * 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 gezelter 1390 *
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 gezelter 1879 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 gezelter 1782 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 tim 309 */
42    
43     #include <algorithm>
44     #include <fstream>
45     #include "applications/staticProps/GofRAngle.hpp"
46 gezelter 1879 #include "primitives/Atom.hpp"
47     #include "types/MultipoleAdapter.hpp"
48 tim 309 #include "utils/simError.h"
49    
50 gezelter 1390 namespace OpenMD {
51 gezelter 2023
52     GofRAngle::GofRAngle(SimInfo* info, const std::string& filename,
53     const std::string& sele1,
54     const std::string& sele2,
55     RealType len, int nrbins, int nangleBins)
56     : RadialDistrFunc(info, filename, sele1, sele2), len_(len),
57     nRBins_(nrbins), nAngleBins_(nangleBins), evaluator3_(info),
58     seleMan3_(info), doSele3_(false) {
59    
60     deltaR_ = len_ /(double) nRBins_;
61     deltaCosAngle_ = 2.0 / (double)nAngleBins_;
62     histogram_.resize(nRBins_);
63     avgGofr_.resize(nRBins_);
64     for (int i = 0 ; i < nRBins_; ++i) {
65     histogram_[i].resize(nAngleBins_);
66     avgGofr_[i].resize(nAngleBins_);
67     }
68     }
69    
70     GofRAngle::GofRAngle(SimInfo* info, const std::string& filename,
71     const std::string& sele1,
72     const std::string& sele2,
73     const std::string& sele3,
74     RealType len, int nrbins, int nangleBins)
75     : RadialDistrFunc(info, filename, sele1, sele2), len_(len),
76     nRBins_(nrbins), nAngleBins_(nangleBins), selectionScript3_(sele3),
77     evaluator3_(info), seleMan3_(info), doSele3_(true) {
78 tim 309
79 gezelter 2023 deltaR_ = len_ /(double) nRBins_;
80     deltaCosAngle_ = 2.0 / (double)nAngleBins_;
81     histogram_.resize(nRBins_);
82     avgGofr_.resize(nRBins_);
83     for (int i = 0 ; i < nRBins_; ++i) {
84     histogram_[i].resize(nAngleBins_);
85     avgGofr_[i].resize(nAngleBins_);
86     }
87 tim 309
88 gezelter 2023 evaluator3_.loadScriptString(sele3);
89     if (!evaluator3_.isDynamic()) {
90     seleMan3_.setSelectionSet(evaluator3_.evaluate());
91     }
92    
93     }
94    
95     void GofRAngle::processNonOverlapping( SelectionManager& sman1,
96     SelectionManager& sman2) {
97     StuntDouble* sd1;
98     StuntDouble* sd2;
99     StuntDouble* sd3;
100     int i;
101     int j;
102     int k;
103    
104     // This is the same as a non-overlapping pairwise loop structure:
105     // for (int i = 0; i < ni ; ++i ) {
106     // for (int j = 0; j < nj; ++j) {}
107     // }
108    
109     if (doSele3_) {
110     if (evaluator3_.isDynamic()) {
111     seleMan3_.setSelectionSet(evaluator3_.evaluate());
112 gezelter 507 }
113 gezelter 2023 if (sman1.getSelectionCount() != seleMan3_.getSelectionCount() ) {
114     RadialDistrFunc::processNonOverlapping( sman1, sman2 );
115     }
116    
117     for (sd1 = sman1.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
118     sd1 != NULL && sd3 != NULL;
119     sd1 = sman1.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
120     for (sd2 = sman2.beginSelected(j); sd2 != NULL;
121     sd2 = sman2.nextSelected(j)) {
122     collectHistogram(sd1, sd2, sd3);
123     }
124     }
125     } else {
126     RadialDistrFunc::processNonOverlapping( sman1, sman2 );
127 tim 354 }
128 gezelter 2023 }
129 tim 309
130 gezelter 2023 void GofRAngle::processOverlapping( SelectionManager& sman) {
131     StuntDouble* sd1;
132     StuntDouble* sd2;
133     StuntDouble* sd3;
134     int i;
135     int j;
136     int k;
137 tim 309
138 gezelter 2023 // This is the same as a pairwise loop structure:
139     // for (int i = 0; i < n-1 ; ++i ) {
140     // for (int j = i + 1; j < n; ++j) {}
141     // }
142    
143     if (doSele3_) {
144     if (evaluator3_.isDynamic()) {
145     seleMan3_.setSelectionSet(evaluator3_.evaluate());
146     }
147     if (sman.getSelectionCount() != seleMan3_.getSelectionCount() ) {
148     RadialDistrFunc::processOverlapping( sman);
149     }
150     for (sd1 = sman.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
151     sd1 != NULL && sd3 != NULL;
152     sd1 = sman.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
153     for (j = i, sd2 = sman.nextSelected(j); sd2 != NULL;
154     sd2 = sman.nextSelected(j)) {
155     collectHistogram(sd1, sd2, sd3);
156     }
157     }
158     } else {
159     RadialDistrFunc::processOverlapping( sman);
160     }
161     }
162    
163    
164 gezelter 507 void GofRAngle::preProcess() {
165 gezelter 1782 for (unsigned int i = 0; i < avgGofr_.size(); ++i) {
166 gezelter 507 std::fill(avgGofr_[i].begin(), avgGofr_[i].end(), 0);
167 tim 310 }
168 gezelter 507 }
169 tim 309
170 jmichalk 1785 void GofRAngle::initializeHistogram() {
171 tim 309 npairs_ = 0;
172 gezelter 1782 for (unsigned int i = 0; i < histogram_.size(); ++i){
173 gezelter 507 std::fill(histogram_[i].begin(), histogram_[i].end(), 0);
174 xsun 1213 }
175 gezelter 507 }
176 tim 309
177 gezelter 507 void GofRAngle::processHistogram() {
178 tim 353 int nPairs = getNPairs();
179 tim 963 RealType volume = info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
180     RealType pairDensity = nPairs /volume;
181     RealType pairConstant = ( 4.0 * NumericConstant::PI * pairDensity ) / 3.0;
182 tim 309
183 gezelter 1782 for(unsigned int i = 0 ; i < histogram_.size(); ++i){
184 tim 309
185 tim 963 RealType rLower = i * deltaR_;
186     RealType rUpper = rLower + deltaR_;
187 gezelter 2023 RealType volSlice = ( rUpper * rUpper * rUpper ) -
188     ( rLower * rLower * rLower );
189 tim 963 RealType nIdeal = volSlice * pairConstant;
190 tim 309
191 gezelter 1782 for (unsigned int j = 0; j < histogram_[i].size(); ++j){
192 gezelter 507 avgGofr_[i][j] += histogram_[i][j] / nIdeal;
193     }
194 tim 309 }
195    
196 gezelter 507 }
197 tim 309
198 gezelter 507 void GofRAngle::collectHistogram(StuntDouble* sd1, StuntDouble* sd2) {
199 tim 309
200     if (sd1 == sd2) {
201 gezelter 507 return;
202 tim 309 }
203     Vector3d pos1 = sd1->getPos();
204     Vector3d pos2 = sd2->getPos();
205 tim 361 Vector3d r12 = pos2 - pos1;
206 gezelter 1078 if (usePeriodicBoundaryConditions_)
207     currentSnapshot_->wrapVector(r12);
208 tim 309
209 tim 963 RealType distance = r12.length();
210 gezelter 1790 int whichRBin = int(distance / deltaR_);
211 tim 309
212 tim 328 if (distance <= len_) {
213 xsun 1213
214 tim 963 RealType cosAngle = evaluateAngle(sd1, sd2);
215     RealType halfBin = (nAngleBins_ - 1) * 0.5;
216 gezelter 1790 int whichThetaBin = int(halfBin * (cosAngle + 1.0));
217 gezelter 507 ++histogram_[whichRBin][whichThetaBin];
218 tim 328
219 gezelter 507 ++npairs_;
220 tim 328 }
221 gezelter 507 }
222 tim 309
223 gezelter 2023 void GofRAngle::collectHistogram(StuntDouble* sd1, StuntDouble* sd2,
224     StuntDouble* sd3) {
225    
226     if (sd1 == sd2) {
227     return;
228     }
229    
230     Vector3d p1 = sd1->getPos();
231     Vector3d p3 = sd3->getPos();
232    
233     Vector3d c = 0.5 * (p1 + p3);
234     Vector3d r13 = p3 - p1;
235    
236     Vector3d r12 = sd2->getPos() - c;
237    
238     if (usePeriodicBoundaryConditions_) {
239     currentSnapshot_->wrapVector(r12);
240     currentSnapshot_->wrapVector(r13);
241     }
242    
243     RealType distance = r12.length();
244     int whichRBin = int(distance / deltaR_);
245    
246     if (distance <= len_) {
247    
248     RealType cosAngle = evaluateAngle(sd1, sd2, sd3);
249     RealType halfBin = (nAngleBins_ - 1) * 0.5;
250     int whichThetaBin = int(halfBin * (cosAngle + 1.0));
251     ++histogram_[whichRBin][whichThetaBin];
252    
253     ++npairs_;
254     }
255     }
256    
257 gezelter 507 void GofRAngle::writeRdf() {
258 tim 309 std::ofstream rdfStream(outputFilename_.c_str());
259     if (rdfStream.is_open()) {
260 gezelter 507 rdfStream << "#radial distribution function\n";
261     rdfStream << "#selection1: (" << selectionScript1_ << ")\t";
262 gezelter 2023 rdfStream << "selection2: (" << selectionScript2_ << ")";
263     if (doSele3_) {
264     rdfStream << "\tselection3: (" << selectionScript3_ << ")\n";
265     } else {
266     rdfStream << "\n";
267     }
268     rdfStream << "#nRBins = " << nRBins_ << "\tmaxLen = "
269     << len_ << "\tdeltaR = " << deltaR_ <<"\n";
270     rdfStream << "#nAngleBins =" << nAngleBins_ << "\tdeltaCosAngle = "
271     << deltaCosAngle_ << "\n";
272 gezelter 1782 for (unsigned int i = 0; i < avgGofr_.size(); ++i) {
273 gezelter 1796 // RealType r = deltaR_ * (i + 0.5);
274 tim 309
275 gezelter 1782 for(unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
276 gezelter 1796 // RealType cosAngle = -1.0 + (j + 0.5)*deltaCosAngle_;
277 gezelter 507 rdfStream << avgGofr_[i][j]/nProcessed_ << "\t";
278     }
279 tim 360
280 gezelter 507 rdfStream << "\n";
281     }
282 tim 309
283     } else {
284 gezelter 2023 sprintf(painCave.errMsg, "GofRAngle: unable to open %s\n",
285     outputFilename_.c_str());
286 gezelter 507 painCave.isFatal = 1;
287     simError();
288 tim 309 }
289    
290     rdfStream.close();
291 gezelter 507 }
292 tim 309
293 tim 963 RealType GofRTheta::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2) {
294 tim 309 Vector3d pos1 = sd1->getPos();
295     Vector3d pos2 = sd2->getPos();
296 tim 361 Vector3d r12 = pos2 - pos1;
297 xsun 1213
298 gezelter 1078 if (usePeriodicBoundaryConditions_)
299     currentSnapshot_->wrapVector(r12);
300    
301 tim 309 r12.normalize();
302 gezelter 1879
303 gezelter 1968 Vector3d vec;
304    
305 gezelter 2023 if (!sd1->isDirectional()) {
306     sprintf(painCave.errMsg,
307     "GofRTheta: attempted to use a non-directional object: %s\n",
308     sd1->getType().c_str());
309     painCave.isFatal = 1;
310     simError();
311     }
312    
313 gezelter 1968 if (sd1->isAtom()) {
314     AtomType* atype1 = static_cast<Atom*>(sd1)->getAtomType();
315     MultipoleAdapter ma1 = MultipoleAdapter(atype1);
316    
317     if (ma1.isDipole() )
318     vec = sd1->getDipole();
319     else
320     vec = sd1->getA().transpose() * V3Z;
321     } else {
322 gezelter 1879 vec = sd1->getA().transpose() * V3Z;
323 gezelter 1968 }
324    
325 gezelter 1879 vec.normalize();
326 gezelter 1968
327 gezelter 1879 return dot(r12, vec);
328 gezelter 507 }
329 tim 309
330 gezelter 2023 RealType GofRTheta::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2,
331     StuntDouble* sd3) {
332     Vector3d p1 = sd1->getPos();
333     Vector3d p3 = sd3->getPos();
334    
335     Vector3d c = 0.5 * (p1 + p3);
336     Vector3d r13 = p3 - p1;
337    
338     Vector3d r12 = sd2->getPos() - c;
339    
340     if (usePeriodicBoundaryConditions_) {
341     currentSnapshot_->wrapVector(r12);
342     currentSnapshot_->wrapVector(r13);
343     }
344    
345     r12.normalize();
346     r13.normalize();
347    
348     return dot(r12, r13);
349     }
350    
351 tim 963 RealType GofROmega::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2) {
352 gezelter 1879 Vector3d v1, v2;
353    
354 gezelter 2023 if (!sd1->isDirectional()) {
355     sprintf(painCave.errMsg,
356     "GofROmega: attempted to use a non-directional object: %s\n",
357     sd1->getType().c_str());
358     painCave.isFatal = 1;
359     simError();
360     }
361    
362 gezelter 1968 if (sd1->isAtom()){
363     AtomType* atype1 = static_cast<Atom*>(sd1)->getAtomType();
364     MultipoleAdapter ma1 = MultipoleAdapter(atype1);
365     if (ma1.isDipole() )
366     v1 = sd1->getDipole();
367     else
368     v1 = sd1->getA().transpose() * V3Z;
369     } else {
370 gezelter 1879 v1 = sd1->getA().transpose() * V3Z;
371 gezelter 1968 }
372    
373 gezelter 2023 if (!sd2->isDirectional()) {
374     sprintf(painCave.errMsg,
375     "GofROmega attempted to use a non-directional object: %s\n",
376     sd2->getType().c_str());
377     painCave.isFatal = 1;
378     simError();
379     }
380    
381 gezelter 1968 if (sd2->isAtom()) {
382     AtomType* atype2 = static_cast<Atom*>(sd2)->getAtomType();
383     MultipoleAdapter ma2 = MultipoleAdapter(atype2);
384    
385     if (ma2.isDipole() )
386     v2 = sd2->getDipole();
387     else
388     v2 = sd2->getA().transpose() * V3Z;
389     } else {
390 gezelter 1879 v2 = sd2->getA().transpose() * V3Z;
391 gezelter 1968 }
392    
393 tim 311 v1.normalize();
394     v2.normalize();
395     return dot(v1, v2);
396 gezelter 507 }
397 tim 309
398 gezelter 2023 RealType GofROmega::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2,
399     StuntDouble* sd3) {
400 tim 309
401 gezelter 2023 Vector3d v1;
402     Vector3d v2;
403    
404     v1 = sd3->getPos() - sd1->getPos();
405     if (usePeriodicBoundaryConditions_)
406     currentSnapshot_->wrapVector(v1);
407    
408     if (!sd2->isDirectional()) {
409     sprintf(painCave.errMsg,
410     "GofROmega: attempted to use a non-directional object: %s\n",
411     sd2->getType().c_str());
412     painCave.isFatal = 1;
413     simError();
414     }
415    
416     if (sd2->isAtom()) {
417     AtomType* atype2 = static_cast<Atom*>(sd2)->getAtomType();
418     MultipoleAdapter ma2 = MultipoleAdapter(atype2);
419    
420     if (ma2.isDipole() )
421     v2 = sd2->getDipole();
422     else
423     v2 = sd2->getA().transpose() * V3Z;
424     } else {
425     v2 = sd2->getA().transpose() * V3Z;
426     }
427    
428     v1.normalize();
429     v2.normalize();
430     return dot(v1, v2);
431     }
432 tim 309 }
433    
434    

Properties

Name Value
svn:keywords Author Id Revision Date