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