ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 572
Committed: Wed Jul 2 21:26:55 2003 UTC (21 years ago) by mmeineke
File size: 14634 byte(s)
Log Message:
fixed the bugs introduced by switching the periodic box to a matrix

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 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 void Integrator::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 double currTime;
171
172 int calcPot, calcStress;
173 int isError;
174
175
176
177 tStats = new Thermo( info );
178 statOut = new StatWriter( info );
179 dumpOut = new DumpWriter( info );
180
181 atoms = info->atoms;
182 DirectionalAtom* dAtom;
183
184 dt = info->dt;
185 dt2 = 0.5 * dt;
186
187 // initialize the forces before the first step
188
189 myFF->doForces(1,1);
190
191 if( info->setTemp ){
192
193 tStats->velocitize();
194 }
195
196 dumpOut->writeDump( 0.0 );
197 statOut->writeStat( 0.0 );
198
199 calcPot = 0;
200 calcStress = 0;
201 currSample = sampleTime;
202 currThermal = thermalTime;
203 currStatus = statusTime;
204 currTime = 0.0;;
205
206
207 readyCheck();
208
209 #ifdef IS_MPI
210 strcpy( checkPointMsg,
211 "The integrator is ready to go." );
212 MPIcheckPoint();
213 #endif // is_mpi
214
215
216 pos = Atom::getPosArray();
217 vel = Atom::getVelArray();
218 frc = Atom::getFrcArray();
219 trq = Atom::getTrqArray();
220 Amat = Atom::getAmatArray();
221
222 while( currTime < runTime ){
223
224 if( (currTime+dt) >= currStatus ){
225 calcPot = 1;
226 calcStress = 1;
227 }
228
229 integrateStep( calcPot, calcStress );
230
231 currTime += dt;
232
233 if( info->setTemp ){
234 if( currTime >= currThermal ){
235 tStats->velocitize();
236 currThermal += thermalTime;
237 }
238 }
239
240 if( currTime >= currSample ){
241 dumpOut->writeDump( currTime );
242 currSample += sampleTime;
243 }
244
245 if( currTime >= currStatus ){
246 statOut->writeStat( currTime );
247 calcPot = 0;
248 calcStress = 0;
249 currStatus += statusTime;
250 }
251
252 #ifdef IS_MPI
253 strcpy( checkPointMsg,
254 "successfully took a time step." );
255 MPIcheckPoint();
256 #endif // is_mpi
257
258 }
259
260 dumpOut->writeFinal(currTime);
261
262 delete dumpOut;
263 delete statOut;
264 }
265
266 void Integrator::integrateStep( int calcPot, int calcStress ){
267
268
269
270 // Position full step, and velocity half step
271
272 preMove();
273 moveA();
274 if( nConstrained ) constrainA();
275
276 // calc forces
277
278 myFF->doForces(calcPot,calcStress);
279
280 // finish the velocity half step
281
282 moveB();
283 if( nConstrained ) constrainB();
284
285 }
286
287
288 void Integrator::moveA( void ){
289
290 int i,j,k;
291 int atomIndex, aMatIndex;
292 DirectionalAtom* dAtom;
293 double Tb[3];
294 double ji[3];
295 double angle;
296
297
298
299 for( i=0; i<nAtoms; i++ ){
300 atomIndex = i * 3;
301 aMatIndex = i * 9;
302
303 // velocity half step
304 for( j=atomIndex; j<(atomIndex+3); j++ )
305 vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
306
307 // position whole step
308 for( j=atomIndex; j<(atomIndex+3); j++ ) pos[j] += dt * vel[j];
309
310 if( atoms[i]->isDirectional() ){
311
312 dAtom = (DirectionalAtom *)atoms[i];
313
314 // get and convert the torque to body frame
315
316 Tb[0] = dAtom->getTx();
317 Tb[1] = dAtom->getTy();
318 Tb[2] = dAtom->getTz();
319
320 dAtom->lab2Body( Tb );
321
322 // get the angular momentum, and propagate a half step
323
324 ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
325 ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
326 ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
327
328 // use the angular velocities to propagate the rotation matrix a
329 // full time step
330
331 // rotate about the x-axis
332 angle = dt2 * ji[0] / dAtom->getIxx();
333 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
334
335 // rotate about the y-axis
336 angle = dt2 * ji[1] / dAtom->getIyy();
337 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
338
339 // rotate about the z-axis
340 angle = dt * ji[2] / dAtom->getIzz();
341 this->rotate( 0, 1, angle, ji, &Amat[aMatIndex] );
342
343 // rotate about the y-axis
344 angle = dt2 * ji[1] / dAtom->getIyy();
345 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
346
347 // rotate about the x-axis
348 angle = dt2 * ji[0] / dAtom->getIxx();
349 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
350
351 dAtom->setJx( ji[0] );
352 dAtom->setJy( ji[1] );
353 dAtom->setJz( ji[2] );
354 }
355
356 }
357 }
358
359
360 void Integrator::moveB( void ){
361 int i,j,k;
362 int atomIndex;
363 DirectionalAtom* dAtom;
364 double Tb[3];
365 double ji[3];
366
367 for( i=0; i<nAtoms; i++ ){
368 atomIndex = i * 3;
369
370 // velocity half step
371 for( j=atomIndex; j<(atomIndex+3); j++ )
372 vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
373
374 if( atoms[i]->isDirectional() ){
375
376 dAtom = (DirectionalAtom *)atoms[i];
377
378 // get and convert the torque to body frame
379
380 Tb[0] = dAtom->getTx();
381 Tb[1] = dAtom->getTy();
382 Tb[2] = dAtom->getTz();
383
384 dAtom->lab2Body( Tb );
385
386 // get the angular momentum, and complete the angular momentum
387 // half step
388
389 ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
390 ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
391 ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
392
393 dAtom->setJx( ji[0] );
394 dAtom->setJy( ji[1] );
395 dAtom->setJz( ji[2] );
396 }
397 }
398
399 }
400
401 void Integrator::preMove( void ){
402 int i;
403
404 if( nConstrained ){
405
406 for(i=0; i<(nAtoms*3); i++) oldPos[i] = pos[i];
407 }
408 }
409
410 void Integrator::constrainA(){
411
412 int i,j,k;
413 int done;
414 double pab[3];
415 double rab[3];
416 int a, b, ax, ay, az, bx, by, bz;
417 double rma, rmb;
418 double dx, dy, dz;
419 double rpab;
420 double rabsq, pabsq, rpabsq;
421 double diffsq;
422 double gab;
423 int iteration;
424
425
426
427 for( i=0; i<nAtoms; i++){
428
429 moving[i] = 0;
430 moved[i] = 1;
431 }
432
433 iteration = 0;
434 done = 0;
435 while( !done && (iteration < maxIteration )){
436
437 done = 1;
438 for(i=0; i<nConstrained; i++){
439
440 a = constrainedA[i];
441 b = constrainedB[i];
442
443 ax = (a*3) + 0;
444 ay = (a*3) + 1;
445 az = (a*3) + 2;
446
447 bx = (b*3) + 0;
448 by = (b*3) + 1;
449 bz = (b*3) + 2;
450
451 if( moved[a] || moved[b] ){
452
453 pab[0] = pos[ax] - pos[bx];
454 pab[1] = pos[ay] - pos[by];
455 pab[2] = pos[az] - pos[bz];
456
457 //periodic boundary condition
458
459 info->wrapVector( pab );
460
461 pabsq = pab[0] * pab[0] + pab[1] * pab[1] + pab[2] * pab[2];
462
463 rabsq = constrainedDsqr[i];
464 diffsq = rabsq - pabsq;
465
466 // the original rattle code from alan tidesley
467 if (fabs(diffsq) > (tol*rabsq*2)) {
468 rab[0] = oldPos[ax] - oldPos[bx];
469 rab[1] = oldPos[ay] - oldPos[by];
470 rab[2] = oldPos[az] - oldPos[bz];
471
472 info->wrapVector( rab );
473
474 rpab = rab[0] * pab[0] + rab[1] * pab[1] + rab[2] * pab[2];
475
476 rpabsq = rpab * rpab;
477
478
479 if (rpabsq < (rabsq * -diffsq)){
480
481 #ifdef IS_MPI
482 a = atoms[a]->getGlobalIndex();
483 b = atoms[b]->getGlobalIndex();
484 #endif //is_mpi
485 sprintf( painCave.errMsg,
486 "Constraint failure in constrainA at atom %d and %d.\n",
487 a, b );
488 painCave.isFatal = 1;
489 simError();
490 }
491
492 rma = 1.0 / atoms[a]->getMass();
493 rmb = 1.0 / atoms[b]->getMass();
494
495 gab = diffsq / ( 2.0 * ( rma + rmb ) * rpab );
496
497 dx = rab[0] * gab;
498 dy = rab[1] * gab;
499 dz = rab[2] * gab;
500
501 pos[ax] += rma * dx;
502 pos[ay] += rma * dy;
503 pos[az] += rma * dz;
504
505 pos[bx] -= rmb * dx;
506 pos[by] -= rmb * dy;
507 pos[bz] -= rmb * dz;
508
509 dx = dx / dt;
510 dy = dy / dt;
511 dz = dz / dt;
512
513 vel[ax] += rma * dx;
514 vel[ay] += rma * dy;
515 vel[az] += rma * dz;
516
517 vel[bx] -= rmb * dx;
518 vel[by] -= rmb * dy;
519 vel[bz] -= rmb * dz;
520
521 moving[a] = 1;
522 moving[b] = 1;
523 done = 0;
524 }
525 }
526 }
527
528 for(i=0; i<nAtoms; i++){
529
530 moved[i] = moving[i];
531 moving[i] = 0;
532 }
533
534 iteration++;
535 }
536
537 if( !done ){
538
539 sprintf( painCave.errMsg,
540 "Constraint failure in constrainA, too many iterations: %d\n",
541 iteration );
542 painCave.isFatal = 1;
543 simError();
544 }
545
546 }
547
548 void Integrator::constrainB( void ){
549
550 int i,j,k;
551 int done;
552 double vxab, vyab, vzab;
553 double rab[3];
554 int a, b, ax, ay, az, bx, by, bz;
555 double rma, rmb;
556 double dx, dy, dz;
557 double rabsq, pabsq, rvab;
558 double diffsq;
559 double gab;
560 int iteration;
561
562 for(i=0; i<nAtoms; i++){
563 moving[i] = 0;
564 moved[i] = 1;
565 }
566
567 done = 0;
568 iteration = 0;
569 while( !done && (iteration < maxIteration ) ){
570
571 done = 1;
572
573 for(i=0; i<nConstrained; i++){
574
575 a = constrainedA[i];
576 b = constrainedB[i];
577
578 ax = (a*3) + 0;
579 ay = (a*3) + 1;
580 az = (a*3) + 2;
581
582 bx = (b*3) + 0;
583 by = (b*3) + 1;
584 bz = (b*3) + 2;
585
586 if( moved[a] || moved[b] ){
587
588 vxab = vel[ax] - vel[bx];
589 vyab = vel[ay] - vel[by];
590 vzab = vel[az] - vel[bz];
591
592 rab[0] = pos[ax] - pos[bx];
593 rab[1] = pos[ay] - pos[by];
594 rab[2] = pos[az] - pos[bz];
595
596 info->wrapVector( rab );
597
598 rma = 1.0 / atoms[a]->getMass();
599 rmb = 1.0 / atoms[b]->getMass();
600
601 rvab = rab[0] * vxab + rab[1] * vyab + rab[2] * vzab;
602
603 gab = -rvab / ( ( rma + rmb ) * constrainedDsqr[i] );
604
605 if (fabs(gab) > tol) {
606
607 dx = rab[0] * gab;
608 dy = rab[1] * gab;
609 dz = rab[2] * gab;
610
611 vel[ax] += rma * dx;
612 vel[ay] += rma * dy;
613 vel[az] += rma * dz;
614
615 vel[bx] -= rmb * dx;
616 vel[by] -= rmb * dy;
617 vel[bz] -= rmb * dz;
618
619 moving[a] = 1;
620 moving[b] = 1;
621 done = 0;
622 }
623 }
624 }
625
626 for(i=0; i<nAtoms; i++){
627 moved[i] = moving[i];
628 moving[i] = 0;
629 }
630
631 iteration++;
632 }
633
634 if( !done ){
635
636
637 sprintf( painCave.errMsg,
638 "Constraint failure in constrainB, too many iterations: %d\n",
639 iteration );
640 painCave.isFatal = 1;
641 simError();
642 }
643
644 }
645
646
647
648
649
650
651
652 void Integrator::rotate( int axes1, int axes2, double angle, double ji[3],
653 double A[9] ){
654
655 int i,j,k;
656 double sinAngle;
657 double cosAngle;
658 double angleSqr;
659 double angleSqrOver4;
660 double top, bottom;
661 double rot[3][3];
662 double tempA[3][3];
663 double tempJ[3];
664
665 // initialize the tempA
666
667 for(i=0; i<3; i++){
668 for(j=0; j<3; j++){
669 tempA[j][i] = A[3*i + j];
670 }
671 }
672
673 // initialize the tempJ
674
675 for( i=0; i<3; i++) tempJ[i] = ji[i];
676
677 // initalize rot as a unit matrix
678
679 rot[0][0] = 1.0;
680 rot[0][1] = 0.0;
681 rot[0][2] = 0.0;
682
683 rot[1][0] = 0.0;
684 rot[1][1] = 1.0;
685 rot[1][2] = 0.0;
686
687 rot[2][0] = 0.0;
688 rot[2][1] = 0.0;
689 rot[2][2] = 1.0;
690
691 // use a small angle aproximation for sin and cosine
692
693 angleSqr = angle * angle;
694 angleSqrOver4 = angleSqr / 4.0;
695 top = 1.0 - angleSqrOver4;
696 bottom = 1.0 + angleSqrOver4;
697
698 cosAngle = top / bottom;
699 sinAngle = angle / bottom;
700
701 rot[axes1][axes1] = cosAngle;
702 rot[axes2][axes2] = cosAngle;
703
704 rot[axes1][axes2] = sinAngle;
705 rot[axes2][axes1] = -sinAngle;
706
707 // rotate the momentum acoording to: ji[] = rot[][] * ji[]
708
709 for(i=0; i<3; i++){
710 ji[i] = 0.0;
711 for(k=0; k<3; k++){
712 ji[i] += rot[i][k] * tempJ[k];
713 }
714 }
715
716 // rotate the Rotation matrix acording to:
717 // A[][] = A[][] * transpose(rot[][])
718
719
720 // NOte for as yet unknown reason, we are performing the
721 // calculation as:
722 // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
723
724 for(i=0; i<3; i++){
725 for(j=0; j<3; j++){
726 A[3*j + i] = 0.0;
727 for(k=0; k<3; k++){
728 A[3*j + i] += tempA[i][k] * rot[j][k];
729 }
730 }
731 }
732 }