• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

src/generic/vclist.c

Go to the documentation of this file.
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 /* if !defined(VINLINE_VCLIST) */
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     /* Set up the structure */
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 /* Get the dimensions of the molecule stored in thee->alist */
00087 VPRIVATE void Vclist_getMolDims(
00088         Vclist *thee, 
00089         double lower_corner[VAPBS_DIM], /* Set to lower corner of molecule */
00090         double upper_corner[VAPBS_DIM], /* Set to lower corner of molecule */
00091         double *r_max /* Set to max atom radius */
00092         ) {
00093 
00094     int i, j;
00095     double pos;
00096     Valist *alist;
00097     Vatom *atom;
00098 
00099     alist = thee->alist;
00100 
00101     /* Initialize */
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     /* Check each atom */
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 /* Setup lookup grid */
00122 VPRIVATE Vrc_Codes Vclist_setupGrid(Vclist *thee) {
00123 
00124     /* Inflation factor ~ sqrt(2)*/
00125     #define VCLIST_INFLATE 1.42
00126 
00127     int i;
00128     double length[VAPBS_DIM], r_max;
00129 
00130     /* Set up the grid corners */
00131     switch (thee->mode) {
00132         case CLIST_AUTO_DOMAIN:
00133             /* Get molecule dimensions */
00134             Vclist_getMolDims(thee, thee->lower_corner, thee->upper_corner, 
00135                     &r_max);
00136             /* Set up grid spacings */
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             /* Grid corners established in constructor */
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     /* Set up the grid lengths and spacings */
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 /* Check and store parameters passed to constructor */
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 /* Calculate the gridpoints an atom spans */
00228 VPRIVATE void Vclist_gridSpan(Vclist *thee, 
00229         Vatom *atom, /* Atom */
00230         int imin[VAPBS_DIM], /* Set to min grid indices */
00231         int imax[VAPBS_DIM]  /* Set to max grid indices */
00232         ) {
00233 
00234     int i;
00235     double *coord, dc, idc, rtot;
00236 
00237     /* Get the position in the grid's frame of reference */
00238     coord = Vatom_getPosition(atom);
00239 
00240     /* Get the range the atom radius + probe radius spans */
00241     rtot = Vatom_getRadius(atom) + thee->max_radius;
00242     
00243     /* Calculate the range of grid points the inflated atom spans in the x 
00244      * direction. */
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 /* Get the array index for a particular cell based on its i,j,k 
00258  * coordinates */
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 /* Assign atoms to cells */
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     /* Find out how many atoms are associated with each grid point */
00277     totatoms = 0;
00278     for (iatom=0; iatom<Valist_getNumberAtoms(thee->alist); iatom++) { 
00279 
00280         /* Get grid span for atom */
00281         atom = Valist_getAtom(thee->alist, iatom);
00282         Vclist_gridSpan(thee, atom, imin, imax);
00283 
00284         /* Now find and assign the grid points */
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                     /* Get index to array */
00290                     ui = Vclist_arrayIndex(thee, i, j, k);
00291                     /* Increment number of atoms for this grid point */
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     /* Allocate the space to store the pointers to the atoms */
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         /* Clear the counter for later use */
00309         cell->natoms = 0;
00310     }
00311  
00312     /* Assign the atoms to grid points */
00313     for (iatom=0; iatom<Valist_getNumberAtoms(thee->alist); iatom++) {
00314 
00315         /* Get grid span for atom */
00316         atom = Valist_getAtom(thee->alist, iatom);
00317         Vclist_gridSpan(thee, atom, imin, imax);
00318 
00319         /* Now find and assign the grid points */
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                     /* Get index to array */
00324                     ui = Vclist_arrayIndex(thee, i, j, k);
00325                     cell = &(thee->cells[ui]);
00326                     /* Index of next available array location */
00327                     inext = cell->natoms;
00328                     cell->atoms[inext] = atom;
00329                     /* Increment number of atoms */
00330                     (cell->natoms)++;
00331                 }
00332             }
00333         }
00334     } 
00335 
00336     return VRC_SUCCESS;
00337 }
00338 
00339 /* Main (FORTRAN stub) constructor */
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     /* Check and store parameters */
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     /* Set up memory */
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     /* Set up cells */
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     /* Set up the grid */
00375     if ( Vclist_setupGrid(thee) == VRC_FAILURE ) {
00376         Vnm_print(2, "Vclist_ctor2:  grid setup failed!\n");
00377         return VRC_FAILURE;
00378     }
00379 
00380     /* Assign atoms to grid cells */
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 /* Destructor */
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 /* Main (stub) destructor */
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     /* Convert to grid based coordinates */
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             /* printf("OFF LOWER CORNER!\n"); */
00431             return VNULL;
00432         } else if (ic[i] >= thee->npts[i]) {
00433             /* printf("OFF UPPER CORNER!\n"); */
00434             return VNULL;
00435         }
00436     }
00437 
00438     /* Get the array index */
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     /* Set up the structure */
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 /* Main (stub) destructor */
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 

Generated on Wed Oct 20 2010 12:01:33 for APBS by  doxygen 1.7.2