OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
Kirkwood.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/Kirkwood.hpp"
49
50#include <algorithm>
51#include <fstream>
52#include <sstream>
53
54#include "types/MultipoleAdapter.hpp"
55#include "utils/Revision.hpp"
56#include "utils/simError.h"
57
58namespace OpenMD {
59
60 Kirkwood::Kirkwood(SimInfo* info, const std::string& filename,
61 const std::string& sele1, const std::string& sele2,
62 RealType len, int nrbins) :
63 RadialDistrFunc(info, filename, sele1, sele2, nrbins),
64 len_(len) {
65 setAnalysisType("Distance-dependent Kirkwood G-factor");
66 setOutputName(getPrefix(filename) + ".kirkwood");
67
68 deltaR_ = len_ / nBins_;
69
70 histogram_.resize(nBins_);
71 avgKirkwood_.resize(nBins_);
72 std::stringstream params;
73 params << " len = " << len_ << ", nrbins = " << nBins_;
74 const std::string paramString = params.str();
75 setParameterString(paramString);
76 }
77
78 void Kirkwood::preProcess() {
79 std::fill(avgKirkwood_.begin(), avgKirkwood_.end(), 0.0);
80 }
81
82 void Kirkwood::initializeHistogram() {
83 std::fill(histogram_.begin(), histogram_.end(), 0);
84 }
85
86 void Kirkwood::processHistogram() {
87 int nSelected1 = seleMan1_.getSelectionCount();
88 for (unsigned int i = 0; i < histogram_.size(); ++i) {
89 avgKirkwood_[i] += histogram_[i] / nSelected1;
90 }
91 }
92
93 void Kirkwood::collectHistogram(StuntDouble* sd1, StuntDouble* sd2) {
94 if (sd1 == sd2) { return; }
95 bool usePeriodicBoundaryConditions_ =
96 info_->getSimParams()->getUsePeriodicBoundaryConditions();
97
98 Vector3d pos1 = sd1->getPos();
99 Vector3d pos2 = sd2->getPos();
100 Vector3d r12 = pos2 - pos1;
101 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
102
103 RealType distance = r12.length();
104
105 AtomType* atype1 = static_cast<Atom*>(sd1)->getAtomType();
106 AtomType* atype2 = static_cast<Atom*>(sd2)->getAtomType();
107
108 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
109 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
110
111 Vector3d d1(0.0);
112 Vector3d d2(0.0);
113 RealType dotProduct(0.0);
114
115 if (ma1.isDipole()) {
116 d1 = sd1->getDipole();
117 d1.normalize();
118 if (ma2.isDipole()) {
119 d2 = sd2->getDipole();
120 d2.normalize();
121 dotProduct = dot(d1, d2);
122 }
123 }
124
125 if (distance < len_) {
126 int whichBin = int(distance / deltaR_);
127 // each dipole pair contributes to all of the radii that contain it.
128 for (unsigned int i = whichBin; i < nBins_; i++) {
129 histogram_[i] += dotProduct;
130 }
131 }
132 }
133
134 void Kirkwood::writeRdf() {
135 std::ofstream ofs(outputFilename_.c_str());
136 if (ofs.is_open()) {
137 Revision r;
138 ofs << "# " << getAnalysisType() << "\n";
139 ofs << "# OpenMD " << r.getFullRevision() << "\n";
140 ofs << "# " << r.getBuildDate() << "\n";
141 ofs << "# selection script1: \"" << selectionScript1_;
142 ofs << "\"\tselection script2: \"" << selectionScript2_ << "\"\n";
143 if (!paramString_.empty())
144 ofs << "# parameters: " << paramString_ << "\n";
145
146 ofs << "#r\tcorrValue\n";
147 for (unsigned int i = 0; i < avgKirkwood_.size(); ++i) {
148 RealType r = deltaR_ * (i + 0.5);
149 ofs << r << "\t" << avgKirkwood_[i] / nProcessed_ << "\n";
150 }
151 } else {
152 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
153 "Kirkwood: unable to open %s\n", outputFilename_.c_str());
154 painCave.isFatal = 1;
155 simError();
156 }
157 ofs.close();
158 }
159
160 KirkwoodQuadrupoles::KirkwoodQuadrupoles(SimInfo* info,
161 const std::string& filename,
162 const std::string& sele1,
163 const std::string& sele2,
164 RealType len, int nrbins) :
165 Kirkwood(info, filename, sele1, sele2, len, nrbins) {
166 setAnalysisType("Distance-dependent Kirkwood G-factor for quadrupoles");
167 setOutputName(getPrefix(filename) + ".kirkwoodQ");
168 }
169
170 void KirkwoodQuadrupoles::collectHistogram(StuntDouble* sd1,
171 StuntDouble* sd2) {
172 if (sd1 == sd2) { return; }
173 bool usePeriodicBoundaryConditions_ =
174 info_->getSimParams()->getUsePeriodicBoundaryConditions();
175
176 Vector3d pos1 = sd1->getPos();
177 Vector3d pos2 = sd2->getPos();
178 Vector3d r12 = pos2 - pos1;
179 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
180
181 RealType distance = r12.length();
182
183 AtomType* atype1 = static_cast<Atom*>(sd1)->getAtomType();
184 AtomType* atype2 = static_cast<Atom*>(sd2)->getAtomType();
185
186 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
187 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
188
189 Mat3x3d Q1(0.0);
190 Mat3x3d Q2(0.0);
191 RealType trQ1(0.0);
192 RealType trQ2(0.0);
193 RealType Q1dQ1(0.0);
194 RealType Q2dQ2(0.0);
195
196 RealType quadrupoleProduct(0.0);
197
198 // Similar to the dipole case, but the effective quadrupole moment
199 // is defined (in our electrostatics work) as:
200 // sqrt (3 Q:Q - Tr(Q)^2 )
201 // so normalization is a bit different. Here : denotes a
202 // contraction (double dot product) of the quadrupole tensor.
203
204 if (ma1.isQuadrupole()) {
205 Q1 = sd1->getQuadrupole();
206 trQ1 = Q1.trace();
207 Q1dQ1 = doubleDot(Q1, Q1);
208 Q1 /= sqrt(3.0 * Q1dQ1 - trQ1 * trQ1);
209 // recompute the trace after normalizing:
210 trQ1 = Q1.trace();
211
212 if (ma2.isQuadrupole()) {
213 Q2 = sd2->getQuadrupole();
214 trQ2 = Q2.trace();
215 Q2dQ2 = doubleDot(Q2, Q2);
216 Q2 /= sqrt(3.0 * Q2dQ2 - trQ2 * trQ2);
217 // recompute the trace after normalizing:
218 trQ2 = Q2.trace();
219
220 quadrupoleProduct = 3.0 * doubleDot(Q1, Q2) - trQ1 * trQ2;
221 }
222 }
223
224 if (distance < len_) {
225 int whichBin = int(distance / deltaR_);
226 // each dipole pair contributes to all of the radii that contain it.
227 for (unsigned int i = whichBin; i < nBins_; i++) {
228 histogram_[i] += quadrupoleProduct;
229 }
230 }
231 }
232} // namespace OpenMD
Radial Distribution Function.
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.