00001 00049 #include "apbscfg.h" 00050 #include "apbs/vopot.h" 00051 #include "apbs/pbeparm.h" 00052 00053 VEMBED(rcsid="$Id: vopot.c 1552 2010-02-10 17:46:27Z yhuang01 $") 00054 00055 /* /////////////////////////////////////////////////////////////////////////// 00056 // Routine: Vopot_ctor 00057 // Author: Nathan Baker 00059 VPUBLIC Vopot* Vopot_ctor(Vmgrid *mgrid, Vpbe *pbe, Vbcfl bcfl) { 00060 00061 Vopot *thee = VNULL; 00062 00063 thee = Vmem_malloc(VNULL, 1, sizeof(Vopot)); 00064 VASSERT(thee != VNULL); 00065 VASSERT(Vopot_ctor2(thee, mgrid, pbe, bcfl)); 00066 00067 return thee; 00068 } 00069 00070 /* /////////////////////////////////////////////////////////////////////////// 00071 // Routine: Vopot_ctor2 00072 // Author: Nathan Baker 00074 VPUBLIC int Vopot_ctor2(Vopot *thee, Vmgrid *mgrid, Vpbe *pbe, Vbcfl bcfl) { 00075 00076 if (thee == VNULL) return 0; 00077 thee->bcfl = bcfl; 00078 thee->mgrid = mgrid; 00079 thee->pbe = pbe; 00080 00081 return 1; 00082 } 00083 00084 /* /////////////////////////////////////////////////////////////////////////// 00085 // Routine: Vopot_dtor 00086 // Author: Nathan Baker 00088 VPUBLIC void Vopot_dtor(Vopot **thee) { 00089 00090 if ((*thee) != VNULL) { 00091 Vopot_dtor2(*thee); 00092 Vmem_free(VNULL, 1, sizeof(Vopot), (void **)thee); 00093 (*thee) = VNULL; 00094 } 00095 } 00096 00097 /* /////////////////////////////////////////////////////////////////////////// 00098 // Routine: Vopot_dtor2 00099 // Author: Nathan Baker 00101 VPUBLIC void Vopot_dtor2(Vopot *thee) { return; } 00102 00103 /* /////////////////////////////////////////////////////////////////////////// 00104 // Routine: Vopot_pot 00105 // Author: Nathan Baker 00107 #define IJK(i,j,k) (((k)*(nx)*(ny))+((j)*(nx))+(i)) 00108 VPUBLIC int Vopot_pot(Vopot *thee, double pt[3], double *value) { 00109 00110 Vatom *atom; 00111 int i, iatom; 00112 double u, T, charge, eps_w, xkappa, dist, size, val, *position; 00113 Valist *alist; 00114 00115 VASSERT(thee != VNULL); 00116 00117 eps_w = Vpbe_getSolventDiel(thee->pbe); 00118 xkappa = (1.0e10)*Vpbe_getXkappa(thee->pbe); 00119 T = Vpbe_getTemperature(thee->pbe); 00120 alist = Vpbe_getValist(thee->pbe); 00121 00122 u = 0; 00123 00124 /* See if we're on the mesh */ 00125 if (Vmgrid_value(thee->mgrid, pt, &u)) { 00126 00127 *value = u; 00128 00129 } else { 00130 00131 switch (thee->bcfl) { 00132 00133 case BCFL_ZERO: 00134 u = 0; 00135 break; 00136 00137 case BCFL_SDH: 00138 size = (1.0e-10)*Vpbe_getSoluteRadius(thee->pbe); 00139 position = Vpbe_getSoluteCenter(thee->pbe); 00140 charge = Vunit_ec*Vpbe_getSoluteCharge(thee->pbe); 00141 dist = 0; 00142 for (i=0; i<3; i++) 00143 dist += VSQR(position[i] - pt[i]); 00144 dist = (1.0e-10)*VSQRT(dist); 00145 val = (charge)/(4*VPI*Vunit_eps0*eps_w*dist); 00146 if (xkappa != 0.0) 00147 val = val*(exp(-xkappa*(dist-size))/(1+xkappa*size)); 00148 val = val*Vunit_ec/(Vunit_kb*T); 00149 u = val; 00150 break; 00151 00152 case BCFL_MDH: 00153 u = 0; 00154 for (iatom=0; iatom<Valist_getNumberAtoms(alist); iatom++) { 00155 atom = Valist_getAtom(alist, iatom); 00156 position = Vatom_getPosition(atom); 00157 charge = Vunit_ec*Vatom_getCharge(atom); 00158 size = (1e-10)*Vatom_getRadius(atom); 00159 dist = 0; 00160 for (i=0; i<3; i++) 00161 dist += VSQR(position[i] - pt[i]); 00162 dist = (1.0e-10)*VSQRT(dist); 00163 val = (charge)/(4*VPI*Vunit_eps0*eps_w*dist); 00164 if (xkappa != 0.0) 00165 val = val*(exp(-xkappa*(dist-size))/(1+xkappa*size)); 00166 val = val*Vunit_ec/(Vunit_kb*T); 00167 u = u + val; 00168 } 00169 break; 00170 00171 case BCFL_UNUSED: 00172 Vnm_print(2, "Vopot_pot: Invalid bcfl flag (%d)!\n", 00173 thee->bcfl); 00174 return 0; 00175 00176 case BCFL_FOCUS: 00177 Vnm_print(2, "Vopot_pot: Invalid bcfl flag (%d)!\n", 00178 thee->bcfl); 00179 return 0; 00180 00181 default: 00182 Vnm_print(2, "Vopot_pot: Bogus thee->bcfl flag (%d)!\n", 00183 thee->bcfl); 00184 return 0; 00185 break; 00186 } 00187 00188 *value = u; 00189 00190 } 00191 00192 return 1; 00193 00194 } 00195 00196 /* /////////////////////////////////////////////////////////////////////////// 00197 // Routine: Vopot_curvature 00198 // 00199 // Notes: cflag=0 ==> Reduced Maximal Curvature 00200 // cflag=1 ==> Mean Curvature (Laplace) 00201 // cflag=2 ==> Gauss Curvature 00202 // cflag=3 ==> True Maximal Curvature 00203 // If we are off the grid, we can still evaluate the Laplacian; assuming, we 00204 // are away from the molecular surface, it is simply equal to the DH factor. 00205 // 00206 // Authors: Nathan Baker 00208 VPUBLIC int Vopot_curvature(Vopot *thee, double pt[3], int cflag, 00209 double *value) { 00210 00211 Vatom *atom; 00212 int i, iatom; 00213 double u, T, charge, eps_w, xkappa, dist, size, val, *position, zkappa2; 00214 Valist *alist; 00215 00216 VASSERT(thee != VNULL); 00217 00218 eps_w = Vpbe_getSolventDiel(thee->pbe); 00219 xkappa = (1.0e10)*Vpbe_getXkappa(thee->pbe); 00220 zkappa2 = Vpbe_getZkappa2(thee->pbe); 00221 T = Vpbe_getTemperature(thee->pbe); 00222 alist = Vpbe_getValist(thee->pbe); 00223 00224 u = 0; 00225 00226 if (Vmgrid_curvature(thee->mgrid, pt, cflag, value)) return 1; 00227 else if (cflag != 1) { 00228 Vnm_print(2, "Vopot_curvature: Off mesh!\n"); 00229 return 1; 00230 } else { 00231 00232 switch (thee->bcfl) { 00233 00234 case BCFL_ZERO: 00235 u = 0; 00236 break; 00237 00238 case BCFL_SDH: 00239 size = (1.0e-10)*Vpbe_getSoluteRadius(thee->pbe); 00240 position = Vpbe_getSoluteCenter(thee->pbe); 00241 charge = Vunit_ec*Vpbe_getSoluteCharge(thee->pbe); 00242 dist = 0; 00243 for (i=0; i<3; i++) 00244 dist += VSQR(position[i] - pt[i]); 00245 dist = (1.0e-10)*VSQRT(dist); 00246 if (xkappa != 0.0) 00247 u = zkappa2*(exp(-xkappa*(dist-size))/(1+xkappa*size)); 00248 break; 00249 00250 case BCFL_MDH: 00251 u = 0; 00252 for (iatom=0; iatom<Valist_getNumberAtoms(alist); iatom++) { 00253 atom = Valist_getAtom(alist, iatom); 00254 position = Vatom_getPosition(atom); 00255 charge = Vunit_ec*Vatom_getCharge(atom); 00256 size = (1e-10)*Vatom_getRadius(atom); 00257 dist = 0; 00258 for (i=0; i<3; i++) 00259 dist += VSQR(position[i] - pt[i]); 00260 dist = (1.0e-10)*VSQRT(dist); 00261 if (xkappa != 0.0) 00262 val = zkappa2*(exp(-xkappa*(dist-size))/(1+xkappa*size)); 00263 u = u + val; 00264 } 00265 break; 00266 00267 case BCFL_UNUSED: 00268 Vnm_print(2, "Vopot_pot: Invlid bcfl (%d)!\n", thee->bcfl); 00269 return 0; 00270 00271 case BCFL_FOCUS: 00272 Vnm_print(2, "Vopot_pot: Invlid bcfl (%d)!\n", thee->bcfl); 00273 return 0; 00274 00275 default: 00276 Vnm_print(2, "Vopot_pot: Bogus thee->bcfl flag (%d)!\n", 00277 thee->bcfl); 00278 return 0; 00279 break; 00280 } 00281 00282 *value = u; 00283 } 00284 00285 return 1; 00286 00287 } 00288 00289 /* /////////////////////////////////////////////////////////////////////////// 00290 // Routine: Vopot_gradient 00291 // 00292 // Authors: Nathan Baker 00294 VPUBLIC int Vopot_gradient(Vopot *thee, double pt[3], double grad[3]) { 00295 00296 Vatom *atom; 00297 int iatom; 00298 double T, charge, eps_w, xkappa, size, val, *position; 00299 double dx, dy, dz, dist; 00300 Valist *alist; 00301 00302 VASSERT(thee != VNULL); 00303 00304 eps_w = Vpbe_getSolventDiel(thee->pbe); 00305 xkappa = (1.0e10)*Vpbe_getXkappa(thee->pbe); 00306 T = Vpbe_getTemperature(thee->pbe); 00307 alist = Vpbe_getValist(thee->pbe); 00308 00309 00310 if (!Vmgrid_gradient(thee->mgrid, pt, grad)) { 00311 00312 switch (thee->bcfl) { 00313 00314 case BCFL_ZERO: 00315 grad[0] = 0.0; 00316 grad[1] = 0.0; 00317 grad[2] = 0.0; 00318 break; 00319 00320 case BCFL_SDH: 00321 grad[0] = 0.0; 00322 grad[1] = 0.0; 00323 grad[2] = 0.0; 00324 size = (1.0e-10)*Vpbe_getSoluteRadius(thee->pbe); 00325 position = Vpbe_getSoluteCenter(thee->pbe); 00326 charge = Vunit_ec*Vpbe_getSoluteCharge(thee->pbe); 00327 dx = position[0] - pt[0]; 00328 dy = position[1] - pt[1]; 00329 dz = position[2] - pt[2]; 00330 dist = VSQR(dx) + VSQR(dy) + VSQR(dz); 00331 dist = (1.0e-10)*VSQRT(dist); 00332 val = (charge)/(4*VPI*Vunit_eps0*eps_w); 00333 if (xkappa != 0.0) 00334 val = val*(exp(-xkappa*(dist-size))/(1+xkappa*size)); 00335 val = val*Vunit_ec/(Vunit_kb*T); 00336 grad[0] = val*dx/dist*(-1.0/dist/dist + xkappa/dist); 00337 grad[1] = val*dy/dist*(-1.0/dist/dist + xkappa/dist); 00338 grad[2] = val*dz/dist*(-1.0/dist/dist + xkappa/dist); 00339 break; 00340 00341 case BCFL_MDH: 00342 grad[0] = 0.0; 00343 grad[1] = 0.0; 00344 grad[2] = 0.0; 00345 for (iatom=0; iatom<Valist_getNumberAtoms(alist); iatom++) { 00346 atom = Valist_getAtom(alist, iatom); 00347 position = Vatom_getPosition(atom); 00348 charge = Vunit_ec*Vatom_getCharge(atom); 00349 size = (1e-10)*Vatom_getRadius(atom); 00350 dx = position[0] - pt[0]; 00351 dy = position[1] - pt[1]; 00352 dz = position[2] - pt[2]; 00353 dist = VSQR(dx) + VSQR(dy) + VSQR(dz); 00354 dist = (1.0e-10)*VSQRT(dist); 00355 val = (charge)/(4*VPI*Vunit_eps0*eps_w); 00356 if (xkappa != 0.0) 00357 val = val*(exp(-xkappa*(dist-size))/(1+xkappa*size)); 00358 val = val*Vunit_ec/(Vunit_kb*T); 00359 grad[0] += (val*dx/dist*(-1.0/dist/dist + xkappa/dist)); 00360 grad[1] += (val*dy/dist*(-1.0/dist/dist + xkappa/dist)); 00361 grad[2] += (val*dz/dist*(-1.0/dist/dist + xkappa/dist)); 00362 } 00363 break; 00364 00365 case BCFL_UNUSED: 00366 Vnm_print(2, "Vopot: Invalid bcfl (%d)!\n", thee->bcfl); 00367 return 0; 00368 00369 case BCFL_FOCUS: 00370 Vnm_print(2, "Vopot: Invalid bcfl (%d)!\n", thee->bcfl); 00371 return 0; 00372 00373 default: 00374 Vnm_print(2, "Vopot_pot: Bogus thee->bcfl flag (%d)!\n", 00375 thee->bcfl); 00376 return 0; 00377 break; 00378 } 00379 00380 return 1; 00381 } 00382 00383 return 1; 00384 00385 } 00386