ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 594
Committed: Fri Jul 11 22:34:48 2003 UTC (21 years ago) by mmeineke
File size: 15654 byte(s)
Log Message:
working on som integrator bugs

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