ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 567
Committed: Wed Jun 25 21:12:14 2003 UTC (21 years ago) by mmeineke
File size: 15366 byte(s)
Log Message:
Changed over the bonds to Harmonic bonds in the DUFF frc file

fixed constraints.

File Contents

# Content
1 #include <iostream>
2 #include <cstdlib>
3 #include <cmath>
4
5 #ifdef IS_MPI
6 #include "mpiSimulation.hpp"
7 #include <unistd.h>
8 #endif //is_mpi
9
10 #include "Integrator.hpp"
11 #include "simError.h"
12
13
14 Integrator::Integrator( SimInfo *theInfo, ForceFields* the_ff ){
15
16 info = theInfo;
17 myFF = the_ff;
18 isFirst = 1;
19
20 molecules = info->molecules;
21 nMols = info->n_mol;
22
23 // give a little love back to the SimInfo object
24
25 if( info->the_integrator != NULL ) delete info->the_integrator;
26 info->the_integrator = this;
27
28 nAtoms = info->n_atoms;
29
30 // check for constraints
31
32 constrainedA = NULL;
33 constrainedB = NULL;
34 constrainedDsqr = NULL;
35 moving = NULL;
36 moved = NULL;
37 oldPos = NULL;
38
39 nConstrained = 0;
40
41 checkConstraints();
42 }
43
44 Integrator::~Integrator() {
45
46 if( nConstrained ){
47 delete[] constrainedA;
48 delete[] constrainedB;
49 delete[] constrainedDsqr;
50 delete[] moving;
51 delete[] moved;
52 delete[] oldPos;
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
144 // save oldAtoms to check for lode balanceing later on.
145
146 oldAtoms = nAtoms;
147
148 moving = new int[nAtoms];
149 moved = new int[nAtoms];
150
151 oldPos = new double[nAtoms*3];
152 }
153
154 delete[] temp_con;
155 }
156
157
158 void Integrator::integrate( void ){
159
160 int i, j; // loop counters
161
162 double runTime = info->run_time;
163 double sampleTime = info->sampleTime;
164 double statusTime = info->statusTime;
165 double thermalTime = info->thermalTime;
166
167 double currSample;
168 double currThermal;
169 double currStatus;
170 double currTime;
171
172 int calcPot, calcStress;
173 int isError;
174
175
176
177 tStats = new Thermo( info );
178 statOut = new StatWriter( info );
179 dumpOut = new DumpWriter( info );
180
181 atoms = info->atoms;
182 DirectionalAtom* dAtom;
183
184 dt = info->dt;
185 dt2 = 0.5 * dt;
186
187 // initialize the forces before the first step
188
189 myFF->doForces(1,1);
190
191 if( info->setTemp ){
192
193 tStats->velocitize();
194 }
195
196 dumpOut->writeDump( 0.0 );
197 statOut->writeStat( 0.0 );
198
199 calcPot = 0;
200 calcStress = 0;
201 currSample = sampleTime;
202 currThermal = thermalTime;
203 currStatus = statusTime;
204 currTime = 0.0;;
205
206
207 readyCheck();
208
209 #ifdef IS_MPI
210 strcpy( checkPointMsg,
211 "The integrator is ready to go." );
212 MPIcheckPoint();
213 #endif // is_mpi
214
215
216 pos = Atom::getPosArray();
217 vel = Atom::getVelArray();
218 frc = Atom::getFrcArray();
219 trq = Atom::getTrqArray();
220 Amat = Atom::getAmatArray();
221
222 while( currTime < runTime ){
223
224 if( (currTime+dt) >= currStatus ){
225 calcPot = 1;
226 calcStress = 1;
227 }
228
229 integrateStep( calcPot, calcStress );
230
231 currTime += dt;
232
233 if( info->setTemp ){
234 if( currTime >= currThermal ){
235 tStats->velocitize();
236 currThermal += thermalTime;
237 }
238 }
239
240 if( currTime >= currSample ){
241 dumpOut->writeDump( currTime );
242 currSample += sampleTime;
243 }
244
245 if( currTime >= currStatus ){
246 statOut->writeStat( currTime );
247 calcPot = 0;
248 calcStress = 0;
249 currStatus += statusTime;
250 }
251
252 #ifdef IS_MPI
253 strcpy( checkPointMsg,
254 "successfully took a time step." );
255 MPIcheckPoint();
256 #endif // is_mpi
257
258 }
259
260 dumpOut->writeFinal();
261
262 delete dumpOut;
263 delete statOut;
264 }
265
266 void Integrator::integrateStep( int calcPot, int calcStress ){
267
268
269
270 // Position full step, and velocity half step
271
272 preMove();
273 moveA();
274 if( nConstrained ) constrainA();
275
276 // calc forces
277
278 myFF->doForces(calcPot,calcStress);
279
280 // finish the velocity half step
281
282 moveB();
283 if( nConstrained ) constrainB();
284
285 }
286
287
288 void Integrator::moveA( void ){
289
290 int i,j,k;
291 int atomIndex, aMatIndex;
292 DirectionalAtom* dAtom;
293 double Tb[3];
294 double ji[3];
295 double angle;
296
297
298
299 for( i=0; i<nAtoms; i++ ){
300 atomIndex = i * 3;
301 aMatIndex = i * 9;
302
303 // velocity half step
304 for( j=atomIndex; j<(atomIndex+3); j++ )
305 vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
306
307 // position whole step
308 for( j=atomIndex; j<(atomIndex+3); j++ ) pos[j] += dt * vel[j];
309
310 if( atoms[i]->isDirectional() ){
311
312 dAtom = (DirectionalAtom *)atoms[i];
313
314 // get and convert the torque to body frame
315
316 Tb[0] = dAtom->getTx();
317 Tb[1] = dAtom->getTy();
318 Tb[2] = dAtom->getTz();
319
320 dAtom->lab2Body( Tb );
321
322 // get the angular momentum, and propagate a half step
323
324 ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
325 ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
326 ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
327
328 // use the angular velocities to propagate the rotation matrix a
329 // full time step
330
331 // rotate about the x-axis
332 angle = dt2 * ji[0] / dAtom->getIxx();
333 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
334
335 // rotate about the y-axis
336 angle = dt2 * ji[1] / dAtom->getIyy();
337 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
338
339 // rotate about the z-axis
340 angle = dt * ji[2] / dAtom->getIzz();
341 this->rotate( 0, 1, angle, ji, &Amat[aMatIndex] );
342
343 // rotate about the y-axis
344 angle = dt2 * ji[1] / dAtom->getIyy();
345 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
346
347 // rotate about the x-axis
348 angle = dt2 * ji[0] / dAtom->getIxx();
349 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
350
351 dAtom->setJx( ji[0] );
352 dAtom->setJy( ji[1] );
353 dAtom->setJz( ji[2] );
354 }
355
356 }
357 }
358
359
360 void Integrator::moveB( void ){
361 int i,j,k;
362 int atomIndex;
363 DirectionalAtom* dAtom;
364 double Tb[3];
365 double ji[3];
366
367 for( i=0; i<nAtoms; i++ ){
368 atomIndex = i * 3;
369
370 // velocity half step
371 for( j=atomIndex; j<(atomIndex+3); j++ )
372 vel[j] += ( dt2 * frc[j] / atoms[i]->getMass() ) * eConvert;
373
374 if( atoms[i]->isDirectional() ){
375
376 dAtom = (DirectionalAtom *)atoms[i];
377
378 // get and convert the torque to body frame
379
380 Tb[0] = dAtom->getTx();
381 Tb[1] = dAtom->getTy();
382 Tb[2] = dAtom->getTz();
383
384 dAtom->lab2Body( Tb );
385
386 // get the angular momentum, and complete the angular momentum
387 // half step
388
389 ji[0] = dAtom->getJx() + ( dt2 * Tb[0] ) * eConvert;
390 ji[1] = dAtom->getJy() + ( dt2 * Tb[1] ) * eConvert;
391 ji[2] = dAtom->getJz() + ( dt2 * Tb[2] ) * eConvert;
392
393 dAtom->setJx( ji[0] );
394 dAtom->setJy( ji[1] );
395 dAtom->setJz( ji[2] );
396 }
397 }
398
399 }
400
401 void Integrator::preMove( void ){
402 int i;
403
404 if( nConstrained ){
405
406 for(i=0; i<(nAtoms*3); i++) oldPos[i] = pos[i];
407 }
408 }
409
410 void Integrator::constrainA(){
411
412 int i,j,k;
413 int done;
414 double pxab, pyab, pzab;
415 double rxab, ryab, rzab;
416 int a, b, ax, ay, az, bx, by, bz;
417 double rma, rmb;
418 double dx, dy, dz;
419 double rpab;
420 double rabsq, pabsq, rpabsq;
421 double diffsq;
422 double gab;
423 int iteration;
424
425
426
427 for( i=0; i<nAtoms; i++){
428
429 moving[i] = 0;
430 moved[i] = 1;
431 }
432
433 iteration = 0;
434 done = 0;
435 while( !done && (iteration < maxIteration )){
436
437 done = 1;
438 for(i=0; i<nConstrained; i++){
439
440 a = constrainedA[i];
441 b = constrainedB[i];
442
443 ax = (a*3) + 0;
444 ay = (a*3) + 1;
445 az = (a*3) + 2;
446
447 bx = (b*3) + 0;
448 by = (b*3) + 1;
449 bz = (b*3) + 2;
450
451 if( moved[a] || moved[b] ){
452
453 pxab = pos[ax] - pos[bx];
454 pyab = pos[ay] - pos[by];
455 pzab = pos[az] - pos[bz];
456
457 //periodic boundary condition
458 pxab = pxab - info->box_x * copysign(1, pxab)
459 * (int)( fabs(pxab / info->box_x) + 0.5);
460 pyab = pyab - info->box_y * copysign(1, pyab)
461 * (int)( fabs(pyab / info->box_y) + 0.5);
462 pzab = pzab - info->box_z * copysign(1, pzab)
463 * (int)( fabs(pzab / info->box_z) + 0.5);
464
465 pabsq = pxab * pxab + pyab * pyab + pzab * pzab;
466
467 rabsq = constrainedDsqr[i];
468 diffsq = rabsq - pabsq;
469
470 // the original rattle code from alan tidesley
471 if (fabs(diffsq) > (tol*rabsq*2)) {
472 rxab = oldPos[ax] - oldPos[bx];
473 ryab = oldPos[ay] - oldPos[by];
474 rzab = oldPos[az] - oldPos[bz];
475
476 rxab = rxab - info->box_x * copysign(1, rxab)
477 * (int)( fabs(rxab / info->box_x) + 0.5);
478 ryab = ryab - info->box_y * copysign(1, ryab)
479 * (int)( fabs(ryab / info->box_y) + 0.5);
480 rzab = rzab - info->box_z * copysign(1, rzab)
481 * (int)( fabs(rzab / info->box_z) + 0.5);
482
483 rpab = rxab * pxab + ryab * pyab + rzab * pzab;
484
485 rpabsq = rpab * rpab;
486
487
488 if (rpabsq < (rabsq * -diffsq)){
489
490 #ifdef IS_MPI
491 a = atoms[a]->getGlobalIndex();
492 b = atoms[b]->getGlobalIndex();
493 #endif //is_mpi
494 sprintf( painCave.errMsg,
495 "Constraint failure in constrainA at atom %d and %d.\n",
496 a, b );
497 painCave.isFatal = 1;
498 simError();
499 }
500
501 rma = 1.0 / atoms[a]->getMass();
502 rmb = 1.0 / atoms[b]->getMass();
503
504 gab = diffsq / ( 2.0 * ( rma + rmb ) * rpab );
505
506 dx = rxab * gab;
507 dy = ryab * gab;
508 dz = rzab * gab;
509
510 pos[ax] += rma * dx;
511 pos[ay] += rma * dy;
512 pos[az] += rma * dz;
513
514 pos[bx] -= rmb * dx;
515 pos[by] -= rmb * dy;
516 pos[bz] -= rmb * dz;
517
518 dx = dx / dt;
519 dy = dy / dt;
520 dz = dz / dt;
521
522 vel[ax] += rma * dx;
523 vel[ay] += rma * dy;
524 vel[az] += rma * dz;
525
526 vel[bx] -= rmb * dx;
527 vel[by] -= rmb * dy;
528 vel[bz] -= rmb * dz;
529
530 moving[a] = 1;
531 moving[b] = 1;
532 done = 0;
533 }
534 }
535 }
536
537 for(i=0; i<nAtoms; i++){
538
539 moved[i] = moving[i];
540 moving[i] = 0;
541 }
542
543 iteration++;
544 }
545
546 if( !done ){
547
548 sprintf( painCave.errMsg,
549 "Constraint failure in constrainA, too many iterations: %d\n",
550 iteration );
551 painCave.isFatal = 1;
552 simError();
553 }
554
555 }
556
557 void Integrator::constrainB( void ){
558
559 int i,j,k;
560 int done;
561 double vxab, vyab, vzab;
562 double rxab, ryab, rzab;
563 int a, b, ax, ay, az, bx, by, bz;
564 double rma, rmb;
565 double dx, dy, dz;
566 double rabsq, pabsq, rvab;
567 double diffsq;
568 double gab;
569 int iteration;
570
571 for(i=0; i<nAtoms; i++){
572 moving[i] = 0;
573 moved[i] = 1;
574 }
575
576 done = 0;
577 iteration = 0;
578 while( !done && (iteration < maxIteration ) ){
579
580 done = 1;
581
582 for(i=0; i<nConstrained; i++){
583
584 a = constrainedA[i];
585 b = constrainedB[i];
586
587 ax = (a*3) + 0;
588 ay = (a*3) + 1;
589 az = (a*3) + 2;
590
591 bx = (b*3) + 0;
592 by = (b*3) + 1;
593 bz = (b*3) + 2;
594
595 if( moved[a] || moved[b] ){
596
597 vxab = vel[ax] - vel[bx];
598 vyab = vel[ay] - vel[by];
599 vzab = vel[az] - vel[bz];
600
601 rxab = pos[ax] - pos[bx];
602 ryab = pos[ay] - pos[by];
603 rzab = pos[az] - pos[bz];
604
605
606 rxab = rxab - info->box_x * copysign(1, rxab)
607 * (int)( fabs(rxab / info->box_x) + 0.5);
608 ryab = ryab - info->box_y * copysign(1, ryab)
609 * (int)( fabs(ryab / info->box_y) + 0.5);
610 rzab = rzab - info->box_z * copysign(1, rzab)
611 * (int)( fabs(rzab / info->box_z) + 0.5);
612
613 rma = 1.0 / atoms[a]->getMass();
614 rmb = 1.0 / atoms[b]->getMass();
615
616 rvab = rxab * vxab + ryab * vyab + rzab * vzab;
617
618 gab = -rvab / ( ( rma + rmb ) * constrainedDsqr[i] );
619
620 if (fabs(gab) > tol) {
621
622 dx = rxab * gab;
623 dy = ryab * gab;
624 dz = rzab * gab;
625
626 vel[ax] += rma * dx;
627 vel[ay] += rma * dy;
628 vel[az] += rma * dz;
629
630 vel[bx] -= rmb * dx;
631 vel[by] -= rmb * dy;
632 vel[bz] -= rmb * dz;
633
634 moving[a] = 1;
635 moving[b] = 1;
636 done = 0;
637 }
638 }
639 }
640
641 for(i=0; i<nAtoms; i++){
642 moved[i] = moving[i];
643 moving[i] = 0;
644 }
645
646 iteration++;
647 }
648
649 if( !done ){
650
651
652 sprintf( painCave.errMsg,
653 "Constraint failure in constrainB, too many iterations: %d\n",
654 iteration );
655 painCave.isFatal = 1;
656 simError();
657 }
658
659 }
660
661
662
663
664
665
666
667 void Integrator::rotate( int axes1, int axes2, double angle, double ji[3],
668 double A[9] ){
669
670 int i,j,k;
671 double sinAngle;
672 double cosAngle;
673 double angleSqr;
674 double angleSqrOver4;
675 double top, bottom;
676 double rot[3][3];
677 double tempA[3][3];
678 double tempJ[3];
679
680 // initialize the tempA
681
682 for(i=0; i<3; i++){
683 for(j=0; j<3; j++){
684 tempA[j][i] = A[3*i + j];
685 }
686 }
687
688 // initialize the tempJ
689
690 for( i=0; i<3; i++) tempJ[i] = ji[i];
691
692 // initalize rot as a unit matrix
693
694 rot[0][0] = 1.0;
695 rot[0][1] = 0.0;
696 rot[0][2] = 0.0;
697
698 rot[1][0] = 0.0;
699 rot[1][1] = 1.0;
700 rot[1][2] = 0.0;
701
702 rot[2][0] = 0.0;
703 rot[2][1] = 0.0;
704 rot[2][2] = 1.0;
705
706 // use a small angle aproximation for sin and cosine
707
708 angleSqr = angle * angle;
709 angleSqrOver4 = angleSqr / 4.0;
710 top = 1.0 - angleSqrOver4;
711 bottom = 1.0 + angleSqrOver4;
712
713 cosAngle = top / bottom;
714 sinAngle = angle / bottom;
715
716 rot[axes1][axes1] = cosAngle;
717 rot[axes2][axes2] = cosAngle;
718
719 rot[axes1][axes2] = sinAngle;
720 rot[axes2][axes1] = -sinAngle;
721
722 // rotate the momentum acoording to: ji[] = rot[][] * ji[]
723
724 for(i=0; i<3; i++){
725 ji[i] = 0.0;
726 for(k=0; k<3; k++){
727 ji[i] += rot[i][k] * tempJ[k];
728 }
729 }
730
731 // rotate the Rotation matrix acording to:
732 // A[][] = A[][] * transpose(rot[][])
733
734
735 // NOte for as yet unknown reason, we are performing the
736 // calculation as:
737 // transpose(A[][]) = transpose(A[][]) * transpose(rot[][])
738
739 for(i=0; i<3; i++){
740 for(j=0; j<3; j++){
741 A[3*j + i] = 0.0;
742 for(k=0; k<3; k++){
743 A[3*j + i] += tempA[i][k] * rot[j][k];
744 }
745 }
746 }
747 }