48#include "applications/staticProps/KirkwoodBuff.hpp"
56#include "utils/Revision.hpp"
57#include "utils/simError.h"
61 KirkwoodBuff::KirkwoodBuff(
SimInfo* info,
const std::string& filename,
62 const std::string& sele1,
const std::string& sele2,
63 RealType len,
unsigned int nrbins) :
65 len_ {len}, meanVol_ {0.0} {
66 setAnalysisType(
"Kirkwood-Buff Integrals");
67 setOutputName(
getPrefix(filename) +
".kirkwood-buff");
70 deltaR_ = len_ / (nBins_ - 1);
72 histograms_.resize(MaxPairs);
73 gofrs_.resize(MaxPairs);
74 gCorr_.resize(MaxPairs);
77 for (std::size_t i {}; i < MaxPairs; ++i) {
78 histograms_[i].resize(nBins_);
79 gofrs_[i].resize(nBins_);
80 gCorr_[i].resize(nBins_);
84 std::stringstream params;
85 params <<
" len = " << len_ <<
", nrbins = " << nBins_;
86 const std::string paramString = params.str();
87 setParameterString(paramString);
90 void KirkwoodBuff::initializeHistograms() {
91 for (
auto& pair : histograms_)
92 std::fill(pair.begin(), pair.end(), 0);
95 void KirkwoodBuff::collectHistograms(StuntDouble* sd1, StuntDouble* sd2,
97 if (sd1 == sd2) {
return; }
99 bool usePeriodicBoundaryConditions_ =
100 info_->getSimParams()->getUsePeriodicBoundaryConditions();
102 Vector3d pos1 = sd1->getPos();
103 Vector3d pos2 = sd2->getPos();
104 Vector3d r12 = pos2 - pos1;
105 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
110 if (distance < (len_ + deltaR_)) {
111 int whichBin =
static_cast<int>(
distance / deltaR_);
112 histograms_[pairIndex][whichBin] += 1;
116 void KirkwoodBuff::processHistograms() {
117 std::vector<int> nPairs = getNPairs();
119 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
123 for (std::size_t i {}; i < histograms_.size(); ++i) {
124 for (std::size_t j {}; j < histograms_[i].size(); ++j) {
125 RealType rLower = j * deltaR_;
126 RealType rUpper = rLower + deltaR_;
127 RealType volSlice = 4.0 * Constants::PI *
128 (std::pow(rUpper, 3) - std::pow(rLower, 3)) / 3.0;
129 RealType pairDensity = nPairs[i] / volume;
130 RealType nIdeal = volSlice * pairDensity;
132 gofrs_[i][j] += histograms_[i][j] / nIdeal;
137 void KirkwoodBuff::postProcess() {
138 for (std::size_t i {}; i < gofrs_.size(); ++i) {
139 for (std::size_t j {}; j < gofrs_[i].size(); ++j) {
140 gofrs_[i][j] /= nProcessed_;
143 meanVol_ /= nProcessed_;
145 std::vector<int> Ns(MaxPairs);
146 Ns[OneOne] = getNSelected1();
147 Ns[OneTwo] = getNSelected2();
148 Ns[TwoTwo] = getNSelected2();
150 std::vector<int> kd(MaxPairs);
155 std::vector<RealType> rho(MaxPairs);
156 rho[OneOne] = Ns[OneOne] / meanVol_;
157 rho[OneTwo] = Ns[OneTwo] / meanVol_;
158 rho[TwoTwo] = Ns[TwoTwo] / meanVol_;
160 std::vector<std::vector<RealType>> deltaN;
161 deltaN.resize(MaxPairs);
162 for (
auto& elem : deltaN)
165 for (std::size_t i {}; i < deltaN.size(); ++i) {
170 for (std::size_t j {1}; j < deltaN[i].size(); ++j) {
171 RealType r = deltaR_ * j;
172 RealType V = 4.0 * Constants::PI * r * r * r / 3.0;
173 RealType x = r / len_;
175 4.0 * Constants::PI * r * r * (1 - 3 * x / 2 + std::pow(x, 3) / 2);
177 deltaN[i][j] += deltaN[i][j - 1] + 4.0 * Constants::PI * r * r *
178 rho[i] * (gofrs_[i][j] - 1) *
180 gCorr_[i][j] = gofrs_[i][j] * (Ns[i] * (1 - V / meanVol_)) /
181 (Ns[i] * (1 - V / meanVol_) - deltaN[i][j] - kd[i]);
183 G_[i][j] += G_[i][j - 1] + (gCorr_[i][j] - 1) * w * deltaR_;
188 void KirkwoodBuff::writeRdf() {
189 std::ofstream ofs(outputFilename_.c_str());
192 ofs <<
"# " << getAnalysisType() <<
"\n";
193 ofs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
194 ofs <<
"# " << r.getBuildDate() <<
"\n";
195 ofs <<
"# selection script1: \"" << selectionScript1_;
196 ofs <<
"\"\tselection script2: \"" << selectionScript2_ <<
"\"\n";
197 if (!paramString_.empty())
198 ofs <<
"# parameters: " << paramString_ <<
"\n";
200 std::vector<std::string> labels {
"g11",
"g12",
"g22",
"gC11",
"gC12",
201 "gC22",
"G11",
"G12",
"G22"};
205 for (
const auto& label : labels)
206 ofs <<
"\t" << std::setw(15) << label;
210 for (
unsigned int j = 0; j < nBins_; ++j) {
211 RealType r = deltaR_ * j;
213 for (
unsigned int i = 0; i < MaxPairs; ++i) {
214 ofs <<
"\t" << std::setw(15) << gofrs_[i][j];
216 for (
unsigned int i = 0; i < MaxPairs; ++i) {
217 ofs <<
"\t" << std::setw(15) << gCorr_[i][j];
219 for (
unsigned int i = 0; i < MaxPairs; ++i) {
220 ofs <<
"\t" << std::setw(15) << G_[i][j];
225 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
226 "KirkwoodBuff: unable to open %s\n", outputFilename_.c_str());
227 painCave.isFatal = 1;
Multi-Component Radial Distribution Function.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
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.