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

# User Rev Content
1 mmeineke 558 #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 mmeineke 559
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 mmeineke 558 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 mmeineke 559
256     #ifdef IS_MPI
257     strcpy( checkPointMsg,
258     "successfully took a time step." );
259     MPIcheckPoint();
260     #endif // is_mpi
261    
262 mmeineke 558 }
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     }