OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
KirkwoodBuff.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45#include "applications/staticProps/KirkwoodBuff.hpp"
46
47#include <algorithm>
48#include <cmath>
49#include <fstream>
50#include <iomanip>
51#include <sstream>
52
53#include "utils/Revision.hpp"
54#include "utils/simError.h"
55
56namespace OpenMD {
57
58 KirkwoodBuff::KirkwoodBuff(SimInfo* info, const std::string& filename,
59 const std::string& sele1, const std::string& sele2,
60 RealType len, unsigned int nrbins) :
61 MultiComponentRDF {info, filename, sele1, sele2, nrbins},
62 len_ {len}, meanVol_ {0.0} {
63 setAnalysisType("Kirkwood-Buff Integrals");
64 setOutputName(getPrefix(filename) + ".kirkwood-buff");
65
66 // Bins are set to the inner radius of a spherical shell.
67 deltaR_ = len_ / (nBins_ - 1);
68
69 histograms_.resize(MaxPairs);
70 gofrs_.resize(MaxPairs);
71 gCorr_.resize(MaxPairs);
72 G_.resize(MaxPairs);
73
74 for (std::size_t i {}; i < MaxPairs; ++i) {
75 histograms_[i].resize(nBins_);
76 gofrs_[i].resize(nBins_);
77 gCorr_[i].resize(nBins_);
78 G_[i].resize(nBins_);
79 }
80
81 std::stringstream params;
82 params << " len = " << len_ << ", nrbins = " << nBins_;
83 const std::string paramString = params.str();
84 setParameterString(paramString);
85 }
86
87 void KirkwoodBuff::initializeHistograms() {
88 for (auto& pair : histograms_)
89 std::fill(pair.begin(), pair.end(), 0);
90 }
91
92 void KirkwoodBuff::collectHistograms(StuntDouble* sd1, StuntDouble* sd2,
93 int pairIndex) {
94 if (sd1 == sd2) { return; }
95
96 bool usePeriodicBoundaryConditions_ =
97 info_->getSimParams()->getUsePeriodicBoundaryConditions();
98
99 Vector3d pos1 = sd1->getPos();
100 Vector3d pos2 = sd2->getPos();
101 Vector3d r12 = pos2 - pos1;
102 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
103
104 RealType distance = r12.length();
105
106 // Bins are set to the inner radius of a spherical shell.
107 if (distance < (len_ + deltaR_)) {
108 int whichBin = static_cast<int>(distance / deltaR_);
109 histograms_[pairIndex][whichBin] += 1;
110 }
111 }
112
113 void KirkwoodBuff::processHistograms() {
114 std::vector<int> nPairs = getNPairs();
115 RealType volume =
116 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
117
118 meanVol_ += volume;
119
120 for (std::size_t i {}; i < histograms_.size(); ++i) {
121 for (std::size_t j {}; j < histograms_[i].size(); ++j) {
122 RealType rLower = j * deltaR_;
123 RealType rUpper = rLower + deltaR_;
124 RealType volSlice = 4.0 * Constants::PI *
125 (std::pow(rUpper, 3) - std::pow(rLower, 3)) / 3.0;
126 RealType pairDensity = nPairs[i] / volume;
127 RealType nIdeal = volSlice * pairDensity;
128
129 gofrs_[i][j] += histograms_[i][j] / nIdeal;
130 }
131 }
132 }
133
134 void KirkwoodBuff::postProcess() {
135 for (std::size_t i {}; i < gofrs_.size(); ++i) {
136 for (std::size_t j {}; j < gofrs_[i].size(); ++j) {
137 gofrs_[i][j] /= nProcessed_;
138 }
139 } // g(r) is the uncorrected g(r)
140 meanVol_ /= nProcessed_;
141
142 std::vector<int> Ns(MaxPairs);
143 Ns[OneOne] = getNSelected1();
144 Ns[OneTwo] = getNSelected2();
145 Ns[TwoTwo] = getNSelected2();
146
147 std::vector<int> kd(MaxPairs);
148 kd[OneOne] = 1;
149 kd[OneTwo] = 0;
150 kd[TwoTwo] = 1;
151
152 std::vector<RealType> rho(MaxPairs);
153 rho[OneOne] = Ns[OneOne] / meanVol_;
154 rho[OneTwo] = Ns[OneTwo] / meanVol_;
155 rho[TwoTwo] = Ns[TwoTwo] / meanVol_;
156
157 std::vector<std::vector<RealType>> deltaN;
158 deltaN.resize(MaxPairs);
159 for (auto& elem : deltaN)
160 elem.resize(nBins_);
161
162 for (std::size_t i {}; i < deltaN.size(); ++i) {
163 deltaN[i][0] = 0.0;
164 gCorr_[i][0] = 0.0;
165 G_[i][0] = 0.0;
166
167 for (std::size_t j {1}; j < deltaN[i].size(); ++j) {
168 RealType r = deltaR_ * j;
169 RealType V = 4.0 * Constants::PI * r * r * r / 3.0;
170 RealType x = r / len_;
171 RealType w =
172 4.0 * Constants::PI * r * r * (1 - 3 * x / 2 + std::pow(x, 3) / 2);
173
174 deltaN[i][j] += deltaN[i][j - 1] + 4.0 * Constants::PI * r * r *
175 rho[i] * (gofrs_[i][j] - 1) *
176 deltaR_;
177 gCorr_[i][j] = gofrs_[i][j] * (Ns[i] * (1 - V / meanVol_)) /
178 (Ns[i] * (1 - V / meanVol_) - deltaN[i][j] - kd[i]);
179
180 G_[i][j] += G_[i][j - 1] + (gCorr_[i][j] - 1) * w * deltaR_;
181 }
182 }
183 }
184
185 void KirkwoodBuff::writeRdf() {
186 std::ofstream ofs(outputFilename_.c_str());
187 if (ofs.is_open()) {
188 Revision r;
189 ofs << "# " << getAnalysisType() << "\n";
190 ofs << "# OpenMD " << r.getFullRevision() << "\n";
191 ofs << "# " << r.getBuildDate() << "\n";
192 ofs << "# selection script1: \"" << selectionScript1_;
193 ofs << "\"\tselection script2: \"" << selectionScript2_ << "\"\n";
194 if (!paramString_.empty())
195 ofs << "# parameters: " << paramString_ << "\n";
196
197 std::vector<std::string> labels {"g11", "g12", "g22", "gC11", "gC12",
198 "gC22", "G11", "G12", "G22"};
199
200 ofs << "# r";
201
202 for (const auto& label : labels)
203 ofs << "\t" << std::setw(15) << label;
204
205 ofs << '\n';
206
207 for (unsigned int j = 0; j < nBins_; ++j) {
208 RealType r = deltaR_ * j;
209 ofs << r;
210 for (unsigned int i = 0; i < MaxPairs; ++i) {
211 ofs << "\t" << std::setw(15) << gofrs_[i][j];
212 }
213 for (unsigned int i = 0; i < MaxPairs; ++i) {
214 ofs << "\t" << std::setw(15) << gCorr_[i][j];
215 }
216 for (unsigned int i = 0; i < MaxPairs; ++i) {
217 ofs << "\t" << std::setw(15) << G_[i][j];
218 }
219 ofs << "\n";
220 }
221 } else {
222 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
223 "KirkwoodBuff: unable to open %s\n", outputFilename_.c_str());
224 painCave.isFatal = 1;
225 simError();
226 }
227 ofs.close();
228 }
229} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.