ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 642
Committed: Mon Jul 21 16:23:57 2003 UTC (20 years, 11 months ago) by mmeineke
File size: 10835 byte(s)
Log Message:
Initialized currentTime to 0, in case no one sets it.

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