ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 626
Committed: Wed Jul 16 21:30:56 2003 UTC (20 years, 11 months ago) by mmeineke
File size: 10814 byte(s)
Log Message:
Changed how cutoffs were handled from C. Now notifyCutoffs in Fortran notifies those who need the information of any changes to cutoffs.

File Contents

# Content
1 #include <cstdlib>
2 #include <cstring>
3 #include <cmath>
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 #ifdef IS_MPI
16 #include "mpiSimulation.hpp"
17 #endif
18
19 inline double roundMe( double x ){
20 return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
21 }
22
23
24 SimInfo* currentInfo;
25
26 SimInfo::SimInfo(){
27 excludes = NULL;
28 n_constraints = 0;
29 n_oriented = 0;
30 n_dipoles = 0;
31 ndf = 0;
32 ndfRaw = 0;
33 the_integrator = NULL;
34 setTemp = 0;
35 thermalTime = 0.0;
36 rCut = 0.0;
37 ecr = 0.0;
38 est = 0.0;
39 oldEcr = 0.0;
40 oldRcut = 0.0;
41
42 haveOrigRcut = 0;
43 haveOrigEcr = 0;
44 boxIsInit = 0;
45
46
47
48 usePBC = 0;
49 useLJ = 0;
50 useSticky = 0;
51 useDipole = 0;
52 useReactionField = 0;
53 useGB = 0;
54 useEAM = 0;
55
56 wrapMeSimInfo( this );
57 }
58
59 void SimInfo::setBox(double newBox[3]) {
60
61 int i, j;
62 double tempMat[3][3];
63
64 for(i=0; i<3; i++)
65 for (j=0; j<3; j++) tempMat[i][j] = 0.0;;
66
67 tempMat[0][0] = newBox[0];
68 tempMat[1][1] = newBox[1];
69 tempMat[2][2] = newBox[2];
70
71 setBoxM( tempMat );
72
73 }
74
75 void SimInfo::setBoxM( double theBox[3][3] ){
76
77 int i, j, status;
78 double smallestBoxL, maxCutoff;
79 double FortranHmat[9]; // to preserve compatibility with Fortran the
80 // ordering in the array is as follows:
81 // [ 0 3 6 ]
82 // [ 1 4 7 ]
83 // [ 2 5 8 ]
84 double FortranHmatInv[9]; // the inverted Hmat (for Fortran);
85
86
87 if( !boxIsInit ) boxIsInit = 1;
88
89 for(i=0; i < 3; i++)
90 for (j=0; j < 3; j++) Hmat[i][j] = theBox[i][j];
91
92 calcBoxL();
93 calcHmatInv();
94
95 for(i=0; i < 3; i++) {
96 for (j=0; j < 3; j++) {
97 FortranHmat[3*j + i] = Hmat[i][j];
98 FortranHmatInv[3*j + i] = HmatInv[i][j];
99 }
100 }
101
102 setFortranBoxSize(FortranHmat, FortranHmatInv, &orthoRhombic);
103
104 }
105
106
107 void SimInfo::getBoxM (double theBox[3][3]) {
108
109 int i, j;
110 for(i=0; i<3; i++)
111 for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j];
112 }
113
114
115 void SimInfo::scaleBox(double scale) {
116 double theBox[3][3];
117 int i, j;
118
119 // cerr << "Scaling box by " << scale << "\n";
120
121 for(i=0; i<3; i++)
122 for (j=0; j<3; j++) theBox[i][j] = Hmat[i][j]*scale;
123
124 setBoxM(theBox);
125
126 }
127
128 void SimInfo::calcHmatInv( void ) {
129
130 int i,j;
131 double smallDiag;
132 double tol;
133 double sanity[3][3];
134
135 invertMat3( Hmat, HmatInv );
136
137 // Check the inverse to make sure it is sane:
138
139 matMul3( Hmat, HmatInv, sanity );
140
141 // check to see if Hmat is orthorhombic
142
143 smallDiag = Hmat[0][0];
144 if(smallDiag > Hmat[1][1]) smallDiag = Hmat[1][1];
145 if(smallDiag > Hmat[2][2]) smallDiag = Hmat[2][2];
146 tol = smallDiag * 1E-6;
147
148 orthoRhombic = 1;
149
150 for (i = 0; i < 3; i++ ) {
151 for (j = 0 ; j < 3; j++) {
152 if (i != j) {
153 if (orthoRhombic) {
154 if (Hmat[i][j] >= tol) orthoRhombic = 0;
155 }
156 }
157 }
158 }
159 }
160
161 double SimInfo::matDet3(double a[3][3]) {
162 int i, j, k;
163 double determinant;
164
165 determinant = 0.0;
166
167 for(i = 0; i < 3; i++) {
168 j = (i+1)%3;
169 k = (i+2)%3;
170
171 determinant += a[0][i] * (a[1][j]*a[2][k] - a[1][k]*a[2][j]);
172 }
173
174 return determinant;
175 }
176
177 void SimInfo::invertMat3(double a[3][3], double b[3][3]) {
178
179 int i, j, k, l, m, n;
180 double determinant;
181
182 determinant = matDet3( a );
183
184 if (determinant == 0.0) {
185 sprintf( painCave.errMsg,
186 "Can't invert a matrix with a zero determinant!\n");
187 painCave.isFatal = 1;
188 simError();
189 }
190
191 for (i=0; i < 3; i++) {
192 j = (i+1)%3;
193 k = (i+2)%3;
194 for(l = 0; l < 3; l++) {
195 m = (l+1)%3;
196 n = (l+2)%3;
197
198 b[l][i] = (a[j][m]*a[k][n] - a[j][n]*a[k][m]) / determinant;
199 }
200 }
201 }
202
203 void SimInfo::matMul3(double a[3][3], double b[3][3], double c[3][3]) {
204 double r00, r01, r02, r10, r11, r12, r20, r21, r22;
205
206 r00 = a[0][0]*b[0][0] + a[0][1]*b[1][0] + a[0][2]*b[2][0];
207 r01 = a[0][0]*b[0][1] + a[0][1]*b[1][1] + a[0][2]*b[2][1];
208 r02 = a[0][0]*b[0][2] + a[0][1]*b[1][2] + a[0][2]*b[2][2];
209
210 r10 = a[1][0]*b[0][0] + a[1][1]*b[1][0] + a[1][2]*b[2][0];
211 r11 = a[1][0]*b[0][1] + a[1][1]*b[1][1] + a[1][2]*b[2][1];
212 r12 = a[1][0]*b[0][2] + a[1][1]*b[1][2] + a[1][2]*b[2][2];
213
214 r20 = a[2][0]*b[0][0] + a[2][1]*b[1][0] + a[2][2]*b[2][0];
215 r21 = a[2][0]*b[0][1] + a[2][1]*b[1][1] + a[2][2]*b[2][1];
216 r22 = a[2][0]*b[0][2] + a[2][1]*b[1][2] + a[2][2]*b[2][2];
217
218 c[0][0] = r00; c[0][1] = r01; c[0][2] = r02;
219 c[1][0] = r10; c[1][1] = r11; c[1][2] = r12;
220 c[2][0] = r20; c[2][1] = r21; c[2][2] = r22;
221 }
222
223 void SimInfo::matVecMul3(double m[3][3], double inVec[3], double outVec[3]) {
224 double a0, a1, a2;
225
226 a0 = inVec[0]; a1 = inVec[1]; a2 = inVec[2];
227
228 outVec[0] = m[0][0]*a0 + m[0][1]*a1 + m[0][2]*a2;
229 outVec[1] = m[1][0]*a0 + m[1][1]*a1 + m[1][2]*a2;
230 outVec[2] = m[2][0]*a0 + m[2][1]*a1 + m[2][2]*a2;
231 }
232
233 void SimInfo::transposeMat3(double in[3][3], double out[3][3]) {
234 double temp[3][3];
235 int i, j;
236
237 for (i = 0; i < 3; i++) {
238 for (j = 0; j < 3; j++) {
239 temp[j][i] = in[i][j];
240 }
241 }
242 for (i = 0; i < 3; i++) {
243 for (j = 0; j < 3; j++) {
244 out[i][j] = temp[i][j];
245 }
246 }
247 }
248
249 void SimInfo::printMat3(double A[3][3] ){
250
251 std::cerr
252 << "[ " << A[0][0] << ", " << A[0][1] << ", " << A[0][2] << " ]\n"
253 << "[ " << A[1][0] << ", " << A[1][1] << ", " << A[1][2] << " ]\n"
254 << "[ " << A[2][0] << ", " << A[2][1] << ", " << A[2][2] << " ]\n";
255 }
256
257 void SimInfo::printMat9(double A[9] ){
258
259 std::cerr
260 << "[ " << A[0] << ", " << A[1] << ", " << A[2] << " ]\n"
261 << "[ " << A[3] << ", " << A[4] << ", " << A[5] << " ]\n"
262 << "[ " << A[6] << ", " << A[7] << ", " << A[8] << " ]\n";
263 }
264
265 void SimInfo::calcBoxL( void ){
266
267 double dx, dy, dz, dsq;
268 int i;
269
270 // boxVol = Determinant of Hmat
271
272 boxVol = matDet3( Hmat );
273
274 // boxLx
275
276 dx = Hmat[0][0]; dy = Hmat[1][0]; dz = Hmat[2][0];
277 dsq = dx*dx + dy*dy + dz*dz;
278 boxL[0] = sqrt( dsq );
279 maxCutoff = 0.5 * boxL[0];
280
281 // boxLy
282
283 dx = Hmat[0][1]; dy = Hmat[1][1]; dz = Hmat[2][1];
284 dsq = dx*dx + dy*dy + dz*dz;
285 boxL[1] = sqrt( dsq );
286 if( (0.5 * boxL[1]) < maxCutoff ) maxCutoff = 0.5 * boxL[1];
287
288 // boxLz
289
290 dx = Hmat[0][2]; dy = Hmat[1][2]; dz = Hmat[2][2];
291 dsq = dx*dx + dy*dy + dz*dz;
292 boxL[2] = sqrt( dsq );
293 if( (0.5 * boxL[2]) < maxCutoff ) maxCutoff = 0.5 * boxL[2];
294
295 }
296
297
298 void SimInfo::wrapVector( double thePos[3] ){
299
300 int i, j, k;
301 double scaled[3];
302
303 if( !orthoRhombic ){
304 // calc the scaled coordinates.
305
306
307 matVecMul3(HmatInv, thePos, scaled);
308
309 for(i=0; i<3; i++)
310 scaled[i] -= roundMe(scaled[i]);
311
312 // calc the wrapped real coordinates from the wrapped scaled coordinates
313
314 matVecMul3(Hmat, scaled, thePos);
315
316 }
317 else{
318 // calc the scaled coordinates.
319
320 for(i=0; i<3; i++)
321 scaled[i] = thePos[i]*HmatInv[i][i];
322
323 // wrap the scaled coordinates
324
325 for(i=0; i<3; i++)
326 scaled[i] -= roundMe(scaled[i]);
327
328 // calc the wrapped real coordinates from the wrapped scaled coordinates
329
330 for(i=0; i<3; i++)
331 thePos[i] = scaled[i]*Hmat[i][i];
332 }
333
334 }
335
336
337 int SimInfo::getNDF(){
338 int ndf_local, ndf;
339
340 ndf_local = 3 * n_atoms + 3 * n_oriented - 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 ndf = ndf - 3;
349
350 return ndf;
351 }
352
353 int SimInfo::getNDFraw() {
354 int ndfRaw_local, ndfRaw;
355
356 // Raw degrees of freedom that we have to set
357 ndfRaw_local = 3 * n_atoms + 3 * n_oriented;
358
359 #ifdef IS_MPI
360 MPI_Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD);
361 #else
362 ndfRaw = ndfRaw_local;
363 #endif
364
365 return ndfRaw;
366 }
367
368 void SimInfo::refreshSim(){
369
370 simtype fInfo;
371 int isError;
372 int n_global;
373 int* excl;
374
375 fInfo.dielect = 0.0;
376
377 if( useDipole ){
378 if( useReactionField )fInfo.dielect = dielectric;
379 }
380
381 fInfo.SIM_uses_PBC = usePBC;
382 //fInfo.SIM_uses_LJ = 0;
383 fInfo.SIM_uses_LJ = useLJ;
384 fInfo.SIM_uses_sticky = useSticky;
385 //fInfo.SIM_uses_sticky = 0;
386 fInfo.SIM_uses_dipoles = useDipole;
387 //fInfo.SIM_uses_dipoles = 0;
388 //fInfo.SIM_uses_RF = useReactionField;
389 fInfo.SIM_uses_RF = 0;
390 fInfo.SIM_uses_GB = useGB;
391 fInfo.SIM_uses_EAM = useEAM;
392
393 excl = Exclude::getArray();
394
395 #ifdef IS_MPI
396 n_global = mpiSim->getTotAtoms();
397 #else
398 n_global = n_atoms;
399 #endif
400
401 isError = 0;
402
403 setFsimulation( &fInfo, &n_global, &n_atoms, identArray, &n_exclude, excl,
404 &nGlobalExcludes, globalExcludes, molMembershipArray,
405 &isError );
406
407 if( isError ){
408
409 sprintf( painCave.errMsg,
410 "There was an error setting the simulation information in fortran.\n" );
411 painCave.isFatal = 1;
412 simError();
413 }
414
415 #ifdef IS_MPI
416 sprintf( checkPointMsg,
417 "succesfully sent the simulation information to fortran.\n");
418 MPIcheckPoint();
419 #endif // is_mpi
420
421 this->ndf = this->getNDF();
422 this->ndfRaw = this->getNDFraw();
423
424 }
425
426
427 void SimInfo::setRcut( double theRcut ){
428
429 if( !haveOrigRcut ){
430 haveOrigRcut = 1;
431 origRcut = theRcut;
432 }
433
434 rCut = theRcut;
435 checkCutOffs();
436 }
437
438 void SimInfo::setEcr( double theEcr ){
439
440 if( !haveOrigEcr ){
441 haveOrigEcr = 1;
442 origEcr = theEcr;
443 }
444
445 ecr = theEcr;
446 checkCutOffs();
447 }
448
449 void SimInfo::setEcr( double theEcr, double theEst ){
450
451 est = theEst;
452 setEcr( theEcr );
453 }
454
455
456 void SimInfo::checkCutOffs( void ){
457
458 int cutChanged = 0;
459
460 if( boxIsInit ){
461
462 //we need to check cutOffs against the box
463
464 if( maxCutoff > rCut ){
465 if( rCut < origRcut ){
466 rCut = origRcut;
467 if (rCut > maxCutoff) rCut = maxCutoff;
468
469 sprintf( painCave.errMsg,
470 "New Box size is setting the long range cutoff radius "
471 "to %lf\n",
472 rCut );
473 painCave.isFatal = 0;
474 simError();
475 }
476 }
477
478 if( maxCutoff > ecr ){
479 if( ecr < origEcr ){
480 rCut = origEcr;
481 if (ecr > maxCutoff) ecr = maxCutoff;
482
483 sprintf( painCave.errMsg,
484 "New Box size is setting the electrostaticCutoffRadius "
485 "to %lf\n",
486 ecr );
487 painCave.isFatal = 0;
488 simError();
489 }
490 }
491
492
493 if (rCut > maxCutoff) {
494 sprintf( painCave.errMsg,
495 "New Box size is setting the long range cutoff radius "
496 "to %lf\n",
497 maxCutoff );
498 painCave.isFatal = 0;
499 simError();
500 rCut = maxCutoff;
501 }
502
503 if( ecr > maxCutoff){
504 sprintf( painCave.errMsg,
505 "New Box size is setting the electrostaticCutoffRadius "
506 "to %lf\n",
507 maxCutoff );
508 painCave.isFatal = 0;
509 simError();
510 ecr = maxCutoff;
511 }
512
513
514 }
515
516
517 if( (oldEcr != ecr) || ( oldRcut != rCut ) ) cutChanged = 1;
518
519 // rlist is the 1.0 plus max( rcut, ecr )
520
521 ( rCut > ecr )? rList = rCut + 1.0: rList = ecr + 1.0;
522
523 if( cutChanged ){
524
525 notifyFortranCutOffs( &rCut, &rList, &ecr, &est );
526 }
527
528 oldEcr = ecr;
529 oldRcut = rCut;
530 }