ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 1201
Committed: Thu May 27 15:31:36 2004 UTC (20 years, 1 month ago) by tim
File size: 13852 byte(s)
Log Message:
groupList new bases on global index of atoms

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