ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Integrator.cpp
Revision: 558
Committed: Thu Jun 19 19:21:23 2003 UTC (21 years ago) by mmeineke
File size: 15703 byte(s)
Log Message:
finished the basics of the integrator and SimSetup.cpp

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