ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-3.0/src/primitives/RigidBody.cpp
(Generate patch)

Comparing branches/new_design/OOPSE-3.0/src/primitives/RigidBody.cpp (file contents):
Revision 1691, Thu Oct 28 22:34:02 2004 UTC vs.
Revision 1692 by tim, Mon Nov 1 20:15:58 2004 UTC

# Line 1 | Line 1
1 < #include <math.h>
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"
3 #include "primitives/DirectionalAtom.hpp"
4 #include "utils/simError.h"
5 #include "math/MatVec3.h"
27  
28 < RigidBody::RigidBody() : StuntDouble() {
8 <  objType = OT_RIGIDBODY;
9 <  is_linear = false;
10 <  linear_axis =  -1;
11 <  momIntTol = 1e-6;
12 < }
28 > namespace oopse {
29  
30 < RigidBody::~RigidBody() {
30 > RigidBody::RigidBody() : StuntDouble(otRigidBody, &Snapshot::rigidbodyData){
31 >
32   }
33  
34 < void RigidBody::addAtom(Atom* at, AtomStamp* ats) {
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 <  vec3 coords;
39 <  vec3 euler;
40 <  mat3x3 Atmp;
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 <  myAtoms.push_back(at);
24 <
25 <  if( !ats->havePosition() ){
26 <    sprintf( painCave.errMsg,
27 <             "RigidBody error.\n"
28 <             "\tAtom %s does not have a position specified.\n"
29 <             "\tThis means RigidBody cannot set up reference coordinates.\n",
30 <             ats->getType() );
31 <    painCave.isFatal = 1;
32 <    simError();
33 <  }
34 <  
35 <  coords[0] = ats->getPosX();
36 <  coords[1] = ats->getPosY();
37 <  coords[2] = ats->getPosZ();
45 > }
46  
47 <  refCoords.push_back(coords);
48 <  
49 <  if (at->isDirectional()) {  
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 <    if( !ats->haveOrientation() ){
53 <      sprintf( painCave.errMsg,
54 <               "RigidBody error.\n"
55 <               "\tAtom %s does not have an orientation specified.\n"
56 <               "\tThis means RigidBody cannot set up reference orientations.\n",
57 <               ats->getType() );
58 <      painCave.isFatal = 1;
50 <      simError();
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 <    euler[0] = ats->getEulerPhi();
61 <    euler[1] = ats->getEulerTheta();
62 <    euler[2] = ats->getEulerPsi();
63 <    
64 <    doEulerToRotMat(euler, Atmp);
65 <    
66 <    refOrients.push_back(Atmp);
67 <    
68 <  }
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 < void RigidBody::getPos(double theP[3]){
78 <  for (int i = 0; i < 3 ; i++)
79 <    theP[i] = pos[i];
67 < }      
77 > Mat3x3d RigidBody::getI() {
78 >    return inertiaTensor_;
79 > }    
80  
81 < void RigidBody::setPos(double theP[3]){
82 <  for (int i = 0; i < 3 ; i++)
83 <    pos[i] = theP[i];
84 < }      
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 < void RigidBody::getVel(double theV[3]){
93 <  for (int i = 0; i < 3 ; i++)
94 <    theV[i] = vel[i];
77 < }      
92 >    force = getFrc();
93 >    torque =getTrq();
94 >    myEuler = getA().toEulerAngles();
95  
96 < void RigidBody::setVel(double theV[3]){
97 <  for (int i = 0; i < 3 ; i++)
98 <    vel[i] = theV[i];
82 < }      
96 >    phi = myEuler[0];
97 >    theta = myEuler[1];
98 >    psi = myEuler[2];
99  
100 < void RigidBody::getFrc(double theF[3]){
101 <  for (int i = 0; i < 3 ; i++)
102 <    theF[i] = frc[i];
103 < }      
100 >    cphi = cos(phi);
101 >    sphi = sin(phi);
102 >    ctheta = cos(theta);
103 >    stheta = sin(theta);
104  
105 < void RigidBody::addFrc(double theF[3]){
90 <  for (int i = 0; i < 3 ; i++)
91 <    frc[i] += theF[i];
92 < }    
105 >    // get unit vectors along the phi, theta and psi rotation axes
106  
107 < void RigidBody::zeroForces() {
107 >    ephi[0] = 0.0;
108 >    ephi[1] = 0.0;
109 >    ephi[2] = 1.0;
110  
111 <  for (int i = 0; i < 3; i++) {
112 <    frc[i] = 0.0;
113 <    trq[i] = 0.0;
99 <  }
111 >    etheta[0] = cphi;
112 >    etheta[1] = sphi;
113 >    etheta[2] = 0.0;
114  
115 < }
115 >    epsi[0] = stheta * cphi;
116 >    epsi[1] = stheta * sphi;
117 >    epsi[2] = ctheta;
118  
119 < void RigidBody::setEuler( double phi, double theta, double psi ){
120 <  
121 <    A[0][0] = (cos(phi) * cos(psi)) - (sin(phi) * cos(theta) * sin(psi));
106 <    A[0][1] = (sin(phi) * cos(psi)) + (cos(phi) * cos(theta) * sin(psi));
107 <    A[0][2] = sin(theta) * sin(psi);
108 <    
109 <    A[1][0] = -(cos(phi) * sin(psi)) - (sin(phi) * cos(theta) * cos(psi));
110 <    A[1][1] = -(sin(phi) * sin(psi)) + (cos(phi) * cos(theta) * cos(psi));
111 <    A[1][2] = sin(theta) * cos(psi);
112 <    
113 <    A[2][0] = sin(phi) * sin(theta);
114 <    A[2][1] = -cos(phi) * sin(theta);
115 <    A[2][2] = cos(theta);
119 >    //gradient is equal to -force
120 >    for (int j = 0 ; j<3; j++)
121 >        grad[j] = -force[j];
122  
123 < }
123 >    for (int j = 0; j < 3; j++ ) {
124  
125 < void RigidBody::getQ( double q[4] ){
126 <  
127 <  double t, s;
128 <  double ad1, ad2, ad3;
123 <    
124 <  t = A[0][0] + A[1][1] + A[2][2] + 1.0;
125 <  if( t > 0.0 ){
126 <    
127 <    s = 0.5 / sqrt( t );
128 <    q[0] = 0.25 / s;
129 <    q[1] = (A[1][2] - A[2][1]) * s;
130 <    q[2] = (A[2][0] - A[0][2]) * s;
131 <    q[3] = (A[0][1] - A[1][0]) * s;
132 <  }
133 <  else{
134 <    
135 <    ad1 = fabs( A[0][0] );
136 <    ad2 = fabs( A[1][1] );
137 <    ad3 = fabs( A[2][2] );
138 <    
139 <    if( ad1 >= ad2 && ad1 >= ad3 ){
140 <      
141 <      s = 2.0 * sqrt( 1.0 + A[0][0] - A[1][1] - A[2][2] );
142 <      q[0] = (A[1][2] + A[2][1]) / s;
143 <      q[1] = 0.5 / s;
144 <      q[2] = (A[0][1] + A[1][0]) / s;
145 <      q[3] = (A[0][2] + A[2][0]) / s;
125 >        grad[3] += torque[j]*ephi[j];
126 >        grad[4] += torque[j]*etheta[j];
127 >        grad[5] += torque[j]*epsi[j];
128 >
129      }
130 <    else if( ad2 >= ad1 && ad2 >= ad3 ){
131 <      
132 <      s = sqrt( 1.0 + A[1][1] - A[0][0] - A[2][2] ) * 2.0;
150 <      q[0] = (A[0][2] + A[2][0]) / s;
151 <      q[1] = (A[0][1] + A[1][0]) / s;
152 <      q[2] = 0.5 / s;
153 <      q[3] = (A[1][2] + A[2][1]) / s;
154 <    }
155 <    else{
156 <      
157 <      s = sqrt( 1.0 + A[2][2] - A[0][0] - A[1][1] ) * 2.0;
158 <      q[0] = (A[0][1] + A[1][0]) / s;
159 <      q[1] = (A[0][2] + A[2][0]) / s;
160 <      q[2] = (A[1][2] + A[2][1]) / s;
161 <      q[3] = 0.5 / s;
162 <    }
163 <  }
164 < }
130 >    
131 >    return grad;
132 > }    
133  
134 < void RigidBody::setQ( double the_q[4] ){
134 > void RigidBody::accept(BaseVisitor* v) {
135 >    v->visit(this);
136 > }    
137  
138 <  double q0Sqr, q1Sqr, q2Sqr, q3Sqr;
139 <  
170 <  q0Sqr = the_q[0] * the_q[0];
171 <  q1Sqr = the_q[1] * the_q[1];
172 <  q2Sqr = the_q[2] * the_q[2];
173 <  q3Sqr = the_q[3] * the_q[3];
174 <  
175 <  A[0][0] = q0Sqr + q1Sqr - q2Sqr - q3Sqr;
176 <  A[0][1] = 2.0 * ( the_q[1] * the_q[2] + the_q[0] * the_q[3] );
177 <  A[0][2] = 2.0 * ( the_q[1] * the_q[3] - the_q[0] * the_q[2] );
178 <  
179 <  A[1][0] = 2.0 * ( the_q[1] * the_q[2] - the_q[0] * the_q[3] );
180 <  A[1][1] = q0Sqr - q1Sqr + q2Sqr - q3Sqr;
181 <  A[1][2] = 2.0 * ( the_q[2] * the_q[3] + the_q[0] * the_q[1] );
182 <  
183 <  A[2][0] = 2.0 * ( the_q[1] * the_q[3] + the_q[0] * the_q[2] );
184 <  A[2][1] = 2.0 * ( the_q[2] * the_q[3] - the_q[0] * the_q[1] );
185 <  A[2][2] = q0Sqr - q1Sqr -q2Sqr +q3Sqr;  
186 <
187 < }
188 <
189 < void RigidBody::getA( double the_A[3][3] ){
190 <  
191 <  for (int i = 0; i < 3; i++)
192 <    for (int j = 0; j < 3; j++)
193 <      the_A[i][j] = A[i][j];
194 <
195 < }
196 <
197 < void RigidBody::setA( double the_A[3][3] ){
198 <
199 <  for (int i = 0; i < 3; i++)
200 <    for (int j = 0; j < 3; j++)
201 <      A[i][j] = the_A[i][j];
202 <  
203 < }
204 <
205 < void RigidBody::getJ( double theJ[3] ){
206 <  
207 <  for (int i = 0; i < 3; i++)
208 <    theJ[i] = ji[i];
209 <
210 < }
211 <
212 < void RigidBody::setJ( double theJ[3] ){
213 <  
214 <  for (int i = 0; i < 3; i++)
215 <    ji[i] = theJ[i];
216 <
217 < }
218 <
219 < void RigidBody::getTrq(double theT[3]){
220 <  for (int i = 0; i < 3 ; i++)
221 <    theT[i] = trq[i];
222 < }      
223 <
224 < void RigidBody::addTrq(double theT[3]){
225 <  for (int i = 0; i < 3 ; i++)
226 <    trq[i] += theT[i];
227 < }      
228 <
229 < void RigidBody::getI( double the_I[3][3] ){  
230 <
231 <    for (int i = 0; i < 3; i++)
232 <      for (int j = 0; j < 3; j++)
233 <        the_I[i][j] = I[i][j];
234 <
235 < }
236 <
237 < void RigidBody::lab2Body( double r[3] ){
238 <
239 <  double rl[3]; // the lab frame vector
240 <  
241 <  rl[0] = r[0];
242 <  rl[1] = r[1];
243 <  rl[2] = r[2];
244 <  
245 <  r[0] = (A[0][0] * rl[0]) + (A[0][1] * rl[1]) + (A[0][2] * rl[2]);
246 <  r[1] = (A[1][0] * rl[0]) + (A[1][1] * rl[1]) + (A[1][2] * rl[2]);
247 <  r[2] = (A[2][0] * rl[0]) + (A[2][1] * rl[1]) + (A[2][2] * rl[2]);
248 <
249 < }
250 <
251 < void RigidBody::body2Lab( double r[3] ){
252 <
253 <  double rb[3]; // the body frame vector
254 <  
255 <  rb[0] = r[0];
256 <  rb[1] = r[1];
257 <  rb[2] = r[2];
258 <  
259 <  r[0] = (A[0][0] * rb[0]) + (A[1][0] * rb[1]) + (A[2][0] * rb[2]);
260 <  r[1] = (A[0][1] * rb[0]) + (A[1][1] * rb[1]) + (A[2][1] * rb[2]);
261 <  r[2] = (A[0][2] * rb[0]) + (A[1][2] * rb[1]) + (A[2][2] * rb[2]);
262 <
263 < }
264 <
265 < double RigidBody::getZangle( ){
266 <    return zAngle;
267 < }
268 <
269 < void RigidBody::setZangle( double zAng ){
270 <    zAngle = zAng;
271 < }
272 <
273 < void RigidBody::addZangle( double zAng ){
274 <    zAngle += zAng;
275 < }
276 <
277 < void RigidBody::calcRefCoords( ) {
278 <
279 <  int i,j,k, it, n_linear_coords;
138 > void  RigidBody::calcRefCoords() {
139 >  /*
140    double mtmp;
141    vec3 apos;
142    double refCOM[3];
# Line 292 | Line 152 | void RigidBody::calcRefCoords( ) {
152    for (j=0; j<3; j++)
153      refCOM[j] = 0.0;
154    
155 <  for (i = 0; i < myAtoms.size(); i++) {
156 <    mtmp = myAtoms[i]->getMass();
155 >  for (i = 0; i < atoms_.size(); i++) {
156 >    mtmp = atoms_[i]->getMass();
157      mass += mtmp;
158  
159      apos = refCoords[i];
# Line 308 | Line 168 | void RigidBody::calcRefCoords( ) {
168  
169   // Next, move the origin of the reference coordinate system to the COM:
170  
171 <  for (i = 0; i < myAtoms.size(); i++) {
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];
# Line 322 | Line 182 | void RigidBody::calcRefCoords( ) {
182      for (j = 0; j < 3; j++)
183        Itmp[i][j] = 0.0;  
184    
185 <  for (it = 0; it < myAtoms.size(); it++) {
185 >  for (it = 0; it < atoms_.size(); it++) {
186  
187 <    mtmp = myAtoms[it]->getMass();
187 >    mtmp = atoms_[it]->getMass();
188      ptmp = refCoords[it];
189      r= norm3(ptmp.vec);
190      r2 = r*r;
# Line 384 | Line 244 | void RigidBody::calcRefCoords( ) {
244        sU[i][j] /= len;
245      }
246    }
247 +  */
248   }
249  
250 < void RigidBody::doEulerToRotMat(vec3 &euler, mat3x3 &myA ){
250 > void  RigidBody::calcForcesAndTorques() {
251 >    unsigned int i;
252 >    unsigned int j;
253 >    //Vector3d apos;
254 >    Vector3d afrc;
255 >    Vector3d atrq;
256 >    Vector3d rpos;
257 >    Vector3d frc;
258 >    Vector3d trq;
259 >    //Vector3d pos;
260  
261 <  double phi, theta, psi;
262 <  
263 <  phi = euler[0];
264 <  theta = euler[1];
265 <  psi = euler[2];
396 <  
397 <  myA[0][0] = (cos(phi) * cos(psi)) - (sin(phi) * cos(theta) * sin(psi));
398 <  myA[0][1] = (sin(phi) * cos(psi)) + (cos(phi) * cos(theta) * sin(psi));
399 <  myA[0][2] = sin(theta) * sin(psi);
400 <  
401 <  myA[1][0] = -(cos(phi) * sin(psi)) - (sin(phi) * cos(theta) * cos(psi));
402 <  myA[1][1] = -(sin(phi) * sin(psi)) + (cos(phi) * cos(theta) * cos(psi));
403 <  myA[1][2] = sin(theta) * cos(psi);
404 <  
405 <  myA[2][0] = sin(phi) * sin(theta);
406 <  myA[2][1] = -cos(phi) * sin(theta);
407 <  myA[2][2] = cos(theta);
261 >    zeroForces();
262 >    
263 >    //pos = getPos();
264 >    frc = getFrc();
265 >    trq = getTrq();
266  
267 < }
267 >    for (i = 0; i < atoms_.size(); i++) {
268  
269 < void RigidBody::calcForcesAndTorques() {
269 >        afrc = atoms_[i]->getFrc();
270  
271 <  // Convert Atomic forces and torques to total forces and torques:
272 <  int i, j;
273 <  double apos[3];
274 <  double afrc[3];
275 <  double atrq[3];
418 <  double rpos[3];
271 >        //apos = atoms_[i]->getPos(apos);
272 >        //rpos = apos - pos;
273 >        rpos = refCoords_[i];
274 >        
275 >        frc += afrc;
276  
277 <  zeroForces();
278 <  
279 <  for (i = 0; i < myAtoms.size(); i++) {
277 >        trq[0] += rpos[1]*afrc[2] - rpos[2]*afrc[1];
278 >        trq[1] += rpos[2]*afrc[0] - rpos[0]*afrc[2];
279 >        trq[2] += rpos[0]*afrc[1] - rpos[1]*afrc[0];
280  
281 <    myAtoms[i]->getPos(apos);
282 <    myAtoms[i]->getFrc(afrc);
281 >        // If the atom has a torque associated with it, then we also need to
282 >        // migrate the torques onto the center of mass:
283  
284 <    for (j=0; j<3; j++) {
285 <      rpos[j] = apos[j] - pos[j];
286 <      frc[j] += afrc[j];
284 >        if (atoms_[i]->isDirectional()) {
285 >            atrq = atoms_[i]->getTrq();
286 >            trq += atrq;
287 >        }
288 >        
289      }
290      
291 <    trq[0] += rpos[1]*afrc[2] - rpos[2]*afrc[1];
292 <    trq[1] += rpos[2]*afrc[0] - rpos[0]*afrc[2];
293 <    trq[2] += rpos[0]*afrc[1] - rpos[1]*afrc[0];
435 <
436 <    // If the atom has a torque associated with it, then we also need to
437 <    // migrate the torques onto the center of mass:
438 <
439 <    if (myAtoms[i]->isDirectional()) {
440 <
441 <      myAtoms[i]->getTrq(atrq);
442 <      
443 <      for (j=0; j<3; j++)
444 <        trq[j] += atrq[j];
445 <    }
446 <  }
447 <
448 <  // Convert Torque to Body-fixed coordinates:
449 <  // (Actually, on second thought, don't.  Integrator does this now.)
450 <  // lab2Body(trq);
451 <
291 >    setFrc(frc);
292 >    setTrq(trq);
293 >    
294   }
295  
296 < void RigidBody::updateAtoms() {
297 <  int i, j;
298 <  vec3 ref;
299 <  double apos[3];
300 <  DirectionalAtom* dAtom;
301 <  
302 <  for (i = 0; i < myAtoms.size(); i++) {
296 > void  RigidBody::updateAtoms() {
297 >    unsigned int i;
298 >    unsigned int j;
299 >    Vector3d ref;
300 >    Vector3d apos;
301 >    DirectionalAtom* dAtom;
302 >    Vector3d pos = getPos();
303 >    RotMat3x3d A = getA();
304 >    
305 >    for (i = 0; i < atoms_.size(); i++) {
306      
307 <    ref = refCoords[i];
307 >        ref = body2Lab(refCoords_[i]);
308  
309 <    body2Lab(ref.vec);
465 <    
466 <    for (j = 0; j<3; j++)
467 <      apos[j] = pos[j] + ref.vec[j];
468 <    
469 <    myAtoms[i]->setPos(apos);
470 <    
471 <    if (myAtoms[i]->isDirectional()) {
472 <      
473 <      dAtom = (DirectionalAtom *) myAtoms[i];
474 <      dAtom->rotateBy( A );
475 <      
476 <    }
477 <  }  
478 < }
309 >        apos = pos + ref;
310  
311 < void RigidBody::getGrad( double grad[6] ) {
311 >        atoms_[i]->setPos(apos);
312  
313 <  double myEuler[3];
314 <  double phi, theta, psi;
315 <  double cphi, sphi, ctheta, stheta;
316 <  double ephi[3];
317 <  double etheta[3];
487 <  double epsi[3];
488 <  
489 <  this->getEulerAngles(myEuler);
313 >        if (atoms_[i]->isDirectional()) {
314 >          
315 >          dAtom = (DirectionalAtom *) atoms_[i];
316 >          dAtom->rotateBy( A );      
317 >        }
318  
319 <  phi = myEuler[0];
492 <  theta = myEuler[1];
493 <  psi = myEuler[2];
494 <
495 <  cphi = cos(phi);
496 <  sphi = sin(phi);
497 <  ctheta = cos(theta);
498 <  stheta = sin(theta);
499 <
500 <  // get unit vectors along the phi, theta and psi rotation axes
501 <
502 <  ephi[0] = 0.0;
503 <  ephi[1] = 0.0;
504 <  ephi[2] = 1.0;
505 <
506 <  etheta[0] = cphi;
507 <  etheta[1] = sphi;
508 <  etheta[2] = 0.0;
319 >    }
320    
510  epsi[0] = stheta * cphi;
511  epsi[1] = stheta * sphi;
512  epsi[2] = ctheta;
513  
514  for (int j = 0 ; j<3; j++)
515    grad[j] = frc[j];
516
517  grad[3] = 0.0;
518  grad[4] = 0.0;
519  grad[5] = 0.0;
520  
521  for (int j = 0; j < 3; j++ ) {
522    
523    grad[3] += trq[j]*ephi[j];
524    grad[4] += trq[j]*etheta[j];
525    grad[5] += trq[j]*epsi[j];
526    
527  }
528  
321   }
322  
531 /**
532  * getEulerAngles computes a set of Euler angle values consistent
533  * with an input rotation matrix.  They are returned in the following
534  * order:
535  *  myEuler[0] = phi;
536  *  myEuler[1] = theta;
537  *  myEuler[2] = psi;
538 */
539 void RigidBody::getEulerAngles(double myEuler[3]) {
323  
324 <  // We use so-called "x-convention", which is the most common
325 <  // definition.  In this convention, the rotation given by Euler
543 <  // angles (phi, theta, psi), where the first rotation is by an angle
544 <  // phi about the z-axis, the second is by an angle theta (0 <= theta
545 <  // <= 180) about the x-axis, and the third is by an angle psi about
546 <  // the z-axis (again).
547 <  
548 <  
549 <  double phi,theta,psi,eps;
550 <  double pi;
551 <  double cphi,ctheta,cpsi;
552 <  double sphi,stheta,spsi;
553 <  double b[3];
554 <  int flip[3];
555 <  
556 <  // set the tolerance for Euler angles and rotation elements
557 <  
558 <  eps = 1.0e-8;
324 > bool RigidBody::getAtomPos(Vector3d& pos, unsigned int index) {
325 >    if (index < atoms_.size()) {
326  
327 <  theta = acos(min(1.0,max(-1.0,A[2][2])));
328 <  ctheta = A[2][2];
329 <  stheta = sqrt(1.0 - ctheta * ctheta);
330 <
331 <  // when sin(theta) is close to 0, we need to consider the
332 <  // possibility of a singularity. In this case, we can assign an
333 <  // arbitary value to phi (or psi), and then determine the psi (or
334 <  // phi) or vice-versa.  We'll assume that phi always gets the
568 <  // rotation, and psi is 0 in cases of singularity.  we use atan2
569 <  // instead of atan, since atan2 will give us -Pi to Pi.  Since 0 <=
570 <  // theta <= 180, sin(theta) will be always non-negative. Therefore,
571 <  // it never changes the sign of both of the parameters passed to
572 <  // atan2.
573 <  
574 <  if (fabs(stheta) <= eps){
575 <    psi = 0.0;
576 <    phi = atan2(-A[1][0], A[0][0]);  
577 <  }
578 <  // we only have one unique solution
579 <  else{    
580 <    phi = atan2(A[2][0], -A[2][1]);
581 <    psi = atan2(A[0][2], A[1][2]);
582 <  }
583 <  
584 <  //wrap phi and psi, make sure they are in the range from 0 to 2*Pi
585 <  //if (phi < 0)
586 <  //  phi += M_PI;
587 <  
588 <  //if (psi < 0)
589 <  //  psi += M_PI;
590 <  
591 <  myEuler[0] = phi;
592 <  myEuler[1] = theta;
593 <  myEuler[2] = psi;
594 <  
595 <  return;
327 >        Vector3d ref = body2Lab(refCoords_[index]);
328 >        pos = getPos() + ref;
329 >        return true;
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 < double RigidBody::max(double x, double  y) {  
338 <  return (x > y) ? x : y;
337 > bool RigidBody::getAtomPos(Vector3d& pos, Atom* atom) {
338 >    std::vector<Atom*>::iterator i;
339 >    i = find(atoms_.begin(), atoms_.end(), atom);
340 >    if (i != atoms_.end()) {
341 >        //RigidBody class makes sure refCoords_ and atoms_ match each other
342 >        Vector3d ref = body2Lab(refCoords_[i - atoms_.begin()]);
343 >        pos = getPos() + ref;
344 >        return true;
345 >    } else {
346 >        std::cerr << "Atom " << atom->getGlobalIndex()
347 >                      <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
348 >        return false;
349 >    }
350   }
351 + bool RigidBody::getAtomVel(Vector3d& vel, unsigned int index) {
352  
353 < double RigidBody::min(double x, double  y) {  
603 <  return (x > y) ? y : x;
604 < }
353 >    //velRot = $(A\cdot skew(I^{-1}j))^{T}refCoor$
354  
355 < void RigidBody::findCOM() {
607 <  
608 <  size_t i;
609 <  int j;
610 <  double mtmp;
611 <  double ptmp[3];
612 <  double vtmp[3];
613 <  
614 <  for(j = 0; j < 3; j++) {
615 <    pos[j] = 0.0;
616 <    vel[j] = 0.0;
617 <  }
618 <  mass = 0.0;
619 <  
620 <  for (i = 0; i < myAtoms.size(); i++) {
621 <    
622 <    mtmp = myAtoms[i]->getMass();    
623 <    myAtoms[i]->getPos(ptmp);
624 <    myAtoms[i]->getVel(vtmp);
625 <    
626 <    mass += mtmp;
627 <    
628 <    for(j = 0; j < 3; j++) {
629 <      pos[j] += ptmp[j]*mtmp;
630 <      vel[j] += vtmp[j]*mtmp;
631 <    }
632 <    
633 <  }
634 <  
635 <  for(j = 0; j < 3; j++) {
636 <    pos[j] /= mass;
637 <    vel[j] /= mass;
638 <  }
355 >    if (index < atoms_.size()) {
356  
357 < }
357 >        Vector3d velRot;
358 >        Mat3x3d skewMat;;
359 >        Vector3d ref = refCoords_[index];
360 >        Vector3d ji = getJ();
361 >        Mat3x3d I =  getI();
362  
363 < void RigidBody::accept(BaseVisitor* v){
364 <  vector<Atom*>::iterator atomIter;
365 <  v->visit(this);
363 >        skewMat(0, 0) =0;
364 >        skewMat(0, 1) = ji[2] /I(2, 2);
365 >        skewMat(0, 2) = -ji[1] /I(1, 1);
366  
367 <  //for(atomIter = myAtoms.begin(); atomIter != myAtoms.end(); ++atomIter)
368 <  //  (*atomIter)->accept(v);
369 < }
649 < void RigidBody::getAtomRefCoor(double pos[3], int index){
650 <  vec3 ref;
367 >        skewMat(1, 0) = -ji[2] /I(2, 2);
368 >        skewMat(1, 1) = 0;
369 >        skewMat(1, 2) = ji[0]/I(0, 0);
370  
371 <  ref = refCoords[index];
372 <  pos[0] = ref[0];
373 <  pos[1] = ref[1];
655 <  pos[2] = ref[2];
656 <  
657 < }
371 >        skewMat(2, 0) =ji[1] /I(1, 1);
372 >        skewMat(2, 1) = -ji[0]/I(0, 0);
373 >        skewMat(2, 2) = 0;
374  
375 +        velRot = (getA() * skewMat).transpose() * ref;
376  
377 < void RigidBody::getAtomPos(double theP[3], int index){
378 <  vec3 ref;
377 >        vel =getVel() + velRot;
378 >        return true;
379 >        
380 >    } else {
381 >        std::cerr << index << " is an invalid index, current rigid body contains "
382 >                      << atoms_.size() << "atoms" << std::endl;
383 >        return false;
384 >    }
385 > }
386  
387 <  if (index >= myAtoms.size())
664 <    cerr << index << " is an invalid index, current rigid body contains " << myAtoms.size() << "atoms" << endl;
387 > bool RigidBody::getAtomVel(Vector3d& vel, Atom* atom) {
388  
389 <  ref = refCoords[index];
390 <  body2Lab(ref.vec);
391 <  
392 <  theP[0] = pos[0] + ref[0];
393 <  theP[1] = pos[1] + ref[1];
394 <  theP[2] = pos[2] + ref[2];
389 >    std::vector<Atom*>::iterator i;
390 >    i = find(atoms_.begin(), atoms_.end(), atom);
391 >    if (i != atoms_.end()) {
392 >        return getAtomVel(vel, i - atoms_.begin());
393 >    } else {
394 >        std::cerr << "Atom " << atom->getGlobalIndex()
395 >                      <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;    
396 >        return false;
397 >    }    
398   }
399  
400 + bool RigidBody::getAtomRefCoor(Vector3d& coor, unsigned int index) {
401 +    if (index < atoms_.size()) {
402  
403 < void RigidBody::getAtomVel(double theV[3], int index){
404 <  vec3 ref;
405 <  double velRot[3];
406 <  double skewMat[3][3];
407 <  double aSkewMat[3][3];
408 <  double aSkewTransMat[3][3];
409 <  
682 <  //velRot = $(A\cdot skew(I^{-1}j))^{T}refCoor$
403 >        coor = refCoords_[index];
404 >        return true;
405 >    } else {
406 >        std::cerr << index << " is an invalid index, current rigid body contains "
407 >                      << atoms_.size() << "atoms" << std::endl;
408 >        return false;
409 >    }
410  
411 <  if (index >= myAtoms.size())
685 <    cerr << index << " is an invalid index, current rigid body contains " << myAtoms.size() << "atoms" << endl;
411 > }
412  
413 <  ref = refCoords[index];
413 > bool RigidBody::getAtomRefCoor(Vector3d& coor, Atom* atom) {
414 >    std::vector<Atom*>::iterator i;
415 >    i = find(atoms_.begin(), atoms_.end(), atom);
416 >    if (i != atoms_.end()) {
417 >        //RigidBody class makes sure refCoords_ and atoms_ match each other
418 >        coor = refCoords_[i - atoms_.begin()];
419 >        return true;
420 >    } else {
421 >        std::cerr << "Atom " << atom->getGlobalIndex()
422 >                      <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;    
423 >        return false;
424 >    }
425  
426 <  skewMat[0][0] =0;
690 <  skewMat[0][1] = ji[2] /I[2][2];
691 <  skewMat[0][2] = -ji[1] /I[1][1];
426 > }
427  
693  skewMat[1][0] = -ji[2] /I[2][2];
694  skewMat[1][1] = 0;
695  skewMat[1][2] = ji[0]/I[0][0];
696
697  skewMat[2][0] =ji[1] /I[1][1];
698  skewMat[2][1] = -ji[0]/I[0][0];
699  skewMat[2][2] = 0;
700  
701  matMul3(A, skewMat, aSkewMat);
702
703  transposeMat3(aSkewMat, aSkewTransMat);
704
705  matVecMul3(aSkewTransMat, ref.vec, velRot);
706  theV[0] = vel[0] + velRot[0];
707  theV[1] = vel[1] + velRot[1];
708  theV[2] = vel[2] + velRot[2];
428   }
429  
711

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines