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: 1883
Committed: Mon Dec 13 22:30:27 2004 UTC (19 years, 6 months ago) by tim
File size: 11514 byte(s)
Log Message:
MPI version is 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 std::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 (std::size_t 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 (std::size_t 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 (std::size_t 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 Vector3d afrc;
196 Vector3d atrq;
197 Vector3d apos;
198 Vector3d rpos;
199 Vector3d frc(0.0);
200 Vector3d trq(0.0);
201 Vector3d pos = this->getPos();
202 for (int i = 0; i < atoms_.size(); i++) {
203
204 afrc = atoms_[i]->getFrc();
205 apos = atoms_[i]->getPos();
206 rpos = apos - pos;
207
208 frc += afrc;
209
210 trq[0] += rpos[1]*afrc[2] - rpos[2]*afrc[1];
211 trq[1] += rpos[2]*afrc[0] - rpos[0]*afrc[2];
212 trq[2] += rpos[0]*afrc[1] - rpos[1]*afrc[0];
213
214 // If the atom has a torque associated with it, then we also need to
215 // migrate the torques onto the center of mass:
216
217 if (atoms_[i]->isDirectional()) {
218 atrq = atoms_[i]->getTrq();
219 trq += atrq;
220 }
221
222 }
223
224 setFrc(frc);
225 setTrq(trq);
226
227 }
228
229 void RigidBody::updateAtoms() {
230 unsigned int i;
231 Vector3d ref;
232 Vector3d apos;
233 DirectionalAtom* dAtom;
234 Vector3d pos = getPos();
235 RotMat3x3d a = getA();
236
237 for (i = 0; i < atoms_.size(); i++) {
238
239 ref = body2Lab(refCoords_[i]);
240
241 apos = pos + ref;
242
243 atoms_[i]->setPos(apos);
244
245 if (atoms_[i]->isDirectional()) {
246
247 dAtom = (DirectionalAtom *) atoms_[i];
248 dAtom->setA(a * refOrients_[i]);
249 //dAtom->rotateBy( A );
250 }
251
252 }
253
254 }
255
256
257 bool RigidBody::getAtomPos(Vector3d& pos, unsigned int index) {
258 if (index < atoms_.size()) {
259
260 Vector3d ref = body2Lab(refCoords_[index]);
261 pos = getPos() + ref;
262 return true;
263 } else {
264 std::cerr << index << " is an invalid index, current rigid body contains "
265 << atoms_.size() << "atoms" << std::endl;
266 return false;
267 }
268 }
269
270 bool RigidBody::getAtomPos(Vector3d& pos, Atom* atom) {
271 std::vector<Atom*>::iterator i;
272 i = find(atoms_.begin(), atoms_.end(), atom);
273 if (i != atoms_.end()) {
274 //RigidBody class makes sure refCoords_ and atoms_ match each other
275 Vector3d ref = body2Lab(refCoords_[i - atoms_.begin()]);
276 pos = getPos() + ref;
277 return true;
278 } else {
279 std::cerr << "Atom " << atom->getGlobalIndex()
280 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
281 return false;
282 }
283 }
284 bool RigidBody::getAtomVel(Vector3d& vel, unsigned int index) {
285
286 //velRot = $(A\cdot skew(I^{-1}j))^{T}refCoor$
287
288 if (index < atoms_.size()) {
289
290 Vector3d velRot;
291 Mat3x3d skewMat;;
292 Vector3d ref = refCoords_[index];
293 Vector3d ji = getJ();
294 Mat3x3d I = getI();
295
296 skewMat(0, 0) =0;
297 skewMat(0, 1) = ji[2] /I(2, 2);
298 skewMat(0, 2) = -ji[1] /I(1, 1);
299
300 skewMat(1, 0) = -ji[2] /I(2, 2);
301 skewMat(1, 1) = 0;
302 skewMat(1, 2) = ji[0]/I(0, 0);
303
304 skewMat(2, 0) =ji[1] /I(1, 1);
305 skewMat(2, 1) = -ji[0]/I(0, 0);
306 skewMat(2, 2) = 0;
307
308 velRot = (getA() * skewMat).transpose() * ref;
309
310 vel =getVel() + velRot;
311 return true;
312
313 } else {
314 std::cerr << index << " is an invalid index, current rigid body contains "
315 << atoms_.size() << "atoms" << std::endl;
316 return false;
317 }
318 }
319
320 bool RigidBody::getAtomVel(Vector3d& vel, Atom* atom) {
321
322 std::vector<Atom*>::iterator i;
323 i = find(atoms_.begin(), atoms_.end(), atom);
324 if (i != atoms_.end()) {
325 return getAtomVel(vel, i - atoms_.begin());
326 } else {
327 std::cerr << "Atom " << atom->getGlobalIndex()
328 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
329 return false;
330 }
331 }
332
333 bool RigidBody::getAtomRefCoor(Vector3d& coor, unsigned int index) {
334 if (index < atoms_.size()) {
335
336 coor = refCoords_[index];
337 return true;
338 } else {
339 std::cerr << index << " is an invalid index, current rigid body contains "
340 << atoms_.size() << "atoms" << std::endl;
341 return false;
342 }
343
344 }
345
346 bool RigidBody::getAtomRefCoor(Vector3d& coor, Atom* atom) {
347 std::vector<Atom*>::iterator i;
348 i = find(atoms_.begin(), atoms_.end(), atom);
349 if (i != atoms_.end()) {
350 //RigidBody class makes sure refCoords_ and atoms_ match each other
351 coor = refCoords_[i - atoms_.begin()];
352 return true;
353 } else {
354 std::cerr << "Atom " << atom->getGlobalIndex()
355 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
356 return false;
357 }
358
359 }
360
361
362 void RigidBody::addAtom(Atom* at, AtomStamp* ats) {
363
364 Vector3d coords;
365 Vector3d euler;
366
367
368 atoms_.push_back(at);
369
370 if( !ats->havePosition() ){
371 sprintf( painCave.errMsg,
372 "RigidBody error.\n"
373 "\tAtom %s does not have a position specified.\n"
374 "\tThis means RigidBody cannot set up reference coordinates.\n",
375 ats->getType() );
376 painCave.isFatal = 1;
377 simError();
378 }
379
380 coords[0] = ats->getPosX();
381 coords[1] = ats->getPosY();
382 coords[2] = ats->getPosZ();
383
384 refCoords_.push_back(coords);
385
386 RotMat3x3d identMat = RotMat3x3d::identity();
387
388 if (at->isDirectional()) {
389
390 if( !ats->haveOrientation() ){
391 sprintf( painCave.errMsg,
392 "RigidBody error.\n"
393 "\tAtom %s does not have an orientation specified.\n"
394 "\tThis means RigidBody cannot set up reference orientations.\n",
395 ats->getType() );
396 painCave.isFatal = 1;
397 simError();
398 }
399
400 euler[0] = ats->getEulerPhi();
401 euler[1] = ats->getEulerTheta();
402 euler[2] = ats->getEulerPsi();
403
404 RotMat3x3d Atmp(euler);
405 refOrients_.push_back(Atmp);
406
407 }else {
408 refOrients_.push_back(identMat);
409 }
410
411
412 }
413
414 }
415