00001
00049 #include "apbscfg.h"
00050 #include "apbs/vclist.h"
00051
00052 #if defined(HAVE_MC_H)
00053 #include "mc/mc.h"
00054 #endif
00055
00056 VEMBED(rcsid="$Id: vclist.c 1552 2010-02-10 17:46:27Z yhuang01 $")
00057
00058 #if !defined(VINLINE_VCLIST)
00059
00060 VPUBLIC unsigned long int Vclist_memChk(Vclist *thee) {
00061 if (thee == VNULL) return 0;
00062 return Vmem_bytes(thee->vmem);
00063 }
00064
00065 VPUBLIC double Vclist_maxRadius(Vclist *thee) {
00066 VASSERT(thee != VNULL);
00067 return thee->max_radius;
00068 }
00069
00070 #endif
00071
00072 VPUBLIC Vclist* Vclist_ctor(Valist *alist, double max_radius,
00073 int npts[VAPBS_DIM], Vclist_DomainMode mode,
00074 double lower_corner[VAPBS_DIM], double upper_corner[VAPBS_DIM]) {
00075
00076 Vclist *thee = VNULL;
00077
00078
00079 thee = Vmem_malloc(VNULL, 1, sizeof(Vclist) );
00080 VASSERT( thee != VNULL);
00081 VASSERT( Vclist_ctor2(thee, alist, max_radius, npts, mode, lower_corner,
00082 upper_corner) == VRC_SUCCESS );
00083 return thee;
00084 }
00085
00086
00087 VPRIVATE void Vclist_getMolDims(
00088 Vclist *thee,
00089 double lower_corner[VAPBS_DIM],
00090 double upper_corner[VAPBS_DIM],
00091 double *r_max
00092 ) {
00093
00094 int i, j;
00095 double pos;
00096 Valist *alist;
00097 Vatom *atom;
00098
00099 alist = thee->alist;
00100
00101
00102 for (i=0; i<VAPBS_DIM; i++) {
00103 lower_corner[i] = VLARGE;
00104 upper_corner[i] = -VLARGE;
00105 }
00106 *r_max = -1.0;
00107
00108
00109 for (i=0; i<Valist_getNumberAtoms(alist); i++) {
00110 atom = Valist_getAtom(alist, i);
00111 for (j=0; j<VAPBS_DIM; j++) {
00112 pos = (Vatom_getPosition(atom))[j];
00113 if ( pos < lower_corner[j] ) lower_corner[j] = pos;
00114 if ( pos > upper_corner[j] ) upper_corner[j] = pos;
00115 }
00116 if (Vatom_getRadius(atom) > *r_max) *r_max = Vatom_getRadius(atom);
00117 }
00118
00119 }
00120
00121
00122 VPRIVATE Vrc_Codes Vclist_setupGrid(Vclist *thee) {
00123
00124
00125 #define VCLIST_INFLATE 1.42
00126
00127 int i;
00128 double length[VAPBS_DIM], r_max;
00129
00130
00131 switch (thee->mode) {
00132 case CLIST_AUTO_DOMAIN:
00133
00134 Vclist_getMolDims(thee, thee->lower_corner, thee->upper_corner,
00135 &r_max);
00136
00137 for (i=0; i<VAPBS_DIM; i++) {
00138 thee->upper_corner[i] = thee->upper_corner[i]
00139 + VCLIST_INFLATE*(r_max+thee->max_radius);
00140 thee->lower_corner[i] = thee->lower_corner[i]
00141 - VCLIST_INFLATE*(r_max+thee->max_radius);
00142 }
00143 break;
00144 case CLIST_MANUAL_DOMAIN:
00145
00146 break;
00147 default:
00148 Vnm_print(2, "Vclist_setupGrid: invalid setup mode (%d)!\n",
00149 thee->mode);
00150 return VRC_FAILURE;
00151 }
00152
00153
00154 for (i=0; i<VAPBS_DIM; i++) {
00155 length[i] = thee->upper_corner[i] - thee->lower_corner[i];
00156 thee->spacs[i] = length[i]/((double)(thee->npts[i] - 1));
00157 }
00158 Vnm_print(0, "Vclist_setupGrid: Grid lengths = (%g, %g, %g)\n",
00159 length[0], length[1], length[2]);
00160
00161 Vnm_print(0, "Vclist_setupGrid: Grid lower corner = (%g, %g, %g)\n",
00162 (thee->lower_corner)[0], (thee->lower_corner)[1],
00163 (thee->lower_corner)[2]);
00164
00165 return VRC_SUCCESS;
00166
00167 #undef VCLIST_INFLATE
00168 }
00169
00170
00171 VPRIVATE Vrc_Codes Vclist_storeParms(Vclist *thee, Valist *alist,
00172 double max_radius, int npts[VAPBS_DIM], Vclist_DomainMode mode,
00173 double lower_corner[VAPBS_DIM], double upper_corner[VAPBS_DIM] ) {
00174
00175 int i = 0;
00176
00177 if (alist == VNULL) {
00178 Vnm_print(2, "Vclist_ctor2: Got NULL Valist!\n");
00179 return VRC_FAILURE;
00180 } else thee->alist = alist;
00181
00182 thee->n = 1;
00183 for (i=0; i<VAPBS_DIM; i++) {
00184 if (npts[i] < 3) {
00185 Vnm_print(2,
00186 "Vclist_ctor2: n[%d] (%d) must be greater than 2!\n",
00187 i, npts[i]);
00188 return VRC_FAILURE;
00189 }
00190 thee->npts[i] = npts[i];
00191 thee->n *= npts[i];
00192 }
00193 Vnm_print(0, "Vclist_ctor2: Using %d x %d x %d hash table\n",
00194 npts[0], npts[1], npts[2]);
00195
00196 thee->mode = mode;
00197 switch (thee->mode) {
00198 case CLIST_AUTO_DOMAIN:
00199 Vnm_print(0, "Vclist_ctor2: automatic domain setup.\n");
00200 break;
00201 case CLIST_MANUAL_DOMAIN:
00202 Vnm_print(0, "Vclist_ctor2: manual domain setup.\n");
00203 Vnm_print(0, "Vclist_ctor2: lower corner = [ \n");
00204 for (i=0; i<VAPBS_DIM; i++) {
00205 thee->lower_corner[i] = lower_corner[i];
00206 Vnm_print(0, "%g ", lower_corner[i]);
00207 }
00208 Vnm_print(0, "]\n");
00209 Vnm_print(0, "Vclist_ctor2: upper corner = [ \n");
00210 for (i=0; i<VAPBS_DIM; i++) {
00211 thee->upper_corner[i] = upper_corner[i];
00212 Vnm_print(0, "%g ", upper_corner[i]);
00213 }
00214 Vnm_print(0, "]\n");
00215 break;
00216 default:
00217 Vnm_print(2, "Vclist_ctor2: invalid setup mode (%d)!\n", mode);
00218 return VRC_FAILURE;
00219 }
00220
00221 thee->max_radius = max_radius;
00222 Vnm_print(0, "Vclist_ctor2: Using %g max radius\n", max_radius);
00223
00224 return VRC_SUCCESS;
00225 }
00226
00227
00228 VPRIVATE void Vclist_gridSpan(Vclist *thee,
00229 Vatom *atom,
00230 int imin[VAPBS_DIM],
00231 int imax[VAPBS_DIM]
00232 ) {
00233
00234 int i;
00235 double *coord, dc, idc, rtot;
00236
00237
00238 coord = Vatom_getPosition(atom);
00239
00240
00241 rtot = Vatom_getRadius(atom) + thee->max_radius;
00242
00243
00244
00245 for (i=0; i<VAPBS_DIM; i++) {
00246 dc = coord[i] - (thee->lower_corner)[i];
00247 idc = (dc + rtot)/(thee->spacs[i]);
00248 imax[i] = (int)(ceil(idc));
00249 imax[i] = VMIN2(imax[i], thee->npts[i]-1);
00250 idc = (dc - rtot)/(thee->spacs[i]);
00251 imin[i] = (int)(floor(idc));
00252 imin[i] = VMAX2(imin[i], 0);
00253 }
00254
00255 }
00256
00257
00258
00259 VPRIVATE int Vclist_arrayIndex(Vclist *thee, int i, int j, int k) {
00260
00261 return (thee->npts[2])*(thee->npts[1])*i + (thee->npts[2])*j + k;
00262
00263 }
00264
00265
00266
00267 VPRIVATE Vrc_Codes Vclist_assignAtoms(Vclist *thee) {
00268
00269 int iatom, i, j, k, ui, inext;
00270 int imax[VAPBS_DIM], imin[VAPBS_DIM];
00271 int totatoms;
00272 Vatom *atom;
00273 VclistCell *cell;
00274
00275
00276
00277 totatoms = 0;
00278 for (iatom=0; iatom<Valist_getNumberAtoms(thee->alist); iatom++) {
00279
00280
00281 atom = Valist_getAtom(thee->alist, iatom);
00282 Vclist_gridSpan(thee, atom, imin, imax);
00283
00284
00285 VASSERT(VAPBS_DIM == 3);
00286 for ( i = imin[0]; i <= imax[0]; i++) {
00287 for ( j = imin[1]; j <= imax[1]; j++) {
00288 for ( k = imin[2]; k <= imax[2]; k++) {
00289
00290 ui = Vclist_arrayIndex(thee, i, j, k);
00291
00292 cell = &(thee->cells[ui]);
00293 (cell->natoms)++;
00294 totatoms++;
00295 }
00296 }
00297 }
00298 }
00299 Vnm_print(0, "Vclist_assignAtoms: Have %d atom entries\n", totatoms);
00300
00301
00302 for (ui=0; ui<thee->n; ui++) {
00303 cell = &(thee->cells[ui]);
00304 if ( VclistCell_ctor2(cell, cell->natoms) == VRC_FAILURE ) {
00305 Vnm_print(2, "Vclist_assignAtoms: cell error!\n");
00306 return VRC_FAILURE;
00307 }
00308
00309 cell->natoms = 0;
00310 }
00311
00312
00313 for (iatom=0; iatom<Valist_getNumberAtoms(thee->alist); iatom++) {
00314
00315
00316 atom = Valist_getAtom(thee->alist, iatom);
00317 Vclist_gridSpan(thee, atom, imin, imax);
00318
00319
00320 for (i = imin[0]; i <= imax[0]; i++) {
00321 for (j = imin[1]; j <= imax[1]; j++) {
00322 for (k = imin[2]; k <= imax[2]; k++) {
00323
00324 ui = Vclist_arrayIndex(thee, i, j, k);
00325 cell = &(thee->cells[ui]);
00326
00327 inext = cell->natoms;
00328 cell->atoms[inext] = atom;
00329
00330 (cell->natoms)++;
00331 }
00332 }
00333 }
00334 }
00335
00336 return VRC_SUCCESS;
00337 }
00338
00339
00340 VPUBLIC Vrc_Codes Vclist_ctor2(Vclist *thee, Valist *alist, double max_radius,
00341 int npts[VAPBS_DIM], Vclist_DomainMode mode,
00342 double lower_corner[VAPBS_DIM], double upper_corner[VAPBS_DIM]) {
00343
00344 int i;
00345 VclistCell *cell;
00346
00347
00348 if ( Vclist_storeParms(thee, alist, max_radius, npts, mode, lower_corner,
00349 upper_corner) == VRC_FAILURE ) {
00350 Vnm_print(2, "Vclist_ctor2: parameter check failed!\n");
00351 return VRC_FAILURE;
00352 }
00353
00354
00355 thee->vmem = Vmem_ctor("APBS::VCLIST");
00356 if (thee->vmem == VNULL) {
00357 Vnm_print(2, "Vclist_ctor2: memory object setup failed!\n");
00358 return VRC_FAILURE;
00359 }
00360
00361
00362 thee->cells = Vmem_malloc( thee->vmem, thee->n, sizeof(VclistCell) );
00363 if (thee->cells == VNULL) {
00364 Vnm_print(2,
00365 "Vclist_ctor2: Failed allocating %d VclistCell objects!\n",
00366 thee->n);
00367 return VRC_FAILURE;
00368 }
00369 for (i=0; i<thee->n; i++) {
00370 cell = &(thee->cells[i]);
00371 cell->natoms = 0;
00372 }
00373
00374
00375 if ( Vclist_setupGrid(thee) == VRC_FAILURE ) {
00376 Vnm_print(2, "Vclist_ctor2: grid setup failed!\n");
00377 return VRC_FAILURE;
00378 }
00379
00380
00381 if (Vclist_assignAtoms(thee) == VRC_FAILURE) {
00382 Vnm_print(2, "Vclist_ctor2: atom assignment failed!\n");
00383 return VRC_FAILURE;
00384 }
00385
00386
00387
00388
00389
00390 return VRC_SUCCESS;
00391 }
00392
00393
00394 VPUBLIC void Vclist_dtor(Vclist **thee) {
00395
00396 if ((*thee) != VNULL) {
00397 Vclist_dtor2(*thee);
00398 Vmem_free(VNULL, 1, sizeof(Vclist), (void **)thee);
00399 (*thee) = VNULL;
00400 }
00401
00402 }
00403
00404
00405 VPUBLIC void Vclist_dtor2(Vclist *thee) {
00406
00407 VclistCell *cell;
00408 int i;
00409
00410 for (i=0; i<thee->n; i++) {
00411 cell = &(thee->cells[i]);
00412 VclistCell_dtor2(cell);
00413 }
00414 Vmem_free(thee->vmem, thee->n, sizeof(VclistCell),
00415 (void **)&(thee->cells));
00416 Vmem_dtor(&(thee->vmem));
00417
00418 }
00419
00420 VPUBLIC VclistCell* Vclist_getCell(Vclist *thee, double pos[VAPBS_DIM]) {
00421
00422 int i, ic[VAPBS_DIM], ui;
00423 double c[VAPBS_DIM];
00424
00425
00426 for (i=0; i<VAPBS_DIM; i++) {
00427 c[i] = pos[i] - (thee->lower_corner)[i];
00428 ic[i] = (int)(c[i]/thee->spacs[i]);
00429 if (ic[i] < 0) {
00430
00431 return VNULL;
00432 } else if (ic[i] >= thee->npts[i]) {
00433
00434 return VNULL;
00435 }
00436 }
00437
00438
00439 VASSERT(VAPBS_DIM == 3);
00440 ui = Vclist_arrayIndex(thee, ic[0], ic[1], ic[2]);
00441
00442 return &(thee->cells[ui]);
00443
00444 }
00445
00446 VPUBLIC VclistCell* VclistCell_ctor(int natoms) {
00447
00448 VclistCell *thee = VNULL;
00449
00450
00451 thee = Vmem_malloc(VNULL, 1, sizeof(VclistCell));
00452 VASSERT( thee != VNULL);
00453 VASSERT( VclistCell_ctor2(thee, natoms) == VRC_SUCCESS );
00454
00455 return thee;
00456 }
00457
00458 VPUBLIC Vrc_Codes VclistCell_ctor2(VclistCell *thee, int natoms) {
00459
00460 if (thee == VNULL) {
00461 Vnm_print(2, "VclistCell_ctor2: NULL thee!\n");
00462 return VRC_FAILURE;
00463 }
00464
00465 thee->natoms = natoms;
00466 if (thee->natoms > 0) {
00467 thee->atoms = Vmem_malloc(VNULL, natoms, sizeof(Vatom *));
00468 if (thee->atoms == VNULL) {
00469 Vnm_print(2,
00470 "VclistCell_ctor2: unable to allocate space for %d atom pointers!\n",
00471 natoms);
00472 return VRC_FAILURE;
00473 }
00474 }
00475
00476 return VRC_SUCCESS;
00477
00478 }
00479
00480 VPUBLIC void VclistCell_dtor(VclistCell **thee) {
00481
00482 if ((*thee) != VNULL) {
00483 VclistCell_dtor2(*thee);
00484 Vmem_free(VNULL, 1, sizeof(VclistCell), (void **)thee);
00485 (*thee) = VNULL;
00486 }
00487
00488 }
00489
00490
00491 VPUBLIC void VclistCell_dtor2(VclistCell *thee) {
00492
00493 if (thee->natoms > 0) {
00494 Vmem_free(VNULL, thee->natoms, sizeof(Vatom *),
00495 (void **)&(thee->atoms));
00496 }
00497
00498 }
00499