OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
DensityPlot.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45#include "applications/staticProps/DensityPlot.hpp"
46
47#include <algorithm>
48#include <functional>
49#include <memory>
50
51#include "io/DumpReader.hpp"
53#include "types/LennardJonesAdapter.hpp"
54#include "utils/Constants.hpp"
55#include "utils/simError.h"
56
57using namespace std;
58
59namespace OpenMD {
60
61 DensityPlot::DensityPlot(SimInfo* info, const std::string& filename,
62 const std::string& sele, const std::string& cmSele,
63 RealType len, int nrbins) :
64 StaticAnalyser(info, filename, nrbins),
65 len_(len), halfLen_(len / 2), nRBins_(nrbins), selectionScript_(sele),
66 seleMan_(info), evaluator_(info), cmSelectionScript_(cmSele),
67 cmSeleMan_(info), cmEvaluator_(info) {
68 setOutputName(getPrefix(filename) + ".density");
69
70 deltaR_ = len_ / nRBins_;
71 histogram_.resize(nRBins_);
72 density_.resize(nRBins_);
73
74 std::fill(histogram_.begin(), histogram_.end(), 0);
75
76 evaluator_.loadScriptString(sele);
77
78 if (!evaluator_.isDynamic()) {
79 seleMan_.setSelectionSet(evaluator_.evaluate());
80 }
81
82 cmEvaluator_.loadScriptString(cmSele);
83 if (!cmEvaluator_.isDynamic()) {
84 cmSeleMan_.setSelectionSet(cmEvaluator_.evaluate());
85 }
86 }
87
88 void DensityPlot::process() {
89 bool usePeriodicBoundaryConditions_ =
90 info_->getSimParams()->getUsePeriodicBoundaryConditions();
91
92 DumpReader reader(info_, dumpFilename_);
93 int nFrames = reader.getNFrames();
94 for (int i = 0; i < nFrames; i += step_) {
95 reader.readFrame(i);
96 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
97
98 if (evaluator_.isDynamic()) {
99 seleMan_.setSelectionSet(evaluator_.evaluate());
100 }
101
102 if (cmEvaluator_.isDynamic()) {
103 cmSeleMan_.setSelectionSet(cmEvaluator_.evaluate());
104 }
105
106 Vector3d origin = calcNewOrigin();
107
108 Mat3x3d hmat = currentSnapshot_->getHmat();
109 RealType slabVolume = deltaR_ * hmat(0, 0) * hmat(1, 1);
110 int k;
111 for (StuntDouble* sd = seleMan_.beginSelected(k); sd != NULL;
112 sd = seleMan_.nextSelected(k)) {
113 if (!sd->isAtom()) {
114 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
115 "Can not calculate electron density if it is not atom\n");
116 painCave.severity = OPENMD_ERROR;
117 painCave.isFatal = 1;
118 simError();
119 }
120
121 Atom* atom = static_cast<Atom*>(sd);
122 std::shared_ptr<GenericData> data =
123 atom->getAtomType()->getPropertyByName("nelectron");
124 if (data == nullptr) {
125 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
126 "Can not find Parameters for nelectron\n");
127 painCave.severity = OPENMD_ERROR;
128 painCave.isFatal = 1;
129 simError();
130 }
131
132 std::shared_ptr<DoubleGenericData> doubleData =
133 std::dynamic_pointer_cast<DoubleGenericData>(data);
134 if (doubleData == nullptr) {
135 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
136 "Can not cast GenericData to DoubleGenericData\n");
137 painCave.severity = OPENMD_ERROR;
138 painCave.isFatal = 1;
139 simError();
140 }
141
142 RealType nelectron = doubleData->getData();
143 LennardJonesAdapter lja = LennardJonesAdapter(atom->getAtomType());
144 RealType sigma = lja.getSigma() * 0.5;
145 RealType sigma2 = sigma * sigma;
146
147 Vector3d pos = sd->getPos() - origin;
148 for (int j = 0; j < nRBins_; ++j) {
149 Vector3d tmp(pos);
150 RealType zdist = j * deltaR_ - halfLen_;
151 tmp[2] += zdist;
152 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(tmp);
153
154 RealType wrappedZdist = tmp.z() + halfLen_;
155 if (wrappedZdist < 0.0 || wrappedZdist > len_) { continue; }
156
157 int which = int(wrappedZdist / deltaR_);
158 density_[which] +=
159 nelectron * exp(-zdist * zdist / (sigma2 * 2.0)) /
160 (slabVolume * sqrt(2 * Constants::PI * sigma * sigma));
161 }
162 }
163 }
164
165 int nProcessed = nFrames / step_;
166 std::transform(
167 density_.begin(), density_.end(), density_.begin(),
168 std::bind(std::divides<RealType>(), std::placeholders::_1, nProcessed));
169 writeDensity();
170 }
171
172 Vector3d DensityPlot::calcNewOrigin() {
173 int i;
174 Vector3d newOrigin(0.0);
175 RealType totalMass = 0.0;
176 for (StuntDouble* sd = seleMan_.beginSelected(i); sd != NULL;
177 sd = seleMan_.nextSelected(i)) {
178 RealType mass = sd->getMass();
179 totalMass += mass;
180 newOrigin += sd->getPos() * mass;
181 }
182 newOrigin /= totalMass;
183 return newOrigin;
184 }
185
186 void DensityPlot::writeDensity() {
187 std::ofstream ofs(outputFilename_.c_str(), std::ios::binary);
188 if (ofs.is_open()) {
189 ofs << "#g(x, y, z)\n";
190 ofs << "#selection: (" << selectionScript_ << ")\n";
191 ofs << "#cmSelection:(" << cmSelectionScript_ << ")\n";
192 ofs << "#nRBins = " << nRBins_ << "\t maxLen = " << len_
193 << "\tdeltaR = " << deltaR_ << "\n";
194 for (unsigned int i = 0; i < histogram_.size(); ++i) {
195 ofs << i * deltaR_ - halfLen_ << "\t" << density_[i] << std::endl;
196 }
197 } else {
198 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
199 "DensityPlot: unable to open %s\n", outputFilename_.c_str());
200 painCave.isFatal = 1;
201 simError();
202 }
203
204 ofs.close();
205 }
206
207} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)