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

src/generic/vpbe.c

Go to the documentation of this file.
00001 
00049 #include "apbscfg.h"
00050 #include "apbs/vpbe.h"
00051 
00052 /* ///////////////////////////////////////////////////////////////////////////
00053 // Class Vpbe: Private method declaration
00055 #define MAX_SPLINE_WINDOW 0.5
00056 
00057 /* ///////////////////////////////////////////////////////////////////////////
00058 // Class Vpbe: Inlineable methods
00060 #if !defined(VINLINE_VPBE)
00061 
00062 VPUBLIC Valist* Vpbe_getValist(Vpbe *thee) { 
00063 
00064    VASSERT(thee != VNULL);
00065    return thee->alist;
00066 
00067 }
00068 
00069 VPUBLIC Vacc* Vpbe_getVacc(Vpbe *thee) { 
00070 
00071    VASSERT(thee != VNULL);
00072    VASSERT(thee->paramFlag);
00073    return thee->acc; 
00074 
00075 }
00076 
00077 VPUBLIC double Vpbe_getBulkIonicStrength(Vpbe *thee) { 
00078 
00079    VASSERT(thee != VNULL);
00080    VASSERT(thee->paramFlag);
00081    return thee->bulkIonicStrength; 
00082 }
00083 
00084 VPUBLIC double Vpbe_getTemperature(Vpbe *thee) { 
00085 
00086    VASSERT(thee != VNULL);
00087    VASSERT(thee->paramFlag);
00088    return thee->T; 
00089 
00090 }
00091 
00092 VPUBLIC double Vpbe_getSoluteDiel(Vpbe *thee) { 
00093 
00094    VASSERT(thee != VNULL);
00095    VASSERT(thee->paramFlag);
00096    return thee->soluteDiel; 
00097 
00098 }
00099 
00100 VPUBLIC double* Vpbe_getSoluteCenter(Vpbe *thee) { 
00101 
00102    VASSERT(thee != VNULL);
00103    return thee->soluteCenter; 
00104 }
00105 
00106 VPUBLIC double Vpbe_getSolventDiel(Vpbe *thee) { 
00107 
00108    VASSERT(thee != VNULL);
00109    VASSERT(thee->paramFlag);
00110    return thee->solventDiel; 
00111 }
00112 
00113 VPUBLIC double Vpbe_getSolventRadius(Vpbe *thee) { 
00114 
00115    VASSERT(thee != VNULL);
00116    VASSERT(thee->paramFlag);
00117    return thee->solventRadius; 
00118 }
00119 
00120 VPUBLIC double Vpbe_getMaxIonRadius(Vpbe *thee) { 
00121 
00122    VASSERT(thee != VNULL);
00123    VASSERT(thee->paramFlag);
00124    return thee->maxIonRadius; 
00125 }
00126 
00127 VPUBLIC double Vpbe_getXkappa(Vpbe *thee) { 
00128 
00129    VASSERT(thee != VNULL);
00130    VASSERT(thee->paramFlag);
00131    return thee->xkappa; 
00132 }
00133 
00134 VPUBLIC double Vpbe_getDeblen(Vpbe *thee) { 
00135 
00136    VASSERT(thee != VNULL);
00137    VASSERT(thee->paramFlag);
00138    return thee->deblen; 
00139 }
00140 
00141 VPUBLIC double Vpbe_getZkappa2(Vpbe *thee) { 
00142 
00143    VASSERT(thee != VNULL);
00144    VASSERT(thee->paramFlag);
00145    return thee->zkappa2; 
00146 }
00147 
00148 VPUBLIC double Vpbe_getZmagic(Vpbe *thee) { 
00149 
00150    VASSERT(thee != VNULL);
00151    VASSERT(thee->paramFlag);
00152    return thee->zmagic; 
00153 }
00154 
00155 VPUBLIC double Vpbe_getSoluteRadius(Vpbe *thee) { 
00156 
00157    VASSERT(thee != VNULL);
00158    return thee->soluteRadius; 
00159 }
00160 
00161 VPUBLIC double Vpbe_getSoluteXlen(Vpbe *thee) { 
00162 
00163    VASSERT(thee != VNULL);
00164    return thee->soluteXlen; 
00165 }
00166 
00167 VPUBLIC double Vpbe_getSoluteYlen(Vpbe *thee) { 
00168 
00169    VASSERT(thee != VNULL);
00170    return thee->soluteYlen; 
00171 }
00172 
00173 VPUBLIC double Vpbe_getSoluteZlen(Vpbe *thee) { 
00174 
00175    VASSERT(thee != VNULL);
00176    return thee->soluteZlen; 
00177 }
00178 
00179 VPUBLIC double Vpbe_getSoluteCharge(Vpbe *thee) { 
00180 
00181    VASSERT(thee != VNULL);
00182    return thee->soluteCharge; 
00183 }
00184 
00185 /* ///////////////////////////////////////////////////////////////////////////
00186  // Routine:  Vpbe_getzmem
00187  // Purpose: This routine returns values stored in the structure thee.
00188  // Author:  Michael Grabe
00190 VPUBLIC double Vpbe_getzmem(Vpbe *thee) {
00191  
00192  VASSERT(thee != VNULL);
00193  VASSERT(thee->param2Flag);
00194  return thee->z_mem;
00195 }
00196 
00197 /* ///////////////////////////////////////////////////////////////////////////
00198  // Routine:  Vpbe_getLmem
00199  // Purpose: This routine returns values stored in the structure thee.
00200  // Author:  Michael Grabe
00202 VPUBLIC double Vpbe_getLmem(Vpbe *thee) {
00203  
00204  VASSERT(thee != VNULL);
00205  VASSERT(thee->param2Flag);
00206  return thee->L;
00207 }
00208 
00209 /* ///////////////////////////////////////////////////////////////////////////
00210  // Routine:  Vpbe_getmembraneDiel
00211  // Purpose: This routine returns values stored in the structure thee.
00212  // Author:  Michael Grabe
00214 VPUBLIC double Vpbe_getmembraneDiel(Vpbe *thee) {
00215  
00216  VASSERT(thee != VNULL);
00217  VASSERT(thee->param2Flag);
00218  return thee->mmembraneDiel;
00219 }
00220 
00221 /* ///////////////////////////////////////////////////////////////////////////
00222  // Routine:  Vpbe_getmemv
00223  // Purpose: This routine returns values stored in the structure thee.
00224  // Author:  Michael Grabe
00226 VPUBLIC double Vpbe_getmemv(Vpbe *thee) {
00227  
00228  VASSERT(thee != VNULL);
00229  VASSERT(thee->param2Flag);
00230  return thee->V;
00231 }
00232 
00233 #endif /* if !defined(VINLINE_VPBE) */
00234 
00235 /* ///////////////////////////////////////////////////////////////////////////
00236 // Class Vpbe: Non-inlineable methods
00238 
00239 VPUBLIC Vpbe* Vpbe_ctor(Valist *alist, int ionNum, double *ionConc,
00240       double *ionRadii, double *ionQ, double T, 
00241       double soluteDiel, double solventDiel,
00242       double solventRadius, int focusFlag, double sdens,
00243       double z_mem, double L, double membraneDiel, double V ) {
00244  
00245     /* Set up the structure */
00246     Vpbe *thee = VNULL;
00247     thee = Vmem_malloc(VNULL, 1, sizeof(Vpbe) );
00248     VASSERT( thee != VNULL);
00249     VASSERT( Vpbe_ctor2(thee, alist, ionNum, ionConc, ionRadii, ionQ, 
00250       T, soluteDiel, solventDiel, solventRadius, focusFlag, sdens, 
00251       z_mem, L, membraneDiel, V) );
00252  
00253     return thee;
00254 }
00255 
00256 
00257 VPUBLIC int Vpbe_ctor2(Vpbe *thee, Valist *alist, int ionNum,
00258         double *ionConc, double *ionRadii,
00259         double *ionQ, double T, double soluteDiel,
00260         double solventDiel, double solventRadius, int focusFlag,
00261         double sdens, double z_mem, double L, double membraneDiel,
00262         double V) {
00263 
00264     int i, iatom, inhash[3];
00265     double atomRadius;
00266     Vatom *atom;
00267     double center[3] = {0.0, 0.0, 0.0};
00268     double lower_corner[3] = {0.0, 0.0, 0.0};
00269     double upper_corner[3] = {0.0, 0.0, 0.0};
00270     double disp[3], dist, radius, charge, xmin, xmax, ymin, ymax, zmin, zmax;
00271     double x, y, z, netCharge;
00272     double nhash[3];
00273     const double N_A = 6.022045000e+23;
00274     const double e_c = 4.803242384e-10;
00275     const double k_B = 1.380662000e-16;
00276     const double pi  = 4. * VATAN(1.);
00277 
00278     /* Set up memory management object */
00279     thee->vmem = Vmem_ctor("APBS::VPBE");
00280 
00281     VASSERT(thee != VNULL);
00282     if (alist == VNULL) {
00283         Vnm_print(2, "Vpbe_ctor2: Got null pointer to Valist object!\n");
00284         return 0;
00285     }
00286 
00287     /* **** STUFF THAT GETS DONE FOR EVERYONE **** */
00288     /* Set pointers */
00289     thee->alist = alist;
00290     thee->paramFlag = 0;
00291 
00292     /* Determine solute center */
00293     center[0] = thee->alist->center[0];
00294     center[1] = thee->alist->center[1];
00295     center[2] = thee->alist->center[2];
00296     thee->soluteCenter[0] = center[0];
00297     thee->soluteCenter[1] = center[1];
00298     thee->soluteCenter[2] = center[2];
00299 
00300     /* Determine solute length and charge*/
00301     radius = 0;
00302     atom = Valist_getAtom(thee->alist, 0);
00303     xmin = Vatom_getPosition(atom)[0];
00304     xmax = Vatom_getPosition(atom)[0];
00305     ymin = Vatom_getPosition(atom)[1];
00306     ymax = Vatom_getPosition(atom)[1];
00307     zmin = Vatom_getPosition(atom)[2];
00308     zmax = Vatom_getPosition(atom)[2];
00309     charge = 0;
00310     for (iatom=0; iatom<Valist_getNumberAtoms(thee->alist); iatom++) {
00311         atom = Valist_getAtom(thee->alist, iatom);
00312         atomRadius = Vatom_getRadius(atom);
00313         x = Vatom_getPosition(atom)[0];
00314         y = Vatom_getPosition(atom)[1];
00315         z = Vatom_getPosition(atom)[2];
00316         if ((x+atomRadius) > xmax) xmax = x + atomRadius;
00317         if ((x-atomRadius) < xmin) xmin = x - atomRadius;
00318         if ((y+atomRadius) > ymax) ymax = y + atomRadius;
00319         if ((y-atomRadius) < ymin) ymin = y - atomRadius;
00320         if ((z+atomRadius) > zmax) zmax = z + atomRadius;
00321         if ((z-atomRadius) < zmin) zmin = z - atomRadius;
00322         disp[0] = (x - center[0]);
00323         disp[1] = (y - center[1]);
00324         disp[2] = (z - center[2]);
00325         dist = (disp[0]*disp[0]) + (disp[1]*disp[1]) + (disp[2]*disp[2]); 
00326         dist = VSQRT(dist) + atomRadius;
00327         if (dist > radius) radius = dist;
00328         charge += Vatom_getCharge(Valist_getAtom(thee->alist, iatom));
00329     }
00330     thee->soluteRadius = radius;
00331     Vnm_print(0, "Vpbe_ctor2:  solute radius = %g\n", radius);
00332     thee->soluteXlen = xmax - xmin;
00333     thee->soluteYlen = ymax - ymin;
00334     thee->soluteZlen = zmax - zmin;
00335     Vnm_print(0, "Vpbe_ctor2:  solute dimensions = %g x %g x %g\n", 
00336             thee->soluteXlen, thee->soluteYlen, thee->soluteZlen);
00337     thee->soluteCharge = charge;
00338     Vnm_print(0, "Vpbe_ctor2:  solute charge = %g\n", charge);
00339 
00340     /* Set parameters */
00341     thee->numIon = ionNum;
00342     if (thee->numIon >= MAXION) {
00343         Vnm_print(2, "Vpbe_ctor2:  Too many ion species (MAX = %d)!\n",
00344           MAXION);
00345         return 0;
00346     }
00347     thee->bulkIonicStrength = 0.0;
00348     thee->maxIonRadius = 0.0;
00349     netCharge = 0.0;
00350     for (i=0; i<thee->numIon; i++) {
00351         thee->ionConc[i] = ionConc[i];
00352         thee->ionRadii[i] = ionRadii[i];
00353         if (ionRadii[i] > thee->maxIonRadius) thee->maxIonRadius = ionRadii[i];
00354         thee->ionQ[i] = ionQ[i];
00355         thee->bulkIonicStrength += (0.5*ionConc[i]*VSQR(ionQ[i]));
00356         netCharge += (ionConc[i]*ionQ[i]);
00357     } 
00358 #ifndef VAPBSQUIET
00359     Vnm_print(1, "  Vpbe_ctor:  Using max ion radius (%g A) for exclusion \
00360 function\n", thee->maxIonRadius);
00361 #endif
00362     if (VABS(netCharge) > VSMALL) {
00363         Vnm_print(2, "Vpbe_ctor2:  You have a counterion charge imbalance!\n");
00364         Vnm_print(2, "Vpbe_ctor2:  Net charge conc. = %g M\n", netCharge);
00365         return 0;
00366     }
00367     thee->T = T;
00368     thee->soluteDiel = soluteDiel;
00369     thee->solventDiel = solventDiel;
00370     thee->solventRadius = solventRadius;
00371 
00372     /* Compute parameters: 
00373      *
00374      * kappa^2 = (8 pi N_A e_c^2) I_s / (1000 eps_w k_B T)
00375      * kappa   = 0.325567 * I_s^{1/2}   angstroms^{-1}
00376      * deblen  = 1 / kappa
00377      *         = 3.071564378 * I_s^{1/2}   angstroms
00378      * \bar{kappa}^2 = eps_w * kappa^2 
00379      * zmagic  = (4 * pi * e_c^2) / (k_B T)   (we scale the diagonal later)
00380      *         = 7046.528838
00381      */
00382     if (thee->T == 0.0) {
00383         Vnm_print(2, "Vpbe_ctor2:  You set the temperature to 0 K.\n");
00384         Vnm_print(2, "Vpbe_ctor2:  That violates the 3rd Law of Thermo.!");
00385         return 0;
00386     }
00387     if (thee->bulkIonicStrength == 0.) {
00388         thee->xkappa  = 0.;
00389         thee->deblen  = 0.;
00390         thee->zkappa2 = 0.;
00391     } else {
00392         thee->xkappa  = VSQRT( thee->bulkIonicStrength * 1.0e-16 *
00393             ((8.0 * pi * N_A * e_c*e_c) / 
00394             (1000.0 * thee->solventDiel * k_B * T))
00395         );
00396         thee->deblen  = 1. / thee->xkappa;
00397         thee->zkappa2 = thee->solventDiel * VSQR(thee->xkappa);
00398     }
00399     Vnm_print(0, "Vpbe_ctor2:  bulk ionic strength = %g\n", 
00400             thee->bulkIonicStrength);
00401     Vnm_print(0, "Vpbe_ctor2:  xkappa = %g\n", thee->xkappa);
00402     Vnm_print(0, "Vpbe_ctor2:  Debye length = %g\n", thee->deblen);
00403     Vnm_print(0, "Vpbe_ctor2:  zkappa2 = %g\n", thee->zkappa2);
00404     thee->zmagic  = ((4.0 * pi * e_c*e_c) / (k_B * thee->T)) * 1.0e+8;
00405     Vnm_print(0, "Vpbe_ctor2:  zmagic = %g\n", thee->zmagic);
00406 
00407     /* Compute accessibility objects:
00408      *   - Allow for extra room in the case of spline windowing 
00409      *   - Place some limits on the size of the hash table in the case of very
00410      *     large molecules
00411      */
00412     if (thee->maxIonRadius > thee->solventRadius) 
00413         radius = thee->maxIonRadius + MAX_SPLINE_WINDOW;
00414     else radius = thee->solventRadius + MAX_SPLINE_WINDOW;
00415  
00416  nhash[0] = (thee->soluteXlen)/0.5;
00417  nhash[1] = (thee->soluteYlen)/0.5;
00418  nhash[2] = (thee->soluteZlen)/0.5;
00419     for (i=0; i<3; i++) inhash[i] = (int)(nhash[i]);
00420  
00421  for (i=0;i<3;i++){ 
00422         if (inhash[i] < 3) inhash[i] = 3; 
00423         if (inhash[i] > MAX_HASH_DIM) inhash[i] = MAX_HASH_DIM;
00424  }
00425     Vnm_print(0, "Vpbe_ctor2:  Constructing Vclist with %d x %d x %d table\n", 
00426             inhash[0], inhash[1], inhash[2]); 
00427 
00428     thee->clist = Vclist_ctor(thee->alist, radius, inhash, 
00429             CLIST_AUTO_DOMAIN, lower_corner, upper_corner);
00430  
00431     VASSERT(thee->clist != VNULL);
00432     thee->acc = Vacc_ctor(thee->alist, thee->clist, sdens);
00433  
00434     VASSERT(thee->acc != VNULL);
00435 
00436  /* SMPBE Added */
00437  thee->smsize = 0.0;
00438  thee->smvolume = 0.0;
00439  thee->ipkey = 0;
00440  
00441     thee->paramFlag = 1;
00442  
00443  /*-----------------------------------------------------------*/
00444  /* added by Michael Grabe                                    */
00445  /*-----------------------------------------------------------*/
00446  
00447     thee->z_mem = z_mem;
00448     thee->L = L;
00449     thee->membraneDiel = membraneDiel;
00450     thee->V = V;
00451  
00452  //    if (V != VNULL) thee->param2Flag = 1;
00453  //    else thee->param2Flag = 0;
00454  
00455  /*-----------------------------------------------------------*/ 
00456  
00457     return 1; 
00458 }
00459 
00460 VPUBLIC void Vpbe_dtor(Vpbe **thee) {
00461     if ((*thee) != VNULL) {
00462         Vpbe_dtor2(*thee);
00463         Vmem_free(VNULL, 1, sizeof(Vpbe), (void **)thee);
00464         (*thee) = VNULL;
00465     }
00466 }
00467 
00468 VPUBLIC void Vpbe_dtor2(Vpbe *thee) { 
00469     Vclist_dtor(&(thee->clist));
00470     Vacc_dtor(&(thee->acc));
00471     Vmem_dtor(&(thee->vmem));
00472 }
00473 
00474 VPUBLIC double Vpbe_getCoulombEnergy1(Vpbe *thee) {
00475 
00476     int i, j, k, natoms;
00477 
00478     double dist, *ipos, *jpos, icharge, jcharge;
00479     double energy = 0.0;
00480     double eps, T;
00481     Vatom *iatom, *jatom;
00482     Valist *alist;
00483  
00484     VASSERT(thee != VNULL);
00485     alist = Vpbe_getValist(thee);
00486     VASSERT(alist != VNULL);
00487     natoms = Valist_getNumberAtoms(alist);
00488   
00489     /* Do the sum */ 
00490     for (i=0; i<natoms; i++) {
00491         iatom = Valist_getAtom(alist,i);
00492         icharge = Vatom_getCharge(iatom);
00493         ipos = Vatom_getPosition(iatom);
00494         for (j=i+1; j<natoms; j++) {
00495             jatom = Valist_getAtom(alist,j);
00496             jcharge = Vatom_getCharge(jatom);
00497             jpos = Vatom_getPosition(jatom);
00498             dist = 0;
00499             for (k=0; k<3; k++) dist += ((ipos[k]-jpos[k])*(ipos[k]-jpos[k]));
00500             dist = VSQRT(dist);
00501             energy = energy + icharge*jcharge/dist;
00502         }
00503     }
00504 
00505     /* Convert the result to J */
00506     T = Vpbe_getTemperature(thee);
00507     eps = Vpbe_getSoluteDiel(thee);
00508     energy = energy*Vunit_ec*Vunit_ec/(4*Vunit_pi*Vunit_eps0*eps*(1.0e-10));
00509    
00510     /* Scale by Boltzmann energy */
00511     energy = energy/(Vunit_kb*T);
00512 
00513     return energy;
00514 }
00515 
00516 VPUBLIC unsigned long int Vpbe_memChk(Vpbe *thee) {
00517    
00518     unsigned long int memUse = 0;
00519 
00520     if (thee == VNULL) return 0;
00521 
00522     memUse = memUse + sizeof(Vpbe);
00523     memUse = memUse + (unsigned long int)Vacc_memChk(thee->acc);
00524 
00525     return memUse;
00526 }
00527 
00528 VPUBLIC int Vpbe_getIons(Vpbe *thee, int *nion, double ionConc[MAXION],
00529   double ionRadii[MAXION], double ionQ[MAXION]) {
00530 
00531     int i;
00532 
00533     VASSERT(thee != VNULL);
00534   
00535     *nion = thee->numIon;
00536     for (i=0; i<(*nion); i++) {
00537         ionConc[i] = thee->ionConc[i];
00538         ionRadii[i] = thee->ionRadii[i];
00539         ionQ[i] = thee->ionQ[i];
00540     }
00541 
00542     return *nion;
00543 }

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