ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 1180
Committed: Thu May 20 20:24:07 2004 UTC (20 years, 3 months ago) by chrisfen
File size: 18519 byte(s)
Log Message:
Several additions... Restraints.cpp and .hpp were included for restraining particles in thermodynamic integration.  By including these, changes were made in Integrator, SimInfo, ForceFeilds, SimSetup, StatWriter, and possibly some other files.  Two bass keywords were also added for performing thermodynamic integration: a lambda value one and a k power one.

File Contents

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