ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/perturbations/UniformGradient.cpp
Revision: 2047
Committed: Thu Dec 11 16:16:43 2014 UTC (10 years, 4 months ago) by gezelter
File size: 8290 byte(s)
Log Message:
Added UniformGradient to perturbation list.

File Contents

# User Rev Content
1 gezelter 2026 /*
2     * Copyright (c) 2014 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9     * 1. Redistributions of source code must retain the above copyright
10     * notice, this list of conditions and the following disclaimer.
11     *
12     * 2. Redistributions in binary form must reproduce the above copyright
13     * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the
15     * distribution.
16     *
17     * This software is provided "AS IS," without a warranty of any
18     * kind. All express or implied conditions, representations and
19     * warranties, including any implied warranty of merchantability,
20     * fitness for a particular purpose or non-infringement, are hereby
21     * excluded. The University of Notre Dame and its licensors shall not
22     * be liable for any damages suffered by licensee as a result of
23     * using, modifying or distributing the software or its
24     * derivatives. In no event will the University of Notre Dame or its
25     * licensors be liable for any lost revenue, profit or data, or for
26     * direct, indirect, special, consequential, incidental or punitive
27     * damages, however caused and regardless of the theory of liability,
28     * arising out of the use of or inability to use software, even if the
29     * University of Notre Dame has been advised of the possibility of
30     * such damages.
31     *
32     * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     * research, please cite the appropriate papers when you publish your
34     * work. Good starting points are:
35     *
36     * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37     * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38     * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39     * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41     */
42    
43     #include "perturbations/UniformGradient.hpp"
44     #include "types/FixedChargeAdapter.hpp"
45     #include "types/FluctuatingChargeAdapter.hpp"
46     #include "types/MultipoleAdapter.hpp"
47     #include "primitives/Molecule.hpp"
48     #include "nonbonded/NonBondedInteraction.hpp"
49     #include "utils/PhysicalConstants.hpp"
50    
51     namespace OpenMD {
52    
53     UniformGradient::UniformGradient(SimInfo* info) : info_(info),
54     doUniformGradient(false),
55     doParticlePot(false),
56     initialized(false) {
57     simParams = info_->getSimParams();
58     }
59    
60     void UniformGradient::initialize() {
61 gezelter 2034
62     bool haveA = false;
63     bool haveB = false;
64     bool haveG = false;
65    
66     if (simParams->haveUniformGradientDirection1()) {
67     std::vector<RealType> d1 = simParams->getUniformGradientDirection1();
68     if (d1.size() != 3) {
69 gezelter 2026 sprintf(painCave.errMsg,
70 gezelter 2034 "uniformGradientDirection1: Incorrect number of parameters\n"
71     "\tspecified. There should be 3 parameters, but %lu were\n"
72     "\tspecified.\n", d1.size());
73 gezelter 2026 painCave.isFatal = 1;
74     simError();
75     }
76 gezelter 2034 a_.x() = d1[0];
77     a_.y() = d1[1];
78     a_.z() = d1[2];
79 gezelter 2026
80 gezelter 2034 a_.normalize();
81     haveA = true;
82     }
83    
84     if (simParams->haveUniformGradientDirection2()) {
85     std::vector<RealType> d2 = simParams->getUniformGradientDirection2();
86     if (d2.size() != 3) {
87     sprintf(painCave.errMsg,
88     "uniformGradientDirection2: Incorrect number of parameters\n"
89     "\tspecified. There should be 3 parameters, but %lu were\n"
90     "\tspecified.\n", d2.size());
91     painCave.isFatal = 1;
92     simError();
93     }
94     b_.x() = d2[0];
95     b_.y() = d2[1];
96     b_.z() = d2[2];
97    
98     b_.normalize();
99     haveB = true;
100     }
101    
102     if (simParams->haveUniformGradientStrength()) {
103     g_ = simParams->getUniformGradientStrength();
104     haveG = true;
105     }
106    
107     if (haveA && haveB && haveG) {
108     doUniformGradient = true;
109     cpsi_ = dot(a_, b_);
110    
111     Grad_(0,0) = 2.0 * (a_.x()*b_.x() - cpsi_ / 3.0);
112     Grad_(0,1) = a_.x()*b_.y() + a_.y()*b_.x();
113     Grad_(0,2) = a_.x()*b_.z() + a_.z()*b_.x();
114 gezelter 2026 Grad_(1,0) = Grad_(0,1);
115 gezelter 2034 Grad_(1,1) = 2.0 * (a_.y()*b_.y() - cpsi_ / 3.0);
116     Grad_(1,2) = a_.y()*b_.z() + a_.z()*b_.y();
117 gezelter 2026 Grad_(2,0) = Grad_(0,2);
118     Grad_(2,1) = Grad_(1,2);
119 gezelter 2034 Grad_(2,2) = 2.0 * (a_.z()*b_.z() - cpsi_ / 3.0);
120    
121     Grad_ *= g_ / 2.0;
122 gezelter 2047
123 gezelter 2034 } else {
124     if (!haveA) {
125     sprintf(painCave.errMsg,
126     "UniformGradient: uniformGradientDirection1 not specified.\n");
127     painCave.isFatal = 1;
128     simError();
129     }
130     if (!haveB) {
131     sprintf(painCave.errMsg,
132     "UniformGradient: uniformGradientDirection2 not specified.\n");
133     painCave.isFatal = 1;
134     simError();
135     }
136     if (!haveG) {
137     sprintf(painCave.errMsg,
138     "UniformGradient: uniformGradientStrength not specified.\n");
139     painCave.isFatal = 1;
140     simError();
141     }
142     }
143    
144 gezelter 2026 int storageLayout_ = info_->getSnapshotManager()->getStorageLayout();
145     if (storageLayout_ & DataStorage::dslParticlePot) doParticlePot = true;
146     initialized = true;
147     }
148    
149     void UniformGradient::applyPerturbation() {
150    
151     if (!initialized) initialize();
152    
153     SimInfo::MoleculeIterator i;
154     Molecule::AtomIterator j;
155     Molecule* mol;
156     Atom* atom;
157     AtomType* atype;
158     potVec longRangePotential(0.0);
159    
160     RealType C;
161     Vector3d D;
162     Mat3x3d Q;
163    
164     RealType U;
165     RealType fPot;
166     Vector3d t;
167     Vector3d f;
168    
169     Vector3d r;
170     Vector3d EF;
171    
172     bool isCharge;
173    
174     if (doUniformGradient) {
175    
176     U = 0.0;
177     fPot = 0.0;
178    
179     for (mol = info_->beginMolecule(i); mol != NULL;
180     mol = info_->nextMolecule(i)) {
181    
182     for (atom = mol->beginAtom(j); atom != NULL;
183     atom = mol->nextAtom(j)) {
184    
185     isCharge = false;
186     C = 0.0;
187    
188     atype = atom->getAtomType();
189    
190     r = atom->getPos();
191     EF = Grad_ * r;
192    
193     if (atype->isElectrostatic()) {
194     atom->addElectricField(EF * PhysicalConstants::chargeFieldConvert);
195     }
196    
197     FixedChargeAdapter fca = FixedChargeAdapter(atype);
198     if ( fca.isFixedCharge() ) {
199     isCharge = true;
200     C = fca.getCharge();
201     }
202    
203     FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atype);
204     if ( fqa.isFluctuatingCharge() ) {
205     isCharge = true;
206     C += atom->getFlucQPos();
207     atom->addFlucQFrc( dot(r, EF)
208     * PhysicalConstants::chargeFieldConvert );
209     }
210    
211     if (isCharge) {
212     f = EF * C * PhysicalConstants::chargeFieldConvert;
213     atom->addFrc(f);
214    
215     U = -dot(r, f);
216     if (doParticlePot) {
217     atom->addParticlePot(U);
218     }
219     fPot += U;
220     }
221    
222     MultipoleAdapter ma = MultipoleAdapter(atype);
223     if (ma.isDipole() ) {
224     D = atom->getDipole() * PhysicalConstants::dipoleFieldConvert;
225    
226     f = D * Grad_;
227     atom->addFrc(f);
228    
229     t = cross(D, EF);
230     atom->addTrq(t);
231    
232     U = -dot(D, EF);
233     if (doParticlePot) {
234     atom->addParticlePot(U);
235     }
236     fPot += U;
237     }
238    
239     if (ma.isQuadrupole() ) {
240     Q = atom->getQuadrupole() * PhysicalConstants::dipoleFieldConvert;
241    
242     t = 2.0 * mCross(Q, Grad_);
243     atom->addTrq(t);
244    
245     U = -doubleDot(Q, Grad_);
246     if (doParticlePot) {
247     atom->addParticlePot(U);
248     }
249     fPot += U;
250     }
251     }
252     }
253    
254     #ifdef IS_MPI
255     MPI_Allreduce(MPI_IN_PLACE, &fPot, 1, MPI_REALTYPE,
256     MPI_SUM, MPI_COMM_WORLD);
257     #endif
258    
259     Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
260     longRangePotential = snap->getLongRangePotentials();
261     longRangePotential[ELECTROSTATIC_FAMILY] += fPot;
262     snap->setLongRangePotential(longRangePotential);
263     }
264     }
265     }

Properties

Name Value
svn:executable *