47#include "applications/staticProps/Hxy.hpp"
58#include "types/LennardJonesAdapter.hpp"
59#include "utils/Accumulator.hpp"
60#include "utils/AccumulatorView.hpp"
61#include "utils/BaseAccumulator.hpp"
62#include "utils/Utility.hpp"
63#include "utils/simError.h"
65using namespace OpenMD::Utils;
69 Hxy::Hxy(
SimInfo* info,
const std::string& filename,
const std::string& sele,
70 int nbins_x,
int nbins_y,
int nbins_z,
int nrbins) :
72 selectionScript_(sele), evaluator_(info), seleMan_(info),
73 nBinsX_(nbins_x), nBinsY_(nbins_y), nBinsZ_(nbins_z) {
74 evaluator_.loadScriptString(sele);
75 if (!evaluator_.isDynamic()) {
76 seleMan_.setSelectionSet(evaluator_.evaluate());
80 dens_.resize(nBinsX_);
83 minHeight_.resize(nBinsX_);
84 maxHeight_.resize(nBinsX_);
86 for (
unsigned int i = 0; i < nBinsX_; i++) {
87 dens_[i].resize(nBinsY_);
88 minHeight_[i].resize(nBinsY_);
89 maxHeight_[i].resize(nBinsY_);
90 for (
unsigned int j = 0; j < nBinsY_; j++) {
91 dens_[i][j].resize(nBinsZ_);
95 mag1.resize(nBinsX_ * nBinsY_);
96 newmag1.resize(nBinsX_ * nBinsY_);
97 mag2.resize(nBinsX_ * nBinsY_);
98 newmag2.resize(nBinsX_ * nBinsY_);
101 data_.resize(Hxy::ENDINDEX);
104 freq.units =
"Angstroms^-1";
105 freq.title =
"Spatial Frequency";
106 freq.dataHandling = DataHandling::Average;
107 for (
unsigned int i = 0; i < nBins_; i++)
108 freq.accumulator.push_back(
110 data_[FREQUECY] = std::move(freq);
113 top.units =
"Angstroms";
114 top.title =
"Hxy (Upper surface)";
115 freq.dataHandling = DataHandling::Max;
116 for (
unsigned int i = 0; i < nBins_; i++)
117 top.accumulator.push_back(
119 data_[TOP] = std::move(top);
122 bottom.units =
"Angstroms";
123 bottom.title =
"Hxy (Lower surface)";
124 freq.dataHandling = DataHandling::Max;
125 for (
unsigned int i = 0; i < nBins_; i++)
126 bottom.accumulator.push_back(
128 data_[BOTTOM] = std::move(bottom);
130 setOutputName(
getPrefix(filename) +
".Hxy");
133 void Hxy::process() {
134#if defined(HAVE_FFTW_H) || defined(HAVE_DFFTW_H) || defined(HAVE_FFTW3_H)
137 bool usePeriodicBoundaryConditions_ =
138 info_->getSimParams()->getUsePeriodicBoundaryConditions();
139 std::cerr <<
"usePeriodicBoundaryConditions_ = "
140 << usePeriodicBoundaryConditions_ <<
"\n";
143 int nFrames = reader.getNFrames();
144 nProcessed_ = nFrames / step_;
146 for (
int istep = 0; istep < nFrames; istep += step_) {
147 for (
unsigned int i = 0; i < nBinsX_; i++) {
148 std::fill(minHeight_[i].begin(), minHeight_[i].end(), 0.0);
149 std::fill(maxHeight_[i].begin(), maxHeight_[i].end(), 0.0);
150 for (
unsigned int j = 0; j < nBinsY_; j++) {
151 std::fill(dens_[i][j].begin(), dens_[i][j].end(), 0.0);
155 reader.readFrame(istep);
156 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
157 if (evaluator_.isDynamic()) {
158 seleMan_.setSelectionSet(evaluator_.evaluate());
166 fftw_complex *in1, *in2, *out1, *out2;
168 in1 = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) *
169 (nBinsX_ * nBinsY_));
170 out1 = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) *
171 (nBinsX_ * nBinsY_));
172 in2 = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) *
173 (nBinsX_ * nBinsY_));
174 out2 = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) *
175 (nBinsX_ * nBinsY_));
178 p1 = fftw_plan_dft_2d(nBinsX_, nBinsY_, in1, out1, FFTW_FORWARD,
180 p2 = fftw_plan_dft_2d(nBinsX_, nBinsY_, in2, out2, FFTW_FORWARD,
183 p1 = fftw2d_create_plan(nBinsX_, nBinsY_, FFTW_FORWARD, FFTW_ESTIMATE);
184 p2 = fftw2d_create_plan(nBinsX_, nBinsY_, FFTW_FORWARD, FFTW_ESTIMATE);
187 Mat3x3d hmat = currentSnapshot_->getHmat();
188 Mat3x3d invBox = currentSnapshot_->getInvHmat();
189 RealType lenX_ = hmat(0, 0);
190 RealType lenY_ = hmat(1, 1);
191 RealType lenZ_ = hmat(2, 2);
193 RealType x, y, z, dx, dy, dz;
194 RealType sigma, rcut;
195 int di, dj, dk, ibin, jbin, kbin;
196 int igrid, jgrid, kgrid;
199 dx = lenX_ / nBinsX_;
200 dy = lenY_ / nBinsY_;
201 dz = lenZ_ / nBinsZ_;
203 for (sd = seleMan_.beginSelected(ii); sd != NULL;
204 sd = seleMan_.nextSelected(ii)) {
206 Atom* atom =
static_cast<Atom*
>(sd);
211 sigma = lja.getSigma() * 0.758176459;
217 scaled = invBox * pos;
221 for (
int j = 0; j < 3; j++) {
222 scaled[j] -= roundMe(scaled[j]);
227 if (scaled[j] >= 1.0) scaled[j] -= 1.0;
230 ibin = nBinsX_ * scaled.
x();
231 jbin = nBinsY_ * scaled.
y();
232 kbin = nBinsZ_ * scaled.
z();
234 di = (int)(rcut / dx);
235 dj = (int)(rcut / dy);
236 dk = (int)(rcut / dz);
238 for (
int i = -di; i <= di; i++) {
240 while (igrid >=
int(nBinsX_)) {
241 igrid -= int(nBinsX_);
244 igrid += int(nBinsX_);
247 x = lenX_ * (RealType(i) / RealType(nBinsX_));
249 for (
int j = -dj; j <= dj; j++) {
251 while (jgrid >=
int(nBinsY_)) {
252 jgrid -= int(nBinsY_);
255 jgrid += int(nBinsY_);
258 y = lenY_ * (RealType(j) / RealType(nBinsY_));
260 for (
int k = -dk; k <= dk; k++) {
262 while (kgrid >=
int(nBinsZ_)) {
263 kgrid -= int(nBinsZ_);
266 kgrid += int(nBinsZ_);
269 z = lenZ_ * (RealType(k) / RealType(nBinsZ_));
271 RealType dist = sqrt(x * x + y * y + z * z);
273 dens_[igrid][jgrid][kgrid] += getDensity(dist, sigma, rcut);
280 RealType maxDens(0.0);
281 for (
unsigned int i = 0; i < nBinsX_; i++) {
282 for (
unsigned int j = 0; j < nBinsY_; j++) {
283 for (
unsigned int k = 0; k < nBinsZ_; k++) {
284 if (dens_[i][j][k] > maxDens) maxDens = dens_[i][j][k];
289 RealType threshold = maxDens / 2.0;
290 RealType z0, z1, h0, h1;
291 std::cerr <<
"maxDens = "
292 <<
"\t" << maxDens <<
"\n";
293 std::cerr <<
"threshold value = "
294 <<
"\t" << threshold <<
"\n";
296 for (
unsigned int i = 0; i < nBinsX_; i++) {
297 for (
unsigned int j = 0; j < nBinsY_; j++) {
307 bool minFound =
false;
308 bool maxFound =
false;
310 if (dens_[i][j][0] < threshold) {
311 for (
unsigned int k = 0; k < nBinsZ_ - 1; k++) {
312 z0 = lenZ_ * (RealType(k) / RealType(nBinsZ_));
313 z1 = lenZ_ * (RealType(k + 1) / RealType(nBinsZ_));
315 h1 = dens_[i][j][k + 1];
317 if (h0 < threshold && h1 > threshold && !minFound) {
320 z0 + (z1 - z0) * (threshold - h0) / (h1 - h0);
323 if (h0 > threshold && h1 < threshold && minFound) {
326 z0 + (z1 - z0) * (threshold - h0) / (h1 - h0);
332 for (
unsigned int k = 0; k < nBinsZ_ - 1; k++) {
333 z0 = lenZ_ * (RealType(k) / RealType(nBinsZ_));
334 z1 = lenZ_ * (RealType(k + 1) / RealType(nBinsZ_));
336 h1 = dens_[i][j][k + 1];
338 if (h0 > threshold && h1 < threshold && !maxFound) {
341 z0 + (z1 - z0) * (threshold - h0) / (h1 - h0);
344 if (h0 < threshold && h1 > threshold && maxFound) {
347 z0 + (z1 - z0) * (threshold - h0) / (h1 - h0);
354 RealType minBar = 0.0;
355 RealType maxBar = 0.0;
357 for (
unsigned int i = 0; i < nBinsX_; i++) {
358 for (
unsigned int j = 0; j < nBinsY_; j++) {
362 minBar += minHeight_[i][j];
363 maxBar += maxHeight_[i][j];
370 std::cerr <<
"bottomSurf = " << minBar <<
"\ttopSurf = " << maxBar
375 for (
unsigned int i = 0; i < nBinsX_; i++) {
376 for (
unsigned int j = 0; j < nBinsY_; j++) {
377 newindex = i * nBinsY_ + j;
379 c_re(in1[newindex]) = maxHeight_[i][j] - maxBar;
381 c_im(in1[newindex]) = 0.0;
382 c_re(in2[newindex]) =
383 minHeight_[i][j] - minBar;
385 c_im(in2[newindex]) = 0.0;
393 fftwnd_one(p1, in1, out1);
394 fftwnd_one(p2, in2, out2);
397 for (
unsigned int i = 0; i < nBinsX_; i++) {
398 for (
unsigned int j = 0; j < nBinsY_; j++) {
399 newindex = i * nBinsY_ + j;
400 mag1[newindex] = sqrt(pow(c_re(out1[newindex]), 2) +
401 pow(c_im(out1[newindex]), 2)) /
402 (RealType(nBinsX_ * nBinsY_));
403 mag2[newindex] = sqrt(pow(c_re(out2[newindex]), 2) +
404 pow(c_im(out2[newindex]), 2)) /
405 (RealType(nBinsX_ * nBinsY_));
410 fftw_destroy_plan(p1);
411 fftw_destroy_plan(p2);
413 fftwnd_destroy_plan(p1);
414 fftwnd_destroy_plan(p2);
421 int index, new_i, new_j, new_index;
422 for (
unsigned int i = 0; i < (nBinsX_ / 2); i++) {
423 for (
unsigned int j = 0; j < (nBinsY_ / 2); j++) {
424 index = i * nBinsY_ + j;
425 new_i = i + (nBinsX_ / 2);
426 new_j = j + (nBinsY_ / 2);
427 new_index = new_i * nBinsY_ + new_j;
428 newmag1[new_index] = mag1[index];
429 newmag2[new_index] = mag2[index];
433 for (
unsigned int i = (nBinsX_ / 2); i < nBinsX_; i++) {
434 for (
unsigned int j = 0; j < (nBinsY_ / 2); j++) {
435 index = i * nBinsY_ + j;
436 new_i = i - (nBinsX_ / 2);
437 new_j = j + (nBinsY_ / 2);
438 new_index = new_i * nBinsY_ + new_j;
439 newmag1[new_index] = mag1[index];
440 newmag2[new_index] = mag2[index];
444 for (
unsigned int i = 0; i < (nBinsX_ / 2); i++) {
445 for (
unsigned int j = (nBinsY_ / 2); j < nBinsY_; j++) {
446 index = i * nBinsY_ + j;
447 new_i = i + (nBinsX_ / 2);
448 new_j = j - (nBinsY_ / 2);
449 new_index = new_i * nBinsY_ + new_j;
450 newmag1[new_index] = mag1[index];
451 newmag2[new_index] = mag2[index];
455 for (
unsigned int i = (nBinsX_ / 2); i < nBinsX_; i++) {
456 for (
unsigned int j = (nBinsY_ / 2); j < nBinsY_; j++) {
457 index = i * nBinsY_ + j;
458 new_i = i - (nBinsX_ / 2);
459 new_j = j - (nBinsY_ / 2);
460 new_index = new_i * nBinsY_ + new_j;
461 newmag1[new_index] = mag1[index];
462 newmag2[new_index] = mag2[index];
476 RealType maxfreqx = RealType(nBinsX_) / lenX_;
477 RealType maxfreqy = RealType(nBinsY_) / lenY_;
479 RealType maxfreq = sqrt(maxfreqx * maxfreqx + maxfreqy * maxfreqy);
480 dfreq_ = maxfreq / (RealType)(nBins_ - 1);
482 int zero_freq_x = nBinsX_ / 2;
483 int zero_freq_y = nBinsY_ / 2;
485 for (
int i = 0; i < (int)nBinsX_; i++) {
486 for (
int j = 0; j < (int)nBinsY_; j++) {
488 (RealType)(i - zero_freq_x) * maxfreqx / (RealType)nBinsX_;
490 (RealType)(j - zero_freq_y) * maxfreqy / (RealType)nBinsY_;
492 RealType freq = sqrt(freq_x * freq_x + freq_y * freq_y);
494 unsigned int whichbin = (
unsigned int)(freq / dfreq_);
496 newindex = i * nBinsY_ + j;
498 data_[FREQUECY].accumulator[whichbin]->add(freq);
499 data_[TOP].accumulator[whichbin]->add(newmag1[newindex]);
500 data_[BOTTOM].accumulator[whichbin]->add(newmag2[newindex]);
508 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
509 "Hxy: FFTW support was not compiled in!\n");
510 painCave.isFatal = 1;
516 RealType Hxy::getDensity(RealType r, RealType sigma, RealType rcut) {
517 RealType sigma2 = sigma * sigma;
519 exp(-r * r / (sigma2 * 2.0)) / (pow(2.0 * Constants::PI * sigma2, 3));
520 RealType dcut = exp(-rcut * rcut / (sigma2 * 2.0)) /
521 (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)