ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Symplectic.cpp
Revision: 443
Committed: Wed Apr 2 22:19:03 2003 UTC (21 years, 3 months ago) by mmeineke
File size: 15770 byte(s)
Log Message:
dipoles mostly work, but there is a memory leak somewhere.

File Contents

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