ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 1144
Committed: Sat May 1 18:52:38 2004 UTC (20 years, 2 months ago) by tim
File size: 14199 byte(s)
Log Message:
C++ pass groupList to fortran

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