00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "msmpot_internal.h"
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #define USE_BIN_HASHING
00035
00036 int Msmpot_compute(Msmpot *msm,
00037 float *epotmap,
00038
00039
00040
00041 int mx, int my, int mz,
00042 float lx, float ly, float lz,
00043 float x0, float y0, float z0,
00044 float vx, float vy, float vz,
00045
00046 const float *atom,
00047 int natoms
00048 ) {
00049 int err;
00050
00051 REPORT("Performing MSM calculation of electrostatic potential map.");
00052
00053 err = Msmpot_check_params(msm, epotmap, mx, my, mz, lx, ly, lz,
00054 vx, vy, vz, atom, natoms);
00055 if (err != MSMPOT_SUCCESS) return ERROR(err);
00056
00057
00058 msm->atom = atom;
00059 msm->natoms = natoms;
00060 msm->epotmap = epotmap;
00061 msm->mx = mx;
00062 msm->my = my;
00063 msm->mz = mz;
00064 msm->lx = lx;
00065 msm->ly = ly;
00066 msm->lz = lz;
00067 msm->lx0 = x0;
00068 msm->ly0 = y0;
00069 msm->lz0 = z0;
00070 msm->dx = lx / mx;
00071 msm->dy = ly / my;
00072 msm->dz = lz / mz;
00073 msm->px = vx;
00074 msm->py = vy;
00075 msm->pz = vz;
00076 msm->isperiodic = 0;
00077
00078 if (vx > 0) SET_X(msm->isperiodic);
00079 if (vy > 0) SET_Y(msm->isperiodic);
00080 if (vz > 0) SET_Z(msm->isperiodic);
00081
00082 err = Msmpot_setup(msm);
00083 if (err != MSMPOT_SUCCESS) return ERROR(err);
00084
00085 memset(epotmap, 0, mx*my*mz*sizeof(float));
00086
00087
00088 #if !defined(MSMPOT_LONGRANGE_ONLY)
00089 #ifdef MSMPOT_CUDA
00090 if (msm->use_cuda_shortrng) {
00091 err = Msmpot_cuda_compute_shortrng(msm->msmcuda);
00092 if (err && msm->cuda_optional) {
00093 #ifdef USE_BIN_HASHING
00094 err = Msmpot_compute_shortrng_bins(msm);
00095 #else
00096 err = Msmpot_compute_shortrng_linklist(msm, msm->atom, msm->natoms);
00097 #endif
00098 if (err) return ERROR(err);
00099 }
00100 else if (err) return ERROR(err);
00101 }
00102 else {
00103 #ifdef USE_BIN_HASHING
00104 err = Msmpot_compute_shortrng_bins(msm);
00105 #else
00106 err = Msmpot_compute_shortrng_linklist(msm, msm->atom, msm->natoms);
00107 #endif
00108 if (err) return ERROR(err);
00109 }
00110 #else
00111 #ifdef USE_BIN_HASHING
00112 err = Msmpot_compute_shortrng_bins(msm);
00113 #else
00114 err = Msmpot_compute_shortrng_linklist(msm, msm->atom, msm->natoms);
00115 #endif
00116 if (err) return ERROR(err);
00117 #endif
00118 #endif
00119
00120 #if !defined(MSMPOT_SHORTRANGE_ONLY)
00121 err = Msmpot_compute_longrng(msm);
00122 if (err) return ERROR(err);
00123 #endif
00124
00125 #ifdef MSMPOT_VERBOSE
00126 #ifdef MSMPOT_CHECKMAPINDEX
00127 printf("epotmap[%d]=%g\n", MAPINDEX, epotmap[MAPINDEX]);
00128 #endif
00129 #endif
00130
00131 return MSMPOT_SUCCESS;
00132 }
00133
00134
00135
00136
00137
00138
00139 int Msmpot_compute_longrng(Msmpot *msm) {
00140 int err = 0;
00141
00142
00143 switch (msm->interp) {
00144 case MSMPOT_INTERP_CUBIC:
00145 err = Msmpot_compute_longrng_cubic(msm);
00146 if (err) return ERROR(err);
00147 break;
00148 default:
00149 return ERRMSG(MSMPOT_ERROR_SUPPORT,
00150 "interpolation method not implemented");
00151 }
00152 return MSMPOT_SUCCESS;
00153 }
00154
00155
00156
00157
00158
00159
00160 static int bin_evaluation(Msmpot *msm);
00161
00162
00163
00164
00165
00166
00167 int Msmpot_compute_shortrng_bins(Msmpot *msm) {
00168 int err = 0;
00169
00170 REPORT("Using atom hashing into bins for short-range part.");
00171
00172 REPORT("Using tight neighborhood for nearby bins.");
00173 err = Msmpot_compute_shortrng_bin_neighborhood(msm,
00174 msm->bx, msm->by, msm->bz);
00175 if (err) return ERROR(err);
00176
00177 err = Msmpot_compute_shortrng_bin_hashing(msm);
00178 if (err) return ERROR(err);
00179
00180 err = bin_evaluation(msm);
00181 if (err) return ERROR(err);
00182
00183 if (msm->nover > 0) {
00184 #ifdef MSMPOT_REPORT
00185 char msg[120];
00186 sprintf(msg, "Extra atoms (%d) from overflowed bins "
00187 "must also be evaluated.", msm->nover);
00188 REPORT(msg);
00189 #endif
00190 err = Msmpot_compute_shortrng_linklist(msm, msm->over, msm->nover);
00191 if (err) return ERROR(err);
00192 }
00193
00194 return MSMPOT_SUCCESS;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 #if defined( __INTEL_COMPILER)
00216 #pragma optimize("",off)
00217 #endif
00218 int Msmpot_compute_shortrng_bin_neighborhood(Msmpot *msm,
00219 float rx,
00220 float ry,
00221 float rz
00222 ) {
00223
00224 union {
00225 float f;
00226 int i;
00227 } v0, v1;
00228
00229 const float cutoff = msm->a;
00230
00231 const float bx = msm->bx;
00232 const float by = msm->by;
00233 const float bz = msm->bz;
00234
00235 const float invbx = msm->invbx;
00236 const float invby = msm->invby;
00237 const float invbz = msm->invbz;
00238
00239 const float bx2 = bx*bx;
00240 const float by2 = by*by;
00241 const float bz2 = bz*bz;
00242
00243 float sqbindiag = 0.f;
00244 float r, r2;
00245
00246 int bpr0, bpr1;
00247
00248 int cx = (int) ceilf(cutoff * invbx);
00249 int cy = (int) ceilf(cutoff * invby);
00250 int cz = (int) ceilf(cutoff * invbz);
00251
00252 int nbrx, nbry, nbrz;
00253 int i, j, k;
00254 int maxboff;
00255
00256 int *boff;
00257
00258
00259 v0.f = bx, v1.f = rx;
00260 if (v0.i == v1.i) {
00261 bpr0 = bpr1 = 1;
00262 }
00263 else {
00264 bpr0 = (int) floorf(rx*invbx);
00265 bpr1 = (int) ceilf(rx*invbx);
00266 }
00267
00268 if (bpr0 == bpr1) {
00269 nbrx = cx + (bpr0 >> 1);
00270
00271 sqbindiag += ((bpr0 & 1) ? 0.25f : 1.f) * bx2;
00272 }
00273 else {
00274 nbrx = (int) ceilf((cutoff + 0.5f*rx + bx) * invbx);
00275 sqbindiag += bx2;
00276 }
00277
00278
00279 v0.f = by, v1.f = ry;
00280 if (v0.i == v1.i) {
00281 bpr0 = bpr1 = 1;
00282 }
00283 else {
00284 bpr0 = (int) floorf(ry*invby);
00285 bpr1 = (int) ceilf(ry*invby);
00286 }
00287
00288 if (bpr0 == bpr1) {
00289 nbry = cy + (bpr0 >> 1);
00290
00291 sqbindiag += ((bpr0 & 1) ? 0.25f : 1.f) * by2;
00292 }
00293 else {
00294 nbry = (int) ceilf((cutoff + 0.5f*ry + by) * invby);
00295 sqbindiag += by2;
00296 }
00297
00298
00299 v0.f = bz, v1.f = rz;
00300 if (v0.i == v1.i) {
00301 bpr0 = bpr1 = 1;
00302 }
00303 else {
00304 bpr0 = (int) floorf(rz*invbz);
00305 bpr1 = (int) ceilf(rz*invbz);
00306 }
00307
00308 if (bpr0 == bpr1) {
00309 nbrz = cz + (bpr0 >> 1);
00310
00311 sqbindiag += ((bpr0 & 1) ? 0.25f : 1.f) * bz2;
00312 }
00313 else {
00314 nbrz = (int) ceilf((cutoff + 0.5f*rz + bz) * invbz);
00315 sqbindiag += bz2;
00316 }
00317
00318 r = cutoff + 0.5f*sqrtf(rx*rx + ry*ry + rz*rz) + sqrtf(sqbindiag);
00319 r2 = r*r;
00320
00321
00322 maxboff = (2*nbrx+1) * (2*nbry+1) * (2*nbrz+1);
00323
00324 if (msm->maxboff < maxboff) {
00325 void *v = realloc(msm->boff, 3*maxboff*sizeof(int));
00326 if (NULL == v) return ERROR(MSMPOT_ERROR_MALLOC);
00327 msm->boff = (int *) v;
00328 msm->maxboff = maxboff;
00329 }
00330
00331 boff = msm->boff;
00332 for (k = -nbrz; k <= nbrz; k++) {
00333 for (j = -nbry; j <= nbry; j++) {
00334 for (i = -nbrx; i <= nbrx; i++) {
00335 if ((i*i*bx2 + j*j*by2 + k*k*bz2) >= r2) continue;
00336 *boff++ = i;
00337 *boff++ = j;
00338 *boff++ = k;
00339 }
00340 }
00341 }
00342 msm->nboff = (boff - msm->boff) / 3;
00343
00344 return MSMPOT_SUCCESS;
00345 }
00346 #if defined(__INTEL_COMPILER)
00347 #pragma optimize("",on)
00348 #endif
00349
00350
00351 int Msmpot_compute_shortrng_bin_hashing(Msmpot *msm) {
00352
00353 union {
00354 float f;
00355 int i;
00356 } q;
00357
00358 int i, j, k;
00359 int n;
00360 int nb;
00361 const int ispx = (IS_SET_X(msm->isperiodic) != 0);
00362 const int ispy = (IS_SET_Y(msm->isperiodic) != 0);
00363 const int ispz = (IS_SET_Z(msm->isperiodic) != 0);
00364 const float px0 = msm->px0;
00365 const float py0 = msm->py0;
00366 const float pz0 = msm->pz0;
00367 const float px = msm->px;
00368 const float py = msm->py;
00369 const float pz = msm->pz;
00370 const float invbx = msm->invbx;
00371 const float invby = msm->invby;
00372 const float invbz = msm->invbz;
00373 float x, y, z;
00374
00375 const float *atom = msm->atom;
00376 const int natoms = msm->natoms;
00377
00378 const int nbx = msm->nbx;
00379 const int nby = msm->nby;
00380 const int nbz = msm->nbz;
00381 const int nbins = (nbx * nby * nbz);
00382 const int bindepth = msm->bindepth;
00383 float *bin = msm->bin;
00384 int *bincount = msm->bincount;
00385
00386 memset(bin, 0, nbins*bindepth*ATOM_SIZE*sizeof(float));
00387 memset(bincount, 0, nbins*sizeof(int));
00388 msm->nover = 0;
00389
00390 for (n = 0; n < natoms; n++) {
00391
00392
00393 q.f = atom[ATOM_Q(n)];
00394 if (0==q.i) continue;
00395
00396 x = atom[ATOM_X(n)] - px0;
00397 y = atom[ATOM_Y(n)] - py0;
00398 z = atom[ATOM_Z(n)] - pz0;
00399 i = (int) floorf(x * invbx);
00400 j = (int) floorf(y * invby);
00401 k = (int) floorf(z * invbz);
00402
00403
00404 if (ispx) {
00405 if (i < 0) do { i += nbx; x += px; } while (i < 0);
00406 else if (i >= nbx) do { i -= nbx; x -= px; } while (i >= nbx);
00407 }
00408 if (ispy) {
00409 if (j < 0) do { j += nby; y += py; } while (j < 0);
00410 else if (j >= nby) do { j -= nby; y -= py; } while (j >= nby);
00411 }
00412 if (ispz) {
00413 if (k < 0) do { k += nbz; z += pz; } while (k < 0);
00414 else if (k >= nbz) do { k -= nbz; z -= pz; } while (k >= nbz);
00415 }
00416
00417 #if 0
00418 if (i < 0 || i >= nbx ||
00419 j < 0 || j >= nby ||
00420 k < 0 || k >= nbz) {
00421 printf("nbx=%d nby=%d nbz=%d\n", nbx, nby, nbz);
00422 printf("i=%d j=%d k=%d\n", i, j, k);
00423 return ERROR(MSMPOT_ERROR_ASSERT);
00424 }
00425 #endif
00426
00427 nb = (k*nby + j)*nbx + i;
00428 ASSERT(0 <= nb && nb < nbins);
00429 if (bincount[nb] < bindepth) {
00430 float *p = bin + (nb*bindepth + bincount[nb])*ATOM_SIZE;
00431 *p++ = x;
00432 *p++ = y;
00433 *p++ = z;
00434 *p = q.f;
00435 bincount[nb]++;
00436 }
00437 else {
00438 int nover = msm->nover;
00439 float *p;
00440 if (nover == msm->maxover) {
00441 void *v = realloc(msm->over, 2*msm->maxover*ATOM_SIZE*sizeof(float));
00442 if (NULL == v) return ERROR(MSMPOT_ERROR_MALLOC);
00443 msm->over = (float *) v;
00444 msm->maxover *= 2;
00445 }
00446 p = msm->over + nover*ATOM_SIZE;
00447 *p++ = x;
00448 *p++ = y;
00449 *p++ = z;
00450 *p = q.f;
00451 msm->nover++;
00452 }
00453 }
00454 return MSMPOT_SUCCESS;
00455 }
00456
00457
00458 int bin_evaluation(Msmpot *msm) {
00459
00460 const float lx0 = msm->lx0;
00461 const float ly0 = msm->ly0;
00462 const float lz0 = msm->lz0;
00463
00464 const float dx = msm->dx;
00465 const float dy = msm->dy;
00466 const float dz = msm->dz;
00467
00468 const float px0 = msm->lx0;
00469 const float py0 = msm->ly0;
00470 const float pz0 = msm->lz0;
00471
00472 const float px = msm->px;
00473 const float py = msm->py;
00474 const float pz = msm->pz;
00475
00476 const float invbx = msm->invbx;
00477 const float invby = msm->invby;
00478 const float invbz = msm->invbz;
00479
00480 const int nbx = msm->nbx;
00481 const int nby = msm->nby;
00482 const int nbz = msm->nbz;
00483
00484 const int bindepth = msm->bindepth;
00485
00486 const int ispx = (IS_SET_X(msm->isperiodic) != 0);
00487 const int ispy = (IS_SET_Y(msm->isperiodic) != 0);
00488 const int ispz = (IS_SET_Z(msm->isperiodic) != 0);
00489
00490 const float a = msm->a;
00491 const float a2 = a*a;
00492 const float a_1 = 1/a;
00493 const float inv_a2 = a_1 * a_1;
00494
00495 const int split = msm->split;
00496
00497 float *epotmap = msm->epotmap;
00498
00499 const int mx = msm->mx;
00500 const int my = msm->my;
00501 const int mz = msm->mz;
00502
00503 int n;
00504 int ic, jc, kc;
00505 int ig, jg, kg;
00506 int i, j, k;
00507
00508 for (kg = 0; kg < mz; kg++) {
00509 for (jg = 0; jg < my; jg++) {
00510 for (ig = 0; ig < mx; ig++) {
00511
00512 float e = 0;
00513
00514 float xg = ig * dx;
00515 float yg = jg * dy;
00516 float zg = kg * dz;
00517
00518 int index = (kg*my + jg)*mx + ig;
00519
00520 xg += lx0;
00521 yg += ly0;
00522 zg += lz0;
00523
00524 xg -= px0;
00525 yg -= py0;
00526 zg -= pz0;
00527
00528 ic = (int) floorf(xg * invbx);
00529 jc = (int) floorf(yg * invby);
00530 kc = (int) floorf(zg * invbz);
00531
00532 for (n = 0; n < msm->nboff; n++) {
00533 float *pbin;
00534 int bindex, bincount, m;
00535 int iw, jw, kw;
00536
00537 float xw = 0;
00538 float yw = 0;
00539 float zw = 0;
00540
00541 i = ic + msm->boff[3*n ];
00542 j = jc + msm->boff[3*n + 1];
00543 k = kc + msm->boff[3*n + 2];
00544
00545 if ( ! ispx && (i < 0 || i >= nbx) ) continue;
00546 if ( ! ispy && (j < 0 || j >= nby) ) continue;
00547 if ( ! ispz && (k < 0 || k >= nbz) ) continue;
00548
00549 iw = i;
00550 jw = j;
00551 kw = k;
00552
00553 if (ispx) {
00554 while (iw < 0) { iw += nbx; xw -= px; }
00555 while (iw >= nbx) { iw -= nbx; xw += px; }
00556 }
00557 if (ispy) {
00558 while (jw < 0) { jw += nby; yw -= py; }
00559 while (jw >= nby) { jw -= nby; yw += py; }
00560 }
00561 if (ispz) {
00562 while (kw < 0) { kw += nbz; zw -= pz; }
00563 while (kw >= nbz) { kw -= nbz; zw += pz; }
00564 }
00565
00566 bindex = (kw*nby + jw)*nbx + iw;
00567 pbin = msm->bin + bindex*bindepth*ATOM_SIZE;
00568 bincount = msm->bincount[bindex];
00569
00570 for (m = 0; m < bincount; m++) {
00571 float x = *pbin++;
00572 float y = *pbin++;
00573 float z = *pbin++;
00574 float q = *pbin++;
00575
00576 float rx = (x+xw) - xg;
00577 float ry = (y+yw) - yg;
00578 float rz = (z+zw) - zg;
00579
00580 float r2 = rx*rx + ry*ry + rz*rz;
00581 float s, gs;
00582
00583 if (r2 >= a2) continue;
00584
00585 s = r2 * inv_a2;
00586 SPOLY(&gs, s, split);
00587 e += q * (1/sqrtf(r2) - a_1 * gs);
00588 }
00589
00590 }
00591
00592 epotmap[index] = e;
00593 }
00594 }
00595 }
00596
00597 return MSMPOT_SUCCESS;
00598 }
00599
00600
00601 static int linklist_hashing(Msmpot *msm, const float *atom, int natoms);
00602 static int linklist_evaluation(Msmpot *msm, const float *atom);
00603
00604
00605
00606
00607
00608 int Msmpot_compute_shortrng_linklist(Msmpot *msm,
00609 const float *atom,
00610 int natoms
00611 ) {
00612 int err = 0;
00613
00614 REPORT("Using linked lists of atoms for short-range part.");
00615
00616 err = linklist_hashing(msm, atom, natoms);
00617 if (err) return ERROR(err);
00618
00619 err = linklist_evaluation(msm, atom);
00620 if (err) return ERROR(err);
00621
00622 return MSMPOT_SUCCESS;
00623 }
00624
00625
00626
00627
00628
00629 int linklist_hashing(Msmpot *msm, const float *atom, int natoms) {
00630
00631 union {
00632 float f;
00633 int i;
00634 } q;
00635
00636 int i, j, k;
00637 int n;
00638 int nb;
00639 const int ispx = (IS_SET_X(msm->isperiodic) != 0);
00640 const int ispy = (IS_SET_Y(msm->isperiodic) != 0);
00641 const int ispz = (IS_SET_Z(msm->isperiodic) != 0);
00642 const float x0 = msm->px0;
00643 const float y0 = msm->py0;
00644 const float z0 = msm->pz0;
00645 const float invbx = msm->invbx;
00646 const float invby = msm->invby;
00647 const float invbz = msm->invbz;
00648 float x, y, z;
00649 int *first = msm->first_atom_index;
00650 int *next = msm->next_atom_index;
00651 const int nbx = msm->nbx;
00652 const int nby = msm->nby;
00653 const int nbz = msm->nbz;
00654 const int nbins = (nbx * nby * nbz);
00655
00656 #ifdef MSMPOT_VERBOSE
00657 printf("bin array: %d %d %d\n", nbx, nby, nbz);
00658 printf("bin lengths: %f %f %f\n", 1/invbx, 1/invby, 1/invbz);
00659 #endif
00660
00661
00662 for (nb = 0; nb < nbins; nb++) first[nb] = -1;
00663 for (n = 0; n < natoms; n++) next[n] = -1;
00664
00665 for (n = 0; n < natoms; n++) {
00666
00667
00668 q.f = atom[ATOM_Q(n)];
00669 if (0==q.i) continue;
00670
00671 x = atom[ATOM_X(n)] - x0;
00672 y = atom[ATOM_Y(n)] - y0;
00673 z = atom[ATOM_Z(n)] - z0;
00674 i = (int) floorf(x * invbx);
00675 j = (int) floorf(y * invby);
00676 k = (int) floorf(z * invbz);
00677
00678
00679 if (ispx) {
00680 if (i < 0) do { i += nbx; } while (i < 0);
00681 else if (i >= nbx) do { i -= nbx; } while (i >= nbx);
00682 }
00683 if (ispy) {
00684 if (j < 0) do { j += nby; } while (j < 0);
00685 else if (j >= nby) do { j -= nby; } while (j >= nby);
00686 }
00687 if (ispz) {
00688 if (k < 0) do { k += nbz; } while (k < 0);
00689 else if (k >= nbz) do { k -= nbz; } while (k >= nbz);
00690 }
00691
00692 nb = (k*nby + j)*nbx + i;
00693 next[n] = first[nb];
00694 first[nb] = n;
00695 }
00696 return MSMPOT_SUCCESS;
00697 }
00698
00699
00700
00701
00702
00703
00704 int linklist_evaluation(Msmpot *msm, const float *atom) {
00705
00706 const float lx0 = msm->lx0;
00707 const float ly0 = msm->ly0;
00708 const float lz0 = msm->lz0;
00709
00710 const float dx = msm->dx;
00711 const float dy = msm->dy;
00712 const float dz = msm->dz;
00713 const float inv_dx = 1/dx;
00714 const float inv_dy = 1/dy;
00715 const float inv_dz = 1/dz;
00716
00717 const float px = msm->px;
00718 const float py = msm->py;
00719 const float pz = msm->pz;
00720
00721 const float plx = px - msm->lx;
00722 const float ply = py - msm->ly;
00723 const float plz = pz - msm->lz;
00724
00725 const float pxd = px * inv_dx;
00726 const float pyd = py * inv_dy;
00727 const float pzd = pz * inv_dz;
00728
00729 const int ispx = (IS_SET_X(msm->isperiodic) != 0);
00730 const int ispy = (IS_SET_Y(msm->isperiodic) != 0);
00731 const int ispz = (IS_SET_Z(msm->isperiodic) != 0);
00732
00733 const float a = msm->a;
00734 const float a2 = a*a;
00735 const float a_1 = 1/a;
00736 const float inv_a2 = a_1 * a_1;
00737
00738 float x, y, z;
00739 float q;
00740
00741 float xg, yg, zg;
00742
00743 int i, j, k;
00744 int ic, jc, kc;
00745 int ia, ib;
00746 int ja, jb;
00747 int ka, kb;
00748 int iw, jw, kw;
00749 int n;
00750 int nbs;
00751 long index;
00752 long jkoff;
00753 int koff;
00754 float rx, ry, rz;
00755 float rz2, ryrz2;
00756 float r2;
00757 float s;
00758 float gs;
00759 float e;
00760
00761 const int split = msm->split;
00762
00763 const int mx = msm->mx;
00764 const int my = msm->my;
00765 const int mz = msm->mz;
00766
00767 const int mri = (int) ceilf(a * inv_dx) - 1;
00768 const int mrj = (int) ceilf(a * inv_dy) - 1;
00769 const int mrk = (int) ceilf(a * inv_dz) - 1;
00770
00771
00772 const int nbins = (msm->nbx * msm->nby * msm->nbz);
00773 const int *first = msm->first_atom_index;
00774 const int *next = msm->next_atom_index;
00775
00776 float *epotmap = msm->epotmap;
00777 #if 0
00778 float *pem = NULL;
00779 #endif
00780
00781 for (nbs = 0; nbs < nbins; nbs++) {
00782 for (n = first[nbs]; n != -1; n = next[n]) {
00783
00784
00785 x = atom[ATOM_X(n)] - lx0;
00786 y = atom[ATOM_Y(n)] - ly0;
00787 z = atom[ATOM_Z(n)] - lz0;
00788
00789
00790 q = atom[ATOM_Q(n)];
00791
00792
00793
00794
00795
00796
00797
00798 if (ispx) {
00799 if (x < 0) do { x += px; } while (x < 0);
00800 else if (x >= px) do { x -= px; } while (x >= px);
00801 }
00802 if (ispy) {
00803 if (y < 0) do { y += py; } while (y < 0);
00804 else if (y >= py) do { y -= py; } while (y >= py);
00805 }
00806 if (ispz) {
00807 if (z < 0) do { z += pz; } while (z < 0);
00808 else if (z >= pz) do { z -= pz; } while (z >= pz);
00809 }
00810
00811
00812 xg = x * inv_dx;
00813 yg = y * inv_dy;
00814 zg = z * inv_dz;
00815
00816
00817 ic = (int) floorf(xg);
00818 jc = (int) floorf(yg);
00819 kc = (int) floorf(zg);
00820
00821
00822 ia = ic - mri;
00823 ib = ic + mri + 1;
00824 ja = jc - mrj;
00825 jb = jc + mrj + 1;
00826 ka = kc - mrk;
00827 kb = kc + mrk + 1;
00828
00829
00830 if ( ! ispx ) {
00831 if (ia < 0) ia = 0;
00832 if (ib >= mx) ib = mx - 1;
00833 }
00834 else {
00835 if (ia-1 < (mx-1) - pxd) {
00836
00837 int na = ((int) floorf(xg + pxd)) - mri;
00838 if (na < 0) na = 0;
00839 ia = na - mx;
00840 }
00841 if (ib+1 > pxd) {
00842
00843 int nb = ((int) floorf(xg - pxd)) + mri + 1;
00844 if (nb >= mx) nb = mx - 1;
00845 ib = nb + mx;
00846 }
00847 }
00848
00849 if ( ! ispy ) {
00850 if (ja < 0) ja = 0;
00851 if (jb >= my) jb = my - 1;
00852 }
00853 else {
00854 if (ja-1 < (my-1) - pyd) {
00855
00856 int na = ((int) floorf(yg + pyd)) - mrj;
00857 if (na < 0) na = 0;
00858 ja = na - my;
00859 }
00860 if (jb+1 > pyd) {
00861
00862 int nb = ((int) floorf(yg - pyd)) + mrj + 1;
00863 if (nb >= my) nb = my - 1;
00864 jb = nb + my;
00865 }
00866 }
00867
00868 if ( ! ispz ) {
00869 if (ka < 0) ka = 0;
00870 if (kb >= mz) kb = mz - 1;
00871 }
00872 else {
00873 if (ka-1 < (mz-1) - pzd) {
00874
00875 int na = ((int) floorf(zg + pzd)) - mrk;
00876 if (na < 0) na = 0;
00877 ka = na - mz;
00878 }
00879 if (kb+1 > pzd) {
00880
00881 int nb = ((int) floorf(zg - pzd)) + mrk + 1;
00882 if (nb >= mz) nb = mz - 1;
00883 kb = nb + mz;
00884 }
00885 }
00886
00887
00888 for (k = ka; k <= kb; k++) {
00889 rz = k*dz - z;
00890 kw = k;
00891 if (k < 0) {
00892 rz -= plz;
00893 kw += mz;
00894 }
00895 else if (k >= mz) {
00896 rz += plz;
00897 kw -= mz;
00898 }
00899 koff = kw*my;
00900 rz2 = rz*rz;
00901
00902 #ifdef MSMPOT_CHECK_CIRCLE_CPU
00903
00904 if (rz2 >= a2) continue;
00905 #endif
00906
00907 for (j = ja; j <= jb; j++) {
00908 ry = j*dy - y;
00909 jw = j;
00910 if (j < 0) {
00911 ry -= ply;
00912 jw += my;
00913 }
00914 else if (j >= my) {
00915 ry += ply;
00916 jw -= my;
00917 }
00918 jkoff = (koff + jw)*(long)mx;
00919 ryrz2 = ry*ry + rz2;
00920
00921 #ifdef MSMPOT_CHECK_CYLINDER_CPU
00922
00923 if (ryrz2 >= a2) continue;
00924 #endif
00925
00926 #if 0
00927 #if defined(__INTEL_COMPILER)
00928 for (i = ia; i <= ib; i++, pem++, rx += dx) {
00929 r2 = rx*rx + ryrz2;
00930 s = r2 * inv_a2;
00931 gs = 1.875f + s*(-1.25f + s*0.375f);
00932 e = q * (1/sqrtf(r2) - a_1 * gs);
00933 *pem += (r2 < a2 ? e : 0);
00934 }
00935 #else
00936 for (i = ia; i <= ib; i++, pem++, rx += dx) {
00937 r2 = rx*rx + ryrz2;
00938 if (r2 >= a2) continue;
00939 s = r2 * inv_a2;
00940 gs = 1.875f + s*(-1.25f + s*0.375f);
00941 e = q * (1/sqrtf(r2) - a_1 * gs);
00942 *pem += e;
00943 }
00944 #endif
00945 #else
00946 for (i = ia; i <= ib; i++) {
00947 rx = i*dx - x;
00948 iw = i;
00949 if (i < 0) {
00950 rx -= plx;
00951 iw += mx;
00952 }
00953 else if (i >= mx) {
00954 rx += plx;
00955 iw -= mx;
00956 }
00957 index = jkoff + iw;
00958 r2 = rx*rx + ryrz2;
00959 if (r2 >= a2) continue;
00960 s = r2 * inv_a2;
00961 SPOLY(&gs, s, split);
00962 e = q * (1/sqrtf(r2) - a_1 * gs);
00963 epotmap[index] += e;
00964 }
00965 #endif
00966
00967 }
00968 }
00969
00970 }
00971 }
00972
00973 return MSMPOT_SUCCESS;
00974 }