LCOV - code coverage report
Current view: top level - kap/private - kap_aesopus.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.0 % 209 163
Test Date: 2025-05-08 18:23:42 Functions: 100.0 % 8 8

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2018-2020  Aaron Dotter, Josiah Schwab & 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 kap_aesopus
      21              : 
      22              :   use forum_m, only: hdf5io_t, OPEN_FILE_RO
      23              :   use math_lib
      24              :   use kap_def
      25              : 
      26              :   implicit none
      27              : 
      28              :   private
      29              :   public :: kap_aesopus_init
      30              :   public :: AESOPUS_get
      31              : 
      32              :   logical, parameter :: debug = .false.
      33              : 
      34              :   ! for 2-D interpolation
      35              :   integer :: ibcx=0, ibcy=0, ilinx=1, iliny=1
      36              :   integer :: ict(6) = [ 1, 1, 1, 0, 0, 0 ]
      37              :   real(dp), parameter :: bc(100) = 0d0
      38              : 
      39              : contains
      40              : 
      41            2 :   subroutine kap_aesopus_init(rq, ierr)
      42              :     use kap_def, only: kap_aesopus_is_initialized
      43              :     type (Kap_General_Info), pointer :: rq
      44              :     integer, intent(out) :: ierr
      45              : 
      46              :     ! real(dp) :: kap, dlnkap_dlnRho, dlnkap_dlnT
      47              : 
      48            2 :     call read_kap_aesopus_tables(rq, ierr)
      49              : 
      50              :     ! call AESOPUS_get(0.02d0, 0.7d0, 0d0, 0d0, 0d0, -10d0, 4d0, &
      51              :     !      kap, dlnkap_dlnRho, dlnkap_dlnT,ierr)
      52              : 
      53              :     ! write(*,*) kap, dlnkap_dlnRho, dlnkap_dlnT
      54              : 
      55            2 :     if (ierr == 0) kap_aesopus_is_initialized = .true.
      56              : 
      57            2 :   end subroutine kap_aesopus_init
      58              : 
      59              : 
      60              :   subroutine kap_aesopus_shutdown
      61              :     use kap_def, only: kap_aesopus_is_initialized
      62              :     kap_aesopus_is_initialized = .false.
      63              :   end subroutine kap_aesopus_shutdown
      64              : 
      65              : 
      66            2 :   subroutine read_kap_aesopus_tables(rq, ierr)
      67              : 
      68              :     use interp_2d_lib_db, only: interp_mkbicub_db
      69              : 
      70              :     type (Kap_General_Info), pointer :: rq
      71              :     integer, intent(out) :: ierr
      72              : 
      73              :     character(len=256) :: filename
      74              :     integer :: n
      75              :     integer :: iX, iCO, iC, iN
      76              : 
      77            2 :     type(hdf5io_t) :: hi, hi_ts
      78              : 
      79            2 :     real(dp), allocatable :: table_data(:,:,:,:,:,:)
      80              :     integer :: table_size
      81              : 
      82              :     character(len=80) :: group_name  ! output buffer
      83              : 
      84              :     character(len=30), parameter :: efmt = '(A14, 99ES12.3)'
      85              :     character(len=30), parameter :: ffmt = '(A14, 99F8.3)'
      86              :     character(len=30), parameter :: ifmt = '(A14, I4)'
      87              : 
      88              :     logical :: file_exists
      89              : 
      90              :     ! get the filename
      91            2 :     filename = trim(aesopus_filename)
      92            2 :     if (filename == '') then
      93            0 :        write(*,*) 'failed to specify AESOPUS_filename'
      94            0 :        ierr = -1
      95            0 :        return
      96              :     end if
      97              : 
      98              :     ! first try local directory
      99            2 :     inquire(file=trim(filename), exist=file_exists)
     100            2 :     if (.not. file_exists) then
     101              :        ! then try MESA directory
     102            2 :        filename = trim(kap_dir) // '/' // filename
     103            2 :        inquire(file=trim(filename), exist=file_exists)
     104            2 :        if (.not. file_exists) then
     105            0 :           write(*,*) 'failed to open AESOPUS file ' // trim(filename)
     106            0 :           ierr = -1
     107            0 :           return
     108              :        end if
     109              :     end if
     110              : 
     111            2 :     if (rq% show_info) write(*,*) 'read filename <' // trim(filename) // '>'
     112              : 
     113            2 :     ierr = 0
     114              : 
     115              :     ! open file (read-only)
     116            2 :     hi = hdf5io_t(filename, OPEN_FILE_RO)
     117              : 
     118            2 :     if (rq% show_info) write(*,*) 'AESOPUS composition parameters'
     119              : 
     120              :     ! read composition parameters
     121              : 
     122            2 :     call hi% read_dset('Zsun', kA% Zsun)
     123            2 :     if (rq% show_info) write(*,efmt) 'Zsun =', kA % Zsun
     124              : 
     125            2 :     call hi% read_dset('fCO_ref', kA% fCO_ref)
     126            2 :     if (rq% show_info) write(*,ffmt) 'fCO_ref =', kA % fCO_ref
     127              : 
     128            2 :     call hi% read_dset('fC_ref', kA% fC_ref)
     129            2 :     if (rq% show_info) write(*,ffmt) 'fC_ref =', kA % fC_ref
     130              : 
     131            2 :     call hi% read_dset('fN_ref', kA% fN_ref)
     132            2 :     if (rq% show_info) write(*,ffmt) 'fN_ref =', kA % fN_ref
     133              : 
     134            2 :     if (rq% show_info) then
     135            0 :        write(*,'(A)')
     136            0 :        write(*,*) 'AESOPUS logT and logR range (logR = logRho - 3 * logT + 18)'
     137              :     end if
     138              : 
     139              :     ! read logT
     140              : 
     141            2 :     call hi% alloc_read_dset('logTs', kA% logTs)
     142            2 :     kA% num_logTs = SIZE(kA% logTs)
     143            2 :     if (rq% show_info) write(*,ifmt) "num logTs =", kA% num_logTs
     144              : 
     145           88 :     kA% min_logT = minval(kA% logTs)
     146           88 :     kA% max_logT = maxval(kA% logTs)
     147              : 
     148            2 :     if (rq% show_info) then
     149            0 :        write(*,ffmt) 'logTs =', kA% logTs
     150              :     end if
     151              : 
     152              :     ! read logR
     153              : 
     154            2 :     call hi% alloc_read_dset('logRs', kA% logRs)
     155            2 :     kA% num_logRs = SIZE(kA% logRs)
     156            2 :     if (rq% show_info) write(*,ifmt) "num logRs =", kA% num_logRs
     157              : 
     158           42 :     kA% min_logR = minval(kA% logRs)
     159           42 :     kA% max_logR = maxval(kA% logRs)
     160              : 
     161            2 :     if (rq% show_info) then
     162            0 :        write(*,ffmt) 'logRs =', kA% logRs
     163              :     end if
     164              : 
     165            2 :     if (rq% show_info) then
     166            0 :        write(*,'(A)')
     167            0 :        write(*,*) 'AESOPUS metallicities'
     168            0 :        write(*,*) '(These Z values are the reference metallicities)'
     169              :     end if
     170              : 
     171              :     ! read Zs
     172              : 
     173            2 :     call hi% alloc_read_dset('Zs', kA% Zs)
     174            2 :     kA% num_Zs = SIZE(kA% Zs)
     175            2 :     if (rq% show_info) write(*,ifmt) "num Zs =", kA% num_Zs
     176              : 
     177              :     if (debug) write(*,*) 'Zs', kA% Zs
     178              : 
     179            2 :     if (rq% show_info) then
     180            0 :        write(*,efmt) "Zs =", kA% Zs
     181              :     end if
     182              : 
     183              :     ! pre-compute logZs
     184              : 
     185            2 :     allocate(kA% logZs(kA % num_Zs))
     186           28 :     do n = 1, kA % num_Zs
     187           28 :        kA% logZs(n) = safe_log10(kA% Zs(n))
     188              :     end do
     189              : 
     190              :     ! now, there is one group for each Z
     191              :     ! walk through these and construct a AESOPUS_TableSet for each one
     192              : 
     193           28 :     allocate(kA% ts(kA% num_Zs))
     194              : 
     195           28 :     do n = 1, kA% num_Zs
     196              : 
     197            2 :        associate(ts => kA% ts(n))
     198              : 
     199              :        ! get group name and open group
     200              : 
     201           26 :        write(group_name, 100) kA% Zs(n)
     202              : 100    format(F8.6)
     203              : 
     204           26 :        if (rq% show_info) then
     205            0 :           write(*,'(A)')
     206            0 :           write(*,'(3A, ES9.3)') "Table ",  trim(group_name), ": Z = ", kA% Zs(n)
     207              :        end if
     208              : 
     209           26 :        hi_ts = hdf5io_t(hi, group_name)
     210              : 
     211              :        ! read Xs
     212              : 
     213           26 :        call hi_ts%  alloc_read_dset('Xs', ts% Xs)
     214              :        if (debug) write(*,*) "Xs", ts% Xs
     215           26 :        ts% num_Xs = SIZE(ts% Xs)
     216           26 :        if (rq% show_info) write(*,ifmt) "num Xs =", ts% num_Xs
     217              : 
     218           26 :        if (rq% show_info) then
     219            0 :           write(*,ffmt) "Xs =", ts% Xs
     220              :        end if
     221              : 
     222              :        ! read fCOs
     223              : 
     224           26 :        call hi_ts% alloc_read_dset('fCOs', ts% fCOs)
     225              :        if (debug) write(*,*) "fCOs", ts% fCOs
     226           26 :        ts% num_fCOs = SIZE(ts% fCOs)
     227           26 :        if (rq% show_info) write(*,ifmt) "num fCOs =", ts% num_fCOs
     228              : 
     229           26 :        if (rq% show_info) then
     230            0 :           write(*,ffmt) "fCOs =", ts% fCOs
     231              :        end if
     232              : 
     233              :        ! read fCs
     234              : 
     235           26 :        call hi_ts% alloc_read_dset('fCs', ts% fCs)
     236              :        if (debug) write(*,*) "fCs", ts% fCs
     237           26 :        ts% num_fCs = SIZE(ts% fCs)
     238           26 :        if (rq% show_info) write(*,ifmt) "num fCs =", ts% num_fCs
     239              : 
     240           26 :        if (rq% show_info) then
     241            0 :           write(*,ffmt) "fCs =", ts% fCs
     242              :        end if
     243              : 
     244              :        ! read fNs
     245              : 
     246           26 :        call hi_ts% alloc_read_dset('fNs', ts% fNs)
     247              :        if (debug) write(*,*) "fNs", ts% fNs
     248           26 :        ts% num_fNs = SIZE(ts% fNs)
     249           26 :        if (rq% show_info) write(*,ifmt) "num fNs =", ts% num_fNs
     250              : 
     251           26 :        if (rq% show_info) then
     252            0 :           write(*,ffmt) "fNs =", ts% fNs
     253              :        end if
     254              : 
     255              :        ! read opacities
     256              : 
     257           26 :        call hi_ts% alloc_read_dset('kap', table_data)
     258              : 
     259        35984 :        allocate(ts% t(ts % num_Xs, ts % num_fCOs, ts % num_fCs, ts % num_fNs))
     260              : 
     261          156 :        do iX = 1, ts % num_Xs
     262         1326 :           do iCO = 1, ts % num_fCOs
     263         7150 :              do iC = 1, ts % num_fCs
     264        36270 :                 do iN = 1, ts % num_fNs
     265              : 
     266         5850 :                    associate(t=> ts% t(iX, iCO, iC, iN))
     267              : 
     268              :                      !allocate(t% kap(4, kA% num_logRs, kA% num_logTs))
     269              : 
     270        29250 :                      table_size = kA% num_logRs*kA% num_logTs
     271        29250 :                      allocate(t% kap(4*table_size))
     272              : 
     273              :                      ! insert data
     274     23400000 :                      t% kap(1:4*table_size:4) = reshape(table_data(iN, iC, iCO, iX, :, :), [table_size])
     275        29250 :                      t% X = ts% Xs(iX)
     276        29250 :                      t% Z = kA% Zs(n)
     277        29250 :                      t% fCO = ts% fCOs(iCO)
     278        29250 :                      t% fC = ts% fCs(iC)
     279        29250 :                      t% fN = ts% fNs(iN)
     280              : 
     281              :                      ! create interpolant
     282              :                      call interp_mkbicub_db(kA% logRs, kA% num_logRs, &
     283              :                           ka% logTs, kA% num_logTs, &
     284              :                           t% kap, ka% num_logRs, &
     285              :                           ibcx, bc, ibcx, bc, &
     286              :                           ibcy, bc, ibcy, bc, &
     287        58500 :                           ilinx, iliny, ierr)
     288              : 
     289              :                      ! if (debug) call interp_evbicub_db(0d0, 3.85d0, &
     290              :                      !      kA% logRs, kA% num_logRs, &
     291              :                      !      ka% logTs, kA% num_logTs, &
     292              :                      !      ilinx, iliny, &
     293              :                      !      t% kap, ka% num_logRs, &
     294              :                      !      ict, res, ierr)
     295              :                      ! if (debug) write(*,'(10F10.4)') kA% logRs(17), kA% logTs(54), &
     296              :                      !      t% X, t% fCO, t% fC, t% fN, &
     297              :                      !      table_data(iN, iC, iCO, iX, 17, 54), res(1)
     298              : 
     299              :                    end associate
     300              : 
     301              :                 end do
     302              :              end do
     303              :           end do
     304              :        end do
     305              : 
     306           26 :        deallocate(table_data)
     307              : 
     308           52 :        call hi_ts%final()
     309              : 
     310              :        end associate
     311              : 
     312              :     end do
     313              : 
     314              :     ! close file
     315              : 
     316            2 :     call hi%final()
     317              : 
     318            2 :     if (rq% show_info) then
     319            0 :        write(*,'(A)')
     320            0 :        write(*,*) 'Finished reading AESOPUS tables'
     321            0 :        write(*,'(A)')
     322              :     end if
     323              : 
     324              : 
     325            2 :   end subroutine read_kap_aesopus_tables
     326              : 
     327              : 
     328            2 :   subroutine AESOPUS_interp(Zref, X, XC, XN, XO, logR, logT, res, ierr)
     329              :     !result=(logKappa, dlogKappa/dlogR, dlogKappa/dlogT)
     330              :     use interp_1d_def, only: pm_work_size
     331              :     use interp_1d_lib, only: interpolate_vector, interp_pm
     332              :     use num_lib, only: binary_search
     333              :     real(dp), intent(in) :: Zref, X, XC, XN, XO, logR, logT
     334              :     real(dp), intent(out) :: res(3)
     335              :     integer, intent(out) :: ierr
     336            2 :     real(dp), pointer :: work1(:)
     337              :     integer, parameter :: nZ = 3
     338              :     integer :: i,iZ
     339           30 :     real(dp) :: my_Z, raw_res(3, nZ), x_new(1), v_new(1)
     340              :     character(len=32) :: junk
     341              :     logical :: clipped
     342              : 
     343              :     ! result=0d0; iZ=0; ierr=0
     344              : 
     345            2 :     if (outside_R_and_T_bounds(logR,logT)) then
     346            0 :        write(*,*) 'AESOPUS_interp: logR, logT outside of table bounds'
     347            0 :        ierr = -1
     348            0 :        return
     349              :     end if
     350              : 
     351              :     ! restrict to range
     352            2 :     clipped = .false.
     353            2 :     if (Zref <= kA% Zs(1)) then
     354            0 :        my_Z = kA% Zs(1)
     355            0 :        iZ = 1
     356              :        clipped = .true.
     357            2 :     else if (Zref >= kA% Zs(kA% num_Zs)) then
     358            0 :        my_Z = kA% Zs(kA% num_Zs)
     359            0 :        iZ = kA% num_Zs
     360              :        clipped = .true.
     361              :     end if
     362              : 
     363              :     ! if clipped in Z, then just need one call
     364            0 :     if (clipped) then
     365            0 :        call AESOPUS_interp_fixedZref(iZ, X, XC, XN, XO, logR, logT, res, ierr)
     366            0 :        return
     367              :     end if
     368              : 
     369            2 :     my_Z = Zref
     370              : 
     371              :     ! it might be easier just to do linear interpolation
     372              :     ! but for now, we use an adapted version of what kapCN does
     373              : 
     374              :     ! require at least 3 Zs for interpolation
     375            2 :     if (nZ > kA% num_Zs) then
     376            0 :        write(*,*) 'AESOPUS_interp: insufficient number of Z values for interpolation'
     377            0 :        write(*,'(I2, A, I2, A)') nZ, ' values are required; ', kA% num_Zs, ' were provided'
     378            0 :        ierr = -1
     379            0 :        return
     380              :     end if
     381              : 
     382              :     ! binary_search returns iZ between 1 and num_Zs-1
     383              :     ! such that Zs(iZ) <= Z < Zs(iZ+1)
     384            2 :     iZ = binary_search(kA% num_Zs, kA% Zs, 0, my_Z)
     385              : 
     386              :     ! make sure this is in an acceptable range
     387              :     ! unless that would go off the ends
     388              :     ! this check is hard-coded assuming nZ = 3
     389            2 :     iZ = min(kA% num_Zs-1, max(iZ, 2))
     390              : 
     391              :     ! want to call at [iZ-1, iZ, iZ+1]
     392            8 :     do i = 1, nZ
     393            8 :        call AESOPUS_interp_fixedZref(iZ+i-2, X, XC, XN, XO, logR, logT, raw_res(:,i), ierr)
     394              :     end do
     395              : 
     396              :     nullify(work1)
     397            2 :     allocate(work1(nZ*pm_work_size))
     398            2 :     x_new(1)=safe_log10(my_Z)
     399              : 
     400              :     ! do the Z interpolation
     401              :     ! loop does over kap and its derivatives
     402            8 :     do i = 1, 3
     403              :        call interpolate_vector(nZ, kA% logZs(iZ-1:iZ+1), 1, &
     404              :             x_new, raw_res(i,:), v_new, &
     405              :             interp_pm, pm_work_size, &
     406            6 :             work1, junk, ierr)
     407            8 :        res(i) = v_new(1)
     408              :     end do
     409              : 
     410            2 :     deallocate(work1)
     411              : 
     412            4 :   end subroutine AESOPUS_interp
     413              : 
     414              : 
     415            2 :   logical function outside_R_and_T_bounds(logR,logT)
     416              :     real(dp), intent(in) :: logR, logT
     417              :     outside_R_and_T_bounds = &
     418              :          logR < kA% min_logR .or. logR > kA% max_logR .or. &
     419            2 :          logT < kA% min_logT .or. logT > kA% max_logT
     420            2 :   end function outside_R_and_T_bounds
     421              : 
     422              : 
     423            6 :   subroutine AESOPUS_interp_fixedZref(iZ, X, XC, XN, XO, logR, logT, res, ierr)
     424              :     ! simple interpolation in each of X, fCO, fC, fN
     425              :     ! at present, interpolation is linear (order = 2)
     426              :     integer, intent(in) :: iZ
     427              :     real(dp), intent(in) :: X, XC, XN, XO, logR, logT
     428              :     real(dp), intent(out) :: res(3)
     429              :     integer, intent(out) :: ierr
     430              : 
     431              :     integer, parameter :: npts = 2
     432           54 :     real(dp), dimension(npts) :: wX, wfCO, wfC, wfN
     433           24 :     real(dp) :: raw_res(3)
     434              :     integer :: iX, ifCO, ifC, ifN
     435              :     integer :: i, j, k, l
     436              : 
     437            6 :     real(dp) :: Zref, fCO, fC, fN
     438              :     logical :: clipped_X, clipped_fCO, clipped_fC, clipped_fN
     439              : 
     440            6 :     ierr = 0
     441            6 :     res = 0d0
     442              :     iX=0; ifCO=0; ifC=0; ifN=0
     443              : 
     444              :     ! AESOPUS defines these quantities as follows
     445              : 
     446              :     ! fCO=log10(XC/XO)-log10(XC/XO)ref
     447              :     ! fC=log10(XC)-log10(XC)ref
     448              :     ! fN=log10(XN)-log10(XN)ref
     449              : 
     450              :     ! Note that the reference values are different for different solar abundance patterns
     451              : 
     452            6 :     Zref = kA% Zs(iZ)
     453            6 :     fCO = safe_log10(XC/XO) - kA% fCO_ref
     454            6 :     fC = safe_log10(XC/Zref) - kA% fC_ref
     455            6 :     fN = safe_log10(XN/Zref) - kA% fN_ref
     456              : 
     457              :     if (debug) then
     458              :        write(*,*) 'call to AESOPUS_interp_RT'
     459              :        write(*,*) 'logR = ', logR
     460              :        write(*,*) 'logT = ', logT
     461              :        write(*,*) 'Zref = ', Zref
     462              :        write(*,*) 'X = ', X
     463              :        write(*,*) 'fCO = ', fCO
     464              :        write(*,*) 'fC = ', fC
     465              :        write(*,*) 'fN = ', fN
     466              :     end if
     467              : 
     468           24 :     associate(ts => kA% ts(iZ))
     469              : 
     470              :       ! get weights for a clipped linear interpolation in each parameter
     471            6 :       call clipped_linear_weights(X, ts% num_Xs, ts% Xs, iX, wX, clipped_X)
     472            6 :       call clipped_linear_weights(fCO, ts% num_fCOs, ts% fCOs, ifCO, wfCO, clipped_fCO)
     473            6 :       call clipped_linear_weights(fC, ts% num_fCs, ts% fCs, ifC, wfC, clipped_fC)
     474            6 :       call clipped_linear_weights(fN, ts% num_fNs, ts% fNs, ifN, wfN, clipped_fN)
     475              : 
     476              :       ! cycles prevent wastefully calling interp_RT with zero weights
     477           24 :       do i = 1, npts
     478           12 :          if (wX(i) == 0) cycle
     479           42 :          do j = 1, npts
     480           24 :             if (wfCO(j) == 0) cycle
     481           84 :             do k = 1, npts
     482           48 :                if (wfC(k) == 0) cycle
     483          168 :                do l = 1, npts
     484           96 :                   if (wfN(l) == 0) cycle
     485              : 
     486              :                   if (debug) then
     487              :                      write(*,*) 'call to AESOPUS_interp_RT'
     488              :                      write(*,*) iX+i-1, ifCO+j-1, ifC+k-1,ifN+l-1
     489              :                      write(*,*) 'X = ', X, ts% Xs(iX+i-1), wX(i)
     490              :                      write(*,*) 'fCO = ', fCO, ts% fCOs(ifCO+j-1), wfCO(j)
     491              :                      write(*,*) 'fC = ', fC, ts% fCs(ifC+k-1), wfC(k)
     492              :                      write(*,*) 'fN = ', fN, ts% fNs(ifN+l-1), wfN(l)
     493              :                   end if
     494              : 
     495              :                   ! now do the call and collect the results
     496              : 
     497           96 :                   call AESOPUS_interp_RT(ts% t(iX+i-1,ifCO+j-1,ifC+k-1,ifN+l-1), logR, logT, raw_res, ierr)
     498           96 :                   if (ierr /= 0) return
     499              : 
     500          528 :                   res = res + wX(i)*wfCO(j)*wfC(k)*wfN(l) * raw_res
     501              : 
     502              :                end do
     503              :             end do
     504              :          end do
     505              :       end do
     506              : 
     507              :     end associate
     508              : 
     509              :   contains
     510              : 
     511           24 :     subroutine clipped_linear_weights(val, len, vec, loc, weights, clipped)
     512              : 
     513              :       ! calculate the weights for a linear interpolation
     514              :       ! clip to table edges
     515              : 
     516              :       use num_lib, only: binary_search
     517              : 
     518              :       real(dp), intent(in) :: val  ! value
     519              :       integer, intent(in) :: len  ! number of tabulated values
     520              :       real(dp), dimension(:), intent(in) :: vec  ! tabulated values
     521              :       integer,  intent(out) :: loc  ! vec(loc) <= val <= vec(loc+1)
     522              :       real(dp), dimension(2), intent(out) :: weights  ! for linear interpolation
     523              :       logical, intent(out) :: clipped  ! did we clip? if so, only locs(1)/weights(1) matter
     524              : 
     525           24 :       weights = 0
     526              : 
     527              :       ! clip to range, if needed
     528           24 :       clipped = .false.
     529           24 :       if (val <= vec(1)) then
     530            0 :          loc = 1
     531            0 :          weights(1) = 1d0
     532              :          weights(2) = 0d0
     533            0 :          clipped = .true.
     534           24 :       else if (val >= vec(len)) then
     535            0 :          loc = len
     536            0 :          weights(1) = 1d0
     537              :          weights(2) = 0d0
     538            0 :          clipped = .true.
     539              :       end if
     540              : 
     541              :       ! find location and calculate linear weights
     542           24 :       if (.not. clipped) then
     543              :          ! binary_search returns k between 1 and n-1 such that vec(k) <= val < vec(k+1)
     544           24 :          loc = binary_search(len, vec, len/2, val)
     545           24 :          weights(2) = (val - vec(loc)) / (vec(loc+1) - vec(loc))
     546           24 :          weights(1) = 1d0 - weights(2)
     547              :       end if
     548              : 
     549           24 :     end subroutine clipped_linear_weights
     550              : 
     551              :   end subroutine AESOPUS_interp_fixedZref
     552              : 
     553              : 
     554           96 :   subroutine AESOPUS_interp_RT(t, logR, logT, res, ierr)
     555              :     use interp_2d_lib_db, only: interp_evbicub_db
     556              :     type(AESOPUS_Table) :: t
     557              :     real(dp), intent(in) :: logR, logT
     558              :     real(dp), intent(out) :: res(3)
     559              :     integer, intent(out) :: ierr
     560          672 :     real(dp) :: raw_res(6)
     561              : 
     562              :     if (debug) then
     563              :        write(*,*) 'inside call to AESOPUS_interp_RT'
     564              :        write(*,*) 'X = ', t% X
     565              :        write(*,*) 'Z = ', t% Z
     566              :        write(*,*) 'fCO = ', t% fCO
     567              :        write(*,*) 'fC = ', t% fC
     568              :        write(*,*) 'fN = ', t% fN
     569              :     end if
     570              : 
     571              :     call interp_evbicub_db(logR, logT, &
     572              :          kA% logRs, kA% num_logRs, &
     573              :          ka% logTs, kA% num_logTs, &
     574              :          ilinx, iliny, &
     575              :          t% kap, ka% num_logRs, &
     576           96 :          ict, raw_res, ierr)
     577              : 
     578          384 :     res = raw_res(1:3)
     579              : 
     580           96 :   end subroutine AESOPUS_interp_RT
     581              : 
     582              : 
     583            2 :   subroutine AESOPUS_get(Zref, X, XC, XN, XO, logRho, logT, kap, &
     584              :        dlnkap_dlnRho, dlnkap_dlnT,ierr)
     585              :     real(dp), intent(in) :: Zref, X, XC, XN, XO
     586              :     real(dp), intent(in) :: logRho, logT
     587              :     real(dp), intent(out) :: kap, dlnkap_dlnRho, dlnkap_dlnT
     588              :     integer, intent(out) :: ierr
     589            8 :     real(dp) :: logR, res(3)
     590              : 
     591              :     ierr = 0
     592            2 :     logR = logRho - 3d0*logT + 18d0
     593              : 
     594              :     if (debug) write(*,*) Zref, X, XC, XN, XO, logR, logT
     595            2 :     call AESOPUS_interp(Zref, X, XC, XN, XO, logR, logT, res, ierr)
     596            2 :     if (ierr == 0) then
     597            2 :        kap = exp10(res(1))
     598            2 :        dlnkap_dlnRho = res(2)
     599            2 :        dlnkap_dlnT = res(3) - 3d0*res(2)
     600              :     else
     601            0 :        kap = -1d0
     602            0 :        dlnkap_dlnRho = 0d0
     603            0 :        dlnkap_dlnT = 0d0
     604              :     end if
     605              : 
     606            2 :   end subroutine AESOPUS_get
     607              : 
     608              : end module kap_aesopus
        

Generated by: LCOV version 2.0-1