ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 1452
Committed: Mon Aug 23 15:11:36 2004 UTC (19 years, 10 months ago) by tim
File size: 21290 byte(s)
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 mmeineke 558 #include <iostream>
2 gezelter 829 #include <stdlib.h>
3     #include <math.h>
4 tim 1234 #include "Rattle.hpp"
5 tim 1268 #include "Roll.hpp"
6 mmeineke 558 #ifdef IS_MPI
7     #include "mpiSimulation.hpp"
8     #include <unistd.h>
9     #endif //is_mpi
10    
11 chuckv 892 #ifdef PROFILE
12     #include "mdProfile.hpp"
13     #endif // profile
14    
15 mmeineke 558 #include "Integrator.hpp"
16     #include "simError.h"
17    
18    
19 tim 725 template<typename T> Integrator<T>::Integrator(SimInfo* theInfo,
20     ForceFields* the_ff){
21 mmeineke 558 info = theInfo;
22     myFF = the_ff;
23     isFirst = 1;
24    
25     molecules = info->molecules;
26     nMols = info->n_mol;
27    
28     // give a little love back to the SimInfo object
29 tim 725
30     if (info->the_integrator != NULL){
31     delete info->the_integrator;
32     }
33 tim 837
34 mmeineke 558 nAtoms = info->n_atoms;
35 gezelter 1097 integrableObjects = info->integrableObjects;
36 tim 1234
37 tim 1452 consFramework = new RollFramework(info);
38 tim 1234
39 tim 1268 if(consFramework == NULL){
40 tim 1234 sprintf(painCave.errMsg,
41     "Integrator::Intergrator() Error: Memory allocation error for RattleFramework" );
42     painCave.isFatal = 1;
43     simError();
44     }
45    
46     /*
47 mmeineke 558 // check for constraints
48 tim 725
49     constrainedA = NULL;
50     constrainedB = NULL;
51 mmeineke 558 constrainedDsqr = NULL;
52 tim 725 moving = NULL;
53     moved = NULL;
54     oldPos = NULL;
55    
56 mmeineke 558 nConstrained = 0;
57    
58     checkConstraints();
59 tim 1234 */
60 mmeineke 558 }
61    
62 tim 725 template<typename T> Integrator<T>::~Integrator(){
63 tim 1268 if (consFramework != NULL)
64     delete consFramework;
65 tim 1234 /*
66 tim 725 if (nConstrained){
67 mmeineke 558 delete[] constrainedA;
68     delete[] constrainedB;
69     delete[] constrainedDsqr;
70     delete[] moving;
71     delete[] moved;
72 mmeineke 561 delete[] oldPos;
73 mmeineke 558 }
74 tim 1234 */
75 mmeineke 558 }
76    
77 tim 1234 /*
78 tim 725 template<typename T> void Integrator<T>::checkConstraints(void){
79 mmeineke 558 isConstrained = 0;
80    
81 tim 725 Constraint* temp_con;
82     Constraint* dummy_plug;
83 mmeineke 558 temp_con = new Constraint[info->n_SRI];
84     nConstrained = 0;
85     int constrained = 0;
86 tim 725
87 mmeineke 558 SRI** theArray;
88 tim 725 for (int i = 0; i < nMols; i++){
89 tim 1057
90     theArray = (SRI * *) molecules[i].getMyBonds();
91 tim 725 for (int j = 0; j < molecules[i].getNBonds(); j++){
92 mmeineke 558 constrained = theArray[j]->is_constrained();
93 mmeineke 594
94 tim 725 if (constrained){
95     dummy_plug = theArray[j]->get_constraint();
96     temp_con[nConstrained].set_a(dummy_plug->get_a());
97     temp_con[nConstrained].set_b(dummy_plug->get_b());
98     temp_con[nConstrained].set_dsqr(dummy_plug->get_dsqr());
99 mmeineke 594
100 tim 725 nConstrained++;
101     constrained = 0;
102     }
103 mmeineke 558 }
104    
105 tim 725 theArray = (SRI * *) molecules[i].getMyBends();
106     for (int j = 0; j < molecules[i].getNBends(); j++){
107 mmeineke 558 constrained = theArray[j]->is_constrained();
108 tim 725
109     if (constrained){
110     dummy_plug = theArray[j]->get_constraint();
111     temp_con[nConstrained].set_a(dummy_plug->get_a());
112 tim 1268 temp_con[nConstrained].set_b(Dummy_plug->get_b());
113 tim 725 temp_con[nConstrained].set_dsqr(dummy_plug->get_dsqr());
114    
115     nConstrained++;
116     constrained = 0;
117 mmeineke 558 }
118     }
119    
120 tim 725 theArray = (SRI * *) molecules[i].getMyTorsions();
121     for (int j = 0; j < molecules[i].getNTorsions(); j++){
122 mmeineke 558 constrained = theArray[j]->is_constrained();
123 tim 725
124     if (constrained){
125     dummy_plug = theArray[j]->get_constraint();
126     temp_con[nConstrained].set_a(dummy_plug->get_a());
127     temp_con[nConstrained].set_b(dummy_plug->get_b());
128     temp_con[nConstrained].set_dsqr(dummy_plug->get_dsqr());
129    
130     nConstrained++;
131     constrained = 0;
132 mmeineke 558 }
133     }
134     }
135    
136 tim 1057
137 tim 725 if (nConstrained > 0){
138 mmeineke 558 isConstrained = 1;
139    
140 tim 725 if (constrainedA != NULL)
141     delete[] constrainedA;
142     if (constrainedB != NULL)
143     delete[] constrainedB;
144     if (constrainedDsqr != NULL)
145     delete[] constrainedDsqr;
146 mmeineke 558
147 tim 725 constrainedA = new int[nConstrained];
148     constrainedB = new int[nConstrained];
149 mmeineke 558 constrainedDsqr = new double[nConstrained];
150 tim 725
151     for (int i = 0; i < nConstrained; i++){
152 mmeineke 558 constrainedA[i] = temp_con[i].get_a();
153     constrainedB[i] = temp_con[i].get_b();
154     constrainedDsqr[i] = temp_con[i].get_dsqr();
155     }
156    
157 tim 725
158 chrisfen 999 // save oldAtoms to check for lode balancing later on.
159 tim 725
160 mmeineke 558 oldAtoms = nAtoms;
161 tim 725
162 mmeineke 558 moving = new int[nAtoms];
163 tim 725 moved = new int[nAtoms];
164 mmeineke 558
165 tim 725 oldPos = new double[nAtoms * 3];
166 mmeineke 558 }
167 tim 725
168 mmeineke 558 delete[] temp_con;
169     }
170 tim 1234 */
171 mmeineke 558
172 tim 725 template<typename T> void Integrator<T>::integrate(void){
173 mmeineke 558
174 tim 725 double runTime = info->run_time;
175     double sampleTime = info->sampleTime;
176     double statusTime = info->statusTime;
177 mmeineke 558 double thermalTime = info->thermalTime;
178 mmeineke 746 double resetTime = info->resetTime;
179 mmeineke 558
180 gezelter 1178 double difference;
181 mmeineke 558 double currSample;
182     double currThermal;
183     double currStatus;
184 mmeineke 746 double currReset;
185 tim 837
186 mmeineke 558 int calcPot, calcStress;
187    
188 tim 725 tStats = new Thermo(info);
189     statOut = new StatWriter(info);
190     dumpOut = new DumpWriter(info);
191 mmeineke 558
192 mmeineke 561 atoms = info->atoms;
193    
194     dt = info->dt;
195 mmeineke 558 dt2 = 0.5 * dt;
196    
197 mmeineke 784 readyCheck();
198    
199 tim 1127 // remove center of mass drift velocity (in case we passed in a configuration
200     // that was drifting
201     tStats->removeCOMdrift();
202 tim 1452 //tStats->removeAngularMomentum();
203    
204 chrisfen 1180 // initialize the retraints if necessary
205 chrisfen 1212 if (info->useSolidThermInt && !info->useLiquidThermInt) {
206 chrisfen 1180 myFF->initRestraints();
207     }
208    
209 mmeineke 558 // initialize the forces before the first step
210    
211 tim 677 calcForce(1, 1);
212 tim 1234
213     //execute constraint algorithm to make sure at the very beginning the system is constrained
214 tim 1284 //consFramework->doPreConstraint();
215     //consFramework->doConstrainA();
216     //calcForce(1, 1);
217     //consFramework->doConstrainB();
218 tim 1035
219 tim 725 if (info->setTemp){
220 tim 677 thermalize();
221 mmeineke 558 }
222 tim 725
223 mmeineke 558 calcPot = 0;
224     calcStress = 0;
225 mmeineke 711 currSample = sampleTime + info->getTime();
226     currThermal = thermalTime+ info->getTime();
227     currStatus = statusTime + info->getTime();
228 mmeineke 746 currReset = resetTime + info->getTime();
229 mmeineke 558
230 tim 725 dumpOut->writeDump(info->getTime());
231     statOut->writeStat(info->getTime());
232 mmeineke 559
233    
234     #ifdef IS_MPI
235 tim 725 strcpy(checkPointMsg, "The integrator is ready to go.");
236 mmeineke 559 MPIcheckPoint();
237     #endif // is_mpi
238    
239 tim 1113 while (info->getTime() < runTime && !stopIntegrator()){
240 gezelter 1178 difference = info->getTime() + dt - currStatus;
241     if (difference > 0 || fabs(difference) < 1e-4 ){
242 mmeineke 558 calcPot = 1;
243     calcStress = 1;
244     }
245 mmeineke 561
246 chuckv 892 #ifdef PROFILE
247     startProfile( pro1 );
248     #endif
249    
250 tim 725 integrateStep(calcPot, calcStress);
251    
252 chuckv 892 #ifdef PROFILE
253     endProfile( pro1 );
254    
255     startProfile( pro2 );
256     #endif // profile
257    
258 mmeineke 643 info->incrTime(dt);
259 mmeineke 558
260 tim 725 if (info->setTemp){
261     if (info->getTime() >= currThermal){
262     thermalize();
263     currThermal += thermalTime;
264 mmeineke 558 }
265     }
266    
267 tim 725 if (info->getTime() >= currSample){
268     dumpOut->writeDump(info->getTime());
269 mmeineke 558 currSample += sampleTime;
270     }
271    
272 tim 725 if (info->getTime() >= currStatus){
273 tim 837 statOut->writeStat(info->getTime());
274     calcPot = 0;
275 mmeineke 558 calcStress = 0;
276     currStatus += statusTime;
277 tim 837 }
278 mmeineke 559
279 mmeineke 746 if (info->resetIntegrator){
280     if (info->getTime() >= currReset){
281     this->resetIntegrator();
282     currReset += resetTime;
283     }
284     }
285 chuckv 892
286     #ifdef PROFILE
287     endProfile( pro2 );
288     #endif //profile
289 mmeineke 746
290 mmeineke 559 #ifdef IS_MPI
291 tim 725 strcpy(checkPointMsg, "successfully took a time step.");
292 mmeineke 559 MPIcheckPoint();
293     #endif // is_mpi
294 mmeineke 558 }
295    
296 chrisfen 1180 // dump out a file containing the omega values for the final configuration
297 chrisfen 1212 if (info->useSolidThermInt && !info->useLiquidThermInt)
298 chrisfen 1180 myFF->dumpzAngle();
299    
300    
301 mmeineke 561 delete dumpOut;
302     delete statOut;
303 mmeineke 558 }
304    
305 tim 725 template<typename T> void Integrator<T>::integrateStep(int calcPot,
306     int calcStress){
307 mmeineke 558 // Position full step, and velocity half step
308 chuckv 892
309     #ifdef PROFILE
310     startProfile(pro3);
311     #endif //profile
312    
313 tim 1234 //save old state (position, velocity etc)
314 tim 1268 consFramework->doPreConstraint();
315 mmeineke 558
316 chuckv 892 #ifdef PROFILE
317     endProfile(pro3);
318    
319     startProfile(pro4);
320     #endif // profile
321    
322 mmeineke 558 moveA();
323    
324 chuckv 892 #ifdef PROFILE
325     endProfile(pro4);
326    
327     startProfile(pro5);
328     #endif//profile
329 tim 725
330    
331 mmeineke 614 #ifdef IS_MPI
332 tim 725 strcpy(checkPointMsg, "Succesful moveA\n");
333 mmeineke 614 MPIcheckPoint();
334     #endif // is_mpi
335    
336 mmeineke 558 // calc forces
337 tim 725 calcForce(calcPot, calcStress);
338 mmeineke 558
339 mmeineke 614 #ifdef IS_MPI
340 tim 725 strcpy(checkPointMsg, "Succesful doForces\n");
341 mmeineke 614 MPIcheckPoint();
342     #endif // is_mpi
343    
344 chuckv 892 #ifdef PROFILE
345     endProfile( pro5 );
346 tim 725
347 chuckv 892 startProfile( pro6 );
348     #endif //profile
349    
350 tim 1452 consFramework->doPreConstraint();
351    
352 mmeineke 558 // finish the velocity half step
353 tim 725
354 mmeineke 558 moveB();
355 tim 725
356 chuckv 892 #ifdef PROFILE
357     endProfile(pro6);
358     #endif // profile
359 tim 725
360 mmeineke 614 #ifdef IS_MPI
361 tim 725 strcpy(checkPointMsg, "Succesful moveB\n");
362 mmeineke 614 MPIcheckPoint();
363     #endif // is_mpi
364 mmeineke 558 }
365    
366    
367 tim 725 template<typename T> void Integrator<T>::moveA(void){
368 gezelter 1097 size_t i, j;
369 mmeineke 558 DirectionalAtom* dAtom;
370 gezelter 600 double Tb[3], ji[3];
371     double vel[3], pos[3], frc[3];
372     double mass;
373 chrisfen 1187 double omega;
374 gezelter 1097
375     for (i = 0; i < integrableObjects.size() ; i++){
376     integrableObjects[i]->getVel(vel);
377     integrableObjects[i]->getPos(pos);
378     integrableObjects[i]->getFrc(frc);
379    
380     mass = integrableObjects[i]->getMass();
381 mmeineke 558
382 tim 725 for (j = 0; j < 3; j++){
383 gezelter 600 // velocity half step
384 tim 725 vel[j] += (dt2 * frc[j] / mass) * eConvert;
385 gezelter 600 // position whole step
386     pos[j] += dt * vel[j];
387     }
388 mmeineke 594
389 gezelter 1097 integrableObjects[i]->setVel(vel);
390     integrableObjects[i]->setPos(pos);
391 gezelter 600
392 gezelter 1097 if (integrableObjects[i]->isDirectional()){
393 mmeineke 558
394     // get and convert the torque to body frame
395 mmeineke 597
396 gezelter 1097 integrableObjects[i]->getTrq(Tb);
397     integrableObjects[i]->lab2Body(Tb);
398 tim 725
399 mmeineke 558 // get the angular momentum, and propagate a half step
400 gezelter 600
401 gezelter 1097 integrableObjects[i]->getJ(ji);
402 gezelter 600
403 tim 725 for (j = 0; j < 3; j++)
404 gezelter 600 ji[j] += (dt2 * Tb[j]) * eConvert;
405 tim 725
406 gezelter 1097 this->rotationPropagation( integrableObjects[i], ji );
407 gezelter 600
408 gezelter 1097 integrableObjects[i]->setJ(ji);
409 tim 1452
410 tim 725 }
411 mmeineke 558 }
412 mmeineke 768
413 tim 1268 consFramework->doConstrainA();
414 mmeineke 558 }
415    
416    
417 tim 725 template<typename T> void Integrator<T>::moveB(void){
418 gezelter 600 int i, j;
419     double Tb[3], ji[3];
420     double vel[3], frc[3];
421     double mass;
422 mmeineke 558
423 gezelter 1097 for (i = 0; i < integrableObjects.size(); i++){
424     integrableObjects[i]->getVel(vel);
425     integrableObjects[i]->getFrc(frc);
426 mmeineke 558
427 gezelter 1097 mass = integrableObjects[i]->getMass();
428 gezelter 600
429 mmeineke 558 // velocity half step
430 tim 725 for (j = 0; j < 3; j++)
431     vel[j] += (dt2 * frc[j] / mass) * eConvert;
432 gezelter 600
433 gezelter 1097 integrableObjects[i]->setVel(vel);
434 mmeineke 597
435 gezelter 1097 if (integrableObjects[i]->isDirectional()){
436 tim 725
437 tim 837 // get and convert the torque to body frame
438 gezelter 600
439 gezelter 1097 integrableObjects[i]->getTrq(Tb);
440     integrableObjects[i]->lab2Body(Tb);
441 gezelter 600
442     // get the angular momentum, and propagate a half step
443    
444 gezelter 1097 integrableObjects[i]->getJ(ji);
445 gezelter 600
446 tim 725 for (j = 0; j < 3; j++)
447 gezelter 600 ji[j] += (dt2 * Tb[j]) * eConvert;
448 mmeineke 597
449 tim 725
450 gezelter 1097 integrableObjects[i]->setJ(ji);
451 mmeineke 558 }
452 tim 1452
453 mmeineke 558 }
454 mmeineke 768
455 tim 1268 consFramework->doConstrainB();
456 mmeineke 558 }
457    
458 tim 1234 /*
459 tim 725 template<typename T> void Integrator<T>::preMove(void){
460 gezelter 600 int i, j;
461     double pos[3];
462 mmeineke 558
463 tim 725 if (nConstrained){
464     for (i = 0; i < nAtoms; i++){
465     atoms[i]->getPos(pos);
466 mmeineke 561
467 tim 725 for (j = 0; j < 3; j++){
468     oldPos[3 * i + j] = pos[j];
469 gezelter 600 }
470     }
471 tim 725 }
472 gezelter 600 }
473    
474 tim 645 template<typename T> void Integrator<T>::constrainA(){
475 mmeineke 787 int i, j;
476 mmeineke 558 int done;
477 gezelter 600 double posA[3], posB[3];
478     double velA[3], velB[3];
479 mmeineke 572 double pab[3];
480     double rab[3];
481 mmeineke 563 int a, b, ax, ay, az, bx, by, bz;
482 mmeineke 558 double rma, rmb;
483     double dx, dy, dz;
484 mmeineke 561 double rpab;
485 mmeineke 558 double rabsq, pabsq, rpabsq;
486     double diffsq;
487     double gab;
488     int iteration;
489    
490 tim 725 for (i = 0; i < nAtoms; i++){
491 mmeineke 558 moving[i] = 0;
492 tim 725 moved[i] = 1;
493 mmeineke 558 }
494 mmeineke 567
495 mmeineke 558 iteration = 0;
496     done = 0;
497 tim 725 while (!done && (iteration < maxIteration)){
498 mmeineke 558 done = 1;
499 tim 725 for (i = 0; i < nConstrained; i++){
500 mmeineke 558 a = constrainedA[i];
501     b = constrainedB[i];
502 mmeineke 563
503 tim 725 ax = (a * 3) + 0;
504     ay = (a * 3) + 1;
505     az = (a * 3) + 2;
506 mmeineke 563
507 tim 725 bx = (b * 3) + 0;
508     by = (b * 3) + 1;
509     bz = (b * 3) + 2;
510    
511     if (moved[a] || moved[b]){
512     atoms[a]->getPos(posA);
513     atoms[b]->getPos(posB);
514    
515     for (j = 0; j < 3; j++)
516 gezelter 600 pab[j] = posA[j] - posB[j];
517 mmeineke 567
518 tim 725 //periodic boundary condition
519 mmeineke 567
520 tim 725 info->wrapVector(pab);
521 mmeineke 572
522 tim 725 pabsq = pab[0] * pab[0] + pab[1] * pab[1] + pab[2] * pab[2];
523 mmeineke 558
524 tim 725 rabsq = constrainedDsqr[i];
525     diffsq = rabsq - pabsq;
526 mmeineke 567
527 tim 725 // the original rattle code from alan tidesley
528     if (fabs(diffsq) > (tol * rabsq * 2)){
529     rab[0] = oldPos[ax] - oldPos[bx];
530     rab[1] = oldPos[ay] - oldPos[by];
531     rab[2] = oldPos[az] - oldPos[bz];
532 mmeineke 558
533 tim 725 info->wrapVector(rab);
534 mmeineke 567
535 tim 725 rpab = rab[0] * pab[0] + rab[1] * pab[1] + rab[2] * pab[2];
536 mmeineke 558
537 tim 725 rpabsq = rpab * rpab;
538 mmeineke 558
539 mmeineke 563
540 tim 725 if (rpabsq < (rabsq * -diffsq)){
541 mmeineke 558 #ifdef IS_MPI
542 tim 725 a = atoms[a]->getGlobalIndex();
543     b = atoms[b]->getGlobalIndex();
544 mmeineke 558 #endif //is_mpi
545 tim 725 sprintf(painCave.errMsg,
546     "Constraint failure in constrainA at atom %d and %d.\n", a,
547     b);
548     painCave.isFatal = 1;
549     simError();
550     }
551 mmeineke 558
552 tim 725 rma = 1.0 / atoms[a]->getMass();
553     rmb = 1.0 / atoms[b]->getMass();
554 mmeineke 567
555 tim 725 gab = diffsq / (2.0 * (rma + rmb) * rpab);
556 mmeineke 567
557 mmeineke 572 dx = rab[0] * gab;
558     dy = rab[1] * gab;
559     dz = rab[2] * gab;
560 mmeineke 558
561 tim 725 posA[0] += rma * dx;
562     posA[1] += rma * dy;
563     posA[2] += rma * dz;
564 mmeineke 558
565 tim 725 atoms[a]->setPos(posA);
566 mmeineke 558
567 tim 725 posB[0] -= rmb * dx;
568     posB[1] -= rmb * dy;
569     posB[2] -= rmb * dz;
570 gezelter 600
571 tim 725 atoms[b]->setPos(posB);
572 gezelter 600
573 mmeineke 558 dx = dx / dt;
574     dy = dy / dt;
575     dz = dz / dt;
576    
577 tim 725 atoms[a]->getVel(velA);
578 mmeineke 558
579 tim 725 velA[0] += rma * dx;
580     velA[1] += rma * dy;
581     velA[2] += rma * dz;
582 mmeineke 558
583 tim 725 atoms[a]->setVel(velA);
584 gezelter 600
585 tim 725 atoms[b]->getVel(velB);
586 gezelter 600
587 tim 725 velB[0] -= rmb * dx;
588     velB[1] -= rmb * dy;
589     velB[2] -= rmb * dz;
590 gezelter 600
591 tim 725 atoms[b]->setVel(velB);
592 gezelter 600
593 tim 725 moving[a] = 1;
594     moving[b] = 1;
595     done = 0;
596     }
597 mmeineke 558 }
598     }
599 tim 725
600     for (i = 0; i < nAtoms; i++){
601 mmeineke 558 moved[i] = moving[i];
602     moving[i] = 0;
603     }
604    
605     iteration++;
606     }
607    
608 tim 725 if (!done){
609     sprintf(painCave.errMsg,
610     "Constraint failure in constrainA, too many iterations: %d\n",
611     iteration);
612 mmeineke 558 painCave.isFatal = 1;
613     simError();
614     }
615 mmeineke 768
616 mmeineke 558 }
617    
618 tim 725 template<typename T> void Integrator<T>::constrainB(void){
619 mmeineke 787 int i, j;
620 mmeineke 558 int done;
621 gezelter 600 double posA[3], posB[3];
622     double velA[3], velB[3];
623 mmeineke 558 double vxab, vyab, vzab;
624 mmeineke 572 double rab[3];
625 mmeineke 563 int a, b, ax, ay, az, bx, by, bz;
626 mmeineke 558 double rma, rmb;
627     double dx, dy, dz;
628 mmeineke 787 double rvab;
629 mmeineke 558 double gab;
630     int iteration;
631    
632 tim 725 for (i = 0; i < nAtoms; i++){
633 mmeineke 558 moving[i] = 0;
634     moved[i] = 1;
635     }
636    
637     done = 0;
638 mmeineke 561 iteration = 0;
639 tim 725 while (!done && (iteration < maxIteration)){
640 mmeineke 567 done = 1;
641    
642 tim 725 for (i = 0; i < nConstrained; i++){
643 mmeineke 558 a = constrainedA[i];
644     b = constrainedB[i];
645    
646 tim 725 ax = (a * 3) + 0;
647     ay = (a * 3) + 1;
648     az = (a * 3) + 2;
649 mmeineke 563
650 tim 725 bx = (b * 3) + 0;
651     by = (b * 3) + 1;
652     bz = (b * 3) + 2;
653 mmeineke 563
654 tim 725 if (moved[a] || moved[b]){
655     atoms[a]->getVel(velA);
656     atoms[b]->getVel(velB);
657 mmeineke 558
658 tim 725 vxab = velA[0] - velB[0];
659     vyab = velA[1] - velB[1];
660     vzab = velA[2] - velB[2];
661 gezelter 600
662 tim 725 atoms[a]->getPos(posA);
663     atoms[b]->getPos(posB);
664 gezelter 600
665 tim 725 for (j = 0; j < 3; j++)
666 gezelter 600 rab[j] = posA[j] - posB[j];
667 mmeineke 558
668 tim 725 info->wrapVector(rab);
669 mmeineke 558
670 tim 725 rma = 1.0 / atoms[a]->getMass();
671     rmb = 1.0 / atoms[b]->getMass();
672 mmeineke 558
673 tim 725 rvab = rab[0] * vxab + rab[1] * vyab + rab[2] * vzab;
674 gezelter 600
675 tim 725 gab = -rvab / ((rma + rmb) * constrainedDsqr[i]);
676 gezelter 600
677 tim 725 if (fabs(gab) > tol){
678     dx = rab[0] * gab;
679     dy = rab[1] * gab;
680     dz = rab[2] * gab;
681    
682     velA[0] += rma * dx;
683     velA[1] += rma * dy;
684     velA[2] += rma * dz;
685    
686     atoms[a]->setVel(velA);
687    
688     velB[0] -= rmb * dx;
689     velB[1] -= rmb * dy;
690     velB[2] -= rmb * dz;
691    
692     atoms[b]->setVel(velB);
693    
694     moving[a] = 1;
695     moving[b] = 1;
696     done = 0;
697     }
698 mmeineke 558 }
699     }
700    
701 tim 725 for (i = 0; i < nAtoms; i++){
702 mmeineke 558 moved[i] = moving[i];
703     moving[i] = 0;
704     }
705 tim 725
706 mmeineke 558 iteration++;
707     }
708    
709 tim 725 if (!done){
710     sprintf(painCave.errMsg,
711     "Constraint failure in constrainB, too many iterations: %d\n",
712     iteration);
713 mmeineke 558 painCave.isFatal = 1;
714     simError();
715 tim 725 }
716 mmeineke 558 }
717 tim 1234 */
718 mmeineke 778 template<typename T> void Integrator<T>::rotationPropagation
719 gezelter 1097 ( StuntDouble* sd, double ji[3] ){
720 mmeineke 778
721     double angle;
722     double A[3][3], I[3][3];
723 tim 1118 int i, j, k;
724 mmeineke 778
725     // use the angular velocities to propagate the rotation matrix a
726     // full time step
727    
728 gezelter 1097 sd->getA(A);
729     sd->getI(I);
730 tim 837
731 tim 1118 if (sd->isLinear()) {
732     i = sd->linearAxis();
733     j = (i+1)%3;
734     k = (i+2)%3;
735    
736     angle = dt2 * ji[j] / I[j][j];
737     this->rotate( k, i, angle, ji, A );
738    
739     angle = dt * ji[k] / I[k][k];
740     this->rotate( i, j, angle, ji, A);
741    
742     angle = dt2 * ji[j] / I[j][j];
743     this->rotate( k, i, angle, ji, A );
744    
745     } else {
746 gezelter 1125 // rotate about the x-axis
747     angle = dt2 * ji[0] / I[0][0];
748     this->rotate( 1, 2, angle, ji, A );
749    
750     // rotate about the y-axis
751     angle = dt2 * ji[1] / I[1][1];
752     this->rotate( 2, 0, angle, ji, A );
753    
754     // rotate about the z-axis
755     angle = dt * ji[2] / I[2][2];
756 chrisfen 1187 sd->addZangle(angle);
757 gezelter 1125 this->rotate( 0, 1, angle, ji, A);
758    
759     // rotate about the y-axis
760     angle = dt2 * ji[1] / I[1][1];
761     this->rotate( 2, 0, angle, ji, A );
762    
763     // rotate about the x-axis
764     angle = dt2 * ji[0] / I[0][0];
765     this->rotate( 1, 2, angle, ji, A );
766    
767 tim 1118 }
768 gezelter 1097 sd->setA( A );
769 mmeineke 778 }
770    
771 tim 725 template<typename T> void Integrator<T>::rotate(int axes1, int axes2,
772     double angle, double ji[3],
773     double A[3][3]){
774     int i, j, k;
775 mmeineke 558 double sinAngle;
776     double cosAngle;
777     double angleSqr;
778     double angleSqrOver4;
779     double top, bottom;
780     double rot[3][3];
781     double tempA[3][3];
782     double tempJ[3];
783    
784     // initialize the tempA
785    
786 tim 725 for (i = 0; i < 3; i++){
787     for (j = 0; j < 3; j++){
788 gezelter 600 tempA[j][i] = A[i][j];
789 mmeineke 558 }
790     }
791    
792     // initialize the tempJ
793    
794 tim 725 for (i = 0; i < 3; i++)
795     tempJ[i] = ji[i];
796    
797 mmeineke 558 // initalize rot as a unit matrix
798    
799     rot[0][0] = 1.0;
800     rot[0][1] = 0.0;
801     rot[0][2] = 0.0;
802    
803     rot[1][0] = 0.0;
804     rot[1][1] = 1.0;
805     rot[1][2] = 0.0;
806 tim 725
807 mmeineke 558 rot[2][0] = 0.0;
808     rot[2][1] = 0.0;
809     rot[2][2] = 1.0;
810 tim 725
811 mmeineke 558 // use a small angle aproximation for sin and cosine
812    
813 tim 725 angleSqr = angle * angle;
814 mmeineke 558 angleSqrOver4 = angleSqr / 4.0;
815     top = 1.0 - angleSqrOver4;
816     bottom = 1.0 + angleSqrOver4;
817    
818     cosAngle = top / bottom;
819     sinAngle = angle / bottom;
820    
821     rot[axes1][axes1] = cosAngle;
822     rot[axes2][axes2] = cosAngle;
823    
824     rot[axes1][axes2] = sinAngle;
825     rot[axes2][axes1] = -sinAngle;
826 tim 725
827 mmeineke 558 // rotate the momentum acoording to: ji[] = rot[][] * ji[]
828 tim 725
829     for (i = 0; i < 3; i++){
830 mmeineke 558 ji[i] = 0.0;
831 tim 725 for (k = 0; k < 3; k++){
832 mmeineke 558 ji[i] += rot[i][k] * tempJ[k];
833     }
834     }
835    
836 tim 837 // rotate the Rotation matrix acording to:
837 mmeineke 558 // A[][] = A[][] * transpose(rot[][])
838    
839    
840 mmeineke 561 // NOte for as yet unknown reason, we are performing the
841 mmeineke 558 // calculation as:
842     // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
843    
844 tim 725 for (i = 0; i < 3; i++){
845     for (j = 0; j < 3; j++){
846 gezelter 600 A[j][i] = 0.0;
847 tim 725 for (k = 0; k < 3; k++){
848     A[j][i] += tempA[i][k] * rot[j][k];
849 mmeineke 558 }
850     }
851     }
852     }
853 tim 677
854 tim 725 template<typename T> void Integrator<T>::calcForce(int calcPot, int calcStress){
855     myFF->doForces(calcPot, calcStress);
856 tim 677 }
857    
858     template<typename T> void Integrator<T>::thermalize(){
859 tim 725 tStats->velocitize();
860 tim 677 }
861 tim 763
862     template<typename T> double Integrator<T>::getConservedQuantity(void){
863     return tStats->getTotalE();
864 mmeineke 768 }
865 tim 837 template<typename T> string Integrator<T>::getAdditionalParameters(void){
866     //By default, return a null string
867     //The reason we use string instead of char* is that if we use char*, we will
868     //return a pointer point to local variable which might cause problem
869     return string();
870     }
871 tim 1452
872    
873     template<typename T> void Integrator<T>::printQuaternion(StuntDouble* sd){
874     Mat4x4d S;
875     double I[3][3];
876     Vector4d j4;
877     Vector3d j;
878     Vector3d tempJ;
879     Vector4d qdot;
880     Vector4d omega4;
881     Mat4x4d I4;
882     Quaternion q;
883     double I0;
884     Vector4d p_qua;
885    
886     if (sd->isDirectional()){
887     sd->getQ(q.vec);
888     sd->getI(I);
889     sd->getJ(j.vec);
890    
891     //omega4[0] = 0.0;
892     //omega4[1] = j[0]/I[0][0];
893     //omega4[2] = j[1]/I[1][1];
894     //omega4[3] = j[2]/I[2][2];
895    
896     //S = getS(q);
897     //qdot = 0.5 * S * omega4;
898    
899     //I0 = (qdot[1] * q[1] * I[0][0] + qdot[2] * q[2] * I[1][1] + qdot[3] * q[3] * I[2][2])/(qdot[1] * q[1]+ qdot[2] * q[2] + qdot[3] * q[3]);
900    
901     //I4.element[0][0] = I0;
902     //I4.element[1][1] = I[0][0];
903     //I4.element[2][2] = I[1][1];
904     //I4.element[3][3] = I[2][2];
905    
906     S = getS(q);
907     j4[0] = 0.0;
908     j4[1] = j[0];
909     j4[2] = j[1];
910     j4[3] = j[2];
911    
912     p_qua = 2 * S * j4;
913    
914     j4 = 0.5 * S.transpose() * p_qua;
915     //cout << "q0^2 + q1^2 + q2^2 + q3^2 = " << q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3] << endl;
916     //cout << "q0*q0dot + q1*q1dot + q2 *q2dot + q3*q3dot = " <<q[0]*qdot[0] + q[1]*qdot[1] + q[2]*qdot[2] + q[3]*qdot[3] << endl;
917     //cout << "q1*q1dot* Ixx + q2*q2dot* Iyy + q3 *q3dot* Izz = " << qdot[1] * q[1] * I[0][0] + qdot[2] * q[2] * I[1][1] + qdot[3] * q[3] * I[2][2] << endl;
918     //cout << "q1*q1dot + q2 *q2dot + q3*q3dot = " << qdot[1] * q[1]+ qdot[2] * q[2] + qdot[3] * q[3] << endl;
919     //cout << "I0 = " << I0 << endl;
920     cout << "p_qua[0] = " << p_qua[0] << endl;
921     }
922     }
923    
924     template<typename T> Mat4x4d Integrator<T>::getS(const Quaternion& q){
925     Mat4x4d result;
926    
927     result.element[0][0] = q.x;
928     result.element[0][1] = -q.y;
929     result.element[0][2] = -q.z;
930     result.element[0][3] = -q.w;
931    
932     result.element[1][0] = q.y;
933     result.element[1][1] = q.x;
934     result.element[1][2] = -q.w;
935     result.element[1][3] = q.z;
936    
937     result.element[2][0] = q.z;
938     result.element[2][1] = q.w;
939     result.element[2][2] = q.x;
940     result.element[2][3] = -q.y;
941    
942     result.element[3][0] = q.w;
943     result.element[3][1] = -q.z;
944     result.element[3][2] = q.y;
945     result.element[3][3] = q.x;
946    
947     return result;
948     }
949