LCOV - code coverage report
Current view: top level - kap/private - load_co_kap.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 77.7 % 466 362
Test Date: 2025-05-08 18:23:42 Functions: 100.0 % 15 15

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2019  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 load_CO_kap
      21              : 
      22              :    use kap_def
      23              :    use math_lib
      24              :    use const_def, only: dp, use_mesa_temp_cache
      25              :    use utils_lib, only: mesa_error, mv, switch_str
      26              : 
      27              :    implicit none
      28              : 
      29              :    private
      30              :    public :: min_version
      31              :    public :: setup_kap_co_tables
      32              :    public :: get_dx_lookup
      33              :    public :: load_one_CO
      34              : 
      35              :    integer, parameter :: min_version = 37
      36              :    logical, parameter :: CO_dbg = .false.
      37              : 
      38              : contains
      39              : 
      40           11 :    subroutine Setup_Kap_CO_Tables(rq, co_z_tables, use_cache, load_on_demand, ierr)
      41              :     type (Kap_General_Info), pointer :: rq
      42              :     type (Kap_CO_Z_Table), dimension(:), pointer :: co_z_tables
      43              :     logical, intent(in) :: use_cache, load_on_demand
      44              :     integer, intent(out) :: ierr
      45              :     integer :: iz, ix, CO_option
      46              :     include 'formats'
      47           11 :     ierr = 0
      48           11 :     CO_option = rq% kap_CO_option
      49           11 :     if (.not. associated(co_z_tables)) then
      50           81 :        allocate(co_z_tables(num_kap_CO_Zs(CO_option)), STAT=ierr)
      51            9 :        if (ierr /= 0) return
      52           81 :        do iz = 1, num_kap_CO_Zs(CO_option)
      53           72 :           co_z_tables(iz)% Zbase = kap_CO_Zs(iz, CO_option)
      54           72 :           co_z_tables(iz)% log10_Zbase = safe_log10(kap_CO_Zs(iz, CO_option))
      55           72 :           co_z_tables(iz)% Zfrac_C = -1
      56           72 :           co_z_tables(iz)% Zfrac_N = -1
      57           72 :           co_z_tables(iz)% Zfrac_O = -1
      58           72 :           co_z_tables(iz)% Zfrac_Ne = -1
      59          432 :           allocate(co_z_tables(iz)% x_tables(num_kap_CO_Xs(CO_option)), STAT=ierr)
      60           81 :           if (ierr /= 0) return
      61              :        end do
      62              :        if (show_allocations) write(*,2) 'setup co_z_tables', &
      63              :              num_kap_CO_Zs(CO_option) + num_kap_CO_Zs(CO_option)*num_kap_CO_Xs(CO_option)
      64              :     end if
      65           99 :     do iz = 1, num_kap_CO_Zs(CO_option)
      66          539 :        do ix = 1, num_kap_CO_Xs(CO_option)
      67          440 :           call load_one_CO(rq,co_z_tables,iz,ix,load_on_demand,ierr)
      68          528 :           if (ierr /= 0) return
      69              :        end do
      70              :     end do
      71              :   end subroutine Setup_Kap_CO_Tables
      72              : 
      73              : 
      74          888 :   subroutine load_one_CO(rq, co_z_tables, iz, ix, read_later, ierr)
      75              :     use utils_lib
      76              :     type (Kap_General_Info), pointer :: rq
      77              :     type (Kap_CO_Z_Table), dimension(:), pointer :: co_z_tables
      78              :     integer, intent(in) :: iz, ix
      79              :     logical, intent(in) :: read_later
      80              :     integer, intent(out) :: ierr
      81              : 
      82              :     character (len=256) :: fname, filename, cache_filename, temp_cache_filename
      83              : 
      84              :     ierr = 0
      85              : 
      86              :     call Get_CO_Filenames(rq, &
      87              :          kap_CO_Zs(iz, rq% kap_CO_option), kap_CO_Xs(ix, rq% kap_CO_option), kap_dir, fname, filename, &
      88          444 :          cache_filename, temp_cache_filename, ierr)
      89          444 :     if (ierr /= 0) return
      90              : 
      91          444 :     if (rq% show_info) write(*,*) 'read filename <' // trim(filename) // '>'
      92              : 
      93              :     call Prepare_Kap_CO_X_Table(rq, &
      94              :        iz, co_z_tables, co_z_tables(iz)% x_tables, &
      95              :        ix, kap_CO_Xs(ix, rq% kap_CO_option), kap_CO_Zs(iz, rq% kap_CO_option), &
      96              :        read_later, fname, filename, &
      97          444 :        cache_filename, temp_cache_filename, ierr)
      98          444 :     if (ierr /= 0) return
      99              : 
     100          444 :     if (.not. read_later) co_z_tables(iz)% x_tables(ix)% not_loaded_yet = .false.
     101              : 
     102              :   end subroutine load_one_CO
     103              : 
     104              : 
     105          888 :   subroutine Prepare_Kap_CO_X_Table(rq, &
     106              :        iz, co_z_tables, x_tables, ix, X_in, Z_in, read_later, &
     107              :        fname, filename, cache_filename, temp_cache_filename, ierr)
     108              :     ! allocates the arrays and stores data
     109              :     type (Kap_General_Info), pointer :: rq
     110              :     type (Kap_CO_Z_Table), dimension(:), pointer :: co_z_tables
     111              :     type (Kap_CO_X_Table), dimension(:), pointer :: x_tables
     112              :     integer, intent(in) :: iz, ix
     113              :     real(dp), intent(in) :: X_in, Z_in  ! expected contents of the Kap file
     114              :     logical, intent(in) :: read_later
     115              :     character (len=*), intent(in) :: fname, filename, cache_filename, temp_cache_filename
     116              :     integer, intent(out) :: ierr
     117              : 
     118              :     integer :: io_unit, cache_io_unit
     119              : 
     120              :     real(dp) :: X, Z
     121              :     integer :: ios, form, version, n, num_tables, num_logRs, num_logTs, status
     122          444 :     real(dp) :: xin, zz, Zfrac_C, Zfrac_N, Zfrac_O, Zfrac_Ne, &
     123          888 :          logR_min, logR_max, logT_min, logT_max, xErr, zErr
     124          444 :     type (Kap_CO_Table), dimension(:), pointer :: co_tables
     125              :     integer :: num_dXC_gt_dXO  ! the number of tables with dXC > dXO
     126              :     integer :: CO_table_numbers(num_kap_CO_dXs,num_kap_CO_dXs)
     127              :     integer :: next_dXO_table(max_num_CO_tables)
     128              :     integer :: next_dXC_table(max_num_CO_tables)
     129              :     character (len=256) :: message
     130        13764 :     real(dp), target :: vec_ary(30)
     131              :     real(dp), pointer :: vec(:)
     132              :     integer :: nvec
     133              :     real(dp), parameter :: tiny = 1d-6
     134              :     include 'formats'
     135              : 
     136          444 :     ierr = 0
     137          444 :     Zfrac_C = 0.d0
     138          444 :     Zfrac_N = 0.d0
     139          444 :     Zfrac_O = 0.d0
     140          444 :     Zfrac_Ne = 0.d0
     141              : 
     142          444 :     vec => vec_ary
     143          444 :     X = X_in
     144          444 :     Z = Z_in
     145          444 :     form = 0
     146          444 :     nvec=-1
     147              : 
     148          444 :     num_dXC_gt_dXO = -1
     149        32412 :     CO_table_numbers = -1
     150        31524 :     next_dXO_table = -1
     151        31524 :     next_dXC_table = -1
     152              : 
     153          444 :     open(newunit=io_unit,file=trim(filename),action='read',status='old',iostat=ios)
     154          444 :     if (ios /= 0) then
     155            0 :        write(*,'(A)')
     156            0 :        write(*,'(A)')
     157            0 :        write(*,'(A)')
     158            0 :        write(*,'(A)')
     159            0 :        write(*,*) 'NOTICE: missing kap data ' // trim(filename)
     160            0 :        write(*,*)
     161            0 :        write(*,*) 'Please check the validity of the kap_prefix string for this file.'
     162            0 :        write(*,*)
     163            0 :        write(*,*) 'If it is okay, you may need to install new kap data.'
     164            0 :        write(*,*) 'To do that, remove the directory mesa/data/kap_data,'
     165            0 :        write(*,*) 'and rerun the mesa ./install script.'
     166            0 :        write(*,'(A)')
     167            0 :        call mesa_error(__FILE__,__LINE__)
     168              :     end if
     169              : 
     170          444 :     version = -1
     171          444 :     read(io_unit,*,iostat=ierr)  ! skip the 1st line
     172          444 :     if (ierr == 0) then
     173          444 :        read(io_unit,*,iostat=ierr)  ! skip the 2nd line
     174          444 :        if (ierr == 0) then
     175          444 :           read(io_unit,'(a)',iostat=ierr) message
     176          444 :           if (ierr == 0) call str_to_vector(message, vec, nvec, ierr)
     177          444 :           if (nvec < 15) ierr = -1
     178          444 :           if (ierr == 0) then
     179          444 :              form = int(vec(1))
     180          444 :              version = int(vec(2))
     181          444 :              num_tables = int(vec(3))
     182          444 :              xin = vec(4)
     183          444 :              zz = vec(5)
     184          444 :              Zfrac_C = vec(6)
     185          444 :              Zfrac_N = vec(7)
     186          444 :              Zfrac_O = vec(8)
     187          444 :              Zfrac_Ne = vec(9)
     188          444 :              num_logRs = int(vec(10))
     189          444 :              logR_min = vec(11)
     190          444 :              logR_max = vec(12)
     191          444 :              num_logTs = int(vec(13))
     192          444 :              logT_min = vec(14)
     193          444 :              logT_max = vec(15)
     194              :           end if
     195              :        end if
     196              :     end if
     197              : 
     198          444 :     if (ierr /= 0 .or. version < min_version) then
     199            0 :        write(*,'(A)')
     200            0 :        write(*,'(A)')
     201            0 :        write(*,'(A)')
     202            0 :        write(*,'(A)')
     203            0 :        write(*,'(A)')
     204            0 :        write(*,*) 'FATAL ERROR: out-of-date version of kap data ' // trim(filename)
     205            0 :        write(*,*) 'Please update by removing the directory mesa/data/kap_data,'
     206            0 :        write(*,*) 'and rerunning the mesa ./install script.'
     207            0 :        write(*,'(A)')
     208            0 :        call mesa_error(__FILE__,__LINE__)
     209              :     end if
     210              : 
     211          444 :     if (form /= kap_table_co_enhanced_form) then
     212            0 :        call mesa_error(__FILE__,__LINE__,'form /= kap_table_co_enhanced_form')
     213              :     end if
     214              : 
     215          444 :     if (max_num_CO_tables < num_tables) then
     216            0 :        ierr = -1
     217          442 :        return
     218              :     end if
     219              : 
     220          444 :     if (Zfrac_C < 0 .or. Zfrac_N < 0 .or. Zfrac_O < 0 .or. Zfrac_Ne < 0) then
     221            0 :        ierr = -1
     222            0 :        return
     223              :     end if
     224              : 
     225          444 :     co_z_tables(iz)% Zfrac_C = Zfrac_C
     226          444 :     co_z_tables(iz)% Zfrac_N = Zfrac_N
     227          444 :     co_z_tables(iz)% Zfrac_O = Zfrac_O
     228          444 :     co_z_tables(iz)% Zfrac_Ne = Zfrac_Ne
     229              : 
     230          444 :     call Setup_Kap_CO_X_Table(ierr)
     231          444 :     if (ierr /= 0) return
     232              : 
     233              :     if (CO_dbg) write(*,*) 'after Setup_Kap_CO_X_Table: associated co_tables', &
     234              :          associated(x_tables(ix)% co_tables), ix
     235              : 
     236          444 :     if (read_later) then
     237          440 :        close(io_unit)
     238          440 :        return
     239              :     end if
     240              : 
     241            4 :     if (kap_use_cache) then
     242              :        open(newunit=cache_io_unit,file=trim(cache_filename),action='read', &
     243            4 :             status='old',iostat=ios,form='unformatted')
     244            4 :        if (ios == 0) then  ! try reading the cached data
     245            2 :           call Read_Kap_CO_X_Table(cache_io_unit, .true., ierr)
     246            2 :           close(cache_io_unit)
     247            2 :           if (ierr == 0) then
     248            2 :              close(io_unit)
     249            2 :              return
     250              :           end if
     251              :           ierr = 0
     252              :        else
     253              :           if (CO_dbg) write(*,'(a)') 'failed to open ' // trim(cache_filename)
     254              :        end if
     255              :     end if
     256              : 
     257              :     if (CO_dbg) write(*,*) 'before call: associated co_tables', &
     258              :          associated(x_tables(ix)% co_tables), ix
     259              :     if (show_allocations) write(*,2) 'loading ' // trim(filename)
     260            2 :     call Read_Kap_CO_X_Table(io_unit, .false., ierr)
     261            2 :     close(io_unit)
     262            2 :     if (ierr /= 0) then
     263            0 :        write(*,*) 'failed in Read_Kap_CO_X_Table ' // trim(filename)
     264            0 :        return
     265              :     end if
     266              : 
     267            2 :     if (.not. kap_use_cache) return
     268              : 
     269              :     open(newunit=cache_io_unit, file=trim(switch_str(temp_cache_filename, cache_filename, use_mesa_temp_cache)),&
     270            2 :          iostat=ios, action='write', form='unformatted')
     271            2 :     if (ios == 0) then
     272            2 :        write(*,'(a)') 'write ' // trim(cache_filename)
     273              :        call Write_Kap_CO_X_Table_Cache( &
     274              :             x_tables, ix, cache_io_unit, x_tables(ix)% num_logRs,  &
     275            2 :             x_tables(ix)% num_logTs, version)
     276            2 :        close(cache_io_unit)
     277            2 :        if(use_mesa_temp_cache) call mv(temp_cache_filename, cache_filename,.true.)
     278            2 :        if (kap_read_after_write_cache) then
     279              :           open(newunit=cache_io_unit,file=trim(cache_filename),action='read', &
     280            2 :                status='old',iostat=ios,form='unformatted')
     281            2 :           if (ios == 0) then
     282            2 :              call Read_Kap_CO_X_Table(cache_io_unit, .true., ierr)
     283            2 :              close(cache_io_unit)
     284              :           else
     285            0 :              ierr = -1
     286              :           end if
     287              :        end if
     288              :     end if
     289              : 
     290              : 
     291              :   contains
     292              : 
     293              : 
     294          444 :     subroutine Setup_Kap_CO_X_Table(ierr)
     295              :       integer, intent(out) :: ierr
     296              : 
     297              :       integer :: i
     298              :       include 'formats'
     299              : 
     300          444 :       xErr = abs(xin - X); zErr = abs(zz - Z)
     301          444 :       if (num_tables <= 0 .or. xErr > tiny .or. zErr > tiny) then
     302            0 :          ierr = -1
     303            0 :          write(*,*) 'bug in file ' // trim(filename), num_tables, xErr, zErr
     304            0 :          write(*,*) 'num_tables <= 0', num_tables <= 0
     305            0 :          write(*,*) 'xErr > tiny', xErr > tiny
     306            0 :          write(*,*) 'zErr > tiny', zErr > tiny
     307            0 :          return
     308              :       end if
     309              : 
     310          444 :       x_tables(ix)% not_loaded_yet = .true.
     311              : 
     312          444 :       x_tables(ix)% X = X
     313          444 :       x_tables(ix)% Z = Z
     314              : 
     315          444 :       x_tables(ix)% logR_min = logR_min
     316          444 :       x_tables(ix)% logR_max = logR_max
     317          444 :       x_tables(ix)% num_logRs = num_logRs
     318          444 :       nullify(x_tables(ix)% logRs)
     319              : 
     320          444 :       x_tables(ix)% logT_min = logT_min
     321          444 :       x_tables(ix)% logT_max = logT_max
     322          444 :       x_tables(ix)% num_logTs = num_logTs
     323          444 :       nullify(x_tables(ix)% logTs)
     324              : 
     325          444 :       x_tables(ix)% num_CO_tables = num_tables
     326              : 
     327              :       if (show_allocations) write(*,2) 'co_tables', num_tables
     328        22764 :       allocate(co_tables(num_tables), STAT=status)
     329          444 :       if (status /= 0) then
     330            0 :          ierr = -1
     331              :          if (CO_dbg) write(*,*) 'InsufficientMemory for Prepare_Kap_CO_X_Table', iz, ix
     332            0 :          return
     333              :       end if
     334          444 :       x_tables(ix)% co_tables => co_tables
     335              :       if (CO_dbg) write(*,*) 'Setup_Kap_CO_X_Table: allocate co_tables', iz, ix, num_tables, status
     336              :       if (CO_dbg) write(*,*) 'Setup_Kap_CO_X_Table: associated(x_tables(ix)% co_tables)', &
     337              :            associated(x_tables(ix)% co_tables), associated(co_tables), ix
     338              : 
     339        22764 :       do i=1,num_tables
     340        22764 :          nullify(co_tables(i)% kap1)  ! allocate when read the data
     341              :       end do
     342              : 
     343              :     end subroutine Setup_Kap_CO_X_Table
     344              : 
     345              : 
     346            6 :     subroutine Read_Kap_CO_X_Table(io_unit, reading_cache, ierr)
     347              :       integer, intent(in) :: io_unit  ! use this for file access
     348              :       logical, intent(in) :: reading_cache
     349              :       integer, intent(out) :: ierr
     350              : 
     351              :       character (len=256) :: message
     352              :       character (len=1) :: char
     353              :       integer :: c_num_tables, c_num_logRs, c_num_logTs, c_version
     354            6 :       real(dp) :: c_xin, c_zz, c_logR_min, c_logR_max, c_logT_min, c_logT_max
     355              : 
     356              :       include 'formats'
     357            6 :       ierr = 0
     358              : 
     359            6 :       if (reading_cache) then
     360              : 
     361            4 :          ios = 0
     362            4 :          read(io_unit, iostat=ios) c_version
     363            4 :          if (ios /= 0 .or. c_version /= version) then
     364            0 :             ierr = 1
     365            0 :             if (ios /= 0) write(*,*) 'cache failed in read'
     366            0 :             if (c_version /= version) write(*,*) 'cache failed for c_version /= version'
     367            0 :             return
     368              :          end if
     369              : 
     370              :          read(io_unit, iostat=ios) &
     371            4 :               c_xin, c_zz, &
     372            4 :               c_logR_min, c_logR_max, c_num_logRs, x_tables(ix)% ili_logRs, &
     373            8 :               c_logT_min, c_logT_max, c_num_logTs, x_tables(ix)% ili_logTs
     374            4 :          if (ios /= 0 .or. c_num_logRs /= num_logRs .or. c_num_logTs /= num_logTs) then
     375            0 :             ierr = 1
     376            0 :             if (ios /= 0) write(*,*) 'cache failed in read'
     377            0 :             if (c_num_logRs /= num_logRs) write(*,*) 'cache failed for c_num_logRs /= num_logRs'
     378            0 :             if (c_num_logTs /= num_logTs) write(*,*) 'cache failed for c_num_logTs /= num_logTs'
     379            0 :             return
     380              :          end if
     381              : 
     382              :          read(io_unit, iostat=ios) &
     383            4 :               c_num_tables, num_dXC_gt_dXO, &
     384            8 :               CO_table_numbers, next_dXO_table, next_dXC_table
     385              : 
     386            4 :          if (ios /= 0) then
     387            0 :             ierr = 1
     388            0 :             if (ios /= 0) write(*,*) 'cache failed in read'
     389            0 :             return
     390              :          end if
     391              : 
     392              :       end if
     393              : 
     394            6 :       xErr = abs(xin - X); zErr = abs(zz - Z)
     395            6 :       if (num_tables <= 0 .or. xErr > tiny .or. zErr > tiny) then
     396            0 :          if (reading_cache) then
     397            0 :             if (num_tables <= 0) write(*,*) 'cache failed for num_tables <= 0'
     398            0 :             if (xErr > tiny) write(*,*) 'cache failed for xErr > tiny'
     399            0 :             if (zErr > tiny) write(*,*) 'cache failed for zErr > tiny'
     400            0 :             ierr = 1; return
     401              :          end if
     402            0 :          ierr = -1
     403            0 :          write(*,*) 'num_tables <= 0', num_tables <= 0
     404            0 :          write(*,*) 'xErr > tiny', xErr > tiny
     405            0 :          write(*,*) 'zErr > tiny', zErr > tiny
     406            0 :          return
     407              :       end if
     408              : 
     409              :       if (show_allocations) write(*,2) 'Read_Kap_CO_X_Table logRs logTs', &
     410              :           num_logRs + num_logTs
     411            6 :       allocate(x_tables(ix)% logRs(num_logRs), x_tables(ix)% logTs(num_logTs), STAT=status)
     412            6 :       if (status /= 0) then
     413            0 :          ierr = -1
     414            0 :          write(*,*) 'InsufficientMemory for Read_Kap_CO_X_Table'
     415            0 :          return
     416              :       end if
     417              : 
     418            6 :       if (.not. reading_cache) then
     419              : 
     420            2 :          read(io_unit,*,iostat=ierr)  ! skip line
     421            2 :          if (ierr /= 0) return
     422            2 :          read(io_unit,'(i3)',iostat=ierr) num_dXC_gt_dXO
     423            2 :          if (ierr /= 0) return
     424            2 :          x_tables(ix)% num_dXC_gt_dXO = num_dXC_gt_dXO
     425              :          do  ! skip to the start of the first table
     426          134 :             read(io_unit,'(a1)',iostat=ierr) char
     427          134 :             if (ierr /= 0) return
     428          134 :             if (char == '-') exit
     429              :          end do
     430            2 :          read(io_unit,*,iostat=ierr)  ! skip line
     431            2 :          if (ierr /= 0) return
     432          146 :          x_tables(ix)% CO_table_numbers = -1
     433          142 :          x_tables(ix)% next_dXC_table = -1
     434          142 :          x_tables(ix)% next_dXO_table = -1
     435              : 
     436              :       else
     437              : 
     438              :          read(io_unit, iostat=ierr) &
     439          152 :               x_tables(ix)% logRs(1:num_logRs), &
     440          560 :               x_tables(ix)% logTs(1:num_logTs)
     441            4 :          if (ierr /= 0) return
     442              : 
     443            4 :          x_tables(ix)% num_dXC_gt_dXO = num_dXC_gt_dXO
     444          292 :          x_tables(ix)% CO_table_numbers = CO_table_numbers
     445          284 :          x_tables(ix)% next_dXO_table = next_dXO_table
     446          284 :          x_tables(ix)% next_dXC_table = next_dXC_table
     447              : 
     448              :       end if
     449              : 
     450          354 :       do n = 1, num_tables
     451              :          if (CO_dbg) write(*,*) 'call Read_Kap_CO_Table', ix, n, X, Z
     452              :          call Read_Kap_CO_Table(x_tables, ix, n, X, Z, &
     453          348 :               num_logRs, num_logTs, io_unit, reading_cache, ierr)
     454          354 :          if (ierr /= 0) return
     455              :       end do
     456              : 
     457            6 :       if (.not. reading_cache) then
     458          118 :          do n = 1, num_tables
     459          116 :             next_dXC_table(n) = find_next_dXC_table(n)
     460          118 :             next_dXO_table(n) = find_next_dXO_table(n)
     461              :          end do
     462          142 :          x_tables(ix)% next_dXO_table = next_dXO_table
     463          142 :          x_tables(ix)% next_dXC_table = next_dXC_table
     464              :       end if
     465              : 
     466              :     end subroutine Read_Kap_CO_X_Table
     467              : 
     468              : 
     469          116 :     integer function find_next_dXC_table(i)
     470              :       integer, intent(in) :: i
     471              :       integer :: j
     472          116 :       real(dp) :: dXC, dXO
     473          116 :       dXC = co_tables(i)% dXC
     474          116 :       dXO = co_tables(i)% dXO
     475          116 :       if (dXC > dXO) then
     476           52 :          find_next_dXC_table = i + 1; return
     477              :       end if
     478         2042 :       do j = 1, num_tables
     479         2042 :          if (co_tables(j)% dXC > dXC .and. co_tables(j)% dXO == dXO) then
     480           50 :             find_next_dXC_table = j; return
     481              :          end if
     482              :       end do
     483          116 :       find_next_dXC_table = -1
     484              :     end function find_next_dXC_table
     485              : 
     486              : 
     487          116 :     integer function find_next_dXO_table(i)
     488              :       integer, intent(in) :: i
     489              :       integer :: j
     490          116 :       real(dp) :: dXC, dXO
     491          116 :       dXC = co_tables(i)% dXC
     492          116 :       dXO = co_tables(i)% dXO
     493          116 :       if (dXC < dXO) then
     494           52 :          find_next_dXO_table = i + 1; return
     495              :       end if
     496         2130 :       do j = 1, num_tables
     497         2130 :          if (co_tables(j)% dXO > dXO .and. co_tables(j)% dXC == dXC) then
     498           50 :             find_next_dXO_table = j
     499           50 :             return
     500              :          end if
     501              :       end do
     502          116 :       find_next_dXO_table = -1
     503              :     end function find_next_dXO_table
     504              : 
     505              : 
     506              :   end subroutine Prepare_Kap_CO_X_Table
     507              : 
     508              : 
     509          348 :   subroutine Read_Kap_CO_Table( &
     510              :        x_tables, ix, n, X_in, Z_in, num_logRs, num_logTs, io_unit, reading_cache, ierr)
     511              :     type (Kap_CO_X_Table), dimension(:), pointer :: x_tables
     512              :     integer, intent(in) :: ix  ! index in x_tables
     513              :     integer, intent(in) :: n  ! index in co_tables
     514              :     real(dp), intent(in) :: X_in, Z_in
     515              :     integer, intent(in) :: io_unit  ! use this for file access
     516              :     logical, intent(in) :: reading_cache
     517              :     integer, intent(in) :: num_logRs, num_logTs
     518              :     integer, intent(out) :: ierr  ! return nonzero if had trouble
     519              : 
     520              :     type (Kap_CO_Table), pointer :: co_tables(:)
     521              :     integer :: table_num, i, j, ios, status, iXC, iXO
     522        13920 :     real(dp) :: X, Z, xin, zz, Y, dXC, dXO, err, logT
     523              :     real(dp), allocatable, target :: kap_table(:)  ! data & spline coefficients
     524          348 :     real(dp), pointer :: kap(:,:,:)
     525        26100 :     real(dp) :: logKs(num_logRs), logRs(num_logRs)
     526              :     character (len=1000) :: message
     527        17748 :     real(dp), target :: vec_ary(50)
     528              :     real(dp), pointer :: vec(:)
     529              :     integer :: nvec
     530              :     real(dp), parameter :: tiny = 1d-6
     531              : 
     532              :     logical :: store_logRs, store_logTs
     533              :     include 'formats'
     534              : 
     535          348 :     ierr = 0
     536          348 :     vec => vec_ary
     537          348 :     X = X_in; Z = Z_in
     538          348 :     nvec=-1
     539              : 
     540              :     if (show_allocations) write(*,2) 'Read_Kap_CO_Table', &
     541              :        sz_per_Kap_point*num_logRs*num_logTs
     542          348 :     allocate(kap_table(sz_per_Kap_point*num_logRs*num_logTs))
     543              : 
     544          348 :     co_tables => x_tables(ix)% co_tables
     545              :     if (CO_dbg) write(*,*) 'Read_Kap_CO_Table associated(co_tables)', &
     546              :          associated(co_tables), ix, reading_cache
     547              : 
     548          348 :     if (.not. reading_cache) then
     549          116 :        read(io_unit,*,iostat=ierr)
     550          116 :        if (ierr /= 0) return
     551          116 :        read(io_unit,'(a)',iostat=ierr) message
     552          116 :        if (ierr == 0) call str_to_vector(message, vec, nvec, ierr)
     553          116 :        if (ierr /= 0 .or. nvec < 6) then
     554            0 :           write(*,*) 'Read_Kap_CO_Table str_to_vector'
     555            0 :           ierr = 1
     556            0 :           return
     557              :        end if
     558          116 :        table_num = int(vec(1))
     559          116 :        xin = vec(2)
     560          116 :        Y = vec(3)
     561          116 :        zz = vec(4)
     562          116 :        dXC = vec(5)
     563          116 :        dXO = vec(6)
     564          116 :        if (table_num /= n) then
     565            0 :           write(*,*) 'wrong num in opacity file for X', X, 'Z', Z, 'table', n
     566            0 :           ierr = -1
     567            0 :           return
     568              :        end if
     569              :     else  ! reading_cache
     570          232 :        read(io_unit, iostat=ios) table_num, xin, Y, zz, dXC, dXO
     571          232 :        if (ios /= 0) then
     572            0 :           ierr = 1
     573            0 :           return
     574              :        end if
     575              :     end if
     576              : 
     577          348 :     if (abs(xin-X) > tiny .or. abs(zz-Z) > tiny) then
     578            0 :        if (reading_cache) then
     579            0 :           ierr = 1
     580            0 :           return
     581              :        end if
     582            0 :        write(*,*) 'error in opacity file for X', X, 'Z', Z, 'table', n
     583            0 :        ierr = -1
     584            0 :        return
     585              :     end if
     586          348 :     X = xin; Z = zz  ! use the values from the file
     587              : 
     588          348 :     err = abs(1d0 - (X + Y + Z + dXC + dXO))
     589          348 :     if (err > tiny) then
     590            0 :        if (reading_cache) then
     591            0 :           ierr = 1; return
     592              :        end if
     593            0 :        write(*,*) 'abundance error in opacity table for X=', &
     594            0 :             X, 'Z=', Z, 'dXC=', dXC, 'dXO=', dXO
     595            0 :        ierr = -1
     596            0 :        return
     597              :     end if
     598              : 
     599          348 :     co_tables(n)% table_num = table_num
     600          348 :     co_tables(n)% X = X
     601          348 :     co_tables(n)% Z = Z
     602          348 :     co_tables(n)% dXC = dXC
     603          348 :     co_tables(n)% dXO = dXO
     604          348 :     co_tables(n)% dXC_lookup = get_dX_lookup(dXC, Z)
     605          348 :     co_tables(n)% dXO_lookup = get_dX_lookup(dXO, Z)
     606              : 
     607              :     if (show_allocations) write(*,2) 'co_tables', &
     608              :        sz_per_Kap_point*num_logRs*num_logTs
     609          348 :     allocate(co_tables(n)% kap1(sz_per_Kap_point*num_logRs*num_logTs), STAT=status)
     610          348 :     if (status /= 0) then
     611            0 :        ierr = -1
     612            0 :        return
     613              :     end if
     614              : 
     615          348 :     if (reading_cache) then
     616              : 
     617          232 :        read(io_unit, iostat=ios) kap_table
     618      4738600 :        do i=1,sz_per_Kap_point*num_logRs*num_logTs
     619      4738600 :           co_tables(n)% kap1(i) = kap_table(i)
     620              :        end do
     621          232 :        if (ios /= 0) then
     622            0 :           ierr = 4; return
     623              :        end if
     624              : 
     625              :     else
     626              : 
     627          116 :        iXC = find_in_dXs(dXC)
     628          116 :        if (iXC > 0) then
     629          104 :           iXO = find_in_dXs(dXO)
     630          104 :           if (iXO > 0) then
     631           92 :              x_tables(ix)% CO_table_numbers(iXC,iXO) = n
     632              :           end if
     633              :        end if
     634              : 
     635          116 :        read(io_unit,*,iostat=ierr)
     636          116 :        if (ierr /= 0) return
     637          116 :        read(io_unit,*,iostat=ierr)
     638          116 :        if (ierr /= 0) return
     639              : 
     640          116 :        read(io_unit,'(a)',iostat=ierr) message
     641          116 :        if (ierr == 0) call str_to_vector(message, vec, nvec, ierr)
     642          116 :        if (ierr /= 0) write(*,*) 'str_to_vector ierr', ierr
     643          116 :        if (nvec < num_logRs) ierr = -1
     644          116 :        if (ierr /= 0) then
     645            0 :           write(*,*) 'Read_Kap_CO_Table str_to_vector logRs: nvec, num_logRs', nvec, num_logRs
     646            0 :           write(*,'(a)') trim(message)
     647            0 :           stop
     648              :           return
     649              :        end if
     650         4408 :        do i=1,num_logRs
     651         4408 :           logRs(i) = vec(i)
     652              :        end do
     653              : 
     654          116 :        if (n == 1) then
     655           76 :           x_tables(ix)% logRs(:) = logRs(:)
     656              :        else  ! check
     657         4332 :           do i=1, num_logRs
     658         4332 :              if (abs(logRs(i) - x_tables(ix)% logRs(i)) > 1d-7) then
     659            0 :                 write(*,*) 'problem with inconsistent logRs'
     660            0 :                 call mesa_error(__FILE__,__LINE__)
     661              :              end if
     662              :           end do
     663              :        end if
     664              : 
     665          116 :        read(io_unit,*,iostat=ierr)
     666          116 :        if (ierr /= 0) return
     667              : 
     668              :        kap(1:sz_per_Kap_point,1:num_logRs,1:num_logTs) => &
     669          116 :             co_tables(n)% kap1(1:sz_per_Kap_point*num_logRs*num_logTs)
     670              : 
     671        16124 :        do i = 1, num_logTs
     672              : 
     673        16008 :           read(io_unit,'(a)',iostat=ierr) message
     674        16008 :           if (ierr == 0) call str_to_vector(message, vec, nvec, ierr)
     675        16008 :           if (nvec < 1+num_logRs) ierr = -1
     676        16008 :           if (ierr /= 0) then
     677            0 :              write(*,*) 'Read_Kap_CO_Table str_to_vector logKs'
     678            0 :              return
     679              :           end if
     680        16008 :           logT = vec(1)
     681       608304 :           do j=1,num_logRs
     682       592296 :              logKs(j) = vec(j+1)
     683       608304 :              kap(1,j,i) = logKs(j)
     684              :           end do
     685              : 
     686        16124 :           if (n == 1) then
     687          276 :              x_tables(ix)% logTs(i) = logT
     688              :           else  ! check
     689        15732 :              if (abs(logT - x_tables(ix)% logTs(i)) > 1d-7) then
     690            0 :                 write(*,*) 'problem with inconsistent logTs'
     691            0 :                 call mesa_error(__FILE__,__LINE__)
     692              :              end if
     693              :           end if
     694              : 
     695              :        end do
     696          116 :        read(io_unit,*,iostat=ierr)
     697          116 :        if (ierr /= 0) return
     698              : 
     699              :        call Make_CO_Interpolation_Data( &
     700              :             co_tables, n, x_tables(ix)% logRs, num_logRs, &
     701              :             x_tables(ix)% logTs, num_logTs, &
     702          116 :             x_tables(ix)% ili_logRs, x_tables(ix)% ili_logTs, ierr)
     703              : 
     704          116 :        if (ierr /= 0) then
     705            0 :           write(*,*) 'call Make_CO_Interpolation_Data ierr', ierr
     706            0 :           write(*,*) 'n', n
     707            0 :           write(*,*) 'num_logRs', num_logRs
     708            0 :           write(*,*) 'num_logTs', num_logTs
     709              :        end  if
     710              : 
     711              :     end if
     712              : 
     713          696 :   end subroutine Read_Kap_CO_Table
     714              : 
     715              : 
     716          116 :   subroutine Make_CO_Interpolation_Data( &
     717              :        co_tables, n, logRs, num_logRs, logTs, num_logTs, ili_logRs, ili_logTs, ierr)
     718              :     use interp_2d_lib_db
     719              :     type (Kap_CO_Table), dimension(:), pointer :: co_tables
     720              :     integer, intent(in) :: n, num_logRs, num_logTs
     721              :     real(dp), intent(in), pointer :: logRs(:)  ! =(num_logRs)
     722              :     real(dp), intent(in), pointer :: logTs(:)  ! =(num_logTs)
     723              :     integer, intent(out) :: ili_logRs, ili_logTs, ierr
     724              : 
     725      2369300 :     real(dp), target :: table_ary(sz_per_kap_point*num_logRs*num_logTs)
     726          116 :     real(dp), pointer :: table(:,:,:), table1(:), kap(:,:,:)
     727              :     character (len=256) :: message
     728              :     integer :: ibcxmin                   ! bc flag for x=xmin
     729        16124 :     real(dp) :: bcxmin(num_logTs)               ! bc data vs. y at x=xmin
     730              :     integer :: ibcxmax                   ! bc flag for x=xmax
     731        16124 :     real(dp) :: bcxmax(num_logTs)               ! bc data vs. y at x=xmax
     732              :     integer :: ibcymin                   ! bc flag for y=ymin
     733         4408 :     real(dp) :: bcymin(num_logRs)               ! bc data vs. x at y=ymin
     734              :     integer :: ibcymax                   ! bc flag for y=ymax
     735         4408 :     real(dp) :: bcymax(num_logRs)               ! bc data vs. x at y=ymax
     736              :     integer :: ier                       ! =0 on exit if there is no error.
     737              :     integer :: i, j
     738              :     real(dp) :: tol
     739              :     real(dp), pointer :: x_out(:), y_out(:), f_out(:,:)
     740              : 
     741              :     ! just use "not a knot" bc's at edges of tables
     742        16124 :     ibcxmin = 0; bcxmin(1:num_logTs) = 0d0
     743        16124 :     ibcxmax = 0; bcxmax(1:num_logTs) = 0d0
     744         4408 :     ibcymin = 0; bcymin(1:num_logRs) = 0d0
     745         4408 :     ibcymax = 0; bcymax(1:num_logRs) = 0d0
     746              : 
     747          116 :     table1 => table_ary
     748              :     table(1:sz_per_kap_point,1:num_logRs,1:num_logTs) => &
     749          116 :          table_ary(1:sz_per_kap_point*num_logRs*num_logTs)
     750              :     kap(1:sz_per_kap_point,1:num_logRs,1:num_logTs) => &
     751          116 :          co_tables(n)% kap1(1:sz_per_kap_point*num_logRs*num_logTs)
     752              : 
     753        16124 :     do j=1,num_logTs
     754       608420 :        do i=1,num_logRs
     755       608304 :           table(1,i,j) = kap(1,i,j)
     756              :        end do
     757              :     end do
     758              : 
     759              :     call interp_mkbicub_db( &
     760              :          logRs, num_logRs, logTs, num_logTs, table1, num_logRs, &
     761              :          ibcxmin,bcxmin,ibcxmax,bcxmax, &
     762              :          ibcymin,bcymin,ibcymax,bcymax, &
     763          116 :          ili_logRs,ili_logTs,ier)
     764              : 
     765          116 :     if (ier /= 0) then
     766            0 :        write(*,*) 'interp_mkbicub_db error happened for Make_CO_Interpolation_Data for table', n
     767            0 :        ierr = -1
     768              :        return
     769              :     end if
     770              : 
     771          116 :     call Check_Interpolation_Data
     772              : 
     773      2369300 :     do i=1,sz_per_kap_point*num_logRs*num_logTs
     774      2369300 :        co_tables(n)% kap1(i) = table1(i)
     775              :     end do
     776              : 
     777          232 :     ierr = 0
     778              : 
     779              : 
     780              :   contains
     781              : 
     782          116 :     subroutine Check_Interpolation_Data
     783              :       use utils_lib,only:is_bad
     784              :       integer :: i, iR, jtemp
     785          116 :       real(dp) :: val
     786              : 
     787          580 :       do i = 1, sz_per_kap_point
     788        17748 :          do iR = 1, num_logRs
     789      2386816 :             do jtemp = 1, num_logTs
     790      2369184 :                val = table(i,iR,jtemp)
     791      2386352 :                if (is_bad(val)) then
     792              :                   if (.true.) then
     793            0 :                      write(*,*) 'bad value in xz', val, i, iR, jtemp
     794              :                      write(*,'(99(a15,3x,f15.8,3x))')  &
     795            0 :                           'logR', logRs(iR), 'logT', logTs(jtemp)
     796              :                   end if
     797            0 :                   table(i,iR,jtemp) = 0
     798              :                end if
     799              :             end do
     800              :          end do
     801              :       end do
     802              : 
     803          116 :     end subroutine Check_Interpolation_Data
     804              : 
     805              : 
     806              :   end subroutine Make_CO_Interpolation_Data
     807              : 
     808              : 
     809            2 :   subroutine Write_Kap_CO_X_Table_Cache(x_tables, ix, io_unit, num_logRs, num_logTs, version)
     810              :     type (Kap_CO_X_Table), dimension(:), pointer :: x_tables
     811              :     integer, intent(in) :: ix, io_unit, num_logRs, num_logTs, version
     812              : 
     813            2 :     type (Kap_CO_Table), dimension(:), pointer :: co_tables
     814              : 
     815              :     integer :: num_tables, n, i
     816            2 :     real(dp) :: X, Z, Y, dXC, dXO
     817              :     real(dp), allocatable, target :: kap_table(:)  ! data & spline coefficients
     818              :     include 'formats'
     819              : 
     820              :     if (show_allocations) write(*,2) 'Write_Kap_CO_X_Table_Cache', &
     821              :        sz_per_Kap_point*num_logRs*num_logTs
     822            2 :     allocate(kap_table(sz_per_Kap_point*num_logRs*num_logTs))
     823              : 
     824            2 :     num_tables = x_tables(ix)% num_CO_tables
     825            2 :     X = x_tables(ix)% X
     826            2 :     Z = x_tables(ix)% Z
     827            2 :     co_tables => x_tables(ix)% co_tables
     828              : 
     829            2 :     write(io_unit) version
     830              : 
     831              :     write(io_unit) &
     832            2 :          X, Z, &
     833            2 :          x_tables(ix)% logR_min, &
     834            2 :          x_tables(ix)% logR_max, &
     835            2 :          num_logRs, x_tables(ix)% ili_logRs, &
     836            2 :          x_tables(ix)% logT_min, &
     837            2 :          x_tables(ix)% logT_max, &
     838            4 :          num_logTs, x_tables(ix)% ili_logTs
     839              : 
     840              :     write(io_unit) &
     841            2 :          num_tables, x_tables(ix)% num_dXC_gt_dXO, &
     842          146 :          x_tables(ix)% CO_table_numbers(:,:), &
     843          142 :          x_tables(ix)% next_dXO_table(:), &
     844          144 :          x_tables(ix)% next_dXC_table(:)
     845              : 
     846              :     write(io_unit) &
     847           76 :          x_tables(ix)% logRs(1:num_logRs), &
     848          280 :          x_tables(ix)% logTs(1:num_logTs)
     849              : 
     850          118 :     do n = 1, num_tables
     851          116 :        dXC = co_tables(n)% dXC
     852          116 :        dXO = co_tables(n)% dXO
     853          116 :        Y = 1 - (X + Z + dXC + dXO)
     854      2369300 :        do i=1,sz_per_Kap_point*num_logRs*num_logTs
     855      2369300 :           kap_table(i) = co_tables(n)% kap1(i)
     856              :        end do
     857          116 :        write(io_unit) co_tables(n)% table_num, X, Y, Z, dXC, dXO
     858          118 :        write(io_unit) kap_table
     859              :     end do
     860              : 
     861            4 :   end subroutine Write_Kap_CO_X_Table_Cache
     862              : 
     863              : 
     864          356 :   real(dp) function get_dX_lookup(dX, Z)
     865              :     real(dp), intent(in) :: dX, Z
     866          348 :     get_dX_lookup = log10(Z + 1d-3 + dX)
     867            8 :   end function get_dX_lookup
     868              : 
     869              : 
     870          220 :   integer function find_in_dXs(dX)
     871              :     real(dp), intent(in) :: dX
     872              :     integer :: i
     873              :     real(dp), parameter :: tiny = 1d-6
     874          962 :     do i = 1, num_kap_CO_dXs
     875          962 :        if (abs(dX-kap_CO_dXs(i)) < tiny) then
     876          196 :           find_in_dXs = i; return
     877              :        end if
     878              :     end do
     879          220 :     find_in_dXs = -1
     880              :   end function find_in_dXs
     881              : 
     882              : 
     883          444 :   subroutine Get_CO_Filenames(rq, &
     884              :         Z, X, data_dir, fname, filename, cache_filename, temp_cache_filename, ierr)
     885              :     type (Kap_General_Info), pointer :: rq
     886              :     real(dp), intent(in) :: Z, X
     887              :     character (*), intent(in) :: data_dir
     888              :     character (*), intent(out) :: fname, filename, cache_filename, temp_cache_filename
     889              :     integer, intent(out) :: ierr
     890              :     ierr=0
     891          444 :     call Create_fname(rq, Z, X, fname,ierr)
     892          444 :     filename = trim(data_dir) // '/' // trim(fname) // '.data'
     893          444 :     cache_filename = trim(kap_cache_dir) // '/' // trim(fname) // '.bin'
     894          444 :     temp_cache_filename = trim(kap_temp_cache_dir) // '/' // trim(fname) // '.bin'
     895          444 :   end subroutine Get_CO_Filenames
     896              : 
     897              : 
     898          888 :   subroutine Create_fname(rq, Z, X, fname,ierr)
     899              :     type (Kap_General_Info), pointer :: rq
     900              :     real(dp), intent(in) :: Z, X
     901              :     character (len=*),intent(out) :: fname
     902              :     integer, intent(out) :: ierr
     903              :     character (len=16) :: zstr, xstr
     904              :     ierr=0
     905          444 :     call get_output_string(Z, zstr,ierr)
     906          444 :     call get_output_string(X, xstr,ierr)
     907              : 
     908              :     write(fname,'(a)') trim(kap_CO_option_str(rq% kap_CO_option)) // '_z' // &
     909          444 :          trim(zstr) // '_x' // trim(xstr)
     910              : 
     911          444 :   end subroutine Create_fname
     912              : 
     913              : end module load_CO_kap
        

Generated by: LCOV version 2.0-1