ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/primitives/RigidBody.cpp
Revision: 1937
Committed: Thu Jan 13 19:40:37 2005 UTC (19 years, 5 months ago) by tim
File size: 12466 byte(s)
Log Message:
port to SGI platform

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