50#include "applications/staticProps/Hxy.hpp"
61#include "types/LennardJonesAdapter.hpp"
62#include "utils/Accumulator.hpp"
63#include "utils/AccumulatorView.hpp"
64#include "utils/BaseAccumulator.hpp"
65#include "utils/Utility.hpp"
66#include "utils/simError.h"
68using namespace OpenMD::Utils;
72 Hxy::Hxy(
SimInfo* info,
const std::string& filename,
const std::string& sele,
73 int nbins_x,
int nbins_y,
int nbins_z,
int nrbins) :
75 selectionScript_(sele), evaluator_(info), seleMan_(info),
76 nBinsX_(nbins_x), nBinsY_(nbins_y), nBinsZ_(nbins_z) {
77 evaluator_.loadScriptString(sele);
78 if (!evaluator_.isDynamic()) {
79 seleMan_.setSelectionSet(evaluator_.evaluate());
83 dens_.resize(nBinsX_);
86 minHeight_.resize(nBinsX_);
87 maxHeight_.resize(nBinsX_);
89 for (
unsigned int i = 0; i < nBinsX_; i++) {
90 dens_[i].resize(nBinsY_);
91 minHeight_[i].resize(nBinsY_);
92 maxHeight_[i].resize(nBinsY_);
93 for (
unsigned int j = 0; j < nBinsY_; j++) {
94 dens_[i][j].resize(nBinsZ_);
98 mag1.resize(nBinsX_ * nBinsY_);
99 newmag1.resize(nBinsX_ * nBinsY_);
100 mag2.resize(nBinsX_ * nBinsY_);
101 newmag2.resize(nBinsX_ * nBinsY_);
104 data_.resize(Hxy::ENDINDEX);
107 freq.units =
"Angstroms^-1";
108 freq.title =
"Spatial Frequency";
109 freq.dataHandling = DataHandling::Average;
110 for (
unsigned int i = 0; i < nBins_; i++)
111 freq.accumulator.push_back(
113 data_[FREQUECY] = std::move(freq);
116 top.units =
"Angstroms";
117 top.title =
"Hxy (Upper surface)";
118 freq.dataHandling = DataHandling::Max;
119 for (
unsigned int i = 0; i < nBins_; i++)
120 top.accumulator.push_back(
122 data_[TOP] = std::move(top);
125 bottom.units =
"Angstroms";
126 bottom.title =
"Hxy (Lower surface)";
127 freq.dataHandling = DataHandling::Max;
128 for (
unsigned int i = 0; i < nBins_; i++)
129 bottom.accumulator.push_back(
131 data_[BOTTOM] = std::move(bottom);
133 setOutputName(
getPrefix(filename) +
".Hxy");
136 void Hxy::process() {
137#if defined(HAVE_FFTW_H) || defined(HAVE_DFFTW_H) || defined(HAVE_FFTW3_H)
140 bool usePeriodicBoundaryConditions_ =
141 info_->getSimParams()->getUsePeriodicBoundaryConditions();
142 std::cerr <<
"usePeriodicBoundaryConditions_ = "
143 << usePeriodicBoundaryConditions_ <<
"\n";
146 int nFrames = reader.getNFrames();
147 nProcessed_ = nFrames / step_;
149 for (
int istep = 0; istep < nFrames; istep += step_) {
150 for (
unsigned int i = 0; i < nBinsX_; i++) {
151 std::fill(minHeight_[i].begin(), minHeight_[i].end(), 0.0);
152 std::fill(maxHeight_[i].begin(), maxHeight_[i].end(), 0.0);
153 for (
unsigned int j = 0; j < nBinsY_; j++) {
154 std::fill(dens_[i][j].begin(), dens_[i][j].end(), 0.0);
158 reader.readFrame(istep);
159 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
160 if (evaluator_.isDynamic()) {
161 seleMan_.setSelectionSet(evaluator_.evaluate());
169 fftw_complex *in1, *in2, *out1, *out2;
171 in1 = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) *
172 (nBinsX_ * nBinsY_));
173 out1 = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) *
174 (nBinsX_ * nBinsY_));
175 in2 = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) *
176 (nBinsX_ * nBinsY_));
177 out2 = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) *
178 (nBinsX_ * nBinsY_));
181 p1 = fftw_plan_dft_2d(nBinsX_, nBinsY_, in1, out1, FFTW_FORWARD,
183 p2 = fftw_plan_dft_2d(nBinsX_, nBinsY_, in2, out2, FFTW_FORWARD,
186 p1 = fftw2d_create_plan(nBinsX_, nBinsY_, FFTW_FORWARD, FFTW_ESTIMATE);
187 p2 = fftw2d_create_plan(nBinsX_, nBinsY_, FFTW_FORWARD, FFTW_ESTIMATE);
190 Mat3x3d hmat = currentSnapshot_->getHmat();
191 Mat3x3d invBox = currentSnapshot_->getInvHmat();
192 RealType lenX_ = hmat(0, 0);
193 RealType lenY_ = hmat(1, 1);
194 RealType lenZ_ = hmat(2, 2);
196 RealType x, y, z, dx, dy, dz;
197 RealType sigma, rcut;
198 int di, dj, dk, ibin, jbin, kbin;
199 int igrid, jgrid, kgrid;
202 dx = lenX_ / nBinsX_;
203 dy = lenY_ / nBinsY_;
204 dz = lenZ_ / nBinsZ_;
206 for (sd = seleMan_.beginSelected(ii); sd != NULL;
207 sd = seleMan_.nextSelected(ii)) {
209 Atom* atom =
static_cast<Atom*
>(sd);
210 Vector3d pos = sd->
getPos();
214 sigma = lja.getSigma() * 0.758176459;
220 scaled = invBox * pos;
224 for (
int j = 0; j < 3; j++) {
225 scaled[j] -= roundMe(scaled[j]);
230 if (scaled[j] >= 1.0) scaled[j] -= 1.0;
233 ibin = nBinsX_ * scaled.
x();
234 jbin = nBinsY_ * scaled.
y();
235 kbin = nBinsZ_ * scaled.
z();
237 di = (int)(rcut / dx);
238 dj = (int)(rcut / dy);
239 dk = (int)(rcut / dz);
241 for (
int i = -di; i <= di; i++) {
243 while (igrid >=
int(nBinsX_)) {
244 igrid -= int(nBinsX_);
247 igrid += int(nBinsX_);
250 x = lenX_ * (RealType(i) / RealType(nBinsX_));
252 for (
int j = -dj; j <= dj; j++) {
254 while (jgrid >=
int(nBinsY_)) {
255 jgrid -= int(nBinsY_);
258 jgrid += int(nBinsY_);
261 y = lenY_ * (RealType(j) / RealType(nBinsY_));
263 for (
int k = -dk; k <= dk; k++) {
265 while (kgrid >=
int(nBinsZ_)) {
266 kgrid -= int(nBinsZ_);
269 kgrid += int(nBinsZ_);
272 z = lenZ_ * (RealType(k) / RealType(nBinsZ_));
274 RealType dist = sqrt(x * x + y * y + z * z);
276 dens_[igrid][jgrid][kgrid] += getDensity(dist, sigma, rcut);
283 RealType maxDens(0.0);
284 for (
unsigned int i = 0; i < nBinsX_; i++) {
285 for (
unsigned int j = 0; j < nBinsY_; j++) {
286 for (
unsigned int k = 0; k < nBinsZ_; k++) {
287 if (dens_[i][j][k] > maxDens) maxDens = dens_[i][j][k];
292 RealType threshold = maxDens / 2.0;
293 RealType z0, z1, h0, h1;
294 std::cerr <<
"maxDens = "
295 <<
"\t" << maxDens <<
"\n";
296 std::cerr <<
"threshold value = "
297 <<
"\t" << threshold <<
"\n";
299 for (
unsigned int i = 0; i < nBinsX_; i++) {
300 for (
unsigned int j = 0; j < nBinsY_; j++) {
310 bool minFound =
false;
311 bool maxFound =
false;
313 if (dens_[i][j][0] < threshold) {
314 for (
unsigned int k = 0; k < nBinsZ_ - 1; k++) {
315 z0 = lenZ_ * (RealType(k) / RealType(nBinsZ_));
316 z1 = lenZ_ * (RealType(k + 1) / RealType(nBinsZ_));
318 h1 = dens_[i][j][k + 1];
320 if (h0 < threshold && h1 > threshold && !minFound) {
323 z0 + (z1 - z0) * (threshold - h0) / (h1 - h0);
326 if (h0 > threshold && h1 < threshold && minFound) {
329 z0 + (z1 - z0) * (threshold - h0) / (h1 - h0);
335 for (
unsigned int k = 0; k < nBinsZ_ - 1; k++) {
336 z0 = lenZ_ * (RealType(k) / RealType(nBinsZ_));
337 z1 = lenZ_ * (RealType(k + 1) / RealType(nBinsZ_));
339 h1 = dens_[i][j][k + 1];
341 if (h0 > threshold && h1 < threshold && !maxFound) {
344 z0 + (z1 - z0) * (threshold - h0) / (h1 - h0);
347 if (h0 < threshold && h1 > threshold && maxFound) {
350 z0 + (z1 - z0) * (threshold - h0) / (h1 - h0);
357 RealType minBar = 0.0;
358 RealType maxBar = 0.0;
360 for (
unsigned int i = 0; i < nBinsX_; i++) {
361 for (
unsigned int j = 0; j < nBinsY_; j++) {
365 minBar += minHeight_[i][j];
366 maxBar += maxHeight_[i][j];
373 std::cerr <<
"bottomSurf = " << minBar <<
"\ttopSurf = " << maxBar
378 for (
unsigned int i = 0; i < nBinsX_; i++) {
379 for (
unsigned int j = 0; j < nBinsY_; j++) {
380 newindex = i * nBinsY_ + j;
382 c_re(in1[newindex]) = maxHeight_[i][j] - maxBar;
384 c_im(in1[newindex]) = 0.0;
385 c_re(in2[newindex]) =
386 minHeight_[i][j] - minBar;
388 c_im(in2[newindex]) = 0.0;
396 fftwnd_one(p1, in1, out1);
397 fftwnd_one(p2, in2, out2);
400 for (
unsigned int i = 0; i < nBinsX_; i++) {
401 for (
unsigned int j = 0; j < nBinsY_; j++) {
402 newindex = i * nBinsY_ + j;
403 mag1[newindex] = sqrt(pow(c_re(out1[newindex]), 2) +
404 pow(c_im(out1[newindex]), 2)) /
405 (RealType(nBinsX_ * nBinsY_));
406 mag2[newindex] = sqrt(pow(c_re(out2[newindex]), 2) +
407 pow(c_im(out2[newindex]), 2)) /
408 (RealType(nBinsX_ * nBinsY_));
413 fftw_destroy_plan(p1);
414 fftw_destroy_plan(p2);
416 fftwnd_destroy_plan(p1);
417 fftwnd_destroy_plan(p2);
424 int index, new_i, new_j, new_index;
425 for (
unsigned int i = 0; i < (nBinsX_ / 2); i++) {
426 for (
unsigned int j = 0; j < (nBinsY_ / 2); j++) {
427 index = i * nBinsY_ + j;
428 new_i = i + (nBinsX_ / 2);
429 new_j = j + (nBinsY_ / 2);
430 new_index = new_i * nBinsY_ + new_j;
431 newmag1[new_index] = mag1[index];
432 newmag2[new_index] = mag2[index];
436 for (
unsigned int i = (nBinsX_ / 2); i < nBinsX_; i++) {
437 for (
unsigned int j = 0; j < (nBinsY_ / 2); j++) {
438 index = i * nBinsY_ + j;
439 new_i = i - (nBinsX_ / 2);
440 new_j = j + (nBinsY_ / 2);
441 new_index = new_i * nBinsY_ + new_j;
442 newmag1[new_index] = mag1[index];
443 newmag2[new_index] = mag2[index];
447 for (
unsigned int i = 0; i < (nBinsX_ / 2); i++) {
448 for (
unsigned int j = (nBinsY_ / 2); j < nBinsY_; j++) {
449 index = i * nBinsY_ + j;
450 new_i = i + (nBinsX_ / 2);
451 new_j = j - (nBinsY_ / 2);
452 new_index = new_i * nBinsY_ + new_j;
453 newmag1[new_index] = mag1[index];
454 newmag2[new_index] = mag2[index];
458 for (
unsigned int i = (nBinsX_ / 2); i < nBinsX_; i++) {
459 for (
unsigned int j = (nBinsY_ / 2); j < nBinsY_; j++) {
460 index = i * nBinsY_ + j;
461 new_i = i - (nBinsX_ / 2);
462 new_j = j - (nBinsY_ / 2);
463 new_index = new_i * nBinsY_ + new_j;
464 newmag1[new_index] = mag1[index];
465 newmag2[new_index] = mag2[index];
479 RealType maxfreqx = RealType(nBinsX_) / lenX_;
480 RealType maxfreqy = RealType(nBinsY_) / lenY_;
482 RealType maxfreq = sqrt(maxfreqx * maxfreqx + maxfreqy * maxfreqy);
483 dfreq_ = maxfreq / (RealType)(nBins_ - 1);
485 int zero_freq_x = nBinsX_ / 2;
486 int zero_freq_y = nBinsY_ / 2;
488 for (
int i = 0; i < (int)nBinsX_; i++) {
489 for (
int j = 0; j < (int)nBinsY_; j++) {
491 (RealType)(i - zero_freq_x) * maxfreqx / (RealType)nBinsX_;
493 (RealType)(j - zero_freq_y) * maxfreqy / (RealType)nBinsY_;
495 RealType freq = sqrt(freq_x * freq_x + freq_y * freq_y);
497 unsigned int whichbin = (
unsigned int)(freq / dfreq_);
499 newindex = i * nBinsY_ + j;
501 data_[FREQUECY].accumulator[whichbin]->add(freq);
502 data_[TOP].accumulator[whichbin]->add(newmag1[newindex]);
503 data_[BOTTOM].accumulator[whichbin]->add(newmag2[newindex]);
511 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
512 "Hxy: FFTW support was not compiled in!\n");
513 painCave.isFatal = 1;
519 RealType Hxy::getDensity(RealType r, RealType sigma, RealType rcut) {
520 RealType sigma2 = sigma * sigma;
522 exp(-r * r / (sigma2 * 2.0)) / (pow(2.0 * Constants::PI * sigma2, 3));
523 RealType dcut = exp(-rcut * rcut / (sigma2 * 2.0)) /
524 (pow(2.0 * Constants::PI * sigma2, 3));
AtomType * getAtomType()
Returns the AtomType of this Atom.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
"Don't move, or you're dead! Stand up! Captain, we've got them!"
Vector3d getPos()
Returns the current position of this stuntDouble.
bool isAtom()
Tests if this stuntDouble is an atom.
Real & z()
Returns reference of the third element of Vector3.
Real & x()
Returns reference of the first element of Vector3.
Real & y()
Returns reference of the second element of Vector3.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)