45#include "applications/staticProps/Field.hpp"
55#include "types/FixedChargeAdapter.hpp"
56#include "types/FluctuatingChargeAdapter.hpp"
57#include "types/MultipoleAdapter.hpp"
58#include "utils/Constants.hpp"
59#include "utils/Revision.hpp"
60#include "utils/simError.h"
67 const std::string& sele, RealType voxelSize) :
69 selectionScript_(sele), seleMan_(info), evaluator_(info),
70 voxelSize_(voxelSize) {
71 evaluator_.loadScriptString(sele);
72 if (!evaluator_.isDynamic()) {
73 seleMan_.setSelectionSet(evaluator_.evaluate());
76 int nSelected = seleMan_.getSelectionCount();
81 usePeriodicBoundaryConditions_ =
82 info_->getSimParams()->getUsePeriodicBoundaryConditions();
84 if (!usePeriodicBoundaryConditions_) {
85 box = snap_->getBoundingBox();
86 invBox = snap_->getInvBoundingBox();
88 box = snap_->getHmat();
89 invBox = snap_->getInvHmat();
94 snap_ = info_->getSnapshotManager()->getCurrentSnapshot();
96 reffective_ = 2.0 * voxelSize;
98 reffective_ = pow((snap_->getVolume() / nSelected), 1. / 3.);
100 rcut_ = 3.0 * reffective_;
117 RealType Wa = abs(
dot(A, BxC));
118 RealType Wb = abs(
dot(B, CxA));
119 RealType Wc = abs(
dot(C, AxB));
121 nBins_.x() = int(Wa / voxelSize_);
122 nBins_.y() = int(Wb / voxelSize_);
123 nBins_.z() = int(Wc / voxelSize_);
126 field_.resize(nBins_.x());
127 dens_.resize(nBins_.x());
128 for (
int i = 0; i < nBins_.x(); ++i) {
129 field_[i].resize(nBins_.y());
130 dens_[i].resize(nBins_.y());
131 for (
int j = 0; j < nBins_.y(); ++j) {
132 field_[i][j].resize(nBins_.z());
133 dens_[i][j].resize(nBins_.z());
135 std::fill(dens_[i][j].begin(), dens_[i][j].end(), 0.0);
136 std::fill(field_[i][j].begin(), field_[i][j].end(), T(0.0));
140 setOutputName(
getPrefix(filename) +
".field");
146 int nFrames = reader.getNFrames();
147 nProcessed_ = nFrames / step_;
149 for (
int istep = 0; istep < nFrames; istep += step_) {
150 reader.readFrame(istep);
151 snap_ = info_->getSnapshotManager()->getCurrentSnapshot();
156 writeVisualizationScript();
164 int ibin, jbin, kbin;
165 int igrid, jgrid, kgrid;
168 RealType weight, Wa, Wb, Wc;
170 if (!usePeriodicBoundaryConditions_) {
171 box = snap_->getBoundingBox();
172 invBox = snap_->getInvBoundingBox();
174 box = snap_->getHmat();
175 invBox = snap_->getInvHmat();
192 Wa = abs(
dot(A, BxC));
193 Wb = abs(
dot(B, CxA));
194 Wc = abs(
dot(C, AxB));
196 if (evaluator_.isDynamic()) {
197 seleMan_.setSelectionSet(evaluator_.evaluate());
202 di = (int)(rcut_ * nBins_.x() / Wa);
203 dj = (int)(rcut_ * nBins_.y() / Wb);
204 dk = (int)(rcut_ * nBins_.z() / Wc);
210 for (sd = seleMan_.beginSelected(isd); sd != NULL;
211 sd = seleMan_.nextSelected(isd)) {
217 if (usePeriodicBoundaryConditions_) { snap_->wrapVector(pos); }
220 scaled = invBox * pos;
224 for (
int j = 0; j < 3; j++) {
227 scaled[j] -= roundMe(scaled[j]);
232 if (scaled[j] >= 1.0) scaled[j] -= 1.0;
236 ibin = (int)(nBins_.x() * scaled.
x());
237 jbin = (int)(nBins_.y() * scaled.
y());
238 kbin = (int)(nBins_.z() * scaled.
z());
240 for (
int i = -di; i <= di; i++) {
242 while (igrid >=
int(nBins_.x())) {
243 igrid -= int(nBins_.x());
246 igrid += int(nBins_.x());
249 x = Wa * (RealType(i) / RealType(nBins_.x()));
251 for (
int j = -dj; j <= dj; j++) {
253 while (jgrid >=
int(nBins_.y())) {
254 jgrid -= int(nBins_.y());
257 jgrid += int(nBins_.y());
260 y = Wb * (RealType(j) / RealType(nBins_.y()));
262 for (
int k = -dk; k <= dk; k++) {
264 while (kgrid >=
int(nBins_.z())) {
265 kgrid -= int(nBins_.z());
268 kgrid += int(nBins_.z());
271 z = Wc * (RealType(k) / RealType(nBins_.z()));
273 RealType dist = sqrt(x * x + y * y + z * z);
275 weight = getDensity(dist, reffective_, rcut_);
276 dens_[igrid][jgrid][kgrid] += weight;
277 field_[igrid][jgrid][kgrid] += weight * getValue(sd);
286 RealType sigma2 = sigma * sigma;
288 exp(-r * r / (sigma2 * 2.0)) / (pow(2.0 * Constants::PI * sigma2, 3));
289 RealType dcut = exp(-rcut * rcut / (sigma2 * 2.0)) /
290 (pow(2.0 * Constants::PI * sigma2, 3));
299 for (
unsigned int i = 0; i < field_.size(); ++i) {
300 for (
unsigned int j = 0; j < field_[i].size(); ++j) {
301 for (
unsigned int k = 0; k < field_[i][j].size(); ++k) {
302 if (dens_[i][j][k] > 0.0) { field_[i][j][k] /= dens_[i][j][k]; }
310 Mat3x3d hmat = info_->getSnapshotManager()->getCurrentSnapshot()->getHmat();
313 std::ofstream fs(outputFilename_.c_str());
316 fs <<
"# " << getAnalysisType() <<
"\n";
317 fs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
318 fs <<
"# " << r.getBuildDate() <<
"\n";
319 fs <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
321 fs <<
"# Vector Field output file format has coordinates of the center\n";
322 fs <<
"# of the voxel followed by the value of field (either vector or\n";
323 fs <<
"# scalar).\n";
325 for (std::size_t k = 0; k < field_[0][0].size(); ++k) {
326 scaled.
z() = RealType(k) / nBins_.z() - 0.5;
327 for (std::size_t j = 0; j < field_[0].size(); ++j) {
328 scaled.
y() = RealType(j) / nBins_.y() - 0.5;
329 for (std::size_t i = 0; i < field_.size(); ++i) {
330 scaled.
y() = RealType(j) / nBins_.y() - 0.5;
334 fs << voxelLoc.
x() <<
"\t";
335 fs << voxelLoc.
y() <<
"\t";
336 fs << voxelLoc.
z() <<
"\t";
338 fs << writeValue(field_[i][j][k]);
350 string pythonFilename = outputFilename_ +
".py";
351 std::ofstream pss(pythonFilename.c_str());
353 pss <<
"#!/opt/local/bin/python\n\n";
354 pss <<
"__author__ = \"Patrick Louden (plouden@nd.edu)\" \n";
355 pss <<
"__copyright__ = \"Copyright (c) 2004-present The University of "
358 "Rights Reserved.\" \n";
359 pss <<
"__license__ = \"OpenMD\"\n\n";
360 pss <<
"import numpy as np\n";
361 pss <<
"from mayavi.mlab import * \n\n";
362 pss <<
"def plotField(inputFileName): \n";
363 pss << t +
"inputFile = open(inputFileName, 'r') \n";
364 pss << t +
"x = np.array([]) \n";
365 pss << t +
"y = np.array([]) \n";
366 pss << t +
"z = np.array([]) \n";
367 if (
typeid(T) ==
typeid(
int)) {
368 pss << t +
"scalarVal = np.array([]) \n\n";
370 if (
typeid(T) ==
typeid(
Vector3d)) {
371 pss << t +
"vectorVal.x = np.array([]) \n";
372 pss << t +
"vectorVal.y = np.array([]) \n";
373 pss << t +
"vectorVal.z = np.array([]) \n\n";
375 pss << t +
"for line in inputFile:\n";
376 pss << t + t +
"if line.split()[0] != \"#\": \n";
377 pss << t + t + t +
"x = np.append(x, float(line.strip().split()[0])) \n";
378 pss << t + t + t +
"y = np.append(y, float(line.strip().split()[1])) \n";
379 pss << t + t + t +
"z = np.append(z, float(line.strip().split()[2])) \n";
380 if (
typeid(T) ==
typeid(
int)) {
382 "scalarVal = np.append(scalarVal, "
383 "float(line.strip().split()[3])) \n\n";
384 pss << t +
"obj = quiver3d(x, y, z, scalarVal, line_width=2, "
385 "scale_factor=3) \n";
387 if (
typeid(T) ==
typeid(
Vector3d)) {
389 "vectorVal.x = np.append(vectorVal.x, "
390 "float(line.strip().split()[3])) "
393 "vectorVal.y = np.append(vectorVal.y, "
394 "float(line.strip().split()[4])) "
397 "vextorVal.z = np.append(vectorVal.z, "
398 "float(line.strip().split()[5])) "
400 pss << t +
"obj = quiver3d(x, y, z, vectorVal.x, vectorVal.y, "
402 "line_width=2, scale_factor=3) \n";
404 pss << t +
"return obj \n\n";
405 pss <<
"plotField(\"";
406 pss << outputFilename_.c_str();
413 std::stringstream str;
414 if (std::isinf(v) || std::isnan(v)) {
415 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
416 "Field detected a numerical error.\n");
417 painCave.isFatal = 1;
426 std::stringstream str;
427 if (std::isinf(v[0]) || std::isnan(v[0]) || std::isinf(v[1]) ||
428 std::isnan(v[1]) || std::isinf(v[2]) || std::isnan(v[2])) {
429 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
430 "Field detected a numerical error.\n");
431 painCave.isFatal = 1;
434 str << v[0] <<
"\t" << v[1] <<
"\t" << v[2];
438 DensityField::DensityField(
SimInfo* info,
const std::string& filename,
439 const std::string& sele1, RealType voxelSize) :
440 Field<RealType>(info, filename, sele1, voxelSize) {
441 setOutputName(
getPrefix(filename) +
".densityField");
446 ChargeField::ChargeField(
SimInfo* info,
const std::string& filename,
447 const std::string& sele1, RealType voxelSize) :
448 Field<RealType>(info, filename, sele1, voxelSize) {
449 setOutputName(
getPrefix(filename) +
".chargeField");
453 RealType charge = 0.0;
454 Atom* atom =
static_cast<Atom*
>(sd);
459 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
462 if (fqa.isFluctuatingCharge()) { charge += atom->
getFlucQPos(); }
466 VelocityField::VelocityField(
SimInfo* info,
const std::string& filename,
467 const std::string& sele1, RealType voxelSize) :
469 setOutputName(
getPrefix(filename) +
".velocityField");
474 DipoleField::DipoleField(
SimInfo* info,
const std::string& filename,
475 const std::string& sele1, RealType voxelSize) :
477 setOutputName(
getPrefix(filename) +
".dipoleField");
481 const RealType eAtoDebye = 4.8032045444;
491 RigidBody::AtomIterator ai;
492 for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) {
493 RealType charge(0.0);
497 if (fca.isFixedCharge()) { charge = fca.getCharge(); }
500 if (fqa.isFluctuatingCharge()) { charge += atom->
getFlucQPos(); }
503 dipoleVector += pos * charge * eAtoDebye;
505 if (atom->isDipole()) { dipoleVector += atom->
getDipole(); }
AtomType * getAtomType()
Returns the AtomType of this Atom.
AtomType is what OpenMD looks to for unchanging data about an atom.
Vector< Real, Col > getColumn(unsigned int col)
Returns a column of this matrix as a vector.
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 getVel()
Returns the current velocity of this stuntDouble.
RealType getMass()
Returns the mass of this stuntDouble.
bool isDirectionalAtom()
Tests if this stuntDouble is an directional atom.
Vector3d getPos()
Returns the current position of this stuntDouble.
RealType getFlucQPos()
Returns the current fluctuating charge of this stuntDouble.
Vector3d getDipole()
Returns the current dipole vector of this stuntDouble.
bool isRigidBody()
Tests if this stuntDouble is a rigid body.
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.
void normalize()
Normalizes this vector in place.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
std::string getPrefix(const std::string &str)