ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/constraints/Shake.cpp
Revision: 1879
Committed: Sun Jun 16 15:15:42 2013 UTC (11 years, 10 months ago) by gezelter
File size: 7762 byte(s)
Log Message:
MERGE OpenMD development 1783:1878 into trunk

File Contents

# Content
1 /*
2 * Copyright (c) 2005 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 "constraints/Shake.hpp"
44 #include "primitives/Molecule.hpp"
45 #include "utils/simError.h"
46 namespace OpenMD {
47
48 Shake::Shake(SimInfo* info) : info_(info), maxConsIteration_(10), consTolerance_(1.0e-6), doShake_(false) {
49
50 if (info_->getNConstraints() > 0)
51 doShake_ = true;
52
53 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
54 }
55
56 void Shake::constraintR() {
57 if (!doShake_) return;
58 doConstraint(&Shake::constraintPairR);
59 }
60 void Shake::constraintF() {
61 if (!doShake_) return;
62 doConstraint(&Shake::constraintPairF);
63 }
64
65 void Shake::doConstraint(ConstraintPairFuncPtr func) {
66 if (!doShake_) return;
67
68 Molecule* mol;
69 SimInfo::MoleculeIterator mi;
70 ConstraintElem* consElem;
71 Molecule::ConstraintElemIterator cei;
72 ConstraintPair* consPair;
73 Molecule::ConstraintPairIterator cpi;
74
75 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi)) {
76 for (consElem = mol->beginConstraintElem(cei); consElem != NULL; consElem = mol->nextConstraintElem(cei)) {
77 consElem->setMoved(true);
78 consElem->setMoving(false);
79 }
80 }
81
82 //main loop of constraint algorithm
83 bool done = false;
84 int iteration = 0;
85 while(!done && iteration < maxConsIteration_){
86 done = true;
87
88 //loop over every constraint pair
89
90 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi)) {
91 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL; consPair = mol->nextConstraintPair(cpi)) {
92
93
94 //dispatch constraint algorithm
95 if(consPair->isMoved()) {
96 int exeStatus = (this->*func)(consPair);
97
98 switch(exeStatus){
99 case consFail:
100 sprintf(painCave.errMsg,
101 "Constraint failure in Shake::constrainA, Constraint Fail\n");
102 painCave.isFatal = 1;
103 simError();
104
105 break;
106 case consSuccess:
107 //constrain the pair by moving two elements
108 done = false;
109 consPair->getConsElem1()->setMoving(true);
110 consPair->getConsElem2()->setMoving(true);
111 break;
112 case consAlready:
113 //current pair is already constrained, do not need to move the elements
114 break;
115 default:
116 sprintf(painCave.errMsg, "ConstraintAlgorithm::doConstrain() Error: unrecognized status");
117 painCave.isFatal = 1;
118 simError();
119 break;
120 }
121 }
122 }
123 }//end for(iter->first())
124
125
126 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi)) {
127 for (consElem = mol->beginConstraintElem(cei); consElem != NULL; consElem = mol->nextConstraintElem(cei)) {
128 consElem->setMoved(consElem->getMoving());
129 consElem->setMoving(false);
130 }
131 }
132
133 iteration++;
134 }//end while
135
136 if (!done){
137 sprintf(painCave.errMsg,
138 "Constraint failure in Shake::constrainA, too many iterations: %d\n",
139 iteration);
140 painCave.isFatal = 1;
141 simError();
142 }
143 }
144
145 /**
146 * remove constraint force along the bond direction
147 */
148 int Shake::constraintPairR(ConstraintPair* consPair){
149
150 ConstraintElem* consElem1 = consPair->getConsElem1();
151 ConstraintElem* consElem2 = consPair->getConsElem2();
152
153 Vector3d posA = consElem1->getPos();
154 Vector3d posB = consElem2->getPos();
155
156 Vector3d pab = posA -posB;
157
158 //periodic boundary condition
159
160 currentSnapshot_->wrapVector(pab);
161
162 RealType pabsq = pab.lengthSquare();
163
164 RealType rabsq = consPair->getConsDistSquare();
165 RealType diffsq = rabsq - pabsq;
166
167 // the original rattle code from alan tidesley
168 if (fabs(diffsq) > (consTolerance_ * rabsq * 2)){
169
170 Vector3d oldPosA = consElem1->getPrevPos();
171 Vector3d oldPosB = consElem2->getPrevPos();
172
173 Vector3d rab = oldPosA - oldPosB;
174
175 currentSnapshot_->wrapVector(rab);
176
177 RealType rpab = dot(rab, pab);
178 RealType rpabsq = rpab * rpab;
179
180 if (rpabsq < (rabsq * -diffsq)){
181 return consFail;
182 }
183
184 RealType rma = 1.0 / consElem1->getMass();
185 RealType rmb = 1.0 / consElem2->getMass();
186
187 RealType gab = diffsq / (2.0 * (rma + rmb) * rpab);
188
189 Vector3d delta = rab * gab;
190
191 //set atom1's position
192 posA += rma * delta;
193 consElem1->setPos(posA);
194
195 //set atom2's position
196 posB -= rmb * delta;
197 consElem2->setPos(posB);
198 return consSuccess;
199 }
200 else
201 return consAlready;
202 }
203
204 /**
205 * remove constraint force along the bond direction
206 */
207 int Shake::constraintPairF(ConstraintPair* consPair){
208 ConstraintElem* consElem1 = consPair->getConsElem1();
209 ConstraintElem* consElem2 = consPair->getConsElem2();
210
211 Vector3d posA = consElem1->getPos();
212 Vector3d posB = consElem2->getPos();
213
214 Vector3d rab = posA - posB;
215
216 currentSnapshot_->wrapVector(rab);
217
218 Vector3d frcA = consElem1->getFrc();
219 Vector3d frcB = consElem2->getFrc();
220
221 RealType rma = 1.0 / consElem1->getMass();
222 RealType rmb = 1.0 / consElem2->getMass();
223
224 Vector3d fpab = frcA * rma - frcB * rmb;
225
226 RealType gab = fpab.lengthSquare();
227 if (gab < 1.0) gab = 1.0;
228
229 RealType rabsq = rab.lengthSquare();
230 RealType rfab = dot(rab, fpab);
231
232 if (fabs(rfab) > sqrt(rabsq*gab) * consTolerance_){
233 gab = -rfab / (rabsq * (rma + rmb));
234
235 frcA += rab*gab;
236 frcB -= rab*gab;
237
238 consElem1->setFrc(frcA);
239 consElem2->setFrc(frcB);
240
241 return consSuccess;
242 }
243 else
244 return consAlready;
245 }
246 }

Properties

Name Value
svn:eol-style native
svn:executable *