c
c     Copyright (c) 1999,2000, Compaq Computer Corporation
c
c     See the file "license.terms" for information on usage and redistribution
c     of this file, and for a DISCLAIMER OF ALL WARRANTIES.
c
c     Avant! kindly provided the format of their Technology Interchange
c     Format (TIF) file.
c     Contact Avant! (http://www.avanticorp.com) for information on
c     purchase of their TCAD tools.
c
c   Subroutine to read TMA TIF (Tma Interchange Format) ascii files
c
c   Parser routines are patterned after those in parser.for
c
      subroutine read_tif(batchmode,read_error)
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'mesh.cmn'
      include 'data.cmn'
      include 'io.cmn'
      include 'plot.cmn'
c
c     read TMA TIF ASCII files
c
      logical batchmode, read_error
c
c     locals
      integer type
c
      call pm_determine_tif_filetype(type, read_error)
c
      if ( read_error ) goto 10000
c
      if( type .eq. 3 ) then
         call pm_read_tif_logfile(batchmode, read_error)
      else
         call pm_read_tif_file(batchmode, read_error)
      endif
c
      if ( read_error ) goto 10000
c
c     compute some stuff related to mesh...
c
c     set up boundary limits information
      call coord_limits
c
      call pm_load_tif_specific
c
      if( lfirst_read ) then
         lfirst_read = .FALSE.
         prev_plane_type = plane_type
         prev_binfilename = binfilename
         prev_binfiletype = binfiletype
      endif
      if( prev_binfiletype .ne. binfiletype .or. tif_1d_data ) then
         oned_lfirst = .TRUE.
         twod_lfirst = .TRUE.
         threed_lfirst = .TRUE.
      endif
      datafile_loaded = .TRUE.
c
10000 return
      end
c
      subroutine pm_read_tif_file(batchmode, read_error)
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'mesh.cmn'
      include 'data.cmn'
      include 'io.cmn'
      include 'plot.cmn'
      include 'bincodes.cmn'
c
c     read TIF ASCII file
c
      logical batchmode, read_error
c
c     locals
c
      integer i, j, ilen, ioerr, string_len,
     1        iline, idum(8), ibnd, ireg, itri, i1, ie, ierr, idop,
     2        nrecl, simtype
      real    rdum(NUM_DATA_ARRAYS)
      character*(PM_MAX_PATHLEN) expanded_name
      character*1024 buffer
      character*131  header
      character*1 ch, ch2
      logical ltif_old, lvalid_header
c
      write(luttyo,10)
10    format(' ','Reading TIF file...')
c
c     TIF file can write very long lines (up to Unix BUFSIZ=1024)
      nrecl=1024
      call pm_open_file(binfil, binfilename,
     1                  'OLD','FORMATTED','READ','FORTRAN','NONSHARED',
     2                  nrecl, ioerr, ierr)
      if( ierr .ne. 0 ) goto 10000
      datafile_record = 1
c
c     Read header
      read(binfil,100,end=10010,err=10010,iostat=ioerr) header
100   format(a)
c     Check for valid header
      call pm_decode_tif_header(header,lvalid_header,ltif_old,simtype)
      if( .NOT. lvalid_header ) goto 10020
c     If this is a (1d) log file, then return an error
c     This should never happen...
      if( simtype .eq. 3 ) then
         read_error = .TRUE.
         close(unit=binfil)
         return
      endif
c
c     get stem of binary file name
      call get_filestem(binfilename, binfilestem)
c
      do 51 j=1,NUM_DATA_ARRAYS
         in_binary_file(j) = .FALSE.
51    continue
c
c     Split up data storage into chunks
      call allocate_tri_arrays(ARR2DSIZE,NUM_DATA_ARRAYS,ierr)
      if( ierr .ne. 0 ) then
c        Failure during array allocation
         write(luttyo,10041)
         read_error = .TRUE.
         close(unit=binfil)
         return
      endif
c
c     Clear out arrays. Not really necessary.
      call zero_real_array(arrdat,ARR2DSIZE,NUM_DATA_ARRAYS)
c
      do i=1,MAX_REGIONS
         imat(i) = 0
      end do
      do i=1,MAX_TRI
         do j=1,3
           nop(j,i) = 0
         end do
      end do
c
      do i=1,ARR2DSIZE
        tri_matpt(i) = -1
      end do
c
      tri_npts = 0
      tri_ne   = 0
      tri_nreg = 0
      ibnd = 0
      ireg = 0
c
c     Note well: in SUPREM4 code, points, triangles, etc. are numbered
c     from 0..n-1, but in structure file, they are 1..n
c     We use 1..n numbering which is more natural for FORTRAN.
c     It is arbitrary in any case.
c
      iline = 1
200   read(binfil,100,err=10010,end=300,iostat=ioerr) buffer
         iline = iline + 1
c        Sometimes key character is in column 1, sometimes column 2
         ch  = buffer(1:1)
         ch2 = buffer(2:2)
         if( ch .eq. ' ' ) then
            ch = buffer(2:2)
            buffer(2:2) = ' '
            ch2 = buffer(3:3)
         else
            buffer(1:1) = ' '
         endif
         if( ch .eq. 'c' .and. ch2 .ne. 'd' ) then
c           Coordinates: c pointnum x y h
            read(buffer,*,err=10030,end=10030)
     1           idum(1), rdum(1), rdum(2)
c           Check for point overflow
            if( idum(1) .gt. ARR2DSIZE ) goto 10040
            cord(1,idum(1)) = MU2CM*rdum(1)
            cord(2,idum(1)) = MU2CM*rdum(2)
            tri_npts=tri_npts+1
         else if( ch .eq. 'e' ) then
c           Edges: e followed by 4 integers
c           Not used, skip
         else if( ch .eq. 'r' ) then
c           Regions: r regionnum mattyp
            call pm_fix_tif_r_line(buffer)
            read(buffer,*,err=10030,end=10030) idum(1), idum(2)
c           Check for region overflow
            if(idum(1) .le. 0 .or. idum(1) .gt. MAX_REGIONS) goto 10050
c           If this is a new region, save number of boundary points
c           in previous region.
            if( ireg .ne. 0 ) tri_nbndpts(ireg) = ibnd
            ireg = idum(1)
            imat(ireg) = idum(2)
            tri_nreg = tri_nreg + 1
            ibnd = 1
         else if( ch .eq. 'b' .and. ch2 .ne. 'i' ) then
c           Boundaries: b edgenum
c           NOTE WELL: I thought this was the boundary point number.
c           It appears to actually be the edge number.. as such
c           it is not useful yet.
            read(buffer,*,err=10030,end=10030) idum(1)
            if( ibnd .eq. 0 .or. ireg .eq. 0 ) goto 10060
CC Since this is not needed yet, avoid storing so we can look at larger files
CC            if( ibnd .gt. MAX_BOUNDPTS ) goto 10070
CC            tri_bndpts(ibnd,ireg) = idum(1)
            ibnd = ibnd + 1
         else if( ch .eq. 't' ) then
c           Triangles: t trinum regionnum pointi pointj pointk edge1 edge1 edge3
c           Mark is doing something funny, I think the edge codes are really
c           boundary (< 0) or neighbor triangle? (>0) information?
c           Note, in TMA TIF file, the triangle information is split onto
c           two lines. WHY, why, why...
c           HACK NO LONGER NEEDED in Medici 1.3. jvf
            read(buffer,*,err=10030,end=10030) (idum(i),i=1,8)
CC            read(binfil,100,err=10010,end=300,iostat=ioerr) buffer
CC            iline = iline + 1
CC            read(buffer,*,err=10030,end=10030) (idum(i),i=7,8)
            itri = idum(1)
c           Check for triangle store overflow
            if( itri .gt. MAX_TRI ) goto 10080
            tri2reg(itri) = idum(2)
            nop(1,itri) = idum(3)
            nop(2,itri) = idum(4)
            nop(3,itri) = idum(5)
            tri_nextel(1,itri) = idum(6)
            tri_nextel(2,itri) = idum(7)
            tri_nextel(3,itri) = idum(8)
            tri_ne = tri_ne + 1
         else if( ch .eq. 's' .and. ch2 .eq. 'i' ) then
c          'simpur' -- ignore for now
         else if( ch .eq. 's' ) then
c           solution: s quantity {list of impuritity numbers}
            call pm_parse_tif_s_line(buffer,tri_ndata,id2impur,
     1                               NUM_DATA_ARRAYS,ierr)
            if( ierr .ne. 0 ) goto 10030
            if( tri_ndata .gt. NUM_DATA_ARRAYS ) then
c              Limit number of variables to NUM_DATA_ARRAYS
               write(luttyo,10092) tri_ndata, NUM_DATA_ARRAYS
10092          format(' ','Warning: Number of quantities (',i5,
     1                ') exceeds internal storage'/
     2                ' ','         Limiting to first ',i5,' entries')
               tri_ndata = NUM_DATA_ARRAYS
            endif
         else if( ch .eq. 'n' ) then
c           node: n numpoint material {list of impurity values, 1..numimpur}
c           NOTE WELL: TIF can output multiple 'n' cards for the
c           same point (since we can have multiple values at a point
c           due to segregation at material boundaries). A workaround
c           is to make these duplicates into new points, and then scan
c           the triangle list later to point to these new points.
c           Fix up buffer because material in TIF format is a character
c           string. Change it to an integer.
            call pm_fix_tif_n_line(buffer)
            read(buffer,*,err=10030,end=10030) i1,idum(1),
     1          (rdum(i),i=1,tri_ndata)
c           "Old" versions of TIF need to adjust the node numbering
c           (numbering starts at 0,  rather than 1...)
            if( ltif_old ) i1 = i1 + 1
            if( i1 .le. 0 .or. i1 .gt. tri_npts ) goto 10100
c           Test for point already defined
            if( tri_matpt(i1) .eq. -1 ) then
               tri_matpt(i1) = idum(1)
               do i=1,tri_ndata
                  arrdat(i1+arrind(i)-1) = rdum(i)
               end do
            else
c              Create new "fake" point and adjust triangles
               if (tri_npts+1 .gt. ARR2DSIZE ) goto 10040
               tri_npts = tri_npts + 1
               cord(1,tri_npts) = cord(1,i1)
               cord(2,tri_npts) = cord(2,i1)
               tri_matpt(tri_npts) = idum(1)
               do i=1,tri_ndata
                  arrdat(tri_npts+arrind(i)-1) = rdum(i)
               end do
               do ie=1,tri_ne
                  if( imat(tri2reg(ie)) .eq. idum(1) ) then
                     do j=1,3
                       if( nop(j,ie) .eq. i1 ) nop(j,ie) = tri_npts
                     end do
                  endif
               end do
            endif
         else if( ch .eq. 'M' ) then
c           Material information, ignore
         else
c           TIF ignores other lines, so we do the same
         endif
      goto 200
300   continue
c
c     set up adjacency information, what plots (if any) need this?
c     Adjacency info takes a lot of memory
c     call nxtel(p2t,p2tc)
c
c     Set placeholder values for old grid info (probably not needed)
      nx = 1
      ny = 1
      nt = ny
      nyoxm = 0
      nytot= ny
      nxsp = 1
      nxsoxm = 1
      plane_index = 1
      prev_plane_type = plane_type
      plane_type = XY_PLANE
      xyz(1,3) = -xw/2.0
      nxy=nx*ny
      nxytot=nx*nytot
c
c     Load generic mesh pointers, depending on plane type
c
      call set_3d_index_limits
      cut_plane_axis = charb
c     This variable must be set by all read routines...
      data_is_trigrid = .TRUE.
c
c     If SUPREM simulation, compute net doping, if it isn't already read in
      if( simtype .eq. 1 ) then
         idop = 0
         do i=1,tri_ndata
c           ID=1 -> net doping
            if( id2impur(i) .eq. 1 ) idop = i
         end do
         if( idop .eq. 0 ) then
            tri_ndata = tri_ndata + 1
            if( tri_ndata .gt. NUM_DATA_ARRAYS ) goto 10090
            id2impur(tri_ndata) = -1 ! Our code for net doping
            do i=1,tri_npts
               arrdat(i+arrind(tri_ndata)-1) = 0.0
            end do
c
            do i=1,tri_npts
c              Scan impurities: 10=As, 11=P, 12=Sb, 13=B
               do j=1,tri_ndata
                  if( id2impur(j) .eq. 10 .or. id2impur(j) .eq. 11 .or.
     1                id2impur(j) .eq. 12 ) then
                     arrdat(i+arrind(tri_ndata)-1)=
     1               arrdat(i+arrind(tri_ndata)-1)+arrdat(i+arrind(j)-1)
                  else if( id2impur(j) .eq. 13 ) then
                     arrdat(i+arrind(tri_ndata)-1)=
     1               arrdat(i+arrind(tri_ndata)-1)-arrdat(i+arrind(j)-1)
                  endif
               end do
            end do
         endif
      endif
c
      do i=1,tri_ndata
         in_binary_file(i) = .TRUE.
      end do
c
      tif_1d_data = .FALSE.
c
      write(luttyo,110)
110   format(' ','...done')
      read_error = .FALSE.
      close(unit=binfil)
      goto 10200
c
c     errors of commission/omission
c
c     I/O error on open of file
10000 continue
      call expand_filename(binfilename,expanded_name)
      ilen = string_len(expanded_name)
      write(luttyo,10001) ioerr, expanded_name(1:ilen)
10001 format(/' ','FORTRAN I/O error #',i5,' on open of tif file:'/
     1       ' ',a)
      write(luttyo,10002)
10002 format(' ','Check for these errors:'/
     1       ' ','   - Incorrect file, directory or disk name'/
     1       ' ','   - You must have read permission on the file'/)
      read_error = .TRUE.  ! go back and get new name...
      goto 10200
c
c     I/O error on read of file
10010 write(luttyo,10011) ioerr, iline
10011 format(/' ','FORTRAN I/O error #',i5,' on read of file at line',
     1      i10)
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10020 continue
      write(luttyo,10021)
10021 format(' ','Error: Invalid header in TIF file')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10030 ilen=string_len(buffer)
      buffer(1:1) = ch
      write(luttyo,10031) ioerr, iline, buffer(1:ilen)
10031 format(/' ','FORTRAN I/O error #',i5,' on read of file at line',
     1      i10/' ','Invalid or insufficient data on line:'/
     2      ' ',a)
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10040 continue
      write(luttyo,10041)
10041 format(' ','Error: Number of points exceeds internal storage')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10050 continue
      write(luttyo,10051)
10051 format(' ','Error: Number of regions exceeds internal storage')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10060 continue
      write(luttyo,10061)
10061 format(' ','Error: boundary information before region defined')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10070 continue
      write(luttyo,10071)
10071 format(' ','Error: Number of boundary pts exceeds internal ',
     1           'storage')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10080 continue
      write(luttyo,10081)
10081 format(' ','Error: Number of triangles exceeds internal storage')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10090 continue
      write(luttyo,10091)
10091 format(' ','Error: Number of quantities exceeds internal storage')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10100 continue
      write(luttyo,10101) iline
10101 format(' ','Error: Invalid point number at line:',i10)
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10200 continue
      return
      end
c
      subroutine pm_load_tif_specific
      implicit none
c
c     Load descriptive arrays with TIF specific data
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'data.cmn'
c
c     Data varies linear or logarithmic
      logical LOG, LIN
      parameter (LOG = .TRUE., LIN = .FALSE.)
c     Data has value in oxide, or not
      logical OX, NO_OX
      parameter (OX = .TRUE., NO_OX = .FALSE.)
c     Data jumps at oxide interfaces
      logical JUMP, NO_JUMP
      parameter (JUMP = .TRUE., NO_JUMP = .FALSE.)
c     Data is 1D or 2D
      logical ONED, TWOD
      parameter (ONED = .TRUE., TWOD = .FALSE.)
c
      integer i, j
      character*35 eltype
      character*20 nickname
      character*10 ext
      integer ilen1, ilen2, string_len
c
      if( tif_1d_data ) then
c        TIF IV LOG FILE
         max_menu_num = 1
c        (2D) array of net doping, not applicable.
         net_dop_array_index = 0
c        File has only 1D data
         three_d = .FALSE.
c
         nickname = tif_names(tif_iycol)
         call upcase(nickname)
         ilen1 = string_len(tif_units(tif_ixcol))
         ilen2 = string_len(tif_units(tif_iycol))
         call load_desc_arr(1, tif_names(tif_iycol), nickname,
     1      tif_units(tif_iycol) ,
     1      tif_units(tif_iycol)(1:ilen2) // 
     1         tif_units(tif_ixcol)(1:ilen1),
     1      tif_units(tif_iycol)(1:ilen2) //
     1         tif_units(tif_ixcol)(1:ilen2) // '^{2}',
     1      '.dat', LIN,OX,NO_JUMP,ONED,1)
         return
      endif
c
c     Number of menu items
      max_menu_num = tri_ndata
c
c     Find (2D) array of net doping
      do i=1,tri_ndata
         if( id2impur(i) .eq. 1 .or. id2impur(i) .eq. -1 ) then
            net_dop_array_index = i
         endif
      end do
c     File has only 2D data
      three_d = .FALSE.
c
      j=1
      do i=1,tri_ndata
         if( id2impur(i) .eq. 1 ) then
            eltype = 'Net doping'
            ext = '.net'
            nickname = 'NET_DOPING'
c           Array index of net doping
            net_dop_array_index = j
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         else if( id2impur(i) .eq. 2 ) then
            eltype = 'Total doping'
            ext = '.totdop'
            nickname = 'TOTAL_DOPING'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 3  ) then
            eltype = 'Donors'
            ext = '.donor'
            nickname = 'DONORS'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 4  ) then
            eltype = 'Acceptors'
            ext = '.acceptor'
            nickname = 'ACCEPTORS'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 5  ) then
            eltype = 'Potential'
            ext = '.pot'
            nickname = 'POTENTIAL'
            call load_desc_arr(j, eltype, nickname,
     1                        'V','V cm','V cm^{2}',ext,
     2                         LIN,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 6 .or. id2impur(i) .eq. 7 ) then
            if ( id2impur(i) .eq. 6 ) then
               eltype = 'Electron concentration'
               ext = '.elec'
               nickname = 'ELECTRONS'
            else
               eltype = 'Hole Concentration'
               ext = '.holes'
               nickname = 'HOLES'
            endif
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .ge. 8 .and. id2impur(i) .le. 15 ) then
            if ( id2impur(i) .eq. 8 ) then
               eltype = 'Vacancies'
               ext = '.vac'
               nickname = 'VACANCIES'
            else if ( id2impur(i) .eq. 9 ) then
               eltype = 'Interstitials'
               ext = '.int'
               nickname = 'INTERSTITIALS'
            else if ( id2impur(i) .eq. 10 ) then
               eltype = 'Chem. Arsenic concentration'
               ext = '.ch_as_conc'
               nickname = 'AS_CHEM'
            else if ( id2impur(i) .eq. 11 ) then
               eltype = 'Chem. Phosphorous Concentration'
               ext = '.ch_p_conc'
               nickname = 'P_CHEM'
            else if ( id2impur(i) .eq. 12 ) then
               eltype = 'Chem. Antimony Concentration'
               ext = '.ch_sb_conc'
               nickname = 'SB_CHEM'
            else if ( id2impur(i) .eq. 13 ) then
               eltype = 'Chem. Boron Concentration'
               ext = '.ch_b_conc'
               nickname = 'B_CHEM'
            else if ( id2impur(i) .eq. 14 ) then
               eltype = 'Steady st. Vacancies'
               ext = '.vac_s'
               nickname = 'VACANCIES_SS'
            else if ( id2impur(i) .eq. 15 ) then
               eltype = 'Steady st. Interstitials'
               ext = '.int_s'
               nickname = 'INTERSTITIAL_SS'
            endif
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 16 ) then
            eltype = 'X velocity'
            ext = '.xvel'
            nickname = 'XVELOCITY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm/s','cm^{2}/s','cm^{3}/s',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 17 ) then
            eltype = 'Y velocity'
            ext = '.yvel'
            nickname = 'YVELOCITY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm/s','cm^{2}/s','cm^{3}/s',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 18 ) then
            eltype = 'O2 Concentration'
            ext = '.o2'
            nickname = 'O2'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 19 ) then
            eltype = 'H2O Concentration'
            ext = '.h2O'
            nickname = 'H2O'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 20 ) then
            eltype = 'Trap Concentration'
            ext = '.traps'
            nickname = 'TRAPS'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .ge. 21 .and. id2impur(i) .le. 23 ) then
            if( id2impur(i) .eq. 21 ) then
               eltype = 'Sxx'
               ext = '.sxx'
               nickname = 'SXX'
            else if( id2impur(i) .eq. 22 ) then
               eltype = 'Syy'
               ext = '.syy'
               nickname = 'SYY'
            else
               eltype = 'Sxy'
               ext = '.sxy'
               nickname = 'SXY'
            endif
            call load_desc_arr(j, eltype, nickname,
     1                        'dyne/cm^{2}','dyne/cm','dyne',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .ge. 24 .and. id2impur(i) .le. 27 ) then
            if( id2impur(i) .eq. 24 ) then
               eltype = 'Active Arsenic Concentration'
               ext = '.as_conc'
               nickname = 'AS'
            else if( id2impur(i) .eq. 22 ) then
               eltype = 'Active Phosphorous Concentration'
               ext = '.p_conc'
               nickname = 'P'
            else if( id2impur(i) .eq. 23 ) then
               eltype = 'Active Antimony Concentration'
               ext = '.sb_conc'
               nickname = 'SB'
            else
               eltype = 'Active Boron Concentration'
               ext = '.b_conc'
               nickname = 'B'
            endif
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 28 ) then
            eltype = 'N quasi-Fermi level'
            ext = '.qfn'
            nickname = 'QFN'
            call load_desc_arr(j, eltype, nickname,
     1                        'V','V cm','V cm^{2}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 29 ) then
            eltype = 'P quasi-Fermi level'
            ext = '.qfp'
            nickname = 'QFP'
            call load_desc_arr(j, eltype, nickname,
     1                        'V','V cm','V cm^{2}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 30 ) then
            eltype = 'Photo generation rate'
            ext = '.photo'
            nickname = 'PHOTOGEN'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 31 ) then
            eltype = 'Impact ionization rate'
            ext = '.avl'
            nickname = 'AVL'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3} s^{-1}','cm^{-2} s^{-1})',
     2                        'cm^{-1} s^{-1})',
     3                         ext,LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 32 ) then
            eltype = 'Recombination rate'
            ext = '.rec'
            nickname = 'RECOMBIN'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3} s^{-1}','cm^{-2} s^{-1})',
     2                        'cm^{-1} s^{-1})',
     3                         ext,LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 33 ) then
            eltype = 'J \dot E'
            ext = '.je'
            nickname = 'J_DOT_E'
            call load_desc_arr(j, eltype, nickname,
     1                        'W cm^{-3}','W cm^{-2}','W cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 34 ) then
            eltype = 'Flowlines'
            ext = '.flow'
            nickname = 'FLOWLINES'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ','cm','cm^{2}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 35 ) then
            eltype = 'Lattice temp'
            ext = '.tl'
            nickname = 'TL'
            call load_desc_arr(j, eltype, nickname,
     1                        'K','K cm','K cm^{2}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 36 ) then
            eltype = 'Electron temp'
            ext = '.tn'
            nickname = 'TN'
            call load_desc_arr(j, eltype, nickname,
     1                        'K','K cm','K cm^{2}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 37 ) then
            eltype = 'Hole temp'
            ext = '.tp'
            nickname = 'TP'
            call load_desc_arr(j, eltype, nickname,
     1                        'K','K cm','K cm^{2}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 38 ) then
            eltype = 'Mag. electron current'
            ext = '.jmag_e'
            nickname = 'JMAG_N'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 39 ) then
            eltype = 'Electron current (x-comp)'
            ext = '.jx_e'
            nickname = 'JX_N'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 40 ) then
            eltype = 'Electron current (y-comp)'
            ext = '.jy_e'
            nickname = 'JY_N'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 41 ) then
            eltype = 'Mag. hole current'
            ext = '.jmag_h'
            nickname = 'JMAG_H'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 42 ) then
            eltype = 'Hole current (x-comp)'
            ext = '.jx_h'
            nickname = 'JX_P'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 43 ) then
            eltype = 'Hole current (y-comp)'
            ext = '.jy_h'
            nickname = 'JY_P'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 44 ) then
            eltype = 'Mag. total current'
            ext = '.jmag_t'
            nickname = 'JMAG_T'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 45 ) then
            eltype = 'Total current (x-comp)'
            ext = '.jx_t'
            nickname = 'JX_T'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 46 ) then
            eltype = 'Total current (y-comp)'
            ext = '.jy_t'
            nickname = 'JY_T'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm^{2}','A/cm','A',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 47 ) then
            eltype = 'Mag. electric field'
            ext = '.emag'
            nickname = 'EMAG'
            call load_desc_arr(j, eltype, nickname,
     1                        'V/cm','V','V cm',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 48 ) then
            eltype = 'Electric field (x-comp)'
            ext = '.ex'
            nickname = 'EX'
            call load_desc_arr(j, eltype, nickname,
     1                        'V/cm','V','V cm',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 49 ) then
            eltype = 'Electric field (y-comp)'
            ext = '.ey'
            nickname = 'EY'
            call load_desc_arr(j, eltype, nickname,
     1                        'V/cm','V','V cm',ext,
     2                         LOG,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 50 ) then
            eltype = 'Band-to-band generation'
            ext = '.bbg'
            nickname = 'BBGEN'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}/s','cm^{-2}/s','cm/s',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 51 ) then
            eltype = 'Valence band'
            ext = '.vband'
            nickname = 'VBAND'
            call load_desc_arr(j, eltype, nickname,
     1                        'V','V cm','V cm^{-2}',ext,
     2                         LIN,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 52 ) then
            eltype = 'Conduction band'
            ext = '.cband'
            nickname = 'CBAND'
            call load_desc_arr(j, eltype, nickname,
     1                        'V','V cm','V cm^{-2}',ext,
     2                         LIN,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 53 ) then
            eltype = 'Vacuum level'
            ext = '.vaclevel'
            nickname = 'VACLEVEL'
            call load_desc_arr(j, eltype, nickname,
     1                        'V','V cm','V cm^{-2}',ext,
     2                         LIN,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 54 ) then
            eltype = 'Net carriers'
            ext = '.ncarr'
            nickname = 'NET_CARR'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 55 ) then
            eltype = 'Net charge'
            ext = '.ncharge'
            nickname = 'NET_CHARGE'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 56 ) then
            eltype = 'Electron velocity (mag)'
            ext = '.vnm'
            nickname = 'ELEC_VELOCITY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm/s','cm^{2}/s','cm^{3}/s',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 57 ) then
            eltype = 'Electron x velocity'
            ext = '.vnx'
            nickname = 'ELEC_X_VELOCITY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm/s','cm^{2}/s','cm^{3}/s',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 58 ) then
            eltype = 'Electron y velocity'
            ext = '.vny'
            nickname = 'ELEC_Y_VELOCITY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm/s','cm^{2}/s','cm^{3}/s',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 59 ) then
            eltype = 'Hole velocity (mag)'
            ext = '.vpm'
            nickname = 'HOLE_VELOCITY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm/s','cm^{2}/s','cm^{3}/s',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 60 ) then
            eltype = 'Hole x velocity'
            ext = '.vpx'
            nickname = 'HOLE_X_VELOCITY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm/s','cm^{2}/s','cm^{3}/s',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 61 ) then
            eltype = 'Hole y velocity'
            ext = '.vpy'
            nickname = 'HOLE_Y_VELOCITY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm/s','cm^{2}/s','cm^{3}/s',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 62 ) then
            eltype = 'Electron Inject. Probability'
            ext = '.ggamn'
            nickname = 'ELEC_INJ_PROB'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ','cm','cm^{2}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 63 ) then
            eltype = 'Hole Inject. Probability'
            ext = '.ggamp'
            nickname = 'HOLE_INJ_PROB'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ','cm','cm^{2}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 64 ) then
            eltype = 'Total Inject. Probability'
            ext = '.ggamt'
            nickname = 'TOTAL_INJ_PROB'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ','cm','cm^{2}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 65 ) then
            eltype = 'Electron Inject. Current'
            ext = '.gin'
            nickname = 'ELEC_INJ_CURR'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm','A','A cm',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 66 ) then
            eltype = 'Hole Inject. Current'
            ext = '.gip'
            nickname = 'HOLE_INJ_CURR'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm','A','A cm',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 67 ) then
            eltype = 'Total Inject. Current'
            ext = '.git'
            nickname = 'TOTAL_INJ_CURR'
            call load_desc_arr(j, eltype, nickname,
     1                        'A/cm','A','A cm',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 68 ) then
            eltype = 'Mole fraction'
            ext = '.xmole'
            nickname = 'MOLE_FRACTION'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ','cm','cm^{2}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 69 ) then
            eltype = 'User defined one'
            ext = '.user1'
            nickname = 'USER1'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ','cm','cm^{2}',ext,
     2                         LIN,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 70 ) then
            eltype = 'User defined two'
            ext = '.user2'
            nickname = 'USER2'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ','cm','cm^{2}',ext,
     2                         LIN,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 71 ) then
            eltype = 'User defined three'
            ext = '.user3'
            nickname = 'USER3'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ','cm','cm^{2}',ext,
     2                         LIN,OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 72 ) then
            eltype = 'Grain size'
            ext = '.lgrain'
            nickname = 'LGRAIN'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm','cm^{2}','cm^{3}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 73 ) then
            eltype = 'Grain orientation'
            ext = '.gorient'
            nickname = 'GORIENT'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm','cm^{2}','cm^{3}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 74 ) then
            eltype = 'T Poly'
            ext = '.tpoly'
            nickname = 'TPOLY'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm','cm^{2}','cm^{3}',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 75 ) then
            eltype = 'Grain Boundary Boron'
            ext = '.gb_boron'
            nickname = 'GB_BORON'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 76 ) then
            eltype = 'Grain Boundary Arsenic'
            ext = '.gb_arsenic'
            nickname = 'GB_ARSENIC'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 77 ) then
            eltype = 'Grain Boundary Phosphorus'
            ext = '.gb_phos'
            nickname = 'GB_PHOS'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 78 ) then
            eltype = 'Clustered Interstitials'
            ext = '.int_clust'
            nickname = 'INTERSTITIAL_CLUSTER'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 79 ) then
            eltype = 'N-type'
            ext = '.ntype'
            nickname = 'N_TYPE'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         elseif( id2impur(i) .eq. 80 ) then
            eltype = 'P-type'
            ext = '.ptype'
            nickname = 'P_TYPE'
            call load_desc_arr(j, eltype, nickname,
     1                        'cm^{-3}','cm^{-2}','cm^{-1}',ext,
     2                         LOG,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         else
            write(eltype,100) id2impur(i)
100         format('TIF ID number ',i5)
            if( id2impur(i) .lt. 10 ) then
               write(nickname,101) id2impur(i)
101            format('TIF_ID_',i1)
            elseif( id2impur(i) .lt. 100) then
               write(nickname,102) id2impur(i)
102            format('TIF_ID_',i2)
            else
               write(nickname,103) id2impur(i)
103            format('TIF_ID_',i3)
            endif
            ext = '.unknown'
            call load_desc_arr(j, eltype, nickname,
     1                        ' ',' ',' ',ext,
     2                         LIN,NO_OX,NO_JUMP,TWOD,j)
            j = j + 1
         endif
      end do
c
      return
      end
c
      subroutine pm_fix_tif_n_line(buffer)
      implicit none
      character*(*) buffer
c
      integer ilen, i, istart, iend
      ilen = LEN(buffer)
c
c     Skip initial white space
      i = 1
      do while( buffer(i:i) .eq. ' ' .and. i .lt. ilen )
        i = i + 1
      end do
c
c     Skip point number
      do while( buffer(i:i) .ne. ' ' .and. i .lt. ilen )
        i = i + 1
      end do
c
c     Skip white space
      do while( buffer(i:i) .eq. ' ' .and. i .lt. ilen )
        i = i + 1
      end do
c
      istart = i
      do while( buffer(i:i) .ne. ' ' .and. i .lt. ilen )
         i = i + 1
      end do
      iend = i
      if( buffer(istart:iend) .eq. 'Si' ) then
         buffer(istart:iend) = '1'
      else if( buffer(istart:iend) .eq. 'Ox' ) then
         buffer(istart:iend) = '-1'
      else if( buffer(istart:iend) .eq. 'Nit' ) then
         buffer(istart:iend) = '-2'
      else if( buffer(istart:iend) .eq. 'Poly' ) then
         buffer(istart:iend) = '-5'
      else if( buffer(istart:iend) .eq. 'Al' ) then
         buffer(istart:iend) = '-5'
      else if( buffer(istart:iend) .eq. 'Elec' ) then
         buffer(istart:iend) = '-5'
      else if( buffer(istart:iend) .eq. 'GaAs' ) then
         buffer(istart:iend) = '2'
      else if( buffer(istart:iend) .eq. 'Semi' ) then
         buffer(istart:iend) = '4'
      else if( buffer(istart:iend) .eq. 'SiGe' ) then
         buffer(istart:iend) = '5'
      else if( buffer(istart:iend) .eq. 'AlGaAs' ) then
         buffer(istart:iend) = '6'
      else if( buffer(istart:iend) .eq. 'Ge' ) then
         buffer(istart:iend) = '7'
      else if( buffer(istart:iend) .eq. 'SiC' ) then
         buffer(istart:iend) = '8'
      else if( buffer(istart:iend) .eq. 'Sapph' ) then
         buffer(istart:iend) = '-3'
      else if( buffer(istart:iend) .eq. 'Insul' ) then
         buffer(istart:iend) = '-4'
      else if( buffer(istart:iend) .eq. 'OxyNit' ) then
         buffer(istart:iend) = '-4'
      else if( buffer(istart:iend) .eq. 'Photo' ) then
         buffer(istart:iend) = '-4'
      else if( buffer(istart:iend) .eq. 'Ambient' ) then
         buffer(istart:iend) = '-4'
      else
c        Punt
         buffer(istart:iend) = '1'
      endif
c
      return
      end
c
      subroutine pm_fix_tif_r_line(buffer)
      implicit none
      character*(*) buffer
c
      integer ilen, i, istart, iend
      ilen = LEN(buffer)
c
c     Skip initial white space
      i = 1
      do while( buffer(i:i) .eq. ' ' .and. i .lt. ilen )
        i = i + 1
      end do
c
c     Skip region number
      do while( buffer(i:i) .ne. ' ' .and. i .lt. ilen )
        i = i + 1
      end do
c
c     Skip white space
      do while( buffer(i:i) .eq. ' ' .and. i .lt. ilen )
        i = i + 1
      end do
c
c     Replace material name with a numeric value
      istart = i
      do while( buffer(i:i) .ne. ' ' .and. i .lt. ilen )
         i = i + 1
      end do
      iend = i
      if( buffer(istart:iend) .eq. 'Si' ) then
         buffer(istart:iend) = '1'
      else if( buffer(istart:iend) .eq. 'Ox' ) then
         buffer(istart:iend) = '-1'
      else if( buffer(istart:iend) .eq. 'Nit' ) then
         buffer(istart:iend) = '-2'
      else if( buffer(istart:iend) .eq. 'Poly' ) then
         buffer(istart:iend) = '3'
      else if( buffer(istart:iend) .eq. 'Al' ) then
         buffer(istart:iend) = '-5'
      else if( buffer(istart:iend) .eq. 'Elec' ) then
         buffer(istart:iend) = '-5'
      else if( buffer(istart:iend) .eq. 'GaAs' ) then
         buffer(istart:iend) = '2'
      else if( buffer(istart:iend) .eq. 'Semi' ) then
         buffer(istart:iend) = '4'
      else if( buffer(istart:iend) .eq. 'SiGe' ) then
         buffer(istart:iend) = '5'
      else if( buffer(istart:iend) .eq. 'AlGaAs' ) then
         buffer(istart:iend) = '6'
      else if( buffer(istart:iend) .eq. 'Ge' ) then
         buffer(istart:iend) = '7'
      else if( buffer(istart:iend) .eq. 'SiC' ) then
         buffer(istart:iend) = '8'
      else if( buffer(istart:iend) .eq. 'Sapph' ) then
         buffer(istart:iend) = '-3'
      else if( buffer(istart:iend) .eq. 'Insul' ) then
         buffer(istart:iend) = '-4'
      else if( buffer(istart:iend) .eq. 'OxyNit' ) then
         buffer(istart:iend) = '-4'
      else if( buffer(istart:iend) .eq. 'Photo' ) then
         buffer(istart:iend) = '-4'
      else if( buffer(istart:iend) .eq. 'Ambient' ) then
         buffer(istart:iend) = '-4'
      else
c        Punt
         buffer(istart:iend) = '1'
      endif
c
      return
      end
c
      subroutine pm_parse_tif_s_line(buffer, ndata, id2impur,
     1                               impur_size, ierr)
      implicit none

      integer ndata, impur_size, id2impur(impur_size)
      character*(*) buffer
      integer ierr
c
      character*50 key
      integer i, ipos, imax
c
      ierr = 0
      ipos = 1
      imax = 81 ! this should be equal to number of known quantities + 1
      call get_keyword(buffer,key,ipos)
      if( ipos .eq. 0 ) goto 1000
      read(key,*,end=1000,err=1000) ndata
c
      do i=1,MIN(ndata,impur_size)
         call get_keyword(buffer,key,ipos)
         if( ipos .eq. 0 ) goto 1000
         if( key .eq. 'Net' ) then
            id2impur(i) = 1
         else if( key .eq. 'Total' ) then
            id2impur(i) = 2
         else if( key .eq. 'Donor' ) then
            id2impur(i) = 3
         else if( key .eq. 'Accept' ) then
            id2impur(i) = 4
         else if( key .eq. 'v' ) then
            id2impur(i) = 5
         else if( key .eq. 'n' ) then
            id2impur(i) = 6
         else if( key .eq. 'p' ) then
            id2impur(i) = 7
         else if( key .eq. 'Vac' ) then
            id2impur(i) = 8
         else if( key .eq. 'Inter' ) then
            id2impur(i) = 9
         else if( key .eq. 'As' ) then
            id2impur(i) = 10
         else if( key .eq. 'P' ) then
            id2impur(i) = 11
         else if( key .eq. 'Sb' ) then
            id2impur(i) = 12
         else if( key .eq. 'B' ) then
            id2impur(i) = 13
         else if( key .eq. 'Vac_s' ) then
            id2impur(i) = 14 ! Vacancy_Steady
         else if( key .eq. 'Inter_s' ) then
            id2impur(i) = 15 ! Interstitial_Steady
         else if( key .eq. 'Xvel' ) then
            id2impur(i) = 16
         else if( key .eq. 'Yvel' ) then
            id2impur(i) = 17
         else if( key .eq. 'O2' ) then
            id2impur(i) = 18
         else if( key .eq. 'H2O' ) then
            id2impur(i) = 19
         else if( key .eq. 'T' ) then
            id2impur(i) = 20 ! Traps
         else if( key .eq. 'Sxx' ) then
            id2impur(i) = 21
         else if( key .eq. 'Syy' ) then
            id2impur(i) = 22
         else if( key .eq. 'Sxy' ) then
            id2impur(i) = 23
         else if( key .eq. 'Asa' ) then
            id2impur(i) = 24 ! Arsenic_Active
         else if( key .eq. 'Pa' ) then
            id2impur(i) = 25 ! Phosphorus_Active
         else if( key .eq. 'Sba' ) then
            id2impur(i) = 26 ! Antimony_Active
         else if( key .eq. 'Ba' ) then
            id2impur(i) = 27 ! Boron_Active
         else if( key .eq. 'qfn' ) then
            id2impur(i) = 28 ! n-quasiFermi level
         else if( key .eq. 'qfp' ) then
            id2impur(i) = 29 ! p-quasiFermi level
         else if( key .eq. 'photogen' ) then
            id2impur(i) = 30 ! photogeneration rate
         else if( key .eq. 'ii.gener' ) then
            id2impur(i) = 31 ! impact ionization rate
         else if( key .eq. 'recombin' ) then
            id2impur(i) = 32 ! recombination rate
         else if( key .eq. 'j.efield' ) then
            id2impur(i) = 33 ! J dot E
         else if( key .eq. 'flowline' ) then
            id2impur(i) = 34 ! flowlines
         else if( key .eq. 'tl' ) then
            id2impur(i) = 35 ! lattice temp
         else if( key .eq. 'tn' ) then
            id2impur(i) = 36 ! electron temp
         else if( key .eq. 'tp' ) then
            id2impur(i) = 37 ! hole temp
         else if( key .eq. 'jnm' ) then
            id2impur(i) = 38 ! |jn|
         else if( key .eq. 'jnx' ) then
            id2impur(i) = 39 ! jn_x
         else if( key .eq. 'jny' ) then
            id2impur(i) = 40 ! jn_y
         else if( key .eq. 'jpm' ) then
            id2impur(i) = 41 ! |jp|
         else if( key .eq. 'jpx' ) then
            id2impur(i) = 42 ! jp_x
         else if( key .eq. 'jpy' ) then
            id2impur(i) = 43 ! jp_y
         else if( key .eq. 'jtm' ) then
            id2impur(i) = 44 ! |jt|
         else if( key .eq. 'jtx' ) then
            id2impur(i) = 45 ! jt_x
         else if( key .eq. 'jty' ) then
            id2impur(i) = 46 ! jt_y
         else if( key .eq. 'em' ) then
            id2impur(i) = 47 ! |E|
         else if( key .eq. 'ex' ) then
            id2impur(i) = 48 ! E_x
         else if( key .eq. 'ey' ) then
            id2impur(i) = 49 ! E_y
         else if( key .eq. 'bb.gener' ) then
            id2impur(i) = 50 ! band-to-band generation rate
         else if( key .eq. 'valenc.b' ) then
            id2impur(i) = 51 ! valence band
         else if( key .eq. 'conduc.b' ) then
            id2impur(i) = 52 ! valence band
         else if( key .eq. 'vacuum' ) then
            id2impur(i) = 53 ! vacuum level
         else if( key .eq. 'net.carr' ) then
            id2impur(i) = 54 ! net carriers
         else if( key .eq. 'net.char' ) then
            id2impur(i) = 55 ! net charge
         else if( key .eq. 'vnm' ) then
            id2impur(i) = 56 ! Electron velocity (mag)
         else if( key .eq. 'vnx' ) then
            id2impur(i) = 57 ! Electron x velocity
         else if( key .eq. 'vny' ) then
            id2impur(i) = 58 ! Electron y velocity
         else if( key .eq. 'vpm' ) then
            id2impur(i) = 59 ! Hole velocity (mag)
         else if( key .eq. 'vpx' ) then
            id2impur(i) = 60 ! Hole n velocity
         else if( key .eq. 'vpy' ) then
            id2impur(i) = 61 ! Hole y velocity
         else if( key .eq. 'g.gamn' ) then
            id2impur(i) = 62 ! electron injection probability
         else if( key .eq. 'g.gamp' ) then
            id2impur(i) = 63 ! hole injection probability
         else if( key .eq. 'g.gamt' ) then
            id2impur(i) = 64 ! total injection probability
         else if( key .eq. 'g.in' ) then
            id2impur(i) = 65 ! electron injection current
         else if( key .eq. 'g.ip' ) then
            id2impur(i) = 66 ! hole injection current
         else if( key .eq. 'g.it' ) then
            id2impur(i) = 67 ! total injection current
         else if( key .eq. 'x.mole' ) then
            id2impur(i) = 68 ! mole fraction
         else if( key .eq. 'array1' ) then
            id2impur(i) = 69 ! User defined array 1
         else if( key .eq. 'array2' ) then
            id2impur(i) = 70 ! User defined array 2
         else if( key .eq. 'array3' ) then
            id2impur(i) = 71 ! User defined array 3
         else if( key .eq. 'LGrain' ) then
            id2impur(i) = 72 ! 
         else if( key .eq. 'GOrient' ) then
            id2impur(i) = 73 ! 
         else if( key .eq. 'TPoly' ) then
            id2impur(i) = 74 ! 
         else if( key .eq. 'gbB' ) then
            id2impur(i) = 75 ! 
         else if( key .eq. 'gbAs' ) then
            id2impur(i) = 76 ! 
         else if( key .eq. 'gbP' ) then
            id2impur(i) = 77 ! 
         else if( key .eq. 'Inter_cl' ) then
            id2impur(i) = 78 ! 
         else if( key .eq. 'N-type' ) then
            id2impur(i) = 79 ! n-type dopant
         else if( key .eq. 'P-type' ) then
            id2impur(i) = 80 ! p-type dopant
         else
c           If you add more quantities, then bump up imax above
            id2impur(i) = imax
            imax = imax + 1
         endif
      end do
c
      return
c
1000  continue
      ierr = 1
      return
      end
c
      subroutine pm_decode_tif_header(header,lvalid_header,ltif_old,
     1                                simtype)
      implicit none
c
      character*(*) header
      logical lvalid_header, ltif_old
      integer simtype
c
c     Check header for validity. Also distinguish TIF version
c
      integer ipos
      character*50 key
c
      lvalid_header = .TRUE.
c
      ipos = 1
c     Skip initial 'h'
      call get_keyword(header,key,ipos)
      if( ipos .eq. 0 .or. key .ne. 'h' ) goto 1000
c
c     Get next token
      call get_keyword(header,key,ipos)
      if( ipos .eq. 0 ) goto 1000
      if( key .eq. 'TMA' ) then
c        "Old" TIF format
         ltif_old = .TRUE.
c        Next token is simulator name
         call get_keyword(header,key,ipos)
         if( ipos .eq. 0 ) goto 1000
         if( key .eq. 'TSUPREM-4' ) then
            simtype = 1
         else if(key .eq. 'MEDICI' ) then
            simtype = 2
         else
            lvalid_header = .FALSE.
         endif
      else if( key .eq. 'TIF' ) then
         ltif_old = .FALSE.
c        Next token is TIF id number (skip)
         call get_keyword(header,key,ipos)
         if( ipos .eq. 0 ) goto 1000
c        Now look for simulator name
         call get_keyword(header,key,ipos)
         if( ipos .eq. 0 ) goto 1000
         if( key .eq. 'TSUPREM-4' ) then
            simtype = 1
         else if( key .eq. 'MEDICI' ) then
            simtype = 2
         else if( key .eq. 'MEDICI_LOG' ) then
c           Medici IV log file
            simtype = 3
         else
c           Other type of simulator, punt and use MEDICI
            simtype = 2
         endif
      else
         lvalid_header = .FALSE.
      endif
c
      goto 2000
c
c     Error parsing header
1000  continue
      lvalid_header = .FALSE.
c
2000  continue
c
      return
      end
c
      subroutine pm_read_tif_logfile(batchmode, read_error)
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'mesh.cmn'
      include 'data.cmn'
      include 'io.cmn'
      include 'plot.cmn'
      include 'bincodes.cmn'
      include 'user.cmn'
c
      logical batchmode, read_error
c
c     locals
      character*131 header
      character*(PM_MAX_PATHLEN) expanded_name
      character*256 buffer
      character*50  key
      integer ipos, iline, num_names, num_units,
     1        icol, ioerr, i, j, nrecl, ierr, simtype,
     2        ilen, local_record, string_len
      double precision tmp(TIF_MAX_NAMES)
      logical lcontinue, name_warning, size_warning
      logical ltif_old, lvalid_header, lskip
c
      character*1 TAB
      parameter (TAB = CHAR(9))
c
      character*3 delim
      parameter (delim = ' =' // TAB)
c
      lskip = .TRUE.
      local_record = 0
c
      write(luttyo,10)
10    format(' ','Reading TIF file...')
c
c     TIF log file is limited in line length, unlike 2D file
      nrecl=0
      call pm_open_file(binfil, binfilename,
     1                  'OLD','FORMATTED','READ','FORTRAN','NONSHARED',
     2                  nrecl, ioerr, ierr)
      if( ierr .ne. 0 ) goto 10000
c
c     Read header
      read(binfil,100,end=10010,err=10010,iostat=ioerr) header
100   format(a)
c     Check for valid header
      call pm_decode_tif_header(header,lvalid_header,ltif_old,simtype)
      if( .NOT. lvalid_header ) goto 10020
c     If this is a (2d) data file, then return an error
c     This should never happen...
      if( simtype .ne. 3 ) then
         read_error = .TRUE.
         close(unit=binfil)
         return
      endif
c
c     get stem of binary file name
      call get_filestem(binfilename, binfilestem)
c
c     clear out arrays
      do 45 j=1,3
         do 45 i=1,ARRAYSIZE
            xyz(i,j) = 0.0
            edxyz(i,j) = 0.0
            dxyzm(i,j) = 0.0
45    continue
      do 51 j=1,MENUSIZE
         in_binary_file(j) = .FALSE.
51       continue
      call zero_real_array(arr2d,COMP_ARRAYSIZE,MENUSIZE)
c
      iline = 1
      i = 0
c
200   read(binfil,100,err=10010,end=300,iostat=ioerr) buffer
         iline = iline + 1
         ipos = 1
         call get_keyword(buffer,key,ipos)
         if( key .eq. 'cd' ) then
c           Skip
         else if( key .eq. '#' ) then
c           Comment, skip
         else if( key .eq. 'dset' ) then
c           Beginning of dataset
            if( .NOT. lskip ) then
c              We read in the last data set, so exit read loop...
               goto 300
            endif
            local_record = local_record + 1
c           If in batch read mode, check to see if this record
c           is the one we want...
            if( batchmode .and. local_record .eq. datafile_record ) then
               lskip = .FALSE.
            endif
c            
            num_names = 0
            num_units = 0
            icol = 0
            i = 0
            name_warning = .FALSE.
            size_warning = .FALSE.
         else if ( key .eq. 'di' ) then
c           List of data item names
            lcontinue = .FALSE.
            call get_keyword_2(buffer,delim,key,ipos)
            do while( ipos .ne. 0 ) 
               if( key .eq. '+' ) then
c                 Continued on next line...
                  lcontinue = .TRUE.
               else
                  num_names = num_names + 1
                  if( num_names .gt. TIF_MAX_NAMES ) then
                     name_warning = .TRUE.
                  else
                     tif_names(num_names) = key
                  endif
               endif
               call get_keyword_2(buffer,delim,key,ipos)
            end do
            if( .not. lcontinue ) then
c              End of data names, ask user which columns to select
               if( .NOT. batchmode ) then
                  call pm_select_tif_columns(tif_names,
     1                    MIN(num_names, TIF_MAX_NAMES),
     2                    tif_ixcol,tif_iycol,lskip)
                  if( .NOT. lskip ) then
                     datafile_record =  local_record
                  endif
               else
c                 Just a check in case columns are not set correctly...
                  if( MIN(tif_ixcol,tif_iycol) .le. 0 .or.
     1                MAX(tif_ixcol,tif_iycol) .gt. num_names ) then
                      goto 10030
                  endif
               endif
            endif
         else if ( key .eq. 'du' ) then
c           List of data item units
            lcontinue = .FALSE.
            call get_keyword(buffer,key,ipos)
            do while( ipos .ne. 0 ) 
               if( key .eq. '+' ) then
c                 Continued on next line...
                  lcontinue = .TRUE.
               else
                  num_units = num_units + 1
                  if( num_units .le. TIF_MAX_NAMES ) then
                     tif_units(num_units) = key
                  endif
               endif
               call get_keyword(buffer,key,ipos)
            end do
         else if ( key .eq. 'dd' ) then
c           Finally... the data
            lcontinue = .FALSE.
            call get_keyword(buffer,key,ipos)
            do while( ipos .ne. 0 ) 
               if( key .eq. '+' ) then
c                 Continued on next line...
                  lcontinue = .TRUE.
               else
                  icol = icol + 1
                  if( icol .le. TIF_MAX_NAMES ) then
                     read(key,*,end=10020,err=10020,iostat=ioerr)
     1                  tmp(icol)
                  endif
               endif
               call get_keyword(buffer,key,ipos)
            end do
            if( .not. lcontinue ) then
c              We've read the entire line into tmp...
               i = i + 1
               if( i .gt. COMP_ARRAYSIZE ) then
                  size_warning = .TRUE.
               else
                  xyz(i,1)   = tmp(tif_ixcol)*MU2CM
                  arr2d(i,1) = tmp(tif_iycol)
               endif
c              Reset for next line
               icol = 0
            endif
         endif
      goto 200
c
300   continue
      if( name_warning ) then
         write(luttyo,201) TIF_MAX_NAMES
201      format(' ','Number of data columns exceeds POSTMINI storage'/
     1          ' ','Only ',i5,' supported')
      endif
      if( size_warning ) then
         write(luttyo,202) COMP_ARRAYSIZE
202      format(' ','File size exceeds POSTMINI array storage'/
     1          ' ','Data will be truncated after ',i5,' points')
      endif
c     Did we find record we were looking for?
      if( batchmode .and. local_record .ne. datafile_record ) goto 10040
c     End of file reached, and no dataset selected?
      if( lskip ) goto 10050
c
      nx = i
c     Fake second dimension
      ny = 1
      xyz(1,2) = 0.0
c
      nz = 1
      nt = ny
      nyoxm = 0
      nytot= ny
      nxsp = 1
      nxsoxm = 1
      plane_index = 1
      prev_plane_type = plane_type
      plane_type = XY_PLANE
      xyz(1,3) = -xw/2.0
      nxy=nx*ny
      nxytot=nx*nytot
c
c     Load generic mesh pointers, depending on plane type
      call set_3d_index_limits
c
c     This variable must be set by all read routines...
      data_is_trigrid = .FALSE.
c
      in_binary_file(1) = .TRUE.
c
      tif_1d_data = .TRUE.
c
      write(luttyo,110)
110   format(' ','...done')
      read_error = .FALSE.
      close(unit=binfil)
      goto 10200
c
c     I/O error on open of file
10000 continue
      call expand_filename(binfilename,expanded_name)
      ilen = string_len(expanded_name)
      write(luttyo,10001) ioerr, expanded_name(1:ilen)
10001 format(/' ','FORTRAN I/O error #',i5,' on open of tif file:'/
     1       ' ',a)
      write(luttyo,10002)
10002 format(' ','Check for these errors:'/
     1       ' ','   - Incorrect file, directory or disk name'/
     1       ' ','   - You must have read permission on the file'/)
      read_error = .TRUE.  ! go back and get new name...
      goto 10200
c
c     I/O error on read of file
10010 write(luttyo,10011) ioerr, iline
10011 format(/' ','FORTRAN I/O error #',i5,' on read of file at line',
     1      i10)
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10020 continue
      write(luttyo,10021) ioerr, iline, key
10021 format(/' ','FORTRAN I/O error #',i5,' on read of file at line',
     1      i10/' ','Invalid or insufficient data on line:'/
     2      ' ',a)
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10030 continue
      write(luttyo,10031)
10031 format(/' ','Invalid columns specified for TIF log file')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10040 continue
      write(luttyo,10041) datafile_record
10041 format(/' ','Dataset number ',i5,' not found in TIF log file')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10050 continue
      write(luttyo,10051)
10051 format(/' ','End of file reached in TIF log file')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10200 continue
c
      return
      end
c
      subroutine pm_select_tif_columns(tif_names,num_names,ixcol,iycol,
     1                                 lskip)
      implicit none
c
      integer num_names, ixcol, iycol
      logical lskip
      character*(*) tif_names(num_names)
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'io.cmn'
c
c     locals
      integer i, ilen, string_len, irow, icol, inames, count
      character*80 tmp
c
      inames = 1
      count = MIN(num_names,54)
c
100   continue
c
      call clear_screen
c
      call display_string(1,1,'File quantities: ',17,0)
c
      irow = 2
      icol = 1
c
      do i=1,count
         irow = irow + 1
         if( irow .gt. 20 ) then
            irow = 3
            icol = icol + 25
         endif
         write(tmp,101) inames, tif_names(inames)
101      format(i3,' :',1x,a)
         ilen = MIN(25,string_len(tmp))
         call display_string(irow,icol,tmp,ilen,0)
         inames = inames + 1
      end do
c
      if( inames .lt. num_names ) then
         call get_string_with_prompt(tmp,
     1                               'Press return to list more names')
         count = MIN(54,(num_names - inames))
         goto 100
      endif
c
200   call get_string_with_prompt(tmp,
     1                           'Enter Y to read this data set')
      call upcase(tmp)
      if( tmp(1:1) .ne. 'Y' ) then
         lskip = .TRUE.
         ixcol = 1
         iycol = 1
         return
      else
         lskip = .FALSE.
      endif

300   call get_ints_with_prompt(ixcol,1,'Enter item number for X axis')
      if( ixcol .le. 0 .or. ixcol .gt. num_names ) then
         call display_message('Invalid item number specified')
         goto 300
      endif
c
400   call get_ints_with_prompt(iycol,1,'Enter item number for Y axis')
      if( iycol .le. 0 .or. iycol .gt. num_names ) then
         call display_message('Invalid item number specified')
         goto 400
      endif
c
      return
      end
c
      subroutine pm_determine_tif_filetype(type, read_error)
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'mesh.cmn'
      include 'data.cmn'
      include 'io.cmn'
      include 'plot.cmn'
c
      integer type
      logical read_error
c
c     Locals
      character*131 header
      character*(PM_MAX_PATHLEN) expanded_name
      integer nrecl, ioerr, ierr, iline, ilen, string_len
      logical lvalid_header, ltif_old
c
      type = 1
      read_error = .FALSE.
c
c     TIF file can write very long lines (up to Unix BUFSIZ=1024)
      nrecl=1024
      call pm_open_file(binfil, binfilename,
     1                  'OLD','FORMATTED','READ','FORTRAN','NONSHARED',
     2                  nrecl, ioerr, ierr)
      if( ierr .ne. 0 ) goto 10000
c
c     Read header
      iline = 1
      read(binfil,100,end=10010,err=10010,iostat=ioerr) header
100   format(a)
c     Check for valid header
      call pm_decode_tif_header(header,lvalid_header,ltif_old,type)
      if( .NOT. lvalid_header ) goto 10020
c
      close(unit=binfil)
      goto 10200
c
c     errors of commission/omission
c
c     I/O error on open of file
10000 continue
      call expand_filename(binfilename,expanded_name)
      ilen = string_len(expanded_name)
      write(luttyo,10001) ioerr, expanded_name(1:ilen)
10001 format(/' ','FORTRAN I/O error #',i5,' on open of tif file:'/
     1       ' ',a)
      write(luttyo,10002)
10002 format(' ','Check for these errors:'/
     1       ' ','   - Incorrect file, directory or disk name'/
     1       ' ','   - You must have read permission on the file'/)
      read_error = .TRUE.  ! go back and get new name...
      goto 10200
c
c     I/O error on read of file
10010 write(luttyo,10011) ioerr, iline
10011 format(/' ','FORTRAN I/O error #',i5,' on read of file at line',
     1      i10)
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10020 continue
      write(luttyo,10021)
10021 format(' ','Error: Invalid header in TIF file')
      read_error = .TRUE.
      close(unit=binfil)
      goto 10200
c
10200 continue
c
      return
      end

