ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 1031
Committed: Fri Feb 6 18:58:06 2004 UTC (20 years, 5 months ago) by tim
File size: 14300 byte(s)
Log Message:
Add some lines into global.cpp to make it work with energy minimization

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