ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-2.0/src/brains/SimInfo.cpp
Revision: 1636
Committed: Fri Oct 22 22:54:01 2004 UTC (19 years, 8 months ago) by chrisfen
Original Path: trunk/OOPSE-2.0/src/brains/SimInfo.cpp
File size: 14181 byte(s)
Log Message:
fixey fixey the breakey breakey

File Contents

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