ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 1154
Committed: Tue May 11 16:00:22 2004 UTC (20 years, 11 months ago) by gezelter
File size: 13418 byte(s)
Log Message:
Fixes to libmdtools to use the simplified cutoff stuff in the BASS library

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