ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/SimInfo.cpp
Revision: 619
Committed: Tue Jul 15 22:22:41 2003 UTC (20 years, 11 months ago) by mmeineke
File size: 9986 byte(s)
Log Message:
fixed a long lived bug in do_forces. Rrf was not being used in the neighborlist correctly. rcut was conssistently being set lowere than Rrf causing the dipole cutoff region to be to small. Also led to the removal of the taper region to buffer the dipole cutoff.

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