ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 1218
Committed: Wed Jun 2 14:21:54 2004 UTC (20 years, 2 months ago) by gezelter
File size: 13700 byte(s)
Log Message:
severity levels in simError

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 "\n\tOOPSE 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 painCave.severity = OOPSE_INFO;
203 simError();
204 }
205 else {
206 sprintf( painCave.errMsg,
207 "\n\tOOPSE is switching from the faster Orthorhombic to the more\n"
208 "\tflexible Non-Orthorhombic periodic boundary computations.\n"
209 "\tThis is usually because the box has deformed under\n"
210 "\tNPTf integration. If you wan't to live on the edge with\n"
211 "\tthe Orthorhombic computations, make the orthoBoxTolerance\n"
212 "\tvariable ( currently set to %G ) larger.\n",
213 orthoTolerance);
214 painCave.severity = OOPSE_WARNING;
215 simError();
216 }
217 }
218 }
219
220 void SimInfo::calcBoxL( void ){
221
222 double dx, dy, dz, dsq;
223
224 // boxVol = Determinant of Hmat
225
226 boxVol = matDet3( Hmat );
227
228 // boxLx
229
230 dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
231 dsq = dx*dx + dy*dy + dz*dz;
232 boxL[0] = sqrt( dsq );
233 //maxCutoff = 0.5 * boxL[0];
234
235 // boxLy
236
237 dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
238 dsq = dx*dx + dy*dy + dz*dz;
239 boxL[1] = sqrt( dsq );
240 //if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
241
242
243 // boxLz
244
245 dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
246 dsq = dx*dx + dy*dy + dz*dz;
247 boxL[2] = sqrt( dsq );
248 //if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
249
250 //calculate the max cutoff
251 maxCutoff = calcMaxCutOff();
252
253 checkCutOffs();
254
255 }
256
257
258 double SimInfo::calcMaxCutOff(){
259
260 double ri[3], rj[3], rk[3];
261 double rij[3], rjk[3], rki[3];
262 double minDist;
263
264 ri[0] = Hmat[0][0];
265 ri[1] = Hmat[1][0];
266 ri[2] = Hmat[2][0];
267
268 rj[0] = Hmat[0][1];
269 rj[1] = Hmat[1][1];
270 rj[2] = Hmat[2][1];
271
272 rk[0] = Hmat[0][2];
273 rk[1] = Hmat[1][2];
274 rk[2] = Hmat[2][2];
275
276 crossProduct3(ri, rj, rij);
277 distXY = dotProduct3(rk,rij) / norm3(rij);
278
279 crossProduct3(rj,rk, rjk);
280 distYZ = dotProduct3(ri,rjk) / norm3(rjk);
281
282 crossProduct3(rk,ri, rki);
283 distZX = dotProduct3(rj,rki) / norm3(rki);
284
285 minDist = min(min(distXY, distYZ), distZX);
286 return minDist/2;
287
288 }
289
290 void SimInfo::wrapVector( double thePos[3] ){
291
292 int i;
293 double scaled[3];
294
295 if( !orthoRhombic ){
296 // calc the scaled coordinates.
297
298
299 matVecMul3(HmatInv, thePos, scaled);
300
301 for(i=0; i<3; i++)
302 scaled[i] -= roundMe(scaled[i]);
303
304 // calc the wrapped real coordinates from the wrapped scaled coordinates
305
306 matVecMul3(Hmat, scaled, thePos);
307
308 }
309 else{
310 // calc the scaled coordinates.
311
312 for(i=0; i<3; i++)
313 scaled[i] = thePos[i]*HmatInv[i][i];
314
315 // wrap the scaled coordinates
316
317 for(i=0; i<3; i++)
318 scaled[i] -= roundMe(scaled[i]);
319
320 // calc the wrapped real coordinates from the wrapped scaled coordinates
321
322 for(i=0; i<3; i++)
323 thePos[i] = scaled[i]*Hmat[i][i];
324 }
325
326 }
327
328
329 int SimInfo::getNDF(){
330 int ndf_local;
331
332 ndf_local = 0;
333
334 for(int i = 0; i < integrableObjects.size(); i++){
335 ndf_local += 3;
336 if (integrableObjects[i]->isDirectional()) {
337 if (integrableObjects[i]->isLinear())
338 ndf_local += 2;
339 else
340 ndf_local += 3;
341 }
342 }
343
344 // n_constraints is local, so subtract them on each processor:
345
346 ndf_local -= n_constraints;
347
348 #ifdef IS_MPI
349 MPI_Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
350 #else
351 ndf = ndf_local;
352 #endif
353
354 // nZconstraints is global, as are the 3 COM translations for the
355 // entire system:
356
357 ndf = ndf - 3 - nZconstraints;
358
359 return ndf;
360 }
361
362 int SimInfo::getNDFraw() {
363 int ndfRaw_local;
364
365 // Raw degrees of freedom that we have to set
366 ndfRaw_local = 0;
367
368 for(int i = 0; i < integrableObjects.size(); i++){
369 ndfRaw_local += 3;
370 if (integrableObjects[i]->isDirectional()) {
371 if (integrableObjects[i]->isLinear())
372 ndfRaw_local += 2;
373 else
374 ndfRaw_local += 3;
375 }
376 }
377
378 #ifdef IS_MPI
379 MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
380 #else
381 ndfRaw = ndfRaw_local;
382 #endif
383
384 return ndfRaw;
385 }
386
387 int SimInfo::getNDFtranslational() {
388 int ndfTrans_local;
389
390 ndfTrans_local = 3 * integrableObjects.size() - n_constraints;
391
392
393 #ifdef IS_MPI
394 MPI_Allreduce(&ndfTrans_local,&ndfTrans,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
395 #else
396 ndfTrans = ndfTrans_local;
397 #endif
398
399 ndfTrans = ndfTrans - 3 - nZconstraints;
400
401 return ndfTrans;
402 }
403
404 int SimInfo::getTotIntegrableObjects() {
405 int nObjs_local;
406 int nObjs;
407
408 nObjs_local = integrableObjects.size();
409
410
411 #ifdef IS_MPI
412 MPI_Allreduce(&nObjs_local,&nObjs,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
413 #else
414 nObjs = nObjs_local;
415 #endif
416
417
418 return nObjs;
419 }
420
421 void SimInfo::refreshSim(){
422
423 simtype fInfo;
424 int isError;
425 int n_global;
426 int* excl;
427
428 fInfo.dielect = 0.0;
429
430 if( useDipoles ){
431 if( useReactionField )fInfo.dielect = dielectric;
432 }
433
434 fInfo.SIM_uses_PBC = usePBC;
435 //fInfo.SIM_uses_LJ = 0;
436 fInfo.SIM_uses_LJ = useLJ;
437 fInfo.SIM_uses_sticky = useSticky;
438 //fInfo.SIM_uses_sticky = 0;
439 fInfo.SIM_uses_charges = useCharges;
440 fInfo.SIM_uses_dipoles = useDipoles;
441 //fInfo.SIM_uses_dipoles = 0;
442 fInfo.SIM_uses_RF = useReactionField;
443 //fInfo.SIM_uses_RF = 0;
444 fInfo.SIM_uses_GB = useGB;
445 fInfo.SIM_uses_EAM = useEAM;
446
447 n_exclude = excludes->getSize();
448 excl = excludes->getFortranArray();
449
450 #ifdef IS_MPI
451 n_global = mpiSim->getNAtomsGlobal();
452 #else
453 n_global = n_atoms;
454 #endif
455
456 isError = 0;
457
458 getFortranGroupArrays(this, FglobalGroupMembership, mfact);
459 //it may not be a good idea to pass the address of first element in vector
460 //since c++ standard does not require vector to be stored continuously in meomory
461 //Most of the compilers will organize the memory of vector continuously
462 setFsimulation( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
463 &nGlobalExcludes, globalExcludes, molMembershipArray,
464 &mfact[0], &ngroup, &FglobalGroupMembership[0], &isError);
465
466 if( isError ){
467
468 sprintf( painCave.errMsg,
469 "There was an error setting the simulation information in fortran.\n" );
470 painCave.isFatal = 1;
471 simError();
472 }
473
474 #ifdef IS_MPI
475 sprintf( checkPointMsg,
476 "succesfully sent the simulation information to fortran.\n");
477 MPIcheckPoint();
478 #endif // is_mpi
479
480 this->ndf = this->getNDF();
481 this->ndfRaw = this->getNDFraw();
482 this->ndfTrans = this->getNDFtranslational();
483 }
484
485 void SimInfo::setDefaultRcut( double theRcut ){
486
487 haveRcut = 1;
488 rCut = theRcut;
489 rList = rCut + 1.0;
490
491 notifyFortranCutOffs( &rCut, &rSw, &rList );
492 }
493
494 void SimInfo::setDefaultRcut( double theRcut, double theRsw ){
495
496 rSw = theRsw;
497 setDefaultRcut( theRcut );
498 }
499
500
501 void SimInfo::checkCutOffs( void ){
502
503 if( boxIsInit ){
504
505 //we need to check cutOffs against the box
506
507 if( rCut > maxCutoff ){
508 sprintf( painCave.errMsg,
509 "\n\tcutoffRadius is too large for the current periodic box.\n"
510 "\tCurrent Value of cutoffRadius = %G at time %G\n "
511 "\tThis is larger than half of at least one of the\n"
512 "\tperiodic box vectors. Right now, the Box matrix is:\n"
513 "\n"
514 "\t[ %G %G %G ]\n"
515 "\t[ %G %G %G ]\n"
516 "\t[ %G %G %G ]\n",
517 rCut, currentTime,
518 Hmat[0][0], Hmat[0][1], Hmat[0][2],
519 Hmat[1][0], Hmat[1][1], Hmat[1][2],
520 Hmat[2][0], Hmat[2][1], Hmat[2][2]);
521 painCave.severity = OOPSE_ERROR;
522 painCave.isFatal = 1;
523 simError();
524 }
525 } else {
526 // initialize this stuff before using it, OK?
527 sprintf( painCave.errMsg,
528 "\n\tTrying to check cutoffs without a box.\n"
529 "\tOOPSE should have better programmers than that.\n" );
530 painCave.severity = OOPSE_ERROR;
531 painCave.isFatal = 1;
532 simError();
533 }
534
535 }
536
537 void SimInfo::addProperty(GenericData* prop){
538
539 map<string, GenericData*>::iterator result;
540 result = properties.find(prop->getID());
541
542 //we can't simply use properties[prop->getID()] = prop,
543 //it will cause memory leak if we already contain a propery which has the same name of prop
544
545 if(result != properties.end()){
546
547 delete (*result).second;
548 (*result).second = prop;
549
550 }
551 else{
552
553 properties[prop->getID()] = prop;
554
555 }
556
557 }
558
559 GenericData* SimInfo::getProperty(const string& propName){
560
561 map<string, GenericData*>::iterator result;
562
563 //string lowerCaseName = ();
564
565 result = properties.find(propName);
566
567 if(result != properties.end())
568 return (*result).second;
569 else
570 return NULL;
571 }
572
573
574 void SimInfo::getFortranGroupArrays(SimInfo* info,
575 vector<int>& FglobalGroupMembership,
576 vector<double>& mfact){
577
578 Molecule* myMols;
579 Atom** myAtoms;
580 int numAtom;
581 double mtot;
582 int numMol;
583 int numCutoffGroups;
584 CutoffGroup* myCutoffGroup;
585 vector<CutoffGroup*>::iterator iterCutoff;
586 Atom* cutoffAtom;
587 vector<Atom*>::iterator iterAtom;
588 int atomIndex;
589 double totalMass;
590
591 mfact.clear();
592 FglobalGroupMembership.clear();
593
594
595 // Fix the silly fortran indexing problem
596 #ifdef IS_MPI
597 numAtom = mpiSim->getNAtomsGlobal();
598 #else
599 numAtom = n_atoms;
600 #endif
601 for (int i = 0; i < numAtom; i++)
602 FglobalGroupMembership.push_back(globalGroupMembership[i] + 1);
603
604
605 myMols = info->molecules;
606 numMol = info->n_mol;
607 for(int i = 0; i < numMol; i++){
608 numCutoffGroups = myMols[i].getNCutoffGroups();
609 for(myCutoffGroup =myMols[i].beginCutoffGroup(iterCutoff);
610 myCutoffGroup != NULL;
611 myCutoffGroup =myMols[i].nextCutoffGroup(iterCutoff)){
612
613 totalMass = myCutoffGroup->getMass();
614
615 for(cutoffAtom = myCutoffGroup->beginAtom(iterAtom);
616 cutoffAtom != NULL;
617 cutoffAtom = myCutoffGroup->nextAtom(iterAtom)){
618 mfact.push_back(cutoffAtom->getMass()/totalMass);
619 }
620 }
621 }
622
623 }