ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Symplectic.cpp
Revision: 468
Committed: Mon Apr 7 16:56:38 2003 UTC (21 years, 4 months ago) by gezelter
File size: 16081 byte(s)
Log Message:
Many fixes to add extended system

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 gezelter 468 int calcPot, calcStress;
188 mmeineke 377
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 gezelter 468 myFF->doForces(1,1);
201 mmeineke 377
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 gezelter 468 myFF->doForces(calcPot, calcStress);
329 mmeineke 377
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 gezelter 468 if( !((time+1) % status_n) ) {
400     calcPot = 1;
401     calcStress = 1;
402     }
403     if( !(time % status_n) ){
404     e_out->writeStat( time * dt );
405     calcPot = 0;
406     calcStress = 0;
407     }
408 mmeineke 377 }
409     }
410     else{
411    
412     for( tl=0; tl<n_loops; tl++ ){
413    
414     kE = 0.0;
415     rot_kE= 0.0;
416     trans_kE = 0.0;
417    
418     for( i=0; i<nAtoms; i++ ){
419    
420     // velocity half step
421    
422     vx = atoms[i]->get_vx() +
423     ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
424     vy = atoms[i]->get_vy() +
425     ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
426     vz = atoms[i]->get_vz() +
427     ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
428    
429     // position whole step
430    
431     rx = atoms[i]->getX() + dt * vx;
432     ry = atoms[i]->getY() + dt * vy;
433     rz = atoms[i]->getZ() + dt * vz;
434    
435     atoms[i]->setX( rx );
436     atoms[i]->setY( ry );
437     atoms[i]->setZ( rz );
438    
439     atoms[i]->set_vx( vx );
440     atoms[i]->set_vy( vy );
441     atoms[i]->set_vz( vz );
442    
443     if( atoms[i]->isDirectional() ){
444    
445     dAtom = (DirectionalAtom *)atoms[i];
446    
447     // get and convert the torque to body frame
448    
449     Tb[0] = dAtom->getTx();
450     Tb[1] = dAtom->getTy();
451     Tb[2] = dAtom->getTz();
452    
453     dAtom->lab2Body( Tb );
454    
455     // get the angular momentum, and propagate a half step
456    
457     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
458     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
459     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
460    
461     // get the atom's rotation matrix
462    
463     A[0][0] = dAtom->getAxx();
464     A[0][1] = dAtom->getAxy();
465     A[0][2] = dAtom->getAxz();
466    
467     A[1][0] = dAtom->getAyx();
468     A[1][1] = dAtom->getAyy();
469     A[1][2] = dAtom->getAyz();
470    
471     A[2][0] = dAtom->getAzx();
472     A[2][1] = dAtom->getAzy();
473     A[2][2] = dAtom->getAzz();
474    
475    
476     // use the angular velocities to propagate the rotation matrix a
477     // full time step
478    
479    
480     angle = dt2 * ji[0] / dAtom->getIxx();
481     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
482    
483     angle = dt2 * ji[1] / dAtom->getIyy();
484     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
485    
486     angle = dt * ji[2] / dAtom->getIzz();
487     this->rotate( 0, 1, angle, ji, A ); // rotate about the z-axis
488    
489     angle = dt2 * ji[1] / dAtom->getIyy();
490     this->rotate( 2, 0, angle, ji, A ); // rotate about the y-axis
491    
492     angle = dt2 * ji[0] / dAtom->getIxx();
493     this->rotate( 1, 2, angle, ji, A ); // rotate about the x-axis
494    
495    
496     dAtom->setA( A );
497     dAtom->setJx( ji[0] );
498     dAtom->setJy( ji[1] );
499     dAtom->setJz( ji[2] );
500     }
501     }
502    
503     // calculate the forces
504    
505 gezelter 468 myFF->doForces(calcPot,calcStress);
506 mmeineke 377
507     for( i=0; i< nAtoms; i++ ){
508    
509     // complete the velocity half step
510    
511     vx = atoms[i]->get_vx() +
512     ( dt2 * atoms[i]->getFx() / atoms[i]->getMass() ) * e_convert;
513     vy = atoms[i]->get_vy() +
514     ( dt2 * atoms[i]->getFy() / atoms[i]->getMass() ) * e_convert;
515     vz = atoms[i]->get_vz() +
516     ( dt2 * atoms[i]->getFz() / atoms[i]->getMass() ) * e_convert;
517    
518     atoms[i]->set_vx( vx );
519     atoms[i]->set_vy( vy );
520     atoms[i]->set_vz( vz );
521    
522     // vx2 = vx * vx;
523     // vy2 = vy * vy;
524     // vz2 = vz * vz;
525    
526     if( atoms[i]->isDirectional() ){
527    
528     dAtom = (DirectionalAtom *)atoms[i];
529    
530     // get and convert the torque to body frame
531    
532     Tb[0] = dAtom->getTx();
533     Tb[1] = dAtom->getTy();
534     Tb[2] = dAtom->getTz();
535    
536     dAtom->lab2Body( Tb );
537    
538     // get the angular momentum, and complete the angular momentum
539     // half step
540    
541     ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * e_convert;
542     ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * e_convert;
543     ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * e_convert;
544    
545     jx2 = ji[0] * ji[0];
546     jy2 = ji[1] * ji[1];
547     jz2 = ji[2] * ji[2];
548    
549     rot_kE += (jx2 / dAtom->getIxx()) + (jy2 / dAtom->getIyy())
550     + (jz2 / dAtom->getIzz());
551    
552     dAtom->setJx( ji[0] );
553     dAtom->setJy( ji[1] );
554     dAtom->setJz( ji[2] );
555     }
556     }
557    
558     time = tl + 1;
559    
560     if( entry_plug->setTemp ){
561     if( !(time % vel_n) ) tStats->velocitize();
562     }
563     if( !(time % sample_n) ) dump_out->writeDump( time * dt );
564 gezelter 468 if( !((time+1) % status_n) ) {
565     calcPot = 1;
566     calcStress = 1;
567     }
568     if( !(time % status_n) ){
569     e_out->writeStat( time * dt );
570     calcPot = 0;
571     calcStress = 0;
572     }
573 mmeineke 377 }
574     }
575    
576     dump_out->writeFinal();
577    
578     delete dump_out;
579     delete e_out;
580     }
581    
582     void Symplectic::rotate( int axes1, int axes2, double angle, double ji[3],
583     double A[3][3] ){
584    
585     int i,j,k;
586     double sinAngle;
587     double cosAngle;
588     double angleSqr;
589     double angleSqrOver4;
590     double top, bottom;
591     double rot[3][3];
592     double tempA[3][3];
593     double tempJ[3];
594    
595     // initialize the tempA
596    
597     for(i=0; i<3; i++){
598     for(j=0; j<3; j++){
599 mmeineke 443 tempA[j][i] = A[i][j];
600 mmeineke 377 }
601     }
602    
603     // initialize the tempJ
604    
605     for( i=0; i<3; i++) tempJ[i] = ji[i];
606    
607     // initalize rot as a unit matrix
608    
609     rot[0][0] = 1.0;
610     rot[0][1] = 0.0;
611     rot[0][2] = 0.0;
612    
613     rot[1][0] = 0.0;
614     rot[1][1] = 1.0;
615     rot[1][2] = 0.0;
616    
617     rot[2][0] = 0.0;
618     rot[2][1] = 0.0;
619     rot[2][2] = 1.0;
620    
621     // use a small angle aproximation for sin and cosine
622    
623     angleSqr = angle * angle;
624     angleSqrOver4 = angleSqr / 4.0;
625     top = 1.0 - angleSqrOver4;
626     bottom = 1.0 + angleSqrOver4;
627    
628     cosAngle = top / bottom;
629     sinAngle = angle / bottom;
630    
631     rot[axes1][axes1] = cosAngle;
632     rot[axes2][axes2] = cosAngle;
633    
634     rot[axes1][axes2] = sinAngle;
635     rot[axes2][axes1] = -sinAngle;
636    
637     // rotate the momentum acoording to: ji[] = rot[][] * ji[]
638    
639     for(i=0; i<3; i++){
640     ji[i] = 0.0;
641     for(k=0; k<3; k++){
642     ji[i] += rot[i][k] * tempJ[k];
643     }
644     }
645    
646     // rotate the Rotation matrix acording to:
647     // A[][] = A[][] * transpose(rot[][])
648    
649    
650     // NOte for as yet unknown reason, we are setting the performing the
651     // calculation as:
652     // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
653    
654     for(i=0; i<3; i++){
655     for(j=0; j<3; j++){
656     A[j][i] = 0.0;
657     for(k=0; k<3; k++){
658 mmeineke 443 A[j][i] += tempA[i][k] * rot[j][k];
659 mmeineke 377 }
660     }
661     }
662     }