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     Vector Technologies kindly provided the format of their FAIM
c     simulator output file.
c     Contact Vector Technologies for information on purchase of their
c     TCAD tools.
c
      subroutine read_faim(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 Vector Technologies FAIM output file (ASCII)
c
      logical batchmode, read_error
c
c     locals
c
      integer i
c
      call read_faim_file(batchmode, read_error)
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
      nxm = nx - 1
      nym = ny - 1
      nytotm = nytot - 1
c
c     inverse mesh spacing...
c
      do 210 i=1,nxm
210      edxyz(i,1) = 1.0/(xyz(i+1,1) - xyz(i,1))
      do 211 i=1,nytotm
211      edxyz(i,2) = 1.0/(xyz(i+1,2) - xyz(i,2))
      do 212 i=1,nz-1
212      edxyz(i,3) = 1.0/(xyz(i+1,3) - xyz(i,3))
c
c     average mesh spacing...
c
      dxyzm(1,1)  = (xyz(2,1)  - xyz(1,1))/2.0
      dxyzm(nx,1) = (xyz(nx,1) - xyz(nx-1,1))/2.0
      do 220 i=2,nxm
220      dxyzm(i,1) = (xyz(i+1,1) - xyz(i-1,1))/2.0
c
      dxyzm(1,2)     = (xyz(2,2)  - xyz(1,2))/2.0
      dxyzm(nytot,2) = (xyz(nytot,2) - xyz(nytot-1,2))/2.0
      do 221 i=2,nytotm
221      dxyzm(i,2) = (xyz(i+1,2) - xyz(i-1,2))/2.0
c
      dxyzm(1,3)     = (xyz(2,3)  - xyz(1,3))/2.0
      dxyzm(nz,3) = (xyz(nz,3) - xyz(nz-1,3))/2.0
      do 222 i=2,nz-1
222      dxyzm(i,3) = (xyz(i+1,3) - xyz(i-1,3))/2.0
c
      call load_faim_specific
c
      if( lfirst_read ) then
         lfirst_read = .FALSE.
         prev_plane_type = plane_type
         prev_binfilename = binfilename
         prev_binfiletype = binfiletype
      endif
c     For FAIM datasets, re-scale plot limits on each read of a new file
      oned_lfirst = .TRUE.
      twod_lfirst = .TRUE.
      threed_lfirst = .TRUE.
c
      datafile_loaded = .TRUE.
c
10000 return
      end
c
      subroutine read_faim_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 Vector Technologies FAIM output file (ASCII)
c
      logical batchmode, read_error
c
c     locals
c
      integer i, j, idum, ilen, ioerr, string_len, ierr, nrecl
      double precision xcoord, ycoord, value
      character*(PM_MAX_PATHLEN) expanded_name
      character*80 buffer
c
      write(luttyo,10)
10    format(' ','Reading FAIM file...')
c
      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     get stem of file name
      call get_filestem(binfilename, binfilestem)
c
100   continue
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
c
c     Try to read the nx,ny from first line. If this fails, assume this
c     is a normal FAIM output file.
      read(binfil,*,err=1000,end=10010,iostat=ioerr) idum, nx, ny
c     If we got here, read suceeded. Go to code which reads array values.
      goto 1100
c
c     Else read failed, assume "small" FAIM output file (skip text header)
1000  continue
c
c     Read lines until we get to 'PARAMETER_END'
1002  read(binfil,1001,end=10010,err=10010,iostat=ioerr) buffer
1001  format(a)
      if( buffer .eq. 'PARAMETER_END' ) goto 1003
      goto 1002
1003  continue
c
c     We've read past the text header, data begins...
      read(binfil,*,end=10010,err=10010,iostat=ioerr) idum, nx, ny
c
c     Code merges to one path here...
1100  continue
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
c     Data file has 2D data
      three_d = .FALSE.
c
c     Is array storage large enough?
      if( MAX(nx,nytot,nz) .gt. COMP_ARRAYSIZE .or.
     1    (nx*nytot) .gt. WORK2DSIZE .or.
     2    (nx*nytot) .gt. NUM_DATA_ARRAYS*ARR2DSIZE ) then
         write(luttyo,10050)
10050    format(' ','Error: file too large for POSTMINI arrays')
         read_error = .TRUE.  ! go back
         close(unit=binfil)
         return
      endif
c
      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
      call allocate_rect_arrays(nx,ny,1,ierr)
      if( ierr .ne. 0 ) then
c        Failure during array allocation
         write(luttyo,10050)
         close(unit=binfil)
         read_error = .TRUE.
         return
      endif
c     Zero array (not really necessary)
      call zero_real_array(arrdat,nx*ny,1)
c
c     This variable must be set by all read routines...
      data_is_trigrid = .FALSE.
c
c     Load data array
      do j=1,ny
         do i=1,nx
c           Read into double precision store to avoid bug in DEC FORTRAN
c           RTL which (until fix gets distributed, 1/19/96)
c           does not truncate denorms to zero on read into single precision
            read(binfil,*,end=2000,err=10010,iostat=ioerr)
     1           xcoord, ycoord, value
            xyz(i,1) = xcoord
            xyz(j,2) = ycoord
            arrdat(i + nx*(j-1)) = value
         end do
      end do
2000  continue
c
c     Scale coordinates to cm
      do i=1,nx
         xyz(i,1) = xyz(i,1)*MU2CM
      end do
      do j=1,ny
         xyz(j,2) = xyz(j,2)*MU2CM
      end do
c
      datafile_record = 1
      in_binary_file(1) = .TRUE.
c
      write(luttyo,110)
110   format(' ','...done')
      read_error = .FALSE.
c
      close(unit=binfil)
      goto 10100
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 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 10100
c
c     I/O error on read of file
10010 write(luttyo,10011) ioerr
10011 format(/' ','FORTRAN I/O error #',i5,' on read of file')
      if( ioerr .eq. 24 ) then       ! End-of-file during read
         write(luttyo,10012)
10012    format(' ','Unexpected end-of-file during read...')
      else if( ioerr .eq. 67 ) then  ! Not enough data in record
         write(luttyo,10014)
10014    format(' ','Insufficient data in record'/)
      else if( ioerr .eq. -1 ) then  ! End of file at start of read
         write(luttyo,10015)
10015    format(' ','Unexpected end-of-file')
      endif
      read_error = .TRUE.  ! go back and get new name...
      close(unit=binfil)
      goto 10100
c
10100 continue
      return
      end
c
      subroutine load_faim_specific
      implicit none
c
c     Load descriptive arrays with FAIM 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
c     Number of menu items
      max_menu_num = 1
c     Array index of net doping (none in this case)
      net_dop_array_index = 0
c
      call load_desc_arr(1,'Aerial image intensity','FAIM',
     1                   ' ',' ',' ','.faim',
     2                   LIN,OX,NO_JUMP,TWOD,1)
      return
      end
