--- /dev/null
+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