LCOV - code coverage report
Current view: top level - ionization/private - ion_tables_load.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 70.4 % 277 195
Test Date: 2025-05-08 18:23:42 Functions: 92.9 % 14 13

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2011  Bill Paxton & The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              :       module ion_tables_load
      21              :       use ionization_def
      22              :       use const_def, only: dp, use_mesa_temp_cache
      23              :       use utils_lib, only: mesa_error, mv, switch_str
      24              : 
      25              :       implicit none
      26              : 
      27              :       contains
      28              : 
      29            6 :       subroutine Init_ion_tables(file_prefix, Z1_suffix, use_cache, ierr)
      30              :          character(*), intent(in) :: file_prefix, Z1_suffix
      31              :          logical, intent(in) :: use_cache
      32              :          integer, intent(out) :: ierr  ! 0 means AOK.
      33            3 :          ierr = 0
      34            3 :          if (ion_root_is_initialized) return
      35            3 :          ion_file_prefix = file_prefix
      36            3 :          ion_Z1_suffix = Z1_suffix
      37            3 :          use_cache_for_ion = use_cache
      38            3 :          call ion_read_sizes(ierr)
      39            3 :          if (ierr /= 0) return
      40            3 :          ion_root_is_initialized = .true.
      41            3 :       end subroutine Init_ion_tables
      42              : 
      43              : 
      44            3 :       subroutine ion_read_sizes(ierr)
      45              :          use utils_lib
      46              :          integer, intent(out) :: ierr
      47              : 
      48              :          character (len=256) :: message, fname, cache_filename, temp_cache_filename
      49              :          integer :: iounit
      50            3 :          real(dp) :: xin, zz
      51              : 
      52            3 :          ierr = 0
      53              : 
      54            3 :          call Get_ion_Table_Filenames(ion_Zs(1), ion_Xs(1), fname, cache_filename, temp_cache_filename)
      55            3 :          open(newunit=iounit, file=trim(fname), action='read', status='old', iostat=ierr)
      56            3 :          call check_for_error_in_ion_data(ierr, fname)
      57              : 
      58            3 :          read(iounit,*, iostat=ierr)
      59            3 :          call check_for_error_in_ion_data(ierr, fname)
      60              : 
      61              :          read(iounit,*, iostat=ierr) &
      62            3 :                ion_version, xin, zz, ion_num_logTs, ion_logT_min, ion_logT_max, ion_del_logT, &
      63            6 :                ion_num_logQs, ion_logQ_min, ion_logQ_max, ion_del_logQ
      64            3 :          call check_for_error_in_ion_data(ierr, fname)
      65              : 
      66            3 :          close(iounit)
      67              : 
      68            3 :          if (ion_version < min_version) call request_user_to_reinstall
      69              : 
      70            3 :       end subroutine ion_read_sizes
      71              : 
      72              : 
      73            0 :       subroutine request_user_to_reinstall
      74            0 :          write(*,*)
      75            0 :          write(*,*)
      76            0 :          write(*,*)
      77            0 :          write(*,*)
      78            0 :          write(*,*)
      79            0 :          write(*,*)
      80            0 :          write(*,*) 'NOTICE: you need to install a new version of the ion data.'
      81            0 :          write(*,*) 'Please update by removing the directory mesa/data/ionization_data,'
      82            0 :          write(*,*) 'and rerunning the mesa ./install script.'
      83            0 :          write(*,*)
      84            0 :          write(*,*)
      85            0 :          call mesa_error(__FILE__,__LINE__)
      86            0 :       end subroutine request_user_to_reinstall
      87              : 
      88              : 
      89           53 :       subroutine check_for_error_in_ion_data(ierr, fname)
      90              :          integer, intent(in) :: ierr
      91              :          character (len=*) :: fname
      92           53 :          if (ierr == 0) return
      93            0 :          write(*,*) 'load ion tables ' // trim(fname)
      94            0 :          write(*,*)
      95            0 :          write(*,*)
      96            0 :          write(*,*)
      97            0 :          write(*,*)
      98            0 :          write(*,*)
      99            0 :          write(*,'(a)') 'FATAL ERROR: missing or bad ion data.'
     100            0 :          write(*,'(a)') 'Please update by removing the directories mesa/data/ionization_data,'
     101            0 :          write(*,'(a)') 'and rerunning the mesa ./install script.'
     102            0 :          write(*,*)
     103            0 :          call mesa_error(__FILE__,__LINE__)
     104              :       end subroutine check_for_error_in_ion_data
     105              : 
     106              : 
     107            2 :       subroutine Load_ion_Table(ierr)
     108              :          use utils_lib
     109              :          integer, intent(out) :: ierr
     110              : 
     111              :          integer :: iz, ix, i
     112              : 
     113            2 :          ierr = 0
     114            4 : !$OMP CRITICAL (load_ionization_table)
     115            2 :          call do_read
     116              : !$OMP END CRITICAL (load_ionization_table)
     117              : 
     118              :          contains
     119              : 
     120            2 :          subroutine do_read
     121              :             integer :: sz_ion_tbl
     122              : 
     123            2 :             if (ion_is_initialized) return
     124              :             sz_ion_tbl = sz_per_ion_point*num_ion_vals* &
     125            2 :                                  ion_num_logQs*ion_num_logTs*num_ion_Xs*num_ion_Zs
     126              :             allocate(ion_tbl1(sz_ion_tbl),&
     127              :                      ion_logQs(ion_num_logQs), ion_logTs(ion_num_logTs),  &
     128            2 :                      STAT=ierr)
     129            2 :             if (ierr /= 0) return
     130              :             ion_tbl(1:sz_per_ion_point, 1:num_ion_vals,&
     131              :                     1:ion_num_logQs, 1:ion_num_logTs, 1:num_ion_Xs, 1:num_ion_Zs) => &
     132            2 :                ion_tbl1(1:sz_ion_tbl)
     133              : 
     134            2 :             ion_logQs(1) = ion_logQ_min
     135          348 :             do i = 2, ion_num_logQs-1
     136          348 :                ion_logQs(i) = ion_logQs(i-1) + ion_del_logQ
     137              :             end do
     138            2 :             ion_logQs(ion_num_logQs) = ion_logQ_max
     139              : 
     140            2 :             ion_logTs(1) = ion_logT_min
     141          202 :             do i = 2, ion_num_logTs-1
     142          202 :                ion_logTs(i) = ion_logTs(i-1) + ion_del_logT
     143              :             end do
     144            2 :             ion_logTs(ion_num_logTs) = ion_logT_max
     145              : 
     146           12 :             do iz = 1, num_ion_Zs
     147           72 :                do ix = 1, num_ion_Xs
     148           60 :                   if (ion_Zs(iz) + ion_Xs(ix) > 1.0000001d0) cycle
     149           44 :                   call read_one(ix,iz,ierr)
     150           54 :                   if (ierr /= 0) return
     151              :                end do
     152              :             end do
     153              : 
     154            2 :             ion_is_initialized = .true.
     155              :          end subroutine do_read
     156              : 
     157           44 :          subroutine read_one(ix,iz,ierr)
     158              :             integer, intent(in) :: ix, iz
     159              :             integer, intent(out) :: ierr
     160              : 
     161              :             character (len=256) :: fname, cache_filename, temp_cache_filename
     162              : 
     163              :             include 'formats'
     164              : 
     165              :             call Get_ion_Table_Filenames(&
     166           44 :                      ion_Zs(iz), ion_Xs(ix), fname, cache_filename, temp_cache_filename)
     167              :             call Load1_ion_Table(&
     168              :                   ion_Xs(ix), ion_Zs(iz), ion_tbl(:,:,:,:,ix,iz),&
     169           44 :                   fname, cache_filename, temp_cache_filename, use_cache_for_ion, ierr)
     170           44 :             if (ierr /= 0) then
     171            0 :                write(*,*) 'Load1_ion_Table ierr', ierr, ix, iz, ion_Xs(ix), ion_Zs(iz)
     172              :             end if
     173              : 
     174           44 :          end subroutine read_one
     175              : 
     176              :       end subroutine Load_ion_Table
     177              : 
     178              : 
     179           47 :       subroutine Get_ion_Table_Filenames(Z, X, fname, cache_filename, temp_cache_filename)
     180              :          use const_def, only: mesa_data_dir
     181              :          real(dp), intent(in) :: Z, X
     182              :          character (len=*), intent(out) :: fname, cache_filename, temp_cache_filename
     183              :          character (len=256) :: Zstr, Xstr, suffix
     184              : 
     185           47 :          call setstr(Z,Zstr)
     186           47 :          call setstr(X,Xstr)
     187           47 :          if (Zstr == '100') then
     188            2 :             suffix = ion_Z1_suffix
     189              :          else
     190           45 :             suffix = ''
     191              :          end if
     192              : 
     193              :          fname = trim(mesa_data_dir) // &
     194              :                '/ionization_data/' // trim(ion_file_prefix) // '_' //&
     195           47 :                trim(Zstr) // 'z' // trim(Xstr) // 'x' // trim(suffix) // '.data'
     196              :          cache_filename = trim(ionization_cache_dir) // &
     197              :                '/' // trim(ion_file_prefix) // '_' //&
     198           47 :                trim(Zstr) // 'z' // trim(Xstr) // 'x' // trim(suffix) // '.bin'
     199              : 
     200              :          temp_cache_filename = trim(ionization_temp_cache_dir) // &
     201              :                '/' // trim(ion_file_prefix) // '_' //&
     202           94 :                trim(Zstr) // 'z' // trim(Xstr) // 'x' // trim(suffix) // '.bin'
     203              : 
     204              :          contains
     205              : 
     206           94 :          subroutine setstr(v,str)
     207              :             real(dp), intent(in) :: v
     208              :             character (len=*) :: str
     209           94 :             if (v > 0.99999d0) then
     210            4 :                str = '100'
     211           90 :             else if (v > 0.09999d0) then
     212           42 :                write(str, '(i2)') floor(100d0 * v + 0.5d0)
     213              :             else
     214           48 :                write(str, '(a,i1)') '0', floor(100d0 * v + 0.5d0)
     215              :             end if
     216           94 :          end subroutine setstr
     217              : 
     218              :       end subroutine Get_ion_Table_Filenames
     219              : 
     220              : 
     221           66 :       subroutine Load1_ion_Table(&
     222           44 :             X, Z, tbl, filename, cache_filename, temp_cache_filename, use_cache, info)
     223              :          real(dp), intent(in) :: X, Z
     224              :          real(dp) :: tbl(sz_per_ion_point, num_ion_vals, ion_num_logQs, ion_num_logTs)
     225              :          character (*), intent(in) :: filename, cache_filename, temp_cache_filename
     226              :          logical, intent(in) :: use_cache
     227              :          integer, intent(out) :: info
     228              : 
     229              :          integer :: io_unit, cache_io_unit
     230              : 
     231              :          integer :: num_logQs_in, num_logTs_in, version_in
     232         1276 :          real(dp) :: logT_min_in, logT_max_in, del_logT_in, vals(num_ion_vals),&
     233           44 :                logQ_min_in, logQ_max_in, del_logQ_in, X_in, Z_in, logQ, logT
     234              :          integer :: j,i,k,iQ,ios,status,line_number
     235              :          character (len=500) :: message, input_line
     236              :          real(dp), parameter :: tiny = 1e-6
     237              : 
     238              :          include 'formats'
     239              : 
     240           44 :          info = 0
     241              : 
     242           44 :          write(message,*) 'open ', trim(filename)
     243           44 :          open(NEWUNIT=io_unit, FILE=trim(filename), ACTION='READ', STATUS='OLD', IOSTAT=ios)
     244           44 :          call check_for_error_in_ion_data(ios, filename)
     245              : 
     246              :          line_number = 0
     247           44 :          read(io_unit,*,iostat=info)
     248           66 :          if (info /= 0) return
     249           44 :          line_number = line_number + 1
     250              :          read(io_unit,*,iostat=info) &
     251           44 :                version_in, X_in, Z_in, num_logTs_in, logT_min_in, logT_max_in, del_logT_in, &
     252           88 :                num_logQs_in, logQ_min_in, logQ_max_in, del_logQ_in
     253           44 :          if (info /= 0) return
     254              :          line_number = line_number + 1
     255           44 :          read(io_unit,*,iostat=info)
     256           44 :          if (info /= 0) return
     257           44 :          line_number = line_number + 1
     258              : 
     259              :          if (ion_version > version_in &
     260              :             .or. ion_num_logQs /= num_logQs_in &
     261              :             .or. ion_num_logTs /= num_logTs_in&
     262              :             .or. abs(X-X_in) > tiny&
     263              :             .or. abs(Z-Z_in) > tiny&
     264              :             .or. abs(ion_logT_min-logT_min_in) > tiny    &
     265              :             .or. abs(ion_logT_max-logT_max_in) > tiny    &
     266              :             .or. abs(ion_del_logT-del_logT_in) > tiny    &
     267              :             .or. abs(ion_logQ_min-logQ_min_in) > tiny    &
     268              :             .or. abs(ion_logQ_max-logQ_max_in) > tiny    &
     269           44 :             .or. abs(ion_del_logQ-del_logQ_in) > tiny    &
     270              :            ) then
     271            0 :             write(*,*) 'bad header info in ' // trim(filename)
     272            0 :             info = -1
     273            0 :             close(io_unit)
     274            0 :             write(*,'(a50,l1,2i10)') 'ion_version > version_in', ion_version > version_in, ion_version, version_in
     275            0 :             write(*,'(a50,l1)') 'ion_num_logQs /= num_logQs_in', ion_num_logQs /= num_logQs_in
     276            0 :             write(*,'(a50,l1)') 'ion_num_logTs /= num_logTs_in', ion_num_logTs /= num_logTs_in
     277            0 :             write(*,'(a50,l1)') 'abs(X-X_in) > tiny', abs(X-X_in) > tiny
     278            0 :             write(*,'(a50,l1)') 'abs(Z-Z_in) > tiny', abs(Z-Z_in) > tiny
     279            0 :             write(*,'(a50,l1)') 'abs(ion_logT_min-logT_min_in) > tiny', abs(ion_logT_min-logT_min_in) > tiny
     280            0 :             write(*,'(a50,l1)') 'abs(ion_logT_max-logT_max_in) > tiny', abs(ion_logT_max-logT_max_in) > tiny
     281            0 :             write(*,'(a50,l1)') 'abs(ion_del_logT-del_logT_in) > tiny', abs(ion_del_logT-del_logT_in) > tiny
     282            0 :             write(*,'(a50,l1)') 'abs(ion_logQ_min-logQ_min_in) > tiny', abs(ion_logQ_min-logQ_min_in) > tiny
     283            0 :             write(*,'(a50,l1)') 'abs(ion_logQ_max-logQ_max_in) > tiny', abs(ion_logQ_max-logQ_max_in) > tiny
     284            0 :             write(*,'(a50,l1)') 'abs(ion_del_logQ-del_logQ_in) > tiny', abs(ion_del_logQ-del_logQ_in) > tiny
     285            0 :             write(*,*)
     286            0 :             write(*,1) 'ion_logT_max', ion_logT_max
     287            0 :             write(*,1) 'logT_max_in', logT_max_in
     288            0 :             stop
     289              :             return
     290              :          end if
     291              : 
     292           44 :          if (use_cache) then
     293           44 :             call Read_ion_Cache(X, Z, tbl, cache_filename, ios)
     294           44 :             if (ios == 0) then
     295           22 :                close(io_unit)
     296           22 :                return
     297              :             end if
     298              :          end if
     299              : 
     300         3872 :          do iQ=1,ion_num_logQs
     301         3850 :             read(io_unit,*,iostat=info)
     302         3850 :             if (failed('skip line')) return
     303         3850 :             line_number = line_number + 1
     304         3850 :             read (io_unit,*,iostat=info) logQ
     305         3850 :             if (failed('skip line')) return
     306         3850 :             line_number = line_number + 1
     307         3850 :             read(io_unit,*,iostat=info)
     308         3850 :             if (failed('skip line')) return
     309         3850 :             line_number = line_number + 1
     310         3850 :             read(io_unit,*,iostat=info)
     311         3850 :             if (failed('skip line')) return
     312         3850 :             line_number = line_number + 1
     313       396550 :             do i=1,ion_num_logTs
     314       392700 :                read(io_unit,'(a)',iostat=info) input_line
     315       392700 :                if (failed('read line')) return
     316       392700 :                line_number = line_number + 1
     317       392700 :                read (input_line,*,iostat=info) logT, vals(1:num_ion_vals)
     318       392700 :                if (failed('read tbl')) then
     319            0 :                   write(*,'(a)') trim(input_line)
     320            0 :                   write(*,*) trim(filename)
     321            0 :                   write(*,*) 'iQ, i', iQ, i
     322            0 :                   write(*,*) 'num_ion_vals', num_ion_vals
     323            0 :                   write(*,*) 'logQ', logQ
     324            0 :                   write(*,*) 'bad input line?'
     325            0 :                   call mesa_error(__FILE__,__LINE__)
     326              :                end if
     327     11392150 :                tbl(1,1:num_ion_vals,iQ,i) = vals(1:num_ion_vals)
     328              :             end do
     329         3850 :             if(iQ < ion_num_logQs) read(io_unit,*,iostat=info)
     330         3850 :             if (failed('skip line')) return
     331         3850 :             line_number = line_number + 1
     332         3850 :             if(iQ < ion_num_logQs) read(io_unit,*,iostat=info)
     333         3850 :             if (failed('skip line')) return
     334         3872 :             line_number = line_number + 1
     335              :          end do
     336              : 
     337           22 :          close(io_unit)
     338              : 
     339           22 :          call Make_ion_Interpolation_Data(tbl, info)
     340           22 :          if (failed('Make_ion_Interpolation_Data')) return
     341              : 
     342           22 :          call Check_ion_Interpolation_Data(tbl)
     343              : 
     344           22 :          if (.not. use_cache) return
     345              : 
     346              :          open(NEWUNIT=cache_io_unit, file=trim(switch_str(temp_cache_filename, cache_filename, use_mesa_temp_cache)),&
     347           22 :           iostat=ios, action='write', form='unformatted')
     348              : 
     349           22 :          if (ios == 0) then
     350           22 :             write(*,'(a)') 'write ' // trim(cache_filename)
     351              :             write(cache_io_unit) &
     352           22 :                X_in, Z_in, ion_num_logTs, ion_logT_min, ion_logT_max, ion_del_logT, &
     353           44 :                ion_num_logQs, ion_logQ_min, ion_logQ_max, ion_del_logQ, ion_version
     354              :             write(cache_io_unit) &
     355           22 :                   tbl(1:sz_per_ion_point, 1:num_ion_vals, 1:ion_num_logQs, 1:ion_num_logTs)
     356           22 :             close(cache_io_unit)
     357           22 :             if(use_mesa_temp_cache) call mv(temp_cache_filename, cache_filename,.true.)
     358              :          end if
     359              : 
     360              :          contains
     361              : 
     362           22 :          subroutine Check_ion_Interpolation_Data(tbl)
     363              :             use utils_lib,only:is_bad
     364              :             real(dp) :: tbl(sz_per_ion_point, num_ion_vals, ion_num_logQs, ion_num_logTs)
     365              : 
     366              :             ! for logT > 6.8 and logRho < -10, splines can get bogus higher order terms
     367              :             ! replace NaN's and Infinities with 0
     368              : 
     369              :             integer :: i, j, iQ, jtemp
     370              : 
     371          110 :             do i = 1, sz_per_ion_point
     372         2574 :                do j = 1, num_ion_vals
     373       433752 :                   do iQ = 1, ion_num_logQs
     374     44416064 :                      do jtemp = 1, ion_num_logTs
     375     44413600 :                         if (is_bad(tbl(i,j,iQ,jtemp))) then
     376            0 :                            tbl(i,j,iQ,jtemp) = 0
     377              :                         end if
     378              :                      end do
     379              :                   end do
     380              :                end do
     381              :             end do
     382              : 
     383           22 :          end subroutine Check_ion_Interpolation_Data
     384              : 
     385       808522 :          logical function failed(str)
     386              :             character (len=*), intent(in) :: str
     387       808522 :             failed = (info /= 0)
     388       808522 :             if (failed) then
     389            0 :                write(*,*)
     390            0 :                write(*,'(a)') trim(filename)
     391              :                write(*,'(a,i9)') &
     392            0 :                   ' Load1_ion_Table failed: ' // trim(str) // ' line', line_number
     393              :             end if
     394       808522 :          end function failed
     395              : 
     396              : 
     397              :       end subroutine Load1_ion_Table
     398              : 
     399              : 
     400           22 :       subroutine Make_ion_Interpolation_Data(tbl, info)
     401              :          use interp_2d_lib_db
     402              :          use const_def, only: crad, ln10
     403              : 
     404              :          real(dp) :: tbl(sz_per_ion_point, num_ion_vals, ion_num_logQs, ion_num_logTs)
     405              :          integer, intent(out) :: info
     406              : 
     407         3872 :          real(dp) :: logQs(ion_num_logQs)              ! x vector, strict ascending
     408         2266 :          real(dp) :: logTs(ion_num_logTs)                    ! y vector, strict ascending
     409              :          real(dp) :: Ts(ion_num_logTs)
     410           22 :          real(dp), allocatable, target :: f1_ary(:)  ! data & spline coefficients
     411           22 :          real(dp), pointer :: f1(:), f(:,:,:)
     412              :          integer :: ibcxmin                   ! bc flag for x=xmin
     413         2266 :          real(dp) :: bcxmin(ion_num_logTs)    ! bc data vs. y at x=xmin
     414              :          integer :: ibcxmax                   ! bc flag for x=xmax
     415         2266 :          real(dp) :: bcxmax(ion_num_logTs)     ! bc data vs. y at x=xmax
     416              :          integer :: ibcymin                   ! bc flag for y=ymin
     417         3872 :          real(dp) :: bcymin(ion_num_logQs)   ! bc data vs. x at y=ymin
     418              :          integer :: ibcymax                   ! bc flag for y=ymax
     419         3894 :          real(dp) :: bcymax(ion_num_logQs)   ! bc data vs. x at y=ymax
     420              :          integer :: ili_logQs    ! =1: logRho grid is "nearly" equally spaced
     421              :          integer :: ili_logTs      ! =1: logT grid is "nearly" equally spaced
     422              :          integer :: ier            ! =0 on exit if there is no error.
     423              :          real(dp) :: logQ, Rho, logRho, T, P, Cv, chiRho, chiT, logT, logT0, logT1, logQ0, logQ1
     424              :          real(dp) :: gamma3, gamma1, grad_ad, Prad, E, S
     425              :          integer :: iQ, jtemp, ilogT, ilogQ
     426              :          real(dp) :: fval(num_ion_vals), df_dx(num_ion_vals), df_dy(num_ion_vals)
     427              : 
     428              :          integer :: v, vlist(3), var, i, j
     429              :          character (len=256) :: message
     430              : 
     431           22 :          allocate(f1_ary(sz_per_ion_point*ion_num_logQs*ion_num_logTs))
     432              : 
     433           22 :          f1 => f1_ary
     434              :          f(1:sz_per_ion_point,1:ion_num_logQs,1:ion_num_logTs) => &
     435           22 :             f1_ary(1:sz_per_ion_point*ion_num_logQs*ion_num_logTs)
     436              : 
     437           22 :          info = 0
     438              : 
     439         3872 :          do iQ = 1, ion_num_logQs
     440         3872 :             logQs(iQ) = ion_logQ_min + (iQ-1) * ion_del_logQ
     441              :          end do
     442              : 
     443         2266 :          do jtemp = 1, ion_num_logTs
     444         2266 :             logTs(jtemp) = ion_logT_min + (jtemp-1) * ion_del_logT
     445              :          end do
     446              : 
     447              :          ! just use "not a knot" bc's at edges of tables
     448         2266 :          ibcxmin = 0; bcxmin(:) = 0
     449         2266 :          ibcxmax = 0; bcxmax(:) = 0
     450         3872 :          ibcymin = 0; bcymin(:) = 0
     451         3872 :          ibcymax = 0; bcymax(:) = 0
     452              : 
     453              :          ! create tables for bicubic spline interpolation
     454          638 :          do v = 1, num_ion_vals
     455              : 
     456     11059048 :             f(1,:,:) = tbl(1,v,:,:)
     457              :             call interp_mkbicub_db(&
     458              :                   logQs,ion_num_logQs,logTs,ion_num_logTs,f1,ion_num_logQs,&
     459              :                   ibcxmin,bcxmin,ibcxmax,bcxmax,&
     460              :                   ibcymin,bcymin,ibcymax,bcymax,&
     461          616 :                   ili_logQs,ili_logTs,ier)
     462          616 :             if (ier /= 0) then
     463            0 :                write(*,*) 'Make_ion_Interpolation_Data error happened for ion_value', v
     464            0 :                info = 3
     465            0 :                return
     466              :             end if
     467     44045870 :             tbl(2:4,v,:,:) = f(2:4,:,:)
     468              : 
     469              :          end do
     470              : 
     471           44 :       end subroutine Make_ion_Interpolation_Data
     472              : 
     473              : 
     474           44 :       subroutine Read_ion_Cache(X, Z, tbl, cache_filename, ios)
     475              :          real(dp), intent(in) :: X, Z
     476              :          real(dp) :: tbl(sz_per_ion_point, num_ion_vals, ion_num_logQs, ion_num_logTs)
     477              :          character (*), intent(in) :: cache_filename
     478              :          integer, intent(out) :: ios
     479              : 
     480              :          integer :: io_unit  ! use this for file access
     481              : 
     482           44 :          real(dp) :: X_in, Z_in, logT_min_in, logT_max_in, del_logT_in, &
     483           44 :                logQ_min_in, logQ_max_in, del_logQ_in
     484              :          integer :: num_logQs_in, num_logTs_in, version_in
     485              :          real(dp), parameter :: tiny = 1d-6
     486              : 
     487           44 :          ios = 0
     488              :          open(newunit=io_unit,file=trim(cache_filename),action='read',&
     489           44 :                status='old',iostat=ios,form='unformatted')
     490           44 :          if (ios /= 0) return
     491              : 
     492              :          read(io_unit, iostat=ios) &
     493           22 :                X_in, Z_in, num_logTs_in, logT_min_in, logT_max_in, del_logT_in, &
     494           44 :                num_logQs_in, logQ_min_in, logQ_max_in, del_logQ_in, version_in
     495           22 :          if (ios /= 0) return
     496              : 
     497           22 :          if (ion_version /= version_in) then
     498            0 :             ios = 1
     499            0 :             write(*,*) 'read cache failed for version_in'
     500              :          end if
     501           22 :          if (ion_num_logQs /= num_logQs_in) then
     502            0 :             ios = 1
     503            0 :             write(*,*) 'read cache failed for ion_num_logQs'
     504              :          end if
     505           22 :          if (ion_num_logTs /= num_logTs_in) then
     506            0 :             ios = 1
     507            0 :             write(*,*) 'read cache failed for ion_num_logTs'
     508              :          end if
     509           22 :          if (abs(X-X_in) > tiny) then
     510            0 :             ios = 1
     511            0 :             write(*,*) 'read cache failed for X_in'
     512              :          end if
     513           22 :          if (abs(Z-Z_in) > tiny) then
     514            0 :             ios = 1
     515            0 :             write(*,*) 'read cache failed for Z_in'
     516              :          end if
     517           22 :          if (abs(ion_logT_min-logT_min_in) > tiny) then
     518            0 :             ios = 1
     519            0 :             write(*,*) 'read cache failed for ion_logT_min'
     520              :          end if
     521           22 :          if (abs(ion_logT_max-logT_max_in) > tiny) then
     522            0 :             ios = 1
     523            0 :             write(*,*) 'read cache failed for ion_logT_max'
     524              :          end if
     525           22 :          if (abs(ion_del_logT-del_logT_in) > tiny) then
     526            0 :             ios = 1
     527            0 :             write(*,*) 'read cache failed for ion_del_logT'
     528              :          end if
     529           22 :          if (abs(ion_logQ_min-logQ_min_in) > tiny) then
     530            0 :             ios = 1
     531            0 :             write(*,*) 'read cache failed for ion_logQ_min'
     532              :          end if
     533           22 :          if (abs(ion_logQ_max-logQ_max_in) > tiny) then
     534            0 :             ios = 1
     535            0 :             write(*,*) 'read cache failed for ion_logQ_max'
     536              :          end if
     537           22 :          if (abs(ion_del_logQ-del_logQ_in) > tiny) then
     538            0 :             ios = 1
     539            0 :             write(*,*) 'read cache failed for ion_del_logQ'
     540              :          end if
     541              : 
     542           22 :          if (ios /= 0) then
     543            0 :             close(io_unit); return
     544              :          end if
     545              : 
     546              :          read(io_unit, iostat=ios) tbl(1:sz_per_ion_point, &
     547           22 :                         1:num_ion_vals, 1:ion_num_logQs, 1:ion_num_logTs)
     548           22 :          if (ios /= 0) then
     549            0 :             close(io_unit); return
     550              :          end if
     551              : 
     552           22 :          close(io_unit)
     553              : 
     554              :       end subroutine Read_ion_Cache
     555              : 
     556              :       end module ion_tables_load
        

Generated by: LCOV version 2.0-1