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: 1815
Committed: Wed Dec 1 18:42:45 2004 UTC (19 years, 7 months ago) by tim
File size: 11510 byte(s)
Log Message:
except integrator and constraint, other directories get built

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