00001
00007 #include "InfoStream.h"
00008 #include "ComputeCrossterms.h"
00009 #include "Molecule.h"
00010 #include "Parameters.h"
00011 #include "Node.h"
00012 #include "ReductionMgr.h"
00013 #include "Lattice.h"
00014 #include "PressureProfile.h"
00015 #include "Debug.h"
00016
00017 #define FASTER
00018
00019 enum {
00020 CMAP_TABLE_DIM = 25,
00021 CMAP_SETUP_DIM = 24,
00022 CMAP_SPACING = 15,
00023 CMAP_PHI_0 = -180,
00024 CMAP_PSI_0 = -180
00025 };
00026
00027 #define INDEX(ncols,i,j) ((i)*ncols + (j))
00028
00029
00030
00031 int CrosstermElem::pressureProfileSlabs = 0;
00032 int CrosstermElem::pressureProfileAtomTypes = 1;
00033 BigReal CrosstermElem::pressureProfileThickness = 0;
00034 BigReal CrosstermElem::pressureProfileMin = 0;
00035
00036
00037 void CrosstermElem::getMoleculePointers
00038 (Molecule* mol, int* count, int32*** byatom, Crossterm** structarray)
00039 {
00040 #ifdef MEM_OPT_VERSION
00041 NAMD_die("Should not be called in CrosstermElem::getMoleculePointers in memory optimized version!");
00042 #else
00043 *count = mol->numCrossterms;
00044 *byatom = mol->crosstermsByAtom;
00045 *structarray = mol->crossterms;
00046 #endif
00047 }
00048
00049 void CrosstermElem::getParameterPointers(Parameters *p, const CrosstermValue **v) {
00050 *v = p->crossterm_array;
00051 }
00052
00053 void CrosstermElem::computeForce(BigReal *reduction,
00054 BigReal *pressureProfileData)
00055 {
00056 DebugM(3, "::computeForce() localIndex = " << localIndex[0] << " "
00057 << localIndex[1] << " " << localIndex[2] << " " <<
00058 localIndex[3] << std::endl);
00059
00060
00061 Vector A,B,C,D,E,F;
00062 BigReal rA,rB,rC,rD,rE,rF;
00063 BigReal energy=0;
00064 BigReal phi,psi;
00065 double cos_phi,cos_psi;
00066 double sin_phi,sin_psi;
00067 Vector dcosdA,dcosdD;
00068 Vector dcosdB,dcosdE;
00069 Vector dsindC,dsindF;
00070 Vector dsindB,dsindE;
00071 BigReal U,U_phi,U_psi;
00072 BigReal diff;
00073 Force f1(0,0,0),f2(0,0,0),f3(0,0,0);
00074 Force f4(0,0,0),f5(0,0,0),f6(0,0,0);
00075
00076
00077
00078
00079 const Position & pos0 = p[0]->x[localIndex[0]].position;
00080 const Position & pos1 = p[1]->x[localIndex[1]].position;
00081 const Position & pos2 = p[2]->x[localIndex[2]].position;
00082 const Position & pos3 = p[3]->x[localIndex[3]].position;
00083 const Position & pos4 = p[4]->x[localIndex[4]].position;
00084 const Position & pos5 = p[5]->x[localIndex[5]].position;
00085 const Position & pos6 = p[6]->x[localIndex[6]].position;
00086 const Position & pos7 = p[7]->x[localIndex[7]].position;
00087 const Lattice & lattice = p[0]->p->lattice;
00088 const Vector r12 = lattice.delta(pos0,pos1);
00089 const Vector r23 = lattice.delta(pos1,pos2);
00090 const Vector r34 = lattice.delta(pos2,pos3);
00091 const Vector r56 = lattice.delta(pos4,pos5);
00092 const Vector r67 = lattice.delta(pos5,pos6);
00093 const Vector r78 = lattice.delta(pos6,pos7);
00094
00095
00096 A = cross(r12,r23);
00097 B = cross(r23,r34);
00098 C = cross(r23,A);
00099 D = cross(r56,r67);
00100 E = cross(r67,r78);
00101 F = cross(r67,D);
00102
00103
00104 rA = A.length();
00105 rB = B.length();
00106 rC = C.length();
00107 rD = D.length();
00108 rE = E.length();
00109 rF = F.length();
00110
00111
00112 cos_phi = A*B/(rA*rB);
00113 sin_phi = C*B/(rC*rB);
00114 cos_psi = D*E/(rD*rE);
00115 sin_psi = F*E/(rF*rE);
00116
00117
00118 rB = 1.0/rB;
00119 B *= rB;
00120 rE = 1.0/rE;
00121 E *= rE;
00122
00123 phi= -atan2(sin_phi,cos_phi);
00124 psi= -atan2(sin_psi,cos_psi);
00125
00126 if (fabs(sin_phi) > 0.1) {
00127
00128 rA = 1.0/rA;
00129 A *= rA;
00130 dcosdA = rA*(cos_phi*A-B);
00131 dcosdB = rB*(cos_phi*B-A);
00132 } else {
00133
00134 rC = 1.0/rC;
00135 C *= rC;
00136 dsindC = rC*(sin_phi*C-B);
00137 dsindB = rB*(sin_phi*B-C);
00138 }
00139
00140 if (fabs(sin_psi) > 0.1) {
00141
00142 rD = 1.0/rD;
00143 D *= rD;
00144 dcosdD = rD*(cos_psi*D-E);
00145 dcosdE = rE*(cos_psi*E-D);
00146 } else {
00147
00148 rF = 1.0/rF;
00149 F *= rF;
00150 dsindF = rF*(sin_psi*F-E);
00151 dsindE = rE*(sin_psi*E-F);
00152 }
00153
00154
00155 {
00156 const double h = CMAP_SPACING * PI / 180.0;
00157 const double h_1 = 1.0 / h;
00158 #ifdef FASTER
00159 const double six_h = 6.0 * h_1;
00160 #endif
00161 const double phi_0 = CMAP_PHI_0 * PI / 180.0;
00162 const double psi_0 = CMAP_PSI_0 * PI / 180.0;
00163
00164 enum { D = CMAP_TABLE_DIM };
00165 double xa[2], xb[2], dxa[2], dxb[2];
00166 double ya[2], yb[2], dya[2], dyb[2];
00167 double t, dx_h, dy_h;
00168 #ifdef FASTER
00169 double s1, s2, s3, s4, s5;
00170 #endif
00171 double f = 0, fx = 0, fy = 0;
00172 const CrosstermData *table = &value->c[0][0];
00173 int i, j, ilo, jlo, ij;
00174
00175
00176 dx_h = (phi - phi_0) * h_1;
00177 dy_h = (psi - psi_0) * h_1;
00178
00179
00180 ilo = (int) floor(dx_h);
00181 if ( ilo < 0 ) ilo = 0;
00182 if ( ilo >= CMAP_SETUP_DIM ) ilo = CMAP_SETUP_DIM - 1;
00183 jlo = (int) floor(dy_h);
00184 if ( jlo < 0 ) jlo = 0;
00185 if ( jlo >= CMAP_SETUP_DIM ) jlo = CMAP_SETUP_DIM - 1;
00186
00187 #if !defined(FASTER)
00188
00189
00190 t = dx_h - (double) ilo;
00191 xa[0] = (1 - t) * (1 - t) * (1 + 2*t);
00192 xb[0] = h * t * (1 - t) * (1 - t);
00193 dxa[0] = -6 * t * (1 - t) * h_1;
00194 dxb[0] = (1 - t) * (1 - 3*t);
00195 t--;
00196 xa[1] = (1 + t) * (1 + t) * (1 - 2*t);
00197 xb[1] = h * t * (1 + t) * (1 + t);
00198 dxa[1] = -6 * t * (1 + t) * h_1;
00199 dxb[1] = (1 + t) * (1 + 3*t);
00200
00201
00202 t = dy_h - (double) jlo;
00203 ya[0] = (1 - t) * (1 - t) * (1 + 2*t);
00204 yb[0] = h * t * (1 - t) * (1 - t);
00205 dya[0] = -6 * t * (1 - t) * h_1;
00206 dyb[0] = (1 - t) * (1 - 3*t);
00207 t--;
00208 ya[1] = (1 + t) * (1 + t) * (1 - 2*t);
00209 yb[1] = h * t * (1 + t) * (1 + t);
00210 dya[1] = -6 * t * (1 + t) * h_1;
00211 dyb[1] = (1 + t) * (1 + 3*t);
00212
00213 #else
00214
00215
00216 t = dx_h - (double) ilo;
00217 s1 = 1-t;
00218 s2 = 2*t;
00219 s3 = 3*t;
00220 s4 = t*s1;
00221 s5 = h*s4;
00222 xa[0] = s1*s1*(1+s2);
00223 xa[1] = t*t*(3-s2);
00224 xb[0] = s5*s1;
00225 xb[1] = -s5*t;
00226 dxa[0] = -six_h*s4;
00227 dxa[1] = -dxa[0];
00228 dxb[0] = s1*(1-s3);
00229 dxb[1] = t*(-2+s3);
00230
00231
00232 t = dy_h - (double) jlo;
00233 s1 = 1-t;
00234 s2 = 2*t;
00235 s3 = 3*t;
00236 s4 = t*s1;
00237 s5 = h*s4;
00238 ya[0] = s1*s1*(1+s2);
00239 ya[1] = t*t*(3-s2);
00240 yb[0] = s5*s1;
00241 yb[1] = -s5*t;
00242 dya[0] = -six_h*s4;
00243 dya[1] = -dya[0];
00244 dyb[0] = s1*(1-s3);
00245 dyb[1] = t*(-2+s3);
00246
00247 #endif
00248
00249 for (i = 0; i < 2; i++) {
00250 for (j = 0; j < 2; j++) {
00251 ij = INDEX(D,i+ilo,j+jlo);
00252
00253 #if !defined(FASTER)
00254
00255 f += xa[i] * ya[j] * table[ij].d00
00256 + xb[i] * ya[j] * table[ij].d10
00257 + xa[i] * yb[j] * table[ij].d01
00258 + xb[i] * yb[j] * table[ij].d11;
00259
00260 fx += dxa[i] * ya[j] * table[ij].d00
00261 + dxb[i] * ya[j] * table[ij].d10
00262 + dxa[i] * yb[j] * table[ij].d01
00263 + dxb[i] * yb[j] * table[ij].d11;
00264
00265 fy += xa[i] * dya[j] * table[ij].d00
00266 + xb[i] * dya[j] * table[ij].d10
00267 + xa[i] * dyb[j] * table[ij].d01
00268 + xb[i] * dyb[j] * table[ij].d11;
00269
00270 #else
00271
00272 s1=ya[j]*table[ij].d00;
00273 s2=yb[j]*table[ij].d01;
00274 s3=ya[j]*table[ij].d10;
00275 s4=yb[j]*table[ij].d11;
00276
00277 f+=xa[i]*(s1+s2)+xb[i]*(s3+s4);
00278 fx+=dxa[i]*(s1+s2)+dxb[i]*(s3+s4);
00279 fy+=xa[i]*(dya[j]*table[ij].d00+dyb[j]*table[ij].d01)
00280 +xb[i]*(dya[j]*table[ij].d10+dyb[j]*table[ij].d11);
00281
00282 #endif
00283 }
00284 }
00285
00286
00287 U = f * scale;
00288 U_phi = fx * scale;
00289 U_psi = fy * scale;
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 }
00302
00303
00304 energy += U;
00305
00306
00307
00308
00309
00310 if (fabs(sin_phi) > 0.1)
00311 {
00312
00313 U_phi = U_phi/sin_phi;
00314
00315 f1.x += U_phi*(r23.y*dcosdA.z - r23.z*dcosdA.y);
00316 f1.y += U_phi*(r23.z*dcosdA.x - r23.x*dcosdA.z);
00317 f1.z += U_phi*(r23.x*dcosdA.y - r23.y*dcosdA.x);
00318
00319 f3.x += U_phi*(r23.z*dcosdB.y - r23.y*dcosdB.z);
00320 f3.y += U_phi*(r23.x*dcosdB.z - r23.z*dcosdB.x);
00321 f3.z += U_phi*(r23.y*dcosdB.x - r23.x*dcosdB.y);
00322
00323 f2.x += U_phi*(r12.z*dcosdA.y - r12.y*dcosdA.z
00324 + r34.y*dcosdB.z - r34.z*dcosdB.y);
00325 f2.y += U_phi*(r12.x*dcosdA.z - r12.z*dcosdA.x
00326 + r34.z*dcosdB.x - r34.x*dcosdB.z);
00327 f2.z += U_phi*(r12.y*dcosdA.x - r12.x*dcosdA.y
00328 + r34.x*dcosdB.y - r34.y*dcosdB.x);
00329 }
00330 else
00331 {
00332
00333
00334 U_phi = -U_phi/cos_phi;
00335
00336 f1.x += U_phi*((r23.y*r23.y + r23.z*r23.z)*dsindC.x
00337 - r23.x*r23.y*dsindC.y
00338 - r23.x*r23.z*dsindC.z);
00339 f1.y += U_phi*((r23.z*r23.z + r23.x*r23.x)*dsindC.y
00340 - r23.y*r23.z*dsindC.z
00341 - r23.y*r23.x*dsindC.x);
00342 f1.z += U_phi*((r23.x*r23.x + r23.y*r23.y)*dsindC.z
00343 - r23.z*r23.x*dsindC.x
00344 - r23.z*r23.y*dsindC.y);
00345
00346 f3 += cross(U_phi,dsindB,r23);
00347
00348 f2.x += U_phi*(-(r23.y*r12.y + r23.z*r12.z)*dsindC.x
00349 +(2.0*r23.x*r12.y - r12.x*r23.y)*dsindC.y
00350 +(2.0*r23.x*r12.z - r12.x*r23.z)*dsindC.z
00351 +dsindB.z*r34.y - dsindB.y*r34.z);
00352 f2.y += U_phi*(-(r23.z*r12.z + r23.x*r12.x)*dsindC.y
00353 +(2.0*r23.y*r12.z - r12.y*r23.z)*dsindC.z
00354 +(2.0*r23.y*r12.x - r12.y*r23.x)*dsindC.x
00355 +dsindB.x*r34.z - dsindB.z*r34.x);
00356 f2.z += U_phi*(-(r23.x*r12.x + r23.y*r12.y)*dsindC.z
00357 +(2.0*r23.z*r12.x - r12.z*r23.x)*dsindC.x
00358 +(2.0*r23.z*r12.y - r12.z*r23.y)*dsindC.y
00359 +dsindB.y*r34.x - dsindB.x*r34.y);
00360 }
00361
00362 if (fabs(sin_psi) > 0.1)
00363 {
00364
00365 U_psi = U_psi/sin_psi;
00366
00367 f4.x += U_psi*(r67.y*dcosdD.z - r67.z*dcosdD.y);
00368 f4.y += U_psi*(r67.z*dcosdD.x - r67.x*dcosdD.z);
00369 f4.z += U_psi*(r67.x*dcosdD.y - r67.y*dcosdD.x);
00370
00371 f6.x += U_psi*(r67.z*dcosdE.y - r67.y*dcosdE.z);
00372 f6.y += U_psi*(r67.x*dcosdE.z - r67.z*dcosdE.x);
00373 f6.z += U_psi*(r67.y*dcosdE.x - r67.x*dcosdE.y);
00374
00375 f5.x += U_psi*(r56.z*dcosdD.y - r56.y*dcosdD.z
00376 + r78.y*dcosdE.z - r78.z*dcosdE.y);
00377 f5.y += U_psi*(r56.x*dcosdD.z - r56.z*dcosdD.x
00378 + r78.z*dcosdE.x - r78.x*dcosdE.z);
00379 f5.z += U_psi*(r56.y*dcosdD.x - r56.x*dcosdD.y
00380 + r78.x*dcosdE.y - r78.y*dcosdE.x);
00381 }
00382 else
00383 {
00384
00385
00386 U_psi = -U_psi/cos_psi;
00387
00388 f4.x += U_psi*((r67.y*r67.y + r67.z*r67.z)*dsindF.x
00389 - r67.x*r67.y*dsindF.y
00390 - r67.x*r67.z*dsindF.z);
00391 f4.y += U_psi*((r67.z*r67.z + r67.x*r67.x)*dsindF.y
00392 - r67.y*r67.z*dsindF.z
00393 - r67.y*r67.x*dsindF.x);
00394 f4.z += U_psi*((r67.x*r67.x + r67.y*r67.y)*dsindF.z
00395 - r67.z*r67.x*dsindF.x
00396 - r67.z*r67.y*dsindF.y);
00397
00398 f6 += cross(U_psi,dsindE,r67);
00399
00400 f5.x += U_psi*(-(r67.y*r56.y + r67.z*r56.z)*dsindF.x
00401 +(2.0*r67.x*r56.y - r56.x*r67.y)*dsindF.y
00402 +(2.0*r67.x*r56.z - r56.x*r67.z)*dsindF.z
00403 +dsindE.z*r78.y - dsindE.y*r78.z);
00404 f5.y += U_psi*(-(r67.z*r56.z + r67.x*r56.x)*dsindF.y
00405 +(2.0*r67.y*r56.z - r56.y*r67.z)*dsindF.z
00406 +(2.0*r67.y*r56.x - r56.y*r67.x)*dsindF.x
00407 +dsindE.x*r78.z - dsindE.z*r78.x);
00408 f5.z += U_psi*(-(r67.x*r56.x + r67.y*r56.y)*dsindF.z
00409 +(2.0*r67.z*r56.x - r56.z*r67.x)*dsindF.x
00410 +(2.0*r67.z*r56.y - r56.z*r67.y)*dsindF.y
00411 +dsindE.y*r78.x - dsindE.x*r78.y);
00412 }
00413
00414
00415 p[0]->f[localIndex[0]] += f1;
00416 p[1]->f[localIndex[1]] += f2 - f1;
00417 p[2]->f[localIndex[2]] += f3 - f2;
00418 p[3]->f[localIndex[3]] += -f3;
00419 p[4]->f[localIndex[4]] += f4;
00420 p[5]->f[localIndex[5]] += f5 - f4;
00421 p[6]->f[localIndex[6]] += f6 - f5;
00422 p[7]->f[localIndex[7]] += -f6;
00423
00424 if ( p[0]->af ) {
00425 p[0]->af[localIndex[0]] += f1;
00426 p[1]->af[localIndex[1]] += f2 - f1;
00427 p[2]->af[localIndex[2]] += f3 - f2;
00428 p[3]->af[localIndex[3]] += -f3;
00429 p[4]->af[localIndex[4]] += f4;
00430 p[5]->af[localIndex[5]] += f5 - f4;
00431 p[6]->af[localIndex[6]] += f6 - f5;
00432 p[7]->af[localIndex[7]] += -f6;
00433 }
00434
00435 DebugM(3, "::computeForce() -- ending with delta energy " << energy << std::endl);
00436 reduction[crosstermEnergyIndex] += energy;
00437 reduction[virialIndex_XX] += ( f1.x * r12.x + f2.x * r23.x + f3.x * r34.x );
00438 reduction[virialIndex_XY] += ( f1.x * r12.y + f2.x * r23.y + f3.x * r34.y );
00439 reduction[virialIndex_XZ] += ( f1.x * r12.z + f2.x * r23.z + f3.x * r34.z );
00440 reduction[virialIndex_YX] += ( f1.y * r12.x + f2.y * r23.x + f3.y * r34.x );
00441 reduction[virialIndex_YY] += ( f1.y * r12.y + f2.y * r23.y + f3.y * r34.y );
00442 reduction[virialIndex_YZ] += ( f1.y * r12.z + f2.y * r23.z + f3.y * r34.z );
00443 reduction[virialIndex_ZX] += ( f1.z * r12.x + f2.z * r23.x + f3.z * r34.x );
00444 reduction[virialIndex_ZY] += ( f1.z * r12.y + f2.z * r23.y + f3.z * r34.y );
00445 reduction[virialIndex_ZZ] += ( f1.z * r12.z + f2.z * r23.z + f3.z * r34.z );
00446
00447 reduction[virialIndex_XX] += ( f4.x * r56.x + f5.x * r67.x + f6.x * r78.x );
00448 reduction[virialIndex_XY] += ( f4.x * r56.y + f5.x * r67.y + f6.x * r78.y );
00449 reduction[virialIndex_XZ] += ( f4.x * r56.z + f5.x * r67.z + f6.x * r78.z );
00450 reduction[virialIndex_YX] += ( f4.y * r56.x + f5.y * r67.x + f6.y * r78.x );
00451 reduction[virialIndex_YY] += ( f4.y * r56.y + f5.y * r67.y + f6.y * r78.y );
00452 reduction[virialIndex_YZ] += ( f4.y * r56.z + f5.y * r67.z + f6.y * r78.z );
00453 reduction[virialIndex_ZX] += ( f4.z * r56.x + f5.z * r67.x + f6.z * r78.x );
00454 reduction[virialIndex_ZY] += ( f4.z * r56.y + f5.z * r67.y + f6.z * r78.y );
00455 reduction[virialIndex_ZZ] += ( f4.z * r56.z + f5.z * r67.z + f6.z * r78.z );
00456
00457 if (pressureProfileData) {
00458 BigReal z1 = p[0]->x[localIndex[0]].position.z;
00459 BigReal z2 = p[1]->x[localIndex[1]].position.z;
00460 BigReal z3 = p[2]->x[localIndex[2]].position.z;
00461 BigReal z4 = p[3]->x[localIndex[3]].position.z;
00462 BigReal z5 = p[4]->x[localIndex[4]].position.z;
00463 BigReal z6 = p[5]->x[localIndex[5]].position.z;
00464 BigReal z7 = p[6]->x[localIndex[6]].position.z;
00465 BigReal z8 = p[7]->x[localIndex[7]].position.z;
00466 int n1 = (int)floor((z1-pressureProfileMin)/pressureProfileThickness);
00467 int n2 = (int)floor((z2-pressureProfileMin)/pressureProfileThickness);
00468 int n3 = (int)floor((z3-pressureProfileMin)/pressureProfileThickness);
00469 int n4 = (int)floor((z4-pressureProfileMin)/pressureProfileThickness);
00470 int n5 = (int)floor((z5-pressureProfileMin)/pressureProfileThickness);
00471 int n6 = (int)floor((z6-pressureProfileMin)/pressureProfileThickness);
00472 int n7 = (int)floor((z7-pressureProfileMin)/pressureProfileThickness);
00473 int n8 = (int)floor((z8-pressureProfileMin)/pressureProfileThickness);
00474 pp_clamp(n1, pressureProfileSlabs);
00475 pp_clamp(n2, pressureProfileSlabs);
00476 pp_clamp(n3, pressureProfileSlabs);
00477 pp_clamp(n4, pressureProfileSlabs);
00478 pp_clamp(n5, pressureProfileSlabs);
00479 pp_clamp(n6, pressureProfileSlabs);
00480 pp_clamp(n7, pressureProfileSlabs);
00481 pp_clamp(n8, pressureProfileSlabs);
00482 int p1 = p[0]->x[localIndex[0]].partition;
00483 int p2 = p[1]->x[localIndex[1]].partition;
00484 int p3 = p[2]->x[localIndex[2]].partition;
00485 int p4 = p[3]->x[localIndex[3]].partition;
00486 int p5 = p[4]->x[localIndex[4]].partition;
00487 int p6 = p[5]->x[localIndex[5]].partition;
00488 int p7 = p[6]->x[localIndex[6]].partition;
00489 int p8 = p[7]->x[localIndex[7]].partition;
00490 int pn = pressureProfileAtomTypes;
00491 pp_reduction(pressureProfileSlabs, n1, n2, p1, p2, pn,
00492 f1.x * r12.x, f1.y * r12.y, f1.z * r12.z,
00493 pressureProfileData);
00494 pp_reduction(pressureProfileSlabs, n2, n3, p2, p3, pn,
00495 f2.x * r23.x, f2.y * r23.y, f2.z * r23.z,
00496 pressureProfileData);
00497 pp_reduction(pressureProfileSlabs, n3, n4, p3, p4, pn,
00498 f3.x * r34.x, f3.y * r34.y, f3.z * r34.z,
00499 pressureProfileData);
00500 pp_reduction(pressureProfileSlabs, n5, n6, p5, p6, pn,
00501 f4.x * r56.x, f4.y * r56.y, f4.z * r56.z,
00502 pressureProfileData);
00503 pp_reduction(pressureProfileSlabs, n6, n7, p6, p7, pn,
00504 f5.x * r67.x, f5.y * r67.y, f5.z * r67.z,
00505 pressureProfileData);
00506 pp_reduction(pressureProfileSlabs, n7, n8, p7, p8, pn,
00507 f6.x * r78.x, f6.y * r78.y, f6.z * r78.z,
00508 pressureProfileData);
00509 }
00510
00511 }
00512
00513 void CrosstermElem::submitReductionData(BigReal *data, SubmitReduction *reduction)
00514 {
00515 reduction->item(REDUCTION_CROSSTERM_ENERGY) += data[crosstermEnergyIndex];
00516 ADD_TENSOR(reduction,REDUCTION_VIRIAL_NORMAL,data,virialIndex);
00517 ADD_TENSOR(reduction,REDUCTION_VIRIAL_AMD_DIHE,data,virialIndex);
00518 }
00519
00520
00521
00522
00523 static void lu_decomp_nopivot(double *m, int n);
00524 static void forward_back_sub(double *b, double *m, int n);
00525
00526 void crossterm_setup(CrosstermData *table)
00527 {
00528 enum { D = CMAP_TABLE_DIM };
00529 enum { N = CMAP_SETUP_DIM };
00530 const double h_1 = 1.0 / ( CMAP_SPACING * PI / 180.0) ;
00531 const double h_2 = h_1 * h_1;
00532 const double tr_h = 3.0 * h_1;
00533 int i, j;
00534 int ij;
00535 int ijp1p1, ijm1m1, ijp1m1, ijm1p1;
00536 int ijp2p2, ijm2m2, ijp2m2, ijm2p2;
00537
00538
00539 double* const m = new double[N*N];
00540 memset(m,0,N*N*sizeof(double));
00541
00542
00543 m[0] = 4;
00544 for (i = 1; i < N; i++) {
00545 m[INDEX(N,i-1,i)] = 1;
00546 m[INDEX(N,i,i-1)] = 1;
00547 m[INDEX(N,i,i)] = 4;
00548 }
00549 m[INDEX(N,0,N-1)] = 1;
00550 m[INDEX(N,N-1,0)] = 1;
00551
00552
00553 lu_decomp_nopivot(m, N);
00554
00555
00556 double* const v = new double[N];
00557 memset(v,0,N*sizeof(double));
00558
00559
00560 for (i = 0; i < N; i++) {
00561
00562
00563 v[0] = tr_h * (table[INDEX(D,i,1)].d00 - table[INDEX(D,i,N-1)].d00);
00564 for (j = 1; j < N; j++) {
00565 v[j] = tr_h * (table[INDEX(D,i,j+1)].d00 - table[INDEX(D,i,j-1)].d00);
00566 }
00567
00568
00569 forward_back_sub(v, m, N);
00570
00571
00572 for (j = 0; j < N; j++) {
00573 table[INDEX(D,i,j)].d01 = v[j];
00574 }
00575 table[INDEX(D,i,N)].d01 = v[0];
00576 }
00577 for (j = 0; j <= N; j++) {
00578 table[INDEX(D,N,j)].d01 = table[INDEX(D,0,j)].d01;
00579 }
00580
00581
00582 for (j = 0; j < N; j++) {
00583
00584
00585 v[0] = tr_h * (table[INDEX(D,1,j)].d00 - table[INDEX(D,N-1,j)].d00);
00586 for (i = 1; i < N; i++) {
00587 v[i] = tr_h * (table[INDEX(D,i+1,j)].d00 - table[INDEX(D,i-1,j)].d00);
00588 }
00589
00590
00591 forward_back_sub(v, m, N);
00592
00593
00594 for (i = 0; i < N; i++) {
00595 table[INDEX(D,i,j)].d10 = v[i];
00596 }
00597 table[INDEX(D,N,j)].d10 = v[0];
00598 }
00599 for (i = 0; i <= N; i++) {
00600 table[INDEX(D,i,N)].d10 = table[INDEX(D,i,0)].d10;
00601 }
00602
00603
00604 for (i = 0; i < N; i++) {
00605 for (j = 0; j < N; j++) {
00606 ij = INDEX(D,i,j);
00607 ijp1p1 = INDEX(D,(i+1)%N,(j+1)%N);
00608 ijm1m1 = INDEX(D,(i+N-1)%N,(j+N-1)%N);
00609 ijp1m1 = INDEX(D,(i+1)%N,(j+N-1)%N);
00610 ijm1p1 = INDEX(D,(i+N-1)%N,(j+1)%N);
00611 ijp2p2 = INDEX(D,(i+2)%N,(j+2)%N);
00612 ijm2m2 = INDEX(D,(i+N-2)%N,(j+N-2)%N);
00613 ijp2m2 = INDEX(D,(i+2)%N,(j+N-2)%N);
00614 ijm2p2 = INDEX(D,(i+N-2)%N,(j+2)%N);
00615 table[ij].d11 = h_2 * (1./3) * (table[ijp1p1].d00 + table[ijm1m1].d00
00616 - table[ijp1m1].d00 - table[ijm1p1].d00
00617 - (1./16) * (table[ijp2p2].d00 + table[ijm2m2].d00
00618 - table[ijp2m2].d00 - table[ijm2p2].d00));
00619 }
00620 }
00621
00622 #if 0
00623
00624 for (i = 0; i < N; i++) {
00625 for (j = 0; j < N; j++) {
00626 ij = INDEX(D,i,j);
00627 ijp1p1 = INDEX(D,(i+1)%N,(j+1)%N);
00628 ijm1m1 = INDEX(D,(i+N-1)%N,(j+N-1)%N);
00629 ijp1m1 = INDEX(D,(i+1)%N,(j+N-1)%N);
00630 ijm1p1 = INDEX(D,(i+N-1)%N,(j+1)%N);
00631 table[ij].d11 = h_2 * (1./4) * (table[ijp1p1].d00 + table[ijm1m1].d00
00632 - table[ijp1m1].d00 - table[ijm1p1].d00);
00633 }
00634 }
00635 #endif
00636
00637
00638 for (i = 0; i < N; i++) {
00639 table[INDEX(D,i,N)].d11 = table[INDEX(D,i,0)].d11;
00640 table[INDEX(D,N,i)].d11 = table[INDEX(D,0,i)].d11;
00641 }
00642 table[INDEX(D,N,N)].d11 = table[INDEX(D,0,0)].d11;
00643
00644
00645 delete [] m;
00646 delete [] v;
00647
00648 }
00649
00650
00651 void lu_decomp_nopivot(double *m, int n)
00652 {
00653 double l_ik;
00654 int i, j, k;
00655
00656 for (k = 0; k < n-1; k++) {
00657 for (i = k+1; i < n; i++) {
00658 l_ik = m[INDEX(n,i,k)] / m[INDEX(n,k,k)];
00659 for (j = k; j < n; j++) {
00660 m[INDEX(n,i,j)] -= l_ik * m[INDEX(n,k,j)];
00661 }
00662 m[INDEX(n,i,k)] = l_ik;
00663 }
00664 }
00665 }
00666
00667
00668 void forward_back_sub(double *b, double *m, int n)
00669 {
00670 int i, j;
00671
00672
00673 for (j = 0; j < n-1; j++) {
00674 for (i = j+1; i < n; i++) {
00675 b[i] -= m[INDEX(n,i,j)] * b[j];
00676 }
00677 }
00678
00679 for (j = n-1; j >= 0; j--) {
00680 b[j] /= m[INDEX(n,j,j)];
00681 for (i = j-1; i >= 0; i--) {
00682 b[i] -= m[INDEX(n,i,j)] * b[j];
00683 }
00684 }
00685 }
00686
00687