ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/mdtools/md_code/Symplectic.cpp
Revision: 11
Committed: Tue Jul 9 18:40:59 2002 UTC (22 years ago) by mmeineke
File size: 14867 byte(s)
Log Message:
This commit was generated by cvs2svn to compensate for changes in r10, which
included commits to RCS files with non-trunk default branches.

File Contents

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