ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Symplectic.cpp
Revision: 548
Committed: Wed Jun 4 21:06:45 2003 UTC (21 years, 11 months ago) by mmeineke
File size: 15285 byte(s)
Log Message:
added constrainA and constrainB to the Symplectic integrator

File Contents

# Content
1 #include <iostream>
2 #include <cstdlib>
3
4 #ifdef IS_MPI
5 #include "mpiSimulation.hpp"
6 #include <unistd.h>
7 #endif //is_mpi
8
9 #include "Integrator.hpp"
10 #include "simError.h"
11
12
13 Integrator::Integrator( SimInfo* theInfo, ForceFields* the_ff ){
14
15 info = theInfo;
16 myFF = the_ff;
17 isFirst = 1;
18
19 molecules = info->molecules;
20 nMols = info->n_mol;
21
22 // give a little love back to the SimInfo object
23
24 if( info->the_integrator != NULL ) delete info->the_integrator;
25 info->the_integrator = this;
26
27 nAtoms = info->n_atoms;
28
29 // check for constraints
30
31 constrainedA = NULL;
32 constrainedB = NULL;
33 constrainedDsqr = NULL;
34 moving = NULL;
35 moved = NULL;
36 prePos = NULL;
37
38 nConstrained = 0;
39
40 checkConstraints();
41 }
42
43 Integrator::~Integrator() {
44
45 if( nConstrained ){
46 delete[] constrainedA;
47 delete[] constrainedB;
48 delete[] constrainedDsqr;
49 delete[] moving;
50 delete[] moved;
51 delete[] prePos;
52 k
53 }
54
55 }
56
57 void Integrator::checkConstraints( void ){
58
59
60 isConstrained = 0;
61
62 Constraint *temp_con;
63 Constraint *dummy_plug;
64 temp_con = new Constraint[info->n_SRI];
65 nConstrained = 0;
66 int constrained = 0;
67
68 SRI** theArray;
69 for(int i = 0; i < nMols; i++){
70
71 theArray = (SRI**) molecules[i].getMyBonds();
72 for(int j=0; j<molecules[i].getNBonds(); j++){
73
74 constrained = theArray[j]->is_constrained();
75
76 if(constrained){
77
78 dummy_plug = theArray[j]->get_constraint();
79 temp_con[nConstrained].set_a( dummy_plug->get_a() );
80 temp_con[nConstrained].set_b( dummy_plug->get_b() );
81 temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
82
83 nConstrained++;
84 constrained = 0;
85 }
86 }
87
88 theArray = (SRI**) molecules[i].getMyBends();
89 for(int j=0; j<molecules[i].getNBends(); j++){
90
91 constrained = theArray[j]->is_constrained();
92
93 if(constrained){
94
95 dummy_plug = theArray[j]->get_constraint();
96 temp_con[nConstrained].set_a( dummy_plug->get_a() );
97 temp_con[nConstrained].set_b( dummy_plug->get_b() );
98 temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
99
100 nConstrained++;
101 constrained = 0;
102 }
103 }
104
105 theArray = (SRI**) molecules[i].getMyTorsions();
106 for(int j=0; j<molecules[i].getNTorsions(); j++){
107
108 constrained = theArray[j]->is_constrained();
109
110 if(constrained){
111
112 dummy_plug = theArray[j]->get_constraint();
113 temp_con[nConstrained].set_a( dummy_plug->get_a() );
114 temp_con[nConstrained].set_b( dummy_plug->get_b() );
115 temp_con[nConstrained].set_dsqr( dummy_plug->get_dsqr() );
116
117 nConstrained++;
118 constrained = 0;
119 }
120 }
121 }
122
123 if(nConstrained > 0){
124
125 isConstrained = 1;
126
127 if(constrainedA != NULL ) delete[] constrainedA;
128 if(constrainedB != NULL ) delete[] constrainedB;
129 if(constrainedDsqr != NULL ) delete[] constrainedDsqr;
130
131 constrainedA = new int[nConstrained];
132 constrainedB = new int[nConstrained];
133 constrainedDsqr = new double[nConstrained];
134
135 for( int i = 0; i < nConstrained; i++){
136
137 constrainedA[i] = temp_con[i].get_a();
138 constrainedB[i] = temp_con[i].get_b();
139 constrainedDsqr[i] = temp_con[i].get_dsqr();
140 }
141
142
143 // save oldAtoms to check for lode balanceing later on.
144
145 oldAtoms = nAtoms;
146
147 moving = new int[nAtoms];
148 moved = new int[nAtoms];
149
150 prePos = new double[nAtoms*3];
151 }
152
153 delete[] temp_con;
154 }
155
156
157 void Integrator::integrate( void ){
158
159 int i, j; // loop counters
160 double kE = 0.0; // the kinetic energy
161 double rot_kE;
162 double trans_kE;
163 int tl; // the time loop conter
164 double dt2; // half the dt
165
166 double vx, vy, vz; // the velocities
167 double vx2, vy2, vz2; // the square of the velocities
168 double rx, ry, rz; // the postitions
169
170 double ji[3]; // the body frame angular momentum
171 double jx2, jy2, jz2; // the square of the angular momentums
172 double Tb[3]; // torque in the body frame
173 double angle; // the angle through which to rotate the rotation matrix
174 double A[3][3]; // the rotation matrix
175 double press[9];
176
177 int time;
178
179 double dt = info->dt;
180 double runTime = info->run_time;
181 double sampleTime = info->sampleTime;
182 double statusTime = info->statusTime;
183 double thermalTime = info->thermalTime;
184
185 int n_loops = (int)( runTime / dt );
186 int sample_n = (int)( sampleTime / dt );
187 int status_n = (int)( statusTime / dt );
188 int vel_n = (int)( thermalTime / dt );
189
190 int calcPot, calcStress;
191 int isError;
192
193 tStats = new Thermo( info );
194 e_out = new StatWriter( info );
195 dump_out = new DumpWriter( info );
196
197 Atom** atoms = info->atoms;
198 DirectionalAtom* dAtom;
199 dt2 = 0.5 * dt;
200
201 // initialize the forces before the first step
202
203 myFF->doForces(1,1);
204
205 if( info->setTemp ){
206
207 tStats->velocitize();
208 }
209
210 dump_out->writeDump( 0.0 );
211 e_out->writeStat( 0.0 );
212
213 calcPot = 0;
214
215 for( tl=0; tl<nLoops; tl++){
216
217 integrateStep( calcPot, calcStress );
218
219 time = tl + 1;
220
221 if( info->setTemp ){
222 if( !(time % vel_n) ) tStats->velocitize();
223 }
224 if( !(time % sample_n) ) dump_out->writeDump( time * dt );
225 if( !((time+1) % status_n) ) {
226 calcPot = 1;
227 calcStress = 1;
228 }
229 if( !(time % status_n) ){
230 e_out->writeStat( time * dt );
231 calcPot = 0;
232 if (!strcasecmp(info->ensemble, "NPT")) calcStress = 1;
233 else calcStress = 0;
234 }
235
236
237 }
238
239 dump_out->writeFinal();
240
241 delete dump_out;
242 delete e_out;
243 }
244
245
246 void Integrator::moveA( void ){
247
248 int i,j,k;
249 int atomIndex, aMatIndex;
250 DirectionalAtom* dAtom;
251 double Tb[3];
252 double ji[3];
253
254 for( i=0; i<nAtoms; i++ ){
255 atomIndex = i * 3;
256 aMatIndex = i * 9;
257
258 // velocity half step
259 for( j=atomIndex; j<(atomIndex+3); j++ )
260 vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
261
262 // position whole step
263 for( j=atomIndex; j<(atomIndex+3); j++ )
264 pos[j] += dt * vel[j];
265
266
267 if( atoms[i]->isDirectional() ){
268
269 dAtom = (DirectionalAtom *)atoms[i];
270
271 // get and convert the torque to body frame
272
273 Tb[0] = dAtom->getTx();
274 Tb[1] = dAtom->getTy();
275 Tb[2] = dAtom->getTz();
276
277 dAtom->lab2Body( Tb );
278
279 // get the angular momentum, and propagate a half step
280
281 ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
282 ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
283 ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
284
285 // use the angular velocities to propagate the rotation matrix a
286 // full time step
287
288 // rotate about the x-axis
289 angle = dt2 * ji[0] / dAtom->getIxx();
290 this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
291
292 // rotate about the y-axis
293 angle = dt2 * ji[1] / dAtom->getIyy();
294 this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
295
296 // rotate about the z-axis
297 angle = dt * ji[2] / dAtom->getIzz();
298 this->rotate( 0, 1, angle, ji, &aMat[aMatIndex] );
299
300 // rotate about the y-axis
301 angle = dt2 * ji[1] / dAtom->getIyy();
302 this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
303
304 // rotate about the x-axis
305 angle = dt2 * ji[0] / dAtom->getIxx();
306 this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
307
308 dAtom->setJx( ji[0] );
309 dAtom->setJy( ji[1] );
310 dAtom->setJz( ji[2] );
311 }
312
313 }
314 }
315
316
317 void Integrator::moveB( void ){
318 int i,j,k;
319 int atomIndex;
320 DirectionalAtom* dAtom;
321 double Tb[3];
322 double ji[3];
323
324 for( i=0; i<nAtoms; i++ ){
325 atomIndex = i * 3;
326
327 // velocity half step
328 for( j=atomIndex; j<(atomIndex+3); j++ )
329 vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
330
331 if( atoms[i]->isDirectional() ){
332
333 dAtom = (DirectionalAtom *)atoms[i];
334
335 // get and convert the torque to body frame
336
337 Tb[0] = dAtom->getTx();
338 Tb[1] = dAtom->getTy();
339 Tb[2] = dAtom->getTz();
340
341 dAtom->lab2Body( Tb );
342
343 // get the angular momentum, and complete the angular momentum
344 // half step
345
346 ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
347 ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
348 ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
349
350 jx2 = ji[0] * ji[0];
351 jy2 = ji[1] * ji[1];
352 jz2 = ji[2] * ji[2];
353
354 dAtom->setJx( ji[0] );
355 dAtom->setJy( ji[1] );
356 dAtom->setJz( ji[2] );
357 }
358 }
359
360 }
361
362 void Integrator::preMove( void ){
363 int i;
364
365 if( nConstrained ){
366 if( oldAtoms != nAtoms ){
367
368 // save oldAtoms to check for lode balanceing later on.
369
370 oldAtoms = nAtoms;
371
372 delete[] moving;
373 delete[] moved;
374 delete[] oldPos;
375
376 moving = new int[nAtoms];
377 moved = new int[nAtoms];
378
379 oldPos = new double[nAtoms*3];
380 }
381
382 for(i=0; i<(nAtoms*3); i++) oldPos[i] = pos[i];
383 }
384 }
385
386 void Integrator::constrainA(){
387
388 int i,j,k;
389 int done;
390 double pxab, pyab, pzab;
391 double rxab, ryab, rzab;
392 int a, b;
393 double rma, rmb;
394 double dx, dy, dz;
395 double rabsq, pabsq, rpabsq;
396 double diffsq;
397 double gab;
398 int iteration;
399
400
401
402 for( i=0; i<nAtoms; i++){
403
404 moving[i] = 0;
405 moved[i] = 1;
406 }
407
408
409 iteration = 0;
410 done = 0;
411 while( !done && (iteration < maxIteration )){
412
413 done = 1;
414 for(i=0; i<nConstrained; i++){
415
416 a = constrainedA[i];
417 b = constrainedB[i];
418
419 if( moved[a] || moved[b] ){
420
421 pxab = pos[3*a+0] - pos[3*b+0];
422 pyab = pos[3*a+1] - pos[3*b+1];
423 pzab = pos[3*a+2] - pos[3*b+2];
424
425 //periodic boundary condition
426 pxab = pxab - info->box_x * copysign(1, pxab)
427 * int(pxab / info->box_x + 0.5);
428 pyab = pyab - info->box_y * copysign(1, pyab)
429 * int(pyab / info->box_y + 0.5);
430 pzab = pzab - info->box_z * copysign(1, pzab)
431 * int(pzab / info->box_z + 0.5);
432
433 pabsq = pxab * pxab + pyab * pyab + pzab * pzab;
434 rabsq = constraintedDsqr[i];
435 diffsq = pabsq - rabsq;
436
437 // the original rattle code from alan tidesley
438 if (fabs(diffsq) > tol*rabsq*2) {
439 rxab = oldPos[3*a+0] - oldPos[3*b+0];
440 ryab = oldPos[3*a+1] - oldPos[3*b+1];
441 rzab = oldPos[3*a+2] - oldPos[3*b+2];
442
443 rxab = rxab - info->box_x * copysign(1, rxab)
444 * int(rxab / info->box_x + 0.5);
445 ryab = ryab - info->box_y * copysign(1, ryab)
446 * int(ryab / info->box_y + 0.5);
447 rzab = rzab - info->box_z * copysign(1, rzab)
448 * int(rzab / info->box_z + 0.5);
449
450 rpab = rxab * pxab + ryab * pyab + rzab * pzab;
451 rpabsq = rpab * rpab;
452
453
454 if (rpabsq < (rabsq * -diffsq)){
455 #ifdef IS_MPI
456 a = atoms[a]->getGlobalIndex();
457 b = atoms[b]->getGlobalIndex();
458 #endif //is_mpi
459 sprintf( painCave.errMsg,
460 "Constraint failure in constrainA at atom %d and %d\n.",
461 a, b );
462 painCave.isFatal = 1;
463 simError();
464 }
465
466 rma = 1.0 / atoms[a]->getMass();
467 rmb = 1.0 / atoms[b]->getMass();
468
469 gab = diffsq / ( 2.0 * ( rma + rmb ) * rpab );
470 dx = rxab * gab;
471 dy = ryab * gab;
472 dz = rzab * gab;
473
474 pos[3*a+0] += rma * dx;
475 pos[3*a+1] += rma * dy;
476 pos[3*a+2] += rma * dz;
477
478 pos[3*b+0] -= rmb * dx;
479 pos[3*b+1] -= rmb * dy;
480 pos[3*b+2] -= rmb * dz;
481
482 dx = dx / dt;
483 dy = dy / dt;
484 dz = dz / dt;
485
486 vel[3*a+0] += rma * dx;
487 vel[3*a+1] += rma * dy;
488 vel[3*a+2] += rma * dz;
489
490 vel[3*b+0] -= rmb * dx;
491 vel[3*b+1] -= rmb * dy;
492 vel[3*b+2] -= rmb * dz;
493
494 moving[a] = 1;
495 moving[b] = 1;
496 done = 0;
497 }
498 }
499 }
500
501 for(i=0; i<nAtoms; i++){
502
503 moved[i] = moving[i];
504 moving[i] = 0;
505 }
506
507 iteration++;
508 }
509
510 if( !done ){
511
512 sprintf( painCae.errMsg,
513 "Constraint failure in constrainA, too many iterations: %d\n",
514 iterations );
515 painCave.isFatal = 1;
516 simError();
517 }
518
519 }
520
521 void Integrator::constrainB( void ){
522
523 int i,j,k;
524 int done;
525 double vxab, vyab, vzab;
526 double rxab, ryab, rzab;
527 int a, b;
528 double rma, rmb;
529 double dx, dy, dz;
530 double rabsq, pabsq, rvab;
531 double diffsq;
532 double gab;
533 int iteration;
534
535 for(i=0; i<nAtom; i++){
536 moving[i] = 0;
537 moved[i] = 1;
538 }
539
540 done = 0;
541 while( !done && (iteration < maxIteration ) ){
542
543 for(i=0; i<nConstrained; i++){
544
545 a = constrainedA[i];
546 b = constrainedB[i];
547
548 if( moved[a] || moved[b] ){
549
550 vxab = vel[3*a+0] - vel[3*b+0];
551 vyab = vel[3*a+1] - vel[3*b+1];
552 vzab = vel[3*a+2] - vel[3*b+2];
553
554 rxab = pos[3*a+0] - pos[3*b+0];q
555 ryab = pos[3*a+1] - pos[3*b+1];
556 rzab = pos[3*a+2] - pos[3*b+2];
557
558 rxab = rxab - info->box_x * copysign(1, rxab)
559 * int(rxab / info->box_x + 0.5);
560 ryab = ryab - info->box_y * copysign(1, ryab)
561 * int(ryab / info->box_y + 0.5);
562 rzab = rzab - info->box_z * copysign(1, rzab)
563 * int(rzab / info->box_z + 0.5);
564
565 rma = 1.0 / atoms[a]->getMass();
566 rmb = 1.0 / atoms[b]->getMass();
567
568 rvab = rxab * vxab + ryab * vyab + rzab * vzab;
569
570 gab = -rvab / ( ( rma + rmb ) * constraintsDsqr[i] );
571
572 if (fabs(gab) > tol) {
573
574 dx = rxab * gab;
575 dy = ryab * gab;
576 dz = rzab * gab;
577
578 vel[3*a+0] += rma * dx;
579 vel[3*a+1] += rma * dy;
580 vel[3*a+2] += rma * dz;
581
582 vel[3*b+0] -= rmb * dx;
583 vel[3*b+1] -= rmb * dy;
584 vel[3*b+2] -= rmb * dz;
585
586 moving[a] = 1;
587 moving[b] = 1;
588 done = 0;
589 }
590 }
591 }
592
593 for(i=0; i<nAtoms; i++){
594 moved[i] = moving[i];
595 moving[i] = 0;
596 }
597
598 iteration++;
599 }
600
601 if( !done ){
602
603
604 sprintf( painCae.errMsg,
605 "Constraint failure in constrainB, too many iterations: %d\n",
606 iterations );
607 painCave.isFatal = 1;
608 simError();
609 }
610
611 }
612
613
614
615
616
617
618
619 void Integrator::rotate( int axes1, int axes2, double angle, double ji[3],
620 double A[3][3] ){
621
622 int i,j,k;
623 double sinAngle;
624 double cosAngle;
625 double angleSqr;
626 double angleSqrOver4;
627 double top, bottom;
628 double rot[3][3];
629 double tempA[3][3];
630 double tempJ[3];
631
632 // initialize the tempA
633
634 for(i=0; i<3; i++){
635 for(j=0; j<3; j++){
636 tempA[j][i] = A[i][j];
637 }
638 }
639
640 // initialize the tempJ
641
642 for( i=0; i<3; i++) tempJ[i] = ji[i];
643
644 // initalize rot as a unit matrix
645
646 rot[0][0] = 1.0;
647 rot[0][1] = 0.0;
648 rot[0][2] = 0.0;
649
650 rot[1][0] = 0.0;
651 rot[1][1] = 1.0;
652 rot[1][2] = 0.0;
653
654 rot[2][0] = 0.0;
655 rot[2][1] = 0.0;
656 rot[2][2] = 1.0;
657
658 // use a small angle aproximation for sin and cosine
659
660 angleSqr = angle * angle;
661 angleSqrOver4 = angleSqr / 4.0;
662 top = 1.0 - angleSqrOver4;
663 bottom = 1.0 + angleSqrOver4;
664
665 cosAngle = top / bottom;
666 sinAngle = angle / bottom;
667
668 rot[axes1][axes1] = cosAngle;
669 rot[axes2][axes2] = cosAngle;
670
671 rot[axes1][axes2] = sinAngle;
672 rot[axes2][axes1] = -sinAngle;
673
674 // rotate the momentum acoording to: ji[] = rot[][] * ji[]
675
676 for(i=0; i<3; i++){
677 ji[i] = 0.0;
678 for(k=0; k<3; k++){
679 ji[i] += rot[i][k] * tempJ[k];
680 }
681 }
682
683 // rotate the Rotation matrix acording to:
684 // A[][] = A[][] * transpose(rot[][])
685
686
687 // NOte for as yet unknown reason, we are setting the performing the
688 // calculation as:
689 // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
690
691 for(i=0; i<3; i++){
692 for(j=0; j<3; j++){
693 A[j][i] = 0.0;
694 for(k=0; k<3; k++){
695 A[j][i] += tempA[i][k] * rot[j][k];
696 }
697 }
698 }
699 }