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

src/generic/vgreen.c

Go to the documentation of this file.
00001 
00049 #include "apbscfg.h"
00050 #include "apbs/vgreen.h"
00051 
00052 /* Define wrappers for F77 treecode routines */
00053 #ifdef HAVE_TREE
00054 #  define F77TREEPEFORCE VF77_MANGLE(treepeforce, TREEPEFORCE)
00055 #  define F77DIRECT_ENG_FORCE VF77_MANGLE(direct_eng_force, DIRECT_ENG_FORCE)
00056 #  define F77CLEANUP VF77_MANGLE(mycleanup, MYCLEANUP)
00057 #  define F77TREE_COMPP VF77_MANGLE(mytree_compp, MYTREE_COMP)
00058 #  define F77TREE_COMPFP VF77_MANGLE(mytree_compfp, MYTREE_COMPFP)
00059 #  define F77CREATE_TREE VF77_MANGLE(mycreate_tree, MYCREATE_TREE)
00060 #  define F77INITLEVELS VF77_MANGLE(myinitlevels, MYINITLEVELS)
00061 #  define F77SETUP VF77_MANGLE(mysetup, MYSETUP)
00062 #endif  /* ifdef HAVE_TREE */
00063 
00064 /* Some constants associated with the tree code */
00065 #ifdef HAVE_TREE
00066 
00069 #   define FMM_DIST_TOL VSMALL
00070 
00075 #   define FMM_IFLAG 2
00076 
00079 #   define FMM_ORDER 4
00080 
00083 #   define FMM_THETA 0.5
00084 
00087 #   define FMM_MAXPARNODE 150
00088 
00091 #   define FMM_SHRINK 1
00092 
00095 #   define FMM_MINLEVEL 50000
00096 
00099 #   define FMM_MAXLEVEL 0
00100 #endif  /* ifdef HAVE_TREE */
00101 
00102 
00103 /*
00104  * @brief  Setup treecode internal structures 
00105  * @ingroup  Vgreen
00106  * @author  Nathan Baker
00107  * @param  thee  Vgreen object
00108  * @return  1 if successful, 0 otherwise
00109  */
00110 VPRIVATE int treesetup(Vgreen *thee);
00111 
00112 /*
00113  * @brief  Clean up treecode internal structures 
00114  * @ingroup  Vgreen
00115  * @author  Nathan Baker
00116  * @param  thee  Vgreen object
00117  * @return  1 if successful, 0 otherwise
00118  */
00119 VPRIVATE int treecleanup(Vgreen *thee);
00120 
00121 /*
00122  * @brief  Calculate forces or potential
00123  * @ingroup  Vgreen
00124  * @author  Nathan Baker
00125  * @param  thee  Vgreen object
00126  * @return  1 if successful, 0 otherwise
00127  */
00128 VPRIVATE int treecalc(Vgreen *thee, double *xtar, double *ytar, double *ztar,
00129         double *qtar, int numtars, double *tpengtar, double *x, double *y,
00130         double *z, double *q, int numpars, double *fx, double *fy, double *fz,
00131         int iflag, int farrdim, int arrdim);
00132 
00133 #if !defined(VINLINE_VGREEN)
00134 
00135 VPUBLIC Valist* Vgreen_getValist(Vgreen *thee) { 
00136 
00137    VASSERT(thee != VNULL);
00138    return thee->alist;
00139 
00140 }
00141 
00142 VPUBLIC unsigned long int Vgreen_memChk(Vgreen *thee) {
00143     if (thee == VNULL) return 0;
00144     return Vmem_bytes(thee->vmem);
00145 }
00146 
00147 #endif /* if !defined(VINLINE_VGREEN) */
00148 
00149 VPUBLIC Vgreen* Vgreen_ctor(Valist *alist) {
00150 
00151     /* Set up the structure */
00152     Vgreen *thee = VNULL;
00153     thee = (Vgreen *)Vmem_malloc(VNULL, 1, sizeof(Vgreen) );
00154     VASSERT( thee != VNULL);
00155     VASSERT( Vgreen_ctor2(thee, alist));
00156 
00157     return thee;
00158 }
00159 
00160 VPUBLIC int Vgreen_ctor2(Vgreen *thee, Valist *alist) { 
00161  
00162     VASSERT( thee != VNULL );
00163 
00164     /* Memory management object */
00165     thee->vmem = Vmem_ctor("APBS:VGREEN");
00166 
00167     /* Set up the atom list and grid manager */
00168     if (alist == VNULL) {
00169         Vnm_print(2,"Vgreen_ctor2: got null pointer to Valist object!\n");
00170     }
00171 
00172     thee->alist = alist;
00173 
00174     /* Setup FMM tree (if applicable) */
00175 #ifdef HAVE_TREE
00176     if (!treesetup(thee)) {
00177         Vnm_print(2, "Vgreen_ctor2:  Error setting up FMM tree!\n");
00178         return 0;
00179     }
00180 #endif /* ifdef HAVE_TREE */
00181    
00182     return 1;
00183 }
00184 
00185 VPUBLIC void Vgreen_dtor(Vgreen **thee) {
00186     if ((*thee) != VNULL) {
00187         Vgreen_dtor2(*thee);
00188         Vmem_free(VNULL, 1, sizeof(Vgreen), (void **)thee);
00189         (*thee) = VNULL;
00190     }
00191 }
00192 
00193 VPUBLIC void Vgreen_dtor2(Vgreen *thee) { 
00194 
00195 #ifdef HAVE_TREE
00196     treecleanup(thee);
00197 #endif
00198     Vmem_dtor(&(thee->vmem));
00199 
00200 }
00201 
00202 VPUBLIC int Vgreen_helmholtz(Vgreen *thee, int npos, double *x, double *y,
00203   double *z, double *val, double kappa) {
00204 
00205     Vnm_print(2, "Error -- Vgreen_helmholtz not implemented yet!\n");
00206     return 0;
00207 }
00208 
00209 VPUBLIC int Vgreen_helmholtzD(Vgreen *thee, int npos, double *x, double *y,
00210   double *z, double *gradx, double *grady, double *gradz, double kappa) {
00211 
00212     Vnm_print(2, "Error -- Vgreen_helmholtzD not implemented yet!\n");
00213     return 0;
00214 
00215 }
00216 
00217 VPUBLIC int Vgreen_coulomb_direct(Vgreen *thee, int npos, double *x, 
00218         double *y, double *z, double *val) {
00219 
00220     Vatom *atom;
00221     double *apos, charge, dist, dx, dy, dz, scale;
00222     double *q, qtemp, fx, fy, fz;
00223     int iatom, ipos;
00224 
00225     if (thee == VNULL) {
00226         Vnm_print(2, "Vgreen_coulomb:  Got NULL thee!\n");
00227         return 0;
00228     }
00229 
00230     for (ipos=0; ipos<npos; ipos++) val[ipos] = 0.0;
00231 
00232     for (iatom=0; iatom<Valist_getNumberAtoms(thee->alist); iatom++) {
00233         atom = Valist_getAtom(thee->alist, iatom);
00234         apos = Vatom_getPosition(atom);
00235         charge = Vatom_getCharge(atom);
00236         for (ipos=0; ipos<npos; ipos++) {
00237             dx = apos[0] - x[ipos];
00238             dy = apos[1] - y[ipos];
00239             dz = apos[2] - z[ipos];
00240             dist = VSQRT(VSQR(dx) + VSQR(dy) + VSQR(dz));
00241             if (dist > VSMALL) val[ipos] += (charge/dist);
00242         }
00243     }
00244 
00245     scale = Vunit_ec/(4*Vunit_pi*Vunit_eps0*1.0e-10);
00246     for (ipos=0; ipos<npos; ipos++) val[ipos] = val[ipos]*scale;
00247 
00248     return 1;
00249 }
00250 
00251 VPUBLIC int Vgreen_coulomb(Vgreen *thee, int npos, double *x, double *y,
00252   double *z, double *val) {
00253 
00254     Vatom *atom;
00255     double *apos, charge, dist, dx, dy, dz, scale;
00256     double *q, qtemp, fx, fy, fz;
00257     int iatom, ipos;
00258 
00259     if (thee == VNULL) {
00260         Vnm_print(2, "Vgreen_coulomb:  Got NULL thee!\n");
00261         return 0;
00262     }
00263 
00264     for (ipos=0; ipos<npos; ipos++) val[ipos] = 0.0;
00265 
00266 #ifdef HAVE_TREE  
00267 
00268     /* Allocate charge array (if necessary) */
00269     if (Valist_getNumberAtoms(thee->alist) > 1) {
00270         if (npos > 1) {
00271             q = VNULL;
00272             q = Vmem_malloc(thee->vmem, npos, sizeof(double));
00273             if (q == VNULL) {
00274                 Vnm_print(2, "Vgreen_coulomb:  Error allocating charge array!\n");
00275                 return 0;
00276             }
00277         } else {
00278             q = &(qtemp);
00279         }
00280         for (ipos=0; ipos<npos; ipos++) q[ipos] = 1.0;
00281     
00282         /* Calculate */
00283         treecalc(thee, x, y, z, q, npos, val, thee->xp, thee->yp, thee->zp,
00284           thee->qp, thee->np, &fx, &fy, &fz, 1, 1, thee->np);
00285     } else return Vgreen_coulomb_direct(thee, npos, x, y, z, val);
00286 
00287     /* De-allocate charge array (if necessary) */
00288     if (npos > 1) Vmem_free(thee->vmem, npos, sizeof(double), (void **)&q);
00289     
00290     scale = Vunit_ec/(4*Vunit_pi*Vunit_eps0*1.0e-10);
00291     for (ipos=0; ipos<npos; ipos++) val[ipos] = val[ipos]*scale;
00292 
00293     return 1;
00294 
00295 #else /* ifdef HAVE_TREE */
00296 
00297     return Vgreen_coulomb_direct(thee, npos, x, y, z, val);
00298 
00299 #endif
00300 
00301 }
00302 
00303 VPUBLIC int Vgreen_coulombD_direct(Vgreen *thee, int npos, 
00304         double *x, double *y, double *z, double *pot, double *gradx, 
00305         double *grady, double *gradz) {
00306 
00307     Vatom *atom;
00308     double *apos, charge, dist, dist2, idist3, dy, dz, dx, scale;
00309     double *q, qtemp;
00310     int iatom, ipos;
00311 
00312     if (thee == VNULL) {
00313         Vnm_print(2, "Vgreen_coulombD:  Got VNULL thee!\n");
00314         return 0;
00315     }
00316 
00317     for (ipos=0; ipos<npos; ipos++) {
00318         pot[ipos] = 0.0;
00319         gradx[ipos] = 0.0;
00320         grady[ipos] = 0.0;
00321         gradz[ipos] = 0.0;
00322     }
00323 
00324     for (iatom=0; iatom<Valist_getNumberAtoms(thee->alist); iatom++) {
00325         atom = Valist_getAtom(thee->alist, iatom);
00326         apos = Vatom_getPosition(atom);
00327         charge = Vatom_getCharge(atom);
00328         for (ipos=0; ipos<npos; ipos++) {
00329             dx = apos[0] - x[ipos];
00330             dy = apos[1] - y[ipos];
00331             dz = apos[2] - z[ipos];
00332             dist2 = VSQR(dx) + VSQR(dy) + VSQR(dz);
00333             dist = VSQRT(dist2);
00334             if (dist > VSMALL) {
00335                 idist3 = 1.0/(dist*dist2);
00336                 gradx[ipos] -= (charge*dx*idist3);
00337                 grady[ipos] -= (charge*dy*idist3);
00338                 gradz[ipos] -= (charge*dz*idist3);
00339                 pot[ipos] += (charge/dist);
00340             } 
00341         }
00342     }
00343 
00344     scale = Vunit_ec/(4*VPI*Vunit_eps0*(1.0e-10));
00345     for (ipos=0; ipos<npos; ipos++) {
00346         gradx[ipos] = gradx[ipos]*scale;
00347         grady[ipos] = grady[ipos]*scale;
00348         gradz[ipos] = gradz[ipos]*scale;
00349         pot[ipos] = pot[ipos]*scale;
00350     }
00351 
00352     return 1;
00353 }
00354 
00355 VPUBLIC int Vgreen_coulombD(Vgreen *thee, int npos, double *x, double *y,
00356         double *z, double *pot, double *gradx, double *grady, double *gradz) {
00357 
00358     Vatom *atom;
00359     double *apos, charge, dist, dist2, idist3, dy, dz, dx, scale;
00360     double *q, qtemp;
00361     int iatom, ipos;
00362 
00363     if (thee == VNULL) {
00364         Vnm_print(2, "Vgreen_coulombD:  Got VNULL thee!\n");
00365         return 0;
00366     }
00367 
00368     for (ipos=0; ipos<npos; ipos++) {
00369         pot[ipos] = 0.0;
00370         gradx[ipos] = 0.0;
00371         grady[ipos] = 0.0;
00372         gradz[ipos] = 0.0;
00373     }
00374 
00375 #ifdef HAVE_TREE
00376 
00377     if (Valist_getNumberAtoms(thee->alist) > 1) {
00378         if (npos > 1) {
00379             q = VNULL;
00380             q = Vmem_malloc(thee->vmem, npos, sizeof(double));
00381             if (q == VNULL) {
00382                 Vnm_print(2, "Vgreen_coulomb:  Error allocating charge array!\n");
00383                 return 0;
00384             }
00385         } else {
00386             q = &(qtemp);
00387         }
00388         for (ipos=0; ipos<npos; ipos++) q[ipos] = 1.0;
00389     
00390         /* Calculate */
00391         treecalc(thee, x, y, z, q, npos, pot, thee->xp, thee->yp, thee->zp,
00392                 thee->qp, thee->np, gradx, grady, gradz, 2, npos, thee->np);
00393     
00394         /* De-allocate charge array (if necessary) */
00395         if (npos > 1) Vmem_free(thee->vmem, npos, sizeof(double), (void **)&q);
00396     } else return Vgreen_coulombD_direct(thee, npos, x, y, z, pot, 
00397             gradx, grady, gradz);
00398 
00399     scale = Vunit_ec/(4*VPI*Vunit_eps0*(1.0e-10));
00400     for (ipos=0; ipos<npos; ipos++) {
00401         gradx[ipos] = gradx[ipos]*scale;
00402         grady[ipos] = grady[ipos]*scale;
00403         gradz[ipos] = gradz[ipos]*scale;
00404         pot[ipos] = pot[ipos]*scale;
00405     }
00406 
00407     return 1;
00408 
00409 #else /* ifdef HAVE_TREE */
00410 
00411     return Vgreen_coulombD_direct(thee, npos, x, y, z, pot, 
00412             gradx, grady, gradz);
00413 
00414 #endif
00415   
00416 }
00417 
00418 VPRIVATE int treesetup(Vgreen *thee) {
00419 
00420 #ifdef HAVE_TREE
00421 
00422     double dist_tol = FMM_DIST_TOL;
00423     int iflag = FMM_IFLAG;
00424     double order = FMM_ORDER;
00425     int theta = FMM_THETA;
00426     int shrink = FMM_SHRINK;
00427     int maxparnode = FMM_MAXPARNODE;
00428     int minlevel = FMM_MINLEVEL;
00429     int maxlevel = FMM_MAXLEVEL;
00430     int level = 0;
00431     int one = 1;
00432     Vatom *atom;
00433     double xyzminmax[6], *pos;
00434     int i;
00435 
00436     /* Set up particle arrays with atomic coordinates and charges */
00437     Vnm_print(0, "treesetup:  Initializing FMM particle arrays...\n");
00438     thee->np = Valist_getNumberAtoms(thee->alist);
00439     thee->xp = VNULL;
00440     thee->xp = (double *)Vmem_malloc(thee->vmem, thee->np, sizeof(double));
00441     if (thee->xp == VNULL) {
00442         Vnm_print(2, "Vgreen_ctor2:  Failed to allocate %d*sizeof(double)!\n",
00443           thee->np);
00444         return 0;
00445     }
00446     thee->yp = VNULL;
00447     thee->yp = (double *)Vmem_malloc(thee->vmem, thee->np, sizeof(double));
00448     if (thee->yp == VNULL) {
00449         Vnm_print(2, "Vgreen_ctor2:  Failed to allocate %d*sizeof(double)!\n",
00450           thee->np);
00451         return 0;
00452     }
00453     thee->zp = VNULL;
00454     thee->zp = (double *)Vmem_malloc(thee->vmem, thee->np, sizeof(double));
00455     if (thee->zp == VNULL) {
00456         Vnm_print(2, "Vgreen_ctor2:  Failed to allocate %d*sizeof(double)!\n",
00457           thee->np);
00458         return 0;
00459     }
00460     thee->qp = VNULL;
00461     thee->qp = (double *)Vmem_malloc(thee->vmem, thee->np, sizeof(double));
00462     if (thee->qp == VNULL) {
00463         Vnm_print(2, "Vgreen_ctor2:  Failed to allocate %d*sizeof(double)!\n",
00464           thee->np);
00465         return 0;
00466     }
00467     for (i=0; i<thee->np; i++) {
00468         atom = Valist_getAtom(thee->alist, i);
00469         pos = Vatom_getPosition(atom);
00470         thee->xp[i] = pos[0];
00471         thee->yp[i] = pos[1];
00472         thee->zp[i] = pos[2];
00473         thee->qp[i] = Vatom_getCharge(atom);
00474     }
00475 
00476     Vnm_print(0, "treesetup:  Setting things up...\n");
00477     F77SETUP(thee->xp, thee->yp, thee->zp, &(thee->np), &order, &theta, &iflag,
00478             &dist_tol, xyzminmax, &(thee->np));
00479 
00480 
00481     Vnm_print(0, "treesetup:  Initializing levels...\n");
00482     F77INITLEVELS(&minlevel, &maxlevel);
00483 
00484     Vnm_print(0, "treesetup:  Creating tree...\n");
00485     F77CREATE_TREE(&one, &(thee->np), thee->xp, thee->yp, thee->zp, thee->qp, 
00486       &shrink, &maxparnode, xyzminmax, &level, &(thee->np));
00487 
00488     return 1;
00489 
00490 #else /* ifdef HAVE_TREE */
00491 
00492     Vnm_print(2, "treesetup:  Error!  APBS not linked with treecode!\n");
00493     return 0;
00494 
00495 #endif /* ifdef HAVE_TREE */
00496 }
00497 
00498 VPRIVATE int treecleanup(Vgreen *thee) {
00499 
00500 #ifdef HAVE_TREE
00501 
00502     Vmem_free(thee->vmem, thee->np, sizeof(double), (void **)&(thee->xp));
00503     Vmem_free(thee->vmem, thee->np, sizeof(double), (void **)&(thee->yp));
00504     Vmem_free(thee->vmem, thee->np, sizeof(double), (void **)&(thee->zp));
00505     Vmem_free(thee->vmem, thee->np, sizeof(double), (void **)&(thee->qp));
00506     F77CLEANUP();
00507 
00508     return 1;
00509 
00510 #else /* ifdef HAVE_TREE */
00511 
00512     Vnm_print(2, "treecleanup:  Error!  APBS not linked with treecode!\n");
00513     return 0;
00514 
00515 #endif /* ifdef HAVE_TREE */
00516 }
00517 
00518 VPRIVATE int treecalc(Vgreen *thee, double *xtar, double *ytar, double *ztar,
00519         double *qtar, int numtars, double *tpengtar, double *x, double *y,
00520         double *z, double *q, int numpars, double *fx, double *fy, double *fz,
00521         int iflag, int farrdim, int arrdim) {
00522 
00523 #ifdef HAVE_TREE
00524     int i, level, err, maxlevel, minlevel, one;
00525     double xyzminmax[6];
00526 
00527 
00528     if (iflag != 1) {
00529         F77TREE_COMPFP(xtar, ytar, ztar, qtar, &numtars, tpengtar, x, y, z, q,
00530                 fx, fy, fz, &numpars, &farrdim, &arrdim);
00531     } else {
00532         F77TREE_COMPP(xtar, ytar, ztar, qtar, &numtars, tpengtar, &farrdim, x,
00533                 y, z, q, &numpars, &arrdim);
00534     }
00535 
00536 
00537     return 1;
00538 
00539 #else /* ifdef HAVE_TREE */
00540 
00541     Vnm_print(2, "treecalc:  Error!  APBS not linked with treecode!\n");
00542     return 0;
00543 
00544 #endif /* ifdef HAVE_TREE */
00545 }
00546 

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