ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 597
Committed: Mon Jul 14 21:28:54 2003 UTC (20 years, 11 months ago) by mmeineke
File size: 15329 byte(s)
Log Message:
found a bug. Unit vectors were not being updated

File Contents

# User Rev Content
1 mmeineke 558 #include <iostream>
2     #include <cstdlib>
3 mmeineke 561 #include <cmath>
4 mmeineke 558
5     #ifdef IS_MPI
6     #include "mpiSimulation.hpp"
7     #include <unistd.h>
8     #endif //is_mpi
9    
10     #include "Integrator.hpp"
11     #include "simError.h"
12    
13    
14 mmeineke 561 Integrator::Integrator( SimInfo *theInfo, ForceFields* the_ff ){
15 mmeineke 558
16     info = theInfo;
17     myFF = the_ff;
18     isFirst = 1;
19    
20     molecules = info->molecules;
21     nMols = info->n_mol;
22    
23     // give a little love back to the SimInfo object
24    
25     if( info->the_integrator != NULL ) delete info->the_integrator;
26     info->the_integrator = this;
27    
28     nAtoms = info->n_atoms;
29    
30 mmeineke 594 std::cerr << "integ nAtoms = " << nAtoms << "\n";
31    
32 mmeineke 558 // check for constraints
33    
34     constrainedA = NULL;
35     constrainedB = NULL;
36     constrainedDsqr = NULL;
37     moving = NULL;
38     moved = NULL;
39 mmeineke 561 oldPos = NULL;
40 mmeineke 558
41     nConstrained = 0;
42    
43     checkConstraints();
44     }
45    
46     Integrator::~Integrator() {
47    
48     if( nConstrained ){
49     delete[] constrainedA;
50     delete[] constrainedB;
51     delete[] constrainedDsqr;
52     delete[] moving;
53     delete[] moved;
54 mmeineke 561 delete[] oldPos;
55 mmeineke 558 }
56    
57     }
58    
59     void Integrator::checkConstraints( void ){
60    
61    
62     isConstrained = 0;
63    
64     Constraint *temp_con;
65     Constraint *dummy_plug;
66     temp_con = new Constraint[info->n_SRI];
67     nConstrained = 0;
68     int constrained = 0;
69    
70     SRI** theArray;
71     for(int i = 0; i < nMols; i++){
72    
73     theArray = (SRI**) molecules[i].getMyBonds();
74     for(int j=0; j<molecules[i].getNBonds(); j++){
75    
76     constrained = theArray[j]->is_constrained();
77 mmeineke 594
78     std::cerr << "Is the folowing bond constrained \n";
79     theArray[j]->printMe();
80 mmeineke 558
81     if(constrained){
82    
83 mmeineke 594 std::cerr << "Yes\n";
84    
85 mmeineke 558 dummy_plug = theArray[j]->get_constraint();
86     temp_con[nConstrained].set_a( dummy_plug->get_a() );
87     temp_con[nConstrained].set_b( dummy_plug->get_b() );
88     temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
89    
90     nConstrained++;
91     constrained = 0;
92 mmeineke 594 }
93     else std::cerr << "No.\n";
94 mmeineke 558 }
95    
96     theArray = (SRI**) molecules[i].getMyBends();
97     for(int j=0; j<molecules[i].getNBends(); j++){
98    
99     constrained = theArray[j]->is_constrained();
100    
101     if(constrained){
102    
103     dummy_plug = theArray[j]->get_constraint();
104     temp_con[nConstrained].set_a( dummy_plug->get_a() );
105     temp_con[nConstrained].set_b( dummy_plug->get_b() );
106     temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
107    
108     nConstrained++;
109     constrained = 0;
110     }
111     }
112    
113     theArray = (SRI**) molecules[i].getMyTorsions();
114     for(int j=0; j<molecules[i].getNTorsions(); j++){
115    
116     constrained = theArray[j]->is_constrained();
117    
118     if(constrained){
119    
120     dummy_plug = theArray[j]->get_constraint();
121     temp_con[nConstrained].set_a( dummy_plug->get_a() );
122     temp_con[nConstrained].set_b( dummy_plug->get_b() );
123     temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
124    
125     nConstrained++;
126     constrained = 0;
127     }
128     }
129     }
130    
131     if(nConstrained > 0){
132    
133     isConstrained = 1;
134    
135     if(constrainedA != NULL ) delete[] constrainedA;
136     if(constrainedB != NULL ) delete[] constrainedB;
137     if(constrainedDsqr != NULL ) delete[] constrainedDsqr;
138    
139     constrainedA = new int[nConstrained];
140     constrainedB = new int[nConstrained];
141     constrainedDsqr = new double[nConstrained];
142    
143     for( int i = 0; i < nConstrained; i++){
144    
145     constrainedA[i] = temp_con[i].get_a();
146     constrainedB[i] = temp_con[i].get_b();
147     constrainedDsqr[i] = temp_con[i].get_dsqr();
148 mmeineke 563
149 mmeineke 558 }
150    
151    
152     // save oldAtoms to check for lode balanceing later on.
153    
154     oldAtoms = nAtoms;
155    
156     moving = new int[nAtoms];
157     moved = new int[nAtoms];
158    
159 mmeineke 561 oldPos = new double[nAtoms*3];
160 mmeineke 558 }
161    
162     delete[] temp_con;
163     }
164    
165    
166     void Integrator::integrate( void ){
167    
168     int i, j; // loop counters
169    
170     double runTime = info->run_time;
171     double sampleTime = info->sampleTime;
172     double statusTime = info->statusTime;
173     double thermalTime = info->thermalTime;
174    
175     double currSample;
176     double currThermal;
177     double currStatus;
178     double currTime;
179    
180     int calcPot, calcStress;
181     int isError;
182    
183 mmeineke 561
184    
185 mmeineke 558 tStats = new Thermo( info );
186 mmeineke 561 statOut = new StatWriter( info );
187     dumpOut = new DumpWriter( info );
188 mmeineke 558
189 mmeineke 561 atoms = info->atoms;
190 mmeineke 558 DirectionalAtom* dAtom;
191 mmeineke 561
192     dt = info->dt;
193 mmeineke 558 dt2 = 0.5 * dt;
194    
195     // initialize the forces before the first step
196    
197     myFF->doForces(1,1);
198    
199     if( info->setTemp ){
200    
201     tStats->velocitize();
202     }
203    
204 mmeineke 561 dumpOut->writeDump( 0.0 );
205     statOut->writeStat( 0.0 );
206 mmeineke 558
207     calcPot = 0;
208     calcStress = 0;
209     currSample = sampleTime;
210     currThermal = thermalTime;
211     currStatus = statusTime;
212     currTime = 0.0;;
213    
214 mmeineke 559
215     readyCheck();
216    
217     #ifdef IS_MPI
218     strcpy( checkPointMsg,
219     "The integrator is ready to go." );
220     MPIcheckPoint();
221     #endif // is_mpi
222    
223 mmeineke 561
224     pos = Atom::getPosArray();
225     vel = Atom::getVelArray();
226     frc = Atom::getFrcArray();
227    
228 mmeineke 558 while( currTime < runTime ){
229    
230     if( (currTime+dt) >= currStatus ){
231     calcPot = 1;
232     calcStress = 1;
233     }
234 mmeineke 561
235 mmeineke 597 std::cerr << currTime << "\n";
236 mmeineke 594
237 mmeineke 558 integrateStep( calcPot, calcStress );
238    
239     currTime += dt;
240    
241     if( info->setTemp ){
242     if( currTime >= currThermal ){
243     tStats->velocitize();
244     currThermal += thermalTime;
245     }
246     }
247    
248     if( currTime >= currSample ){
249 mmeineke 561 dumpOut->writeDump( currTime );
250 mmeineke 558 currSample += sampleTime;
251     }
252    
253     if( currTime >= currStatus ){
254 mmeineke 561 statOut->writeStat( currTime );
255 mmeineke 558 calcPot = 0;
256     calcStress = 0;
257     currStatus += statusTime;
258     }
259 mmeineke 559
260     #ifdef IS_MPI
261     strcpy( checkPointMsg,
262     "successfully took a time step." );
263     MPIcheckPoint();
264     #endif // is_mpi
265    
266 mmeineke 558 }
267    
268 mmeineke 572 dumpOut->writeFinal(currTime);
269 mmeineke 558
270 mmeineke 561 delete dumpOut;
271     delete statOut;
272 mmeineke 558 }
273    
274     void Integrator::integrateStep( int calcPot, int calcStress ){
275    
276 mmeineke 561
277    
278 mmeineke 558 // Position full step, and velocity half step
279    
280 mmeineke 561 preMove();
281 mmeineke 558 moveA();
282 mmeineke 597 //if( nConstrained ) constrainA();
283 mmeineke 558
284     // calc forces
285    
286     myFF->doForces(calcPot,calcStress);
287    
288     // finish the velocity half step
289    
290     moveB();
291     if( nConstrained ) constrainB();
292    
293     }
294    
295    
296     void Integrator::moveA( void ){
297    
298     int i,j,k;
299     int atomIndex, aMatIndex;
300     DirectionalAtom* dAtom;
301     double Tb[3];
302     double ji[3];
303 mmeineke 561 double angle;
304 mmeineke 597 double A[3][3], At[3][3];
305 mmeineke 558
306 mmeineke 567
307 mmeineke 558 for( i=0; i<nAtoms; i++ ){
308     atomIndex = i * 3;
309     aMatIndex = i * 9;
310 mmeineke 567
311 mmeineke 558 // velocity half step
312     for( j=atomIndex; j<(atomIndex+3); j++ )
313     vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
314    
315 mmeineke 594
316 mmeineke 558 // position whole step
317 mmeineke 567 for( j=atomIndex; j<(atomIndex+3); j++ ) pos[j] += dt * vel[j];
318    
319 mmeineke 594
320 mmeineke 558 if( atoms[i]->isDirectional() ){
321    
322     dAtom = (DirectionalAtom *)atoms[i];
323    
324     // get and convert the torque to body frame
325    
326     Tb[0] = dAtom->getTx();
327     Tb[1] = dAtom->getTy();
328     Tb[2] = dAtom->getTz();
329 mmeineke 597
330 mmeineke 558 dAtom->lab2Body( Tb );
331 mmeineke 597
332 mmeineke 558 // get the angular momentum, and propagate a half step
333    
334     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
335     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
336     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
337    
338     // use the angular velocities to propagate the rotation matrix a
339     // full time step
340    
341     // rotate about the x-axis
342     angle = dt2 * ji[0] / dAtom->getIxx();
343 mmeineke 597 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
344    
345 mmeineke 558 // rotate about the y-axis
346     angle = dt2 * ji[1] / dAtom->getIyy();
347 mmeineke 597 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
348 mmeineke 558
349     // rotate about the z-axis
350     angle = dt * ji[2] / dAtom->getIzz();
351 mmeineke 597 this->rotate( 0, 1, angle, ji, &Amat[aMatIndex] );
352 mmeineke 558
353     // rotate about the y-axis
354     angle = dt2 * ji[1] / dAtom->getIyy();
355 mmeineke 597 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
356 mmeineke 558
357     // rotate about the x-axis
358     angle = dt2 * ji[0] / dAtom->getIxx();
359 mmeineke 597 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
360 mmeineke 558
361     dAtom->setJx( ji[0] );
362     dAtom->setJy( ji[1] );
363     dAtom->setJz( ji[2] );
364 mmeineke 597
365     std::cerr << "Amat[" << i << "]\n";
366     info->printMat9( &Amat[aMatIndex] );
367    
368     std::cerr << "ji[" << i << "]\t"
369     << ji[0] << "\t"
370     << ji[1] << "\t"
371     << ji[2] << "\n";
372    
373 mmeineke 558 }
374    
375     }
376     }
377    
378    
379     void Integrator::moveB( void ){
380     int i,j,k;
381 mmeineke 597 int atomIndex, aMatIndex;
382 mmeineke 558 DirectionalAtom* dAtom;
383     double Tb[3];
384     double ji[3];
385    
386     for( i=0; i<nAtoms; i++ ){
387     atomIndex = i * 3;
388 mmeineke 597 aMatIndex = i * 9;
389 mmeineke 558
390     // velocity half step
391     for( j=atomIndex; j<(atomIndex+3); j++ )
392     vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
393    
394 mmeineke 597
395 mmeineke 558 if( atoms[i]->isDirectional() ){
396    
397     dAtom = (DirectionalAtom *)atoms[i];
398    
399     // get and convert the torque to body frame
400    
401     Tb[0] = dAtom->getTx();
402     Tb[1] = dAtom->getTy();
403     Tb[2] = dAtom->getTz();
404    
405 mmeineke 597 std::cerr << "TrqB[" << i << "]\t"
406     << Tb[0] << "\t"
407     << Tb[1] << "\t"
408     << Tb[2] << "\n";
409    
410 mmeineke 558 dAtom->lab2Body( Tb );
411    
412     // get the angular momentum, and complete the angular momentum
413     // half step
414    
415     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
416     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
417     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
418    
419     dAtom->setJx( ji[0] );
420     dAtom->setJy( ji[1] );
421     dAtom->setJz( ji[2] );
422 mmeineke 597
423    
424     std::cerr << "Amat[" << i << "]\n";
425     info->printMat9( &Amat[aMatIndex] );
426    
427     std::cerr << "ji[" << i << "]\t"
428     << ji[0] << "\t"
429     << ji[1] << "\t"
430     << ji[2] << "\n";
431 mmeineke 558 }
432     }
433    
434     }
435    
436     void Integrator::preMove( void ){
437     int i;
438    
439     if( nConstrained ){
440 mmeineke 561
441 mmeineke 558 for(i=0; i<(nAtoms*3); i++) oldPos[i] = pos[i];
442     }
443     }
444    
445     void Integrator::constrainA(){
446    
447     int i,j,k;
448     int done;
449 mmeineke 572 double pab[3];
450     double rab[3];
451 mmeineke 563 int a, b, ax, ay, az, bx, by, bz;
452 mmeineke 558 double rma, rmb;
453     double dx, dy, dz;
454 mmeineke 561 double rpab;
455 mmeineke 558 double rabsq, pabsq, rpabsq;
456     double diffsq;
457     double gab;
458     int iteration;
459    
460     for( i=0; i<nAtoms; i++){
461    
462     moving[i] = 0;
463     moved[i] = 1;
464     }
465 mmeineke 567
466 mmeineke 558 iteration = 0;
467     done = 0;
468     while( !done && (iteration < maxIteration )){
469    
470     done = 1;
471     for(i=0; i<nConstrained; i++){
472    
473     a = constrainedA[i];
474     b = constrainedB[i];
475 mmeineke 563
476     ax = (a*3) + 0;
477     ay = (a*3) + 1;
478     az = (a*3) + 2;
479    
480     bx = (b*3) + 0;
481     by = (b*3) + 1;
482     bz = (b*3) + 2;
483    
484 mmeineke 558 if( moved[a] || moved[b] ){
485    
486 mmeineke 572 pab[0] = pos[ax] - pos[bx];
487     pab[1] = pos[ay] - pos[by];
488     pab[2] = pos[az] - pos[bz];
489 mmeineke 558
490 mmeineke 567 //periodic boundary condition
491    
492 mmeineke 572 info->wrapVector( pab );
493 mmeineke 567
494 mmeineke 572 pabsq = pab[0] * pab[0] + pab[1] * pab[1] + pab[2] * pab[2];
495    
496 mmeineke 561 rabsq = constrainedDsqr[i];
497 mmeineke 567 diffsq = rabsq - pabsq;
498 mmeineke 558
499     // the original rattle code from alan tidesley
500 mmeineke 563 if (fabs(diffsq) > (tol*rabsq*2)) {
501 mmeineke 572 rab[0] = oldPos[ax] - oldPos[bx];
502     rab[1] = oldPos[ay] - oldPos[by];
503     rab[2] = oldPos[az] - oldPos[bz];
504 mmeineke 567
505 mmeineke 572 info->wrapVector( rab );
506 mmeineke 558
507 mmeineke 572 rpab = rab[0] * pab[0] + rab[1] * pab[1] + rab[2] * pab[2];
508 mmeineke 567
509 mmeineke 558 rpabsq = rpab * rpab;
510    
511    
512     if (rpabsq < (rabsq * -diffsq)){
513 mmeineke 563
514 mmeineke 558 #ifdef IS_MPI
515     a = atoms[a]->getGlobalIndex();
516     b = atoms[b]->getGlobalIndex();
517     #endif //is_mpi
518     sprintf( painCave.errMsg,
519 mmeineke 563 "Constraint failure in constrainA at atom %d and %d.\n",
520 mmeineke 558 a, b );
521     painCave.isFatal = 1;
522     simError();
523     }
524    
525     rma = 1.0 / atoms[a]->getMass();
526     rmb = 1.0 / atoms[b]->getMass();
527 mmeineke 567
528 mmeineke 558 gab = diffsq / ( 2.0 * ( rma + rmb ) * rpab );
529 mmeineke 567
530 mmeineke 572 dx = rab[0] * gab;
531     dy = rab[1] * gab;
532     dz = rab[2] * gab;
533 mmeineke 558
534 mmeineke 563 pos[ax] += rma * dx;
535     pos[ay] += rma * dy;
536     pos[az] += rma * dz;
537 mmeineke 558
538 mmeineke 563 pos[bx] -= rmb * dx;
539     pos[by] -= rmb * dy;
540     pos[bz] -= rmb * dz;
541 mmeineke 558
542     dx = dx / dt;
543     dy = dy / dt;
544     dz = dz / dt;
545    
546 mmeineke 563 vel[ax] += rma * dx;
547     vel[ay] += rma * dy;
548     vel[az] += rma * dz;
549 mmeineke 558
550 mmeineke 563 vel[bx] -= rmb * dx;
551     vel[by] -= rmb * dy;
552     vel[bz] -= rmb * dz;
553 mmeineke 558
554     moving[a] = 1;
555     moving[b] = 1;
556     done = 0;
557     }
558     }
559     }
560    
561     for(i=0; i<nAtoms; i++){
562    
563     moved[i] = moving[i];
564     moving[i] = 0;
565     }
566    
567     iteration++;
568     }
569    
570     if( !done ){
571    
572 mmeineke 561 sprintf( painCave.errMsg,
573 mmeineke 558 "Constraint failure in constrainA, too many iterations: %d\n",
574 mmeineke 561 iteration );
575 mmeineke 558 painCave.isFatal = 1;
576     simError();
577     }
578    
579     }
580    
581     void Integrator::constrainB( void ){
582    
583     int i,j,k;
584     int done;
585     double vxab, vyab, vzab;
586 mmeineke 572 double rab[3];
587 mmeineke 563 int a, b, ax, ay, az, bx, by, bz;
588 mmeineke 558 double rma, rmb;
589     double dx, dy, dz;
590     double rabsq, pabsq, rvab;
591     double diffsq;
592     double gab;
593     int iteration;
594    
595 mmeineke 561 for(i=0; i<nAtoms; i++){
596 mmeineke 558 moving[i] = 0;
597     moved[i] = 1;
598     }
599    
600     done = 0;
601 mmeineke 561 iteration = 0;
602 mmeineke 558 while( !done && (iteration < maxIteration ) ){
603    
604 mmeineke 567 done = 1;
605    
606 mmeineke 558 for(i=0; i<nConstrained; i++){
607    
608     a = constrainedA[i];
609     b = constrainedB[i];
610    
611 mmeineke 567 ax = (a*3) + 0;
612     ay = (a*3) + 1;
613     az = (a*3) + 2;
614 mmeineke 563
615 mmeineke 567 bx = (b*3) + 0;
616     by = (b*3) + 1;
617     bz = (b*3) + 2;
618 mmeineke 563
619 mmeineke 558 if( moved[a] || moved[b] ){
620    
621 mmeineke 563 vxab = vel[ax] - vel[bx];
622     vyab = vel[ay] - vel[by];
623     vzab = vel[az] - vel[bz];
624 mmeineke 558
625 mmeineke 572 rab[0] = pos[ax] - pos[bx];
626     rab[1] = pos[ay] - pos[by];
627     rab[2] = pos[az] - pos[bz];
628 mmeineke 558
629 mmeineke 572 info->wrapVector( rab );
630 mmeineke 567
631 mmeineke 558 rma = 1.0 / atoms[a]->getMass();
632     rmb = 1.0 / atoms[b]->getMass();
633    
634 mmeineke 572 rvab = rab[0] * vxab + rab[1] * vyab + rab[2] * vzab;
635 mmeineke 558
636 mmeineke 561 gab = -rvab / ( ( rma + rmb ) * constrainedDsqr[i] );
637 mmeineke 558
638     if (fabs(gab) > tol) {
639    
640 mmeineke 572 dx = rab[0] * gab;
641     dy = rab[1] * gab;
642     dz = rab[2] * gab;
643 mmeineke 558
644 mmeineke 563 vel[ax] += rma * dx;
645     vel[ay] += rma * dy;
646     vel[az] += rma * dz;
647 mmeineke 558
648 mmeineke 563 vel[bx] -= rmb * dx;
649     vel[by] -= rmb * dy;
650     vel[bz] -= rmb * dz;
651 mmeineke 558
652     moving[a] = 1;
653     moving[b] = 1;
654     done = 0;
655     }
656     }
657     }
658    
659     for(i=0; i<nAtoms; i++){
660     moved[i] = moving[i];
661     moving[i] = 0;
662     }
663    
664     iteration++;
665     }
666    
667     if( !done ){
668    
669    
670 mmeineke 561 sprintf( painCave.errMsg,
671 mmeineke 558 "Constraint failure in constrainB, too many iterations: %d\n",
672 mmeineke 561 iteration );
673 mmeineke 558 painCave.isFatal = 1;
674     simError();
675     }
676    
677     }
678    
679    
680    
681    
682    
683    
684    
685     void Integrator::rotate( int axes1, int axes2, double angle, double ji[3],
686 mmeineke 597 double A[9] ){
687 mmeineke 558
688     int i,j,k;
689     double sinAngle;
690     double cosAngle;
691     double angleSqr;
692     double angleSqrOver4;
693     double top, bottom;
694     double rot[3][3];
695     double tempA[3][3];
696     double tempJ[3];
697    
698 mmeineke 597
699 mmeineke 558 // initialize the tempA
700    
701     for(i=0; i<3; i++){
702     for(j=0; j<3; j++){
703 mmeineke 597 tempA[j][i] = A[3*i+j];
704 mmeineke 558 }
705     }
706    
707     // initialize the tempJ
708    
709     for( i=0; i<3; i++) tempJ[i] = ji[i];
710    
711     // initalize rot as a unit matrix
712    
713     rot[0][0] = 1.0;
714     rot[0][1] = 0.0;
715     rot[0][2] = 0.0;
716    
717     rot[1][0] = 0.0;
718     rot[1][1] = 1.0;
719     rot[1][2] = 0.0;
720    
721     rot[2][0] = 0.0;
722     rot[2][1] = 0.0;
723     rot[2][2] = 1.0;
724    
725     // use a small angle aproximation for sin and cosine
726    
727     angleSqr = angle * angle;
728     angleSqrOver4 = angleSqr / 4.0;
729     top = 1.0 - angleSqrOver4;
730     bottom = 1.0 + angleSqrOver4;
731    
732     cosAngle = top / bottom;
733     sinAngle = angle / bottom;
734    
735     rot[axes1][axes1] = cosAngle;
736     rot[axes2][axes2] = cosAngle;
737    
738     rot[axes1][axes2] = sinAngle;
739     rot[axes2][axes1] = -sinAngle;
740    
741     // rotate the momentum acoording to: ji[] = rot[][] * ji[]
742    
743     for(i=0; i<3; i++){
744     ji[i] = 0.0;
745     for(k=0; k<3; k++){
746     ji[i] += rot[i][k] * tempJ[k];
747     }
748     }
749    
750     // rotate the Rotation matrix acording to:
751     // A[][] = A[][] * transpose(rot[][])
752    
753    
754 mmeineke 561 // NOte for as yet unknown reason, we are performing the
755 mmeineke 558 // calculation as:
756     // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
757    
758     for(i=0; i<3; i++){
759     for(j=0; j<3; j++){
760 mmeineke 597 A[3*j+i] = 0.0;
761 mmeineke 558 for(k=0; k<3; k++){
762 mmeineke 597 A[3*j+i] += tempA[i][k] * rot[j][k];
763 mmeineke 558 }
764     }
765     }
766     }