ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-2.0/src/primitives/RigidBody.cpp
Revision: 1929
Committed: Wed Jan 12 18:13:36 2005 UTC (19 years, 6 months ago) by tim
File size: 12448 byte(s)
Log Message:
forget to include <algorithm>

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. Acknowledgement of the program authors must be made in any
10 * publication of scientific results based in part on use of the
11 * program. An acceptable form of acknowledgement is citation of
12 * the article in which the program was described (Matthew
13 * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 * Parallel Simulation Engine for Molecular Dynamics,"
16 * J. Comput. Chem. 26, pp. 252-271 (2005))
17 *
18 * 2. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 3. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * This software is provided "AS IS," without a warranty of any
27 * kind. All express or implied conditions, representations and
28 * warranties, including any implied warranty of merchantability,
29 * fitness for a particular purpose or non-infringement, are hereby
30 * excluded. The University of Notre Dame and its licensors shall not
31 * be liable for any damages suffered by licensee as a result of
32 * using, modifying or distributing the software or its
33 * derivatives. In no event will the University of Notre Dame or its
34 * licensors be liable for any lost revenue, profit or data, or for
35 * direct, indirect, special, consequential, incidental or punitive
36 * damages, however caused and regardless of the theory of liability,
37 * arising out of the use of or inability to use software, even if the
38 * University of Notre Dame has been advised of the possibility of
39 * such damages.
40 */
41 #include <algorithm>
42 #include "primitives/RigidBody.hpp"
43 #include "utils/simError.h"
44 namespace oopse {
45
46 RigidBody::RigidBody() : StuntDouble(otRigidBody, &Snapshot::rigidbodyData), inertiaTensor_(0.0){
47
48 }
49
50 void RigidBody::setPrevA(const RotMat3x3d& a) {
51 ((snapshotMan_->getPrevSnapshot())->*storage_).aMat[localIndex_] = a;
52 //((snapshotMan_->getPrevSnapshot())->*storage_).electroFrame[localIndex_] = a.transpose() * sU_;
53
54 for (int i =0 ; i < atoms_.size(); ++i){
55 if (atoms_[i]->isDirectional()) {
56 atoms_[i]->setPrevA(a * refOrients_[i]);
57 }
58 }
59
60 }
61
62
63 void RigidBody::setA(const RotMat3x3d& a) {
64 ((snapshotMan_->getCurrentSnapshot())->*storage_).aMat[localIndex_] = a;
65 //((snapshotMan_->getCurrentSnapshot())->*storage_).electroFrame[localIndex_] = a.transpose() * sU_;
66
67 for (int i =0 ; i < atoms_.size(); ++i){
68 if (atoms_[i]->isDirectional()) {
69 atoms_[i]->setA(a * refOrients_[i]);
70 }
71 }
72 }
73
74 void RigidBody::setA(const RotMat3x3d& a, int snapshotNo) {
75 ((snapshotMan_->getSnapshot(snapshotNo))->*storage_).aMat[localIndex_] = a;
76 //((snapshotMan_->getSnapshot(snapshotNo))->*storage_).electroFrame[localIndex_] = a.transpose() * sU_;
77
78 for (int i =0 ; i < atoms_.size(); ++i){
79 if (atoms_[i]->isDirectional()) {
80 atoms_[i]->setA(a * refOrients_[i], snapshotNo);
81 }
82 }
83
84 }
85
86 Mat3x3d RigidBody::getI() {
87 return inertiaTensor_;
88 }
89
90 std::vector<double> RigidBody::getGrad() {
91 std::vector<double> grad(6, 0.0);
92 Vector3d force;
93 Vector3d torque;
94 Vector3d myEuler;
95 double phi, theta, psi;
96 double cphi, sphi, ctheta, stheta;
97 Vector3d ephi;
98 Vector3d etheta;
99 Vector3d epsi;
100
101 force = getFrc();
102 torque =getTrq();
103 myEuler = getA().toEulerAngles();
104
105 phi = myEuler[0];
106 theta = myEuler[1];
107 psi = myEuler[2];
108
109 cphi = cos(phi);
110 sphi = sin(phi);
111 ctheta = cos(theta);
112 stheta = sin(theta);
113
114 // get unit vectors along the phi, theta and psi rotation axes
115
116 ephi[0] = 0.0;
117 ephi[1] = 0.0;
118 ephi[2] = 1.0;
119
120 etheta[0] = cphi;
121 etheta[1] = sphi;
122 etheta[2] = 0.0;
123
124 epsi[0] = stheta * cphi;
125 epsi[1] = stheta * sphi;
126 epsi[2] = ctheta;
127
128 //gradient is equal to -force
129 for (int j = 0 ; j<3; j++)
130 grad[j] = -force[j];
131
132 for (int j = 0; j < 3; j++ ) {
133
134 grad[3] += torque[j]*ephi[j];
135 grad[4] += torque[j]*etheta[j];
136 grad[5] += torque[j]*epsi[j];
137
138 }
139
140 return grad;
141 }
142
143 void RigidBody::accept(BaseVisitor* v) {
144 v->visit(this);
145 }
146
147 /**@todo need modification */
148 void RigidBody::calcRefCoords() {
149 double mtmp;
150 Vector3d refCOM(0.0);
151 mass_ = 0.0;
152 for (std::size_t i = 0; i < atoms_.size(); ++i) {
153 mtmp = atoms_[i]->getMass();
154 mass_ += mtmp;
155 refCOM += refCoords_[i]*mtmp;
156 }
157 refCOM /= mass_;
158
159 // Next, move the origin of the reference coordinate system to the COM:
160 for (std::size_t i = 0; i < atoms_.size(); ++i) {
161 refCoords_[i] -= refCOM;
162 }
163
164 // Moment of Inertia calculation
165 Mat3x3d Itmp(0.0);
166
167 for (std::size_t i = 0; i < atoms_.size(); i++) {
168 mtmp = atoms_[i]->getMass();
169 Itmp -= outProduct(refCoords_[i], refCoords_[i]) * mtmp;
170 double r2 = refCoords_[i].lengthSquare();
171 Itmp(0, 0) += mtmp * r2;
172 Itmp(1, 1) += mtmp * r2;
173 Itmp(2, 2) += mtmp * r2;
174 }
175
176 //diagonalize
177 Vector3d evals;
178 Mat3x3d::diagonalize(Itmp, evals, sU_);
179
180 // zero out I and then fill the diagonals with the moments of inertia:
181 inertiaTensor_(0, 0) = evals[0];
182 inertiaTensor_(1, 1) = evals[1];
183 inertiaTensor_(2, 2) = evals[2];
184
185 int nLinearAxis = 0;
186 for (int i = 0; i < 3; i++) {
187 if (fabs(evals[i]) < oopse::epsilon) {
188 linear_ = true;
189 linearAxis_ = i;
190 ++ nLinearAxis;
191 }
192 }
193
194 if (nLinearAxis > 1) {
195 sprintf( painCave.errMsg,
196 "RigidBody error.\n"
197 "\tOOPSE found more than one axis in this rigid body with a vanishing \n"
198 "\tmoment of inertia. This can happen in one of three ways:\n"
199 "\t 1) Only one atom was specified, or \n"
200 "\t 2) All atoms were specified at the same location, or\n"
201 "\t 3) The programmers did something stupid.\n"
202 "\tIt is silly to use a rigid body to describe this situation. Be smarter.\n"
203 );
204 painCave.isFatal = 1;
205 simError();
206 }
207
208 }
209
210 void RigidBody::calcForcesAndTorques() {
211 Vector3d afrc;
212 Vector3d atrq;
213 Vector3d apos;
214 Vector3d rpos;
215 Vector3d frc(0.0);
216 Vector3d trq(0.0);
217 Vector3d pos = this->getPos();
218 for (int i = 0; i < atoms_.size(); i++) {
219
220 afrc = atoms_[i]->getFrc();
221 apos = atoms_[i]->getPos();
222 rpos = apos - pos;
223
224 frc += afrc;
225
226 trq[0] += rpos[1]*afrc[2] - rpos[2]*afrc[1];
227 trq[1] += rpos[2]*afrc[0] - rpos[0]*afrc[2];
228 trq[2] += rpos[0]*afrc[1] - rpos[1]*afrc[0];
229
230 // If the atom has a torque associated with it, then we also need to
231 // migrate the torques onto the center of mass:
232
233 if (atoms_[i]->isDirectional()) {
234 atrq = atoms_[i]->getTrq();
235 trq += atrq;
236 }
237
238 }
239
240 setFrc(frc);
241 setTrq(trq);
242
243 }
244
245 void RigidBody::updateAtoms() {
246 unsigned int i;
247 Vector3d ref;
248 Vector3d apos;
249 DirectionalAtom* dAtom;
250 Vector3d pos = getPos();
251 RotMat3x3d a = getA();
252
253 for (i = 0; i < atoms_.size(); i++) {
254
255 ref = body2Lab(refCoords_[i]);
256
257 apos = pos + ref;
258
259 atoms_[i]->setPos(apos);
260
261 if (atoms_[i]->isDirectional()) {
262
263 dAtom = (DirectionalAtom *) atoms_[i];
264 dAtom->setA(a * refOrients_[i]);
265 //dAtom->rotateBy( A );
266 }
267
268 }
269
270 }
271
272
273 bool RigidBody::getAtomPos(Vector3d& pos, unsigned int index) {
274 if (index < atoms_.size()) {
275
276 Vector3d ref = body2Lab(refCoords_[index]);
277 pos = getPos() + ref;
278 return true;
279 } else {
280 std::cerr << index << " is an invalid index, current rigid body contains "
281 << atoms_.size() << "atoms" << std::endl;
282 return false;
283 }
284 }
285
286 bool RigidBody::getAtomPos(Vector3d& pos, Atom* atom) {
287 std::vector<Atom*>::iterator i;
288 i = std::find(atoms_.begin(), atoms_.end(), atom);
289 if (i != atoms_.end()) {
290 //RigidBody class makes sure refCoords_ and atoms_ match each other
291 Vector3d ref = body2Lab(refCoords_[i - atoms_.begin()]);
292 pos = getPos() + ref;
293 return true;
294 } else {
295 std::cerr << "Atom " << atom->getGlobalIndex()
296 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
297 return false;
298 }
299 }
300 bool RigidBody::getAtomVel(Vector3d& vel, unsigned int index) {
301
302 //velRot = $(A\cdot skew(I^{-1}j))^{T}refCoor$
303
304 if (index < atoms_.size()) {
305
306 Vector3d velRot;
307 Mat3x3d skewMat;;
308 Vector3d ref = refCoords_[index];
309 Vector3d ji = getJ();
310 Mat3x3d I = getI();
311
312 skewMat(0, 0) =0;
313 skewMat(0, 1) = ji[2] /I(2, 2);
314 skewMat(0, 2) = -ji[1] /I(1, 1);
315
316 skewMat(1, 0) = -ji[2] /I(2, 2);
317 skewMat(1, 1) = 0;
318 skewMat(1, 2) = ji[0]/I(0, 0);
319
320 skewMat(2, 0) =ji[1] /I(1, 1);
321 skewMat(2, 1) = -ji[0]/I(0, 0);
322 skewMat(2, 2) = 0;
323
324 velRot = (getA() * skewMat).transpose() * ref;
325
326 vel =getVel() + velRot;
327 return true;
328
329 } else {
330 std::cerr << index << " is an invalid index, current rigid body contains "
331 << atoms_.size() << "atoms" << std::endl;
332 return false;
333 }
334 }
335
336 bool RigidBody::getAtomVel(Vector3d& vel, Atom* atom) {
337
338 std::vector<Atom*>::iterator i;
339 i = std::find(atoms_.begin(), atoms_.end(), atom);
340 if (i != atoms_.end()) {
341 return getAtomVel(vel, i - atoms_.begin());
342 } else {
343 std::cerr << "Atom " << atom->getGlobalIndex()
344 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
345 return false;
346 }
347 }
348
349 bool RigidBody::getAtomRefCoor(Vector3d& coor, unsigned int index) {
350 if (index < atoms_.size()) {
351
352 coor = refCoords_[index];
353 return true;
354 } else {
355 std::cerr << index << " is an invalid index, current rigid body contains "
356 << atoms_.size() << "atoms" << std::endl;
357 return false;
358 }
359
360 }
361
362 bool RigidBody::getAtomRefCoor(Vector3d& coor, Atom* atom) {
363 std::vector<Atom*>::iterator i;
364 i = std::find(atoms_.begin(), atoms_.end(), atom);
365 if (i != atoms_.end()) {
366 //RigidBody class makes sure refCoords_ and atoms_ match each other
367 coor = refCoords_[i - atoms_.begin()];
368 return true;
369 } else {
370 std::cerr << "Atom " << atom->getGlobalIndex()
371 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
372 return false;
373 }
374
375 }
376
377
378 void RigidBody::addAtom(Atom* at, AtomStamp* ats) {
379
380 Vector3d coords;
381 Vector3d euler;
382
383
384 atoms_.push_back(at);
385
386 if( !ats->havePosition() ){
387 sprintf( painCave.errMsg,
388 "RigidBody error.\n"
389 "\tAtom %s does not have a position specified.\n"
390 "\tThis means RigidBody cannot set up reference coordinates.\n",
391 ats->getType() );
392 painCave.isFatal = 1;
393 simError();
394 }
395
396 coords[0] = ats->getPosX();
397 coords[1] = ats->getPosY();
398 coords[2] = ats->getPosZ();
399
400 refCoords_.push_back(coords);
401
402 RotMat3x3d identMat = RotMat3x3d::identity();
403
404 if (at->isDirectional()) {
405
406 if( !ats->haveOrientation() ){
407 sprintf( painCave.errMsg,
408 "RigidBody error.\n"
409 "\tAtom %s does not have an orientation specified.\n"
410 "\tThis means RigidBody cannot set up reference orientations.\n",
411 ats->getType() );
412 painCave.isFatal = 1;
413 simError();
414 }
415
416 euler[0] = ats->getEulerPhi();
417 euler[1] = ats->getEulerTheta();
418 euler[2] = ats->getEulerPsi();
419
420 RotMat3x3d Atmp(euler);
421 refOrients_.push_back(Atmp);
422
423 }else {
424 refOrients_.push_back(identMat);
425 }
426
427
428 }
429
430 }
431