ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Symplectic.cpp
Revision: 469
Committed: Mon Apr 7 20:06:31 2003 UTC (21 years, 3 months ago) by mmeineke
File size: 16290 byte(s)
Log Message:
bug fixes

File Contents

# User Rev Content
1 mmeineke 377 #include <iostream>
2     #include <cstdlib>
3    
4     #include "Integrator.hpp"
5     #include "Thermo.hpp"
6     #include "ReadWrite.hpp"
7     #include "ForceFields.hpp"
8 gezelter 466 #include "ExtendedSystem.hpp"
9 mmeineke 377 #include "simError.h"
10    
11     extern "C"{
12    
13     void v_constrain_a_( double &dt, int &n_atoms, double* mass,
14     double* Rx, double* Ry, double* Rz,
15     double* Vx, double* Vy, double* Vz,
16     double* Fx, double* Fy, double* Fz,
17     int &n_constrained, double *constr_sqr,
18     int* constr_i, int* constr_j,
19     double &box_x, double &box_y, double &box_z );
20    
21     void v_constrain_b_( double &dt, int &n_atoms, double* mass,
22     double* Rx, double* Ry, double* Rz,
23     double* Vx, double* Vy, double* Vz,
24     double* Fx, double* Fy, double* Fz,
25     double &Kinetic,
26     int &n_constrained, double *constr_sqr,
27     int* constr_i, int* constr_j,
28     double &box_x, double &box_y, double &box_z );
29     }
30    
31    
32    
33    
34 gezelter 466 Symplectic::Symplectic( SimInfo* the_entry_plug, ForceFields* the_ff,
35     ExtendedSystem* the_es ){
36 mmeineke 377 entry_plug = the_entry_plug;
37     myFF = the_ff;
38 gezelter 466 myES = the_es;
39 mmeineke 377 isFirst = 1;
40    
41 mmeineke 469 std::cerr<< "calling symplectic constructor\n";
42    
43 mmeineke 423 molecules = entry_plug->molecules;
44     nMols = entry_plug->n_mol;
45 mmeineke 377
46     // give a little love back to the SimInfo object
47    
48     if( entry_plug->the_integrator != NULL ) delete entry_plug->the_integrator;
49     entry_plug->the_integrator = this;
50    
51     // grab the masses
52    
53     mass = new double[entry_plug->n_atoms];
54     for(int i = 0; i < entry_plug->n_atoms; i++){
55     mass[i] = entry_plug->atoms[i]->getMass();
56 gezelter 466 }
57 mmeineke 377
58     // check for constraints
59    
60     is_constrained = 0;
61    
62     Constraint *temp_con;
63     Constraint *dummy_plug;
64 mmeineke 423 temp_con = new Constraint[entry_plug->n_SRI];
65 mmeineke 377 n_constrained = 0;
66     int constrained = 0;
67    
68 mmeineke 423 SRI** theArray;
69     for(int i = 0; i < nMols; i++){
70 mmeineke 377
71 mmeineke 428 theArray = (SRI**) molecules[i].getMyBonds();
72     for(int j=0; j<molecules[i].getNBonds(); j++){
73 mmeineke 377
74 mmeineke 423 constrained = theArray[j]->is_constrained();
75    
76     if(constrained){
77    
78     dummy_plug = theArray[j]->get_constraint();
79 mmeineke 428 temp_con[n_constrained].set_a( dummy_plug->get_a() );
80     temp_con[n_constrained].set_b( dummy_plug->get_b() );
81     temp_con[n_constrained].set_dsqr( dummy_plug->get_dsqr() );
82 mmeineke 423
83 mmeineke 428 n_constrained++;
84 mmeineke 423 constrained = 0;
85     }
86     }
87 mmeineke 377
88 mmeineke 428 theArray = (SRI**) molecules[i].getMyBends();
89     for(int j=0; j<molecules[i].getNBends(); j++){
90 mmeineke 423
91     constrained = theArray[j]->is_constrained();
92    
93     if(constrained){
94    
95     dummy_plug = theArray[j]->get_constraint();
96 mmeineke 428 temp_con[n_constrained].set_a( dummy_plug->get_a() );
97     temp_con[n_constrained].set_b( dummy_plug->get_b() );
98     temp_con[n_constrained].set_dsqr( dummy_plug->get_dsqr() );
99 mmeineke 423
100 mmeineke 428 n_constrained++;
101 mmeineke 423 constrained = 0;
102     }
103 mmeineke 377 }
104 mmeineke 423
105 mmeineke 428 theArray = (SRI**) molecules[i].getMyTorsions();
106     for(int j=0; j<molecules[i].getNTorsions(); j++){
107 mmeineke 423
108     constrained = theArray[j]->is_constrained();
109    
110     if(constrained){
111    
112     dummy_plug = theArray[j]->get_constraint();
113 mmeineke 428 temp_con[n_constrained].set_a( dummy_plug->get_a() );
114     temp_con[n_constrained].set_b( dummy_plug->get_b() );
115     temp_con[n_constrained].set_dsqr( dummy_plug->get_dsqr() );
116 mmeineke 423
117 mmeineke 428 n_constrained++;
118 mmeineke 423 constrained = 0;
119     }
120     }
121 mmeineke 377 }
122    
123     if(n_constrained > 0){
124    
125     is_constrained = 1;
126     constrained_i = new int[n_constrained];
127     constrained_j = new int[n_constrained];
128     constrained_dsqr = new double[n_constrained];
129    
130     for( int i = 0; i < n_constrained; i++){
131    
132     /* add 1 to the index for the fortran arrays. */
133    
134     constrained_i[i] = temp_con[i].get_a() + 1;
135     constrained_j[i] = temp_con[i].get_b() + 1;
136     constrained_dsqr[i] = temp_con[i].get_dsqr();
137     }
138     }
139    
140     delete[] temp_con;
141     }
142    
143     Symplectic::~Symplectic() {
144    
145     if( n_constrained ){
146     delete[] constrained_i;
147     delete[] constrained_j;
148     delete[] constrained_dsqr;
149     }
150    
151     }
152    
153    
154     void Symplectic::integrate( void ){
155    
156     const double e_convert = 4.184e-4; // converts kcal/mol -> amu*A^2/fs^2
157    
158     int i, j; // loop counters
159     int nAtoms = entry_plug->n_atoms; // the number of atoms
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    
176     int time;
177    
178     double dt = entry_plug->dt;
179     double runTime = entry_plug->run_time;
180     double sampleTime = entry_plug->sampleTime;
181     double statusTime = entry_plug->statusTime;
182     double thermalTime = entry_plug->thermalTime;
183    
184     int n_loops = (int)( runTime / dt );
185     int sample_n = (int)( sampleTime / dt );
186     int status_n = (int)( statusTime / dt );
187     int vel_n = (int)( thermalTime / dt );
188    
189 gezelter 468 int calcPot, calcStress;
190 mmeineke 377
191 mmeineke 469 Thermo *tStats;
192     StatWriter* e_out;
193     DumpWriter* dump_out;
194 mmeineke 377
195 mmeineke 469 std::cerr << "about to call new thermo\n";
196 mmeineke 377
197 mmeineke 469 tStats = new Thermo( entry_plug );
198     e_out = new StatWriter( entry_plug );
199    
200     std::cerr << "calling dumpWriter \n";
201     dump_out = new DumpWriter( entry_plug );
202     std::cerr << "called dumpWriter \n";
203    
204 mmeineke 377 Atom** atoms = entry_plug->atoms;
205     DirectionalAtom* dAtom;
206     dt2 = 0.5 * dt;
207    
208     // initialize the forces the before the first step
209    
210 gezelter 468 myFF->doForces(1,1);
211 mmeineke 377
212     if( entry_plug->setTemp ){
213    
214     tStats->velocitize();
215     }
216    
217     dump_out->writeDump( 0.0 );
218     e_out->writeStat( 0.0 );
219    
220     calcPot = 0;
221    
222     if( n_constrained ){
223    
224     double *Rx = new double[nAtoms];
225     double *Ry = new double[nAtoms];
226     double *Rz = new double[nAtoms];
227    
228     double *Vx = new double[nAtoms];
229     double *Vy = new double[nAtoms];
230     double *Vz = new double[nAtoms];
231    
232     double *Fx = new double[nAtoms];
233     double *Fy = new double[nAtoms];
234     double *Fz = new double[nAtoms];
235    
236    
237     for( tl=0; tl < n_loops; tl++ ){
238    
239     for( j=0; j<nAtoms; j++ ){
240    
241     Rx[j] = atoms[j]->getX();
242     Ry[j] = atoms[j]->getY();
243     Rz[j] = atoms[j]->getZ();
244    
245     Vx[j] = atoms[j]->get_vx();
246     Vy[j] = atoms[j]->get_vy();
247     Vz[j] = atoms[j]->get_vz();
248    
249     Fx[j] = atoms[j]->getFx();
250     Fy[j] = atoms[j]->getFy();
251     Fz[j] = atoms[j]->getFz();
252    
253     }
254    
255     v_constrain_a_( dt, nAtoms, mass, Rx, Ry, Rz, Vx, Vy, Vz,
256     Fx, Fy, Fz,
257     n_constrained, constrained_dsqr,
258     constrained_i, constrained_j,
259     entry_plug->box_x,
260     entry_plug->box_y,
261     entry_plug->box_z );
262    
263     for( j=0; j<nAtoms; j++ ){
264    
265     atoms[j]->setX(Rx[j]);
266     atoms[j]->setY(Ry[j]);
267     atoms[j]->setZ(Rz[j]);
268    
269     atoms[j]->set_vx(Vx[j]);
270     atoms[j]->set_vy(Vy[j]);
271     atoms[j]->set_vz(Vz[j]);
272     }
273    
274    
275     for( i=0; i<nAtoms; i++ ){
276     if( atoms[i]->isDirectional() ){
277    
278     dAtom = (DirectionalAtom *)atoms[i];
279    
280     // get and convert the torque to body frame
281    
282     Tb[0] = dAtom->getTx();
283     Tb[1] = dAtom->getTy();
284     Tb[2] = dAtom->getTz();
285    
286     dAtom->lab2Body( Tb );
287    
288     // get the angular momentum, and propagate a half step
289    
290     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
291     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
292     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
293    
294     // get the atom's rotation matrix
295    
296     A[0][0] = dAtom->getAxx();
297     A[0][1] = dAtom->getAxy();
298     A[0][2] = dAtom->getAxz();
299    
300     A[1][0] = dAtom->getAyx();
301     A[1][1] = dAtom->getAyy();
302     A[1][2] = dAtom->getAyz();
303    
304     A[2][0] = dAtom->getAzx();
305     A[2][1] = dAtom->getAzy();
306     A[2][2] = dAtom->getAzz();
307    
308    
309     // use the angular velocities to propagate the rotation matrix a
310     // full time step
311    
312    
313     angle = dt2 * ji[0] / dAtom->getIxx();
314     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
315    
316     angle = dt2 * ji[1] / dAtom->getIyy();
317     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
318    
319     angle = dt * ji[2] / dAtom->getIzz();
320     this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
321    
322     angle = dt2 * ji[1] / dAtom->getIyy();
323     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
324    
325     angle = dt2 * ji[0] / dAtom->getIxx();
326     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
327    
328    
329     dAtom->setA( A );
330     dAtom->setJx( ji[0] );
331     dAtom->setJy( ji[1] );
332     dAtom->setJz( ji[2] );
333     }
334     }
335    
336     // calculate the forces
337    
338 gezelter 468 myFF->doForces(calcPot, calcStress);
339 mmeineke 377
340     // move b
341    
342     for( j=0; j<nAtoms; j++ ){
343    
344     Rx[j] = atoms[j]->getX();
345     Ry[j] = atoms[j]->getY();
346     Rz[j] = atoms[j]->getZ();
347    
348     Vx[j] = atoms[j]->get_vx();
349     Vy[j] = atoms[j]->get_vy();
350     Vz[j] = atoms[j]->get_vz();
351    
352     Fx[j] = atoms[j]->getFx();
353     Fy[j] = atoms[j]->getFy();
354     Fz[j] = atoms[j]->getFz();
355     }
356    
357     v_constrain_b_( dt, nAtoms, mass, Rx, Ry, Rz, Vx, Vy, Vz,
358     Fx, Fy, Fz,
359     kE, n_constrained, constrained_dsqr,
360     constrained_i, constrained_j,
361     entry_plug->box_x,
362     entry_plug->box_y,
363     entry_plug->box_z );
364    
365     for( j=0; j<nAtoms; j++ ){
366    
367     atoms[j]->setX(Rx[j]);
368     atoms[j]->setY(Ry[j]);
369     atoms[j]->setZ(Rz[j]);
370    
371     atoms[j]->set_vx(Vx[j]);
372     atoms[j]->set_vy(Vy[j]);
373     atoms[j]->set_vz(Vz[j]);
374     }
375    
376     for( i=0; i< nAtoms; i++ ){
377    
378     if( atoms[i]->isDirectional() ){
379    
380     dAtom = (DirectionalAtom *)atoms[i];
381    
382     // get and convert the torque to body frame
383    
384     Tb[0] = dAtom->getTx();
385     Tb[1] = dAtom->getTy();
386     Tb[2] = dAtom->getTz();
387    
388     dAtom->lab2Body( Tb );
389    
390     // get the angular momentum, and complete the angular momentum
391     // half step
392    
393     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
394     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
395     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
396    
397     dAtom->setJx( ji[0] );
398     dAtom->setJy( ji[1] );
399     dAtom->setJz( ji[2] );
400     }
401     }
402    
403     time = tl + 1;
404    
405     if( entry_plug->setTemp ){
406     if( !(time % vel_n) ) tStats->velocitize();
407     }
408     if( !(time % sample_n) ) dump_out->writeDump( time * dt );
409 gezelter 468 if( !((time+1) % status_n) ) {
410     calcPot = 1;
411     calcStress = 1;
412     }
413     if( !(time % status_n) ){
414     e_out->writeStat( time * dt );
415     calcPot = 0;
416     calcStress = 0;
417     }
418 mmeineke 377 }
419     }
420     else{
421    
422     for( tl=0; tl<n_loops; tl++ ){
423    
424     kE = 0.0;
425     rot_kE= 0.0;
426     trans_kE = 0.0;
427    
428     for( i=0; i<nAtoms; i++ ){
429    
430     // velocity half step
431    
432     vx = atoms[i]->get_vx() +
433     ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
434     vy = atoms[i]->get_vy() +
435     ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
436     vz = atoms[i]->get_vz() +
437     ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
438    
439     // position whole step
440    
441     rx = atoms[i]->getX() + dt * vx;
442     ry = atoms[i]->getY() + dt * vy;
443     rz = atoms[i]->getZ() + dt * vz;
444    
445     atoms[i]->setX( rx );
446     atoms[i]->setY( ry );
447     atoms[i]->setZ( rz );
448    
449     atoms[i]->set_vx( vx );
450     atoms[i]->set_vy( vy );
451     atoms[i]->set_vz( vz );
452    
453     if( atoms[i]->isDirectional() ){
454    
455     dAtom = (DirectionalAtom *)atoms[i];
456    
457     // get and convert the torque to body frame
458    
459     Tb[0] = dAtom->getTx();
460     Tb[1] = dAtom->getTy();
461     Tb[2] = dAtom->getTz();
462    
463     dAtom->lab2Body( Tb );
464    
465     // get the angular momentum, and propagate a half step
466    
467     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
468     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
469     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
470    
471     // get the atom's rotation matrix
472    
473     A[0][0] = dAtom->getAxx();
474     A[0][1] = dAtom->getAxy();
475     A[0][2] = dAtom->getAxz();
476    
477     A[1][0] = dAtom->getAyx();
478     A[1][1] = dAtom->getAyy();
479     A[1][2] = dAtom->getAyz();
480    
481     A[2][0] = dAtom->getAzx();
482     A[2][1] = dAtom->getAzy();
483     A[2][2] = dAtom->getAzz();
484    
485    
486     // use the angular velocities to propagate the rotation matrix a
487     // full time step
488    
489    
490     angle = dt2 * ji[0] / dAtom->getIxx();
491     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
492    
493     angle = dt2 * ji[1] / dAtom->getIyy();
494     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
495    
496     angle = dt * ji[2] / dAtom->getIzz();
497     this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
498    
499     angle = dt2 * ji[1] / dAtom->getIyy();
500     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
501    
502     angle = dt2 * ji[0] / dAtom->getIxx();
503     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
504    
505    
506     dAtom->setA( A );
507     dAtom->setJx( ji[0] );
508     dAtom->setJy( ji[1] );
509     dAtom->setJz( ji[2] );
510     }
511     }
512    
513     // calculate the forces
514    
515 gezelter 468 myFF->doForces(calcPot,calcStress);
516 mmeineke 377
517     for( i=0; i< nAtoms; i++ ){
518    
519     // complete the velocity half step
520    
521     vx = atoms[i]->get_vx() +
522     ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
523     vy = atoms[i]->get_vy() +
524     ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
525     vz = atoms[i]->get_vz() +
526     ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
527    
528     atoms[i]->set_vx( vx );
529     atoms[i]->set_vy( vy );
530     atoms[i]->set_vz( vz );
531    
532     // vx2 = vx * vx;
533     // vy2 = vy * vy;
534     // vz2 = vz * vz;
535    
536     if( atoms[i]->isDirectional() ){
537    
538     dAtom = (DirectionalAtom *)atoms[i];
539    
540     // get and convert the torque to body frame
541    
542     Tb[0] = dAtom->getTx();
543     Tb[1] = dAtom->getTy();
544     Tb[2] = dAtom->getTz();
545    
546     dAtom->lab2Body( Tb );
547    
548     // get the angular momentum, and complete the angular momentum
549     // half step
550    
551     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
552     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
553     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
554    
555     jx2 = ji[0] * ji[0];
556     jy2 = ji[1] * ji[1];
557     jz2 = ji[2] * ji[2];
558    
559     rot_kE += (jx2 / dAtom->getIxx()) + (jy2 / dAtom->getIyy())
560     + (jz2 / dAtom->getIzz());
561    
562     dAtom->setJx( ji[0] );
563     dAtom->setJy( ji[1] );
564     dAtom->setJz( ji[2] );
565     }
566     }
567    
568     time = tl + 1;
569    
570     if( entry_plug->setTemp ){
571     if( !(time % vel_n) ) tStats->velocitize();
572     }
573     if( !(time % sample_n) ) dump_out->writeDump( time * dt );
574 gezelter 468 if( !((time+1) % status_n) ) {
575     calcPot = 1;
576     calcStress = 1;
577     }
578     if( !(time % status_n) ){
579     e_out->writeStat( time * dt );
580     calcPot = 0;
581     calcStress = 0;
582     }
583 mmeineke 377 }
584     }
585    
586     dump_out->writeFinal();
587    
588     delete dump_out;
589     delete e_out;
590     }
591    
592     void Symplectic::rotate( int axes1, int axes2, double angle, double ji[3],
593     double A[3][3] ){
594    
595     int i,j,k;
596     double sinAngle;
597     double cosAngle;
598     double angleSqr;
599     double angleSqrOver4;
600     double top, bottom;
601     double rot[3][3];
602     double tempA[3][3];
603     double tempJ[3];
604    
605     // initialize the tempA
606    
607     for(i=0; i<3; i++){
608     for(j=0; j<3; j++){
609 mmeineke 443 tempA[j][i] = A[i][j];
610 mmeineke 377 }
611     }
612    
613     // initialize the tempJ
614    
615     for( i=0; i<3; i++) tempJ[i] = ji[i];
616    
617     // initalize rot as a unit matrix
618    
619     rot[0][0] = 1.0;
620     rot[0][1] = 0.0;
621     rot[0][2] = 0.0;
622    
623     rot[1][0] = 0.0;
624     rot[1][1] = 1.0;
625     rot[1][2] = 0.0;
626    
627     rot[2][0] = 0.0;
628     rot[2][1] = 0.0;
629     rot[2][2] = 1.0;
630    
631     // use a small angle aproximation for sin and cosine
632    
633     angleSqr = angle * angle;
634     angleSqrOver4 = angleSqr / 4.0;
635     top = 1.0 - angleSqrOver4;
636     bottom = 1.0 + angleSqrOver4;
637    
638     cosAngle = top / bottom;
639     sinAngle = angle / bottom;
640    
641     rot[axes1][axes1] = cosAngle;
642     rot[axes2][axes2] = cosAngle;
643    
644     rot[axes1][axes2] = sinAngle;
645     rot[axes2][axes1] = -sinAngle;
646    
647     // rotate the momentum acoording to: ji[] = rot[][] * ji[]
648    
649     for(i=0; i<3; i++){
650     ji[i] = 0.0;
651     for(k=0; k<3; k++){
652     ji[i] += rot[i][k] * tempJ[k];
653     }
654     }
655    
656     // rotate the Rotation matrix acording to:
657     // A[][] = A[][] * transpose(rot[][])
658    
659    
660     // NOte for as yet unknown reason, we are setting the performing the
661     // calculation as:
662     // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
663    
664     for(i=0; i<3; i++){
665     for(j=0; j<3; j++){
666     A[j][i] = 0.0;
667     for(k=0; k<3; k++){
668 mmeineke 443 A[j][i] += tempA[i][k] * rot[j][k];
669 mmeineke 377 }
670     }
671     }
672     }