ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 1212
Committed: Tue Jun 1 17:15:43 2004 UTC (20 years, 11 months ago) by chrisfen
File size: 13886 byte(s)
Log Message:
Implemented a separate solid and liquid thermodynamic integration routines

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 #include "MatVec3.h"
16
17 #ifdef IS_MPI
18 #include "mpiSimulation.hpp"
19 #endif
20
21 inline double roundMe( double x ){
22 return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
23 }
24
25 inline double min( double a, double b ){
26 return (a < b ) ? a : b;
27 }
28
29 SimInfo* currentInfo;
30
31 SimInfo::SimInfo(){
32
33 n_constraints = 0;
34 nZconstraints = 0;
35 n_oriented = 0;
36 n_dipoles = 0;
37 ndf = 0;
38 ndfRaw = 0;
39 nZconstraints = 0;
40 the_integrator = NULL;
41 setTemp = 0;
42 thermalTime = 0.0;
43 currentTime = 0.0;
44 rCut = 0.0;
45 rSw = 0.0;
46
47 haveRcut = 0;
48 haveRsw = 0;
49 boxIsInit = 0;
50
51 resetTime = 1e99;
52
53 orthoRhombic = 0;
54 orthoTolerance = 1E-6;
55 useInitXSstate = true;
56
57 usePBC = 0;
58 useLJ = 0;
59 useSticky = 0;
60 useCharges = 0;
61 useDipoles = 0;
62 useReactionField = 0;
63 useGB = 0;
64 useEAM = 0;
65 useSolidThermInt = 0;
66 useLiquidThermInt = 0;
67
68 haveCutoffGroups = false;
69
70 excludes = Exclude::Instance();
71
72 myConfiguration = new SimState();
73
74 has_minimizer = false;
75 the_minimizer =NULL;
76
77 ngroup = 0;
78
79 wrapMeSimInfo( this );
80 }
81
82
83 SimInfo::~SimInfo(){
84
85 delete myConfiguration;
86
87 map<string, GenericData*>::iterator i;
88
89 for(i = properties.begin(); i != properties.end(); i++)
90 delete (*i).second;
91
92 }
93
94 void SimInfo::setBox(double newBox[3]) {
95
96 int i, j;
97 double tempMat[3][3];
98
99 for(i=0; i<3; i++)
100 for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
101
102 tempMat[0][0] = newBox[0];
103 tempMat[1][1] = newBox[1];
104 tempMat[2][2] = newBox[2];
105
106 setBoxM( tempMat );
107
108 }
109
110 void SimInfo::setBoxM( double theBox[3][3] ){
111
112 int i, j;
113 double FortranHmat[9]; // to preserve compatibility with Fortran the
114 // ordering in the array is as follows:
115 // [ 0 3 6 ]
116 // [ 1 4 7 ]
117 // [ 2 5 8 ]
118 double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
119
120 if( !boxIsInit ) boxIsInit = 1;
121
122 for(i=0; i < 3; i++)
123 for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
124
125 calcBoxL();
126 calcHmatInv();
127
128 for(i=0; i < 3; i++) {
129 for (j=0; j < 3; j++) {
130 FortranHmat[3*j + i] = Hmat[i][j];
131 FortranHmatInv[3*j + i] = HmatInv[i][j];
132 }
133 }
134
135 setFortranBoxSize(FortranHmat, FortranHmatInv, &orthoRhombic);
136
137 }
138
139
140 void SimInfo::getBoxM (double theBox[3][3]) {
141
142 int i, j;
143 for(i=0; i<3; i++)
144 for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
145 }
146
147
148 void SimInfo::scaleBox(double scale) {
149 double theBox[3][3];
150 int i, j;
151
152 // cerr << "Scaling box by " << scale << "\n";
153
154 for(i=0; i<3; i++)
155 for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
156
157 setBoxM(theBox);
158
159 }
160
161 void SimInfo::calcHmatInv( void ) {
162
163 int oldOrtho;
164 int i,j;
165 double smallDiag;
166 double tol;
167 double sanity[3][3];
168
169 invertMat3( Hmat, HmatInv );
170
171 // check to see if Hmat is orthorhombic
172
173 oldOrtho = orthoRhombic;
174
175 smallDiag = fabs(Hmat[0][0]);
176 if(smallDiag > fabs(Hmat[1][1])) smallDiag = fabs(Hmat[1][1]);
177 if(smallDiag > fabs(Hmat[2][2])) smallDiag = fabs(Hmat[2][2]);
178 tol = smallDiag * orthoTolerance;
179
180 orthoRhombic = 1;
181
182 for (i = 0; i < 3; i++ ) {
183 for (j = 0 ; j < 3; j++) {
184 if (i != j) {
185 if (orthoRhombic) {
186 if ( fabs(Hmat[i][j]) >= tol) orthoRhombic = 0;
187 }
188 }
189 }
190 }
191
192 if( oldOrtho != orthoRhombic ){
193
194 if( orthoRhombic ){
195 sprintf( painCave.errMsg,
196 "OOPSE is switching from the default Non-Orthorhombic\n"
197 "\tto the faster Orthorhombic periodic boundary computations.\n"
198 "\tThis is usually a good thing, but if you wan't the\n"
199 "\tNon-Orthorhombic computations, make the orthoBoxTolerance\n"
200 "\tvariable ( currently set to %G ) smaller.\n",
201 orthoTolerance);
202 simError();
203 }
204 else {
205 sprintf( painCave.errMsg,
206 "OOPSE is switching from the faster Orthorhombic to the more\n"
207 "\tflexible Non-Orthorhombic periodic boundary computations.\n"
208 "\tThis is usually because the box has deformed under\n"
209 "\tNPTf integration. If you wan't to live on the edge with\n"
210 "\tthe Orthorhombic computations, make the orthoBoxTolerance\n"
211 "\tvariable ( currently set to %G ) larger.\n",
212 orthoTolerance);
213 simError();
214 }
215 }
216 }
217
218 void SimInfo::calcBoxL( void ){
219
220 double dx, dy, dz, dsq;
221
222 // boxVol = Determinant of Hmat
223
224 boxVol = matDet3( Hmat );
225
226 // boxLx
227
228 dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
229 dsq = dx*dx + dy*dy + dz*dz;
230 boxL[0] = sqrt( dsq );
231 //maxCutoff = 0.5 * boxL[0];
232
233 // boxLy
234
235 dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
236 dsq = dx*dx + dy*dy + dz*dz;
237 boxL[1] = sqrt( dsq );
238 //if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
239
240
241 // boxLz
242
243 dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
244 dsq = dx*dx + dy*dy + dz*dz;
245 boxL[2] = sqrt( dsq );
246 //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
247
248 //calculate the max cutoff
249 maxCutoff = calcMaxCutOff();
250
251 checkCutOffs();
252
253 }
254
255
256 double SimInfo::calcMaxCutOff(){
257
258 double ri[3], rj[3], rk[3];
259 double rij[3], rjk[3], rki[3];
260 double minDist;
261
262 ri[0] = Hmat[0][0];
263 ri[1] = Hmat[1][0];
264 ri[2] = Hmat[2][0];
265
266 rj[0] = Hmat[0][1];
267 rj[1] = Hmat[1][1];
268 rj[2] = Hmat[2][1];
269
270 rk[0] = Hmat[0][2];
271 rk[1] = Hmat[1][2];
272 rk[2] = Hmat[2][2];
273
274 crossProduct3(ri, rj, rij);
275 distXY = dotProduct3(rk,rij) / norm3(rij);
276
277 crossProduct3(rj,rk, rjk);
278 distYZ = dotProduct3(ri,rjk) / norm3(rjk);
279
280 crossProduct3(rk,ri, rki);
281 distZX = dotProduct3(rj,rki) / norm3(rki);
282
283 minDist = min(min(distXY, distYZ), distZX);
284 return minDist/2;
285
286 }
287
288 void SimInfo::wrapVector( double thePos[3] ){
289
290 int i;
291 double scaled[3];
292
293 if( !orthoRhombic ){
294 // calc the scaled coordinates.
295
296
297 matVecMul3(HmatInv, thePos, scaled);
298
299 for(i=0; i<3; i++)
300 scaled[i] -= roundMe(scaled[i]);
301
302 // calc the wrapped real coordinates from the wrapped scaled coordinates
303
304 matVecMul3(Hmat, scaled, thePos);
305
306 }
307 else{
308 // calc the scaled coordinates.
309
310 for(i=0; i<3; i++)
311 scaled[i] = thePos[i]*HmatInv[i][i];
312
313 // wrap the scaled coordinates
314
315 for(i=0; i<3; i++)
316 scaled[i] -= roundMe(scaled[i]);
317
318 // calc the wrapped real coordinates from the wrapped scaled coordinates
319
320 for(i=0; i<3; i++)
321 thePos[i] = scaled[i]*Hmat[i][i];
322 }
323
324 }
325
326
327 int SimInfo::getNDF(){
328 int ndf_local;
329
330 ndf_local = 0;
331
332 for(int i = 0; i < integrableObjects.size(); i++){
333 ndf_local += 3;
334 if (integrableObjects[i]->isDirectional()) {
335 if (integrableObjects[i]->isLinear())
336 ndf_local += 2;
337 else
338 ndf_local += 3;
339 }
340 }
341
342 // n_constraints is local, so subtract them on each processor:
343
344 ndf_local -= n_constraints;
345
346 #ifdef IS_MPI
347 MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
348 #else
349 ndf = ndf_local;
350 #endif
351
352 // nZconstraints is global, as are the 3 COM translations for the
353 // entire system:
354
355 ndf = ndf - 3 - nZconstraints;
356
357 return ndf;
358 }
359
360 int SimInfo::getNDFraw() {
361 int ndfRaw_local;
362
363 // Raw degrees of freedom that we have to set
364 ndfRaw_local = 0;
365
366 for(int i = 0; i < integrableObjects.size(); i++){
367 ndfRaw_local += 3;
368 if (integrableObjects[i]->isDirectional()) {
369 if (integrableObjects[i]->isLinear())
370 ndfRaw_local += 2;
371 else
372 ndfRaw_local += 3;
373 }
374 }
375
376 #ifdef IS_MPI
377 MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
378 #else
379 ndfRaw = ndfRaw_local;
380 #endif
381
382 return ndfRaw;
383 }
384
385 int SimInfo::getNDFtranslational() {
386 int ndfTrans_local;
387
388 ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
389
390
391 #ifdef IS_MPI
392 MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
393 #else
394 ndfTrans = ndfTrans_local;
395 #endif
396
397 ndfTrans = ndfTrans - 3 - nZconstraints;
398
399 return ndfTrans;
400 }
401
402 int SimInfo::getTotIntegrableObjects() {
403 int nObjs_local;
404 int nObjs;
405
406 nObjs_local = integrableObjects.size();
407
408
409 #ifdef IS_MPI
410 MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
411 #else
412 nObjs = nObjs_local;
413 #endif
414
415
416 return nObjs;
417 }
418
419 void SimInfo::refreshSim(){
420
421 simtype fInfo;
422 int isError;
423 int n_global;
424 int* excl;
425
426 fInfo.dielect = 0.0;
427
428 if( useDipoles ){
429 if( useReactionField )fInfo.dielect = dielectric;
430 }
431
432 fInfo.SIM_uses_PBC = usePBC;
433 //fInfo.SIM_uses_LJ = 0;
434 fInfo.SIM_uses_LJ = useLJ;
435 fInfo.SIM_uses_sticky = useSticky;
436 //fInfo.SIM_uses_sticky = 0;
437 fInfo.SIM_uses_charges = useCharges;
438 fInfo.SIM_uses_dipoles = useDipoles;
439 //fInfo.SIM_uses_dipoles = 0;
440 fInfo.SIM_uses_RF = useReactionField;
441 //fInfo.SIM_uses_RF = 0;
442 fInfo.SIM_uses_GB = useGB;
443 fInfo.SIM_uses_EAM = useEAM;
444
445 n_exclude = excludes->getSize();
446 excl = excludes->getFortranArray();
447
448 #ifdef IS_MPI
449 n_global = mpiSim->getNAtomsGlobal();
450 #else
451 n_global = n_atoms;
452 #endif
453
454 isError = 0;
455
456 getFortranGroupArray(this, mfact, ngroup, groupList, groupStart);
457 //it may not be a good idea to pass the address of first element in vector
458 //since c++ standard does not require vector to be stored continuously in meomory
459 //Most of the compilers will organize the memory of vector continuously
460 setFsimulation( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
461 &nGlobalExcludes, globalExcludes, molMembershipArray,
462 &mfact[0], &ngroup, &groupList[0], &groupStart[0], &isError);
463
464 if( isError ){
465
466 sprintf( painCave.errMsg,
467 "There was an error setting the simulation information in fortran.\n" );
468 painCave.isFatal = 1;
469 simError();
470 }
471
472 #ifdef IS_MPI
473 sprintf( checkPointMsg,
474 "succesfully sent the simulation information to fortran.\n");
475 MPIcheckPoint();
476 #endif // is_mpi
477
478 this->ndf = this->getNDF();
479 this->ndfRaw = this->getNDFraw();
480 this->ndfTrans = this->getNDFtranslational();
481 }
482
483 void SimInfo::setDefaultRcut( double theRcut ){
484
485 haveRcut = 1;
486 rCut = theRcut;
487 rList = rCut + 1.0;
488
489 notifyFortranCutOffs( &rCut, &rSw, &rList );
490 }
491
492 void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
493
494 rSw = theRsw;
495 setDefaultRcut( theRcut );
496 }
497
498
499 void SimInfo::checkCutOffs( void ){
500
501 if( boxIsInit ){
502
503 //we need to check cutOffs against the box
504
505 if( rCut > maxCutoff ){
506 sprintf( painCave.errMsg,
507 "cutoffRadius is too large for the current periodic box.\n"
508 "\tCurrent Value of cutoffRadius = %G at time %G\n "
509 "\tThis is larger than half of at least one of the\n"
510 "\tperiodic box vectors. Right now, the Box matrix is:\n"
511 "\n"
512 "\t[ %G %G %G ]\n"
513 "\t[ %G %G %G ]\n"
514 "\t[ %G %G %G ]\n",
515 rCut, currentTime,
516 Hmat[0][0], Hmat[0][1], Hmat[0][2],
517 Hmat[1][0], Hmat[1][1], Hmat[1][2],
518 Hmat[2][0], Hmat[2][1], Hmat[2][2]);
519 painCave.isFatal = 1;
520 simError();
521 }
522 } else {
523 // initialize this stuff before using it, OK?
524 sprintf( painCave.errMsg,
525 "Trying to check cutoffs without a box.\n"
526 "\tOOPSE should have better programmers than that.\n" );
527 painCave.isFatal = 1;
528 simError();
529 }
530
531 }
532
533 void SimInfo::addProperty(GenericData* prop){
534
535 map<string, GenericData*>::iterator result;
536 result = properties.find(prop->getID());
537
538 //we can't simply use properties[prop->getID()] = prop,
539 //it will cause memory leak if we already contain a propery which has the same name of prop
540
541 if(result != properties.end()){
542
543 delete (*result).second;
544 (*result).second = prop;
545
546 }
547 else{
548
549 properties[prop->getID()] = prop;
550
551 }
552
553 }
554
555 GenericData* SimInfo::getProperty(const string& propName){
556
557 map<string, GenericData*>::iterator result;
558
559 //string lowerCaseName = ();
560
561 result = properties.find(propName);
562
563 if(result != properties.end())
564 return (*result).second;
565 else
566 return NULL;
567 }
568
569
570 void getFortranGroupArray(SimInfo* info, vector<double>& mfact, int& ngroup,
571 vector<int>& groupList, vector<int>& groupStart){
572 Molecule* myMols;
573 Atom** myAtoms;
574 int numAtom;
575 int curIndex;
576 double mtot;
577 int numMol;
578 int numCutoffGroups;
579 CutoffGroup* myCutoffGroup;
580 vector<CutoffGroup*>::iterator iterCutoff;
581 Atom* cutoffAtom;
582 vector<Atom*>::iterator iterAtom;
583 int atomIndex;
584 double totalMass;
585
586 mfact.clear();
587 groupList.clear();
588 groupStart.clear();
589
590 //Be careful, fortran array begin at 1
591 curIndex = 1;
592
593 myMols = info->molecules;
594 numMol = info->n_mol;
595 for(int i = 0; i < numMol; i++){
596 numCutoffGroups = myMols[i].getNCutoffGroups();
597 for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff); myCutoffGroup != NULL;
598 myCutoffGroup =myMols[i].nextCutoffGroup(iterCutoff)){
599
600 totalMass = myCutoffGroup->getMass();
601
602 for(cutoffAtom = myCutoffGroup->beginAtom(iterAtom); cutoffAtom != NULL;
603 cutoffAtom = myCutoffGroup->nextAtom(iterAtom)){
604 mfact.push_back(cutoffAtom->getMass()/totalMass);
605 #ifdef IS_MPI
606 groupList.push_back(cutoffAtom->getGlobalIndex() + 1);
607 #else
608 groupList.push_back(cutoffAtom->getIndex() + 1);
609 #endif
610 }
611
612 groupStart.push_back(curIndex);
613 curIndex += myCutoffGroup->getNumAtom();
614
615 }//end for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff))
616
617 }//end for(int i = 0; i < numMol; i++)
618
619
620 //The last cutoff group need more element to indicate the end of the cutoff
621 ngroup = groupStart.size();
622 }