ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/DirectionalAtom.cpp
(Generate patch)

Comparing trunk/OOPSE/libmdtools/DirectionalAtom.cpp (file contents):
Revision 689 by tim, Tue Aug 12 19:56:49 2003 UTC vs.
Revision 1046 by tim, Tue Feb 10 21:33:44 2004 UTC

# Line 1 | Line 1
1 < #include <cmath>
1 > #include <math.h>
2  
3   #include "Atom.hpp"
4   #include "simError.h"
5  
6 +
7 +
8   void DirectionalAtom::zeroForces() {
9    if( hasCoords ){
10      frc[offsetX] = 0.0;
# Line 39 | Line 41 | void DirectionalAtom::setCoords(void){
41    else{
42      sprintf( painCave.errMsg,
43               "Attempted to set Atom %d  coordinates with an unallocated "
44 <             "SimState object.\n" );
44 >             "SimState object.\n", index );
45      painCave.isFatal = 1;
46      simError();
47    }
48  
49    hasCoords = true;
50  
51 <  mu[index] = myMu;
51 >  *mu = myMu;
52  
53   }
54  
55   double DirectionalAtom::getMu( void ) {
56  
57    if( hasCoords ){
58 <    return mu[index];
58 >    return *mu;
59    }
60    else{
61      return myMu;
62    }
61  return 0;
63   }
64  
65   void DirectionalAtom::setMu( double the_mu ) {
66  
67    if( hasCoords ){
68 <    mu[index] = the_mu;
68 >    *mu = the_mu;
69      myMu = the_mu;
70    }
71    else{
# Line 401 | Line 402 | void DirectionalAtom::getI( double the_I[3][3] ){
402    the_I[2][0] = Izx;
403    the_I[2][1] = Izy;
404    the_I[2][2] = Izz;
405 + }
406 +
407 + void DirectionalAtom::getGrad( double grad[6] ) {
408 +
409 +  double myEuler[3];
410 +  double phi, theta, psi;
411 +  double cphi, sphi, ctheta, stheta;
412 +  double ephi[3];
413 +  double etheta[3];
414 +  double epsi[3];
415 +
416 +  this->getEulerAngles(myEuler);
417 +
418 +  phi = myEuler[0];
419 +  theta = myEuler[1];
420 +  psi = myEuler[2];
421 +
422 +  cphi = cos(phi);
423 +  sphi = sin(phi);
424 +  ctheta = cos(theta);
425 +  stheta = sin(theta);
426 +
427 +  // get unit vectors along the phi, theta and psi rotation axes
428 +
429 +  ephi[0] = 0.0;
430 +  ephi[1] = 0.0;
431 +  ephi[2] = 1.0;
432 +
433 +  etheta[0] = cphi;
434 +  etheta[1] = sphi;
435 +  etheta[2] = 0.0;
436 +  
437 +  epsi[0] = stheta * cphi;
438 +  epsi[1] = stheta * sphi;
439 +  epsi[2] = ctheta;
440 +  
441 +  for (int j = 0 ; j<3; j++)
442 +    grad[j] = frc[j];
443 +
444 +  grad[3] = 0;
445 +  grad[4] = 0;
446 +  grad[5] = 0;
447 +
448 +  for (int j = 0; j < 3; j++ ) {
449 +    
450 +    grad[3] += trq[j]*ephi[j];
451 +    grad[4] += trq[j]*etheta[j];
452 +    grad[5] += trq[j]*epsi[j];
453 +    
454 +  }
455 +
456 + }
457 +
458 + /**
459 +  * getEulerAngles computes a set of Euler angle values consistent
460 +  *  with an input rotation matrix.  They are returned in the following
461 +  * order:
462 +  *  myEuler[0] = phi;
463 +  *  myEuler[1] = theta;
464 +  *  myEuler[2] = psi;
465 + */
466 + void DirectionalAtom::getEulerAngles(double myEuler[3]) {
467 +
468 +  // We use so-called "x-convention", which is the most common definition.
469 +  // In this convention, the rotation given by Euler angles (phi, theta, psi), where the first
470 +  // rotation is by an angle phi about the z-axis, the second is by an angle  
471 +  // theta (0 <= theta <= 180)about the x-axis, and thethird is by an angle psi about the
472 +  //z-axis (again).
473 +  
474 +  
475 +  double phi,theta,psi,eps;
476 +  double pi;
477 +  double cphi,ctheta,cpsi;
478 +  double sphi,stheta,spsi;
479 +  double b[3];
480 +  int flip[3];
481 +
482 +  // set the tolerance for Euler angles and rotation elements
483 +  
484 +  eps = 1.0e-8;
485 +
486 +  theta = acos(min(1.0,max(-1.0,Amat[Azz])));
487 +  ctheta = Amat[Azz];
488 +  stheta = sqrt(1.0 - ctheta * ctheta);
489 +
490 +  // when sin(theta) is close to 0, we need to consider singularity
491 +  // In this case, we can assign an arbitary value to phi (or psi), and then determine
492 +  // the psi (or phi) or vice-versa. We'll assume that phi always gets the rotation, and psi is 0
493 +  // in cases of singularity.  
494 +  // we use atan2 instead of atan, since atan2 will give us -Pi to Pi.
495 +  // Since 0 <= theta <= 180, sin(theta) will be always non-negative. Therefore, it never
496 +  // change the sign of both of the parameters passed to atan2.
497 +  
498 +  if (fabs(stheta) <= eps){
499 +    psi = 0.0;
500 +    phi = atan2(-Amat[Ayx], Amat[Axx]);  
501 +  }
502 +  // we only have one unique solution
503 +  else{    
504 +      phi = atan2(Amat[Azx], -Amat[Azy]);
505 +      psi = atan2(Amat[Axz], Amat[Ayz]);
506 +  }
507 +
508 +  //wrap phi and psi, make sure they are in the range from 0 to 2*Pi
509 +  //if (phi < 0)
510 +  //  phi += M_PI;
511 +
512 +  //if (psi < 0)
513 +  //  psi += M_PI;
514 +
515 +  myEuler[0] = phi;
516 +  myEuler[1] = theta;
517 +  myEuler[2] = psi;
518 +  
519 +  return;
520   }
521 +
522 + double DirectionalAtom::max(double x, double  y) {  
523 +  return (x > y) ? x : y;
524 + }
525 +
526 + double DirectionalAtom::min(double x, double  y) {  
527 +  return (x > y) ? y : x;
528 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines