ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 601
Committed: Mon Jul 14 23:06:09 2003 UTC (20 years, 11 months ago) by gezelter
File size: 15009 byte(s)
Log Message:
Removed some debugging write statements

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