ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/staticProps/NitrileFrequencyMap.cpp
Revision: 1994
Committed: Wed Apr 30 18:50:45 2014 UTC (11 years ago) by gezelter
File size: 9528 byte(s)
Log Message:
Added NitrileFrequencyMap module to staticProps

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 * [4] , Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011). *
41 */
42
43 #include <algorithm>
44 #include <fstream>
45 #include "applications/staticProps/NitrileFrequencyMap.hpp"
46 #include "utils/simError.h"
47 #include "io/DumpReader.hpp"
48 #include "primitives/Molecule.hpp"
49 #include "brains/Thermo.hpp"
50
51 namespace OpenMD {
52
53 NitrileFrequencyMap::NitrileFrequencyMap(SimInfo* info,
54 const std::string& filename,
55 const std::string& sele1,
56 int nbins)
57 : StaticAnalyser(info, filename), selectionScript1_(sele1),
58 evaluator1_(info), seleMan1_(info), nBins_(nbins), info_(info) {
59
60 setOutputName(getPrefix(filename) + ".freqs");
61
62 evaluator1_.loadScriptString(sele1);
63 if (!evaluator1_.isDynamic()) {
64 seleMan1_.setSelectionSet(evaluator1_.evaluate());
65 }
66
67 count_.resize(nBins_);
68 histogram_.resize(nBins_);
69
70 freqs_.resize(info_->getNGlobalMolecules());
71
72 minFreq_ = -50;
73 maxFreq_ = 50;
74
75 // Values from Choi et. al. "Nitrile and thiocyanate IR probes:
76 // Quantum chemistry calculation studies and multivariate
77 // least-square fitting analysis," J. Chem. Phys. 128, 134506 (2008).
78 //
79 // These map site electrostatic potentials onto frequency shifts
80 // in the same energy units that one computes the total potential.
81
82 frequencyMap_["CN"] = 0.0801;
83 frequencyMap_["NC"] = 0.00521;
84 frequencyMap_["RCHar3"] = -0.00182;
85 frequencyMap_["SigmaN"] = 0.00157;
86 frequencyMap_["PiN"] = -0.00167;
87 frequencyMap_["PiC"] = -0.00896;
88
89 ForceField* forceField_ = info_->getForceField();
90 set<AtomType*> atypes = info_->getSimulatedAtomTypes();
91 PairList* excludes = info_->getExcludedInteractions();
92 int nAtoms = info->getSnapshotManager()->getCurrentSnapshot()->getNumberOfAtoms();
93
94 RealType rcut;
95 if (info_->getSimParams()->haveCutoffRadius()) {
96 rcut = info_->getSimParams()->getCutoffRadius();
97 } else {
98 rcut = 12.0;
99 }
100
101 EF_ = V3Zero;
102
103 if (info_->getSimParams()->haveElectricField())
104 EF_ = info_->getSimParams()->getElectricField();
105
106 excludesForAtom.clear();
107 excludesForAtom.resize(nAtoms);
108
109 for (int i = 0; i < nAtoms; i++) {
110 for (int j = 0; j < nAtoms; j++) {
111 if (excludes->hasPair(i, j))
112 excludesForAtom[i].push_back(j);
113 }
114 }
115
116 electrostatic_ = new Electrostatic();
117 electrostatic_->setSimInfo(info_);
118 electrostatic_->setForceField(forceField_);
119 electrostatic_->setSimulatedAtomTypes(atypes);
120 electrostatic_->setCutoffRadius(rcut);
121 }
122
123 bool NitrileFrequencyMap::excludeAtomPair(int atom1, int atom2) {
124
125 for (vector<int>::iterator i = excludesForAtom[atom1].begin();
126 i != excludesForAtom[atom1].end(); ++i) {
127 if ( (*i) == atom2 ) return true;
128 }
129
130 return false;
131 }
132
133 void NitrileFrequencyMap::process() {
134 Molecule* mol;
135 RigidBody* rb;
136 Atom* atom;
137 AtomType* atype;
138 SimInfo::MoleculeIterator mi;
139 Molecule::RigidBodyIterator rbIter;
140 Molecule::AtomIterator ai2;
141 Atom* atom2;
142 StuntDouble* sd1;
143 int ii, sdID, molID, sdID2;
144 RealType li;
145 RealType sPot, s1, s2;
146 RealType freqShift;
147 std::string name;
148 map<string,RealType>::iterator fi;
149 bool excluded;
150 const RealType chrgToKcal = 23.0609;
151
152 DumpReader reader(info_, dumpFilename_);
153 int nFrames = reader.getNFrames();
154
155 nProcessed_ = nFrames/step_;
156
157 std::fill(histogram_.begin(), histogram_.end(), 0.0);
158 std::fill(count_.begin(), count_.end(), 0);
159
160 for (int istep = 0; istep < nFrames; istep += step_) {
161 reader.readFrame(istep);
162 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
163
164 std::fill(freqs_.begin(), freqs_.end(), 0.0);
165
166 for (mol = info_->beginMolecule(mi); mol != NULL;
167 mol = info_->nextMolecule(mi)) {
168 //change the positions of atoms which belong to the rigidbodies
169 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
170 rb = mol->nextRigidBody(rbIter)) {
171 rb->updateAtoms();
172 }
173 }
174
175 if (evaluator1_.isDynamic()) {
176 seleMan1_.setSelectionSet(evaluator1_.evaluate());
177 }
178
179 for (sd1 = seleMan1_.beginSelected(ii);
180 sd1 != NULL;
181 sd1 = seleMan1_.nextSelected(ii)) {
182
183 sdID = sd1->getGlobalIndex();
184 molID = info_->getGlobalMolMembership(sdID);
185 mol = info_->getMoleculeByGlobalIndex(molID);
186
187 Vector3d CNcentroid = mol->getRigidBodyAt(2)->getPos();
188 Vector3d ra = sd1->getPos();
189
190 atom = dynamic_cast<Atom *>(sd1);
191 atype = atom->getAtomType();
192 name = atype->getName();
193 fi = frequencyMap_.find(name);
194 if ( fi != frequencyMap_.end() ) {
195 li = (*fi).second;
196 } else {
197 // throw error
198 sprintf( painCave.errMsg,
199 "NitrileFrequencyMap::process: Unknown atype requested.\n"
200 "\t(Selection specified %s .)\n",
201 name.c_str() );
202 painCave.isFatal = 1;
203 simError();
204 }
205
206 sPot = sd1->getSitePotential();
207
208 // Subtract out the contribution from every other site on this molecule:
209 for(atom2 = mol->beginAtom(ai2); atom2 != NULL;
210 atom2 = mol->nextAtom(ai2)) {
211
212 sdID2 = atom2->getGlobalIndex();
213 if (sdID == sdID2) {
214 excluded = true;
215 } else {
216 excluded = excludeAtomPair(sdID, sdID2);
217 }
218
219 electrostatic_->getSitePotentials(atom, atom2, excluded, s1, s2);
220
221 sPot -= s1;
222 }
223
224 // Add the contribution from the electric field:
225
226 sPot += dot(EF_, ra - CNcentroid) * chrgToKcal ;
227
228 freqShift = sPot * li;
229
230 // convert the kcal/mol energies to wavenumbers:
231 freqShift *= 349.757;
232
233 freqs_[molID] += freqShift;
234 }
235
236 for (int i = 0; i < info_->getNGlobalMolecules(); ++i) {
237 int binNo = int(nBins_ * (freqs_[i] - minFreq_)/(maxFreq_-minFreq_));
238
239 count_[binNo]++;
240 }
241 }
242
243 processHistogram();
244 writeProbs();
245
246 }
247
248 void NitrileFrequencyMap::processHistogram() {
249
250 int atot = 0;
251 for(unsigned int i = 0; i < count_.size(); ++i)
252 atot += count_[i];
253
254 for(unsigned int i = 0; i < count_.size(); ++i) {
255 histogram_[i] = double(count_[i] / double(atot));
256 }
257 }
258
259 void NitrileFrequencyMap::writeProbs() {
260
261 std::ofstream rdfStream(outputFilename_.c_str());
262 if (rdfStream.is_open()) {
263 rdfStream << "#NitrileFrequencyMap\n";
264 rdfStream << "#nFrames:\t" << nProcessed_ << "\n";
265 rdfStream << "#selection1: (" << selectionScript1_ << ")";
266 rdfStream << "\n";
267 rdfStream << "#nu\tp(nu))\n";
268 for (unsigned int i = 0; i < histogram_.size(); ++i) {
269 RealType freq = minFreq_ + (RealType)(i)*(maxFreq_-minFreq_) /
270 (RealType)histogram_.size();
271 rdfStream << freq << "\t" << histogram_[i] << "\n";
272 }
273
274 } else {
275
276 sprintf(painCave.errMsg, "NitrileFrequencyMap: unable to open %s\n",
277 outputFilename_.c_str());
278 painCave.isFatal = 1;
279 simError();
280 }
281
282 rdfStream.close();
283 }
284
285 }
286

Properties

Name Value
svn:eol-style native