OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
PotDiff.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 following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
49
50#include <algorithm>
51#include <functional>
52
55#include "io/DumpReader.hpp"
57#include "types/FixedChargeAdapter.hpp"
58#include "types/FluctuatingChargeAdapter.hpp"
59#include "utils/simError.h"
60
61namespace OpenMD {
62
63 PotDiff::PotDiff(SimInfo* info, const std::string& filename,
64 const std::string& sele) :
65 StaticAnalyser(info, filename, 1),
66 selectionScript_(sele), seleMan_(info), evaluator_(info) {
67 StuntDouble* sd;
68 int i;
69
70 setOutputName(getPrefix(filename) + ".potDiff");
71
72 // The PotDiff is computed by negating the charge on the atom type
73 // using fluctuating charge values. If we don't have any
74 // fluctuating charges in the simulation, we need to expand
75 // storage to hold them.
76 int atomStorageLayout = info_->getAtomStorageLayout();
77 int rigidBodyStorageLayout = info->getRigidBodyStorageLayout();
78 int cutoffGroupStorageLayout = info->getCutoffGroupStorageLayout();
79
80 atomStorageLayout |= DataStorage::dslFlucQPosition;
81 atomStorageLayout |= DataStorage::dslFlucQVelocity;
82 atomStorageLayout |= DataStorage::dslFlucQForce;
83
84 info_->setAtomStorageLayout(atomStorageLayout);
85 info_->setSnapshotManager(new SimSnapshotManager(info_, atomStorageLayout,
86 rigidBodyStorageLayout,
87 cutoffGroupStorageLayout));
88
89 // now we have to figure out which AtomTypes to convert to fluctuating
90 // charges
91 evaluator_.loadScriptString(sele);
92 seleMan_.setSelectionSet(evaluator_.evaluate());
93 for (sd = seleMan_.beginSelected(i); sd != NULL;
94 sd = seleMan_.nextSelected(i)) {
95 AtomType* at = static_cast<Atom*>(sd)->getAtomType();
97 if (fqa.isFluctuatingCharge()) {
98 selectionWasFlucQ_.push_back(true);
99 } else {
100 selectionWasFlucQ_.push_back(false);
101 // make a fictitious fluctuating charge with an unphysical
102 // charge mass and slaterN, but we need to zero out the
103 // electronegativity and hardness to remove the self
104 // contribution:
105 fqa.makeFluctuatingCharge(1.0e9, 0.0, 0.0, 1);
106 sd->setFlucQPos(0.0);
107 }
108 }
109 info_->getSnapshotManager()->advance();
110 }
111
113 StuntDouble* sd;
114 int j;
115
116 diff_.clear();
117 DumpReader reader(info_, dumpFilename_);
118 int nFrames = reader.getNFrames();
119
120 // We'll need the force manager to compute the potential
121 ForceManager* forceMan = new ForceManager(info_);
122
123 // We'll need thermo to report the potential
124 Thermo* thermo = new Thermo(info_);
125
126 for (int i = 0; i < nFrames; i += step_) {
127 reader.readFrame(i);
128 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
129
130 for (sd = seleMan_.beginSelected(j); sd != NULL;
131 sd = seleMan_.nextSelected(j)) {
132 if (!selectionWasFlucQ_[j]) { sd->setFlucQPos(0.0); }
133 }
134
135 forceMan->calcForces();
136 RealType pot1 = thermo->getPotential();
137
138 if (evaluator_.isDynamic()) {
139 seleMan_.setSelectionSet(evaluator_.evaluate());
140 }
141
142 for (sd = seleMan_.beginSelected(j); sd != NULL;
143 sd = seleMan_.nextSelected(j)) {
144 AtomType* at = static_cast<Atom*>(sd)->getAtomType();
145
148
149 RealType charge = 0.0;
150
151 if (fca.isFixedCharge()) charge += fca.getCharge();
152 if (fqa.isFluctuatingCharge()) charge += sd->getFlucQPos();
153
154 sd->setFlucQPos(-charge);
155 }
156
157 currentSnapshot_->clearDerivedProperties();
158 forceMan->calcForces();
159 RealType pot2 = thermo->getPotential();
160 RealType diff = pot2 - pot1;
161
162 data_.add(diff);
163 diff_.push_back(diff);
164 times_.push_back(currentSnapshot_->getTime());
165
166 info_->getSnapshotManager()->advance();
167 }
168
169 writeDiff();
170 }
171
172 void PotDiff::writeDiff() {
173 std::ofstream ofs(outputFilename_.c_str(), std::ios::binary);
174 if (ofs.is_open()) {
175 RealType mu = data_.getAverage();
176 RealType sigma = data_.getStdDev();
177 RealType m95 = data_.get95percentConfidenceInterval();
178
179 ofs << "#potDiff\n";
180 ofs << "#selection: (" << selectionScript_ << ")\n";
181 ofs << "# <diff> = " << mu << "\n";
182 ofs << "# StdDev = " << sigma << "\n";
183 ofs << "# 95% confidence interval = " << m95 << "\n";
184 ofs << "# t\tdiff[t]\n";
185 for (unsigned int i = 0; i < diff_.size(); ++i) {
186 ofs << times_[i] << "\t" << diff_[i] << "\n";
187 }
188
189 } else {
190 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
191 "PotDiff: unable to open %s\n", outputFilename_.c_str());
192 painCave.isFatal = 1;
193 simError();
194 }
195 ofs.close();
196 }
197
198} // namespace OpenMD
StaticAnalyser for Potential Energy changes with charges turned off.
AtomType is what OpenMD looks to for unchanging data about an atom.
Definition AtomType.hpp:69
int getNFrames()
Returns the number of frames in the dump file.
ForceManager is responsible for calculating both the short range (bonded) interactions and long range...
virtual void process()
Process the data.
Definition PotDiff.cpp:112
PotDiff(SimInfo *info, const std::string &filename, const std::string &sele)
Default constructor.
Definition PotDiff.cpp:63
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:96
"brains/SimSnapshotManager.hpp"
"Don't move, or you're dead! Stand up! Captain, we've got them!"
void setFlucQPos(RealType charge)
Sets the current fluctuating charge of this stuntDouble.
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)