ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Symplectic.cpp
Revision: 378
Committed: Fri Mar 21 17:42:12 2003 UTC (21 years, 3 months ago) by mmeineke
File size: 14764 byte(s)
Log Message:
This commit was generated by cvs2svn to compensate for changes in r377,
which included commits to RCS files with non-trunk default branches.

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