ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 859
Committed: Mon Nov 10 21:50:36 2003 UTC (20 years, 8 months ago) by mmeineke
File size: 13601 byte(s)
Log Message:
reordered the rcut/ecr/boxSize initialization

removed the rcut/ecr shrink and grow algorithm. the simulation will now exit when it runs into rcut or ecr.

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