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

src/fem/vcsm.c

Go to the documentation of this file.
00001 
00050 #include "apbscfg.h"
00051 
00052 #if defined(HAVE_MC_H)
00053 #include "apbs/vcsm.h"
00054 
00055 /* Inlineable methods */
00056 #if !defined(VINLINE_VCSM)
00057 
00058 VPUBLIC Valist* Vcsm_getValist(Vcsm *thee) { 
00059 
00060    VASSERT(thee != VNULL);
00061    return thee->alist;
00062 
00063 }
00064 
00065 VPUBLIC int Vcsm_getNumberAtoms(Vcsm *thee, int isimp) {
00066 
00067    VASSERT(thee != VNULL);
00068    VASSERT(thee->initFlag);
00069    return thee->nsqm[isimp];
00070 
00071 }
00072 
00073 VPUBLIC Vatom* Vcsm_getAtom(Vcsm *thee, int iatom, int isimp) {
00074 
00075 
00076    VASSERT(thee != VNULL);
00077    VASSERT(thee->initFlag);
00078 
00079    VASSERT(iatom < (thee->nsqm)[isimp]);
00080    return Valist_getAtom(thee->alist, (thee->sqm)[isimp][iatom]);
00081 
00082 }
00083 
00084 VPUBLIC int Vcsm_getAtomIndex(Vcsm *thee, int iatom, int isimp) {
00085 
00086 
00087    VASSERT(thee != VNULL);
00088    VASSERT(thee->initFlag);
00089 
00090    VASSERT(iatom < (thee->nsqm)[isimp]);
00091    return (thee->sqm)[isimp][iatom];
00092 
00093 }
00094 
00095 VPUBLIC int Vcsm_getNumberSimplices(Vcsm *thee, int iatom) {
00096 
00097 
00098    VASSERT(thee != VNULL);
00099    VASSERT(thee->initFlag);
00100 
00101    return (thee->nqsm)[iatom];
00102 
00103 }
00104 
00105 VPUBLIC SS* Vcsm_getSimplex(Vcsm *thee, int isimp, int iatom) {
00106 
00107 
00108    VASSERT(thee != VNULL);
00109    VASSERT(thee->initFlag);
00110 
00111    return Gem_SS(thee->gm, (thee->qsm)[iatom][isimp]);
00112 
00113 }
00114 
00115 VPUBLIC int Vcsm_getSimplexIndex(Vcsm *thee, int isimp, int iatom) {
00116 
00117 
00118    VASSERT(thee != VNULL);
00119    VASSERT(thee->initFlag);
00120 
00121    return (thee->qsm)[iatom][isimp];
00122 
00123 }
00124 
00125 VPUBLIC unsigned long int Vcsm_memChk(Vcsm *thee) {
00126     if (thee == VNULL) return 0;
00127     return Vmem_bytes(thee->vmem);
00128 }
00129 
00130 #endif /* if !defined(VINLINE_VCSM) */
00131 
00132 VPUBLIC Vcsm* Vcsm_ctor(Valist *alist, Gem *gm) {
00133 
00134     /* Set up the structure */
00135     Vcsm *thee = VNULL;
00136     thee = Vmem_malloc(VNULL, 1, sizeof(Vcsm) );
00137     VASSERT( thee != VNULL);
00138     VASSERT( Vcsm_ctor2(thee, alist, gm));
00139 
00140     return thee;
00141 }
00142 
00143 VPUBLIC int Vcsm_ctor2(Vcsm *thee, Valist *alist, Gem *gm) { 
00144  
00145     VASSERT( thee != VNULL );
00146 
00147     /* Memory management object */
00148     thee->vmem = Vmem_ctor("APBS:VCSM");
00149 
00150     /* Set up the atom list and grid manager */
00151     if( alist == VNULL) {
00152         Vnm_print(2,"Vcsm_ctor2: got null pointer to Valist object!\n");
00153         return 0;
00154     }
00155     thee->alist = alist;
00156     if( gm == VNULL) {
00157         Vnm_print(2,"Vcsm_ctor2: got a null pointer to the Gem object!\n");
00158         return 0;
00159     }
00160     thee->gm = gm;
00161    
00162     thee->initFlag = 0;
00163     return 1;
00164 }
00165 
00166 VPUBLIC void Vcsm_init(Vcsm *thee) {
00167  
00168     /* Counters */
00169     int iatom, jatom, isimp, jsimp, gotSimp;
00170     /* Atomic information */
00171     Vatom *atom;
00172     double *position;
00173     /* Simplex/Vertex information */
00174     SS *simplex;
00175     /* Basis function values */
00176 
00177     if (thee == VNULL) {
00178         Vnm_print(2, "Vcsm_init:  Error!  Got NULL thee!\n");
00179         VASSERT(0);
00180     }
00181     if (thee->gm == VNULL) {
00182     VASSERT(thee->gm != VNULL);
00183         Vnm_print(2, "Vcsm_init:  Error!  Got NULL thee->gm!\n");
00184         VASSERT(0);
00185     }
00186     thee->nsimp = Gem_numSS(thee->gm);
00187     if (thee->nsimp <= 0) {
00188         Vnm_print(2, "Vcsm_init:  Error!  Got %d simplices!\n", thee->nsimp);
00189         VASSERT(0);
00190     }
00191     thee->natom = Valist_getNumberAtoms(thee->alist);
00192 
00193     /* Allocate and initialize space for the first dimensions of the 
00194      * simplex-charge map, the simplex array, and the counters */
00195     thee->sqm = Vmem_malloc(thee->vmem, thee->nsimp, sizeof(int *));
00196     VASSERT(thee->sqm != VNULL);
00197     thee->nsqm = Vmem_malloc(thee->vmem, thee->nsimp, sizeof(int));
00198     VASSERT(thee->nsqm != VNULL);
00199     for (isimp=0; isimp<thee->nsimp; isimp++) (thee->nsqm)[isimp] = 0;
00200 
00201     /* Count the number of charges per simplex. */
00202     for (iatom=0; iatom<thee->natom; iatom++) {
00203         atom = Valist_getAtom(thee->alist, iatom);
00204         position = Vatom_getPosition(atom);
00205         gotSimp = 0;
00206         for (isimp=0; isimp<thee->nsimp; isimp++) {
00207             simplex = Gem_SS(thee->gm, isimp);
00208             if (Gem_pointInSimplex(thee->gm, simplex, position)) {
00209                 (thee->nsqm)[isimp]++;
00210                 gotSimp = 1;
00211              }
00212         }
00213     }
00214 
00215     /* Allocate the space for the simplex-charge map */
00216     for (isimp=0; isimp<thee->nsimp; isimp++) {
00217         if ((thee->nsqm)[isimp] > 0) {
00218             thee->sqm[isimp] = Vmem_malloc(thee->vmem, (thee->nsqm)[isimp], 
00219               sizeof(int));
00220             VASSERT(thee->sqm[isimp] != VNULL);
00221         }
00222     }
00223 
00224     /* Finally, set up the map */
00225     for (isimp=0; isimp<thee->nsimp; isimp++) {
00226         jsimp = 0;
00227         simplex = Gem_SS(thee->gm, isimp);
00228         for (iatom=0; iatom<thee->natom; iatom++) {
00229             atom = Valist_getAtom(thee->alist, iatom);
00230             position = Vatom_getPosition(atom);
00231             /* Check to see if the atom's in this simplex */
00232             if (Gem_pointInSimplex(thee->gm, simplex, position)) {
00233                 /* Assign the entries in the next vacant spot */
00234                 (thee->sqm)[isimp][jsimp] = iatom;
00235                 jsimp++;
00236             }
00237         }
00238     }
00239 
00240     thee->msimp = thee->nsimp;
00241 
00242     /* Allocate space for the charge-simplex map */
00243     thee->qsm = Vmem_malloc(thee->vmem, thee->natom, sizeof(int *));
00244     VASSERT(thee->qsm != VNULL);
00245     thee->nqsm = Vmem_malloc(thee->vmem, thee->natom, sizeof(int));
00246     VASSERT(thee->nqsm != VNULL);
00247     for (iatom=0; iatom<thee->natom; iatom++) (thee->nqsm)[iatom] = 0;
00248     /* Loop through the list of simplices and count the number of times
00249      * each atom appears */
00250     for (isimp=0; isimp<thee->nsimp; isimp++) {
00251         for (iatom=0; iatom<thee->nsqm[isimp]; iatom++) {
00252             jatom = thee->sqm[isimp][iatom];
00253             thee->nqsm[jatom]++;
00254         }
00255     }
00256     /* Do a TIME-CONSUMING SANITY CHECK to make sure that each atom was
00257      * placed in at simplex */
00258     for (iatom=0; iatom<thee->natom; iatom++) {
00259         if (thee->nqsm[iatom] == 0) {
00260             Vnm_print(2, "Vcsm_init: Atom %d not placed in simplex!\n", iatom);
00261             VASSERT(0);
00262         }
00263     }
00264     /* Allocate the appropriate amount of space for each entry in the
00265      * charge-simplex map and clear the counter for re-use in assignment */
00266     for (iatom=0; iatom<thee->natom; iatom++) {
00267         thee->qsm[iatom] = Vmem_malloc(thee->vmem, (thee->nqsm)[iatom],
00268           sizeof(int));
00269         VASSERT(thee->qsm[iatom] != VNULL);
00270         thee->nqsm[iatom] = 0;
00271     }
00272     /* Assign the simplices to atoms */
00273     for (isimp=0; isimp<thee->nsimp; isimp++) {
00274         for (iatom=0; iatom<thee->nsqm[isimp]; iatom++) {
00275             jatom = thee->sqm[isimp][iatom];
00276             thee->qsm[jatom][thee->nqsm[jatom]] = isimp;
00277             thee->nqsm[jatom]++;
00278         }
00279     }
00280 
00281     thee->initFlag = 1;
00282 }
00283 
00284 VPUBLIC void Vcsm_dtor(Vcsm **thee) {
00285     if ((*thee) != VNULL) {
00286         Vcsm_dtor2(*thee);
00287         Vmem_free(VNULL, 1, sizeof(Vcsm), (void **)thee);
00288         (*thee) = VNULL;
00289     }
00290 }
00291 
00292 VPUBLIC void Vcsm_dtor2(Vcsm *thee) { 
00293     int i;
00294 
00295     if ((thee != VNULL) && thee->initFlag) {
00296 
00297         for (i=0; i<thee->msimp; i++) {
00298             if (thee->nsqm[i] > 0) Vmem_free(thee->vmem, thee->nsqm[i], 
00299               sizeof(int), (void **)&(thee->sqm[i]));
00300         }
00301         for (i=0; i<thee->natom; i++) {
00302             if (thee->nqsm[i] > 0) Vmem_free(thee->vmem, thee->nqsm[i], 
00303               sizeof(int), (void **)&(thee->qsm[i]));
00304         }
00305         Vmem_free(thee->vmem, thee->msimp, sizeof(int *), 
00306           (void **)&(thee->sqm));
00307         Vmem_free(thee->vmem, thee->msimp, sizeof(int),
00308           (void **)&(thee->nsqm));
00309         Vmem_free(thee->vmem, thee->natom, sizeof(int *), 
00310           (void **)&(thee->qsm));
00311         Vmem_free(thee->vmem, thee->natom, sizeof(int),
00312           (void **)&(thee->nqsm));
00313 
00314     }
00315     Vmem_dtor(&(thee->vmem));
00316 }
00317 
00318 VPUBLIC int Vcsm_update(Vcsm *thee, SS **simps, int num) {
00319 
00320     /* Counters */
00321     int isimp, jsimp, iatom, jatom, atomID, simpID;
00322     int nsimps, gotMem;
00323     /* Object info */
00324     Vatom *atom;
00325     SS *simplex;
00326     double *position;
00327     /* Lists */
00328     int *qParent, nqParent;
00329     int **sqmNew, *nsqmNew;
00330     int *affAtoms, nAffAtoms;
00331     int *dnqsm, *nqsmNew, **qsmNew;
00332 
00333     VASSERT(thee != VNULL);
00334     VASSERT(thee->initFlag);
00335 
00336     /* If we don't have enough memory to accommodate the new entries, 
00337      * add more by doubling the existing amount */
00338     isimp = thee->nsimp + num - 1;
00339     gotMem = 0;
00340     while (!gotMem) {
00341         if (isimp > thee->msimp) {
00342             isimp = 2 * isimp;
00343             thee->nsqm = Vmem_realloc(thee->vmem, thee->msimp, sizeof(int), 
00344               (void **)&(thee->nsqm), isimp);
00345             VASSERT(thee->nsqm != VNULL);
00346             thee->sqm = Vmem_realloc(thee->vmem, thee->msimp, sizeof(int *), 
00347               (void **)&(thee->sqm), isimp);
00348             VASSERT(thee->sqm != VNULL);
00349             thee->msimp = isimp;
00350         } else gotMem = 1;
00351     }
00352     /* Initialize the nsqm entires we just allocated */
00353     for (isimp = thee->nsimp; isimp<thee->nsimp+num-1 ; isimp++) {
00354        thee->nsqm[isimp] = 0;
00355     }
00356     
00357     thee->nsimp = thee->nsimp + num - 1;
00358 
00359     /* There's a simple case to deal with:  if simps[0] didn't have a
00360      * charge in the first place */
00361     isimp = SS_id(simps[0]);
00362     if (thee->nsqm[isimp] == 0) {
00363         for (isimp=1; isimp<num; isimp++) {
00364             thee->nsqm[SS_id(simps[isimp])] = 0;
00365         }
00366         return 1;
00367     }
00368 
00369     /* The more complicated case has occured; the parent simplex had one or
00370      * more charges.  First, generate the list of affected charges. */
00371     isimp = SS_id(simps[0]);
00372     nqParent = thee->nsqm[isimp];
00373     qParent = thee->sqm[isimp];
00374 
00375     sqmNew = Vmem_malloc(thee->vmem, num, sizeof(int *));
00376     VASSERT(sqmNew != VNULL);
00377     nsqmNew = Vmem_malloc(thee->vmem, num, sizeof(int));
00378     VASSERT(nsqmNew != VNULL);
00379     for (isimp=0; isimp<num; isimp++) nsqmNew[isimp] = 0;
00380 
00381     /* Loop throught the affected atoms to determine how many atoms each
00382      * simplex will get. */
00383     for (iatom=0; iatom<nqParent; iatom++) {
00384 
00385         atomID = qParent[iatom];
00386         atom = Valist_getAtom(thee->alist, atomID);
00387         position = Vatom_getPosition(atom);
00388         nsimps = 0;
00389 
00390         jsimp = 0;
00391 
00392         for (isimp=0; isimp<num; isimp++) {
00393             simplex = simps[isimp];
00394             if (Gem_pointInSimplex(thee->gm, simplex, position)) {
00395                 nsqmNew[isimp]++;
00396                 jsimp = 1;
00397             }
00398         }
00399  
00400         VASSERT(jsimp != 0);
00401     }
00402 
00403     /* Sanity check that we didn't lose any atoms... */
00404     iatom = 0;
00405     for (isimp=0; isimp<num; isimp++) iatom += nsqmNew[isimp];
00406     if (iatom < nqParent) {
00407         Vnm_print(2,"Vcsm_update: Lost %d (of %d) atoms!\n", 
00408             nqParent - iatom, nqParent);
00409         VASSERT(0);
00410     }
00411 
00412     /* Allocate the storage */
00413     for (isimp=0; isimp<num; isimp++) {
00414         if (nsqmNew[isimp] > 0) {
00415             sqmNew[isimp] = Vmem_malloc(thee->vmem, nsqmNew[isimp], 
00416               sizeof(int));
00417             VASSERT(sqmNew[isimp] != VNULL);
00418         }
00419     }
00420 
00421     /* Assign charges to simplices */
00422     for (isimp=0; isimp<num; isimp++) {
00423 
00424         jsimp = 0;
00425         simplex = simps[isimp];
00426 
00427         /* Loop over the atoms associated with the parent simplex */
00428         for (iatom=0; iatom<nqParent; iatom++) {
00429 
00430             atomID = qParent[iatom];
00431             atom = Valist_getAtom(thee->alist, atomID);
00432             position = Vatom_getPosition(atom);
00433             if (Gem_pointInSimplex(thee->gm, simplex, position)) {
00434                 sqmNew[isimp][jsimp] = atomID;
00435                 jsimp++;
00436             }
00437         }
00438     }
00439 
00440     /* Update the QSM map using the old and new SQM lists */
00441     /* The affected atoms are those contained in the parent simplex; i.e.
00442      * thee->sqm[SS_id(simps[0])] */
00443     affAtoms = thee->sqm[SS_id(simps[0])];
00444     nAffAtoms = thee->nsqm[SS_id(simps[0])];
00445     /* Each of these atoms will go somewhere else; i.e., the entries in
00446      * thee->qsm are never destroyed and thee->nqsm never decreases.
00447      * However, it is possible that a subdivision could cause an atom to be
00448      * shared by two child simplices.  Here we record the change, if any,
00449      * in the number of simplices associated with each atom. */
00450     dnqsm = Vmem_malloc(thee->vmem, nAffAtoms, sizeof(int));
00451     VASSERT(dnqsm != VNULL);
00452     nqsmNew = Vmem_malloc(thee->vmem, nAffAtoms, sizeof(int));
00453     VASSERT(nqsmNew != VNULL);
00454     qsmNew = Vmem_malloc(thee->vmem, nAffAtoms, sizeof(int*));
00455     VASSERT(qsmNew != VNULL);
00456     for (iatom=0; iatom<nAffAtoms; iatom++) {
00457         dnqsm[iatom] = -1;
00458         atomID = affAtoms[iatom];
00459         for (isimp=0; isimp<num; isimp++) {
00460             for (jatom=0; jatom<nsqmNew[isimp]; jatom++) {
00461                 if (sqmNew[isimp][jatom] == atomID) dnqsm[iatom]++;
00462             }
00463         }
00464         VASSERT(dnqsm[iatom] > -1);
00465     }
00466     /* Setup the new entries in the array */
00467     for (iatom=0;iatom<nAffAtoms; iatom++) {
00468         atomID = affAtoms[iatom];
00469         qsmNew[iatom] = Vmem_malloc(thee->vmem, 
00470                 (dnqsm[iatom] + thee->nqsm[atomID]), 
00471                 sizeof(int));
00472         nqsmNew[iatom] = 0;
00473         VASSERT(qsmNew[iatom] != VNULL);
00474     }
00475     /* Fill the new entries in the array */
00476     /* First, do the modified entries */
00477     for (isimp=0; isimp<num; isimp++) {
00478         simpID = SS_id(simps[isimp]);
00479         for (iatom=0; iatom<nsqmNew[isimp]; iatom++) {
00480             atomID = sqmNew[isimp][iatom];
00481             for (jatom=0; jatom<nAffAtoms; jatom++) {
00482                 if (atomID == affAtoms[jatom]) break;
00483             }
00484             if (jatom < nAffAtoms) {
00485                 qsmNew[jatom][nqsmNew[jatom]] = simpID;
00486                 nqsmNew[jatom]++;
00487             } 
00488         }
00489     }
00490     /* Now do the unmodified entries */
00491     for (iatom=0; iatom<nAffAtoms; iatom++) {
00492         atomID = affAtoms[iatom];
00493         for (isimp=0; isimp<thee->nqsm[atomID]; isimp++) {
00494             for (jsimp=0; jsimp<num; jsimp++) {
00495                 simpID = SS_id(simps[jsimp]);
00496                 if (thee->qsm[atomID][isimp] == simpID) break;
00497             }
00498             if (jsimp == num) {
00499                 qsmNew[iatom][nqsmNew[iatom]] = thee->qsm[atomID][isimp];
00500                 nqsmNew[iatom]++;
00501             }
00502         }
00503     }
00504 
00505     /* Replace the existing entries in the table.  Do the QSM entires
00506      * first, since they require affAtoms = thee->sqm[simps[0]] */
00507     for (iatom=0; iatom<nAffAtoms; iatom++) {
00508         atomID = affAtoms[iatom]; 
00509         Vmem_free(thee->vmem, thee->nqsm[atomID], sizeof(int), 
00510           (void **)&(thee->qsm[atomID]));
00511         thee->qsm[atomID] = qsmNew[iatom];
00512         thee->nqsm[atomID] = nqsmNew[iatom];
00513     }
00514     for (isimp=0; isimp<num; isimp++) {
00515         simpID = SS_id(simps[isimp]);
00516         if (thee->nsqm[simpID] > 0) Vmem_free(thee->vmem, thee->nsqm[simpID], 
00517           sizeof(int), (void **)&(thee->sqm[simpID]));
00518         thee->sqm[simpID] = sqmNew[isimp];
00519         thee->nsqm[simpID] = nsqmNew[isimp];
00520     }
00521 
00522     Vmem_free(thee->vmem, num, sizeof(int *), (void **)&sqmNew);
00523     Vmem_free(thee->vmem, num, sizeof(int), (void **)&nsqmNew);
00524     Vmem_free(thee->vmem, nAffAtoms, sizeof(int *), (void **)&qsmNew);
00525     Vmem_free(thee->vmem, nAffAtoms, sizeof(int), (void **)&nqsmNew);
00526     Vmem_free(thee->vmem, nAffAtoms, sizeof(int), (void **)&dnqsm);
00527 
00528 
00529     return 1;
00530 
00531 
00532 }
00533 
00534 #endif

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