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: 1738
Committed: Sat Nov 13 05:08:12 2004 UTC (19 years, 8 months ago) by tim
File size: 10968 byte(s)
Log Message:
refactory, refactory, refactory

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
28 namespace oopse {
29
30 RigidBody::RigidBody() : StuntDouble(otRigidBody, &Snapshot::rigidbodyData){
31
32 }
33
34 void RigidBody::setPrevA(const RotMat3x3d& a) {
35 ((snapshotMan_->getPrevSnapshot())->*storage_).aMat[localIndex_] = a;
36 ((snapshotMan_->getPrevSnapshot())->*storage_).unitVector[localIndex_] = a.inverse() * sU_.getColum(2);
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_).unitVector[localIndex_] = a.inverse() * sU_.getColum(2);
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_).unitVector[localIndex_] = a.inverse() * sU_.getColum(2);
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 void RigidBody::calcRefCoords() {
139 /*
140 double mtmp;
141 vec3 apos;
142 double refCOM[3];
143 vec3 ptmp;
144 double Itmp[3][3];
145 double evals[3];
146 double evects[3][3];
147 double r, r2, len;
148
149 // First, find the center of mass:
150
151 mass = 0.0;
152 for (j=0; j<3; j++)
153 refCOM[j] = 0.0;
154
155 for (i = 0; i < atoms_.size(); i++) {
156 mtmp = atoms_[i]->getMass();
157 mass += mtmp;
158
159 apos = refCoords[i];
160
161 for(j = 0; j < 3; j++) {
162 refCOM[j] += apos[j]*mtmp;
163 }
164 }
165
166 for(j = 0; j < 3; j++)
167 refCOM[j] /= mass;
168
169 // Next, move the origin of the reference coordinate system to the COM:
170
171 for (i = 0; i < atoms_.size(); i++) {
172 apos = refCoords[i];
173 for (j=0; j < 3; j++) {
174 apos[j] = apos[j] - refCOM[j];
175 }
176 refCoords[i] = apos;
177 }
178
179 // Moment of Inertia calculation
180
181 for (i = 0; i < 3; i++)
182 for (j = 0; j < 3; j++)
183 Itmp[i][j] = 0.0;
184
185 for (it = 0; it < atoms_.size(); it++) {
186
187 mtmp = atoms_[it]->getMass();
188 ptmp = refCoords[it];
189 r= norm3(ptmp.vec);
190 r2 = r*r;
191
192 for (i = 0; i < 3; i++) {
193 for (j = 0; j < 3; j++) {
194
195 if (i==j) Itmp[i][j] += mtmp * r2;
196
197 Itmp[i][j] -= mtmp * ptmp.vec[i]*ptmp.vec[j];
198 }
199 }
200 }
201
202 diagonalize3x3(Itmp, evals, sU);
203
204 // zero out I and then fill the diagonals with the moments of inertia:
205
206 n_linear_coords = 0;
207
208 for (i = 0; i < 3; i++) {
209 for (j = 0; j < 3; j++) {
210 I[i][j] = 0.0;
211 }
212 I[i][i] = evals[i];
213
214 if (fabs(evals[i]) < momIntTol) {
215 is_linear = true;
216 n_linear_coords++;
217 linear_axis = i;
218 }
219 }
220
221 if (n_linear_coords > 1) {
222 sprintf( painCave.errMsg,
223 "RigidBody error.\n"
224 "\tOOPSE found more than one axis in this rigid body with a vanishing \n"
225 "\tmoment of inertia. This can happen in one of three ways:\n"
226 "\t 1) Only one atom was specified, or \n"
227 "\t 2) All atoms were specified at the same location, or\n"
228 "\t 3) The programmers did something stupid.\n"
229 "\tIt is silly to use a rigid body to describe this situation. Be smarter.\n"
230 );
231 painCave.isFatal = 1;
232 simError();
233 }
234
235 // renormalize column vectors:
236
237 for (i=0; i < 3; i++) {
238 len = 0.0;
239 for (j = 0; j < 3; j++) {
240 len += sU[i][j]*sU[i][j];
241 }
242 len = sqrt(len);
243 for (j = 0; j < 3; j++) {
244 sU[i][j] /= len;
245 }
246 }
247 */
248 }
249
250 void RigidBody::calcForcesAndTorques() {
251 unsigned int i;
252 unsigned int j;
253 Vector3d afrc;
254 Vector3d atrq;
255 Vector3d rpos;
256 Vector3d frc;
257 Vector3d trq;
258
259
260 zeroForces();
261
262 frc = getFrc();
263 trq = getTrq();
264
265 for (i = 0; i < atoms_.size(); i++) {
266
267 afrc = atoms_[i]->getFrc();
268
269 rpos = refCoords_[i];
270
271 frc += afrc;
272
273 trq[0] += rpos[1]*afrc[2] - rpos[2]*afrc[1];
274 trq[1] += rpos[2]*afrc[0] - rpos[0]*afrc[2];
275 trq[2] += rpos[0]*afrc[1] - rpos[1]*afrc[0];
276
277 // If the atom has a torque associated with it, then we also need to
278 // migrate the torques onto the center of mass:
279
280 if (atoms_[i]->isDirectional()) {
281 atrq = atoms_[i]->getTrq();
282 trq += atrq;
283 }
284
285 }
286
287 setFrc(frc);
288 setTrq(trq);
289
290 }
291
292 void RigidBody::updateAtoms() {
293 unsigned int i;
294 unsigned int j;
295 Vector3d ref;
296 Vector3d apos;
297 DirectionalAtom* dAtom;
298 Vector3d pos = getPos();
299 RotMat3x3d A = getA();
300
301 for (i = 0; i < atoms_.size(); i++) {
302
303 ref = body2Lab(refCoords_[i]);
304
305 apos = pos + ref;
306
307 atoms_[i]->setPos(apos);
308
309 if (atoms_[i]->isDirectional()) {
310
311 dAtom = (DirectionalAtom *) atoms_[i];
312 dAtom->rotateBy( A );
313 }
314
315 }
316
317 }
318
319
320 bool RigidBody::getAtomPos(Vector3d& pos, unsigned int index) {
321 if (index < atoms_.size()) {
322
323 Vector3d ref = body2Lab(refCoords_[index]);
324 pos = getPos() + ref;
325 return true;
326 } else {
327 std::cerr << index << " is an invalid index, current rigid body contains "
328 << atoms_.size() << "atoms" << std::endl;
329 return false;
330 }
331 }
332
333 bool RigidBody::getAtomPos(Vector3d& pos, Atom* atom) {
334 std::vector<Atom*>::iterator i;
335 i = find(atoms_.begin(), atoms_.end(), atom);
336 if (i != atoms_.end()) {
337 //RigidBody class makes sure refCoords_ and atoms_ match each other
338 Vector3d ref = body2Lab(refCoords_[i - atoms_.begin()]);
339 pos = getPos() + ref;
340 return true;
341 } else {
342 std::cerr << "Atom " << atom->getGlobalIndex()
343 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
344 return false;
345 }
346 }
347 bool RigidBody::getAtomVel(Vector3d& vel, unsigned int index) {
348
349 //velRot = $(A\cdot skew(I^{-1}j))^{T}refCoor$
350
351 if (index < atoms_.size()) {
352
353 Vector3d velRot;
354 Mat3x3d skewMat;;
355 Vector3d ref = refCoords_[index];
356 Vector3d ji = getJ();
357 Mat3x3d I = getI();
358
359 skewMat(0, 0) =0;
360 skewMat(0, 1) = ji[2] /I(2, 2);
361 skewMat(0, 2) = -ji[1] /I(1, 1);
362
363 skewMat(1, 0) = -ji[2] /I(2, 2);
364 skewMat(1, 1) = 0;
365 skewMat(1, 2) = ji[0]/I(0, 0);
366
367 skewMat(2, 0) =ji[1] /I(1, 1);
368 skewMat(2, 1) = -ji[0]/I(0, 0);
369 skewMat(2, 2) = 0;
370
371 velRot = (getA() * skewMat).transpose() * ref;
372
373 vel =getVel() + velRot;
374 return true;
375
376 } else {
377 std::cerr << index << " is an invalid index, current rigid body contains "
378 << atoms_.size() << "atoms" << std::endl;
379 return false;
380 }
381 }
382
383 bool RigidBody::getAtomVel(Vector3d& vel, Atom* atom) {
384
385 std::vector<Atom*>::iterator i;
386 i = find(atoms_.begin(), atoms_.end(), atom);
387 if (i != atoms_.end()) {
388 return getAtomVel(vel, i - atoms_.begin());
389 } else {
390 std::cerr << "Atom " << atom->getGlobalIndex()
391 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
392 return false;
393 }
394 }
395
396 bool RigidBody::getAtomRefCoor(Vector3d& coor, unsigned int index) {
397 if (index < atoms_.size()) {
398
399 coor = refCoords_[index];
400 return true;
401 } else {
402 std::cerr << index << " is an invalid index, current rigid body contains "
403 << atoms_.size() << "atoms" << std::endl;
404 return false;
405 }
406
407 }
408
409 bool RigidBody::getAtomRefCoor(Vector3d& coor, Atom* atom) {
410 std::vector<Atom*>::iterator i;
411 i = find(atoms_.begin(), atoms_.end(), atom);
412 if (i != atoms_.end()) {
413 //RigidBody class makes sure refCoords_ and atoms_ match each other
414 coor = refCoords_[i - atoms_.begin()];
415 return true;
416 } else {
417 std::cerr << "Atom " << atom->getGlobalIndex()
418 <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
419 return false;
420 }
421
422 }
423
424 }
425