ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Symplectic.cpp
Revision: 466
Committed: Mon Apr 7 14:30:36 2003 UTC (21 years, 3 months ago) by gezelter
File size: 15863 byte(s)
Log Message:
Added ExtendedSystem infrastructure for NPT and NVT calculations

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