c
c
c     ###################################################
c     ##  COPYRIGHT (C)  1990  by  Jay William Ponder  ##
c     ##              All Rights Reserved              ##
c     ###################################################
c
c     #################################################################
c     ##                                                             ##
c     ##  subroutine bounds  --  check periodic boundary conditions  ##
c     ##                                                             ##
c     #################################################################
c
c
c     "bounds" finds the center of mass of each molecule, translates
c     any stray molecules back into the periodic box, and saves the
c     offset of each atom relative to the molecular center of mass
c
c
      subroutine bounds
      implicit none
      include 'sizes.i'
      include 'atmtyp.i'
      include 'atoms.i'
      include 'boxes.i'
      include 'centre.i'
      include 'molcul.i'
      integer i,j,k,init,stop
      real*8 weight,x_mid,y_mid,z_mid
      real*8 x_frac,y_frac,z_frac
c
c
c     locate the center of mass of each molecule
c
      do i = 1, nmol
         init = imol(1,i)
         stop = imol(2,i)
         x_mid = 0.0d0
         y_mid = 0.0d0
         z_mid = 0.0d0
         do j = init, stop
            k = kmol(j)
            weight = mass(k)
            x_mid = x_mid + x(k)*weight
            y_mid = y_mid + y(k)*weight
            z_mid = z_mid + z(k)*weight
         end do
         weight = molmass(i)
         x_mid = x_mid / weight
         y_mid = y_mid / weight
         z_mid = z_mid / weight
c
c     store coordinates of atoms relative to center of mass
c
         do j = init, stop
            k = kmol(j)
            xcm(k) = x(k) - x_mid
            ycm(k) = y(k) - y_mid
            zcm(k) = z(k) - z_mid
         end do
c
c     get fractional coordinates of center of mass
c
         if (orthogonal .or. octahedron) then
            z_frac = z_mid
            y_frac = y_mid
            x_frac = x_mid
         else if (monoclinic) then
            z_frac = z_mid / beta_sin
            y_frac = y_mid
            x_frac = x_mid - z_frac*beta_cos
         else if (triclinic) then
            z_frac = z_mid / gamma_term
            y_frac = (y_mid - z_frac*beta_term) / gamma_sin
            x_frac = x_mid - y_frac*gamma_cos - z_frac*beta_cos
         end if
c
c     translate center of mass into the periodic box
c
         dowhile (x_frac .gt. xbox2)
            x_frac = x_frac - xbox
         end do
         dowhile (x_frac .lt. -xbox2)
            x_frac = x_frac + xbox
         end do
         dowhile (y_frac .gt. ybox2)
            y_frac = y_frac - ybox
         end do
         dowhile (y_frac .lt. -ybox2)
            y_frac = y_frac + ybox
         end do
         dowhile (z_frac .gt. zbox2)
            z_frac = z_frac - zbox
         end do
         dowhile (z_frac .lt. -zbox2)
            z_frac = z_frac + zbox
         end do
c
c     truncated octahedron needs to have corners removed
c
         if (octahedron) then
            if (abs(x_frac)+abs(y_frac)+abs(z_frac) .gt. box34) then
               x_frac = x_frac - sign(xbox2,x_frac)
               y_frac = y_frac - sign(ybox2,y_frac)
               z_frac = z_frac - sign(zbox2,z_frac)
            end if
         end if
c
c     convert fractional center of mass back to Cartesian
c
         if (orthogonal .or. octahedron) then
            x_mid = x_frac
            y_mid = y_frac
            z_mid = z_frac
         else if (monoclinic) then
            x_mid = x_frac + z_frac*beta_cos
            y_mid = y_frac
            z_mid = z_frac * beta_sin
         else if (triclinic) then
            x_mid = x_frac + y_frac*gamma_cos + z_frac*beta_cos
            y_mid = y_frac*gamma_sin + z_frac*beta_term
            z_mid = z_frac * gamma_term
         end if
c
c     translate atomic coordinates based upon center of mass
c
         do j = init, stop
            k = kmol(j)
            x(k) = xcm(k) + x_mid
            y(k) = ycm(k) + y_mid
            z(k) = zcm(k) + z_mid
         end do
      end do
      return
      end
