ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 853
Committed: Thu Nov 6 19:11:38 2003 UTC (20 years, 8 months ago) by mmeineke
File size: 15212 byte(s)
Log Message:
did a merge by hand from the new-templateless branch to the main trunk.

bug Fixes include:
  * fixed the switching function from ortho to non-ortho box.
         !!!!! THis was responsible for all of the sudden deaths we saw.
  * some formating in the string when we write out the extended system state.
  * added NPT.cpp to the makefile.in

File Contents

# Content
1 #include <stdlib.h>
2 #include <string.h>
3 #include <math.h>
4
5 #include <iostream>
6 using namespace std;
7
8 #include "SimInfo.hpp"
9 #define __C
10 #include "fSimulation.h"
11 #include "simError.h"
12
13 #include "fortranWrappers.hpp"
14
15 #ifdef IS_MPI
16 #include "mpiSimulation.hpp"
17 #endif
18
19 inline double roundMe( double x ){
20 return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
21 }
22
23
24 SimInfo* currentInfo;
25
26 SimInfo::SimInfo(){
27 excludes = NULL;
28 n_constraints = 0;
29 nZconstraints = 0;
30 n_oriented = 0;
31 n_dipoles = 0;
32 ndf = 0;
33 ndfRaw = 0;
34 nZconstraints = 0;
35 the_integrator = NULL;
36 setTemp = 0;
37 thermalTime = 0.0;
38 currentTime = 0.0;
39 rCut = 0.0;
40 origRcut = -1.0;
41 ecr = 0.0;
42 origEcr = -1.0;
43 est = 0.0;
44 oldEcr = 0.0;
45 oldRcut = 0.0;
46
47 haveOrigRcut = 0;
48 haveOrigEcr = 0;
49 boxIsInit = 0;
50
51 resetTime = 1e99;
52
53
54 usePBC = 0;
55 useLJ = 0;
56 useSticky = 0;
57 useDipole = 0;
58 useReactionField = 0;
59 useGB = 0;
60 useEAM = 0;
61
62 myConfiguration = new SimState();
63
64 wrapMeSimInfo( this );
65 }
66
67
68 SimInfo::~SimInfo(){
69
70 delete myConfiguration;
71
72 map<string, GenericData*>::iterator i;
73
74 for(i = properties.begin(); i != properties.end(); i++)
75 delete (*i).second;
76
77 }
78
79 void SimInfo::setBox(double newBox[3]) {
80
81 int i, j;
82 double tempMat[3][3];
83
84 for(i=0; i<3; i++)
85 for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
86
87 tempMat[0][0] = newBox[0];
88 tempMat[1][1] = newBox[1];
89 tempMat[2][2] = newBox[2];
90
91 setBoxM( tempMat );
92
93 }
94
95 void SimInfo::setBoxM( double theBox[3][3] ){
96
97 int i, j;
98 double FortranHmat[9]; // to preserve compatibility with Fortran the
99 // ordering in the array is as follows:
100 // [ 0 3 6 ]
101 // [ 1 4 7 ]
102 // [ 2 5 8 ]
103 double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
104
105
106 if( !boxIsInit ) boxIsInit = 1;
107
108 for(i=0; i < 3; i++)
109 for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
110
111 calcBoxL();
112 calcHmatInv();
113
114 for(i=0; i < 3; i++) {
115 for (j=0; j < 3; j++) {
116 FortranHmat[3*j + i] = Hmat[i][j];
117 FortranHmatInv[3*j + i] = HmatInv[i][j];
118 }
119 }
120
121 setFortranBoxSize(FortranHmat, FortranHmatInv, &orthoRhombic);
122
123 }
124
125
126 void SimInfo::getBoxM (double theBox[3][3]) {
127
128 int i, j;
129 for(i=0; i<3; i++)
130 for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
131 }
132
133
134 void SimInfo::scaleBox(double scale) {
135 double theBox[3][3];
136 int i, j;
137
138 // cerr << "Scaling box by " << scale << "\n";
139
140 for(i=0; i<3; i++)
141 for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
142
143 setBoxM(theBox);
144
145 }
146
147 void SimInfo::calcHmatInv( void ) {
148
149 int oldOrtho;
150 int i,j;
151 double smallDiag;
152 double tol;
153 double sanity[3][3];
154
155 invertMat3( Hmat, HmatInv );
156
157 // check to see if Hmat is orthorhombic
158
159 oldOrtho = orthoRhombic;
160
161 smallDiag = fabs(Hmat[0][0]);
162 if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
163 if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
164 tol = smallDiag * 1E-6;
165
166 orthoRhombic = 1;
167
168 for (i = 0; i < 3; i++ ) {
169 for (j = 0 ; j < 3; j++) {
170 if (i != j) {
171 if (orthoRhombic) {
172 if ( fabs(Hmat[i][j]) >= tol) orthoRhombic = 0;
173 }
174 }
175 }
176 }
177
178 if( oldOrtho != orthoRhombic ){
179
180 if( orthoRhombic ){
181 sprintf( painCave.errMsg,
182 "Hmat is switching from Non-Orthorhombic to OrthoRhombic\n"
183 " If this is a bad thing change the ortho tolerance in SimInfo.\n" );
184 simError();
185 }
186 else {
187 sprintf( painCave.errMsg,
188 "Hmat is switching from Orthorhombic to Non-OrthoRhombic\n"
189 " If this is a bad thing change the ortho tolerance in SimInfo.\n" );
190 simError();
191 }
192 }
193 }
194
195 double SimInfo::matDet3(double a[3][3]) {
196 int i, j, k;
197 double determinant;
198
199 determinant = 0.0;
200
201 for(i = 0; i < 3; i++) {
202 j = (i+1)%3;
203 k = (i+2)%3;
204
205 determinant += a[0][i] * (a[1][j]*a[2][k] - a[1][k]*a[2][j]);
206 }
207
208 return determinant;
209 }
210
211 void SimInfo::invertMat3(double a[3][3], double b[3][3]) {
212
213 int i, j, k, l, m, n;
214 double determinant;
215
216 determinant = matDet3( a );
217
218 if (determinant == 0.0) {
219 sprintf( painCave.errMsg,
220 "Can't invert a matrix with a zero determinant!\n");
221 painCave.isFatal = 1;
222 simError();
223 }
224
225 for (i=0; i < 3; i++) {
226 j = (i+1)%3;
227 k = (i+2)%3;
228 for(l = 0; l < 3; l++) {
229 m = (l+1)%3;
230 n = (l+2)%3;
231
232 b[l][i] = (a[j][m]*a[k][n] - a[j][n]*a[k][m]) / determinant;
233 }
234 }
235 }
236
237 void SimInfo::matMul3(double a[3][3], double b[3][3], double c[3][3]) {
238 double r00, r01, r02, r10, r11, r12, r20, r21, r22;
239
240 r00 = a[0][0]*b[0][0] + a[0][1]*b[1][0] + a[0][2]*b[2][0];
241 r01 = a[0][0]*b[0][1] + a[0][1]*b[1][1] + a[0][2]*b[2][1];
242 r02 = a[0][0]*b[0][2] + a[0][1]*b[1][2] + a[0][2]*b[2][2];
243
244 r10 = a[1][0]*b[0][0] + a[1][1]*b[1][0] + a[1][2]*b[2][0];
245 r11 = a[1][0]*b[0][1] + a[1][1]*b[1][1] + a[1][2]*b[2][1];
246 r12 = a[1][0]*b[0][2] + a[1][1]*b[1][2] + a[1][2]*b[2][2];
247
248 r20 = a[2][0]*b[0][0] + a[2][1]*b[1][0] + a[2][2]*b[2][0];
249 r21 = a[2][0]*b[0][1] + a[2][1]*b[1][1] + a[2][2]*b[2][1];
250 r22 = a[2][0]*b[0][2] + a[2][1]*b[1][2] + a[2][2]*b[2][2];
251
252 c[0][0] = r00; c[0][1] = r01; c[0][2] = r02;
253 c[1][0] = r10; c[1][1] = r11; c[1][2] = r12;
254 c[2][0] = r20; c[2][1] = r21; c[2][2] = r22;
255 }
256
257 void SimInfo::matVecMul3(double m[3][3], double inVec[3], double outVec[3]) {
258 double a0, a1, a2;
259
260 a0 = inVec[0]; a1 = inVec[1]; a2 = inVec[2];
261
262 outVec[0] = m[0][0]*a0 + m[0][1]*a1 + m[0][2]*a2;
263 outVec[1] = m[1][0]*a0 + m[1][1]*a1 + m[1][2]*a2;
264 outVec[2] = m[2][0]*a0 + m[2][1]*a1 + m[2][2]*a2;
265 }
266
267 void SimInfo::transposeMat3(double in[3][3], double out[3][3]) {
268 double temp[3][3];
269 int i, j;
270
271 for (i = 0; i < 3; i++) {
272 for (j = 0; j < 3; j++) {
273 temp[j][i] = in[i][j];
274 }
275 }
276 for (i = 0; i < 3; i++) {
277 for (j = 0; j < 3; j++) {
278 out[i][j] = temp[i][j];
279 }
280 }
281 }
282
283 void SimInfo::printMat3(double A[3][3] ){
284
285 std::cerr
286 << "[ " << A[0][0] << ", " << A[0][1] << ", " << A[0][2] << " ]\n"
287 << "[ " << A[1][0] << ", " << A[1][1] << ", " << A[1][2] << " ]\n"
288 << "[ " << A[2][0] << ", " << A[2][1] << ", " << A[2][2] << " ]\n";
289 }
290
291 void SimInfo::printMat9(double A[9] ){
292
293 std::cerr
294 << "[ " << A[0] << ", " << A[1] << ", " << A[2] << " ]\n"
295 << "[ " << A[3] << ", " << A[4] << ", " << A[5] << " ]\n"
296 << "[ " << A[6] << ", " << A[7] << ", " << A[8] << " ]\n";
297 }
298
299
300 void SimInfo::crossProduct3(double a[3],double b[3], double out[3]){
301
302 out[0] = a[1] * b[2] - a[2] * b[1];
303 out[1] = a[2] * b[0] - a[0] * b[2] ;
304 out[2] = a[0] * b[1] - a[1] * b[0];
305
306 }
307
308 double SimInfo::dotProduct3(double a[3], double b[3]){
309 return a[0]*b[0] + a[1]*b[1]+ a[2]*b[2];
310 }
311
312 double SimInfo::length3(double a[3]){
313 return sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
314 }
315
316 void SimInfo::calcBoxL( void ){
317
318 double dx, dy, dz, dsq;
319
320 // boxVol = Determinant of Hmat
321
322 boxVol = matDet3( Hmat );
323
324 // boxLx
325
326 dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
327 dsq = dx*dx + dy*dy + dz*dz;
328 boxL[0] = sqrt( dsq );
329 //maxCutoff = 0.5 * boxL[0];
330
331 // boxLy
332
333 dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
334 dsq = dx*dx + dy*dy + dz*dz;
335 boxL[1] = sqrt( dsq );
336 //if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
337
338
339 // boxLz
340
341 dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
342 dsq = dx*dx + dy*dy + dz*dz;
343 boxL[2] = sqrt( dsq );
344 //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
345
346 //calculate the max cutoff
347 maxCutoff = calcMaxCutOff();
348
349 checkCutOffs();
350
351 }
352
353
354 double SimInfo::calcMaxCutOff(){
355
356 double ri[3], rj[3], rk[3];
357 double rij[3], rjk[3], rki[3];
358 double minDist;
359
360 ri[0] = Hmat[0][0];
361 ri[1] = Hmat[1][0];
362 ri[2] = Hmat[2][0];
363
364 rj[0] = Hmat[0][1];
365 rj[1] = Hmat[1][1];
366 rj[2] = Hmat[2][1];
367
368 rk[0] = Hmat[0][2];
369 rk[1] = Hmat[1][2];
370 rk[2] = Hmat[2][2];
371
372 crossProduct3(ri,rj, rij);
373 distXY = dotProduct3(rk,rij) / length3(rij);
374
375 crossProduct3(rj,rk, rjk);
376 distYZ = dotProduct3(ri,rjk) / length3(rjk);
377
378 crossProduct3(rk,ri, rki);
379 distZX = dotProduct3(rj,rki) / length3(rki);
380
381 minDist = min(min(distXY, distYZ), distZX);
382 return minDist/2;
383
384 }
385
386 void SimInfo::wrapVector( double thePos[3] ){
387
388 int i;
389 double scaled[3];
390
391 if( !orthoRhombic ){
392 // calc the scaled coordinates.
393
394
395 matVecMul3(HmatInv, thePos, scaled);
396
397 for(i=0; i<3; i++)
398 scaled[i] -= roundMe(scaled[i]);
399
400 // calc the wrapped real coordinates from the wrapped scaled coordinates
401
402 matVecMul3(Hmat, scaled, thePos);
403
404 }
405 else{
406 // calc the scaled coordinates.
407
408 for(i=0; i<3; i++)
409 scaled[i] = thePos[i]*HmatInv[i][i];
410
411 // wrap the scaled coordinates
412
413 for(i=0; i<3; i++)
414 scaled[i] -= roundMe(scaled[i]);
415
416 // calc the wrapped real coordinates from the wrapped scaled coordinates
417
418 for(i=0; i<3; i++)
419 thePos[i] = scaled[i]*Hmat[i][i];
420 }
421
422 }
423
424
425 int SimInfo::getNDF(){
426 int ndf_local;
427
428 ndf_local = 3 * n_atoms + 3 * n_oriented - n_constraints;
429
430 #ifdef IS_MPI
431 MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
432 #else
433 ndf = ndf_local;
434 #endif
435
436 ndf = ndf - 3 - nZconstraints;
437
438 return ndf;
439 }
440
441 int SimInfo::getNDFraw() {
442 int ndfRaw_local;
443
444 // Raw degrees of freedom that we have to set
445 ndfRaw_local = 3 * n_atoms + 3 * n_oriented;
446
447 #ifdef IS_MPI
448 MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
449 #else
450 ndfRaw = ndfRaw_local;
451 #endif
452
453 return ndfRaw;
454 }
455
456 int SimInfo::getNDFtranslational() {
457 int ndfTrans_local;
458
459 ndfTrans_local = 3 * n_atoms - n_constraints;
460
461 #ifdef IS_MPI
462 MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
463 #else
464 ndfTrans = ndfTrans_local;
465 #endif
466
467 ndfTrans = ndfTrans - 3 - nZconstraints;
468
469 return ndfTrans;
470 }
471
472 void SimInfo::refreshSim(){
473
474 simtype fInfo;
475 int isError;
476 int n_global;
477 int* excl;
478
479 fInfo.dielect = 0.0;
480
481 if( useDipole ){
482 if( useReactionField )fInfo.dielect = dielectric;
483 }
484
485 fInfo.SIM_uses_PBC = usePBC;
486 //fInfo.SIM_uses_LJ = 0;
487 fInfo.SIM_uses_LJ = useLJ;
488 fInfo.SIM_uses_sticky = useSticky;
489 //fInfo.SIM_uses_sticky = 0;
490 fInfo.SIM_uses_dipoles = useDipole;
491 //fInfo.SIM_uses_dipoles = 0;
492 //fInfo.SIM_uses_RF = useReactionField;
493 fInfo.SIM_uses_RF = 0;
494 fInfo.SIM_uses_GB = useGB;
495 fInfo.SIM_uses_EAM = useEAM;
496
497 excl = Exclude::getArray();
498
499 #ifdef IS_MPI
500 n_global = mpiSim->getTotAtoms();
501 #else
502 n_global = n_atoms;
503 #endif
504
505 isError = 0;
506
507 setFsimulation( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
508 &nGlobalExcludes, globalExcludes, molMembershipArray,
509 &isError );
510
511 if( isError ){
512
513 sprintf( painCave.errMsg,
514 "There was an error setting the simulation information in fortran.\n" );
515 painCave.isFatal = 1;
516 simError();
517 }
518
519 #ifdef IS_MPI
520 sprintf( checkPointMsg,
521 "succesfully sent the simulation information to fortran.\n");
522 MPIcheckPoint();
523 #endif // is_mpi
524
525 this->ndf = this->getNDF();
526 this->ndfRaw = this->getNDFraw();
527 this->ndfTrans = this->getNDFtranslational();
528 }
529
530
531 void SimInfo::setRcut( double theRcut ){
532
533 rCut = theRcut;
534 checkCutOffs();
535 }
536
537 void SimInfo::setDefaultRcut( double theRcut ){
538
539 haveOrigRcut = 1;
540 origRcut = theRcut;
541 rCut = theRcut;
542
543 ( rCut > ecr )? rList = rCut + 1.0: rList = ecr + 1.0;
544
545 notifyFortranCutOffs( &rCut, &rList, &ecr, &est );
546 }
547
548 void SimInfo::setEcr( double theEcr ){
549
550 ecr = theEcr;
551 checkCutOffs();
552 }
553
554 void SimInfo::setDefaultEcr( double theEcr ){
555
556 haveOrigEcr = 1;
557 origEcr = theEcr;
558
559 ( rCut > ecr )? rList = rCut + 1.0: rList = ecr + 1.0;
560
561 ecr = theEcr;
562
563 notifyFortranCutOffs( &rCut, &rList, &ecr, &est );
564 }
565
566 void SimInfo::setEcr( double theEcr, double theEst ){
567
568 est = theEst;
569 setEcr( theEcr );
570 }
571
572 void SimInfo::setDefaultEcr( double theEcr, double theEst ){
573
574 est = theEst;
575 setDefaultEcr( theEcr );
576 }
577
578
579 void SimInfo::checkCutOffs( void ){
580
581 int cutChanged = 0;
582
583 if( boxIsInit ){
584
585 //we need to check cutOffs against the box
586
587 //detect the change of rCut
588 if(( maxCutoff > rCut )&&(usePBC)){
589 if( rCut < origRcut ){
590 rCut = origRcut;
591
592 if (rCut > maxCutoff)
593 rCut = maxCutoff;
594
595 sprintf( painCave.errMsg,
596 "New Box size is setting the long range cutoff radius "
597 "to %lf at time %lf\n",
598 rCut, currentTime );
599 painCave.isFatal = 0;
600 simError();
601 }
602 }
603 else if ((rCut > maxCutoff)&&(usePBC)) {
604 sprintf( painCave.errMsg,
605 "New Box size is setting the long range cutoff radius "
606 "to %lf at time %lf\n",
607 maxCutoff, currentTime );
608 painCave.isFatal = 0;
609 simError();
610 rCut = maxCutoff;
611 }
612
613
614 //detect the change of ecr
615 if( maxCutoff > ecr ){
616 if( ecr < origEcr ){
617 ecr = origEcr;
618 if (ecr > maxCutoff) ecr = maxCutoff;
619
620 sprintf( painCave.errMsg,
621 "New Box size is setting the electrostaticCutoffRadius "
622 "to %lf at time %lf\n",
623 ecr, currentTime );
624 painCave.isFatal = 0;
625 simError();
626 }
627 }
628 else if( ecr > maxCutoff){
629 sprintf( painCave.errMsg,
630 "New Box size is setting the electrostaticCutoffRadius "
631 "to %lf at time %lf\n",
632 maxCutoff, currentTime );
633 painCave.isFatal = 0;
634 simError();
635 ecr = maxCutoff;
636 }
637
638 if( (oldEcr != ecr) || ( oldRcut != rCut ) ) cutChanged = 1;
639
640 // rlist is the 1.0 plus max( rcut, ecr )
641
642 ( rCut > ecr )? rList = rCut + 1.0: rList = ecr + 1.0;
643
644 if( cutChanged ){
645 notifyFortranCutOffs( &rCut, &rList, &ecr, &est );
646 }
647
648 oldEcr = ecr;
649 oldRcut = rCut;
650
651 } else {
652 // initialize this stuff before using it, OK?
653 sprintf( painCave.errMsg,
654 "Trying to check cutoffs without a box. Be smarter.\n" );
655 painCave.isFatal = 1;
656 simError();
657 }
658
659 }
660
661 void SimInfo::addProperty(GenericData* prop){
662
663 map<string, GenericData*>::iterator result;
664 result = properties.find(prop->getID());
665
666 //we can't simply use properties[prop->getID()] = prop,
667 //it will cause memory leak if we already contain a propery which has the same name of prop
668
669 if(result != properties.end()){
670
671 delete (*result).second;
672 (*result).second = prop;
673
674 }
675 else{
676
677 properties[prop->getID()] = prop;
678
679 }
680
681 }
682
683 GenericData* SimInfo::getProperty(const string& propName){
684
685 map<string, GenericData*>::iterator result;
686
687 //string lowerCaseName = ();
688
689 result = properties.find(propName);
690
691 if(result != properties.end())
692 return (*result).second;
693 else
694 return NULL;
695 }
696
697 vector<GenericData*> SimInfo::getProperties(){
698
699 vector<GenericData*> result;
700 map<string, GenericData*>::iterator i;
701
702 for(i = properties.begin(); i != properties.end(); i++)
703 result.push_back((*i).second);
704
705 return result;
706 }
707
708 double SimInfo::matTrace3(double m[3][3]){
709 double trace;
710 trace = m[0][0] + m[1][1] + m[2][2];
711
712 return trace;
713 }