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
      subroutine read_bambi(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 BAMBI binary file (as processed by Gerd Nanz's PLPREP program)
c
c     locals
c
      integer i
      logical read_error
c
      call read_bambi_bin(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
      data_is_trigrid = .FALSE.
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_bambi_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 ) then
         oned_lfirst = .TRUE.
         twod_lfirst = .TRUE.
         threed_lfirst = .TRUE.
      endif
      datafile_loaded = .TRUE.
c
10000 return
      end
c
      subroutine read_bambi_bin(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 double precision BAMBI binary file
c
      logical read_error
c
c     locals
c
      integer MRECL
      parameter (MRECL = 4000)
c
      integer i, j, k, icnt, ii, ilen, ioerr, string_len,
     1        num, icount, nk, ierr, ioff1, ioff2, nrecl
      character*(PM_MAX_PATHLEN) expanded_name
c
      write(luttyo,10)
10    format(' ','Reading BAMBI binary file...',$)
c
      nrecl=0
      call pm_open_file(binfil, binfilename,
     1               'OLD','UNFORMATTED','READ','NONE','NONSHARED',
     2               nrecl, ioerr, ierr)
      if( ierr .ne. 0 ) goto 10000
      datafile_record = 1
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,COMP_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
      icount = 0
      title = 'BAMBI simulation'
c
1000  continue
c     1. now nx, ny
      read(binfil,err=10010,end=2000,iostat=ioerr) nx,ny,num
      icount = icount + 1
c     If number of data elements exceeds size of arrays, then exit
      if( icount .gt. NUM_DATA_ARRAYS ) goto 2000
      bambi_data_type(icount) = num
      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
c     Is array storage large enough?
      if( MAX(nx,ny) .gt. COMP_ARRAYSIZE .or.
     1    (nx*ny) .gt. ARR2DSIZE ) then
         write(luttyo,10050)
10050    format(' ','Error: binary file too large for POSTMINI arrays')
         read_error = .TRUE.  ! go back
         close(unit=binfil)
         return
      endif
c
      nxy=nx*ny
      nxytot=nx*nytot
c
      call allocate_rect_arrays(ni,nj,NUM_DATA_ARRAYS,ierr)
      if( ierr .ne. 0 ) then
c        Failure during array allocation
         write(luttyo,10050)
         read_error = .TRUE.
         close(unit=binfil)
         return
      endif
c
c     2. read lateral spacing
      read(binfil,err=10010,iostat=ioerr) (work_dbl(i),i=1,nx)
      do 200 i=1,nx
200      xyz(i,1) = SNGL(work_dbl(i))
c
c     3. read transversal spacing
      read(binfil,err=10010,iostat=ioerr) (work_dbl(i),i=1,nytot)
      do 210 i=1,nytot
210      xyz(i,2) = SNGL(work_dbl(i))
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 = .FALSE.
c
c     4. Load data array
      nk = nx*ny
c     Following code is from Gerd Nanz's PLPREP program:
      icnt    = nk / MRECL 
      k     = 0
      do 220 ii = 1,icnt
          read(binfil,err=10010,end=10010) (work_dbl(i),i=k+1,k+MRECL)
          k = k + MRECL
220   continue
      if (nk-icnt*MRECL .gt. 0) 
     1    read(binfil,err=10010,end=10010) (work_dbl(i),i=k+1,nk)
c
      do 230 j=1,ny
          ioff1 = arrind(icount) - 1 + (j-1)*nx
          ioff2 = (j-1)*nx
          do 240, i=1,nx
              arrdat(ioff1+i) = SNGL(work_dbl(ioff2+i))
240       continue
230   continue
c
      in_binary_file(icount) = .TRUE.
      goto 1000
c
c
2000  write(luttyo,110)
110   format(' ','...done')
      read_error = .FALSE.
      close(unit=binfil)
c
c     Number of menu items
      max_menu_num = icount
      goto 10100
c
c     errors of commission/omission
c
c     I/O error on open of binary 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 binary 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
c     I/O error on read of binary file
10010 write(luttyo,10011) ioerr
10011 format(/' ','FORTRAN I/O error #',i5,' on read of binary file')
      if( ioerr .eq. 24 ) then       ! End-of-file during read
         write(luttyo,10012)
10012    format(' ','Unexpected end-of-file during read...'/
     1          ' ','File may not be a BAMBI binary file'/)
      else if( ioerr .eq. 35 ) then  ! Not binary file format
         write(luttyo,10013)
10013    format(' ','File is probably not a FORTRAN binary file...'/)
      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'/
     1     ' ','File may not have been written completely by BAMBI'/)
      endif
      read_error = .TRUE.  ! go back and get new name...
      close(unit=binfil)
      goto 10100
c
10100 continue
      return
      end
c
      subroutine load_bambi_specific
      implicit none
c
c     Load descriptive arrays with BAMBI 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
c
c     Array index of net doping (unknown unless doping is in file)
      net_dop_array_index = 0
c     File has 2D data
      three_d = .FALSE.
c
      do i = 1,max_menu_num
         if( bambi_data_type(i) .eq. 1 ) then
            call load_desc_arr(i, 'Potential', 'POTENTIAL',
     1                         'V','V cm','V cm^{2}','.psi',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 2 ) then
            call load_desc_arr(i, 'Electron Concentration', 'ELECTRONS',
     1                         'cm^{-3}','cm^{-2}','cm^{-1}','.econc',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 3 ) then
            call load_desc_arr(i, 'Hole Concentration', 'HOLES',
     1                         'cm^{-3}','cm^{-2}','cm^{-1}','.hconc',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 4 ) then
            call load_desc_arr(i, 'E field (x comp)', 'EX',
     1                         'V/cm','V','V cm','.ex',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 5 ) then
            call load_desc_arr(i, 'E field (y comp)', 'EY',
     1                         'V/cm','V','V cm','.ey',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 6 ) then
            call load_desc_arr(i, 'E field (magnitude)', 'EMAG',
     1                         'V/cm','V','V cm','.bambi',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 7 ) then
            call load_desc_arr(i, 'Electron mobility', 'MU_E',
     1                         'cm^{2}/V s','cm^{3}/V s',
     2                         'cm^{4}/V s','.mu_e',
     3                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 8 ) then
            call load_desc_arr(i, 'Hole mobility', 'MU_P',
     1                         'cm^{2}/V s','cm^{3}/V s',
     2                         'cm^{4}/V s','.mu_h',
     3                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 9 ) then
            call load_desc_arr(i, 'Electron current (x comp)', 'JX_N',
     1                         'A/cm','A','A cm','.jx_e',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 10 ) then
            call load_desc_arr(i, 'Electron current (y comp)', 'JY_N',
     1                         'A/cm','A','A cm','.jy_e',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 11 ) then
            call load_desc_arr(i, 'Electron current (mag.)', 'JMAG_N',
     1                         'A/cm','A','A cm','.jmag_e',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 12 ) then
            call load_desc_arr(i, 'Hole current (x comp)', 'JX_P',
     1                         'A/cm','A','A cm','.jx_h',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 13 ) then
            call load_desc_arr(i, 'Hole current (y comp)', 'JY_P',
     1                         'A/cm','A','A cm','.jy_h',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 14 ) then
            call load_desc_arr(i, 'Hole current (mag.)', 'JMAG_P',
     1                         'A/cm','A','A cm','.jmag_h',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 15 ) then
            call load_desc_arr(i, 'Total current (x comp)', 'JX_TOTAL',
     1                         'A/cm','A','A cm','.jx_t',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 16 ) then
            call load_desc_arr(i, 'Total current (y comp)', 'JY_TOTAL',
     1                         'A/cm','A','A cm','.jy_t',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 17 ) then
            call load_desc_arr(i, 'Total current (mag)', 'JMAG_TOTAL',
     1                         'A/cm','A','A cm','.jmag_t',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 18 ) then
            call load_desc_arr(i, 'Doping concentration', 'NET_DOPING',
     1                         'cm^{-3}','cm^{-2}','cm^{-1}','.dc',
     2                         LOG,OX,NO_JUMP,TWOD,i)
            net_dop_array_index = i
         else if( bambi_data_type(i) .eq. 19 ) then
            call load_desc_arr(i, 'Charge density', 'NET_CHARGE',
     1                         'cm^{-3}','cm^{-2}','cm^{-1}','.ch_den',
     2                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 20 ) then
            call load_desc_arr(i, 'Net recombination', 'NET_RECOMB',
     1                         'cm^{-3}/s','cm^{-2}/s',
     2                         'cm^{-1}/s','.rec',
     3                         LOG,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 21 ) then
            call load_desc_arr(i, 'X error estimate', 'X_ERROR',
     1                         ' ',' ',' ','.x_esti',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 22 ) then
            call load_desc_arr(i, 'Y error estimate', 'Y_ERROR',
     1                         ' ',' ',' ','.y_esti',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 23 ) then
            call load_desc_arr(i, 'Total error estimate', 'TOTAL_ERROR',
     1                         ' ',' ',' ','.t_esti',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 24 ) then
            call load_desc_arr(i, 'Integrated electron conc.', 'N_INT',
     1                         '1/cm',' ','cm ','.intn',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 25 ) then
            call load_desc_arr(i, 'Integrated hole conc.' , 'P_INT',
     1                         '1/cm',' ','cm','.intp',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 26 ) then
            call load_desc_arr(i, 'Int (n - p)', 'N_P_INT',
     1                         '1/cm',' ','cm','.intnmp',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 27 ) then
            call load_desc_arr(i, 'Int. q(n - p + N_{d} - N_{a})',
     1                         'NET_CHARGE_INT',
     2                         'C/cm','C','C cm','.int_ch',
     3                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 28 ) then
            call load_desc_arr(i, 'Int. Recombination' , 'RECOMB_INT',
     1                         'cm^{-1}s^{-1}','1/s ','cm/s ','.intrec',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 29 ) then
            call load_desc_arr(i, 'Electron qFermi Level', 'QFN',
     1                         'V','V cm','V cm^{2}','.qf_e',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         else if( bambi_data_type(i) .eq. 30 ) then
            call load_desc_arr(i, 'Hole qFermi level' , 'QFP',
     1                         'V','V cm','V cm^{2}','.qf_h',
     2                         LIN,OX,NO_JUMP,TWOD,i)
         endif
      end do
c
      return
      end
