ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 874
Committed: Fri Nov 21 20:10:02 2003 UTC (20 years, 7 months ago) by mmeineke
File size: 14060 byte(s)
Log Message:
added a more verbose error message in SimInfo. Added a more informative error message in InitializeFromFile

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