OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
MultipoleSum.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
48#include "applications/staticProps/MultipoleSum.hpp"
49
50#include <fstream>
51
52#include "io/DumpReader.hpp"
53#include "primitives/Atom.hpp"
55#include "types/MultipoleAdapter.hpp"
56#include "utils/simError.h"
57
58namespace OpenMD {
59
60 MultipoleSum::MultipoleSum(SimInfo* info, const std::string& filename,
61 const std::string& sele1, RealType rmax,
62 int nrbins) :
63 StaticAnalyser(info, filename, nrbins),
64 nRBins_(nrbins), rMax_(rmax), selectionScript1_(sele1), seleMan1_(info),
65 evaluator1_(info) {
66 setOutputName(getPrefix(filename) + ".multipoleSum");
67
68 evaluator1_.loadScriptString(sele1);
69 if (!evaluator1_.isDynamic()) {
70 seleMan1_.setSelectionSet(evaluator1_.evaluate());
71 }
72
73 aveDlength_.clear();
74 aveDlength_.resize(nRBins_, 0.0);
75 aveQlength_.clear();
76 aveQlength_.resize(nRBins_, 0.0);
77 aveDcount_.clear();
78 aveDcount_.resize(nRBins_, 0.0);
79 aveQcount_.clear();
80 aveQcount_.resize(nRBins_, 0.0);
81 aveDproj_.clear();
82 aveDproj_.resize(nRBins_, 0.0);
83 deltaR_ = rMax_ / nRBins_;
84 }
85
86 void MultipoleSum::process() {
87 Molecule* mol;
88 SimInfo::MoleculeIterator miter;
89 vector<Atom*>::iterator aiter;
90 Atom* atom;
91 StuntDouble* sd1;
92 int i1;
93 Vector3d pos1;
94 Vector3d ri;
95 std::vector<RealType> dipoleHist(nRBins_, 0.0);
96 std::vector<RealType> qpoleHist(nRBins_, 0.0);
97 std::vector<int> lengthCount(nRBins_, 0);
98 std::vector<Vector3d> totalDipole;
99 std::vector<Mat3x3d> totalQpole;
100 std::vector<int> dipoleCount;
101 std::vector<int> qpoleCount;
102 std::vector<RealType> dipoleProjection;
103 Vector3d dipole;
104 Mat3x3d qpole;
105 bool usePeriodicBoundaryConditions_ =
106 info_->getSimParams()->getUsePeriodicBoundaryConditions();
107
108 DumpReader reader(info_, dumpFilename_);
109 int nFrames = reader.getNFrames();
110
111 for (int i = 0; i < nFrames; i += step_) {
112 reader.readFrame(i);
113 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
114
115 if (evaluator1_.isDynamic()) {
116 seleMan1_.setSelectionSet(evaluator1_.evaluate());
117 }
118
119 for (sd1 = seleMan1_.beginSelected(i1); sd1 != NULL;
120 sd1 = seleMan1_.nextSelected(i1)) {
121 pos1 = sd1->getPos();
122
123 totalDipole.clear();
124 totalDipole.resize(nRBins_, V3Zero);
125 dipoleCount.clear();
126 dipoleCount.resize(nRBins_, 0);
127 totalQpole.clear();
128 totalQpole.resize(nRBins_, M3Zero);
129 qpoleCount.clear();
130 qpoleCount.resize(nRBins_, 0);
131 dipoleProjection.clear();
132 dipoleProjection.resize(nRBins_, 0.0);
133
134 for (mol = info_->beginMolecule(miter); mol != NULL;
135 mol = info_->nextMolecule(miter)) {
136 for (atom = mol->beginAtom(aiter); atom != NULL;
137 atom = mol->nextAtom(aiter)) {
138 // ri is vector difference between central site and this atom:
139 ri = atom->getPos() - pos1;
140
141 if (usePeriodicBoundaryConditions_)
142 currentSnapshot_->wrapVector(ri);
143
144 dipole = V3Zero;
145 qpole = M3Zero;
146 AtomType* atype2 = atom->getAtomType();
147 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
148
149 if (ma2.isDipole()) dipole = atom->getDipole();
150 if (ma2.isQuadrupole()) qpole = atom->getQuadrupole();
151
152 RealType distance = ri.length();
153 std::size_t bin = int(distance / deltaR_);
154 // this multipole is contained within the cutoff spheres that are
155 // larger than the bin:
156 if (bin < nRBins_) {
157 for (std::size_t j = bin; j < nRBins_; j++) {
158 totalDipole[j] += dipole;
159 dipoleCount[j]++;
160 totalQpole[j] += qpole;
161 qpoleCount[j]++;
162 }
163 }
164 }
165 }
166 Vector3d myDipole = sd1->getDipole();
167
168 for (std::size_t j = 0; j < nRBins_; j++) {
169 RealType myProjection =
170 dot(myDipole, totalDipole[j]) / myDipole.length();
171
172 RealType dipoleLength = totalDipole[j].length();
173 RealType Qtrace = totalQpole[j].trace();
174 RealType Qddot = doubleDot(totalQpole[j], totalQpole[j]);
175 RealType qpoleLength = 2.0 * (3.0 * Qddot - Qtrace * Qtrace);
176 dipoleHist[j] += dipoleLength;
177 qpoleHist[j] += qpoleLength;
178 aveDcount_[j] += dipoleCount[j];
179 aveQcount_[j] += qpoleCount[j];
180 lengthCount[j] += 1;
181 dipoleProjection[j] += myProjection;
182 }
183 }
184 }
185
186 int nSelected = seleMan1_.getSelectionCount();
187 for (std::size_t j = 0; j < nRBins_; j++) {
188 if (lengthCount[j] > 0) {
189 aveDlength_[j] = dipoleHist[j] / RealType(lengthCount[j]);
190 aveQlength_[j] = qpoleHist[j] / RealType(lengthCount[j]);
191 aveDcount_[j] /= RealType(nSelected);
192 aveQcount_[j] /= RealType(nSelected);
193 aveDproj_[j] = dipoleProjection[j] / RealType(lengthCount[j]);
194 } else {
195 aveDlength_[j] = 0.0;
196 aveQlength_[j] = 0.0;
197 aveDcount_[j] = 0.0;
198 aveQcount_[j] = 0.0;
199 aveDproj_[j] = 0.0;
200 }
201 }
202 writeOut();
203 }
204
205 void MultipoleSum::writeOut() {
206 ofstream os(getOutputFileName().c_str());
207 os << "#multipole sum\n";
208 os << "#selection1: (" << selectionScript1_ << ")\t";
209 os << "#r\taveDlength\taveDdensity\taveDproj\taveQlength\taveQdensity\n";
210
211 for (std::size_t i = 0; i < nRBins_; ++i) {
212 RealType r = deltaR_ * i;
213 os << r << "\t" << aveDlength_[i] << "\t"
214 << aveDlength_[i] / aveDcount_[i] << "\t" << aveDproj_[i] << "\t"
215 << aveQlength_[i] << "\t" << aveQlength_[i] / aveQcount_[i] << "\n";
216 }
217 os.close();
218 }
219} // namespace OpenMD
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:96
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Real doubleDot(const RectMatrix< Real, Row, Col > &t1, const RectMatrix< Real, Row, Col > &t2)
Returns the tensor contraction (double dot product) of two rank 2 tensors (or Matrices).
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
std::string getPrefix(const std::string &str)
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.