      SUBROUTINE TARCYL(A1,A2,A,B,DX,CDESCR,IOSHP,MXNAT,NAT,IXYZ,ICOMP)
      IMPLICIT NONE
C Scalar arguments:
      CHARACTER CDESCR*67
      INTEGER MXNAT,NAT
      REAL A,B
C Array arguments:
      INTEGER*2 ICOMP(MXNAT,3),IXYZ(MXNAT,3)
      REAL A1(3),A2(3),DX(3)
C Local scalars:
      INTEGER IOSHP,JX,JY,JZ,
     &    NB,NFAC,NLAY,
     &    NX2,NY1,NY2,NZ1,NZ2
      REAL ASPR,PI,REFF2,Y2M,YCM,Z2,ZCM
C***********************************************************************
C Purpose: to construct cylindrical target from "atoms", with cylinder
C axis along x axis.
C Input:
C        A = cylinder length (in units of lattice spacing d)
C        B = cylinder diameter (in units of lattice spacing d)
C        DX(1-3)=(dx,dy,dz)/d where dx,dy,dz=lattice spacings in x,y,z
C                directions, and d=(dx*dy*dz)**(1/3)=effective lattice
C                spacing
C        IOSHP=device number for "target.out" file
C             =-1 to suppress printing of "target.out"
C        MXNAT = dimensioning information
C Returns:
C        A1(1-3) = unit vector along cylinder axis
C        A2(1-3) = unit vector perpendicular to cylinder axis
C        CDESCR = string describing target (up to 67 chars.)
C        NAT = number of atoms in target
C        IXYZ(1-NAT,1-3)=x/d,y/d,z/d for atoms in target
C        ICOMP(1-NAT,1-3)=1 (composition identifier)
C
C B.T.Draine, Princeton Univ. Obs., 87.04.03
C History:
C 89.12.21 (BTD): Modified for use by ddscat 89.12.21
C 90.12.03 (BTD): Modified for conformity with other target routines
C 91.01.05 (BTD): Changed I4 -> I7 when printing NAT
C 91.04.22 (BTD): Added XV,YV,ZV and A1,A2 to WRITE(IOSHP,FMT=9020)
C 93.03.12 (BTD): Changed CDESCR*(*) -> CDESCR*67
C 95.04.07 (BTD): Corrected error in code which affected target
C                 construction for 4.5<B<5.5, 6.5<B<7.5, ...
C                 In these cases code was construction target with
C                 diameter 4, 6, ... dipoles
C                 This error was discovered by Tao Du
C 96.01.25 (BTD): Modified for conformity with DDSCAT.5a
C 96.01.26 (BTD): Replaced IX,IY,IZ by IXYZ
C 97.12.26 (BTD): Added DX(1-3) to argument list to support noncubic
C                 lattice.
C 98.02.11 (BTD): Make changes to generate target for noncubic lattice.
C                 Take opportunity to simplify and streamline.
C 98.04.27 (BTD): Delete unused variables IN,Y2,ROFF,X,Z,IAXIS
C                 Declare variabels Y2M
C                 Delete IAXIS from WRITE(IOSHP,FMT=9020) statement
C 00.11.02 (BTD): Add ICOMP to argument list, return with ICOMP=1
C                 for occupied sites.
C                 write ICOMP to target.out
c 06.09.13 (BTD): Corrected error: initialize NAT
C end history
C Copyright (C) 1993,1995,1996,1997,1998,2000,2006
C               B.T. Draine and P.J. Flatau
C This code is covered by the GNU General Public License.
C***********************************************************************

      PI=4.*ATAN(1.)

      NAT=0

C Cylinder axis is along x axis in target frame.

      DO JX=1,3
         A1(JX)=0.
         A2(JX)=0.
      ENDDO
      A1(1)=1.
      A2(2)=1.

C A = cylinder length/d
C B = cylinder diameter/d

C Determine centroid XCM,YCM,ZCM

C If A/d_x is near an odd integer, XCM=0
C If A/d_x is near an even integer, XCM=0.5

C If B/d_y is near an odd or even integer, YCM=0 or 0.5
C If B/d_z is near an odd or even integer, ZCM=0 or 0.5

C Determine limits for testing x,y,z values
C In case of disk axis, run from I=1 to I=INT(A+0.5)
C In radial directions, place atoms as follows:
C     If B is close to even number
C          x = i + 0.5
C          with i running from -int((b+.5)/2) to int((b+.5)/2)-1
C     If B is close to odd number
C          x = i
C          with i running from -int((b+.5)/2) to int((b+.5)/2)

      NX2=INT(A/DX(1)+0.5)
      NB=INT(B/DX(2)+0.5)
      IF(2*(NB/2).LT.NB)THEN
         YCM=0.
         NY1=-NB/2
         NY2=NB/2
      ELSE
         YCM=0.5
         NY1=-NB/2+1
         NY2=NB/2
      ENDIF
      NB=INT(B/DX(3)+0.5)
      IF(2*(NB/2).LT.NB)THEN
         ZCM=0.
         NZ1=-NB/2
         NZ2=NB/2
      ELSE
         ZCM=0.5
         NZ1=-NB/2+1
         NZ2=NB/2
      ENDIF
      
      DO JZ=NZ1,NZ2
         Z2=((JZ-ZCM)*DX(3))**2
         Y2M=((0.5*B)**2-Z2)/DX(2)**2
         DO JY=NY1,NY2
            IF((JY-YCM)**2.LT.Y2M)THEN
               DO JX=1,NX2
                  NAT=NAT+1
                  IF(NAT.GT.MXNAT)THEN
                     CALL ERRMSG('FATAL','TARCYL',' NAT.GT.MXNAT')
                  ENDIF
                  IXYZ(NAT,1)=JX
                  IXYZ(NAT,2)=JY
                  IXYZ(NAT,3)=JZ
               ENDDO
            ENDIF
         ENDDO
      ENDDO

C Set composition

      DO JZ=1,3
         DO JX=1,NAT
            ICOMP(JX,JZ)=1
         ENDDO
      ENDDO

C NLAY = number of layers in cylinder
C NFAC = number of atoms in slice

      NLAY=NX2
      NFAC=NAT/NLAY

C REFF2=effective radius**2 of disk

      REFF2=REAL(NFAC)/PI

C ASPR=aspect ratio (length/diameter)

      ASPR=0.5*REAL(NLAY)/SQRT(REFF2)
      WRITE(CDESCR,FMT='(A,I7,A,I4,A,I4,A,F7.4)')
     &    ' Cyl.prism, NAT=',NAT,' NFAC=',NFAC,' NLAY=',NLAY,
     &    ' asp.ratio=',ASPR

      IF(IOSHP.GE.0)THEN
         OPEN(UNIT=IOSHP,FILE='target.out',STATUS='UNKNOWN')
         WRITE(IOSHP,FMT=9020)A,B,NAT,A1,A2,DX
         DO JX=1,NAT
            WRITE(IOSHP,FMT=9030)JX,IXYZ(JX,1),IXYZ(JX,2),IXYZ(JX,3),
     &                           ICOMP(JX,1),ICOMP(JX,2),ICOMP(JX,3)
         ENDDO
         CLOSE(UNIT=IOSHP)
      ENDIF
      RETURN
 9020 FORMAT(' >TARELL  cylindrical target: Length=',F8.4,
     &' Diameter=',F8.4,/,
     &I7,' = NAT',/,
     &3F9.4,' = A_1 vector',/,
     &3F9.4,' = A_2 vector',/,
     &3F9.6,' = (d_x,d_y,d_z)/d',/,
     &'     JA  IX  IY  IZ ICOMP(x,y,z)')
 9030 FORMAT(I7,3I4,3I2)
      END

