45#include "applications/staticProps/KirkwoodBuff.hpp"
53#include "utils/Revision.hpp"
54#include "utils/simError.h"
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");
67 deltaR_ = len_ / (nBins_ - 1);
69 histograms_.resize(MaxPairs);
70 gofrs_.resize(MaxPairs);
71 gCorr_.resize(MaxPairs);
74 for (std::size_t i {}; i < MaxPairs; ++i) {
75 histograms_[i].resize(nBins_);
76 gofrs_[i].resize(nBins_);
77 gCorr_[i].resize(nBins_);
81 std::stringstream params;
82 params <<
" len = " << len_ <<
", nrbins = " << nBins_;
83 const std::string paramString = params.str();
84 setParameterString(paramString);
87 void KirkwoodBuff::initializeHistograms() {
88 for (
auto& pair : histograms_)
89 std::fill(pair.begin(), pair.end(), 0);
92 void KirkwoodBuff::collectHistograms(StuntDouble* sd1, StuntDouble* sd2,
94 if (sd1 == sd2) {
return; }
96 bool usePeriodicBoundaryConditions_ =
97 info_->getSimParams()->getUsePeriodicBoundaryConditions();
99 Vector3d pos1 = sd1->getPos();
100 Vector3d pos2 = sd2->getPos();
101 Vector3d r12 = pos2 - pos1;
102 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
107 if (distance < (len_ + deltaR_)) {
108 int whichBin =
static_cast<int>(
distance / deltaR_);
109 histograms_[pairIndex][whichBin] += 1;
113 void KirkwoodBuff::processHistograms() {
114 std::vector<int> nPairs = getNPairs();
116 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
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;
129 gofrs_[i][j] += histograms_[i][j] / nIdeal;
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_;
140 meanVol_ /= nProcessed_;
142 std::vector<int> Ns(MaxPairs);
143 Ns[OneOne] = getNSelected1();
144 Ns[OneTwo] = getNSelected2();
145 Ns[TwoTwo] = getNSelected2();
147 std::vector<int> kd(MaxPairs);
152 std::vector<RealType> rho(MaxPairs);
153 rho[OneOne] = Ns[OneOne] / meanVol_;
154 rho[OneTwo] = Ns[OneTwo] / meanVol_;
155 rho[TwoTwo] = Ns[TwoTwo] / meanVol_;
157 std::vector<std::vector<RealType>> deltaN;
158 deltaN.resize(MaxPairs);
159 for (
auto& elem : deltaN)
162 for (std::size_t i {}; i < deltaN.size(); ++i) {
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_;
172 4.0 * Constants::PI * r * r * (1 - 3 * x / 2 + std::pow(x, 3) / 2);
174 deltaN[i][j] += deltaN[i][j - 1] + 4.0 * Constants::PI * r * r *
175 rho[i] * (gofrs_[i][j] - 1) *
177 gCorr_[i][j] = gofrs_[i][j] * (Ns[i] * (1 - V / meanVol_)) /
178 (Ns[i] * (1 - V / meanVol_) - deltaN[i][j] - kd[i]);
180 G_[i][j] += G_[i][j - 1] + (gCorr_[i][j] - 1) * w * deltaR_;
185 void KirkwoodBuff::writeRdf() {
186 std::ofstream ofs(outputFilename_.c_str());
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";
197 std::vector<std::string> labels {
"g11",
"g12",
"g22",
"gC11",
"gC12",
198 "gC22",
"G11",
"G12",
"G22"};
202 for (
const auto& label : labels)
203 ofs <<
"\t" << std::setw(15) << label;
207 for (
unsigned int j = 0; j < nBins_; ++j) {
208 RealType r = deltaR_ * j;
210 for (
unsigned int i = 0; i < MaxPairs; ++i) {
211 ofs <<
"\t" << std::setw(15) << gofrs_[i][j];
213 for (
unsigned int i = 0; i < MaxPairs; ++i) {
214 ofs <<
"\t" << std::setw(15) << gCorr_[i][j];
216 for (
unsigned int i = 0; i < MaxPairs; ++i) {
217 ofs <<
"\t" << std::setw(15) << G_[i][j];
222 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
223 "KirkwoodBuff: unable to open %s\n", outputFilename_.c_str());
224 painCave.isFatal = 1;
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.