ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 597
Committed: Mon Jul 14 21:28:54 2003 UTC (20 years, 11 months ago) by mmeineke
File size: 15329 byte(s)
Log Message:
found a bug. Unit vectors were not being updated

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