48#include "applications/staticProps/ChargeDensityZ.hpp"
53#include "brains/Thermo.hpp"
56#include "types/FixedChargeAdapter.hpp"
57#include "types/FluctuatingChargeAdapter.hpp"
58#include "utils/Constants.hpp"
59#include "utils/simError.h"
63 ChargeDensityZ::ChargeDensityZ(
SimInfo* info,
const std::string& filename,
64 const std::string& sele,
int nzbins,
65 RealType vRadius, std::string atomName,
66 bool xyzGen,
int axis) :
68 selectionScript_(sele), evaluator_(info), seleMan_(info), thermo_(info),
69 axis_(axis), vRadius_(vRadius), fileName_(filename),
70 atomFlucCharge_(atomName), genXYZ_(xyzGen) {
71 evaluator_.loadScriptString(sele);
72 if (!evaluator_.isDynamic()) {
73 seleMan_.setSelectionSet(evaluator_.evaluate());
78 densityZAverageAllFrame_.resize(nBins_);
79 densityFlucZAverageAllFrame_.resize(nBins_);
80 absDensityFlucZAverageAllFrame_.resize(nBins_);
81 averageDensityZ_.resize(nBins_);
82 flucDensityZAverageAllFrame_.resize(nBins_);
83 std::fill(densityFlucZAverageAllFrame_.begin(),
84 densityFlucZAverageAllFrame_.end(), 0);
85 std::fill(densityZAverageAllFrame_.begin(), densityZAverageAllFrame_.end(),
87 std::fill(absDensityFlucZAverageAllFrame_.begin(),
88 absDensityFlucZAverageAllFrame_.end(), 0);
89 std::fill(averageDensityZ_.begin(), averageDensityZ_.end(), 0);
90 std::fill(flucDensityZAverageAllFrame_.begin(),
91 flucDensityZAverageAllFrame_.end(), 0);
93 densityFlucZAverageFirstFrame_.resize(nBins_);
94 absDensityFlucZAverageFirstFrame_.resize(nBins_);
95 std::fill(densityFlucZAverageFirstFrame_.begin(),
96 densityFlucZAverageFirstFrame_.end(), 0);
97 std::fill(absDensityFlucZAverageFirstFrame_.begin(),
98 absDensityFlucZAverageFirstFrame_.end(), 0);
113 setOutputName(
getPrefix(filename) +
".ChargeDensityZ");
115 void ChargeDensityZ::process() {
116 bool usePeriodicBoundaryConditions_ =
117 info_->getSimParams()->getUsePeriodicBoundaryConditions();
119 DumpReader reader(info_, dumpFilename_);
120 int nFrames_ = reader.getNFrames();
121 nProcessed_ = nFrames_ / step_;
126 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
128 hmat_ = currentSnapshot_->getHmat();
129 zBox_.push_back(hmat_(axis_, axis_));
131 std::vector<RealType>::iterator j;
133 for (j = zBox_.begin(); j != zBox_.end(); ++j) {
137 RealType zAve = zSum / zBox_.size();
139 axisValues.insert(0);
140 axisValues.insert(1);
141 axisValues.insert(2);
142 axisValues.erase(axis_);
143 set<int>::iterator axis_it;
144 std::vector<int> cartesian_axis;
145 for (axis_it = axisValues.begin(); axis_it != axisValues.end(); ++axis_it) {
146 cartesian_axis.push_back(*axis_it);
148 x_ = cartesian_axis[0];
149 y_ = cartesian_axis[1];
150 RealType area = hmat_(x_, x_) * hmat_(y_, y_);
151 RealType sliceVolume = zAve / densityZAverageAllFrame_.size() * area;
153 for (
int i = 1; i < nFrames_; i += step_) {
155 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
157 if (evaluator_.isDynamic()) {
158 seleMan_.setSelectionSet(evaluator_.evaluate());
162 for (StuntDouble* sd = seleMan_.beginSelected(kk); sd != NULL;
163 sd = seleMan_.nextSelected(kk)) {
165 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
166 "Can not calculate charge density distribution if it is not "
168 painCave.severity = OPENMD_ERROR;
169 painCave.isFatal = 1;
174 Atom* atom =
static_cast<Atom*
>(sd);
176 AtomType* atomType = atom->getAtomType();
179 FixedChargeAdapter fca = FixedChargeAdapter(atomType);
180 if (fca.isFixedCharge()) { q += fca.getCharge(); }
182 FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atomType);
183 if (fqa.isFluctuatingCharge()) { q += atom->getFlucQPos(); }
187 std::string atomName;
188 std::vector<AtomType*> atChain = atomType->allYourBase();
189 std::vector<AtomType*>::iterator i;
190 for (i = atChain.begin(); i != atChain.end(); ++i) {
191 atomName = (*i)->getName().c_str();
198 if (obanum == 0) { sigma = vRadius_; }
200 Vector3d pos = sd->getPos();
201 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(pos);
206 int globalIndex = sd->getGlobalIndex();
208 atomNameGlobalIndex_[globalIndex] = atomName;
209 averageChargeUsingGlobalIndex_[globalIndex] =
210 (countUsingGlobalIndex_[globalIndex] *
211 averageChargeUsingGlobalIndex_[globalIndex] +
213 (countUsingGlobalIndex_[globalIndex] + 1);
214 totalChargeUsingGlobalIndex_[globalIndex].push_back(q);
215 zPosUsingGlobalIndex_[globalIndex].push_back(pos[axis_]);
216 xPosUsingGlobalIndex_[globalIndex].push_back(pos[x_]);
217 yPosUsingGlobalIndex_[globalIndex].push_back(pos[y_]);
219 vanderRUsingGlobalIndex_[globalIndex] = sigma;
220 countUsingGlobalIndex_[globalIndex]++;
223 for (std::map<int, std::string>::iterator it =
224 atomNameGlobalIndex_.begin();
225 it != atomNameGlobalIndex_.end(); ++it) {
226 int g_Index = it->first;
227 std::string a_name = it->second;
228 averageChargeForEachType_[a_name] =
229 (SDCount_[a_name] * averageChargeForEachType_[a_name] +
230 totalChargeUsingGlobalIndex_[g_Index].front()) /
231 (SDCount_[a_name] + 1);
235 RealType epsilon = 1e-10;
236 for (std::map<int, std::string>::iterator it = atomNameGlobalIndex_.begin();
237 it != atomNameGlobalIndex_.end(); ++it) {
239 std::string a_name = it->second;
241 RealType averageCharge = averageChargeUsingGlobalIndex_[key];
242 RealType averageChargeUsingFirstFrame = averageChargeForEachType_[a_name];
243 RealType v_radius = vanderRUsingGlobalIndex_[key];
244 RealType v_radius2 = v_radius * v_radius;
245 for (
size_t index = 0; index < zPosUsingGlobalIndex_[key].size();
247 RealType z_pos = zPosUsingGlobalIndex_[key][index];
248 RealType charge = totalChargeUsingGlobalIndex_[key][index];
249 RealType chargeDiff =
250 fabs(charge - averageCharge) > epsilon ? charge - averageCharge : 0;
251 RealType chargeDiffUsingFirstFrameAverage =
252 fabs(charge - averageChargeUsingFirstFrame) > epsilon ?
253 charge - averageChargeUsingFirstFrame :
256 for (
size_t i = 0; i < densityFlucZAverageAllFrame_.size(); ++i) {
257 RealType z = -zAve / 2 + i * zAve / densityZAverageAllFrame_.size();
258 RealType zdist = z_pos - z;
260 RealType gaussian_scale =
261 exp(-zdist * zdist / (v_radius2 * 2.0)) /
262 (sliceVolume * (sqrt(2 * Constants::PI * v_radius * v_radius)));
263 densityZAverageAllFrame_[i] += charge * gaussian_scale;
265 densityFlucZAverageAllFrame_[i] += chargeDiff * gaussian_scale;
266 absDensityFlucZAverageAllFrame_[i] +=
267 abs(chargeDiff) * abs(chargeDiff) * gaussian_scale;
269 densityFlucZAverageFirstFrame_[i] +=
270 chargeDiffUsingFirstFrameAverage * gaussian_scale;
271 absDensityFlucZAverageFirstFrame_[i] +=
272 abs(chargeDiffUsingFirstFrameAverage) *
273 abs(chargeDiffUsingFirstFrameAverage) * gaussian_scale;
280 if (genXYZ_) generateXYZForLastFrame();
283 void ChargeDensityZ::writeDensity() {
285 std::vector<RealType>::iterator j;
287 for (j = zBox_.begin(); j != zBox_.end(); ++j) {
290 RealType zAve = zSum / zBox_.size();
292 std::ofstream rdfStream(outputFilename_.c_str());
293 if (rdfStream.is_open()) {
294 rdfStream <<
"#ChargeDensityZ "
296 rdfStream <<
"#selection: (" << selectionScript_ <<
")\n";
299 <<
"\tchargeDensity\tchargeDensityFluctuations_Average_on_all_frame\t"
300 <<
"Absolute_chargeDensityFluctuations_Average_on_all_frame\t"
301 <<
"chargeDensityFluctuations_Average_On_first_frame\t"
302 <<
"Absolute_chargeDensityFluctuations_Average_on_first_frame\n";
304 for (
unsigned int i = 0; i < densityFlucZAverageAllFrame_.size(); ++i) {
305 RealType z = zAve * (i + 0.5) / densityFlucZAverageAllFrame_.size();
306 rdfStream << z <<
"\t" << densityZAverageAllFrame_[i] / nProcessed_
307 <<
"\t" << densityFlucZAverageAllFrame_[i] / (nProcessed_)
308 <<
"\t" << absDensityFlucZAverageAllFrame_[i] / (nProcessed_)
309 <<
"\t" << densityFlucZAverageFirstFrame_[i] / (nProcessed_)
311 << absDensityFlucZAverageFirstFrame_[i] / (nProcessed_)
316 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
317 "ChargeDensityZ: unable to open %s\n", outputFilename_.c_str());
318 painCave.isFatal = 1;
325 void ChargeDensityZ::generateXYZForLastFrame() {
326 std::string XYZFile(
getPrefix(fileName_) +
".xyz");
327 std::ofstream rdfStream(XYZFile.c_str());
328 int nAtoms = zPosUsingGlobalIndex_.size();
330 if (rdfStream.is_open()) {
331 rdfStream << nAtoms <<
"\n";
332 rdfStream << 1 <<
";\t" << hmat_(x_, x_) <<
"\t" << hmat_(x_, y_) <<
"\t"
333 << hmat_(x_, axis_) <<
"\t" << hmat_(y_, x_) <<
"\t"
334 << hmat_(y_, y_) <<
"\t" << hmat_(y_, axis_) <<
"\t"
335 << hmat_(axis_, x_) <<
"\t" << hmat_(axis_, y_) <<
"\t"
336 << hmat_(axis_, axis_) <<
"\n";
338 for (std::map<int, std::string>::iterator it =
339 atomNameGlobalIndex_.begin();
340 it != atomNameGlobalIndex_.end(); ++it) {
342 std::string a_name = it->second;
343 RealType x = zPosUsingGlobalIndex_[key].back();
344 RealType y = xPosUsingGlobalIndex_[key].back();
345 RealType z = yPosUsingGlobalIndex_[key].back();
348 if (a_name == atomFlucCharge_) {
349 for (std::map<int, std::string>::iterator it1 =
350 atomNameGlobalIndex_.begin();
351 it1 != atomNameGlobalIndex_.end(); ++it1) {
352 int key1 = it1->first;
353 std::string a_name1 = it1->second;
355 RealType v_radius = vanderRUsingGlobalIndex_[key1];
356 RealType v_radius2 = v_radius * v_radius;
357 RealType averageCharge = averageChargeUsingGlobalIndex_[key1];
359 for (
size_t index = 0; index < zPosUsingGlobalIndex_[key1].size();
361 RealType xt = xPosUsingGlobalIndex_[key][index];
362 RealType yt = yPosUsingGlobalIndex_[key][index];
363 RealType zt = zPosUsingGlobalIndex_[key][index];
365 RealType z_pos = zPosUsingGlobalIndex_[key1][index];
366 RealType x_pos = xPosUsingGlobalIndex_[key1][index];
367 RealType y_pos = yPosUsingGlobalIndex_[key1][index];
368 RealType r2 = (xt - x_pos) * (xt - x_pos) +
369 (yt - y_pos) * (yt - y_pos) +
370 (zt - z_pos) * (zt - z_pos);
372 RealType charge_for_atom =
373 totalChargeUsingGlobalIndex_[key1][index];
374 RealType chargeDiff =
375 fabs(charge_for_atom - averageCharge) > epsilon ?
376 charge_for_atom - averageCharge :
378 RealType gaussian_scale =
379 exp(-r2 / (v_radius2 * 2.0)) /
380 (sqrt(2 * Constants::PI * v_radius * v_radius));
384 charge += chargeDiff * gaussian_scale;
387 charge /= (nProcessed_ * atomNameGlobalIndex_.size());
390 charge = totalChargeUsingGlobalIndex_[key].back();
393 rdfStream << a_name <<
"\t" << x <<
"\t" << y <<
"\t" << z <<
"\t"
398 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
399 "XYZ file: unable to open %s\n", outputFilename_.c_str());
400 painCave.isFatal = 1;
RealType GetVdwRad(int atomicnum)
int GetAtomicNum(const char *str)
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)