ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/mdtools/md_code/Symplectic.cpp
Revision: 249
Committed: Mon Jan 27 21:28:19 2003 UTC (21 years, 5 months ago) by chuckv
File size: 15067 byte(s)
Log Message:
For some unknown reason the Single processor builds. Has not been tested!

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 chuckv 249 #include "ForceFields.hpp"
8 mmeineke 184 #include "simError.h"
9 mmeineke 10
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 ){
34     entry_plug = the_entry_plug;
35     isFirst = 1;
36    
37     srInteractions = entry_plug->sr_interactions;
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 chuckv 134 // double vx2, vy2, vz2; // the square of the velocities
124 mmeineke 10 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 mmeineke 25 int time;
133 mmeineke 10
134     double dt = entry_plug->dt;
135     double runTime = entry_plug->run_time;
136     double sampleTime = entry_plug->sampleTime;
137     double statusTime = entry_plug->statusTime;
138     double thermalTime = entry_plug->thermalTime;
139    
140     int n_loops = (int)( runTime / dt );
141     int sample_n = (int)( sampleTime / dt );
142     int status_n = (int)( statusTime / dt );
143     int vel_n = (int)( thermalTime / dt );
144    
145 chuckv 249 // ForceFields *ff = entry_plug->
146 mmeineke 238
147 mmeineke 10 Thermo *tStats = new Thermo( entry_plug );
148    
149     StatWriter* e_out = new StatWriter( entry_plug );
150     DumpWriter* dump_out = new DumpWriter( entry_plug );
151    
152     Atom** atoms = entry_plug->atoms;
153     DirectionalAtom* dAtom;
154     dt2 = 0.5 * dt;
155    
156     // initialize the forces the before the first step
157    
158    
159 mmeineke 238
160 mmeineke 10 for(i = 0; i < nAtoms; i++){
161     atoms[i]->zeroForces();
162     }
163    
164     for(i = 0; i < nSRI; i++){
165    
166     srInteractions[i]->calc_forces();
167     }
168    
169     longRange->calc_forces();
170    
171     if( entry_plug->setTemp ){
172    
173     tStats->velocitize();
174     }
175    
176 mmeineke 25 dump_out->writeDump( 0.0 );
177     e_out->writeStat( 0.0 );
178    
179 mmeineke 10 if( n_constrained ){
180    
181     double *Rx = new double[nAtoms];
182     double *Ry = new double[nAtoms];
183     double *Rz = new double[nAtoms];
184    
185     double *Vx = new double[nAtoms];
186     double *Vy = new double[nAtoms];
187     double *Vz = new double[nAtoms];
188    
189     double *Fx = new double[nAtoms];
190     double *Fy = new double[nAtoms];
191     double *Fz = new double[nAtoms];
192    
193    
194     for( tl=0; tl < n_loops; tl++ ){
195    
196     for( j=0; j<nAtoms; j++ ){
197    
198     Rx[j] = atoms[j]->getX();
199     Ry[j] = atoms[j]->getY();
200     Rz[j] = atoms[j]->getZ();
201    
202     Vx[j] = atoms[j]->get_vx();
203     Vy[j] = atoms[j]->get_vy();
204     Vz[j] = atoms[j]->get_vz();
205    
206     Fx[j] = atoms[j]->getFx();
207     Fy[j] = atoms[j]->getFy();
208     Fz[j] = atoms[j]->getFz();
209    
210     }
211    
212     v_constrain_a_( dt, nAtoms, mass, Rx, Ry, Rz, Vx, Vy, Vz,
213     Fx, Fy, Fz,
214     n_constrained, constrained_dsqr,
215     constrained_i, constrained_j,
216     entry_plug->box_x,
217     entry_plug->box_y,
218     entry_plug->box_z );
219    
220     for( j=0; j<nAtoms; j++ ){
221    
222     atoms[j]->setX(Rx[j]);
223     atoms[j]->setY(Ry[j]);
224     atoms[j]->setZ(Rz[j]);
225    
226     atoms[j]->set_vx(Vx[j]);
227     atoms[j]->set_vy(Vy[j]);
228     atoms[j]->set_vz(Vz[j]);
229     }
230    
231    
232     for( i=0; i<nAtoms; i++ ){
233     if( atoms[i]->isDirectional() ){
234    
235     dAtom = (DirectionalAtom *)atoms[i];
236    
237     // get and convert the torque to body frame
238    
239     Tb[0] = dAtom->getTx();
240     Tb[1] = dAtom->getTy();
241     Tb[2] = dAtom->getTz();
242    
243     dAtom->lab2Body( Tb );
244    
245     // get the angular momentum, and propagate a half step
246    
247     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
248     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
249     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
250    
251     // get the atom's rotation matrix
252    
253     A[0][0] = dAtom->getAxx();
254     A[0][1] = dAtom->getAxy();
255     A[0][2] = dAtom->getAxz();
256    
257     A[1][0] = dAtom->getAyx();
258     A[1][1] = dAtom->getAyy();
259     A[1][2] = dAtom->getAyz();
260    
261     A[2][0] = dAtom->getAzx();
262     A[2][1] = dAtom->getAzy();
263     A[2][2] = dAtom->getAzz();
264    
265    
266     // use the angular velocities to propagate the rotation matrix a
267     // full time step
268    
269    
270     angle = dt2 * ji[0] / dAtom->getIxx();
271     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-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 = dt * ji[2] / dAtom->getIzz();
277     this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
278    
279     angle = dt2 * ji[1] / dAtom->getIyy();
280     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
281    
282     angle = dt2 * ji[0] / dAtom->getIxx();
283     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
284    
285    
286     dAtom->setA( A );
287     dAtom->setJx( ji[0] );
288     dAtom->setJy( ji[1] );
289     dAtom->setJz( ji[2] );
290     }
291     }
292    
293     // calculate the forces
294    
295     for(j = 0; j < nAtoms; j++){
296     atoms[j]->zeroForces();
297     }
298    
299     for(j = 0; j < nSRI; j++){
300     srInteractions[j]->calc_forces();
301     }
302    
303     longRange->calc_forces();
304    
305     // move b
306    
307     for( j=0; j<nAtoms; j++ ){
308    
309     Rx[j] = atoms[j]->getX();
310     Ry[j] = atoms[j]->getY();
311     Rz[j] = atoms[j]->getZ();
312    
313     Vx[j] = atoms[j]->get_vx();
314     Vy[j] = atoms[j]->get_vy();
315     Vz[j] = atoms[j]->get_vz();
316    
317     Fx[j] = atoms[j]->getFx();
318     Fy[j] = atoms[j]->getFy();
319     Fz[j] = atoms[j]->getFz();
320     }
321    
322     v_constrain_b_( dt, nAtoms, mass, Rx, Ry, Rz, Vx, Vy, Vz,
323     Fx, Fy, Fz,
324     kE, n_constrained, constrained_dsqr,
325     constrained_i, constrained_j,
326     entry_plug->box_x,
327     entry_plug->box_y,
328     entry_plug->box_z );
329    
330     for( j=0; j<nAtoms; j++ ){
331    
332     atoms[j]->setX(Rx[j]);
333     atoms[j]->setY(Ry[j]);
334     atoms[j]->setZ(Rz[j]);
335    
336     atoms[j]->set_vx(Vx[j]);
337     atoms[j]->set_vy(Vy[j]);
338     atoms[j]->set_vz(Vz[j]);
339     }
340    
341     for( i=0; i< nAtoms; i++ ){
342    
343     if( atoms[i]->isDirectional() ){
344    
345     dAtom = (DirectionalAtom *)atoms[i];
346    
347     // get and convert the torque to body frame
348    
349     Tb[0] = dAtom->getTx();
350     Tb[1] = dAtom->getTy();
351     Tb[2] = dAtom->getTz();
352    
353     dAtom->lab2Body( Tb );
354    
355     // get the angular momentum, and complete the angular momentum
356     // half step
357    
358     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
359     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
360     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
361    
362     dAtom->setJx( ji[0] );
363     dAtom->setJy( ji[1] );
364     dAtom->setJz( ji[2] );
365     }
366     }
367 mmeineke 25
368     time = tl + 1;
369    
370 mmeineke 10 if( entry_plug->setTemp ){
371 mmeineke 25 if( !(time % vel_n) ) tStats->velocitize();
372 mmeineke 10 }
373 mmeineke 25 if( !(time % sample_n) ) dump_out->writeDump( time * dt );
374     if( !(time % status_n) ) e_out->writeStat( time * dt );
375 mmeineke 10 }
376     }
377     else{
378    
379     for( tl=0; tl<n_loops; tl++ ){
380    
381     kE = 0.0;
382     rot_kE= 0.0;
383     trans_kE = 0.0;
384    
385     for( i=0; i<nAtoms; i++ ){
386    
387     // velocity half step
388    
389     vx = atoms[i]->get_vx() +
390     ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
391     vy = atoms[i]->get_vy() +
392     ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
393     vz = atoms[i]->get_vz() +
394     ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
395    
396     // position whole step
397    
398     rx = atoms[i]->getX() + dt * vx;
399     ry = atoms[i]->getY() + dt * vy;
400     rz = atoms[i]->getZ() + dt * vz;
401    
402     atoms[i]->setX( rx );
403     atoms[i]->setY( ry );
404     atoms[i]->setZ( rz );
405    
406     atoms[i]->set_vx( vx );
407     atoms[i]->set_vy( vy );
408     atoms[i]->set_vz( vz );
409    
410     if( atoms[i]->isDirectional() ){
411    
412     dAtom = (DirectionalAtom *)atoms[i];
413    
414     // get and convert the torque to body frame
415    
416     Tb[0] = dAtom->getTx();
417     Tb[1] = dAtom->getTy();
418     Tb[2] = dAtom->getTz();
419    
420     dAtom->lab2Body( Tb );
421    
422     // get the angular momentum, and propagate a half step
423    
424     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
425     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
426     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
427    
428     // get the atom's rotation matrix
429    
430     A[0][0] = dAtom->getAxx();
431     A[0][1] = dAtom->getAxy();
432     A[0][2] = dAtom->getAxz();
433    
434     A[1][0] = dAtom->getAyx();
435     A[1][1] = dAtom->getAyy();
436     A[1][2] = dAtom->getAyz();
437    
438     A[2][0] = dAtom->getAzx();
439     A[2][1] = dAtom->getAzy();
440     A[2][2] = dAtom->getAzz();
441    
442    
443     // use the angular velocities to propagate the rotation matrix a
444     // full time step
445    
446    
447     angle = dt2 * ji[0] / dAtom->getIxx();
448     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
449    
450     angle = dt2 * ji[1] / dAtom->getIyy();
451     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
452    
453     angle = dt * ji[2] / dAtom->getIzz();
454     this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
455    
456     angle = dt2 * ji[1] / dAtom->getIyy();
457     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
458    
459     angle = dt2 * ji[0] / dAtom->getIxx();
460     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
461    
462    
463     dAtom->setA( A );
464     dAtom->setJx( ji[0] );
465     dAtom->setJy( ji[1] );
466     dAtom->setJz( ji[2] );
467     }
468     }
469    
470     // calculate the forces
471    
472     for(j = 0; j < nAtoms; j++){
473     atoms[j]->zeroForces();
474     }
475    
476     for(j = 0; j < nSRI; j++){
477     srInteractions[j]->calc_forces();
478     }
479    
480     longRange->calc_forces();
481    
482     for( i=0; i< nAtoms; i++ ){
483    
484     // complete the velocity half step
485    
486     vx = atoms[i]->get_vx() +
487     ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
488     vy = atoms[i]->get_vy() +
489     ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
490     vz = atoms[i]->get_vz() +
491     ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
492    
493     atoms[i]->set_vx( vx );
494     atoms[i]->set_vy( vy );
495     atoms[i]->set_vz( vz );
496    
497 chuckv 134 // vx2 = vx * vx;
498     // vy2 = vy * vy;
499     // vz2 = vz * vz;
500 mmeineke 10
501     if( atoms[i]->isDirectional() ){
502    
503     dAtom = (DirectionalAtom *)atoms[i];
504    
505     // get and convert the torque to body frame
506    
507     Tb[0] = dAtom->getTx();
508     Tb[1] = dAtom->getTy();
509     Tb[2] = dAtom->getTz();
510    
511     dAtom->lab2Body( Tb );
512    
513     // get the angular momentum, and complete the angular momentum
514     // half step
515    
516     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
517     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
518     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
519    
520     jx2 = ji[0] * ji[0];
521     jy2 = ji[1] * ji[1];
522     jz2 = ji[2] * ji[2];
523    
524     rot_kE += (jx2 / dAtom->getIxx()) + (jy2 / dAtom->getIyy())
525     + (jz2 / dAtom->getIzz());
526    
527     dAtom->setJx( ji[0] );
528     dAtom->setJy( ji[1] );
529     dAtom->setJz( ji[2] );
530     }
531     }
532 mmeineke 25
533     time = tl + 1;
534    
535 mmeineke 10 if( entry_plug->setTemp ){
536 mmeineke 25 if( !(time % vel_n) ) tStats->velocitize();
537 mmeineke 10 }
538 mmeineke 25 if( !(time % sample_n) ) dump_out->writeDump( time * dt );
539     if( !(time % status_n) ) e_out->writeStat( time * dt );
540 mmeineke 10 }
541     }
542    
543     dump_out->writeFinal();
544    
545     delete dump_out;
546     delete e_out;
547     }
548    
549     void Symplectic::rotate( int axes1, int axes2, double angle, double ji[3],
550     double A[3][3] ){
551    
552     int i,j,k;
553     double sinAngle;
554     double cosAngle;
555     double angleSqr;
556     double angleSqrOver4;
557     double top, bottom;
558     double rot[3][3];
559     double tempA[3][3];
560     double tempJ[3];
561    
562     // initialize the tempA
563    
564     for(i=0; i<3; i++){
565     for(j=0; j<3; j++){
566     tempA[i][j] = A[i][j];
567     }
568     }
569    
570     // initialize the tempJ
571    
572     for( i=0; i<3; i++) tempJ[i] = ji[i];
573    
574     // initalize rot as a unit matrix
575    
576     rot[0][0] = 1.0;
577     rot[0][1] = 0.0;
578     rot[0][2] = 0.0;
579    
580     rot[1][0] = 0.0;
581     rot[1][1] = 1.0;
582     rot[1][2] = 0.0;
583    
584     rot[2][0] = 0.0;
585     rot[2][1] = 0.0;
586     rot[2][2] = 1.0;
587    
588     // use a small angle aproximation for sin and cosine
589    
590     angleSqr = angle * angle;
591     angleSqrOver4 = angleSqr / 4.0;
592     top = 1.0 - angleSqrOver4;
593     bottom = 1.0 + angleSqrOver4;
594    
595     cosAngle = top / bottom;
596     sinAngle = angle / bottom;
597    
598     rot[axes1][axes1] = cosAngle;
599     rot[axes2][axes2] = cosAngle;
600    
601     rot[axes1][axes2] = sinAngle;
602     rot[axes2][axes1] = -sinAngle;
603    
604     // rotate the momentum acoording to: ji[] = rot[][] * ji[]
605    
606     for(i=0; i<3; i++){
607     ji[i] = 0.0;
608     for(k=0; k<3; k++){
609     ji[i] += rot[i][k] * tempJ[k];
610     }
611     }
612    
613     // rotate the Rotation matrix acording to:
614     // A[][] = A[][] * transpose(rot[][])
615    
616    
617     // NOte for as yet unknown reason, we are setting the performing the
618     // calculation as:
619     // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
620    
621     for(i=0; i<3; i++){
622     for(j=0; j<3; j++){
623     A[j][i] = 0.0;
624     for(k=0; k<3; k++){
625     A[j][i] += tempA[k][i] * rot[j][k];
626     }
627     }
628     }
629     }