c c c ################################################### c ## COPYRIGHT (C) 1996 by Jay William Ponder ## c ## All Rights Reserved ## c ################################################### c c ################################################################ c ## ## c ## subroutine surfatom -- exposed surface area of an atom ## c ## ## c ################################################################ c c c "surfatom" performs an analytical computation of the surface c area of a specified atom; a simplified version of "surface" c c literature references: c c T. J. Richmond, "Solvent Accessible Surface Area and c Excluded Volume in Proteins", Journal of Molecular Biology, c 178, 63-89 (1984) c c L. Wesson and D. Eisenberg, "Atomic Solvation Parameters c Applied to Molecular Dynamics of Proteins in Solution", c Protein Science, 1, 227-235 (1992) c c variables and parameters: c c ir number of atom for which area is desired c area accessible surface area of the atom c radius radii of each of the individual atoms c c subroutine surfatom (ir,area,radius) implicit real*8 (a-h,o-z) include 'DIMENSIONS' include 'sizes.i' include 'COMMON.GEO' include 'COMMON.IOUNITS' integer nres,nsup,nstart_sup double precision c,dc,dc_old,d_c_work,xloc,xrot,dc_norm common /chain/ c(3,maxres2+2),dc(3,0:maxres2),dc_old(3,0:maxres2), & xloc(3,maxres),xrot(3,maxres),dc_norm(3,0:maxres2), & dc_work(MAXRES6),nres,nres0 integer maxarc parameter (maxarc=300) integer i,j,k,m integer ii,ib,jb integer io,ir integer mi,ni,narc integer key(maxarc) integer intag(maxarc) integer intag1(maxarc) real*8 area,arcsum real*8 arclen,exang real*8 delta,delta2 real*8 eps,rmove real*8 xr,yr,zr real*8 rr,rrsq real*8 rplus,rminus real*8 axx,axy,axz real*8 ayx,ayy real*8 azx,azy,azz real*8 uxj,uyj,uzj real*8 tx,ty,tz real*8 txb,tyb,td real*8 tr2,tr,txr,tyr real*8 tk1,tk2 real*8 thec,the,t,tb real*8 txk,tyk,tzk real*8 t1,ti,tf,tt real*8 txj,tyj,tzj real*8 ccsq,cc,xysq real*8 bsqk,bk,cosine real*8 dsqj,gi,pix2 real*8 therk,dk,gk real*8 risqk,rik real*8 radius(maxatm) real*8 ri(maxarc),risq(maxarc) real*8 ux(maxarc),uy(maxarc),uz(maxarc) real*8 xc(maxarc),yc(maxarc),zc(maxarc) real*8 xc1(maxarc),yc1(maxarc),zc1(maxarc) real*8 dsq(maxarc),bsq(maxarc) real*8 dsq1(maxarc),bsq1(maxarc) real*8 arci(maxarc),arcf(maxarc) real*8 ex(maxarc),lt(maxarc),gr(maxarc) real*8 b(maxarc),b1(maxarc),bg(maxarc) real*8 kent(maxarc),kout(maxarc) real*8 ther(maxarc) logical moved,top logical omit(maxarc) c c c zero out the surface area for the sphere of interest c area = 0.0d0 c write (2,*) "ir",ir," radius",radius(ir) if (radius(ir) .eq. 0.0d0) return c c set the overlap significance and connectivity shift c pix2 = 2.0d0 * pi delta = 1.0d-8 delta2 = delta * delta eps = 1.0d-8 moved = .false. rmove = 1.0d-8 c c store coordinates and radius of the sphere of interest c xr = c(1,ir) yr = c(2,ir) zr = c(3,ir) rr = radius(ir) rrsq = rr * rr c c initialize values of some counters and summations c 10 continue io = 0 jb = 0 ib = 0 arclen = 0.0d0 exang = 0.0d0 c c test each sphere to see if it overlaps the sphere of interest c do i = 1, 2*nres if (i.eq.ir .or. radius(i).eq.0.0d0) goto 30 rplus = rr + radius(i) tx = c(1,i) - xr if (abs(tx) .ge. rplus) goto 30 ty = c(2,i) - yr if (abs(ty) .ge. rplus) goto 30 tz = c(3,i) - zr if (abs(tz) .ge. rplus) goto 30 c c check for sphere overlap by testing distance against radii c xysq = tx*tx + ty*ty if (xysq .lt. delta2) then tx = delta ty = 0.0d0 xysq = delta2 end if ccsq = xysq + tz*tz cc = sqrt(ccsq) if (rplus-cc .le. delta) goto 30 rminus = rr - radius(i) c c check to see if sphere of interest is completely buried c if (cc-abs(rminus) .le. delta) then if (rminus .le. 0.0d0) goto 170 goto 30 end if c c check for too many overlaps with sphere of interest c if (io .ge. maxarc) then write (iout,20) 20 format (/,' SURFATOM -- Increase the Value of MAXARC') stop end if c c get overlap between current sphere and sphere of interest c io = io + 1 xc1(io) = tx yc1(io) = ty zc1(io) = tz dsq1(io) = xysq bsq1(io) = ccsq b1(io) = cc gr(io) = (ccsq+rplus*rminus) / (2.0d0*rr*b1(io)) intag1(io) = i omit(io) = .false. 30 continue end do c c case where no other spheres overlap the sphere of interest c if (io .eq. 0) then area = 4.0d0 * pi * rrsq return end if c c case where only one sphere overlaps the sphere of interest c if (io .eq. 1) then area = pix2 * (1.0d0 + gr(1)) area = mod(area,4.0d0*pi) * rrsq return end if c c case where many spheres intersect the sphere of interest; c sort the intersecting spheres by their degree of overlap c call sort2 (io,gr,key) do i = 1, io k = key(i) intag(i) = intag1(k) xc(i) = xc1(k) yc(i) = yc1(k) zc(i) = zc1(k) dsq(i) = dsq1(k) b(i) = b1(k) bsq(i) = bsq1(k) end do c c get radius of each overlap circle on surface of the sphere c do i = 1, io gi = gr(i) * rr bg(i) = b(i) * gi risq(i) = rrsq - gi*gi ri(i) = sqrt(risq(i)) ther(i) = 0.5d0*pi - asin(min(1.0d0,max(-1.0d0,gr(i)))) end do c c find boundary of inaccessible area on sphere of interest c do k = 1, io-1 if (.not. omit(k)) then txk = xc(k) tyk = yc(k) tzk = zc(k) bk = b(k) therk = ther(k) c c check to see if J circle is intersecting K circle; c get distance between circle centers and sum of radii c do j = k+1, io if (omit(j)) goto 60 cc = (txk*xc(j)+tyk*yc(j)+tzk*zc(j))/(bk*b(j)) cc = acos(min(1.0d0,max(-1.0d0,cc))) td = therk + ther(j) c c check to see if circles enclose separate regions c if (cc .ge. td) goto 60 c c check for circle J completely inside circle K c if (cc+ther(j) .lt. therk) goto 40 c c check for circles that are essentially parallel c if (cc .gt. delta) goto 50 40 continue omit(j) = .true. goto 60 c c check to see if sphere of interest is completely buried c 50 continue if (pix2-cc .le. td) goto 170 60 continue end do end if end do c c find T value of circle intersections c do k = 1, io if (omit(k)) goto 110 omit(k) = .true. narc = 0 top = .false. txk = xc(k) tyk = yc(k) tzk = zc(k) dk = sqrt(dsq(k)) bsqk = bsq(k) bk = b(k) gk = gr(k) * rr risqk = risq(k) rik = ri(k) therk = ther(k) c c rotation matrix elements c t1 = tzk / (bk*dk) axx = txk * t1 axy = tyk * t1 axz = dk / bk ayx = tyk / dk ayy = txk / dk azx = txk / bk azy = tyk / bk azz = tzk / bk do j = 1, io if (.not. omit(j)) then txj = xc(j) tyj = yc(j) tzj = zc(j) c c rotate spheres so K vector colinear with z-axis c uxj = txj*axx + tyj*axy - tzj*axz uyj = tyj*ayy - txj*ayx uzj = txj*azx + tyj*azy + tzj*azz cosine = min(1.0d0,max(-1.0d0,uzj/b(j))) if (acos(cosine) .lt. therk+ther(j)) then dsqj = uxj*uxj + uyj*uyj tb = uzj*gk - bg(j) txb = uxj * tb tyb = uyj * tb td = rik * dsqj tr2 = risqk*dsqj - tb*tb tr2 = max(eps,tr2) tr = sqrt(tr2) txr = uxj * tr tyr = uyj * tr c c get T values of intersection for K circle c tb = (txb+tyr) / td tb = min(1.0d0,max(-1.0d0,tb)) tk1 = acos(tb) if (tyb-txr .lt. 0.0d0) tk1 = pix2 - tk1 tb = (txb-tyr) / td tb = min(1.0d0,max(-1.0d0,tb)) tk2 = acos(tb) if (tyb+txr .lt. 0.0d0) tk2 = pix2 - tk2 thec = (rrsq*uzj-gk*bg(j)) / (rik*ri(j)*b(j)) if (abs(thec) .lt. 1.0d0) then the = -acos(thec) else if (thec .ge. 1.0d0) then the = 0.0d0 else if (thec .le. -1.0d0) then the = -pi end if c c see if "tk1" is entry or exit point; check t=0 point; c "ti" is exit point, "tf" is entry point c cosine = min(1.0d0,max(-1.0d0, & (uzj*gk-uxj*rik)/(b(j)*rr))) if ((acos(cosine)-ther(j))*(tk2-tk1) .le. 0.0d0) then ti = tk2 tf = tk1 else ti = tk2 tf = tk1 end if narc = narc + 1 if (narc .ge. maxarc) then write (iout,70) 70 format (/,' SURFATOM -- Increase the Value', & ' of MAXARC') stop end if if (tf .le. ti) then arcf(narc) = tf arci(narc) = 0.0d0 tf = pix2 lt(narc) = j ex(narc) = the top = .true. narc = narc + 1 end if arcf(narc) = tf arci(narc) = ti lt(narc) = j ex(narc) = the ux(j) = uxj uy(j) = uyj uz(j) = uzj end if end if end do omit(k) = .false. c c special case; K circle without intersections c if (narc .le. 0) goto 90 c c general case; sum up arclength and set connectivity code c call sort2 (narc,arci,key) arcsum = arci(1) mi = key(1) t = arcf(mi) ni = mi if (narc .gt. 1) then do j = 2, narc m = key(j) if (t .lt. arci(j)) then arcsum = arcsum + arci(j) - t exang = exang + ex(ni) jb = jb + 1 if (jb .ge. maxarc) then write (iout,80) 80 format (/,' SURFATOM -- Increase the Value', & ' of MAXARC') stop end if i = lt(ni) kent(jb) = maxarc*i + k i = lt(m) kout(jb) = maxarc*k + i end if tt = arcf(m) if (tt .ge. t) then t = tt ni = m end if end do end if arcsum = arcsum + pix2 - t if (.not. top) then exang = exang + ex(ni) jb = jb + 1 i = lt(ni) kent(jb) = maxarc*i + k i = lt(mi) kout(jb) = maxarc*k + i end if goto 100 90 continue arcsum = pix2 ib = ib + 1 100 continue arclen = arclen + gr(k)*arcsum 110 continue end do if (arclen .eq. 0.0d0) goto 170 if (jb .eq. 0) goto 150 c c find number of independent boundaries and check connectivity c j = 0 do k = 1, jb if (kout(k) .ne. 0) then i = k 120 continue m = kout(i) kout(i) = 0 j = j + 1 do ii = 1, jb if (m .eq. kent(ii)) then if (ii .eq. k) then ib = ib + 1 if (j .eq. jb) goto 150 goto 130 end if i = ii goto 120 end if end do 130 continue end if end do ib = ib + 1 c c attempt to fix connectivity error by moving atom slightly c if (moved) then write (iout,140) ir 140 format (/,' SURFATOM -- Connectivity Error at Atom',i6) else moved = .true. xr = xr + rmove yr = yr + rmove zr = zr + rmove goto 10 end if c c compute the exposed surface area for the sphere of interest c 150 continue area = ib*pix2 + exang + arclen area = mod(area,4.0d0*pi) * rrsq c c attempt to fix negative area by moving atom slightly c if (area .lt. 0.0d0) then if (moved) then write (iout,160) ir 160 format (/,' SURFATOM -- Negative Area at Atom',i6) else moved = .true. xr = xr + rmove yr = yr + rmove zr = zr + rmove goto 10 end if end if 170 continue return end