ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 733
Committed: Wed Aug 27 19:23:29 2003 UTC (20 years, 10 months ago) by tim
File size: 16232 byte(s)
Log Message:
fix bug of MPI_Allreduce in ZConstraint, the MPITYPE is set to MPI_DOUBLE,
however, the corret type is MPI_INT. Therefore, when we turn on the
optimization flag, it causes a seg fault

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