ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE_old/src/mdtools/libmdCode/Symplectic.cpp
Revision: 365
Committed: Tue Mar 18 22:17:31 2003 UTC (21 years, 3 months ago) by mmeineke
File size: 14764 byte(s)
Log Message:
some initial bug fixes

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
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 }