ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 645
Committed: Tue Jul 22 19:54:52 2003 UTC (20 years, 11 months ago) by tim
File size: 15473 byte(s)
Log Message:
*** empty log message ***

File Contents

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