45#include "applications/staticProps/BOPofR.hpp"
47#include "brains/Thermo.hpp"
49#include "math/Wigner3jm.hpp"
51#include "utils/Constants.hpp"
52#include "utils/Revision.hpp"
53#include "utils/simError.h"
55using namespace MATPACK;
58 BOPofR::BOPofR(SimInfo* info,
const std::string& filename,
59 const std::string& sele,
double rCut,
unsigned int nbins,
61 StaticAnalyser(info, filename, nbins),
62 selectionScript_(sele), seleMan_(info), evaluator_(info) {
63 setOutputName(
getPrefix(filename) +
".bo");
64 setAnalysisType(
"Bond Order Parameter(r)");
66 evaluator_.loadScriptString(sele);
67 if (!evaluator_.isDynamic()) {
68 seleMan_.setSelectionSet(evaluator_.evaluate());
76 std::stringstream params;
77 params <<
" rcut = " << rCut_ <<
", len = " << len_
78 <<
", nbins = " << nBins_;
79 const std::string paramString = params.str();
80 setParameterString(paramString);
82 deltaR_ = len_ / nBins_;
83 RCount_.resize(nBins_);
87 for (
unsigned int i = 0; i < nBins_; i++) {
94 RealType* THRCOF =
new RealType[2 * lMax_ + 1];
96 RealType lPass, m1Pass, m2m, m2M;
98 mSize = 2 * lMax_ + 1;
100 for (
int l = 0; l <= lMax_; l++) {
102 for (
int m1 = -l; m1 <= l; m1++) {
103 m1Pass = (RealType)m1;
105 std::pair<int, int> lm = std::make_pair(l, m1);
108 for (
int ii = 0; ii < 2 * l + 1; ii++) {
113 Wigner3jm(lPass, lPass, lPass, m1Pass, m2m, m2M, THRCOF, mSize, error);
115 m2Min[lm] = (int)floor(m2m);
116 m2Max[lm] = (int)floor(m2M);
118 for (
int mmm = 0; mmm <= (int)(m2M - m2m); mmm++) {
119 w3j[lm].push_back(THRCOF[mmm]);
128 void BOPofR::initializeHistogram() {
129 for (
unsigned int i = 0; i < nBins_; i++) {
136 void BOPofR::process() {
140 SimInfo::MoleculeIterator mi;
141 Molecule::AtomIterator ai;
150 Vector3d CenterOfMass;
151 std::map<std::pair<int, int>, ComplexType> q;
152 std::vector<RealType> q_l;
153 std::vector<RealType> q2;
154 std::vector<ComplexType> w;
155 std::vector<ComplexType> w_hat;
156 std::vector<RealType> Q2;
157 std::vector<RealType> Q;
158 std::vector<ComplexType> W;
159 std::vector<ComplexType> W_hat;
161 SphericalHarmonic sphericalHarmonic;
163 bool usePeriodicBoundaryConditions_ =
164 info_->getSimParams()->getUsePeriodicBoundaryConditions();
166 DumpReader reader(info_, dumpFilename_);
167 int nFrames = reader.getNFrames();
170 Thermo thermo(info_);
172 q_l.resize(lMax_ + 1);
173 q2.resize(lMax_ + 1);
175 w_hat.resize(lMax_ + 1);
177 Q2.resize(lMax_ + 1);
180 W_hat.resize(lMax_ + 1);
182 for (
int istep = 0; istep < nFrames; istep += step_) {
183 reader.readFrame(istep);
185 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
186 CenterOfMass = thermo.getCom();
187 if (evaluator_.isDynamic()) {
188 seleMan_.setSelectionSet(evaluator_.evaluate());
193 for (sd = seleMan_.beginSelected(i); sd != NULL;
194 sd = seleMan_.nextSelected(i)) {
195 myIndex = sd->getGlobalIndex();
199 for (
int l = 0; l <= lMax_; l++) {
200 for (
int m = -l; m <= l; m++) {
201 q[std::make_pair(l, m)] = 0.0;
205 rCOM = CenterOfMass - pos;
206 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(rCOM);
207 distCOM = rCOM.length();
211 for (mol = info_->beginMolecule(mi); mol != NULL;
212 mol = info_->nextMolecule(mi)) {
213 for (atom = mol->beginAtom(ai); atom != NULL;
214 atom = mol->nextAtom(ai)) {
215 if (atom->getGlobalIndex() != myIndex) {
216 vec = pos - atom->getPos();
218 if (usePeriodicBoundaryConditions_)
219 currentSnapshot_->wrapVector(vec);
231 costheta = vec.z() / r;
232 phi = atan2(vec.y(), vec.x());
234 for (
int l = 0; l <= lMax_; l++) {
235 sphericalHarmonic.setL(l);
236 for (
int m = -l; m <= l; m++) {
237 sphericalHarmonic.setM(m);
238 q[std::make_pair(l, m)] +=
239 sphericalHarmonic.getValueAt(costheta, phi);
248 for (
int l = 0; l <= lMax_; l++) {
250 for (
int m = -l; m <= l; m++) {
251 q[std::make_pair(l, m)] /= (RealType)nBonds;
252 q2[l] += norm(q[std::make_pair(l, m)]);
254 q_l[l] = sqrt(q2[l] * 4.0 * Constants::PI / (RealType)(2 * l + 1));
259 for (
int l = 0; l <= lMax_; l++) {
261 for (
int m1 = -l; m1 <= l; m1++) {
262 std::pair<int, int> lm = std::make_pair(l, m1);
263 for (
int mmm = 0; mmm <= (m2Max[lm] - m2Min[lm]); mmm++) {
264 int m2 = m2Min[lm] + mmm;
266 w[l] += w3j[lm][mmm] * q[lm] * q[std::make_pair(l, m2)] *
267 q[std::make_pair(l, m3)];
271 w_hat[l] = w[l] / pow(q2[l], RealType(1.5));
274 collectHistogram(q_l, w_hat, distCOM);
281 writeOrderParameter();
284 IcosahedralOfR::IcosahedralOfR(SimInfo* info,
const std::string& filename,
285 const std::string& sele,
double rCut,
286 unsigned int nbins, RealType len) :
287 BOPofR(info, filename, sele, rCut, nbins, len) {
288 setAnalysisType(
"Icosahedral Bond Order Parameter(r)");
291 void IcosahedralOfR::collectHistogram(std::vector<RealType> q,
292 std::vector<ComplexType> what,
294 if (distCOM < len_) {
296 int whichBin = int(distCOM / deltaR_);
299 if (real(what[6]) < -0.15) { WofR_[whichBin]++; }
300 if (q[6] > 0.5) { QofR_[whichBin]++; }
304 FCCOfR::FCCOfR(SimInfo* info,
const std::string& filename,
305 const std::string& sele,
double rCut,
unsigned int nbins,
307 BOPofR(info, filename, sele, rCut, nbins, len) {
308 setAnalysisType(
"FCC Bond Order Parameter(r)");
311 void FCCOfR::collectHistogram(std::vector<RealType>,
312 std::vector<ComplexType> what,
314 if (distCOM < len_) {
316 int whichBin = int(distCOM / deltaR_);
319 if (real(what[4]) < -0.12) { WofR_[whichBin]++; }
323 void IcosahedralOfR::writeOrderParameter() {
325 std::ofstream osq((getOutputFileName() +
"qr").c_str());
328 osq <<
"# " << getAnalysisType() <<
"\n";
329 osq <<
"# OpenMD " << rev.getFullRevision() <<
"\n";
330 osq <<
"# " << rev.getBuildDate() <<
"\n";
331 osq <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
332 if (!paramString_.empty())
333 osq <<
"# parameters: " << paramString_ <<
"\n";
337 for (
unsigned int i = 0; i < nBins_; ++i) {
338 RealType Rval = (i + 0.5) * deltaR_;
340 if (RCount_[i] == 0) {
344 osq <<
"\t" << (RealType)QofR_[i] / (RealType)RCount_[i];
352 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
353 "IcosahedralOfR: unable to open %s\n",
354 (getOutputFileName() +
"q").c_str());
355 painCave.isFatal = 1;
359 std::ofstream osw((getOutputFileName() +
"wr").c_str());
362 osw <<
"# " << getAnalysisType() <<
"\n";
363 osw <<
"# OpenMD " << rev.getFullRevision() <<
"\n";
364 osw <<
"# " << rev.getBuildDate() <<
"\n";
365 osw <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
366 if (!paramString_.empty())
367 osw <<
"# parameters: " << paramString_ <<
"\n";
370 for (
unsigned int i = 0; i < nBins_; ++i) {
371 RealType Rval = deltaR_ * (i + 0.5);
373 if (RCount_[i] == 0) {
377 osw <<
"\t" << (RealType)WofR_[i] / (RealType)RCount_[i];
384 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
385 "IcosahedralOfR: unable to open %s\n",
386 (getOutputFileName() +
"w").c_str());
387 painCave.isFatal = 1;
391 void FCCOfR::writeOrderParameter() {
392 std::ofstream osw((getOutputFileName() +
"wr").c_str());
396 osw <<
"# " << getAnalysisType() <<
"\n";
397 osw <<
"# OpenMD " << rev.getFullRevision() <<
"\n";
398 osw <<
"# " << rev.getBuildDate() <<
"\n";
399 osw <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
400 if (!paramString_.empty())
401 osw <<
"# parameters: " << paramString_ <<
"\n";
404 for (
unsigned int i = 0; i < nBins_; ++i) {
405 RealType Rval = deltaR_ * (i + 0.5);
407 if (RCount_[i] == 0) {
411 osw <<
"\t" << (RealType)WofR_[i] / (RealType)RCount_[i];
418 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
419 "FCCOfR: unable to open %s\n",
420 (getOutputFileName() +
"w").c_str());
421 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)