Fortran TLM Code

You can use any part of this code in your own work provided that this source is acknowledged.


      PROGRAM TLM3D
*************************************************************
*                                                           *
* Transmission-line modelling of electromagnetic fields in  *
* 3-dimensions using the symmetrical condensed node.        *
*                                                           *
* Written by:                                               *
*   J L Herring                                             *
*                                                           *
* Address:                                                  *
*   Department of Electrical & Computer Engineering         *
*   University of Victoria                                  *
*   Victoria, B.C., Canada.                                 *
*                                                           *
* E-mail: jherring@ece.uvic.ca                              *
* WWW:    http://www.wjrh.ece.uvic.ca/tlm/                  *
*                                                           *
* History:                                                  *
*   Date started    : 10 Dec 1995                           *
*   Updated         : 10 Dec 1995 (HP-UX) 1.00              *
*   Current version : 30 Jun 1996 (HP-UX) 1.10              *
*                     - more efficient scattering           *
*                     - two-sided internal boundaries       *
*                                                           *
*************************************************************

      IMPLICIT NONE

*---- constant declarations

      CHARACTER*(*) VERSN
      INTEGER INUNT,OUTUNT
      INTEGER XMAX0,YMAX0,ZMAX0
      INTEGER NMBCS0,NMNEX0,NMNOU0
      INTEGER PYNX,PZNX,PXNY,PZNY,PYNZ,PXNZ
      INTEGER PYPZ,PZPY,PZPX,PXPZ,PXPY,PYPX
      REAL    Z0

      PARAMETER ( VERSN = '1.10' )
      PARAMETER ( INUNT=7,OUTUNT=8 )
      PARAMETER ( XMAX0=16,YMAX0=16,ZMAX0=16 )
      PARAMETER ( NMBCS0=20,NMNEX0=10,NMNOU0=10 )
      PARAMETER ( PYNX= 1,PZNX= 2,PXNY= 3,PZNY= 4,PYNZ= 5,PXNZ= 6 )
      PARAMETER ( PYPZ= 7,PZPY= 8,PZPX= 9,PXPZ=10,PXPY=11,PYPX=12 )
      PARAMETER ( Z0=376.7 )

*---- variable declarations

      CHARACTER*80 LINE,COMM
      CHARACTER*40 INNAME,OUTNAM
      CHARACTER*2  LORIEN
      CHARACTER    TYP,DIRN,LSIGN
      LOGICAL EX
      INTEGER ERR,N,X,Y,Z,I
      INTEGER X1,Y1,Z1,D,T
      INTEGER XMAX,YMAX,ZMAX,NUMDT
      INTEGER NUMBCS,NUMNEX,NUMNOU
      REAL    DL,VE,VH,OUT
      REAL    VYNX,VZNX,VXNY,VZNY,VYNZ,VXNZ
      REAL    VYPZ,VZPY,VZPX,VXPZ,VXPY,VYPX
      REAL    RHO,V0,VTEMP,VDIFF

*---- array declarations

      CHARACTER BDIRN(NMBCS0),BSIGN(NMBCS0)
      INTEGER BOX1(NMBCS0),BOY1(NMBCS0),BOZ1(NMBCS0)
      INTEGER BOX2(NMBCS0),BOY2(NMBCS0),BOZ2(NMBCS0)
      REAL BRHO(NMBCS0)

      CHARACTER*3 NEID(NMNEX0)
      INTEGER NEX1(NMNEX0),NEY1(NMNEX0),NEZ1(NMNEX0)
      INTEGER NEX2(NMNEX0),NEY2(NMNEX0),NEZ2(NMNEX0)
      REAL NEAMP(NMNEX0)

      CHARACTER*2 NOID(NMNOU0)
      INTEGER NOX1(NMNOU0),NOY1(NMNOU0),NOZ1(NMNOU0)

      COMMON/COMV/V
      REAL V(12,XMAX0,YMAX0,ZMAX0)

*---- display program details

      WRITE(*,*)
      WRITE(*,*) 'TLM3D (v'//VERSN//') - '//
     ;           'Transmission-Line Modelling in 3-Dimensions'
      WRITE(*,*)
      WRITE(*,*) 'Limits :'
      WRITE(*,99010) 'mesh      ',XMAX0,YMAX0,ZMAX0
      WRITE(*,99020) 'boundaries',NMBCS0
      WRITE(*,99020) 'excite    ',NMNEX0
      WRITE(*,99020) 'output    ',NMNOU0
      WRITE(*,*)
99010 FORMAT(1X,'  ',A,' = ',I2,' x ',I2,' x ',I2)
99020 FORMAT(1X,'  ',A,' = ',I2)

*---- open input file

      WRITE(*,*) 'Name of input file : '
      READ(*,'(A)') INNAME
      INQUIRE(FILE=INNAME,EXIST=EX)
      IF (.NOT.EX) STOP 'File does not exist'
      OPEN(INUNT,FILE=INNAME,STATUS='OLD',ACCESS='SEQUENTIAL',
     ;  FORM='FORMATTED',IOSTAT=ERR)
      IF (ERR.NE.0) STOP 'File cannot be opened'
      REWIND(INUNT)

*---- set default data

      OUTNAM = '?'
      XMAX = XMAX0
      YMAX = YMAX0
      ZMAX = ZMAX0
      DL = 1.0
      NUMDT = 0
      NUMBCS = 0
      NUMNEX = 0
      NUMNOU = 0

*---- read input file

11010 READ(INUNT,'(A)',IOSTAT=ERR) LINE
      IF (ERR.NE.0) STOP 'Error reading file'
      IF (LINE(1:1).EQ.'!') GOTO 11010
      IF (LINE(1:1).NE.':') STOP 'Start of data expected'
      COMM = LINE(2:80)

*------ mesh size
      IF (COMM.EQ.'MESH') THEN
        READ(INUNT,*) XMAX,YMAX,ZMAX
        IF (XMAX.GT.XMAX0.OR.YMAX.GT.YMAX0.OR.ZMAX.GT.ZMAX0)
     ;    STOP 'Too big'

*------ node spacing
      ELSE IF (COMM.EQ.'DL') THEN
        READ(INUNT,*) DL

*------ number of timesteps
      ELSE IF (COMM.EQ.'TIMESTEPS') THEN
        READ(INUNT,*) NUMDT

*------ output file
      ELSE IF (COMM.EQ.'OUTPUT_FILE') THEN
        READ(INUNT,*) OUTNAM

*------ boundaries
      ELSE IF (COMM.EQ.'BOUNDARIES') THEN
        READ(INUNT,*) NUMBCS
        IF (NUMBCS.GT.NMBCS0) STOP 'Too many boundaries'
        DO 12010, I = 1, NUMBCS
          READ(INUNT,*) BRHO(I),LORIEN,BOX1(I),BOY1(I),BOZ1(I),
     ;                  BOX2(I),BOY2(I),BOZ2(I)
          BDIRN(I) = LORIEN(1:1)
          BSIGN(I) = LORIEN(2:2)
        IF ((BSIGN(I).NE.'N'.AND.BSIGN(I).NE.'P'.AND.
     ;        BSIGN(I).NE.'0').OR.
     ;      BOX1(I).LT.1.OR.BOX2(I).GT.XMAX.OR.BOX2(I).LT.BOX1(I).OR.
     ;      BOY1(I).LT.1.OR.BOY2(I).GT.YMAX.OR.BOY2(I).LT.BOY1(I).OR.
     ;      BOZ1(I).LT.1.OR.BOZ2(I).GT.ZMAX.OR.BOZ2(I).LT.BOZ1(I).OR.
     ;      BDIRN(I).EQ.'X'.AND.(BOX1(I).NE.BOX2(I).OR.
     ;        (BSIGN(I).EQ.'0'.AND.BOX2(I).EQ.XMAX)).OR.
     ;      BDIRN(I).EQ.'Y'.AND.(BOY1(I).NE.BOY2(I).OR.
     ;        (BSIGN(I).EQ.'0'.AND.BOY2(I).EQ.YMAX)).OR.
     ;      BDIRN(I).EQ.'Z'.AND.(BOZ1(I).NE.BOZ2(I).OR.
     ;        (BSIGN(I).EQ.'0'.AND.BOZ2(I).EQ.ZMAX)))
     ;        STOP 'Bad boundary coordinates'
12010   CONTINUE

*------ excitation
      ELSE IF (COMM.EQ.'EXCITE') THEN
        READ(INUNT,*) NUMNEX
        IF (NUMNEX.GT.NMNEX0) STOP 'Too many excite'
        DO 13010, I = 1, NUMNEX
          READ(INUNT,*) NEID(I),NEAMP(I),NEX1(I),NEY1(I),NEZ1(I),
     ;                  NEX2(I),NEY2(I),NEZ2(I)
        IF (NEX1(I).LT.1.OR.NEX2(I).GT.XMAX.OR.NEX2(I).LT.NEX1(I).OR.
     ;      NEY1(I).LT.1.OR.NEY2(I).GT.YMAX.OR.NEY2(I).LT.NEY1(I).OR.
     ;      NEZ1(I).LT.1.OR.NEZ2(I).GT.ZMAX.OR.NEZ2(I).LT.NEZ1(I))
     ;      STOP 'Bad excitation coordinates'
13010   CONTINUE

*------ output
      ELSE IF (COMM.EQ.'OUTPUT') THEN
        READ(INUNT,*) NUMNOU
        IF (NUMNOU.GT.NMNOU0) STOP 'Too many output'
        DO 14010, I = 1, NUMNOU
          READ(INUNT,*) NOID(I),NOX1(I),NOY1(I),NOZ1(I)
        IF (NOX1(I).LT.1.OR.NOX1(I).GT.XMAX.OR.
     ;      NOY1(I).LT.1.OR.NOY1(I).GT.YMAX.OR.
     ;      NOZ1(I).LT.1.OR.NOZ1(I).GT.ZMAX)
     ;      STOP 'Bad output coordinates'
14010   CONTINUE

*---- end of read

      ELSE IF (COMM.NE.'END') THEN
        STOP 'Data not recognised'
      END IF
      IF (COMM.NE.'END') GOTO 11010
      CLOSE(INUNT)
      WRITE(*,*) 'Input file closed'

*---- open output file

      IF (OUTNAM.EQ.'?') THEN
        WRITE(*,*) 'Name of output file : '
        READ(*,'(A)') OUTNAM
      END IF
      OPEN(OUTUNT,FILE=OUTNAM,STATUS='NEW',ACCESS='SEQUENTIAL',
     ;  FORM='FORMATTED',IOSTAT=ERR)
      IF (ERR.NE.0) STOP 'Output file cannot be opened'

*---- clear array

      DO 21010, Z = 1, ZMAX
        DO 21020, Y = 1, YMAX
          DO 21030, X = 1, XMAX
            DO 21040, D = 1, 12
              V(D,X,Y,Z) = 0.0
21040        CONTINUE
21030      CONTINUE
21020    CONTINUE
21010  CONTINUE

*---- excite

       DO 22010, N = 1, NUMNEX

        TYP  = NEID(N)(1:1)
        DIRN = NEID(N)(2:2)
        IF (TYP.EQ.'E') THEN
          VE = - DL * NEAMP(N) / 2.0
        ELSE IF (TYP.EQ.'H') THEN
          VH = DL * Z0 * NEAMP(N) / 2.0
        ELSE
          STOP 'Excitation field error'
        END IF

        DO 22020, Z = NEZ1(N), NEZ2(N)
          DO 22030, Y = NEY1(N), NEY2(N)
            DO 22040, X = NEX1(N), NEX2(N)

              IF (TYP.EQ.'E') THEN
                IF (DIRN.EQ.'X') THEN
                  V(PYNX,X,Y,Z) = V(PYNX,X,Y,Z) + VE
                  V(PZNX,X,Y,Z) = V(PZNX,X,Y,Z) + VE
                  V(PYPX,X,Y,Z) = V(PYPX,X,Y,Z) + VE
                  V(PZPX,X,Y,Z) = V(PZPX,X,Y,Z) + VE
                ELSE IF (DIRN.EQ.'Y') THEN
                  V(PZNY,X,Y,Z) = V(PZNY,X,Y,Z) + VE
                  V(PXNY,X,Y,Z) = V(PXNY,X,Y,Z) + VE
                  V(PZPY,X,Y,Z) = V(PZPY,X,Y,Z) + VE
                  V(PXPY,X,Y,Z) = V(PXPY,X,Y,Z) + VE
                ELSE IF (DIRN.EQ.'Z') THEN
                  V(PXNZ,X,Y,Z) = V(PXNZ,X,Y,Z) + VE
                  V(PYNZ,X,Y,Z) = V(PYNZ,X,Y,Z) + VE
                  V(PXPZ,X,Y,Z) = V(PXPZ,X,Y,Z) + VE
                  V(PYPZ,X,Y,Z) = V(PYPZ,X,Y,Z) + VE
                ELSE
                  STOP 'E-field excitation error'
                END IF

              ELSE IF (TYP.EQ.'H') THEN
                IF (DIRN.EQ.'X') THEN
                  V(PZNY,X,Y,Z) = V(PZNY,X,Y,Z) + VH
                  V(PYNZ,X,Y,Z) = V(PYNZ,X,Y,Z) - VH
                  V(PZPY,X,Y,Z) = V(PZPY,X,Y,Z) - VH
                  V(PYPZ,X,Y,Z) = V(PYPZ,X,Y,Z) + VH
                ELSE IF (DIRN.EQ.'Y') THEN
                  V(PXNZ,X,Y,Z) = V(PXNZ,X,Y,Z) + VH
                  V(PZNX,X,Y,Z) = V(PZNX,X,Y,Z) - VH
                  V(PXPZ,X,Y,Z) = V(PXPZ,X,Y,Z) - VH
                  V(PZPX,X,Y,Z) = V(PZPX,X,Y,Z) + VH
                ELSE IF (DIRN.EQ.'Z') THEN
                  V(PYNX,X,Y,Z) = V(PYNX,X,Y,Z) + VH
                  V(PXNY,X,Y,Z) = V(PXNY,X,Y,Z) - VH
                  V(PYPX,X,Y,Z) = V(PYPX,X,Y,Z) - VH
                  V(PXPY,X,Y,Z) = V(PXPY,X,Y,Z) + VH
                ELSE
                  STOP 'H-field excitation error'
                END IF

              END IF

22040       CONTINUE
22030     CONTINUE
22020   CONTINUE

22010 CONTINUE

*---- start calculation

      WRITE(*,*) 'Start of calculation'

      DO 30010, T = 1, NUMDT

      WRITE(*,99100) 100.0*REAL(T-1)/REAL(NUMDT)
99100 FORMAT(1X,F6.3,' %')

*---- output

      DO 41010, N = 1, NUMNOU

        TYP  = NOID(N)(1:1)
        DIRN = NOID(N)(2:2)

        Z = NOZ1(N)
        Y = NOY1(N)
        X = NOX1(N)

        IF (TYP.EQ.'E') THEN
          IF (DIRN.EQ.'X') THEN
            OUT = V(PYNX,X,Y,Z) + V(PZNX,X,Y,Z) +
     ;            V(PYPX,X,Y,Z) + V(PZPX,X,Y,Z)
          ELSE IF (DIRN.EQ.'Y') THEN
            OUT = V(PZNY,X,Y,Z) + V(PXNY,X,Y,Z) +
     ;            V(PZPY,X,Y,Z) + V(PXPY,X,Y,Z)
          ELSE IF (DIRN.EQ.'Z') THEN
            OUT = V(PXNZ,X,Y,Z) + V(PYNZ,X,Y,Z) +
     ;            V(PXPZ,X,Y,Z) + V(PYPZ,X,Y,Z)
          ELSE
            STOP 'E-field output error'
          END IF
          OUT = - OUT / DL / 2.0
 
        ELSE IF (TYP.EQ.'H') THEN
          IF (DIRN.EQ.'X') THEN
            OUT = V(PZNY,X,Y,Z) - V(PYNZ,X,Y,Z) -
     ;            V(PZPY,X,Y,Z) + V(PYPZ,X,Y,Z)
          ELSE IF (DIRN.EQ.'Y') THEN
            OUT = V(PXNZ,X,Y,Z) - V(PZNX,X,Y,Z) -
     ;            V(PXPZ,X,Y,Z) + V(PZPX,X,Y,Z)
          ELSE IF (DIRN.EQ.'Z') THEN
            OUT = V(PYNX,X,Y,Z) - V(PXNY,X,Y,Z) -
     ;            V(PYPX,X,Y,Z) + V(PXPY,X,Y,Z)
          ELSE
            STOP 'H-field output error'
          END IF
          OUT = OUT / Z0 / DL / 2.0

        ELSE
          STOP 'Output field error'
        END IF

        WRITE(OUTUNT,99200) OUT
99200 FORMAT(1X,E13.6)

41010 CONTINUE

*---- scatter

      DO 42010, Z = 1, ZMAX
        DO 42020, Y = 1, YMAX
          DO 42030, X = 1, XMAX

            VYNX = V(PYNX,X,Y,Z)
            VZNX = V(PZNX,X,Y,Z)
            VXNY = V(PXNY,X,Y,Z)
            VZNY = V(PZNY,X,Y,Z)
            VYNZ = V(PYNZ,X,Y,Z)
            VXNZ = V(PXNZ,X,Y,Z)
            VYPZ = V(PYPZ,X,Y,Z)
            VZPY = V(PZPY,X,Y,Z)
            VZPX = V(PZPX,X,Y,Z)
            VXPZ = V(PXPZ,X,Y,Z)
            VXPY = V(PXPY,X,Y,Z)
            VYPX = V(PYPX,X,Y,Z)

            VDIFF = VXPY - VXNY
            VTEMP = 0.5 * ( VZNX + VZPX + VDIFF )
            V(PYPX,X,Y,Z) = VTEMP
            V(PYNX,X,Y,Z) = VTEMP - VDIFF

            VDIFF = VXPZ - VXNZ
            VTEMP = 0.5 * ( VYNX + VYPX + VDIFF )
            V(PZPX,X,Y,Z) = VTEMP
            V(PZNX,X,Y,Z) = VTEMP - VDIFF

            VDIFF = VYPZ - VYNZ
            VTEMP = 0.5 * ( VXNY + VXPY + VDIFF )
            V(PZPY,X,Y,Z) = VTEMP
            V(PZNY,X,Y,Z) = VTEMP - VDIFF

            VDIFF = VYPX - VYNX
            VTEMP = 0.5 * ( VZNY + VZPY + VDIFF )
            V(PXPY,X,Y,Z) = VTEMP
            V(PXNY,X,Y,Z) = VTEMP - VDIFF

            VDIFF = VZPX - VZNX
            VTEMP = 0.5 * ( VYNZ + VYPZ + VDIFF )
            V(PXPZ,X,Y,Z) = VTEMP
            V(PXNZ,X,Y,Z) = VTEMP - VDIFF

            VDIFF = VZPY - VZNY
            VTEMP = 0.5 * ( VXNZ + VXPZ + VDIFF )
            V(PYPZ,X,Y,Z) = VTEMP
            V(PYNZ,X,Y,Z) = VTEMP - VDIFF

42030     CONTINUE
42020   CONTINUE
42010 CONTINUE

*---- boundaries

      DO 43010, N = 1, NUMBCS

        DIRN = BDIRN(N)
        LSIGN = BSIGN(N)
        RHO  = BRHO(N)

        IF (DIRN.EQ.'X') THEN
          X = BOX1(N)

          IF (LSIGN.EQ.'N'.AND.X.EQ.1) THEN
            DO 43110, Z = BOZ1(N), BOZ2(N)
              DO 43120, Y = BOY1(N), BOY2(N)
                V(PXNY,X,Y,Z) = RHO * V(PXNY,X,Y,Z)
                V(PXNZ,X,Y,Z) = RHO * V(PXNZ,X,Y,Z)
43120         CONTINUE
43110       CONTINUE

          ELSE IF (LSIGN.EQ.'P'.AND.X.EQ.XMAX) THEN
            DO 43130, Z = BOZ1(N), BOZ2(N)
              DO 43140, Y = BOY1(N), BOY2(N)
                V(PXPZ,X,Y,Z) = RHO * V(PXPZ,X,Y,Z)
                V(PXPY,X,Y,Z) = RHO * V(PXPY,X,Y,Z)
43140         CONTINUE
43130      CONTINUE

          ELSE
            IF (LSIGN.EQ.'N') X = X - 1
            X1 = X + 1
            DO 43150, Z = BOZ1(N), BOZ2(N)
              DO 43160, Y = BOY1(N), BOY2(N)
                VTEMP = V(PXPY,X,Y,Z)
                V(PXPY,X,Y,Z) = RHO * V(PXNY,X1,Y,Z)
                V(PXNY,X1,Y,Z) = RHO * VTEMP
                VTEMP = V(PXPZ,X,Y,Z)
                V(PXPZ,X,Y,Z) = RHO * V(PXNZ,X1,Y,Z)
                V(PXNZ,X1,Y,Z) = RHO * VTEMP
43160         CONTINUE
43150       CONTINUE

          END IF

        ELSE IF (DIRN.EQ.'Y') THEN
          Y = BOY1(N)

          IF (LSIGN.EQ.'N'.AND.Y.EQ.1) THEN
            DO 43210, Z = BOZ1(N), BOZ2(N)
              DO 43220, X = BOX1(N), BOX2(N)
                V(PYNZ,X,Y,Z) = RHO * V(PYNZ,X,Y,Z)
                V(PYNX,X,Y,Z) = RHO * V(PYNX,X,Y,Z)
43220         CONTINUE
43210       CONTINUE

          ELSE IF (LSIGN.EQ.'P'.AND.Y.EQ.YMAX) THEN
            DO 43230, Z = BOZ1(N), BOZ2(N)
              DO 43240, X = BOX1(N), BOX2(N)
                V(PYPZ,X,Y,Z) = RHO * V(PYPZ,X,Y,Z)
                V(PYPX,X,Y,Z) = RHO * V(PYPX,X,Y,Z)
43240         CONTINUE
43230       CONTINUE

          ELSE
            IF (LSIGN.EQ.'N') Y = Y - 1
            Y1 = Y + 1
            DO 43250, Z = BOZ1(N), BOZ2(N)
              DO 43260, X = BOX1(N), BOX2(N)
                VTEMP = V(PYPZ,X,Y,Z)
                V(PYPZ,X,Y,Z) = RHO * V(PYNZ,X,Y1,Z)
                V(PYNZ,X,Y1,Z) = RHO * VTEMP
                VTEMP = V(PYPX,X,Y,Z)
                V(PYPX,X,Y,Z) = RHO * V(PYNX,X,Y1,Z)
                V(PYNX,X,Y1,Z) = RHO * VTEMP
43260         CONTINUE
43250       CONTINUE

          END IF

        ELSE IF (DIRN.EQ.'Z') THEN
          Z = BOZ1(N)

          IF (LSIGN.EQ.'N'.AND.Z.EQ.1) THEN
            DO 43310, Y = BOY1(N), BOY2(N)
              DO 43320, X = BOX1(N), BOX2(N)
                V(PZNX,X,Y,Z) = RHO * V(PZNX,X,Y,Z)
                V(PZNY,X,Y,Z) = RHO * V(PZNY,X,Y,Z)
43320         CONTINUE
43310       CONTINUE

          ELSE IF (LSIGN.EQ.'P'.AND.Z.EQ.ZMAX) THEN
            DO 43330, Y = BOY1(N), BOY2(N)
              DO 43340, X = BOX1(N), BOX2(N)
                V(PZPX,X,Y,Z) = RHO * V(PZPX,X,Y,Z)
                V(PZPY,X,Y,Z) = RHO * V(PZPY,X,Y,Z)
43340         CONTINUE
43330       CONTINUE

          ELSE
            IF (LSIGN.EQ.'N') Z = Z - 1
            Z1 = Z + 1
            DO 43350, Y = BOY1(N), BOY2(N)
              DO 43360, X = BOX1(N), BOX2(N)
                VTEMP = V(PZPX,X,Y,Z)
                V(PZPX,X,Y,Z) = RHO * V(PZNX,X,Y,Z1)
                V(PZNX,X,Y,Z1) = RHO * VTEMP
                VTEMP = V(PZPY,X,Y,Z)
                V(PZPY,X,Y,Z) = RHO * V(PZNY,X,Y,Z1)
                V(PZNY,X,Y,Z1) = RHO * VTEMP
43360         CONTINUE
43350       CONTINUE

          END IF

        ELSE
          STOP 'Boundary direction error'
        END IF

43010 CONTINUE

*---- connect

      DO 44010, Z = 1, ZMAX
        Z1 = Z + 1
        DO 44020, Y = 1, YMAX
          Y1 = Y + 1
          DO 44030, X = 1, XMAX
            X1 = X + 1
 
            IF (X.LT.XMAX) THEN
              V0 = V(PXPZ,X,Y,Z)
              V(PXPZ,X,Y,Z) = V(PXNZ,X1,Y,Z)
              V(PXNZ,X1,Y,Z) = V0
              V0 = V(PXPY,X,Y,Z)
              V(PXPY,X,Y,Z) = V(PXNY,X1,Y,Z)
              V(PXNY,X1,Y,Z) = V0
            END IF
 
            IF (Y.LT.YMAX) THEN
              V0 = V(PYPZ,X,Y,Z)
              V(PYPZ,X,Y,Z) = V(PYNZ,X,Y1,Z)
              V(PYNZ,X,Y1,Z) = V0
              V0 = V(PYPX,X,Y,Z)
              V(PYPX,X,Y,Z) = V(PYNX,X,Y1,Z)
              V(PYNX,X,Y1,Z) = V0
            END IF
 
            IF (Z.LT.ZMAX) THEN
              V0 = V(PZPY,X,Y,Z)
              V(PZPY,X,Y,Z) = V(PZNY,X,Y,Z1)
              V(PZNY,X,Y,Z1) = V0
              V0 = V(PZPX,X,Y,Z)
              V(PZPX,X,Y,Z) = V(PZNX,X,Y,Z1)
              V(PZNX,X,Y,Z1) = V0
            END IF
 
44030     CONTINUE
44020   CONTINUE
44010 CONTINUE

*---- end calculation

30010 CONTINUE

*---- close output file

      CLOSE(OUTUNT)
      WRITE(*,*) 'Output file closed'
      WRITE(*,*)
      END

J. L. Herring, 30 June 1996.