ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 558
Committed: Thu Jun 19 19:21:23 2003 UTC (21 years ago) by mmeineke
File size: 15703 byte(s)
Log Message:
finished the basics of the integrator and SimSetup.cpp

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