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 int Msmpot_check_params(Msmpot *msm, const float *epotmap,
00022 int mx, int my, int mz, float lx, float ly, float lz,
00023 float vx, float vy, float vz, const float *atom, int natoms) {
00024
00025 if (NULL == epotmap) {
00026 return ERRMSG(MSMPOT_ERROR_PARAM, "map buffer is NULL");
00027 }
00028 else if (NULL == atom) {
00029 return ERRMSG(MSMPOT_ERROR_PARAM, "atom array is NULL");
00030 }
00031 else if (natoms <= 0) {
00032 return ERRMSG(MSMPOT_ERROR_PARAM, "number of atoms is not positive");
00033 }
00034 else if (mx <= 0 || my <= 0 || mz <= 0) {
00035 return ERRMSG(MSMPOT_ERROR_PARAM, "number of map points is not positive");
00036 }
00037 else if (lx <= 0 || ly <= 0 || lz <= 0) {
00038 return ERRMSG(MSMPOT_ERROR_PARAM, "map lengths are not positive");
00039 }
00040 else if ((vx <= msm->hmin && vx != 0) || (vy <= msm->hmin && vy != 0)
00041 || (vz <= msm->hmin && vz != 0)) {
00042 return ERRMSG(MSMPOT_ERROR_PARAM,
00043 "periodic cell lengths must be greater than MSM spacing");
00044 }
00045 else if ((lx > vx && vx != 0) || (ly > vy && vy != 0)
00046 || (lz > vz && vz != 0)) {
00047 return ERRMSG(MSMPOT_ERROR_PARAM,
00048 "map lengths must be within periodic cell");
00049 }
00050
00051 return MSMPOT_SUCCESS;
00052 }
00053
00054
00055
00056 void Msmpot_set_defaults(Msmpot *msm) {
00057
00058 msm->hmin = DEFAULT_HMIN;
00059 msm->a = DEFAULT_CUTOFF;
00060 msm->interp = DEFAULT_INTERP;
00061 msm->split = DEFAULT_SPLIT;
00062 msm->bindepth = DEFAULT_BINDEPTH;
00063 msm->binfill = DEFAULT_BINFILL;
00064 msm->density = DEFAULT_DENSITY;
00065 msm->errtol = ((float) DEFAULT_ERRTOL);
00066
00067 #ifdef MSMPOT_CUDA
00068
00069 msm->use_cuda = 1;
00070 msm->cuda_optional = 1;
00071 #endif
00072 }
00073
00074
00075 int Msmpot_configure(Msmpot *msm,
00076 int interp,
00077 int split,
00078 float cutoff,
00079 float hmin,
00080 int nlevels,
00081 float density,
00082 float binfill,
00083 float errtol,
00084 int usecuda
00085 ) {
00086 if (interp < 0 || interp >= MSMPOT_INTERPMAX) {
00087 return ERROR(MSMPOT_ERROR_PARAM);
00088 }
00089 else msm->interp = interp;
00090
00091 if (split < 0 || split >= MSMPOT_SPLITMAX) {
00092 return ERROR(MSMPOT_ERROR_PARAM);
00093 }
00094 else msm->split = split;
00095
00096 if (cutoff < 0) return ERROR(MSMPOT_ERROR_PARAM);
00097 else if (cutoff > 0) msm->a = cutoff;
00098 else msm->a = DEFAULT_CUTOFF;
00099
00100 if (hmin < 0) return ERROR(MSMPOT_ERROR_PARAM);
00101 else if (hmin > 0) msm->hmin = hmin;
00102 else msm->hmin = DEFAULT_HMIN;
00103
00104 if (nlevels < 0) return ERROR(MSMPOT_ERROR_PARAM);
00105 else msm->nlevels = nlevels;
00106
00107 if (density < 0) return ERROR(MSMPOT_ERROR_PARAM);
00108 else if (density > 0) msm->density = density;
00109 else msm->density = DEFAULT_DENSITY;
00110
00111 if (binfill < 0) return ERROR(MSMPOT_ERROR_PARAM);
00112 else if (binfill > 0) msm->binfill = binfill;
00113 else msm->binfill = DEFAULT_BINFILL;
00114
00115 if (errtol < 0) return ERROR(MSMPOT_ERROR_PARAM);
00116 else if (errtol > 0) msm->errtol = errtol;
00117 else msm->errtol = ((float) DEFAULT_ERRTOL);
00118
00119 #ifdef MSMPOT_CUDA
00120 msm->use_cuda = (usecuda != 0);
00121 #else
00122 if (usecuda != 0) {
00123 return ERROR(MSMPOT_ERROR_SUPPORT);
00124 }
00125 #endif
00126
00127 return MSMPOT_SUCCESS;
00128 }
00129
00130
00131
00132 void Msmpot_cleanup(Msmpot *msm) {
00133 int i;
00134 for (i = 0; i < msm->maxlevels; i++) {
00135 GRID_DONE( &(msm->qh[i]) );
00136 GRID_DONE( &(msm->eh[i]) );
00137 GRID_DONE( &(msm->gc[i]) );
00138 }
00139 free(msm->qh);
00140 free(msm->eh);
00141 free(msm->gc);
00142 free(msm->ezd);
00143 free(msm->eyzd);
00144 free(msm->lzd);
00145 free(msm->lyzd);
00146 free(msm->phi_x);
00147 free(msm->phi_y);
00148 free(msm->phi_z);
00149
00150 free(msm->first_atom_index);
00151 free(msm->next_atom_index);
00152
00153 free(msm->bin);
00154 free(msm->bincount);
00155 free(msm->over);
00156 free(msm->boff);
00157 }
00158
00159
00160 static int setup_domain(Msmpot *msm);
00161 static int setup_bins(Msmpot *msm);
00162 static int setup_origin(Msmpot *msm);
00163
00164 static int setup_hierarchy(Msmpot *msm);
00165
00166
00167 static int setup_periodic_hlevelparams_1d(Msmpot *msm,
00168 float len,
00169 float *hh,
00170 int *nn,
00171 int *aindex,
00172 int *bindex
00173 );
00174
00175
00176 static int setup_nonperiodic_hlevelparams_1d(Msmpot *msm,
00177 float len,
00178 float *hh,
00179 int *nn,
00180 int *aindex,
00181 int *bindex
00182 );
00183
00184 static int setup_mapinterp(Msmpot *msm);
00185
00186 static int setup_mapinterpcoef_1d(Msmpot *msm,
00187 float h,
00188 float delta,
00189 int n,
00190 int m,
00191 float *p_h_delta,
00192 int *p_cycle,
00193 int *p_rmap,
00194 float **p_phi,
00195 int *p_max_phi
00196 );
00197
00198
00199 #ifdef MSMPOT_VERBOSE
00200 static int print_status(Msmpot *msm);
00201 #endif
00202
00203
00204
00205 int Msmpot_setup(Msmpot *msm) {
00206 int err = 0;
00207
00208 REPORT("Setting up for MSM computation.");
00209
00210
00211 err = setup_domain(msm);
00212 if (err) return ERROR(err);
00213
00214
00215 err = setup_bins(msm);
00216 if (err) return ERROR(err);
00217
00218
00219 err = setup_origin(msm);
00220 if (err) return ERROR(err);
00221
00222
00223 err = setup_hierarchy(msm);
00224 if (err) return ERROR(err);
00225
00226
00227 #if ! defined(MSMPOT_SHORTRANGE_ONLY)
00228 if (msm->px == msm->lx && msm->py == msm->ly && msm->pz == msm->lz) {
00229
00230
00231 err = setup_mapinterp(msm);
00232 if (err) return ERROR(err);
00233 }
00234 #endif
00235
00236
00237 #ifdef MSMPOT_VERBOSE
00238 err = print_status(msm);
00239 if (err) return ERROR(err);
00240 #endif
00241
00242 #ifdef MSMPOT_CUDA
00243
00244 if (msm->use_cuda) {
00245 err = Msmpot_cuda_setup(msm->msmcuda, msm);
00246 if (err) return ERROR(err);
00247 }
00248 #endif
00249
00250 return MSMPOT_SUCCESS;
00251 }
00252
00253
00254 typedef struct InterpParams_t {
00255 int nu;
00256 int stencil;
00257 int omega;
00258 } InterpParams;
00259
00260 static InterpParams INTERP_PARAMS[] = {
00261 { 1, 4, 6 },
00262 { 2, 6, 10 },
00263 { 2, 6, 10 },
00264 { 3, 8, 14 },
00265 { 3, 8, 14 },
00266 { 4, 10, 18 },
00267 { 4, 10, 18 },
00268 };
00269
00270
00271 #ifdef MSMPOT_VERBOSE
00272 int print_status(Msmpot *msm) {
00273 int j, k;
00274 int ispx = (IS_SET_X(msm->isperiodic) != 0);
00275 int ispy = (IS_SET_Y(msm->isperiodic) != 0);
00276 int ispz = (IS_SET_Z(msm->isperiodic) != 0);
00277 int ispany = (IS_SET_ANY(msm->isperiodic) != 0);
00278 printf("#MSMPOT STATUS\n");
00279 printf("# natoms= %d\n", msm->natoms);
00280 printf("# domain lengths= %g %g %g\n", msm->px, msm->py, msm->pz);
00281 printf("# domain origin= %g %g %g\n", msm->px0, msm->py0, msm->pz0);
00282 printf("# map size= %d x %d x %d\n", msm->mx, msm->my, msm->mz);
00283 printf("# map spacing= %g, %g, %g\n", msm->dx, msm->dy, msm->dz);
00284 printf("# map lengths= %g, %g, %g\n", msm->lx, msm->ly, msm->lz);
00285 printf("# map origin= %g, %g, %g\n", msm->lx0, msm->ly0, msm->lz0);
00286 printf("# hmin= %g\n", msm->hmin);
00287 printf("# cutoff= %g\n", msm->a);
00288 printf("# MSM size= %d x %d x %d\n", msm->nx, msm->ny, msm->nz);
00289 printf("# MSM spacing= %g, %g, %g\n", msm->hx, msm->hy, msm->hz);
00290 printf("# MSM interpolation= %d\n", msm->interp);
00291 printf("# MSM splitting= %d\n", msm->split);
00292 printf("# MSM number of levels= %d\n", msm->nlevels);
00293 printf("# MSM lattice hierarchy:\n");
00294 for (k = 0; k < msm->nlevels; k++) {
00295 floatGrid *qh = &(msm->qh[k]);
00296 int ia = qh->i0;
00297 int ib = ia + qh->ni - 1;
00298 int ja = qh->j0;
00299 int jb = ja + qh->nj - 1;
00300 int ka = qh->k0;
00301 int kb = ka + qh->nk - 1;
00302 printf("# level= %d: [%d..%d] x [%d..%d] x [%d..%d]\n",
00303 k, ia, ib, ja, jb, ka, kb);
00304 }
00305 printf("# ispx= %d ispy= %d ispz= %d ispany= %d\n",
00306 ispx, ispy, ispz, ispany);
00307 printf("# hx_dx= %g hy_dy= %g hz_dz= %g\n",
00308 msm->hx_dx, msm->hy_dy, msm->hz_dz);
00309 printf("# cycle_x= %d rmap_x= %d\n", msm->cycle_x, msm->rmap_x);
00310 for (k = 0; k < msm->cycle_x; k++) {
00311 int jtotal = 2*msm->rmap_x + 1;
00312 float *phi = msm->phi_x + k*jtotal;
00313 float phisum = 0;
00314 for (j = 0; j < jtotal; j++) phisum += phi[j];
00315 printf("# %d: sum= %g (", k, phisum);
00316 for (j = 0; j < jtotal; j++) {
00317 printf("%s%g", (0==j ? "= " : " + "), phi[j]);
00318 }
00319 printf(")\n");
00320 }
00321 printf("# cycle_y= %d rmap_y= %d\n", msm->cycle_y, msm->rmap_y);
00322 for (k = 0; k < msm->cycle_y; k++) {
00323 int jtotal = 2*msm->rmap_y + 1;
00324 float *phi = msm->phi_y + k*jtotal;
00325 float phisum = 0;
00326 for (j = 0; j < jtotal; j++) phisum += phi[j];
00327 printf("# %d: sum= %g (", k, phisum);
00328 for (j = 0; j < jtotal; j++) {
00329 printf("%s%g", (0==j ? "= " : " + "), phi[j]);
00330 }
00331 printf(")\n");
00332 }
00333 printf("# cycle_z= %d rmap_z= %d\n", msm->cycle_z, msm->rmap_z);
00334 for (k = 0; k < msm->cycle_z; k++) {
00335 int jtotal = 2*msm->rmap_z + 1;
00336 float *phi = msm->phi_z + k*jtotal;
00337 float phisum = 0;
00338 for (j = 0; j < jtotal; j++) phisum += phi[j];
00339 printf("# %d: sum= %g (", k, phisum);
00340 for (j = 0; j < jtotal; j++) {
00341 printf("%s%g", (0==j ? "= " : " + "), phi[j]);
00342 }
00343 printf(")\n");
00344 }
00345 printf("# bin size= %g %g %g\n", msm->bx, msm->by, msm->bz);
00346 printf("# atom bins= %d x %d x %d\n",
00347 msm->nbx, msm->nby, msm->nbz);
00348 return MSMPOT_SUCCESS;
00349 }
00350 #endif
00351
00352
00353 int setup_mapinterp(Msmpot *msm) {
00354 int mymz = msm->my * msm->mz;
00355 int err = 0;
00356
00357 ASSERT(msm->mx > 0);
00358 ASSERT(msm->my > 0);
00359 ASSERT(msm->mz > 0);
00360 if (msm->max_eyzd < mymz) {
00361 float *t;
00362 t = (float *) realloc(msm->eyzd, mymz * sizeof(float));
00363 if (NULL == t) return ERROR(MSMPOT_ERROR_MALLOC);
00364 msm->eyzd = t;
00365 msm->max_eyzd = mymz;
00366 }
00367 if (msm->max_ezd < msm->mz) {
00368 float *t;
00369 t = (float *) realloc(msm->ezd, msm->mz * sizeof(float));
00370 if (NULL == t) return ERROR(MSMPOT_ERROR_MALLOC);
00371 msm->ezd = t;
00372 msm->max_ezd = msm->mz;
00373 }
00374
00375 if (msm->px != msm->lx
00376 || msm->py != msm->ly
00377 || msm->pz != msm->lz) {
00378
00379 printf("px = %f lx = %f\n", msm->px, msm->lx);
00380 return ERRMSG(MSMPOT_ERROR_SUPPORT,
00381 "can't do interpolation for map lengths "
00382 "not equal to atom domain lengths");
00383 }
00384
00385
00386 err |= setup_mapinterpcoef_1d(msm,
00387 msm->hx, msm->dx, msm->nx, msm->mx, &(msm->hx_dx),
00388 &(msm->cycle_x), &(msm->rmap_x), &(msm->phi_x), &(msm->max_phi_x));
00389 err |= setup_mapinterpcoef_1d(msm,
00390 msm->hy, msm->dy, msm->ny, msm->my, &(msm->hy_dy),
00391 &(msm->cycle_y), &(msm->rmap_y), &(msm->phi_y), &(msm->max_phi_y));
00392 err |= setup_mapinterpcoef_1d(msm,
00393 msm->hz, msm->dz, msm->nz, msm->mz, &(msm->hz_dz),
00394 &(msm->cycle_z), &(msm->rmap_z), &(msm->phi_z), &(msm->max_phi_z));
00395 if (err) return ERROR(err);
00396
00397
00398 return MSMPOT_SUCCESS;
00399 }
00400
00401
00402 static int gcd(int a, int b) {
00403
00404 if (0 == a) return b;
00405 while (b != 0) {
00406 if (a > b) a -= b;
00407 else b -= a;
00408 }
00409 return a;
00410 }
00411
00412
00413 int setup_mapinterpcoef_1d(Msmpot *msm,
00414 float h,
00415 float delta,
00416 int n,
00417 int m,
00418 float *p_h_delta,
00419 int *p_cycle,
00420 int *p_rmap,
00421 float **p_phi,
00422 int *p_max_phi
00423 ) {
00424 float *phi = NULL;
00425 const int nu = INTERP_PARAMS[msm->interp].nu;
00426 float delta_h, h_delta, t;
00427 int cycle, rmap, diam, nphi;
00428 int i, k;
00429
00430 *p_h_delta = h_delta = h / delta;
00431 *p_cycle = cycle = n / gcd(m, n);
00432 *p_rmap = rmap = (int) ceilf(h_delta * (nu+1));
00433
00434 delta_h = delta / h;
00435 diam = 2*rmap + 1;
00436 nphi = diam * cycle;
00437
00438 if (*p_max_phi < nphi) {
00439 phi = (float *) realloc(*p_phi, nphi * sizeof(float));
00440 if (NULL == phi) return ERROR(MSMPOT_ERROR_MALLOC);
00441 *p_phi = phi;
00442 *p_max_phi = nphi;
00443 }
00444 ASSERT(*p_phi != NULL);
00445
00446 for (k = 0; k < cycle; k++) {
00447 float offset = floorf(k * h_delta) * delta_h - k;
00448 phi = *p_phi + k * diam + rmap;
00449 switch (msm->interp) {
00450 case MSMPOT_INTERP_CUBIC:
00451 for (i = -rmap; i <= rmap; i++) {
00452 t = fabsf(i * delta_h + offset);
00453 if (t <= 1) {
00454 phi[i] = (1 - t) * (1 + t - 1.5f * t * t);
00455 }
00456 else if (t <= 2) {
00457 phi[i] = 0.5f * (1 - t) * (2 - t) * (2 - t);
00458 }
00459 else {
00460 phi[i] = 0;
00461 }
00462 }
00463 break;
00464 case MSMPOT_INTERP_QUINTIC:
00465 for (i = -rmap; i <= rmap; i++) {
00466 t = fabsf(i * delta_h);
00467 if (t <= 1) {
00468 phi[i] = (1-t*t) * (2-t) * (0.5f + t * (0.25f - (5.f/12)*t));
00469 }
00470 else if (t <= 2) {
00471 phi[i] = (1-t)*(2-t)*(3-t) * ((1.f/6) + t*(0.375f - (5.f/24)*t));
00472 }
00473 else if (t <= 3) {
00474 phi[i] = (1.f/24) * (1-t) * (2-t) * (3-t) * (3-t) * (4-t);
00475 }
00476 else {
00477 phi[i] = 0;
00478 }
00479 }
00480 break;
00481 default:
00482 return ERRMSG(MSMPOT_ERROR_SUPPORT,
00483 "interpolation method not implemented");
00484 }
00485 }
00486 return MSMPOT_SUCCESS;
00487 }
00488
00489
00490 int setup_domain(Msmpot *msm) {
00491 const float *atom = msm->atom;
00492 const int natoms = msm->natoms;
00493 int n;
00494 float xmin, xmax, ymin, ymax, zmin, zmax;
00495
00496
00497 ASSERT(natoms > 0);
00498 xmin = xmax = atom[ATOM_X(0)];
00499 ymin = ymax = atom[ATOM_Y(0)];
00500 zmin = zmax = atom[ATOM_Z(0)];
00501 for (n = 1; n < natoms; n++) {
00502 float x = atom[ATOM_X(n)];
00503 float y = atom[ATOM_Y(n)];
00504 float z = atom[ATOM_Z(n)];
00505 if (xmin > x) xmin = x;
00506 else if (xmax < x) xmax = x;
00507 if (ymin > y) ymin = y;
00508 else if (ymax < y) ymax = y;
00509 if (zmin > z) zmin = z;
00510 else if (zmax < z) zmax = z;
00511 }
00512
00513
00514 msm->xmin = xmin;
00515 msm->xmax = xmax;
00516 msm->ymin = ymin;
00517 msm->ymax = ymax;
00518 msm->zmin = zmin;
00519 msm->zmax = zmax;
00520
00521 #if 1
00522
00523 if ( ! IS_SET_X(msm->isperiodic) ) {
00524 float lx1 = msm->lx0 + msm->lx;
00525 if (xmin >= msm->lx0 && xmax < lx1) {
00526 msm->px = msm->lx;
00527 msm->px0 = msm->lx0;
00528 }
00529 else {
00530 if (xmin > msm->lx0) xmin = msm->lx0;
00531 msm->px0 = xmin;
00532 if (xmax < lx1) {
00533 xmax = lx1;
00534 msm->px = xmax - xmin;
00535 }
00536 else {
00537 msm->px = xmax - xmin + msm->dx;
00538 }
00539 }
00540 }
00541 if ( ! IS_SET_Y(msm->isperiodic) ) {
00542 float ly1 = msm->ly0 + msm->ly;
00543 if (ymin >= msm->ly0 && ymax < ly1) {
00544 msm->py = msm->ly;
00545 msm->py0 = msm->ly0;
00546 }
00547 else {
00548 if (ymin > msm->ly0) ymin = msm->ly0;
00549 msm->py0 = ymin;
00550 if (ymax < ly1) {
00551 ymax = ly1;
00552 msm->py = ymax - ymin;
00553 }
00554 else {
00555 msm->py = ymax - ymin + msm->dy;
00556 }
00557 }
00558 }
00559 if ( ! IS_SET_Z(msm->isperiodic) ) {
00560 float lz1 = msm->lz0 + msm->lz;
00561 if (zmin >= msm->lz0 && zmax < lz1) {
00562 msm->pz = msm->lz;
00563 msm->pz0 = msm->lz0;
00564 }
00565 else {
00566 if (zmin > msm->lz0) zmin = msm->lz0;
00567 msm->pz0 = zmin;
00568 if (zmax < lz1) {
00569 zmax = lz1;
00570 msm->pz = zmax - zmin;
00571 }
00572 else {
00573 msm->pz = zmax - zmin + msm->dz;
00574 }
00575 }
00576 }
00577 #else
00578
00579 if ( ! IS_SET_X(msm->isperiodic) ) {
00580 float lx1 = msm->lx0 + msm->lx;
00581 if (xmin >= msm->lx0 && xmax < lx1) {
00582 msm->px = msm->lx;
00583 msm->px0 = msm->lx0;
00584 }
00585 else {
00586 if (xmin > msm->lx0) xmin = msm->lx0;
00587 if (xmax < lx1) xmax = lx1;
00588 msm->px = xmax - xmin;
00589 msm->px0 = xmin;
00590 }
00591 }
00592 if ( ! IS_SET_Y(msm->isperiodic) ) {
00593 float ly1 = msm->ly0 + msm->ly;
00594 if (ymin >= msm->ly0 && ymax < ly1) {
00595 msm->py = msm->ly;
00596 msm->py0 = msm->ly0;
00597 }
00598 else {
00599 if (ymin > msm->ly0) ymin = msm->ly0;
00600 if (ymax < ly1) ymax = ly1;
00601 msm->py = ymax - ymin;
00602 msm->py0 = ymin;
00603 }
00604 }
00605 if ( ! IS_SET_Z(msm->isperiodic) ) {
00606 float lz1 = msm->lz0 + msm->lz;
00607 if (zmin >= msm->lz0 && zmax < lz1) {
00608 msm->pz = msm->lz;
00609 msm->pz0 = msm->lz0;
00610 }
00611 else {
00612 if (zmin > msm->lz0) zmin = msm->lz0;
00613 if (zmax < lz1) zmax = lz1;
00614 msm->pz = zmax - zmin;
00615 msm->pz0 = zmin;
00616 }
00617 }
00618 #endif
00619
00620 return MSMPOT_SUCCESS;
00621 }
00622
00623
00624
00625
00626
00627
00628 int setup_bins(Msmpot *msm) {
00629
00630 float vol = msm->binfill * msm->bindepth / msm->density;
00631 float blen = powf(vol, 1.f/3);
00632 int maxbin;
00633 int nbx = (int) ceilf(msm->px / blen);
00634 int nby = (int) ceilf(msm->py / blen);
00635 int nbz = (int) ceilf(msm->pz / blen);
00636
00637 ASSERT(nbx > 0);
00638 ASSERT(nby > 0);
00639 ASSERT(nbz > 0);
00640
00641 maxbin = nbx * nby * nbz;
00642 if (msm->maxbin < maxbin) {
00643 void *v;
00644 size_t floatsperbin = msm->bindepth * ATOM_SIZE;
00645 v = realloc(msm->bin, maxbin * floatsperbin * sizeof(float));
00646 if (NULL == v) return ERROR(MSMPOT_ERROR_MALLOC);
00647 msm->bin = (float *) v;
00648 v = realloc(msm->bincount, maxbin * sizeof(int));
00649 if (NULL == v) return ERROR(MSMPOT_ERROR_MALLOC);
00650 msm->bincount = (int *) v;
00651 msm->maxbin = maxbin;
00652
00653
00654 v = realloc(msm->first_atom_index, maxbin * sizeof(int));
00655 if (NULL == v) return ERROR(MSMPOT_ERROR_MALLOC);
00656 msm->first_atom_index = (int *) v;
00657
00658 }
00659
00660
00661 if (msm->maxatoms < msm->natoms) {
00662 void *v;
00663 v = realloc(msm->next_atom_index, msm->natoms * sizeof(int));
00664 if (NULL == v) return ERROR(MSMPOT_ERROR_MALLOC);
00665 msm->next_atom_index = (int *) v;
00666 msm->maxatoms = msm->natoms;
00667 }
00668
00669
00670 msm->nbx = nbx;
00671 msm->nby = nby;
00672 msm->nbz = nbz;
00673
00674 msm->bx = msm->px / nbx;
00675 msm->by = msm->py / nby;
00676 msm->bz = msm->pz / nbz;
00677
00678 msm->invbx = 1 / msm->bx;
00679 msm->invby = 1 / msm->by;
00680 msm->invbz = 1 / msm->bz;
00681
00682 if (msm->maxover < DEFAULT_OVER) {
00683 void *vover = realloc(msm->over, DEFAULT_OVER * ATOM_SIZE * sizeof(float));
00684 if (NULL == vover) return ERROR(MSMPOT_ERROR_MALLOC);
00685 msm->over = (float *) vover;
00686 msm->maxover = DEFAULT_OVER;
00687 }
00688
00689 return MSMPOT_SUCCESS;
00690 }
00691
00692
00693 int setup_origin(Msmpot *msm) {
00694
00695
00696
00697 msm->isbinwrap = 0;
00698 msm->islongcutoff = 0;
00699
00700 if (IS_SET_X(msm->isperiodic)) {
00701
00702 int mbx = (int) ceilf(msm->a * msm->invbx);
00703 if (msm->lx < (msm->px - 2*mbx*msm->bx)) {
00704
00705 msm->px0 = msm->lx0 - mbx * msm->bx;
00706 }
00707 else {
00708
00709 msm->px0 = msm->lx0;
00710 SET_X(msm->isbinwrap);
00711 if (mbx > msm->nbx) SET_X(msm->islongcutoff);
00712 }
00713 }
00714
00715 if (IS_SET_Y(msm->isperiodic)) {
00716
00717 int mby = (int) ceilf(msm->a * msm->invby);
00718 if (msm->ly < (msm->py - 2*mby*msm->by)) {
00719
00720 msm->py0 = msm->ly0 - mby * msm->by;
00721 }
00722 else {
00723
00724 msm->py0 = msm->ly0;
00725 SET_Y(msm->isbinwrap);
00726 if (mby > msm->nby) SET_Y(msm->islongcutoff);
00727 }
00728 }
00729
00730 if (IS_SET_Z(msm->isperiodic)) {
00731
00732 int mbz = (int) ceilf(msm->a * msm->invbz);
00733 if (msm->lz < (msm->pz - 2*mbz*msm->bz)) {
00734
00735 msm->pz0 = msm->lz0 - mbz * msm->bz;
00736 }
00737 else {
00738
00739 msm->pz0 = msm->lz0;
00740 SET_Z(msm->isbinwrap);
00741 if (mbz > msm->nbz) SET_Z(msm->islongcutoff);
00742 }
00743 }
00744
00745 return MSMPOT_SUCCESS;
00746 }
00747
00748
00749 int setup_nonperiodic_hlevelparams_1d(Msmpot *msm,
00750 float len,
00751 float *hh,
00752 int *nn,
00753 int *aindex,
00754 int *bindex
00755 ) {
00756 const float hmin = msm->hmin;
00757 const int nu = INTERP_PARAMS[msm->interp].nu;
00758
00759 int n = (int) floorf(len / hmin) + 1;
00760 *hh = hmin;
00761 *nn = n;
00762 *aindex = -nu;
00763 *bindex = n + nu;
00764 return MSMPOT_SUCCESS;
00765 }
00766
00767
00768 int setup_periodic_hlevelparams_1d(Msmpot *msm,
00769 float len,
00770 float *hh,
00771 int *nn,
00772 int *aindex,
00773 int *bindex
00774 ) {
00775 const float hmin = msm->hmin;
00776 const float hmax = 1.5f * hmin;
00777 float h = len;
00778 int n = 1;
00779 while (h >= hmax) {
00780 h *= 0.5f;
00781 n <<= 1;
00782 }
00783 if (h < hmin) {
00784 if (n < 4) {
00785 return ERRMSG(MSMPOT_ERROR_PARAM,
00786 "ratio of domain length to hmin is too small");
00787 }
00788 h *= (4.f/3);
00789 n >>= 2;
00790 n *= 3;
00791 }
00792
00793
00794 *hh = h;
00795 *nn = n;
00796 *aindex = 0;
00797 *bindex = n-1;
00798 return MSMPOT_SUCCESS;
00799 }
00800
00801
00802 int setup_hierarchy(Msmpot *msm) {
00803 const int nu = INTERP_PARAMS[msm->interp].nu;
00804 const int omega = INTERP_PARAMS[msm->interp].omega;
00805 const int split = msm->split;
00806 const int ispx = IS_SET_X(msm->isperiodic);
00807 const int ispy = IS_SET_Y(msm->isperiodic);
00808 const int ispz = IS_SET_Z(msm->isperiodic);
00809 const int ispany = IS_SET_ANY(msm->isperiodic);
00810 const float a = msm->a;
00811 float hx, hy, hz;
00812 float scaling;
00813
00814 floatGrid *p = NULL;
00815 int ia, ib, ja, jb, ka, kb, ni, nj, nk;
00816 int nx, ny, nz;
00817
00818 int i, j, k, n;
00819 int index;
00820 int level, toplevel, nlevels, maxlevels;
00821 int lastnelems = 1;
00822 int isclamped = 0;
00823 int done, alldone;
00824
00825 int err = 0;
00826
00827 if (ispx) {
00828 err = setup_periodic_hlevelparams_1d(msm, msm->px, &hx, &nx, &ia, &ib);
00829 }
00830 else {
00831 float xmax = msm->lx0 + msm->lx - msm->dx;
00832 if (xmax < msm->xmax) xmax = msm->xmax;
00833 err = setup_nonperiodic_hlevelparams_1d(msm, xmax - msm->px0,
00834 &hx, &nx, &ia, &ib);
00835 }
00836 if (err) return ERROR(err);
00837
00838 if (ispy) {
00839 err = setup_periodic_hlevelparams_1d(msm, msm->py, &hy, &ny, &ja, &jb);
00840 }
00841 else {
00842 float ymax = msm->ly0 + msm->ly - msm->dy;
00843 if (ymax < msm->ymax) ymax = msm->ymax;
00844 err = setup_nonperiodic_hlevelparams_1d(msm, ymax - msm->py0,
00845 &hy, &ny, &ja, &jb);
00846 }
00847 if (err) return ERROR(err);
00848
00849 if (ispz) {
00850 err = setup_periodic_hlevelparams_1d(msm, msm->pz, &hz, &nz, &ka, &kb);
00851 }
00852 else {
00853 float zmax = msm->lz0 + msm->lz - msm->dz;
00854 if (zmax < msm->zmax) zmax = msm->zmax;
00855 err = setup_nonperiodic_hlevelparams_1d(msm, zmax - msm->pz0,
00856 &hz, &nz, &ka, &kb);
00857 }
00858 if (err) return ERROR(err);
00859
00860 msm->hx = hx;
00861 msm->hy = hy;
00862 msm->hz = hz;
00863
00864 msm->nx = nx;
00865 msm->ny = ny;
00866 msm->nz = nz;
00867
00868 ni = ib - ia + 1;
00869 nj = jb - ja + 1;
00870 nk = kb - ka + 1;
00871
00872
00873 n = (nk > omega ? nk : omega);
00874 if (msm->max_lzd < n) {
00875 float *t;
00876 t = (float *) realloc(msm->lzd, n * sizeof(float));
00877 if (NULL == t) return ERROR(MSMPOT_ERROR_MALLOC);
00878 msm->lzd = t;
00879 msm->max_lzd = n;
00880 }
00881 n *= (nj > omega ? nj : omega);
00882 if (msm->max_lyzd < n) {
00883 float *t;
00884 t = (float *) realloc(msm->lyzd, n * sizeof(float));
00885 if (NULL == t) return ERROR(MSMPOT_ERROR_MALLOC);
00886 msm->lyzd = t;
00887 msm->max_lyzd = n;
00888 }
00889
00890 nlevels = msm->nlevels;
00891 if (nlevels <= 0) {
00892
00893 n = ni;
00894 if (n < nj) n = nj;
00895 if (n < nk) n = nk;
00896 for (maxlevels = 1; n > 0; n >>= 1) maxlevels++;
00897 nlevels = maxlevels;
00898 if ( ! ispany ) {
00899 int omega3 = omega * omega * omega;
00900 int nhalf = (int) sqrtf((float) ni*nj*nk);
00901 lastnelems = (nhalf > omega3 ? nhalf : omega3);
00902 isclamped = 1;
00903 }
00904 }
00905 else {
00906
00907 maxlevels = nlevels;
00908 }
00909
00910
00911 if (msm->maxlevels < maxlevels) {
00912 void *vqh, *veh, *vgc;
00913 vqh = realloc(msm->qh, maxlevels * sizeof(floatGrid));
00914 if (NULL == vqh) return ERROR(MSMPOT_ERROR_MALLOC);
00915 veh = realloc(msm->eh, maxlevels * sizeof(floatGrid));
00916 if (NULL == veh) return ERROR(MSMPOT_ERROR_MALLOC);
00917 vgc = realloc(msm->gc, maxlevels * sizeof(floatGrid));
00918 if (NULL == vgc) return ERROR(MSMPOT_ERROR_MALLOC);
00919 msm->qh = (floatGrid *) vqh;
00920 msm->eh = (floatGrid *) veh;
00921 msm->gc = (floatGrid *) vgc;
00922
00923 for (level = msm->maxlevels; level < maxlevels; level++) {
00924 GRID_INIT( &(msm->qh[level]) );
00925 GRID_INIT( &(msm->eh[level]) );
00926 GRID_INIT( &(msm->gc[level]) );
00927 }
00928 msm->maxlevels = maxlevels;
00929 }
00930
00931 level = 0;
00932 done = 0;
00933 alldone = 0;
00934 do {
00935 GRID_RESIZE( &(msm->qh[level]), ia, ni, ja, nj, ka, nk);
00936 GRID_RESIZE( &(msm->eh[level]), ia, ni, ja, nj, ka, nk);
00937
00938 if (++level == nlevels) done |= 0x07;
00939
00940 alldone = (done == 0x07);
00941
00942 if (isclamped) {
00943 int nelems = ni * nj * nk;
00944 if (nelems <= lastnelems) done |= 0x07;
00945 }
00946
00947 if (ispx) {
00948 ni >>= 1;
00949 ib = ni-1;
00950 if (ni & 1) done |= 0x07;
00951 else if (ni == 2) done |= 0x01;
00952 }
00953 else {
00954 ia = -((-ia+1)/2) - nu;
00955 ib = (ib+1)/2 + nu;
00956 ni = ib - ia + 1;
00957 if (ni <= omega) done |= 0x01;
00958 }
00959
00960 if (ispy) {
00961 nj >>= 1;
00962 jb = nj-1;
00963 if (nj & 1) done |= 0x07;
00964 else if (nj == 2) done |= 0x02;
00965 }
00966 else {
00967 ja = -((-ja+1)/2) - nu;
00968 jb = (jb+1)/2 + nu;
00969 nj = jb - ja + 1;
00970 if (nj <= omega) done |= 0x02;
00971 }
00972
00973 if (ispz) {
00974 nk >>= 1;
00975 kb = nk-1;
00976 if (nk & 1) done |= 0x07;
00977 else if (nk == 2) done |= 0x04;
00978 }
00979 else {
00980 ka = -((-ka+1)/2) - nu;
00981 kb = (kb+1)/2 + nu;
00982 nk = kb - ka + 1;
00983 if (nk <= omega) done |= 0x04;
00984 }
00985
00986 } while ( ! alldone );
00987 msm->nlevels = level;
00988
00989 toplevel = (ispany ? msm->nlevels : msm->nlevels - 1);
00990
00991
00992 ni = (int) ceilf(2*a/hx) - 1;
00993 nj = (int) ceilf(2*a/hy) - 1;
00994 nk = (int) ceilf(2*a/hz) - 1;
00995 scaling = 1;
00996 for (level = 0; level < toplevel; level++) {
00997 p = &(msm->gc[level]);
00998 GRID_RESIZE(p, -ni, 2*ni+1, -nj, 2*nj+1, -nk, 2*nk+1);
00999
01000 if (0 == level) {
01001 index = 0;
01002 for (k = -nk; k <= nk; k++) {
01003 for (j = -nj; j <= nj; j++) {
01004 for (i = -ni; i <= ni; i++) {
01005 float s, t, gs, gt, g;
01006 s = ( (i*hx)*(i*hx) + (j*hy)*(j*hy) + (k*hz)*(k*hz) ) / (a*a);
01007 t = 0.25f * s;
01008 if (t >= 1) {
01009 g = 0;
01010 }
01011 else if (s >= 1) {
01012 gs = 1/sqrtf(s);
01013 SPOLY(>, t, split);
01014 g = (gs - 0.5f * gt) / a;
01015 }
01016 else {
01017 SPOLY(&gs, s, split);
01018 SPOLY(>, t, split);
01019 g = (gs - 0.5f * gt) / a;
01020 }
01021 GRID_INDEX_CHECK(p, i, j, k);
01022 ASSERT( p->buffer + index == p->data + GRID_INDEX(p, i, j, k) );
01023 p->buffer[index] = g;
01024 index++;
01025 }
01026 }
01027 }
01028 }
01029 else {
01030
01031 const floatGrid *first = &(msm->gc[0]);
01032 scaling *= 0.5f;
01033 index = 0;
01034 for (k = -nk; k <= nk; k++) {
01035 for (j = -nj; j <= nj; j++) {
01036 for (i = -ni; i <= ni; i++) {
01037 GRID_INDEX_CHECK(p, i, j, k);
01038 ASSERT( p->buffer + index == p->data + GRID_INDEX(p, i, j, k) );
01039 p->buffer[index] = scaling * first->buffer[index];
01040 index++;
01041 }
01042 }
01043 }
01044 }
01045 }
01046
01047 if (toplevel < msm->nlevels) {
01048
01049
01050 const floatGrid *qhtop = &(msm->qh[toplevel]);
01051 ni = qhtop->ni - 1;
01052 nj = qhtop->nj - 1;
01053 nk = qhtop->nk - 1;
01054 p = &(msm->gc[toplevel]);
01055 GRID_RESIZE(p, -ni, 2*ni+1, -nj, 2*nj+1, -nk, 2*nk+1);
01056 scaling *= 0.5f;
01057 index = 0;
01058 for (k = -nk; k <= nk; k++) {
01059 for (j = -nj; j <= nj; j++) {
01060 for (i = -ni; i <= ni; i++) {
01061 float s, gs;
01062 s = ( (i*hx)*(i*hx) + (j*hy)*(j*hy) + (k*hz)*(k*hz) ) / (a*a);
01063 if (s >= 1) {
01064 gs = 1/sqrtf(s);
01065 }
01066 else {
01067 SPOLY(&gs, s, split);
01068 }
01069 GRID_INDEX_CHECK(p, i, j, k);
01070 ASSERT( p->buffer + index == p->data + GRID_INDEX(p, i, j, k) );
01071 p->buffer[index] = scaling * gs/a;
01072 index++;
01073 }
01074 }
01075 }
01076 }
01077
01078 return 0;
01079 }