ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 559
Committed: Thu Jun 19 22:02:44 2003 UTC (21 years ago) by mmeineke
File size: 15958 byte(s)
Log Message:
slowly converting to new integrator and forcefield names.

File Contents

# Content
1 #include <iostream>
2 #include <cstdlib>
3
4 #ifdef IS_MPI
5 #include "mpiSimulation.hpp"
6 #include <unistd.h>
7 #endif //is_mpi
8
9 #include "Integrator.hpp"
10 #include "simError.h"
11
12
13 Integrator::Integrator( SimInfo* theInfo, ForceFields* the_ff ){
14
15 info = theInfo;
16 myFF = the_ff;
17 isFirst = 1;
18
19 molecules = info->molecules;
20 nMols = info->n_mol;
21
22 // give a little love back to the SimInfo object
23
24 if( info->the_integrator != NULL ) delete info->the_integrator;
25 info->the_integrator = this;
26
27 nAtoms = info->n_atoms;
28
29 // check for constraints
30
31 constrainedA = NULL;
32 constrainedB = NULL;
33 constrainedDsqr = NULL;
34 moving = NULL;
35 moved = NULL;
36 prePos = NULL;
37
38 nConstrained = 0;
39
40 checkConstraints();
41 }
42
43 Integrator::~Integrator() {
44
45 if( nConstrained ){
46 delete[] constrainedA;
47 delete[] constrainedB;
48 delete[] constrainedDsqr;
49 delete[] moving;
50 delete[] moved;
51 delete[] prePos;
52 }
53
54 }
55
56 void Integrator::checkConstraints( void ){
57
58
59 isConstrained = 0;
60
61 Constraint *temp_con;
62 Constraint *dummy_plug;
63 temp_con = new Constraint[info->n_SRI];
64 nConstrained = 0;
65 int constrained = 0;
66
67 SRI** theArray;
68 for(int i = 0; i < nMols; i++){
69
70 theArray = (SRI**) molecules[i].getMyBonds();
71 for(int j=0; j<molecules[i].getNBonds(); j++){
72
73 constrained = theArray[j]->is_constrained();
74
75 if(constrained){
76
77 dummy_plug = theArray[j]->get_constraint();
78 temp_con[nConstrained].set_a( dummy_plug->get_a() );
79 temp_con[nConstrained].set_b( dummy_plug->get_b() );
80 temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
81
82 nConstrained++;
83 constrained = 0;
84 }
85 }
86
87 theArray = (SRI**) molecules[i].getMyBends();
88 for(int j=0; j<molecules[i].getNBends(); j++){
89
90 constrained = theArray[j]->is_constrained();
91
92 if(constrained){
93
94 dummy_plug = theArray[j]->get_constraint();
95 temp_con[nConstrained].set_a( dummy_plug->get_a() );
96 temp_con[nConstrained].set_b( dummy_plug->get_b() );
97 temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
98
99 nConstrained++;
100 constrained = 0;
101 }
102 }
103
104 theArray = (SRI**) molecules[i].getMyTorsions();
105 for(int j=0; j<molecules[i].getNTorsions(); j++){
106
107 constrained = theArray[j]->is_constrained();
108
109 if(constrained){
110
111 dummy_plug = theArray[j]->get_constraint();
112 temp_con[nConstrained].set_a( dummy_plug->get_a() );
113 temp_con[nConstrained].set_b( dummy_plug->get_b() );
114 temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
115
116 nConstrained++;
117 constrained = 0;
118 }
119 }
120 }
121
122 if(nConstrained > 0){
123
124 isConstrained = 1;
125
126 if(constrainedA != NULL ) delete[] constrainedA;
127 if(constrainedB != NULL ) delete[] constrainedB;
128 if(constrainedDsqr != NULL ) delete[] constrainedDsqr;
129
130 constrainedA = new int[nConstrained];
131 constrainedB = new int[nConstrained];
132 constrainedDsqr = new double[nConstrained];
133
134 for( int i = 0; i < nConstrained; i++){
135
136 constrainedA[i] = temp_con[i].get_a();
137 constrainedB[i] = temp_con[i].get_b();
138 constrainedDsqr[i] = temp_con[i].get_dsqr();
139 }
140
141
142 // save oldAtoms to check for lode balanceing later on.
143
144 oldAtoms = nAtoms;
145
146 moving = new int[nAtoms];
147 moved = new int[nAtoms];
148
149 prePos = new double[nAtoms*3];
150 }
151
152 delete[] temp_con;
153 }
154
155
156 void Integrator::integrate( void ){
157
158 int i, j; // loop counters
159 double kE = 0.0; // the kinetic energy
160 double rot_kE;
161 double trans_kE;
162 int tl; // the time loop conter
163 double dt2; // half the dt
164
165 double vx, vy, vz; // the velocities
166 double vx2, vy2, vz2; // the square of the velocities
167 double rx, ry, rz; // the postitions
168
169 double ji[3]; // the body frame angular momentum
170 double jx2, jy2, jz2; // the square of the angular momentums
171 double Tb[3]; // torque in the body frame
172 double angle; // the angle through which to rotate the rotation matrix
173 double A[3][3]; // the rotation matrix
174 double press[9];
175
176 double dt = info->dt;
177 double runTime = info->run_time;
178 double sampleTime = info->sampleTime;
179 double statusTime = info->statusTime;
180 double thermalTime = info->thermalTime;
181
182 double currSample;
183 double currThermal;
184 double currStatus;
185 double currTime;
186
187 int calcPot, calcStress;
188 int isError;
189
190 tStats = new Thermo( info );
191 e_out = new StatWriter( info );
192 dump_out = new DumpWriter( info );
193
194 Atom** atoms = info->atoms;
195 DirectionalAtom* dAtom;
196 dt2 = 0.5 * dt;
197
198 // initialize the forces before the first step
199
200 myFF->doForces(1,1);
201
202 if( info->setTemp ){
203
204 tStats->velocitize();
205 }
206
207 dump_out->writeDump( 0.0 );
208 e_out->writeStat( 0.0 );
209
210 calcPot = 0;
211 calcStress = 0;
212 currSample = sampleTime;
213 currThermal = thermalTime;
214 currStatus = statusTime;
215 currTime = 0.0;;
216
217
218 readyCheck();
219
220 #ifdef IS_MPI
221 strcpy( checkPointMsg,
222 "The integrator is ready to go." );
223 MPIcheckPoint();
224 #endif // is_mpi
225
226 while( currTime < runTime ){
227
228 if( (currTime+dt) >= currStatus ){
229 calcPot = 1;
230 calcStress = 1;
231 }
232
233 integrateStep( calcPot, calcStress );
234
235 currTime += dt;
236
237 if( info->setTemp ){
238 if( currTime >= currThermal ){
239 tStats->velocitize();
240 currThermal += thermalTime;
241 }
242 }
243
244 if( currTime >= currSample ){
245 dump_out->writeDump( currTime );
246 currSample += sampleTime;
247 }
248
249 if( currTime >= currStatus ){
250 e_out->writeStat( time * dt );
251 calcPot = 0;
252 calcStress = 0;
253 currStatus += statusTime;
254 }
255
256 #ifdef IS_MPI
257 strcpy( checkPointMsg,
258 "successfully took a time step." );
259 MPIcheckPoint();
260 #endif // is_mpi
261
262 }
263
264 dump_out->writeFinal();
265
266 delete dump_out;
267 delete e_out;
268 }
269
270 void Integrator::integrateStep( int calcPot, int calcStress ){
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
298 for( i=0; i<nAtoms; i++ ){
299 atomIndex = i * 3;
300 aMatIndex = i * 9;
301
302 // velocity half step
303 for( j=atomIndex; j<(atomIndex+3); j++ )
304 vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
305
306 // position whole step
307 for( j=atomIndex; j<(atomIndex+3); j++ )
308 pos[j] += dt * vel[j];
309
310
311 if( atoms[i]->isDirectional() ){
312
313 dAtom = (DirectionalAtom *)atoms[i];
314
315 // get and convert the torque to body frame
316
317 Tb[0] = dAtom->getTx();
318 Tb[1] = dAtom->getTy();
319 Tb[2] = dAtom->getTz();
320
321 dAtom->lab2Body( Tb );
322
323 // get the angular momentum, and propagate a half step
324
325 ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
326 ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
327 ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
328
329 // use the angular velocities to propagate the rotation matrix a
330 // full time step
331
332 // rotate about the x-axis
333 angle = dt2 * ji[0] / dAtom->getIxx();
334 this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
335
336 // rotate about the y-axis
337 angle = dt2 * ji[1] / dAtom->getIyy();
338 this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
339
340 // rotate about the z-axis
341 angle = dt * ji[2] / dAtom->getIzz();
342 this->rotate( 0, 1, angle, ji, &aMat[aMatIndex] );
343
344 // rotate about the y-axis
345 angle = dt2 * ji[1] / dAtom->getIyy();
346 this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
347
348 // rotate about the x-axis
349 angle = dt2 * ji[0] / dAtom->getIxx();
350 this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
351
352 dAtom->setJx( ji[0] );
353 dAtom->setJy( ji[1] );
354 dAtom->setJz( ji[2] );
355 }
356
357 }
358 }
359
360
361 void Integrator::moveB( void ){
362 int i,j,k;
363 int atomIndex;
364 DirectionalAtom* dAtom;
365 double Tb[3];
366 double ji[3];
367
368 for( i=0; i<nAtoms; i++ ){
369 atomIndex = i * 3;
370
371 // velocity half step
372 for( j=atomIndex; j<(atomIndex+3); j++ )
373 vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
374
375 if( atoms[i]->isDirectional() ){
376
377 dAtom = (DirectionalAtom *)atoms[i];
378
379 // get and convert the torque to body frame
380
381 Tb[0] = dAtom->getTx();
382 Tb[1] = dAtom->getTy();
383 Tb[2] = dAtom->getTz();
384
385 dAtom->lab2Body( Tb );
386
387 // get the angular momentum, and complete the angular momentum
388 // half step
389
390 ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
391 ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
392 ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
393
394 jx2 = ji[0] * ji[0];
395 jy2 = ji[1] * ji[1];
396 jz2 = ji[2] * ji[2];
397
398 dAtom->setJx( ji[0] );
399 dAtom->setJy( ji[1] );
400 dAtom->setJz( ji[2] );
401 }
402 }
403
404 }
405
406 void Integrator::preMove( void ){
407 int i;
408
409 if( nConstrained ){
410 if( oldAtoms != nAtoms ){
411
412 // save oldAtoms to check for lode balanceing later on.
413
414 oldAtoms = nAtoms;
415
416 delete[] moving;
417 delete[] moved;
418 delete[] oldPos;
419
420 moving = new int[nAtoms];
421 moved = new int[nAtoms];
422
423 oldPos = new double[nAtoms*3];
424 }
425
426 for(i=0; i<(nAtoms*3); i++) oldPos[i] = pos[i];
427 }
428 }
429
430 void Integrator::constrainA(){
431
432 int i,j,k;
433 int done;
434 double pxab, pyab, pzab;
435 double rxab, ryab, rzab;
436 int a, b;
437 double rma, rmb;
438 double dx, dy, dz;
439 double rabsq, pabsq, rpabsq;
440 double diffsq;
441 double gab;
442 int iteration;
443
444
445
446 for( i=0; i<nAtoms; i++){
447
448 moving[i] = 0;
449 moved[i] = 1;
450 }
451
452
453 iteration = 0;
454 done = 0;
455 while( !done && (iteration < maxIteration )){
456
457 done = 1;
458 for(i=0; i<nConstrained; i++){
459
460 a = constrainedA[i];
461 b = constrainedB[i];
462
463 if( moved[a] || moved[b] ){
464
465 pxab = pos[3*a+0] - pos[3*b+0];
466 pyab = pos[3*a+1] - pos[3*b+1];
467 pzab = pos[3*a+2] - pos[3*b+2];
468
469 //periodic boundary condition
470 pxab = pxab - info->box_x * copysign(1, pxab)
471 * int(pxab / info->box_x + 0.5);
472 pyab = pyab - info->box_y * copysign(1, pyab)
473 * int(pyab / info->box_y + 0.5);
474 pzab = pzab - info->box_z * copysign(1, pzab)
475 * int(pzab / info->box_z + 0.5);
476
477 pabsq = pxab * pxab + pyab * pyab + pzab * pzab;
478 rabsq = constraintedDsqr[i];
479 diffsq = pabsq - rabsq;
480
481 // the original rattle code from alan tidesley
482 if (fabs(diffsq) > tol*rabsq*2) {
483 rxab = oldPos[3*a+0] - oldPos[3*b+0];
484 ryab = oldPos[3*a+1] - oldPos[3*b+1];
485 rzab = oldPos[3*a+2] - oldPos[3*b+2];
486
487 rxab = rxab - info->box_x * copysign(1, rxab)
488 * int(rxab / info->box_x + 0.5);
489 ryab = ryab - info->box_y * copysign(1, ryab)
490 * int(ryab / info->box_y + 0.5);
491 rzab = rzab - info->box_z * copysign(1, rzab)
492 * int(rzab / info->box_z + 0.5);
493
494 rpab = rxab * pxab + ryab * pyab + rzab * pzab;
495 rpabsq = rpab * rpab;
496
497
498 if (rpabsq < (rabsq * -diffsq)){
499 #ifdef IS_MPI
500 a = atoms[a]->getGlobalIndex();
501 b = atoms[b]->getGlobalIndex();
502 #endif //is_mpi
503 sprintf( painCave.errMsg,
504 "Constraint failure in constrainA at atom %d and %d\n.",
505 a, b );
506 painCave.isFatal = 1;
507 simError();
508 }
509
510 rma = 1.0 / atoms[a]->getMass();
511 rmb = 1.0 / atoms[b]->getMass();
512
513 gab = diffsq / ( 2.0 * ( rma + rmb ) * rpab );
514 dx = rxab * gab;
515 dy = ryab * gab;
516 dz = rzab * gab;
517
518 pos[3*a+0] += rma * dx;
519 pos[3*a+1] += rma * dy;
520 pos[3*a+2] += rma * dz;
521
522 pos[3*b+0] -= rmb * dx;
523 pos[3*b+1] -= rmb * dy;
524 pos[3*b+2] -= rmb * dz;
525
526 dx = dx / dt;
527 dy = dy / dt;
528 dz = dz / dt;
529
530 vel[3*a+0] += rma * dx;
531 vel[3*a+1] += rma * dy;
532 vel[3*a+2] += rma * dz;
533
534 vel[3*b+0] -= rmb * dx;
535 vel[3*b+1] -= rmb * dy;
536 vel[3*b+2] -= rmb * dz;
537
538 moving[a] = 1;
539 moving[b] = 1;
540 done = 0;
541 }
542 }
543 }
544
545 for(i=0; i<nAtoms; i++){
546
547 moved[i] = moving[i];
548 moving[i] = 0;
549 }
550
551 iteration++;
552 }
553
554 if( !done ){
555
556 sprintf( painCae.errMsg,
557 "Constraint failure in constrainA, too many iterations: %d\n",
558 iterations );
559 painCave.isFatal = 1;
560 simError();
561 }
562
563 }
564
565 void Integrator::constrainB( void ){
566
567 int i,j,k;
568 int done;
569 double vxab, vyab, vzab;
570 double rxab, ryab, rzab;
571 int a, b;
572 double rma, rmb;
573 double dx, dy, dz;
574 double rabsq, pabsq, rvab;
575 double diffsq;
576 double gab;
577 int iteration;
578
579 for(i=0; i<nAtom; i++){
580 moving[i] = 0;
581 moved[i] = 1;
582 }
583
584 done = 0;
585 while( !done && (iteration < maxIteration ) ){
586
587 for(i=0; i<nConstrained; i++){
588
589 a = constrainedA[i];
590 b = constrainedB[i];
591
592 if( moved[a] || moved[b] ){
593
594 vxab = vel[3*a+0] - vel[3*b+0];
595 vyab = vel[3*a+1] - vel[3*b+1];
596 vzab = vel[3*a+2] - vel[3*b+2];
597
598 rxab = pos[3*a+0] - pos[3*b+0];q
599 ryab = pos[3*a+1] - pos[3*b+1];
600 rzab = pos[3*a+2] - pos[3*b+2];
601
602 rxab = rxab - info->box_x * copysign(1, rxab)
603 * int(rxab / info->box_x + 0.5);
604 ryab = ryab - info->box_y * copysign(1, ryab)
605 * int(ryab / info->box_y + 0.5);
606 rzab = rzab - info->box_z * copysign(1, rzab)
607 * int(rzab / info->box_z + 0.5);
608
609 rma = 1.0 / atoms[a]->getMass();
610 rmb = 1.0 / atoms[b]->getMass();
611
612 rvab = rxab * vxab + ryab * vyab + rzab * vzab;
613
614 gab = -rvab / ( ( rma + rmb ) * constraintsDsqr[i] );
615
616 if (fabs(gab) > tol) {
617
618 dx = rxab * gab;
619 dy = ryab * gab;
620 dz = rzab * gab;
621
622 vel[3*a+0] += rma * dx;
623 vel[3*a+1] += rma * dy;
624 vel[3*a+2] += rma * dz;
625
626 vel[3*b+0] -= rmb * dx;
627 vel[3*b+1] -= rmb * dy;
628 vel[3*b+2] -= rmb * dz;
629
630 moving[a] = 1;
631 moving[b] = 1;
632 done = 0;
633 }
634 }
635 }
636
637 for(i=0; i<nAtoms; i++){
638 moved[i] = moving[i];
639 moving[i] = 0;
640 }
641
642 iteration++;
643 }
644
645 if( !done ){
646
647
648 sprintf( painCae.errMsg,
649 "Constraint failure in constrainB, too many iterations: %d\n",
650 iterations );
651 painCave.isFatal = 1;
652 simError();
653 }
654
655 }
656
657
658
659
660
661
662
663 void Integrator::rotate( int axes1, int axes2, double angle, double ji[3],
664 double A[3][3] ){
665
666 int i,j,k;
667 double sinAngle;
668 double cosAngle;
669 double angleSqr;
670 double angleSqrOver4;
671 double top, bottom;
672 double rot[3][3];
673 double tempA[3][3];
674 double tempJ[3];
675
676 // initialize the tempA
677
678 for(i=0; i<3; i++){
679 for(j=0; j<3; j++){
680 tempA[j][i] = A[i][j];
681 }
682 }
683
684 // initialize the tempJ
685
686 for( i=0; i<3; i++) tempJ[i] = ji[i];
687
688 // initalize rot as a unit matrix
689
690 rot[0][0] = 1.0;
691 rot[0][1] = 0.0;
692 rot[0][2] = 0.0;
693
694 rot[1][0] = 0.0;
695 rot[1][1] = 1.0;
696 rot[1][2] = 0.0;
697
698 rot[2][0] = 0.0;
699 rot[2][1] = 0.0;
700 rot[2][2] = 1.0;
701
702 // use a small angle aproximation for sin and cosine
703
704 angleSqr = angle * angle;
705 angleSqrOver4 = angleSqr / 4.0;
706 top = 1.0 - angleSqrOver4;
707 bottom = 1.0 + angleSqrOver4;
708
709 cosAngle = top / bottom;
710 sinAngle = angle / bottom;
711
712 rot[axes1][axes1] = cosAngle;
713 rot[axes2][axes2] = cosAngle;
714
715 rot[axes1][axes2] = sinAngle;
716 rot[axes2][axes1] = -sinAngle;
717
718 // rotate the momentum acoording to: ji[] = rot[][] * ji[]
719
720 for(i=0; i<3; i++){
721 ji[i] = 0.0;
722 for(k=0; k<3; k++){
723 ji[i] += rot[i][k] * tempJ[k];
724 }
725 }
726
727 // rotate the Rotation matrix acording to:
728 // A[][] = A[][] * transpose(rot[][])
729
730
731 // NOte for as yet unknown reason, we are setting the performing the
732 // calculation as:
733 // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
734
735 for(i=0; i<3; i++){
736 for(j=0; j<3; j++){
737 A[j][i] = 0.0;
738 for(k=0; k<3; k++){
739 A[j][i] += tempA[i][k] * rot[j][k];
740 }
741 }
742 }
743 }