ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 1234
Committed: Fri Jun 4 03:15:31 2004 UTC (20 years, 1 month ago) by tim
File size: 13812 byte(s)
Log Message:
new rattle algorithm is working

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