48#include "applications/staticProps/BOPofR.hpp"
50#include "brains/Thermo.hpp"
52#include "math/Wigner3jm.hpp"
54#include "utils/Constants.hpp"
55#include "utils/Revision.hpp"
56#include "utils/simError.h"
58using namespace MATPACK;
61 BOPofR::BOPofR(
SimInfo* info,
const std::string& filename,
62 const std::string& sele,
double rCut,
unsigned int nbins,
65 selectionScript_(sele), seleMan_(info), evaluator_(info) {
66 setOutputName(
getPrefix(filename) +
".bo");
67 setAnalysisType(
"Bond Order Parameter(r)");
69 evaluator_.loadScriptString(sele);
70 if (!evaluator_.isDynamic()) {
71 seleMan_.setSelectionSet(evaluator_.evaluate());
79 std::stringstream params;
80 params <<
" rcut = " << rCut_ <<
", len = " << len_
81 <<
", nbins = " << nBins_;
82 const std::string paramString = params.str();
83 setParameterString(paramString);
85 deltaR_ = len_ / nBins_;
86 RCount_.resize(nBins_);
90 for (
unsigned int i = 0; i < nBins_; i++) {
97 RealType* THRCOF =
new RealType[2 * lMax_ + 1];
99 RealType lPass, m1Pass, m2m, m2M;
101 mSize = 2 * lMax_ + 1;
103 for (
int l = 0; l <= lMax_; l++) {
105 for (
int m1 = -l; m1 <= l; m1++) {
106 m1Pass = (RealType)m1;
108 std::pair<int, int> lm = std::make_pair(l, m1);
111 for (
int ii = 0; ii < 2 * l + 1; ii++) {
116 Wigner3jm(lPass, lPass, lPass, m1Pass, m2m, m2M, THRCOF, mSize, error);
118 m2Min[lm] = (int)floor(m2m);
119 m2Max[lm] = (int)floor(m2M);
121 for (
int mmm = 0; mmm <= (int)(m2M - m2m); mmm++) {
122 w3j[lm].push_back(THRCOF[mmm]);
131 void BOPofR::initializeHistogram() {
132 for (
unsigned int i = 0; i < nBins_; i++) {
139 void BOPofR::process() {
143 SimInfo::MoleculeIterator mi;
144 Molecule::AtomIterator ai;
153 Vector3d CenterOfMass;
154 std::map<std::pair<int, int>, ComplexType> q;
155 std::vector<RealType> q_l;
156 std::vector<RealType> q2;
157 std::vector<ComplexType> w;
158 std::vector<ComplexType> w_hat;
159 std::vector<RealType> Q2;
160 std::vector<RealType> Q;
161 std::vector<ComplexType> W;
162 std::vector<ComplexType> W_hat;
164 SphericalHarmonic sphericalHarmonic;
166 bool usePeriodicBoundaryConditions_ =
167 info_->getSimParams()->getUsePeriodicBoundaryConditions();
169 DumpReader reader(info_, dumpFilename_);
170 int nFrames = reader.getNFrames();
173 Thermo thermo(info_);
175 q_l.resize(lMax_ + 1);
176 q2.resize(lMax_ + 1);
178 w_hat.resize(lMax_ + 1);
180 Q2.resize(lMax_ + 1);
183 W_hat.resize(lMax_ + 1);
185 for (
int istep = 0; istep < nFrames; istep += step_) {
186 reader.readFrame(istep);
188 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
189 CenterOfMass = thermo.getCom();
190 if (evaluator_.isDynamic()) {
191 seleMan_.setSelectionSet(evaluator_.evaluate());
196 for (sd = seleMan_.beginSelected(i); sd != NULL;
197 sd = seleMan_.nextSelected(i)) {
198 myIndex = sd->getGlobalIndex();
202 for (
int l = 0; l <= lMax_; l++) {
203 for (
int m = -l; m <= l; m++) {
204 q[std::make_pair(l, m)] = 0.0;
208 rCOM = CenterOfMass - pos;
209 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(rCOM);
210 distCOM = rCOM.length();
214 for (mol = info_->beginMolecule(mi); mol != NULL;
215 mol = info_->nextMolecule(mi)) {
216 for (atom = mol->beginAtom(ai); atom != NULL;
217 atom = mol->nextAtom(ai)) {
218 if (atom->getGlobalIndex() != myIndex) {
219 vec = pos - atom->getPos();
221 if (usePeriodicBoundaryConditions_)
222 currentSnapshot_->wrapVector(vec);
234 costheta = vec.z() / r;
235 phi = atan2(vec.y(), vec.x());
237 for (
int l = 0; l <= lMax_; l++) {
238 sphericalHarmonic.setL(l);
239 for (
int m = -l; m <= l; m++) {
240 sphericalHarmonic.setM(m);
241 q[std::make_pair(l, m)] +=
242 sphericalHarmonic.getValueAt(costheta, phi);
251 for (
int l = 0; l <= lMax_; l++) {
253 for (
int m = -l; m <= l; m++) {
254 q[std::make_pair(l, m)] /= (RealType)nBonds;
255 q2[l] += norm(q[std::make_pair(l, m)]);
257 q_l[l] = sqrt(q2[l] * 4.0 * Constants::PI / (RealType)(2 * l + 1));
262 for (
int l = 0; l <= lMax_; l++) {
264 for (
int m1 = -l; m1 <= l; m1++) {
265 std::pair<int, int> lm = std::make_pair(l, m1);
266 for (
int mmm = 0; mmm <= (m2Max[lm] - m2Min[lm]); mmm++) {
267 int m2 = m2Min[lm] + mmm;
269 w[l] += w3j[lm][mmm] * q[lm] * q[std::make_pair(l, m2)] *
270 q[std::make_pair(l, m3)];
274 w_hat[l] = w[l] / pow(q2[l], RealType(1.5));
277 collectHistogram(q_l, w_hat, distCOM);
284 writeOrderParameter();
287 IcosahedralOfR::IcosahedralOfR(SimInfo* info,
const std::string& filename,
288 const std::string& sele,
double rCut,
289 unsigned int nbins, RealType len) :
290 BOPofR(info, filename, sele, rCut, nbins, len) {
291 setAnalysisType(
"Icosahedral Bond Order Parameter(r)");
294 void IcosahedralOfR::collectHistogram(std::vector<RealType> q,
295 std::vector<ComplexType> what,
297 if (distCOM < len_) {
299 int whichBin = int(distCOM / deltaR_);
302 if (real(what[6]) < -0.15) { WofR_[whichBin]++; }
303 if (q[6] > 0.5) { QofR_[whichBin]++; }
307 FCCOfR::FCCOfR(SimInfo* info,
const std::string& filename,
308 const std::string& sele,
double rCut,
unsigned int nbins,
310 BOPofR(info, filename, sele, rCut, nbins, len) {
311 setAnalysisType(
"FCC Bond Order Parameter(r)");
314 void FCCOfR::collectHistogram(std::vector<RealType>,
315 std::vector<ComplexType> what,
317 if (distCOM < len_) {
319 int whichBin = int(distCOM / deltaR_);
322 if (real(what[4]) < -0.12) { WofR_[whichBin]++; }
326 void IcosahedralOfR::writeOrderParameter() {
328 std::ofstream osq((getOutputFileName() +
"qr").c_str());
331 osq <<
"# " << getAnalysisType() <<
"\n";
332 osq <<
"# OpenMD " << rev.getFullRevision() <<
"\n";
333 osq <<
"# " << rev.getBuildDate() <<
"\n";
334 osq <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
335 if (!paramString_.empty())
336 osq <<
"# parameters: " << paramString_ <<
"\n";
340 for (
unsigned int i = 0; i < nBins_; ++i) {
341 RealType Rval = (i + 0.5) * deltaR_;
343 if (RCount_[i] == 0) {
347 osq <<
"\t" << (RealType)QofR_[i] / (RealType)RCount_[i];
355 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
356 "IcosahedralOfR: unable to open %s\n",
357 (getOutputFileName() +
"q").c_str());
358 painCave.isFatal = 1;
362 std::ofstream osw((getOutputFileName() +
"wr").c_str());
365 osw <<
"# " << getAnalysisType() <<
"\n";
366 osw <<
"# OpenMD " << rev.getFullRevision() <<
"\n";
367 osw <<
"# " << rev.getBuildDate() <<
"\n";
368 osw <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
369 if (!paramString_.empty())
370 osw <<
"# parameters: " << paramString_ <<
"\n";
373 for (
unsigned int i = 0; i < nBins_; ++i) {
374 RealType Rval = deltaR_ * (i + 0.5);
376 if (RCount_[i] == 0) {
380 osw <<
"\t" << (RealType)WofR_[i] / (RealType)RCount_[i];
387 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
388 "IcosahedralOfR: unable to open %s\n",
389 (getOutputFileName() +
"w").c_str());
390 painCave.isFatal = 1;
394 void FCCOfR::writeOrderParameter() {
395 std::ofstream osw((getOutputFileName() +
"wr").c_str());
399 osw <<
"# " << getAnalysisType() <<
"\n";
400 osw <<
"# OpenMD " << rev.getFullRevision() <<
"\n";
401 osw <<
"# " << rev.getBuildDate() <<
"\n";
402 osw <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
403 if (!paramString_.empty())
404 osw <<
"# parameters: " << paramString_ <<
"\n";
407 for (
unsigned int i = 0; i < nBins_; ++i) {
408 RealType Rval = deltaR_ * (i + 0.5);
410 if (RCount_[i] == 0) {
414 osw <<
"\t" << (RealType)WofR_[i] / (RealType)RCount_[i];
421 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
422 "FCCOfR: unable to open %s\n",
423 (getOutputFileName() +
"w").c_str());
424 painCave.isFatal = 1;
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)