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.