Re: CCL:file format?



 On Wed, 28 Feb 2001, Rajarshi Guha wrote:
 >   I was using the software package DTMM (for windows) to draw some
 > molecules.
 > Could anybody tell me what file format DTMM uses?
 The answer appears to be 'a very fussy one'.  My experience is that the
 file format, while it is plain text, has to have the numbers in strictly
 defined column positions.
 For a modest sized molecule, it is easy to get from dtmm format by using
 a text editor to hand edit the file to .xyz format, which can then be
 translated using babel or molden.  You just need a text editor which
 preferably can do rectangular block copy, delete etc., i.e. is designed for
 column-oriented text.
 To go to dtmm format, I eventually became desperate enough to write a
 program, todtmm.for, which I attach as plain text.  This reads a coordinates
 file which is in relatively free format, so can easily be generated from
 an .xyz file by hand editing.  This format is described in the program
 comments.
 My coordinates file format was originally designed for input to my
 programs bangl and tangl, to tabulate bond lengths and angles, and
 torsion angles, respectively.  I also attach these programs, in case
 they are of any use to you.  They produce identical results to the
 distance or angle tables in Gaussian output, or individual measurements
 using molden (but different to Rasmol or the Chime plugin, which seem to
 suffer from rounding errors).
 No guarantees given!  Bangl and tangl have been in use for many years,
 but todtmm is much less tested, as I have now given up using dtmm in favour
 of software which can read mdl .mol files etc.
 Bruce Tattershall
 Bruce.Tattershall "at@at" newcastle.ac.uk
     Dr. B.W. Tattershall    Department of Chemistry
     University of Newcastle    Newcastle upon Tyne
     England
 
      PROGRAM TODTMM
 C===  READS .CRD FILE, SUITABLE FOR BANGL;
 C===  WRITES .MOL FILE, SUITABLE FOR DTMM
 C===
 C===  PROGRAM CREATED BY MODIFYING BANGL
 C===
 C===  INPUT FILE (STANDARD INPUT) CONSISTS OF:
 C===   TITLE (A79)
 C===   NO. OF ATOMS
 C===   MAX. LENGTH OF BONDS
 C===  THEN NATOMS PAIRS OF LINES:
 C===   ATOM LABEL (A8)
 C===   X  Y  Z   (FREE FORMAT)
 C===
 C===  HANDLES UP TO 100 ATOMS, 400 BONDS, COORD. NO. 10
 C===
       REAL X(100),Y(100),Z(100)
       DOUBLE PRECISION BLEN(400),BLEN2(400),DIST2,
      & XI,YI,ZI,BLJ,BL2J,BONDMX,BONDM2
       INTEGER IBNDED(400),JBNDED(400),LIGND(10)
       CHARACTER SYMBOL(100)*8,SYMBI*8
 C===
       DIST2(JATOM)=(XI-X(JATOM))**2+(YI-Y(JATOM))**2+(ZI-Z(JATOM))**2
 C===
       MATOMS=400
       MBONDS=100
       MLIGS=10
 C===
       ONE=1.0
       RNINTY=90.0
 C===
 C===  READ IN DATA
       READ(*,10)
 10    FORMAT(A79)
       READ(*,30)NATOMS
 30    FORMAT(I3)
       IF(NATOMS.LE.MATOMS)GOTO 50
       WRITE(*,40)MATOMS
 40    FORMAT(/' TOO MANY ATOMS, LIMIT IS ',I3)
       STOP
 50    READ(*,60)BONDMX
 60    FORMAT(F10.0)
       DO 80 IATOM=1,NATOMS
       READ(*,70,END=240)SYMBOL(IATOM)
 70    FORMAT(A8)
 80    READ(*,*,END=240,ERR=240)X(IATOM),Y(IATOM),Z(IATOM)
 C===
       NBONDS=0
       BONDM2=BONDMX**2
 C===  LOOP TO STORE BOND LENGTHS BLEN(), THEIR SQUARES BLEN2(),
 C===   AND THE INDICES OF ATOMS THEY ARE BETWEEN, IBNDED() AND JBNDED()
       DO 110 IATOM=1,NATOMS-1
       XI=X(IATOM)
       YI=Y(IATOM)
       ZI=Z(IATOM)
       DO 110 JATOM=IATOM+1,NATOMS
       BL2J=DIST2(JATOM)
       IF(BL2J.GT.BONDM2)GOTO 110
       IF(NBONDS.LT.MBONDS)GOTO 100
       WRITE(*,90)MBONDS,BONDMX
 90    FORMAT(/'TOO MANY BONDS;  LIMIT IS ',I4/
      & ' MAX. BOND LENGTH INPUT WAS',F7.3)
       STOP
 100   NBONDS=NBONDS+1
       IBNDED(NBONDS)=IATOM
       JBNDED(NBONDS)=JATOM
 110   CONTINUE
 C===  WRITE HEADER LINES
       WRITE(*,112)ONE,ONE,ONE,RNINTY,RNINTY,RNINTY,NATOMS
 112   FORMAT(T42,F5.3,T50,F5.3,T58,F5.3/T24,F6.3,T32,F6.3,T40,F6.3/
      & I4/' ')
 C===
 C===  FOR EACH ATOM, MAKE TEMPORARY ARRAYS
 C===   INBNDS() OF INDEXES TO BONDS ARRAYS
 C===   LIGND()  OF INDEXES TO ATOMS ARRAYS
       DO 230 IATOM=1,NATOMS
       SYMBI=SYMBOL(IATOM)
       DO 120 KBOND=1,NBONDS
       IF(IBNDED(KBOND).EQ.IATOM)GOTO 130
 120   CONTINUE
 130   NLIGS=0
       IF(KBOND.EQ.1)GOTO 145
 C===  BONDS FROM EARLIER ATOMS WILL BE SPREAD OUT UP TO HERE
       DO 140 IBOND=1,KBOND-1
       IF(JBNDED(IBOND).NE.IATOM)GOTO 140
       NLIGS=NLIGS+1
       IF(NLIGS.GT.MLIGS)GOTO 160
       LIGND(NLIGS)=IBNDED(IBOND)
 140   CONTINUE
 C===
 C===  BONDS TO LATER ATOMS WILL BE BUNCHED HERE
 145   DO 150 IBOND=KBOND,NBONDS
       IF(IBNDED(IBOND).NE.IATOM)GOTO 180
       NLIGS=NLIGS+1
       IF(NLIGS.GT.MLIGS)GOTO 160
       LIGND(NLIGS)=JBNDED(IBOND)
 150   CONTINUE
       GOTO 180
 C===
 160   WRITE(*,170)SYMBI,MLIGS,BONDMX
 170   FORMAT(/' ATOM ',A8,':  TOO MANY LIGANDS;  LIMIT IS ',I3/
      & ' MAX. BOND LENGTH INPUT WAS',F7.3)
       STOP
 C===
 C===  WRITE ATOM RECORD
 180   WRITE(*,190)IATOM,SYMBI,X(IATOM),Y(IATOM),Z(IATOM),
      & (LIGND(ILIGND),ILIGND=1,NLIGS)
 190   FORMAT(I4,1X,A2,3X,3F10.5,1X,4I4)
 C===
 230   CONTINUE
       STOP
 C===
 240   WRITE(*,250)
 250   FORMAT(/' BAD DATA')
       STOP
 C===
       END
 L
      PROGRAM BANGL
 C===  CALCULATES BOND LENGTHS AND ANGLES FROM CARTESIAN COORDS.
 C===
 C===  INPUT FILE (STANDARD INPUT) CONSISTS OF:
 C===   TITLE (A79)
 C===   NO. OF ATOMS
 C===   MAX. LENGTH OF BONDS
 C===  THEN NATOMS PAIRS OF LINES:
 C===   ATOM LABEL (A8)
 C===   X  Y  Z   (FREE FORMAT)
 C===
 C===  HANDLES UP TO 100 ATOMS, 400 BONDS, COORD. NO. 10
 C===
       REAL X(100),Y(100),Z(100)
       DOUBLE PRECISION BLEN(400),BLEN2(400),DIST2,
      & XI,YI,ZI,BLJ,BL2J,BONDMX,BONDM2
       INTEGER IBNDED(400),JBNDED(400),LIGND(10),INBNDS(10)
       CHARACTER SYMBOL(100)*8,SYMBI*8,SYMBJ*8,TITLE*79
 C===
       DIST2(JATOM)=(XI-X(JATOM))**2+(YI-Y(JATOM))**2+(ZI-Z(JATOM))**2
 C===
       MATOMS=400
       MBONDS=100
       MLIGS=10
       RTOD=180.0/ACOS(-1.0)
 C===
 C===  READ IN DATA
       READ(*,10)TITLE
 10    FORMAT(A79)
       WRITE(*,20)TITLE
 20    FORMAT(1X,A79)
       READ(*,30)NATOMS
 30    FORMAT(I3)
       IF(NATOMS.LE.MATOMS)GOTO 50
       WRITE(*,40)MATOMS
 40    FORMAT(/' TOO MANY ATOMS, LIMIT IS ',I3)
       STOP
 50    READ(*,60)BONDMX
 60    FORMAT(F10.0)
       DO 80 IATOM=1,NATOMS
       READ(*,70,END=240)SYMBOL(IATOM)
 70    FORMAT(A8)
 80    READ(*,*,END=240,ERR=240)X(IATOM),Y(IATOM),Z(IATOM)
 C===
       NBONDS=0
       BONDM2=BONDMX**2
 C===  LOOP TO STORE BOND LENGTHS BLEN(), THEIR SQUARES BLEN2(),
 C===   AND THE INDICES OF ATOMS THEY ARE BETWEEN, IBNDED() AND JBNDED()
       DO 110 IATOM=1,NATOMS-1
       XI=X(IATOM)
       YI=Y(IATOM)
       ZI=Z(IATOM)
       DO 110 JATOM=IATOM+1,NATOMS
       BL2J=DIST2(JATOM)
       IF(BL2J.GT.BONDM2)GOTO 110
       IF(NBONDS.LT.MBONDS)GOTO 100
       WRITE(*,90)MBONDS,BONDMX
 90    FORMAT(/'TOO MANY BONDS;  LIMIT IS ',I4/
      & ' MAX. BOND LENGTH INPUT WAS',F7.3)
       STOP
 100   NBONDS=NBONDS+1
       IBNDED(NBONDS)=IATOM
       JBNDED(NBONDS)=JATOM
       BLEN2(NBONDS)=BL2J
       BLEN(NBONDS)=SQRT(BL2J)
 110   CONTINUE
 C===
 C===  FOR EACH ATOM, MAKE TEMPORARY ARRAYS
 C===   INBNDS() OF INDEXES TO BONDS ARRAYS
 C===   LIGND()  OF INDEXES TO ATOMS ARRAYS
       DO 230 IATOM=1,NATOMS
       SYMBI=SYMBOL(IATOM)
       DO 120 KBOND=1,NBONDS
       IF(IBNDED(KBOND).EQ.IATOM)GOTO 130
 120   CONTINUE
 130   NLIGS=0
       IF(KBOND.EQ.1)GOTO 145
 C===  BONDS FROM EARLIER ATOMS WILL BE SPREAD OUT UP TO HERE
       DO 140 IBOND=1,KBOND-1
       IF(JBNDED(IBOND).NE.IATOM)GOTO 140
       NLIGS=NLIGS+1
       IF(NLIGS.GT.MLIGS)GOTO 160
       INBNDS(NLIGS)=IBOND
       LIGND(NLIGS)=IBNDED(IBOND)
 140   CONTINUE
 C===
 C===  BONDS TO LATER ATOMS WILL BE BUNCHED HERE
 145   DO 150 IBOND=KBOND,NBONDS
       IF(IBNDED(IBOND).NE.IATOM)GOTO 180
       NLIGS=NLIGS+1
       IF(NLIGS.GT.MLIGS)GOTO 160
       INBNDS(NLIGS)=IBOND
       LIGND(NLIGS)=JBNDED(IBOND)
 150   CONTINUE
       GOTO 180
 C===
 160   WRITE(*,170)SYMBI,MLIGS,BONDMX
 170   FORMAT(/' ATOM ',A8,':  TOO MANY LIGANDS;  LIMIT IS ',I3/
      & ' MAX. BOND LENGTH INPUT WAS',F7.3)
       STOP
 C===
 180   IF(NLIGS.EQ.0)GOTO 230
 C===  OUTPUT BOND LENGTHS
       WRITE(*,190)SYMBI,NLIGS
 190   FORMAT(/' ATOM ',A8,':  COORDINATION NUMBER ',I2/
      & ' BOND LENGTHS:')
       DO 200 ILIGND=1,NLIGS
       JATOM=LIGND(ILIGND)
       IBOND=INBNDS(ILIGND)
 200   WRITE(*,210)SYMBI,SYMBOL(JATOM),BLEN(IBOND)
 210   FORMAT(1X,A8,' -- ',A8,2X,F6.4)
 C===
       IF(NLIGS.EQ.1)GOTO 230
 C===  OUTPUT BOND ANGLES
       WRITE(*,220)SYMBI
 220   FORMAT(' ANGLES ABOUT ATOM ',A8,':')
       DO 230 JLIGND=1,NLIGS-1
       JATOM=LIGND(JLIGND)
       JBOND=INBNDS(JLIGND)
       XI=X(JATOM)
       YI=Y(JATOM)
       ZI=Z(JATOM)
       SYMBJ=SYMBOL(JATOM)
       BL2J=BLEN2(JBOND)
       BLJ=BLEN(JBOND)
       DO 230 KLIGND=JLIGND+1,NLIGS
       KATOM=LIGND(KLIGND)
       KBOND=INBNDS(KLIGND)
       ANGLE=RTOD*ABS(ACOS((BL2J+BLEN2(KBOND)-DIST2(KATOM))/
      & (2*BLJ*BLEN(KBOND))))
       WRITE(*,229)SYMBJ,SYMBI,SYMBOL(KATOM),ANGLE
 229   FORMAT(1X,A8,' -- ',A8,' -- ',A8,2X,F7.3)
 C===
 230   CONTINUE
       STOP
 C===
 240   WRITE(*,250)
 250   FORMAT(/' BAD DATA')
       STOP
 C===
       END
  
      PROGRAM TANGL
 C===  CALCULATES TORSION ANGLES A-B-C-D FROM CARTESIAN COORDS.
 C===
 C===  INPUT FILE (STANDARD INPUT) IS THE SAME AS FOR BANGL, AND
 C===    CONSISTS OF:
 C===   TITLE (A79)
 C===   NO. OF ATOMS
 C===   MAX. LENGTH OF BONDS
 C===  THEN NATOMS PAIRS OF LINES:
 C===   ATOM LABEL (A8)
 C===   X  Y  Z   (FREE FORMAT)
 C===
 C===  HANDLES UP TO 100 ATOMS, 400 BONDS, COORD. NO. 10
 C===
 C***
       COMMON X,Y,Z,NBONDS,IBNDED,JBNDED,MLIGS,BONDMX
       DOUBLE PRECISION BONDMX
       REAL X(100),Y(100),Z(100)
       INTEGER IBNDED(400),JBNDED(400)
 C***
       DOUBLE PRECISION RTOD,DIST2,XI,YI,ZI,BL2J,BONDM2,ANGLA,ANGLT,
      & ANGLD,VECBA(3),VECBC(3),VECCB(3),VECCD(3),VECCR1(3),VECCR2(3),
      & VECCR3(3),VDOT,VANGL
       INTEGER LIGNDB(10),LIGNDC(10)
       CHARACTER SYMBOL(100)*8,SYMBA*8,SYMBB*8,SYMBC*8,SYMBD*8,TITLE*79
 C===
       DIST2(JATOM)=(XI-X(JATOM))**2+(YI-Y(JATOM))**2+(ZI-Z(JATOM))**2
 C===
       MATOMS=400
       MBONDS=100
       MLIGS=10
       RTOD=DBLE(180.0)/DACOS(DBLE(-1.0))
 C===
 C===  READ IN DATA
       READ(*,10)TITLE
 10    FORMAT(A79)
       WRITE(*,20)TITLE
 20    FORMAT(1X,A79)
       READ(*,30)NATOMS
 30    FORMAT(I3)
       IF(NATOMS.LE.MATOMS)GOTO 50
       WRITE(*,40)MATOMS
 40    FORMAT(/' TOO MANY ATOMS, LIMIT IS ',I3)
       STOP
 50    READ(*,60)BONDMX
 60    FORMAT(F10.0)
       DO 80 IATOM=1,NATOMS
       READ(*,70,END=240)SYMBOL(IATOM)
 70    FORMAT(A8)
 80    READ(*,*,END=240,ERR=240)X(IATOM),Y(IATOM),Z(IATOM)
 C===
       NBONDS=0
       BONDM2=BONDMX**2
 C===  LOOP TO STORE THE INDICES OF ATOMS BONDS ARE BETWEEN,
 C===   IBNDED() AND JBNDED()
       DO 110 IATOM=1,NATOMS-1
       XI=X(IATOM)
       YI=Y(IATOM)
       ZI=Z(IATOM)
       DO 110 JATOM=IATOM+1,NATOMS
       BL2J=DIST2(JATOM)
       IF(BL2J.GT.BONDM2)GOTO 110
       IF(NBONDS.LT.MBONDS)GOTO 100
       WRITE(*,90)MBONDS,BONDMX
 90    FORMAT(/'TOO MANY BONDS;  LIMIT IS ',I4/
      & ' MAX. BOND LENGTH INPUT WAS',F7.3)
       STOP
 100   NBONDS=NBONDS+1
       IBNDED(NBONDS)=IATOM
       JBNDED(NBONDS)=JATOM
 110   CONTINUE
 C===
 C===  HEADING FOR TABLE
       WRITE(*,115)
 115   FORMAT(/,3X,'A',11X,'B',11X,'C',11X,'D',6X,'Layback A',2X,
      & 'Torsion',2X,'Layback D')
 C===  FOR EACH ATOM B
       DO 230 IATOMB=1,NATOMS-1
       SYMBB=SYMBOL(IATOMB)
 C===  GET THE LIGAND SET FOR B
       CALL LIGNDS(IATOMB,NLIGSB,LIGNDB)
       IF(NLIGSB.LT.2)GOTO 230
 C===
 C===  FOR EACH ATOM C
       DO 230 ILC=1,NLIGSB
       IATOMC=LIGNDB(ILC)
 C===  EXCLUDE BC BONDS DONE ALREADY
       IF(IATOMC.LT.IATOMB)GOTO 230
       SYMBC=SYMBOL(IATOMC)
 C===  SPACE THE OUTPUT
       WRITE(*,120)
 120   FORMAT(' ')
 C===  GET LIGAND SET FOR C
       CALL LIGNDS(IATOMC,NLIGSC,LIGNDC)
 C===  VECTOR B->C
       CALL VBTWEN(IATOMB,IATOMC,VECBC)
 C===
 C===  FOR EACH ATOM A
       DO 230 ILA=1,NLIGSB
 C===  EXCLUDE ATOM C
       IF(ILA.EQ.ILC)GOTO 230
       IATOMA=LIGNDB(ILA)
       SYMBA=SYMBOL(IATOMA)
 C===  VECTOR B->A
       CALL VBTWEN(IATOMB,IATOMA,VECBA)
 C===  CALC CROSS PRODUCT BC x BA
       CALL VCROSS(VECBC,VECBA,VECCR1)
 C===  CALC LAYBACK ANGLE ABC-90
       ANGLA=VANGL(VECBC,VECBA,RTOD)-9.D1
 C===
 C===  FOR EACH ATOM D
       DO 230 ILD=1,NLIGSC
       IATOMD=LIGNDC(ILD)
 C===  EXCLUDE ATOM B
       IF(IATOMD.EQ.IATOMB)GOTO 230
       SYMBD=SYMBOL(IATOMD)
 C===  VECTOR C->D
       CALL VBTWEN(IATOMC,IATOMD,VECCD)
 C===  CALC CROSS PRODUCT CD x CB
 C===  REVERSE VECTOR BC
       DO 150 I=1,3
 150   VECCB(I)=-VECBC(I)
       CALL VCROSS(VECCD,VECCB,VECCR2)
 C===  CALC LAYBACK ANGLE BCD-90
       ANGLD=VANGL(VECCD,VECCB,RTOD)-9.D1
 C===  THE CROSS PRODUCTS NOW IN VECCR1 AND VECCR2 ARE IN THE PLANE
 C===   PERPENDICULAR TO B->C AND ARE AT 90 DEG TO THE PROJECTIONS
 C===   OF B->A AND C->D RESPECTIVELY ONTO THIS PLANE
 C===
 C===  NOW FIND DOT PRODUCT OF THESE AS A MEANS OF FINDING THE
 C===   ANGLE BETWEEN THEM AND
 C===  COMPARE DIRECTION OF CROSS PRODUCT OF THEM, WHICH WILL BE
 C===   PARALLEL TO B->C, WITH B->C, TO GET SIGN OF ANGLE
 C===
       ANGLT=VANGL(VECCR1,VECCR2,RTOD)
       IF(ANGLT.EQ.3.6D2)GOTO 210
       CALL VCROSS(VECCR1,VECCR2,VECCR3)
       ANGLT=DSIGN(ANGLT,VDOT(VECCR3,VECBC))
 C===
       WRITE(*,200)SYMBA,SYMBB,SYMBC,SYMBD,ANGLA,ANGLT,ANGLD
 200   FORMAT(1X,A8,3(' -- ',A8),3(2X,F8.3))
       GOTO 230
 210   WRITE(*,220)SYMBA,SYMBB,SYMBC,SYMBD,ANGLA,ANGLD
 220   FORMAT(1X,A8,3(' -- ',A8),2X,F8.3,10X,F8.3)
 C===
 230   CONTINUE
 C===
       STOP
 C===
 240   WRITE(*,250)
 250   FORMAT(/' BAD DATA')
       STOP
 C===
       END
 C*****
       SUBROUTINE LIGNDS(IATOM,NLIGS,LIGND)
 C===  COUNT LIGANDS AND MAKE TEMPORARY ARRAY
 C===   LIGND()  OF INDEXES TO ATOMS ARRAYS
 C***
       COMMON X,Y,Z,NBONDS,IBNDED,JBNDED,MLIGS,BONDMX
       DOUBLE PRECISION BONDMX
       REAL X(100),Y(100),Z(100)
       INTEGER IBNDED(400),JBNDED(400)
 C***
       INTEGER LIGND(10)
 C===
       DO 120 KBOND=1,NBONDS
       IF(IBNDED(KBOND).EQ.IATOM)GOTO 130
 120   CONTINUE
 130   NLIGS=0
       IF(KBOND.EQ.1)GOTO 145
 C===  BONDS FROM EARLIER ATOMS WILL BE SPREAD OUT UP TO HERE
       DO 140 IBOND=1,KBOND-1
       IF(JBNDED(IBOND).NE.IATOM)GOTO 140
       NLIGS=NLIGS+1
       IF(NLIGS.GT.MLIGS)GOTO 160
       LIGND(NLIGS)=IBNDED(IBOND)
 140   CONTINUE
 C===
 C===  BONDS TO LATER ATOMS WILL BE BUNCHED HERE
 145   DO 150 IBOND=KBOND,NBONDS
       IF(IBNDED(IBOND).NE.IATOM)GOTO 155
       NLIGS=NLIGS+1
       IF(NLIGS.GT.MLIGS)GOTO 160
       LIGND(NLIGS)=JBNDED(IBOND)
 150   CONTINUE
 155   RETURN
 C===
 160   WRITE(*,170)SYMBI,MLIGS,BONDMX
 170   FORMAT(/' ATOM ',A8,':  TOO MANY LIGANDS;  LIMIT IS ',I3/
      & ' MAX. BOND LENGTH INPUT WAS',F7.3)
       STOP
       END
 C*****
       SUBROUTINE VBTWEN(IATOM,JATOM,VEC)
 C===  LOOKS UP ATOM COORDS AND CALCULATES VECTOR BETWEEN THEM
 C***
       COMMON X,Y,Z,NBONDS,IBNDED,JBNDED,MLIGS,BONDMX
       DOUBLE PRECISION BONDMX
       REAL X(100),Y(100),Z(100)
       INTEGER IBNDED(400),JBNDED(400)
 C***
       DOUBLE PRECISION VEC(3)
 C===
       VEC(1)=X(JATOM)-X(IATOM)
       VEC(2)=Y(JATOM)-Y(IATOM)
       VEC(3)=Z(JATOM)-Z(IATOM)
       RETURN
       END
 C*****
       SUBROUTINE VCROSS(VEC1,VEC2,VEC3)
 C===  CALCULATES THE CROSS PRODUCT
 C===    VEC3 = VEC1 x VEC2
 C===
       DOUBLE PRECISION VEC1(3),VEC2(3),VEC3(3)
 C===
       VEC3(1)=VEC1(2)*VEC2(3)-VEC1(3)*VEC2(2)
       VEC3(2)=VEC1(3)*VEC2(1)-VEC1(1)*VEC2(3)
       VEC3(3)=VEC1(1)*VEC2(2)-VEC1(2)*VEC2(1)
       RETURN
       END
 C*****
       DOUBLE PRECISION FUNCTION VANGL(VEC1,VEC2,RTOD)
 C===  CALCULATES ANGLE IN DEGREES BETWEEN TWO VECTORS
 C===  RTOD IS THE RADIANS TO DEGREES CONVERSION FACTOR
       DOUBLE PRECISION VEC1(3),VEC2(3),VDOT,VMAG,RTOD,COSANG,VLEN1,VLEN2
       VLEN1=VMAG(VEC1)
       VLEN2=VMAG(VEC2)
       VANGL=3.6D2
       IF(VLEN1.LT.1.D-12.OR.VLEN2.LT.1.D-12)GOTO 10
       COSANG=VDOT(VEC1,VEC2)/(VLEN1*VLEN2)
       IF(COSANG.GT.1.D0)COSANG=1.D0
       IF(COSANG.LT.-1.D0)COSANG=-1.D0
       VANGL=RTOD*DACOS(COSANG)
 10    RETURN
       END
 C*****
       DOUBLE PRECISION FUNCTION VDOT(VEC1,VEC2)
 C===  CALCULATES THE DOT PRODUCT  VEC1.VEC2
       DOUBLE PRECISION VEC1(3),VEC2(3)
       VDOT=0.0
       DO 10 I=1,3
 10    VDOT=VDOT+VEC1(I)*VEC2(I)
       RETURN
       END
 C*****
       DOUBLE PRECISION FUNCTION VMAG(VEC)
 C===  CALCULATES MAGNITUDE OF VECTOR VMAG
       DOUBLE PRECISION VEC(3),DZERO,COMP,SUM
       DZERO=DBLE(0.0)
       SUM=DZERO
       DO 10 I=1,3
       COMP=VEC(I)
       IF(DABS(COMP).LT.1.D-12)GOTO 10
       SUM=SUM+COMP*COMP
 10    CONTINUE
       VMAG=DZERO
       IF(SUM.LE.DZERO)GOTO 20
       VMAG=DSQRT(SUM)
 20    RETURN
       END
 C*****
 E