ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 563
Committed: Mon Jun 23 21:24:03 2003 UTC (21 years ago) by mmeineke
File size: 15623 byte(s)
Log Message:
Doing some work to debug the constraint code.

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