00001
00049 #include "apbscfg.h"
00050 #include "apbs/vacc.h"
00051 #include "apbs/apolparm.h"
00052
00053 #if defined(HAVE_MC_H)
00054 #include "mc/mc.h"
00055 #endif
00056
00057 VEMBED(rcsid="$Id: vacc.c 1605 2010-09-13 15:12:09Z yhuang01 $")
00058
00059 #if !defined(VINLINE_VACC)
00060
00061 VPUBLIC unsigned long int Vacc_memChk(Vacc *thee) {
00062 if (thee == VNULL) return 0;
00063 return Vmem_bytes(thee->mem);
00064 }
00065
00066 #endif
00067
00077 VPRIVATE int ivdwAccExclus(
00078 Vacc *thee,
00079 double center[3],
00080 double radius,
00081 int atomID
00082 ) {
00083
00084 int iatom;
00085 double dist2, *apos;
00086 Vatom *atom;
00087 VclistCell *cell;
00088
00089 VASSERT(thee != VNULL);
00090
00091
00092 if (radius > Vclist_maxRadius(thee->clist)) {
00093 Vnm_print(2,
00094 "Vacc_ivdwAcc: got radius (%g) bigger than max radius (%g)\n",
00095 radius, Vclist_maxRadius(thee->clist));
00096 VASSERT(0);
00097 }
00098
00099
00100 cell = Vclist_getCell(thee->clist, center);
00101
00102
00103
00104 if (cell == VNULL) {
00105 return 1;
00106 }
00107
00108
00109 for (iatom=0; iatom<cell->natoms; iatom++) {
00110 atom = cell->atoms[iatom];
00111 apos = atom->position;
00112 dist2 = VSQR(center[0]-apos[0]) + VSQR(center[1]-apos[1])
00113 + VSQR(center[2]-apos[2]);
00114 if (dist2 < VSQR(atom->radius+radius)){
00115 if (atom->id != atomID) return 0;
00116 }
00117 }
00118
00119
00120 return 1;
00121
00122 }
00123
00124 VPUBLIC Vacc* Vacc_ctor(Valist *alist, Vclist *clist, double surf_density) {
00125
00126
00127 Vacc *thee = VNULL;
00128
00129
00130 thee = Vmem_malloc(VNULL, 1, sizeof(Vacc) );
00131 VASSERT( thee != VNULL);
00132 VASSERT( Vacc_ctor2(thee, alist, clist, surf_density));
00133 return thee;
00134 }
00135
00137 VPRIVATE int Vacc_storeParms(Vacc *thee, Valist *alist, Vclist *clist,
00138 double surf_density) {
00139
00140 int nsphere, iatom;
00141 double maxrad, maxarea, rad;
00142 Vatom *atom;
00143
00144 if (alist == VNULL) {
00145 Vnm_print(2, "Vacc_storeParms: Got NULL Valist!\n");
00146 return 0;
00147 } else thee->alist = alist;
00148 if (clist == VNULL) {
00149 Vnm_print(2, "Vacc_storeParms: Got NULL Vclist!\n");
00150 return 0;
00151 } else thee->clist = clist;
00152 thee->surf_density = surf_density;
00153
00154
00155 maxrad = 0.0;
00156 for (iatom=0; iatom<Valist_getNumberAtoms(alist); iatom++) {
00157 atom = Valist_getAtom(alist, iatom);
00158 rad = Vatom_getRadius(atom);
00159 if (rad > maxrad) maxrad = rad;
00160 }
00161 maxrad = maxrad + Vclist_maxRadius(thee->clist);
00162
00163 maxarea = 4.0*VPI*maxrad*maxrad;
00164 nsphere = (int)ceil(maxarea*surf_density);
00165
00166 Vnm_print(0, "Vacc_storeParms: Surf. density = %g\n", surf_density);
00167 Vnm_print(0, "Vacc_storeParms: Max area = %g\n", maxarea);
00168 thee->refSphere = VaccSurf_refSphere(thee->mem, nsphere);
00169 Vnm_print(0, "Vacc_storeParms: Using %d-point reference sphere\n",
00170 thee->refSphere->npts);
00171
00172 return 1;
00173 }
00174
00176 VPRIVATE int Vacc_allocate(Vacc *thee) {
00177
00178 int i, natoms;
00179
00180 natoms = Valist_getNumberAtoms(thee->alist);
00181
00182 thee->atomFlags = Vmem_malloc(thee->mem, natoms, sizeof(int));
00183 if (thee->atomFlags == VNULL) {
00184 Vnm_print(2,
00185 "Vacc_allocate: Failed to allocate %d (int)s for atomFlags!\n",
00186 natoms);
00187 return 0;
00188 }
00189 for (i=0; i<natoms; i++) (thee->atomFlags)[i] = 0;
00190
00191 return 1;
00192 }
00193
00194
00195 VPUBLIC int Vacc_ctor2(Vacc *thee, Valist *alist, Vclist *clist,
00196 double surf_density) {
00197
00198
00199 if (!Vacc_storeParms(thee, alist, clist, surf_density)) {
00200 Vnm_print(2, "Vacc_ctor2: parameter check failed!\n");
00201 return 0;
00202 }
00203
00204
00205 thee->mem = Vmem_ctor("APBS::VACC");
00206 if (thee->mem == VNULL) {
00207 Vnm_print(2, "Vacc_ctor2: memory object setup failed!\n");
00208 return 0;
00209 }
00210
00211
00212 thee->surf = VNULL;
00213
00214
00215 if (!Vacc_allocate(thee)) {
00216 Vnm_print(2, "Vacc_ctor2: memory allocation failed!\n");
00217 return 0;
00218 }
00219
00220 return 1;
00221 }
00222
00223
00224 VPUBLIC void Vacc_dtor(Vacc **thee) {
00225
00226 if ((*thee) != VNULL) {
00227 Vacc_dtor2(*thee);
00228 Vmem_free(VNULL, 1, sizeof(Vacc), (void **)thee);
00229 (*thee) = VNULL;
00230 }
00231
00232 }
00233
00234 VPUBLIC void Vacc_dtor2(Vacc *thee) {
00235
00236 int i, natoms;
00237
00238 natoms = Valist_getNumberAtoms(thee->alist);
00239 Vmem_free(thee->mem, natoms, sizeof(int), (void **)&(thee->atomFlags));
00240
00241 if (thee->refSphere != VNULL) {
00242 VaccSurf_dtor(&(thee->refSphere));
00243 thee->refSphere = VNULL;
00244 }
00245 if (thee->surf != VNULL) {
00246 for (i=0; i<natoms; i++) VaccSurf_dtor(&(thee->surf[i]));
00247 Vmem_free(thee->mem, natoms, sizeof(VaccSurf *),
00248 (void **)&(thee->surf));
00249 thee->surf = VNULL;
00250 }
00251
00252 Vmem_dtor(&(thee->mem));
00253 }
00254
00255 VPUBLIC double Vacc_vdwAcc(Vacc *thee, double center[3]) {
00256
00257 VclistCell *cell;
00258 Vatom *atom;
00259 int iatom;
00260 double *apos;
00261 double dist2;
00262
00263
00264 cell = Vclist_getCell(thee->clist, center);
00265
00266
00267
00268 if (cell == VNULL) return 1.0;
00269
00270
00271 for (iatom=0; iatom<cell->natoms; iatom++) {
00272 atom = cell->atoms[iatom];
00273 apos = Vatom_getPosition(atom);
00274 dist2 = VSQR(center[0]-apos[0]) + VSQR(center[1]-apos[1])
00275 + VSQR(center[2]-apos[2]);
00276 if (dist2 < VSQR(Vatom_getRadius(atom))) return 0.0;
00277 }
00278
00279
00280 return 1.0;
00281 }
00282
00283 VPUBLIC double Vacc_ivdwAcc(Vacc *thee, double center[3], double radius) {
00284
00285 return (double)ivdwAccExclus(thee, center, radius, -1);
00286
00287 }
00288
00289 VPUBLIC void Vacc_splineAccGradAtomNorm(Vacc *thee, double center[VAPBS_DIM],
00290 double win, double infrad, Vatom *atom, double *grad) {
00291
00292 int i;
00293 double dist, *apos, arad, sm, sm2, w2i, w3i, mygrad;
00294 double mychi = 1.0;
00295
00296 VASSERT(thee != NULL);
00297
00298
00299 w2i = 1.0/(win*win);
00300 w3i = 1.0/(win*win*win);
00301
00302
00303 for (i=0; i<VAPBS_DIM; i++) grad[i] = 0.0;
00304
00305
00306
00307 apos = Vatom_getPosition(atom);
00308
00309 if (Vatom_getRadius(atom) > 0.0) {
00310 arad = Vatom_getRadius(atom) + infrad;
00311 dist = VSQRT(VSQR(apos[0]-center[0]) + VSQR(apos[1]-center[1])
00312 + VSQR(apos[2]-center[2]));
00313
00314
00315 if (dist < (arad - win)) return;
00316
00317
00318 else if (dist > (arad + win)) return;
00319
00320
00321
00322 else if ((VABS(dist - (arad - win)) < VSMALL) ||
00323 (VABS(dist - (arad + win)) < VSMALL)) return;
00324
00325 else {
00326 sm = dist - arad + win;
00327 sm2 = VSQR(sm);
00328 mychi = 0.75*sm2*w2i -0.25*sm*sm2*w3i;
00329 mygrad = 1.5*sm*w2i - 0.75*sm2*w3i;
00330 }
00331
00332 VASSERT(mychi > 0.0);
00333 for (i=0; i<VAPBS_DIM; i++)
00334 grad[i] = -(mygrad/mychi)*((center[i] - apos[i])/dist);
00335 }
00336 }
00337
00338 VPUBLIC void Vacc_splineAccGradAtomUnnorm(Vacc *thee, double center[VAPBS_DIM],
00339 double win, double infrad, Vatom *atom, double *grad) {
00340
00341 int i;
00342 double dist, *apos, arad, sm, sm2, w2i, w3i, mygrad;
00343 double mychi = 1.0;
00344
00345 VASSERT(thee != NULL);
00346
00347
00348 w2i = 1.0/(win*win);
00349 w3i = 1.0/(win*win*win);
00350
00351
00352 for (i=0; i<VAPBS_DIM; i++) grad[i] = 0.0;
00353
00354
00355
00356 apos = Vatom_getPosition(atom);
00357
00358 if (Vatom_getRadius(atom) > 0.0) {
00359 arad = Vatom_getRadius(atom) + infrad;
00360 dist = VSQRT(VSQR(apos[0]-center[0]) + VSQR(apos[1]-center[1])
00361 + VSQR(apos[2]-center[2]));
00362
00363
00364 if (dist < (arad - win)) return;
00365
00366
00367 else if (dist > (arad + win)) return;
00368
00369
00370
00371 else if ((VABS(dist - (arad - win)) < VSMALL) ||
00372 (VABS(dist - (arad + win)) < VSMALL)) return;
00373
00374 else {
00375 sm = dist - arad + win;
00376 sm2 = VSQR(sm);
00377 mychi = 0.75*sm2*w2i -0.25*sm*sm2*w3i;
00378 mygrad = 1.5*sm*w2i - 0.75*sm2*w3i;
00379 }
00380
00381 VASSERT(mychi > 0.0);
00382 for (i=0; i<VAPBS_DIM; i++)
00383 grad[i] = -(mygrad)*((center[i] - apos[i])/dist);
00384 }
00385 }
00386
00387 VPUBLIC double Vacc_splineAccAtom(Vacc *thee, double center[VAPBS_DIM],
00388 double win, double infrad, Vatom *atom) {
00389
00390 double dist, *apos, arad, sm, sm2, w2i, w3i, value, stot, sctot;
00391
00392 VASSERT(thee != NULL);
00393
00394
00395 w2i = 1.0/(win*win);
00396 w3i = 1.0/(win*win*win);
00397
00398 apos = Vatom_getPosition(atom);
00399
00400 if (Vatom_getRadius(atom) > 0.0) {
00401 arad = Vatom_getRadius(atom) + infrad;
00402 stot = arad + win;
00403 sctot = VMAX2(0, (arad - win));
00404 dist = VSQRT(VSQR(apos[0]-center[0]) + VSQR(apos[1]-center[1])
00405 + VSQR(apos[2]-center[2]));
00406
00407
00408 if ((dist < sctot) || (VABS(dist - sctot) < VSMALL)){
00409 value = 0.0;
00410
00411 } else if ((dist > stot) || (VABS(dist - stot) < VSMALL)) {
00412 value = 1.0;
00413
00414 } else {
00415 sm = dist - arad + win;
00416 sm2 = VSQR(sm);
00417 value = 0.75*sm2*w2i - 0.25*sm*sm2*w3i;
00418 }
00419 } else value = 1.0;
00420
00421 return value;
00422 }
00423
00429 VPRIVATE double splineAcc(
00430 Vacc *thee,
00431 double center[VAPBS_DIM],
00433 double win,
00434 double infrad,
00435 VclistCell *cell
00436 ) {
00437
00438 int atomID, iatom;
00439 Vatom *atom;
00440 double value = 1.0;
00441
00442 VASSERT(thee != NULL);
00443
00444
00445 for (iatom=0; iatom<cell->natoms; iatom++) {
00446
00447 atom = cell->atoms[iatom];
00448 atomID = atom->id;
00449
00450
00451 if ( !(thee->atomFlags[atomID]) ) {
00452
00453 thee->atomFlags[atomID] = 1;
00454 value *= Vacc_splineAccAtom(thee, center, win, infrad, atom);
00455
00456 if (value < VSMALL) return value;
00457 }
00458 }
00459
00460 return value;
00461 }
00462
00463
00464 VPUBLIC double Vacc_splineAcc(Vacc *thee, double center[VAPBS_DIM], double win,
00465 double infrad) {
00466
00467 VclistCell *cell;
00468 Vatom *atom;
00469 int iatom, atomID;
00470
00471
00472 VASSERT(thee != NULL);
00473
00474 if (Vclist_maxRadius(thee->clist) < (win + infrad)) {
00475 Vnm_print(2, "Vacc_splineAcc: Vclist has max_radius=%g;\n",
00476 Vclist_maxRadius(thee->clist));
00477 Vnm_print(2, "Vacc_splineAcc: Insufficient for win=%g, infrad=%g\n",
00478 win, infrad);
00479 VASSERT(0);
00480 }
00481
00482
00483 cell = Vclist_getCell(thee->clist, center);
00484 if (cell == VNULL) return 1.0;
00485
00486
00487
00488 for (iatom=0; iatom<cell->natoms; iatom++) {
00489 atom = cell->atoms[iatom];
00490 atomID = atom->id;
00491 thee->atomFlags[atomID] = 0;
00492 }
00493
00494 return splineAcc(thee, center, win, infrad, cell);
00495 }
00496
00497 VPUBLIC void Vacc_splineAccGrad(Vacc *thee, double center[VAPBS_DIM],
00498 double win, double infrad, double *grad) {
00499
00500 int iatom, i, atomID;
00501 double acc = 1.0;
00502 double tgrad[VAPBS_DIM];
00503 VclistCell *cell;
00504 Vatom *atom = VNULL;
00505
00506 VASSERT(thee != NULL);
00507
00508 if (Vclist_maxRadius(thee->clist) < (win + infrad)) {
00509 Vnm_print(2, "Vacc_splineAccGrad: Vclist max_radius=%g;\n",
00510 Vclist_maxRadius(thee->clist));
00511 Vnm_print(2, "Vacc_splineAccGrad: Insufficient for win=%g, infrad=%g\n",
00512 win, infrad);
00513 VASSERT(0);
00514 }
00515
00516
00517 for (i=0; i<VAPBS_DIM; i++) grad[i] = 0.0;
00518
00519
00520 cell = Vclist_getCell(thee->clist, center);
00521 if (cell == VNULL) return;
00522
00523
00524 for (iatom=0; iatom<cell->natoms; iatom++) {
00525 atom = cell->atoms[iatom];
00526 atomID = atom->id;
00527 thee->atomFlags[atomID] = 0;
00528 }
00529
00530
00531 acc = splineAcc(thee, center, win, infrad, cell);
00532
00533
00534 if (acc > VSMALL) {
00535 for (iatom=0; iatom<cell->natoms; iatom++) {
00536 atom = cell->atoms[iatom];
00537 Vacc_splineAccGradAtomNorm(thee, center, win, infrad, atom, tgrad);
00538 }
00539 for (i=0; i<VAPBS_DIM; i++) grad[i] += tgrad[i];
00540 }
00541 for (i=0; i<VAPBS_DIM; i++) grad[i] *= -acc;
00542 }
00543
00544 VPUBLIC double Vacc_molAcc(Vacc *thee, double center[VAPBS_DIM],
00545 double radius) {
00546
00547 double rc;
00548
00549
00550 if (Vacc_ivdwAcc(thee, center, radius) == 1.0) {
00551
00552
00553 rc = 1.0;
00554
00555
00556 } else if (Vacc_vdwAcc(thee, center) == 0.0) {
00557
00558
00559 rc = 0.0;
00560
00561
00562 } else {
00563
00564
00565 rc = Vacc_fastMolAcc(thee, center, radius);
00566
00567 }
00568
00569 return rc;
00570
00571 }
00572
00573 VPUBLIC double Vacc_fastMolAcc(Vacc *thee, double center[VAPBS_DIM],
00574 double radius) {
00575
00576 Vatom *atom;
00577 VaccSurf *surf;
00578 VclistCell *cell;
00579 int ipt, iatom, atomID;
00580 double dist2, rad2;
00581
00582 rad2 = radius*radius;
00583
00584
00585 if (thee->surf == VNULL) Vacc_SASA(thee, radius);
00586
00587
00588 cell = Vclist_getCell(thee->clist, center);
00589 if (cell == VNULL) {
00590 Vnm_print(2, "Vacc_fastMolAcc: unexpected VNULL VclistCell!\n");
00591 return 1.0;
00592 }
00593
00594
00595 for (iatom=0; iatom<cell->natoms; iatom++) {
00596 atom = cell->atoms[iatom];
00597 atomID = Vatom_getAtomID(atom);
00598 surf = thee->surf[atomID];
00599
00600 for (ipt=0; ipt<surf->npts; ipt++) {
00601
00602 dist2 = VSQR(center[0]-(surf->xpts[ipt]))
00603 + VSQR(center[1]-(surf->ypts[ipt]))
00604 + VSQR(center[2]-(surf->zpts[ipt]));
00605 if (dist2 < rad2) return 1.0;
00606 }
00607 }
00608
00609
00610 return 0.0;
00611 }
00612
00613
00614 #if defined(HAVE_MC_H)
00615 VPUBLIC void Vacc_writeGMV(Vacc *thee, double radius, int meth, Gem *gm,
00616 char *iodev, char *iofmt, char *iohost, char *iofile) {
00617
00618 double *accVals[MAXV], coord[3];
00619 Vio *sock;
00620 int ivert, icoord;
00621
00622 for (ivert=0; ivert<MAXV; ivert++) accVals[ivert] = VNULL;
00623 accVals[0] = (void *)Vmem_malloc(thee->mem, Gem_numVV(gm), sizeof(double));
00624 accVals[1] = (void *)Vmem_malloc(thee->mem, Gem_numVV(gm), sizeof(double));
00625 for (ivert=0; ivert<Gem_numVV(gm); ivert++) {
00626 for (icoord=0;icoord<3;icoord++)
00627 coord[icoord] = VV_coord(Gem_VV(gm, ivert), icoord);
00628 if (meth == 0) {
00629 accVals[0][ivert] = Vacc_molAcc(thee, coord, radius);
00630 accVals[1][ivert] = Vacc_molAcc(thee, coord, radius);
00631 } else if (meth == 1) {
00632 accVals[0][ivert] = Vacc_ivdwAcc(thee, coord, radius);
00633 accVals[1][ivert] = Vacc_ivdwAcc(thee, coord, radius);
00634 } else if (meth == 2) {
00635 accVals[0][ivert] = Vacc_vdwAcc(thee, coord);
00636 accVals[1][ivert] = Vacc_vdwAcc(thee, coord);
00637 } else VASSERT(0);
00638 }
00639 sock = Vio_ctor(iodev, iofmt, iohost, iofile, "w");
00640 Gem_writeGMV(gm, sock, 1, accVals);
00641 Vio_dtor(&sock);
00642 Vmem_free(thee->mem, Gem_numVV(gm), sizeof(double),
00643 (void **)&(accVals[0]));
00644 Vmem_free(thee->mem, Gem_numVV(gm), sizeof(double),
00645 (void **)&(accVals[1]));
00646 }
00647 #endif
00648
00649 VPUBLIC double Vacc_SASA(Vacc *thee, double radius) {
00650
00651 int i, natom;
00652 double area, *apos;
00653 Vatom *atom;
00654 VaccSurf *asurf;
00655
00656 unsigned long long mbeg;
00657
00658 natom = Valist_getNumberAtoms(thee->alist);
00659
00660
00661 if (thee->surf == VNULL) {
00662 thee->surf = Vmem_malloc(thee->mem, natom, sizeof(VaccSurf *));
00663
00664 #if defined(DEBUG_MAC_OSX_OCL) || defined(DEBUG_MAC_OSX_STANDARD)
00665 #include "mach_chud.h"
00666 machm_(&mbeg);
00667 #pragma omp parallel for private(i,atom)
00668 #endif
00669 for (i=0; i<natom; i++) {
00670 atom = Valist_getAtom(thee->alist, i);
00671
00672
00673 thee->surf[i] = Vacc_atomSurf(thee, atom, thee->refSphere,
00674 radius);
00675 }
00676 }
00677
00678
00679 area = 0.0;
00680 for (i=0; i<natom; i++) {
00681 atom = Valist_getAtom(thee->alist, i);
00682 asurf = thee->surf[i];
00683
00684 if (asurf->probe_radius != radius) {
00685 Vnm_print(2, "Vacc_SASA: Warning -- probe radius changed from %g to %g!\n",
00686 asurf->probe_radius, radius);
00687 VaccSurf_dtor2(asurf);
00688 thee->surf[i] = Vacc_atomSurf(thee, atom, thee->refSphere, radius);
00689 asurf = thee->surf[i];
00690 }
00691 area += (asurf->area);
00692 }
00693
00694 #if defined(DEBUG_MAC_OSX_OCL) || defined(DEBUG_MAC_OSX_STANDARD)
00695 mets_(&mbeg, "Vacc_SASA - Parallel");
00696 #endif
00697
00698 return area;
00699
00700 }
00701
00702 VPUBLIC double Vacc_totalSASA(Vacc *thee, double radius) {
00703
00704 return Vacc_SASA(thee, radius);
00705
00706 }
00707
00708 VPUBLIC double Vacc_atomSASA(Vacc *thee, double radius, Vatom *atom) {
00709
00710 VaccSurf *asurf;
00711 int id;
00712
00713 if (thee->surf == VNULL) Vacc_SASA(thee, radius);
00714
00715 id = Vatom_getAtomID(atom);
00716 asurf = thee->surf[id];
00717
00718
00719 if (asurf->probe_radius != radius) {
00720 Vnm_print(2, "Vacc_SASA: Warning -- probe radius changed from %g to %g!\n",
00721 asurf->probe_radius, radius);
00722 VaccSurf_dtor2(asurf);
00723 thee->surf[id] = Vacc_atomSurf(thee, atom, thee->refSphere, radius);
00724 asurf = thee->surf[id];
00725 }
00726
00727 return asurf->area;
00728
00729 }
00730
00731 VPUBLIC VaccSurf* VaccSurf_ctor(Vmem *mem, double probe_radius, int nsphere) {
00732 VaccSurf *thee;
00733
00734
00735 if (nsphere >= MAX_SPHERE_PTS) {
00736 Vnm_print(2, "VaccSurf_ctor: Error! The requested number of grid points (%d) exceeds the maximum (%d)!\n", nsphere, MAX_SPHERE_PTS);
00737 Vnm_print(2, "VaccSurf_ctor: Please check the variable MAX_SPHERE_PTS to reset.\n");
00738 VASSERT(0);
00739 }
00740 thee = (VaccSurf*)calloc(1,sizeof(Vacc));
00741 VASSERT( VaccSurf_ctor2(thee, mem, probe_radius, nsphere) );
00742
00743 return thee;
00744 }
00745
00746 VPUBLIC int VaccSurf_ctor2(VaccSurf *thee, Vmem *mem, double probe_radius,
00747 int nsphere) {
00748
00749 if (thee == VNULL) return 0;
00750
00751 thee->mem = mem;
00752 thee->npts = nsphere;
00753 thee->probe_radius = probe_radius;
00754 thee->area = 0.0;
00755
00756 if (thee->npts > 0) {
00757
00758
00759
00760
00761
00762
00763 thee->xpts = (double*)calloc(thee->npts,sizeof(double));
00764 thee->ypts = (double*)calloc(thee->npts,sizeof(double));
00765 thee->zpts = (double*)calloc(thee->npts,sizeof(double));
00766 thee->bpts = (char*)calloc(thee->npts,sizeof(char));
00767 } else {
00768 thee->xpts = VNULL;
00769 thee->ypts = VNULL;
00770 thee->zpts = VNULL;
00771 thee->bpts = VNULL;
00772 }
00773
00774 return 1;
00775 }
00776
00777 VPUBLIC void VaccSurf_dtor(VaccSurf **thee) {
00778
00779 Vmem *mem;
00780
00781 if ((*thee) != VNULL) {
00782 mem = (*thee)->mem;
00783 VaccSurf_dtor2(*thee);
00784
00785 free(*thee);
00786 (*thee) = VNULL;
00787 }
00788
00789 }
00790
00791 VPUBLIC void VaccSurf_dtor2(VaccSurf *thee) {
00792
00793 if (thee->npts > 0) {
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 free(thee->xpts);
00805 free(thee->ypts);
00806 free(thee->zpts);
00807 free(thee->bpts);
00808 }
00809 }
00810
00811 VPUBLIC VaccSurf* Vacc_atomSurf(Vacc *thee, Vatom *atom,
00812 VaccSurf *ref, double prad) {
00813
00814 VaccSurf *surf;
00815 int i, j, npts, atomID;
00816 double arad, rad, pos[3], *apos;
00817 char bpts[MAX_SPHERE_PTS];
00818
00819
00820 arad = Vatom_getRadius(atom);
00821 apos = Vatom_getPosition(atom);
00822 atomID = Vatom_getAtomID(atom);
00823
00824 if (arad < VSMALL) {
00825 return VaccSurf_ctor(thee->mem, prad, 0);
00826 }
00827
00828 rad = arad + prad;
00829
00830
00831 npts = 0;
00832 for (i=0; i<ref->npts; i++) {
00833
00834 pos[0] = rad*(ref->xpts[i]) + apos[0];
00835 pos[1] = rad*(ref->ypts[i]) + apos[1];
00836 pos[2] = rad*(ref->zpts[i]) + apos[2];
00837 if (ivdwAccExclus(thee, pos, prad, atomID)) {
00838 npts++;
00839 bpts[i] = 1;
00840 } else {
00841 bpts[i] = 0;
00842 }
00843 }
00844
00845
00846 surf = VaccSurf_ctor(thee->mem, prad, npts);
00847
00848
00849 j = 0;
00850 for (i=0; i<ref->npts; i++) {
00851 if (bpts[i]) {
00852 surf->bpts[j] = 1;
00853 surf->xpts[j] = rad*(ref->xpts[i]) + apos[0];
00854 surf->ypts[j] = rad*(ref->ypts[i]) + apos[1];
00855 surf->zpts[j] = rad*(ref->zpts[i]) + apos[2];
00856 j++;
00857 }
00858 }
00859
00860
00861 surf->area = 4.0*VPI*rad*rad*((double)(surf->npts))/((double)(ref->npts));
00862
00863 return surf;
00864
00865 }
00866
00867 VPUBLIC VaccSurf* VaccSurf_refSphere(Vmem *mem, int npts) {
00868
00869 VaccSurf *surf;
00870 int nactual, i, itheta, ntheta, iphi, nphimax, nphi;
00871 double frac;
00872 double sintheta, costheta, theta, dtheta;
00873 double sinphi, cosphi, phi, dphi;
00874
00875
00876 frac = ((double)(npts))/4.0;
00877 ntheta = VRINT(VSQRT(Vunit_pi*frac));
00878 dtheta = Vunit_pi/((double)(ntheta));
00879 nphimax = 2*ntheta;
00880
00881
00882 nactual = 0;
00883 for (itheta=0; itheta<ntheta; itheta++) {
00884 theta = dtheta*((double)(itheta));
00885 sintheta = VSIN(theta);
00886 costheta = VCOS(theta);
00887 nphi = VRINT(sintheta*nphimax);
00888 nactual += nphi;
00889 }
00890
00891
00892 surf = VaccSurf_ctor(mem, 1.0, nactual);
00893
00894
00895 for (i=0; i<nactual; i++) surf->bpts[i] = 1;
00896
00897
00898 nactual = 0;
00899 for (itheta=0; itheta<ntheta; itheta++) {
00900 theta = dtheta*((double)(itheta));
00901 sintheta = VSIN(theta);
00902 costheta = VCOS(theta);
00903 nphi = VRINT(sintheta*nphimax);
00904 if (nphi != 0) {
00905 dphi = 2*Vunit_pi/((double)(nphi));
00906 for (iphi=0; iphi<nphi; iphi++) {
00907 phi = dphi*((double)(iphi));
00908 sinphi = VSIN(phi);
00909 cosphi = VCOS(phi);
00910 surf->xpts[nactual] = cosphi * sintheta;
00911 surf->ypts[nactual] = sinphi * sintheta;
00912 surf->zpts[nactual] = costheta;
00913 nactual++;
00914 }
00915 }
00916 }
00917
00918 surf->npts = nactual;
00919
00920 return surf;
00921 }
00922
00923 VPUBLIC VaccSurf* Vacc_atomSASPoints(Vacc *thee, double radius,
00924 Vatom *atom) {
00925
00926 VaccSurf *asurf = VNULL;
00927 int id;
00928
00929 if (thee->surf == VNULL) Vacc_SASA(thee, radius);
00930 id = Vatom_getAtomID(atom);
00931
00932 asurf = thee->surf[id];
00933
00934
00935 if (asurf->probe_radius != radius) {
00936 Vnm_print(2, "Vacc_SASA: Warning -- probe radius changed from %g to %g!\n",
00937 asurf->probe_radius, radius);
00938 VaccSurf_dtor2(asurf);
00939 thee->surf[id] = Vacc_atomSurf(thee, atom, thee->refSphere, radius);
00940 asurf = thee->surf[id];
00941 }
00942
00943 return asurf;
00944
00945 }
00946
00947 VPUBLIC void Vacc_splineAccGradAtomNorm4(Vacc *thee, double center[VAPBS_DIM],
00948 double win, double infrad, Vatom *atom, double *grad) {
00949
00950 int i;
00951 double dist, *apos, arad, sm, sm2, sm3, sm4, sm5, sm6, sm7;
00952 double e, e2, e3, e4, e5, e6, e7;
00953 double b, b2, b3, b4, b5, b6, b7;
00954 double c0, c1, c2, c3, c4, c5, c6, c7;
00955 double denom, mygrad;
00956 double mychi = 1.0;
00957
00958 VASSERT(thee != NULL);
00959
00960
00961 for (i=0; i<VAPBS_DIM; i++) grad[i] = 0.0;
00962
00963
00964
00965 apos = Vatom_getPosition(atom);
00966
00967 if (Vatom_getRadius(atom) > 0.0) {
00968
00969 arad = Vatom_getRadius(atom);
00970 arad = arad + infrad;
00971 b = arad - win;
00972 e = arad + win;
00973
00974 e2 = e * e;
00975 e3 = e2 * e;
00976 e4 = e3 * e;
00977 e5 = e4 * e;
00978 e6 = e5 * e;
00979 e7 = e6 * e;
00980 b2 = b * b;
00981 b3 = b2 * b;
00982 b4 = b3 * b;
00983 b5 = b4 * b;
00984 b6 = b5 * b;
00985 b7 = b6 * b;
00986
00987 denom = e7 - 7.0*b*e6 + 21.0*b2*e5 - 35.0*e4*b3
00988 + 35.0*e3*b4 - 21.0*b5*e2 + 7.0*e*b6 - b7;
00989 c0 = b4*(35.0*e3 - 21.0*b*e2 + 7*e*b2 - b3)/denom;
00990 c1 = -140.0*b3*e3/denom;
00991 c2 = 210.0*e2*b2*(e + b)/denom;
00992 c3 = -140.0*e*b*(e2 + 3.0*b*e + b2)/denom;
00993 c4 = 35.0*(e3 + 9.0*b*e2 + + 9.0*e*b2 + b3)/denom;
00994 c5 = -84.0*(e2 + 3.0*b*e + b2)/denom;
00995 c6 = 70.0*(e + b)/denom;
00996 c7 = -20.0/denom;
00997
00998 dist = VSQRT(VSQR(apos[0]-center[0]) + VSQR(apos[1]-center[1])
00999 + VSQR(apos[2]-center[2]));
01000
01001
01002
01003 if (dist < (arad - win)) return;
01004
01005
01006 else if (dist > (arad + win)) return;
01007
01008
01009
01010 else if ((VABS(dist - (arad - win)) < VSMALL) ||
01011 (VABS(dist - (arad + win)) < VSMALL)) return;
01012
01013 else {
01014 sm = dist;
01015 sm2 = sm * sm;
01016 sm3 = sm2 * sm;
01017 sm4 = sm3 * sm;
01018 sm5 = sm4 * sm;
01019 sm6 = sm5 * sm;
01020 sm7 = sm6 * sm;
01021 mychi = c0 + c1*sm + c2*sm2 + c3*sm3
01022 + c4*sm4 + c5*sm5 + c6*sm6 + c7*sm7;
01023 mygrad = c1 + 2.0*c2*sm + 3.0*c3*sm2 + 4.0*c4*sm3
01024 + 5.0*c5*sm4 + 6.0*c6*sm5 + 7.0*c7*sm6;
01025 if (mychi <= 0.0) {
01026
01027 return;
01028 } else if (mychi > 1.0) {
01029
01030 mychi = 1.0;
01031 }
01032 }
01033
01034 VASSERT(mychi > 0.0);
01035 for (i=0; i<VAPBS_DIM; i++)
01036 grad[i] = -(mygrad/mychi)*((center[i] - apos[i])/dist);
01037 }
01038 }
01039
01040 VPUBLIC void Vacc_splineAccGradAtomNorm3(Vacc *thee, double center[VAPBS_DIM],
01041 double win, double infrad, Vatom *atom, double *grad) {
01042
01043 int i;
01044 double dist, *apos, arad, sm, sm2, sm3, sm4, sm5;
01045 double e, e2, e3, e4, e5;
01046 double b, b2, b3, b4, b5;
01047 double c0, c1, c2, c3, c4, c5;
01048 double denom, mygrad;
01049 double mychi = 1.0;
01050
01051 VASSERT(thee != NULL);
01052
01053
01054 for (i=0; i<VAPBS_DIM; i++) grad[i] = 0.0;
01055
01056
01057
01058 apos = Vatom_getPosition(atom);
01059
01060 if (Vatom_getRadius(atom) > 0.0) {
01061
01062 arad = Vatom_getRadius(atom);
01063 arad = arad + infrad;
01064 b = arad - win;
01065 e = arad + win;
01066
01067 e2 = e * e;
01068 e3 = e2 * e;
01069 e4 = e3 * e;
01070 e5 = e4 * e;
01071 b2 = b * b;
01072 b3 = b2 * b;
01073 b4 = b3 * b;
01074 b5 = b4 * b;
01075
01076 denom = pow((e - b), 5.0);
01077 c0 = -10.0*e2*b3 + 5.0*e*b4 - b5;
01078 c1 = 30.0*e2*b2;
01079 c2 = -30.0*(e2*b + e*b2);
01080 c3 = 10.0*(e2 + 4.0*e*b + b2);
01081 c4 = -15.0*(e + b);
01082 c5 = 6;
01083 c0 = c0/denom;
01084 c1 = c1/denom;
01085 c2 = c2/denom;
01086 c3 = c3/denom;
01087 c4 = c4/denom;
01088 c5 = c5/denom;
01089
01090 dist = VSQRT(VSQR(apos[0]-center[0]) + VSQR(apos[1]-center[1])
01091 + VSQR(apos[2]-center[2]));
01092
01093
01094
01095 if (dist < (arad - win)) return;
01096
01097
01098 else if (dist > (arad + win)) return;
01099
01100
01101
01102 else if ((VABS(dist - (arad - win)) < VSMALL) ||
01103 (VABS(dist - (arad + win)) < VSMALL)) return;
01104
01105 else {
01106 sm = dist;
01107 sm2 = sm * sm;
01108 sm3 = sm2 * sm;
01109 sm4 = sm3 * sm;
01110 sm5 = sm4 * sm;
01111 mychi = c0 + c1*sm + c2*sm2 + c3*sm3
01112 + c4*sm4 + c5*sm5;
01113 mygrad = c1 + 2.0*c2*sm + 3.0*c3*sm2 + 4.0*c4*sm3
01114 + 5.0*c5*sm4;
01115 if (mychi <= 0.0) {
01116
01117 return;
01118 } else if (mychi > 1.0) {
01119
01120 mychi = 1.0;
01121 }
01122 }
01123
01124 VASSERT(mychi > 0.0);
01125 for (i=0; i<VAPBS_DIM; i++)
01126 grad[i] = -(mygrad/mychi)*((center[i] - apos[i])/dist);
01127 }
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 ref = thee->refSphere;
01154 iatom = Vatom_getAtomID(atom);
01155
01156 dSA[0] = 0.0;
01157 dSA[1] = 0.0;
01158 dSA[2] = 0.0;
01159
01160 tPos = Vatom_getPosition(atom);
01161 tRad = Vatom_getRadius(atom);
01162
01163 if(tRad == 0.0) return;
01164
01165 area = 4.0*VPI*(tRad+srad)*(tRad+srad)/((double)(ref->npts));
01166 for (ipt=0; ipt<ref->npts; ipt++) {
01167 vec[0] = (tRad+srad)*ref->xpts[ipt] + tPos[0];
01168 vec[1] = (tRad+srad)*ref->ypts[ipt] + tPos[1];
01169 vec[2] = (tRad+srad)*ref->zpts[ipt] + tPos[2];
01170 if (ivdwAccExclus(thee, vec, srad, iatom)) {
01171 dx = dx+vec[0]-tPos[0];
01172 dy = dy+vec[1]-tPos[1];
01173 dz = dz+vec[2]-tPos[2];
01174 }
01175 }
01176
01177 if ((tRad+srad) != 0){
01178 dSA[0] = dx*area/(tRad+srad);
01179 dSA[1] = dy*area/(tRad+srad);
01180 dSA[2] = dz*area/(tRad+srad);
01181 }
01182
01183 }
01184
01185
01186
01187
01188
01189 VPRIVATE double Vacc_SASAPos(Vacc *thee, double radius) {
01190
01191 int i, natom;
01192 double area;
01193 Vatom *atom;
01194 VaccSurf *asurf;
01195
01196 natom = Valist_getNumberAtoms(thee->alist);
01197
01198
01199 area = 0.0;
01200 for (i=0; i<natom; i++) {
01201 atom = Valist_getAtom(thee->alist, i);
01202 asurf = thee->surf[i];
01203
01204 VaccSurf_dtor2(asurf);
01205 thee->surf[i] = Vacc_atomSurf(thee, atom, thee->refSphere, radius);
01206 asurf = thee->surf[i];
01207 area += (asurf->area);
01208 }
01209
01210 return area;
01211
01212 }
01213
01214 VPRIVATE double Vacc_atomSASAPos(Vacc *thee, double radius, Vatom *atom,int mode) {
01215
01216 VaccSurf *asurf;
01217 int id;
01218 static int warned = 0;
01219
01220 if ((thee->surf == VNULL) || (mode == 1)){
01221 if(!warned){
01222 printf("WARNING: Recalculating entire surface!!!!\n");
01223 warned = 1;
01224 }
01225 Vacc_SASAPos(thee, radius);
01226 }
01227
01228 id = Vatom_getAtomID(atom);
01229 asurf = thee->surf[id];
01230
01231 VaccSurf_dtor(&asurf);
01232 thee->surf[id] = Vacc_atomSurf(thee, atom, thee->refSphere, radius);
01233 asurf = thee->surf[id];
01234
01235 return asurf->area;
01236
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 ref = thee->refSphere;
01262 temp_Pos = Vatom_getPosition(atom);
01263 tRad = Vatom_getRadius(atom);
01264 iatom = Vatom_getAtomID(atom);
01265
01266 dSA[0] = 0.0;
01267 dSA[1] = 0.0;
01268 dSA[2] = 0.0;
01269
01270 tPos[0] = temp_Pos[0];
01271 tPos[1] = temp_Pos[1];
01272 tPos[2] = temp_Pos[2];
01273
01274
01275 temp_Pos[0] -= dpos;
01276 axb1 = Vacc_atomSASAPos(thee, srad, atom,0);
01277 temp_Pos[0] = tPos[0];
01278
01279 temp_Pos[0] += dpos;
01280 axt1 = Vacc_atomSASAPos(thee, srad, atom,0);
01281 temp_Pos[0] = tPos[0];
01282
01283
01284 temp_Pos[1] -= dpos;
01285 ayb1 = Vacc_atomSASAPos(thee, srad, atom,0);
01286 temp_Pos[1] = tPos[1];
01287
01288 temp_Pos[1] += dpos;
01289 ayt1 = Vacc_atomSASAPos(thee, srad, atom,0);
01290 temp_Pos[1] = tPos[1];
01291
01292
01293 temp_Pos[2] -= dpos;
01294 azb1 = Vacc_atomSASAPos(thee, srad, atom,0);
01295 temp_Pos[2] = tPos[2];
01296
01297 temp_Pos[2] += dpos;
01298 azt1 = Vacc_atomSASAPos(thee, srad, atom,0);
01299 temp_Pos[2] = tPos[2];
01300
01301
01302 Vacc_atomSASAPos(thee, srad, atom,0);
01303
01304
01305 dSA[0] = (axt1-axb1)/(2.0 * dpos);
01306 dSA[1] = (ayt1-ayb1)/(2.0 * dpos);
01307 dSA[2] = (azt1-azb1)/(2.0 * dpos);
01308 }
01309
01310
01311
01312
01313
01314 VPUBLIC void Vacc_totalAtomdSASA(Vacc *thee, double dpos, double srad, Vatom *atom, double *dSA) {
01315
01316 int iatom;
01317 double *temp_Pos, tRad;
01318 double tPos[3];
01319 double axb1,axt1,ayb1,ayt1,azb1,azt1;
01320 VaccSurf *ref;
01321
01322
01323 ref = thee->refSphere;
01324 temp_Pos = Vatom_getPosition(atom);
01325 tRad = Vatom_getRadius(atom);
01326 iatom = Vatom_getAtomID(atom);
01327
01328 dSA[0] = 0.0;
01329 dSA[1] = 0.0;
01330 dSA[2] = 0.0;
01331
01332 tPos[0] = temp_Pos[0];
01333 tPos[1] = temp_Pos[1];
01334 tPos[2] = temp_Pos[2];
01335
01336
01337 temp_Pos[0] -= dpos;
01338 axb1 = Vacc_atomSASAPos(thee, srad, atom, 1);
01339 temp_Pos[0] = tPos[0];
01340
01341 temp_Pos[0] += dpos;
01342 axt1 = Vacc_atomSASAPos(thee, srad, atom, 1);
01343 temp_Pos[0] = tPos[0];
01344
01345
01346 temp_Pos[1] -= dpos;
01347 ayb1 = Vacc_atomSASAPos(thee, srad, atom, 1);
01348 temp_Pos[1] = tPos[1];
01349
01350 temp_Pos[1] += dpos;
01351 ayt1 = Vacc_atomSASAPos(thee, srad, atom, 1);
01352 temp_Pos[1] = tPos[1];
01353
01354
01355 temp_Pos[2] -= dpos;
01356 azb1 = Vacc_atomSASAPos(thee, srad, atom, 1);
01357 temp_Pos[2] = tPos[2];
01358
01359 temp_Pos[2] += dpos;
01360 azt1 = Vacc_atomSASAPos(thee, srad, atom, 1);
01361 temp_Pos[2] = tPos[2];
01362
01363
01364 dSA[0] = (axt1-axb1)/(2.0 * dpos);
01365 dSA[1] = (ayt1-ayb1)/(2.0 * dpos);
01366 dSA[2] = (azt1-azb1)/(2.0 * dpos);
01367 }
01368
01369
01370
01371
01372
01373 VPUBLIC void Vacc_totalAtomdSAV(Vacc *thee, double dpos, double srad, Vatom *atom, double *dSA, Vclist *clist) {
01374
01375 int iatom;
01376 double *temp_Pos, tRad;
01377 double tPos[3];
01378 double axb1,axt1,ayb1,ayt1,azb1,azt1;
01379 VaccSurf *ref;
01380
01381
01382 ref = thee->refSphere;
01383 temp_Pos = Vatom_getPosition(atom);
01384 tRad = Vatom_getRadius(atom);
01385 iatom = Vatom_getAtomID(atom);
01386
01387 dSA[0] = 0.0;
01388 dSA[1] = 0.0;
01389 dSA[2] = 0.0;
01390
01391 tPos[0] = temp_Pos[0];
01392 tPos[1] = temp_Pos[1];
01393 tPos[2] = temp_Pos[2];
01394
01395
01396 temp_Pos[0] -= dpos;
01397 axb1 = Vacc_totalSAV(thee,clist, VNULL, srad);
01398 temp_Pos[0] = tPos[0];
01399
01400 temp_Pos[0] += dpos;
01401 axt1 = Vacc_totalSAV(thee,clist, VNULL, srad);
01402 temp_Pos[0] = tPos[0];
01403
01404
01405 temp_Pos[1] -= dpos;
01406 ayb1 = Vacc_totalSAV(thee,clist, VNULL, srad);
01407 temp_Pos[1] = tPos[1];
01408
01409 temp_Pos[1] += dpos;
01410 ayt1 = Vacc_totalSAV(thee,clist, VNULL, srad);
01411 temp_Pos[1] = tPos[1];
01412
01413
01414 temp_Pos[2] -= dpos;
01415 azb1 = Vacc_totalSAV(thee,clist, VNULL, srad);
01416 temp_Pos[2] = tPos[2];
01417
01418 temp_Pos[2] += dpos;
01419 azt1 = Vacc_totalSAV(thee,clist, VNULL, srad);
01420 temp_Pos[2] = tPos[2];
01421
01422
01423 dSA[0] = (axt1-axb1)/(2.0 * dpos);
01424 dSA[1] = (ayt1-ayb1)/(2.0 * dpos);
01425 dSA[2] = (azt1-azb1)/(2.0 * dpos);
01426 }
01427
01428 VPUBLIC double Vacc_totalSAV(Vacc *thee, Vclist *clist, APOLparm *apolparm, double radius) {
01429
01430 int i;
01431 int npts[3];
01432
01433 double spacs[3], vec[3];
01434 double w, wx, wy, wz, len, fn, x, y, z, vol;
01435 double vol_density,sav;
01436 double *lower_corner, *upper_corner;
01437
01438 sav = 0.0;
01439 vol = 1.0;
01440 vol_density = 2.0;
01441
01442 lower_corner = clist->lower_corner;
01443 upper_corner = clist->upper_corner;
01444
01445 for (i=0; i<3; i++) {
01446 len = upper_corner[i] - lower_corner[i];
01447 vol *= len;
01448 fn = len*vol_density + 1;
01449 npts[i] = (int)ceil(fn);
01450 spacs[i] = len/((double)(npts[i])-1.0);
01451 if (apolparm != VNULL) {
01452 if (apolparm->setgrid) {
01453 if (apolparm->grid[i] > spacs[i]) {
01454 Vnm_print(2, "Vacc_totalSAV: Warning, your GRID value (%g) is larger than the recommended value (%g)!\n",
01455 apolparm->grid[i], spacs[i]);
01456 }
01457 spacs[i] = apolparm->grid[i];
01458
01459 }
01460 }
01461 }
01462
01463 for (x=lower_corner[0]; x<=upper_corner[0]; x=x+spacs[0]) {
01464 if ( VABS(x - lower_corner[0]) < VSMALL) {
01465 wx = 0.5;
01466 } else if ( VABS(x - upper_corner[0]) < VSMALL) {
01467 wx = 0.5;
01468 } else {
01469 wx = 1.0;
01470 }
01471 vec[0] = x;
01472 for (y=lower_corner[1]; y<=upper_corner[1]; y=y+spacs[1]) {
01473 if ( VABS(y - lower_corner[1]) < VSMALL) {
01474 wy = 0.5;
01475 } else if ( VABS(y - upper_corner[1]) < VSMALL) {
01476 wy = 0.5;
01477 } else {
01478 wy = 1.0;
01479 }
01480 vec[1] = y;
01481 for (z=lower_corner[2]; z<=upper_corner[2]; z=z+spacs[2]) {
01482 if ( VABS(z - lower_corner[2]) < VSMALL) {
01483 wz = 0.5;
01484 } else if ( VABS(z - upper_corner[2]) < VSMALL) {
01485 wz = 0.5;
01486 } else {
01487 wz = 1.0;
01488 }
01489 vec[2] = z;
01490
01491 w = wx*wy*wz;
01492
01493 sav += (w*(1.0-Vacc_ivdwAcc(thee, vec, radius)));
01494
01495 }
01496 }
01497 }
01498
01499 w = spacs[0]*spacs[1]*spacs[2];
01500 sav *= w;
01501
01502 return sav;
01503 }
01504
01505 int Vacc_wcaEnergyAtom(Vacc *thee, APOLparm *apolparm, Valist *alist,
01506 Vclist *clist, int iatom, double *value) {
01507
01508 int i;
01509 int npts[3];
01510 int pad = 14;
01511
01512 int xmin, ymin, zmin;
01513 int xmax, ymax, zmax;
01514
01515 double sigma6, sigma12;
01516
01517 double spacs[3], vec[3];
01518 double w, wx, wy, wz, len, fn, x, y, z, vol;
01519 double x2,y2,z2,r;
01520 double vol_density, energy, rho, srad;
01521 double psig, epsilon, watepsilon, sigma, watsigma, eni, chi;
01522
01523 double *pos;
01524 double *lower_corner, *upper_corner;
01525
01526 Vatom *atom = VNULL;
01527 VASSERT(apolparm != VNULL);
01528
01529 energy = 0.0;
01530 vol = 1.0;
01531 vol_density = 2.0;
01532
01533 lower_corner = clist->lower_corner;
01534 upper_corner = clist->upper_corner;
01535
01536 atom = Valist_getAtom(alist, iatom);
01537 pos = Vatom_getPosition(atom);
01538
01539
01540
01541
01542
01543
01544
01545
01546 srad = apolparm->srad;
01547 rho = apolparm->bconc;
01548 watsigma = apolparm->watsigma;
01549 watepsilon = apolparm->watepsilon;
01550 psig = atom->radius;
01551 epsilon = atom->epsilon;
01552 sigma = psig + watsigma;
01553 epsilon = VSQRT((epsilon * watepsilon));
01554
01555
01556 sigma6 = VPOW(sigma,6);
01557 sigma12 = VPOW(sigma,12);
01558
01559
01560 xmin = pos[0] - pad;
01561 xmax = pos[0] + pad;
01562 ymin = pos[1] - pad;
01563 ymax = pos[1] + pad;
01564 zmin = pos[2] - pad;
01565 zmax = pos[2] + pad;
01566
01567 for (i=0; i<3; i++) {
01568 len = (upper_corner[i] + pad) - (lower_corner[i] - pad);
01569 vol *= len;
01570 fn = len*vol_density + 1;
01571 npts[i] = (int)ceil(fn);
01572 spacs[i] = 0.5;
01573 if (apolparm->setgrid) {
01574 if (apolparm->grid[i] > spacs[i]) {
01575 Vnm_print(2, "Vacc_totalSAV: Warning, your GRID value (%g) is larger than the recommended value (%g)!\n",
01576 apolparm->grid[i], spacs[i]);
01577 }
01578 spacs[i] = apolparm->grid[i];
01579 }
01580 }
01581
01582 for (x=xmin; x<=xmax; x=x+spacs[0]) {
01583 if ( VABS(x - xmin) < VSMALL) {
01584 wx = 0.5;
01585 } else if ( VABS(x - xmax) < VSMALL) {
01586 wx = 0.5;
01587 } else {
01588 wx = 1.0;
01589 }
01590 vec[0] = x;
01591 for (y=ymin; y<=ymax; y=y+spacs[1]) {
01592 if ( VABS(y - ymin) < VSMALL) {
01593 wy = 0.5;
01594 } else if ( VABS(y - ymax) < VSMALL) {
01595 wy = 0.5;
01596 } else {
01597 wy = 1.0;
01598 }
01599 vec[1] = y;
01600 for (z=zmin; z<=zmax; z=z+spacs[2]) {
01601 if ( VABS(z - zmin) < VSMALL) {
01602 wz = 0.5;
01603 } else if ( VABS(z - zmax) < VSMALL) {
01604 wz = 0.5;
01605 } else {
01606 wz = 1.0;
01607 }
01608 vec[2] = z;
01609
01610 w = wx*wy*wz;
01611
01612 chi = Vacc_ivdwAcc(thee, vec, srad);
01613
01614 if (VABS(chi) > VSMALL) {
01615
01616 x2 = VSQR(vec[0]-pos[0]);
01617 y2 = VSQR(vec[1]-pos[1]);
01618 z2 = VSQR(vec[2]-pos[2]);
01619 r = VSQRT(x2+y2+z2);
01620
01621 if (r <= 14 && r >= sigma) {
01622 eni = chi*rho*epsilon*(-2.0*sigma6/VPOW(r,6)+sigma12/VPOW(r,12));
01623 }else if (r <= 14){
01624 eni = -1.0*epsilon*chi*rho;
01625 }else{
01626 eni = 0.0;
01627 }
01628 }else{
01629 eni = 0.0;
01630 }
01631
01632 energy += eni*w;
01633
01634 }
01635 }
01636 }
01637
01638 w = spacs[0]*spacs[1]*spacs[2];
01639 energy *= w;
01640
01641 *value = energy;
01642
01643 return VRC_SUCCESS;
01644 }
01645
01646 VPUBLIC int Vacc_wcaEnergy(Vacc *acc, APOLparm *apolparm, Valist *alist,
01647 Vclist *clist){
01648
01649 int iatom;
01650 int rc = 0;
01651
01652 double energy = 0.0;
01653 double tenergy = 0.0;
01654 double rho = apolparm->bconc;
01655
01656
01657
01658 if(apolparm->setwat == 0){
01659 Vnm_print(2,"Vacc_wcaEnergy: Error. No value was set for watsigma and watepsilon.\n");
01660 return VRC_FAILURE;
01661 }
01662
01663 if (VABS(rho) < VSMALL) {
01664 apolparm->wcaEnergy = tenergy;
01665 return 1;
01666 }
01667
01668 for (iatom=0; iatom<Valist_getNumberAtoms(alist); iatom++){
01669 rc = Vacc_wcaEnergyAtom(acc, apolparm, alist, clist, iatom, &energy);
01670 if(rc == 0) return 0;
01671
01672 tenergy += energy;
01673 }
01674
01675 apolparm->wcaEnergy = tenergy;
01676
01677 return VRC_SUCCESS;
01678
01679 }
01680
01681 VPUBLIC int Vacc_wcaForceAtom(Vacc *thee, APOLparm *apolparm, Vclist *clist,
01682 Vatom *atom, double *force){
01683 int i,si;
01684 int npts[3];
01685 int pad = 14;
01686
01687 int xmin, ymin, zmin;
01688 int xmax, ymax, zmax;
01689
01690 double sigma6, sigma12;
01691
01692 double spacs[3], vec[3], fpt[3];
01693 double w, wx, wy, wz, len, fn, x, y, z, vol;
01694 double x2,y2,z2,r;
01695 double vol_density, fo;
01696 double rho;
01697 double srad, psig, epsilon, watepsilon, sigma, watsigma, chi;
01698
01699 double *pos;
01700 double *lower_corner, *upper_corner;
01701
01702 VASSERT(apolparm != VNULL);
01703
01704
01705
01706 if(apolparm->setwat == 0){
01707 Vnm_print(2,"Vacc_wcaEnergy: Error. No value was set for watsigma and watepsilon.\n");
01708 return VRC_FAILURE;
01709 }
01710
01711 vol = 1.0;
01712 vol_density = 2.0;
01713
01714 lower_corner = clist->lower_corner;
01715 upper_corner = clist->upper_corner;
01716
01717 pos = Vatom_getPosition(atom);
01718
01719
01720
01721
01722
01723
01724
01725 srad = apolparm->srad;
01726 rho = apolparm->bconc;
01727 watsigma = apolparm->watsigma;
01728 watepsilon = apolparm->watepsilon;
01729
01730 psig = atom->radius;
01731 epsilon = atom->epsilon;
01732 sigma = psig + watsigma;
01733 epsilon = VSQRT((epsilon * watepsilon));
01734
01735
01736 sigma6 = VPOW(sigma,6);
01737 sigma12 = VPOW(sigma,12);
01738
01739
01740 for (i=0; i<3; i++) {
01741 len = (upper_corner[i] + pad) - (lower_corner[i] - pad);
01742 vol *= len;
01743 fn = len*vol_density + 1;
01744 npts[i] = (int)ceil(fn);
01745 spacs[i] = 0.5;
01746 force[i] = 0.0;
01747 if (apolparm->setgrid) {
01748 if (apolparm->grid[i] > spacs[i]) {
01749 Vnm_print(2, "Vacc_totalSAV: Warning, your GRID value (%g) is larger than the recommended value (%g)!\n",
01750 apolparm->grid[i], spacs[i]);
01751 }
01752 spacs[i] = apolparm->grid[i];
01753 }
01754 }
01755
01756 xmin = pos[0] - pad;
01757 xmax = pos[0] + pad;
01758 ymin = pos[1] - pad;
01759 ymax = pos[1] + pad;
01760 zmin = pos[2] - pad;
01761 zmax = pos[2] + pad;
01762
01763 for (x=xmin; x<=xmax; x=x+spacs[0]) {
01764 if ( VABS(x - xmin) < VSMALL) {
01765 wx = 0.5;
01766 } else if ( VABS(x - xmax) < VSMALL) {
01767 wx = 0.5;
01768 } else {
01769 wx = 1.0;
01770 }
01771 vec[0] = x;
01772 for (y=ymin; y<=ymax; y=y+spacs[1]) {
01773 if ( VABS(y - ymin) < VSMALL) {
01774 wy = 0.5;
01775 } else if ( VABS(y - ymax) < VSMALL) {
01776 wy = 0.5;
01777 } else {
01778 wy = 1.0;
01779 }
01780 vec[1] = y;
01781 for (z=zmin; z<=zmax; z=z+spacs[2]) {
01782 if ( VABS(z - zmin) < VSMALL) {
01783 wz = 0.5;
01784 } else if ( VABS(z - zmax) < VSMALL) {
01785 wz = 0.5;
01786 } else {
01787 wz = 1.0;
01788 }
01789 vec[2] = z;
01790
01791 w = wx*wy*wz;
01792
01793 chi = Vacc_ivdwAcc(thee, vec, srad);
01794
01795 if (chi != 0.0) {
01796
01797 x2 = VSQR(vec[0]-pos[0]);
01798 y2 = VSQR(vec[1]-pos[1]);
01799 z2 = VSQR(vec[2]-pos[2]);
01800 r = VSQRT(x2+y2+z2);
01801
01802 if (r <= 14 && r >= sigma){
01803
01804 fo = 12.0*chi*rho*epsilon*(sigma6/VPOW(r,7)-sigma12/VPOW(r,13));
01805
01806 fpt[0] = -1.0*(pos[0]-vec[0])*fo/r;
01807 fpt[1] = -1.0*(pos[1]-vec[1])*fo/r;
01808 fpt[2] = -1.0*(pos[2]-vec[2])*fo/r;
01809
01810 }else {
01811 for (si=0; si < 3; si++) fpt[si] = 0.0;
01812 }
01813 }else {
01814 for (si=0; si < 3; si++) fpt[si] = 0.0;
01815 }
01816
01817 for(i=0;i<3;i++){
01818 force[i] += (w*fpt[i]);
01819 }
01820
01821 }
01822 }
01823 }
01824
01825 w = spacs[0]*spacs[1]*spacs[2];
01826 for(i=0;i<3;i++) force[i] *= w;
01827
01828 return VRC_SUCCESS;
01829 }
01830