45#include "applications/staticProps/ChargeDensityZ.hpp"
50#include "brains/Thermo.hpp"
53#include "types/FixedChargeAdapter.hpp"
54#include "types/FluctuatingChargeAdapter.hpp"
55#include "utils/Constants.hpp"
56#include "utils/simError.h"
60 ChargeDensityZ::ChargeDensityZ(
SimInfo* info,
const std::string& filename,
61 const std::string& sele,
int nzbins,
62 RealType vRadius, std::string atomName,
63 bool xyzGen,
int axis) :
65 selectionScript_(sele), evaluator_(info), seleMan_(info), thermo_(info),
66 axis_(axis), vRadius_(vRadius), fileName_(filename),
67 atomFlucCharge_(atomName), genXYZ_(xyzGen) {
68 evaluator_.loadScriptString(sele);
69 if (!evaluator_.isDynamic()) {
70 seleMan_.setSelectionSet(evaluator_.evaluate());
75 densityZAverageAllFrame_.resize(nBins_);
76 densityFlucZAverageAllFrame_.resize(nBins_);
77 absDensityFlucZAverageAllFrame_.resize(nBins_);
78 averageDensityZ_.resize(nBins_);
79 flucDensityZAverageAllFrame_.resize(nBins_);
80 std::fill(densityFlucZAverageAllFrame_.begin(),
81 densityFlucZAverageAllFrame_.end(), 0);
82 std::fill(densityZAverageAllFrame_.begin(), densityZAverageAllFrame_.end(),
84 std::fill(absDensityFlucZAverageAllFrame_.begin(),
85 absDensityFlucZAverageAllFrame_.end(), 0);
86 std::fill(averageDensityZ_.begin(), averageDensityZ_.end(), 0);
87 std::fill(flucDensityZAverageAllFrame_.begin(),
88 flucDensityZAverageAllFrame_.end(), 0);
90 densityFlucZAverageFirstFrame_.resize(nBins_);
91 absDensityFlucZAverageFirstFrame_.resize(nBins_);
92 std::fill(densityFlucZAverageFirstFrame_.begin(),
93 densityFlucZAverageFirstFrame_.end(), 0);
94 std::fill(absDensityFlucZAverageFirstFrame_.begin(),
95 absDensityFlucZAverageFirstFrame_.end(), 0);
110 setOutputName(
getPrefix(filename) +
".ChargeDensityZ");
112 void ChargeDensityZ::process() {
113 bool usePeriodicBoundaryConditions_ =
114 info_->getSimParams()->getUsePeriodicBoundaryConditions();
117 int nFrames_ = reader.getNFrames();
118 nProcessed_ = nFrames_ / step_;
125 hmat_ = currentSnapshot_->
getHmat();
126 zBox_.push_back(hmat_(axis_, axis_));
128 std::vector<RealType>::iterator j;
130 for (j = zBox_.begin(); j != zBox_.end(); ++j) {
134 RealType zAve = zSum / zBox_.size();
136 axisValues.insert(0);
137 axisValues.insert(1);
138 axisValues.insert(2);
139 axisValues.erase(axis_);
140 set<int>::iterator axis_it;
141 std::vector<int> cartesian_axis;
142 for (axis_it = axisValues.begin(); axis_it != axisValues.end(); ++axis_it) {
143 cartesian_axis.push_back(*axis_it);
145 x_ = cartesian_axis[0];
146 y_ = cartesian_axis[1];
147 RealType area = hmat_(x_, x_) * hmat_(y_, y_);
148 RealType sliceVolume = zAve / densityZAverageAllFrame_.size() * area;
150 for (
int i = 1; i < nFrames_; i += step_) {
155 seleMan_.setSelectionSet(evaluator_.evaluate());
162 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
163 "Can not calculate charge density distribution if it is not "
165 painCave.severity = OPENMD_ERROR;
166 painCave.isFatal = 1;
171 Atom* atom =
static_cast<Atom*
>(sd);
177 if (fca.isFixedCharge()) { q += fca.getCharge(); }
180 if (fqa.isFluctuatingCharge()) { q += atom->
getFlucQPos(); }
184 std::string atomName;
185 std::vector<AtomType*> atChain = atomType->allYourBase();
186 std::vector<AtomType*>::iterator i;
187 for (i = atChain.begin(); i != atChain.end(); ++i) {
188 atomName = (*i)->getName().c_str();
195 if (obanum == 0) { sigma = vRadius_; }
198 if (usePeriodicBoundaryConditions_) currentSnapshot_->
wrapVector(pos);
203 int globalIndex = sd->getGlobalIndex();
205 atomNameGlobalIndex_[globalIndex] = atomName;
206 averageChargeUsingGlobalIndex_[globalIndex] =
207 (countUsingGlobalIndex_[globalIndex] *
208 averageChargeUsingGlobalIndex_[globalIndex] +
210 (countUsingGlobalIndex_[globalIndex] + 1);
211 totalChargeUsingGlobalIndex_[globalIndex].push_back(q);
212 zPosUsingGlobalIndex_[globalIndex].push_back(pos[axis_]);
213 xPosUsingGlobalIndex_[globalIndex].push_back(pos[x_]);
214 yPosUsingGlobalIndex_[globalIndex].push_back(pos[y_]);
216 vanderRUsingGlobalIndex_[globalIndex] = sigma;
217 countUsingGlobalIndex_[globalIndex]++;
220 for (std::map<int, std::string>::iterator it =
221 atomNameGlobalIndex_.begin();
222 it != atomNameGlobalIndex_.end(); ++it) {
223 int g_Index = it->first;
224 std::string a_name = it->second;
225 averageChargeForEachType_[a_name] =
226 (SDCount_[a_name] * averageChargeForEachType_[a_name] +
227 totalChargeUsingGlobalIndex_[g_Index].front()) /
228 (SDCount_[a_name] + 1);
232 RealType epsilon = 1e-10;
233 for (std::map<int, std::string>::iterator it = atomNameGlobalIndex_.begin();
234 it != atomNameGlobalIndex_.end(); ++it) {
236 std::string a_name = it->second;
238 RealType averageCharge = averageChargeUsingGlobalIndex_[key];
239 RealType averageChargeUsingFirstFrame = averageChargeForEachType_[a_name];
240 RealType v_radius = vanderRUsingGlobalIndex_[key];
241 RealType v_radius2 = v_radius * v_radius;
242 for (
size_t index = 0; index < zPosUsingGlobalIndex_[key].size();
244 RealType z_pos = zPosUsingGlobalIndex_[key][index];
245 RealType charge = totalChargeUsingGlobalIndex_[key][index];
246 RealType chargeDiff =
247 fabs(charge - averageCharge) > epsilon ? charge - averageCharge : 0;
248 RealType chargeDiffUsingFirstFrameAverage =
249 fabs(charge - averageChargeUsingFirstFrame) > epsilon ?
250 charge - averageChargeUsingFirstFrame :
253 for (
size_t i = 0; i < densityFlucZAverageAllFrame_.size(); ++i) {
254 RealType z = -zAve / 2 + i * zAve / densityZAverageAllFrame_.size();
255 RealType zdist = z_pos - z;
257 RealType gaussian_scale =
258 exp(-zdist * zdist / (v_radius2 * 2.0)) /
259 (sliceVolume * (sqrt(2 * Constants::PI * v_radius * v_radius)));
260 densityZAverageAllFrame_[i] += charge * gaussian_scale;
262 densityFlucZAverageAllFrame_[i] += chargeDiff * gaussian_scale;
263 absDensityFlucZAverageAllFrame_[i] +=
264 abs(chargeDiff) * abs(chargeDiff) * gaussian_scale;
266 densityFlucZAverageFirstFrame_[i] +=
267 chargeDiffUsingFirstFrameAverage * gaussian_scale;
268 absDensityFlucZAverageFirstFrame_[i] +=
269 abs(chargeDiffUsingFirstFrameAverage) *
270 abs(chargeDiffUsingFirstFrameAverage) * gaussian_scale;
277 if (genXYZ_) generateXYZForLastFrame();
280 void ChargeDensityZ::writeDensity() {
282 std::vector<RealType>::iterator j;
284 for (j = zBox_.begin(); j != zBox_.end(); ++j) {
287 RealType zAve = zSum / zBox_.size();
289 std::ofstream rdfStream(outputFilename_.c_str());
290 if (rdfStream.is_open()) {
291 rdfStream <<
"#ChargeDensityZ "
293 rdfStream <<
"#selection: (" << selectionScript_ <<
")\n";
296 <<
"\tchargeDensity\tchargeDensityFluctuations_Average_on_all_frame\t"
297 <<
"Absolute_chargeDensityFluctuations_Average_on_all_frame\t"
298 <<
"chargeDensityFluctuations_Average_On_first_frame\t"
299 <<
"Absolute_chargeDensityFluctuations_Average_on_first_frame\n";
301 for (
unsigned int i = 0; i < densityFlucZAverageAllFrame_.size(); ++i) {
302 RealType z = zAve * (i + 0.5) / densityFlucZAverageAllFrame_.size();
303 rdfStream << z <<
"\t" << densityZAverageAllFrame_[i] / nProcessed_
304 <<
"\t" << densityFlucZAverageAllFrame_[i] / (nProcessed_)
305 <<
"\t" << absDensityFlucZAverageAllFrame_[i] / (nProcessed_)
306 <<
"\t" << densityFlucZAverageFirstFrame_[i] / (nProcessed_)
308 << absDensityFlucZAverageFirstFrame_[i] / (nProcessed_)
313 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
314 "ChargeDensityZ: unable to open %s\n", outputFilename_.c_str());
315 painCave.isFatal = 1;
322 void ChargeDensityZ::generateXYZForLastFrame() {
323 std::string XYZFile(
getPrefix(fileName_) +
".xyz");
324 std::ofstream rdfStream(XYZFile.c_str());
325 int nAtoms = zPosUsingGlobalIndex_.size();
327 if (rdfStream.is_open()) {
328 rdfStream << nAtoms <<
"\n";
329 rdfStream << 1 <<
";\t" << hmat_(x_, x_) <<
"\t" << hmat_(x_, y_) <<
"\t"
330 << hmat_(x_, axis_) <<
"\t" << hmat_(y_, x_) <<
"\t"
331 << hmat_(y_, y_) <<
"\t" << hmat_(y_, axis_) <<
"\t"
332 << hmat_(axis_, x_) <<
"\t" << hmat_(axis_, y_) <<
"\t"
333 << hmat_(axis_, axis_) <<
"\n";
335 for (std::map<int, std::string>::iterator it =
336 atomNameGlobalIndex_.begin();
337 it != atomNameGlobalIndex_.end(); ++it) {
339 std::string a_name = it->second;
340 RealType x = zPosUsingGlobalIndex_[key].back();
341 RealType y = xPosUsingGlobalIndex_[key].back();
342 RealType z = yPosUsingGlobalIndex_[key].back();
345 if (a_name == atomFlucCharge_) {
346 for (std::map<int, std::string>::iterator it1 =
347 atomNameGlobalIndex_.begin();
348 it1 != atomNameGlobalIndex_.end(); ++it1) {
349 int key1 = it1->first;
350 std::string a_name1 = it1->second;
352 RealType v_radius = vanderRUsingGlobalIndex_[key1];
353 RealType v_radius2 = v_radius * v_radius;
354 RealType averageCharge = averageChargeUsingGlobalIndex_[key1];
356 for (
size_t index = 0; index < zPosUsingGlobalIndex_[key1].size();
358 RealType xt = xPosUsingGlobalIndex_[key][index];
359 RealType yt = yPosUsingGlobalIndex_[key][index];
360 RealType zt = zPosUsingGlobalIndex_[key][index];
362 RealType z_pos = zPosUsingGlobalIndex_[key1][index];
363 RealType x_pos = xPosUsingGlobalIndex_[key1][index];
364 RealType y_pos = yPosUsingGlobalIndex_[key1][index];
365 RealType r2 = (xt - x_pos) * (xt - x_pos) +
366 (yt - y_pos) * (yt - y_pos) +
367 (zt - z_pos) * (zt - z_pos);
369 RealType charge_for_atom =
370 totalChargeUsingGlobalIndex_[key1][index];
371 RealType chargeDiff =
372 fabs(charge_for_atom - averageCharge) > epsilon ?
373 charge_for_atom - averageCharge :
375 RealType gaussian_scale =
376 exp(-r2 / (v_radius2 * 2.0)) /
377 (sqrt(2 * Constants::PI * v_radius * v_radius));
381 charge += chargeDiff * gaussian_scale;
384 charge /= (nProcessed_ * atomNameGlobalIndex_.size());
387 charge = totalChargeUsingGlobalIndex_[key].back();
390 rdfStream << a_name <<
"\t" << x <<
"\t" << y <<
"\t" << z <<
"\t"
395 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
396 "XYZ file: unable to open %s\n", outputFilename_.c_str());
397 painCave.isFatal = 1;
AtomType * getAtomType()
Returns the AtomType of this Atom.
AtomType is what OpenMD looks to for unchanging data about an atom.
RealType GetVdwRad(int atomicnum)
int GetAtomicNum(const char *str)
bool isDynamic()
Tests if the result from evaluation of script is dynamic.
StuntDouble * nextSelected(int &i)
Finds the next selected StuntDouble in the selection.
StuntDouble * beginSelected(int &i)
Finds the first selected StuntDouble in the selection.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
SnapshotManager * getSnapshotManager()
Returns the snapshot manager.
Mat3x3d getHmat()
Returns the H-Matrix.
void wrapVector(Vector3d &v)
Wrapping the vector according to periodic boundary condition.
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
RealType getFlucQPos()
Returns the current fluctuating charge of this stuntDouble.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)