ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-3.0/src/primitives/RigidBody.cpp
Revision: 1811
Committed: Wed Dec 1 03:11:29 2004 UTC (19 years, 7 months ago) by tim
File size: 11590 byte(s)
Log Message:
minor change

File Contents

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