ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 1108
Committed: Wed Apr 14 15:37:41 2004 UTC (20 years, 2 months ago) by tim
File size: 17630 byte(s)
Log Message:
Change DumpWriter and InitFromFile

File Contents

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