LCOV - code coverage report
Current view: top level - eos/private - pc_support.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 476 0
Test Date: 2025-05-08 18:23:42 Functions: 0.0 % 13 0

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2022  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 pc_support
      21              :    use utils_lib, only: is_bad, mesa_error, mv, switch_str
      22              :    use eos_def
      23              :    use const_def, only: ln10, mesa_temp_caches_dir, one_sixth
      24              :    use math_lib
      25              : 
      26              :    implicit none
      27              : 
      28              :    public :: get_FITION9, get_EXCOR7, get_FSCRliq8
      29              :    private
      30              : 
      31              :    ! the file data for EXCOR7
      32              :    integer, parameter :: jFXC = 1
      33              :    integer, parameter :: jUXC = 2
      34              :    integer, parameter :: jPXC = 3
      35              :    integer, parameter :: jCVXC = 4
      36              :    integer, parameter :: jSXC = 5
      37              :    integer, parameter :: jPDTXC = 6
      38              :    integer, parameter :: jPDRXC = 7
      39              :    integer, parameter :: nvals_EXCOR7 = 7
      40              : 
      41              :    ! the file data for FSCRliq8   FSCR, USCR, PSCR, CVSCR, PDTSCR, PDRSCR
      42              :    integer, parameter :: iFSCR = 1
      43              :    integer, parameter :: iUSCR = 2
      44              :    integer, parameter :: iPSCR = 3
      45              :    integer, parameter :: iCVSCR = 4
      46              :    integer, parameter :: iPDTSCR = 5
      47              :    integer, parameter :: iPDRSCR = 6
      48              :    integer, parameter :: nvals_FSCRliq8 = 6
      49              : 
      50              : 
      51              :    contains
      52              : 
      53              : 
      54            0 :    subroutine get_FITION9(GAMI, &
      55              :          FION, dFION_dlnGAMI, &
      56              :          UION, dUION_dlnGAMI, &
      57              :          PION, dPION_dlnGAMI, &
      58              :          CVii, dCVii_dlnGAMI, &
      59              :          PDTii, dPDTii_dlnGAMI, &
      60              :          PDRii, dPDRii_dlnGAMI, &
      61              :          skip, ierr)
      62              :       real(dp), intent(in) :: GAMI
      63              :       real(dp), intent(out) :: &
      64              :          FION, dFION_dlnGAMI, &
      65              :          UION, dUION_dlnGAMI, &
      66              :          PION, dPION_dlnGAMI, &
      67              :          CVii, dCVii_dlnGAMI, &
      68              :          PDTii, dPDTii_dlnGAMI, &
      69              :          PDRii, dPDRii_dlnGAMI
      70              :       logical, intent(out) :: skip
      71              :       integer, intent(out) :: ierr
      72              : 
      73              :       integer, parameter :: iFION = 1
      74              :       integer, parameter :: iUION = 2
      75              :       integer, parameter :: iPION = 3
      76              :       integer, parameter :: iCVii = 4
      77              :       integer, parameter :: iPDTii = 5
      78              :       integer, parameter :: iPDRii = 6
      79            0 :       real(dp) :: lnGAMI_min, lnGAMI_max, dlnGAMI, lnGAMI
      80              :       integer :: nlnGAMI, k_old
      81            0 :       real(dp) :: xk_old, xkp1_old, xk_new, delta
      82            0 :       real(dp), pointer, dimension(:,:) :: f_1, f_2, f_3, f_4, f_5, f_6
      83              : 
      84              :       include 'formats'
      85              : 
      86            0 :       ierr = 0
      87            0 :       skip = .false.
      88              : 
      89            0 :       lnGAMI_min = -2.0d0*ln10
      90            0 :       lnGAMI_max = 6.5d0*ln10
      91            0 :       dlnGAMI = 1d-2*ln10
      92            0 :       nlnGAMI = (lnGAMI_max - lnGAMI_min)/dlnGAMI + 1
      93              : 
      94            0 :       if (.not. FITION9_loaded) then
      95            0 : !$OMP CRITICAL(eosPC_support_FITION9_load)
      96            0 :          if (.not. FITION9_loaded) then
      97            0 :             call build_FITION9_data(ierr)
      98            0 :             if (ierr == 0) FITION9_loaded = .true.
      99              :          end if
     100              : !$OMP END CRITICAL(eosPC_support_FITION9_load)
     101            0 :          if (ierr /= 0) return
     102              :       end if
     103              : 
     104            0 :       lnGAMI = log(GAMI)
     105            0 :       if (lnGAMI < lnGAMI_min .or. lnGAMI > lnGAMI_max) then
     106            0 :          skip = .true.
     107            0 :          return
     108              :       end if
     109              : 
     110            0 :       f_1(1:4,1:nlnGAMI) => FITION_data(iFION)% f1
     111            0 :       f_2(1:4,1:nlnGAMI) => FITION_data(iUION)% f1
     112            0 :       f_3(1:4,1:nlnGAMI) => FITION_data(iPION)% f1
     113            0 :       f_4(1:4,1:nlnGAMI) => FITION_data(iCVii)% f1
     114            0 :       f_5(1:4,1:nlnGAMI) => FITION_data(iPDTii)% f1
     115            0 :       f_6(1:4,1:nlnGAMI) => FITION_data(iPDRii)% f1
     116              : 
     117            0 :       xk_new = lnGAMI
     118            0 :       k_old = int((lnGAMI - lnGAMI_min)/dlnGAMI + 1d-4) + 1
     119            0 :       if (k_old < 1 .or. k_old >= nlnGAMI) then
     120              :          if (k_old < 1) then
     121            0 :             k_old = 1
     122            0 :             xk_old = lnGAMI_min
     123            0 :             xkp1_old = xk_old + dlnGAMI
     124              :          else
     125            0 :             k_old = nlnGAMI-1
     126            0 :             xk_old = lnGAMI_min + (k_old-1)*dlnGAMI
     127            0 :             xkp1_old = xk_old + dlnGAMI
     128              :          end if
     129              :       else
     130            0 :          xk_old = lnGAMI_min + (k_old-1)*dlnGAMI
     131            0 :          xkp1_old = xk_old + dlnGAMI
     132              :       end if
     133              : 
     134            0 :       delta = xk_new - xk_old
     135              : 
     136              :       FION = &
     137              :             f_1(1, k_old) + delta*(f_1(2, k_old)  &
     138            0 :                + delta*(f_1(3, k_old) + delta*f_1(4, k_old)))
     139              :       dFION_dlnGAMI = &
     140            0 :             f_1(2, k_old) + 2*delta*(f_1(3, k_old) + 1.5d0*delta*f_1(4, k_old))
     141              : 
     142              :       UION = &
     143              :             f_2(1, k_old) + delta*(f_2(2, k_old)  &
     144            0 :                + delta*(f_2(3, k_old) + delta*f_2(4, k_old)))
     145              :       dUION_dlnGAMI = &
     146            0 :             f_2(2, k_old) + 2*delta*(f_2(3, k_old) + 1.5d0*delta*f_2(4, k_old))
     147              : 
     148              :       PION = &
     149              :             f_3(1, k_old) + delta*(f_3(2, k_old)  &
     150            0 :                + delta*(f_3(3, k_old) + delta*f_3(4, k_old)))
     151              :       dPION_dlnGAMI = &
     152            0 :             f_3(2, k_old) + 2*delta*(f_3(3, k_old) + 1.5d0*delta*f_3(4, k_old))
     153              : 
     154              :       CVii = &
     155              :             f_4(1, k_old) + delta*(f_4(2, k_old)  &
     156            0 :                + delta*(f_4(3, k_old) + delta*f_4(4, k_old)))
     157              :       dCVii_dlnGAMI = &
     158            0 :             f_4(2, k_old) + 2*delta*(f_4(3, k_old) + 1.5d0*delta*f_4(4, k_old))
     159              : 
     160              :       PDTii = &
     161              :             f_5(1, k_old) + delta*(f_5(2, k_old)  &
     162            0 :                + delta*(f_5(3, k_old) + delta*f_5(4, k_old)))
     163              :       dPDTii_dlnGAMI = &
     164            0 :             f_5(2, k_old) + 2*delta*(f_5(3, k_old) + 1.5d0*delta*f_5(4, k_old))
     165              : 
     166              :       PDRii = &
     167              :             f_6(1, k_old) + delta*(f_6(2, k_old)  &
     168            0 :                + delta*(f_6(3, k_old) + delta*f_6(4, k_old)))
     169              :       dPDRii_dlnGAMI = &
     170            0 :             f_6(2, k_old) + 2*delta*(f_6(3, k_old) + 1.5d0*delta*f_6(4, k_old))
     171              : 
     172              :       contains
     173              : 
     174              : 
     175            0 :       subroutine build_FITION9_data(ierr)
     176              :          use interp_1d_def, only : pm_work_size
     177              :          use interp_1d_lib, only : interp_pm
     178              :          integer, intent(out) :: ierr
     179              :          type (FITION_Info), pointer :: fi
     180            0 :          real(dp), pointer :: work(:)
     181            0 :          real(dp) :: lnGAMI, GAMI, FION, UION, PION, CVii, PDTii, PDRii
     182              :          integer :: j
     183              :          include 'formats'
     184              : 
     185            0 :          ierr = 0
     186              :          !write(*,'(a)') 'eosPC build_FITION9_data'
     187              : 
     188            0 :          allocate(FITION9_lnGAMIs(nlnGAMI), work(pm_work_size*nlnGAMI))
     189            0 :          do j=1,FITION_vals
     190            0 :             fi => FITION_data(j)
     191            0 :             allocate(fi% f1(4*nlnGAMI))
     192            0 :             fi% f(1:4, 1:nlnGAMI) => fi% f1(1:4*nlnGAMI)
     193              :          end do
     194              : 
     195            0 :          do j=1,nlnGAMI-1
     196            0 :             FITION9_lnGAMIs(j) = lnGAMI_min + (j-1)*dlnGAMI
     197              :          end do
     198            0 :          FITION9_lnGAMIs(nlnGAMI) = lnGAMI_max
     199              : 
     200            0 :          do j=1,nlnGAMI
     201            0 :             lnGAMI = FITION9_lnGAMIs(j)
     202            0 :             GAMI = exp(lnGAMI)
     203            0 :             call FITION9(GAMI,FION,UION,PION,CVii,PDTii,PDRii)
     204            0 :             fi => FITION_data(iFION); fi% f(1,j) = FION
     205            0 :             fi => FITION_data(iUION); fi% f(1,j) = UION
     206            0 :             fi => FITION_data(iPION); fi% f(1,j) = PION
     207            0 :             fi => FITION_data(iCVii); fi% f(1,j) = CVii
     208            0 :             fi => FITION_data(iPDTii); fi% f(1,j) = PDTii
     209            0 :             fi => FITION_data(iPDRii); fi% f(1,j) = PDRii
     210              :          end do
     211              : 
     212            0 :          do j=1,FITION_vals
     213            0 :             fi => FITION_data(j)
     214              :             call interp_pm(FITION9_lnGAMIs, nlnGAMI, &
     215            0 :                fi% f1, pm_work_size, work, 'build_FITION9_data', ierr)
     216            0 :             if (ierr /= 0) return
     217              :          end do
     218              : 
     219            0 :          deallocate(work)
     220              : 
     221              :          !write(*,'(a)') 'done eosPC build_FITION9_data'
     222              : 
     223            0 :       end subroutine build_FITION9_data
     224              : 
     225              :    end subroutine get_FITION9
     226              : 
     227              : 
     228            0 :    subroutine get_FSCRliq8(iZion, RS, GAME, &
     229              :          FSCR, dFSCR_dlnRS, dFSCR_dlnGAME, &
     230              :          USCR, dUSCR_dlnRS, dUSCR_dlnGAME, &
     231              :          PSCR, dPSCR_dlnRS, dPSCR_dlnGAME, &
     232              :          CVSCR, dCVSCR_dlnRS, dCVSCR_dlnGAME, &
     233              :          PDTSCR, dPDTSCR_dlnRS, dPDTSCR_dlnGAME, &
     234              :          PDRSCR, dPDRSCR_dlnRS, dPDRSCR_dlnGAME, &
     235              :          skip, ierr)
     236              :       integer, intent(in) :: iZion
     237              :       real(dp), intent(in) :: RS, GAME
     238              :       real(dp), intent(out) :: &
     239              :          FSCR, dFSCR_dlnRS, dFSCR_dlnGAME, &
     240              :          USCR, dUSCR_dlnRS, dUSCR_dlnGAME, &
     241              :          PSCR, dPSCR_dlnRS, dPSCR_dlnGAME, &
     242              :          CVSCR, dCVSCR_dlnRS, dCVSCR_dlnGAME, &
     243              :          PDTSCR, dPDTSCR_dlnRS, dPDTSCR_dlnGAME, &
     244              :          PDRSCR, dPDRSCR_dlnRS, dPDRSCR_dlnGAME
     245              :       logical, intent(out) :: skip
     246              :       integer, intent(out) :: ierr
     247              : 
     248              :       integer :: iRS, jGAME
     249            0 :       real(dp) :: lnRS, lnRS0, lnRS1, lnGAME, lnGAME0, lnGAME1
     250            0 :       real(dp), dimension(nvals_FSCRliq8) :: fval, df_dlnRS, df_dlnGAME
     251              :       type (eosPC_Support_Info), pointer :: fq
     252              :       include 'formats'
     253            0 :       ierr = 0
     254            0 :       skip = .false.
     255              : 
     256            0 :       if (iZion < 1 .or. iZion > max_FSCRliq8_Zion) then
     257            0 :          write(*,2) 'invalid value for Z ion in get_FSCRliq8', iZion
     258            0 :          ierr = -1
     259            0 :          return
     260              :       end if
     261              : 
     262            0 :       fq => FSCRliq8_data(iZion)
     263              : 
     264            0 :       if (.not. FSCRliq8_Zion_loaded(iZion)) then
     265            0 : !$OMP CRITICAL(eosPC_support_FSCRliq8_load)
     266            0 :          if (.not. FSCRliq8_Zion_loaded(iZion)) then
     267            0 :             call load_eosPC_support_Info(fq,iZion,ierr)
     268            0 :             if (ierr == 0) FSCRliq8_Zion_loaded(iZion) = .true.
     269              :          end if
     270              : !$OMP END CRITICAL(eosPC_support_FSCRliq8_load)
     271            0 :          if (ierr /= 0) return
     272              :       end if
     273              : 
     274              :       ! get interpolation results
     275            0 :       lnRS = log(RS)
     276            0 :       lnGAME = log(GAME)
     277              :       if (lnRS < fq% lnRS_min .or. lnRS > fq% lnRS_max .or. &
     278            0 :           lnGAME < fq% lnGAME_min .or. lnGAME > fq% lnGAME_max) then
     279            0 :          skip = .true.
     280            0 :          return
     281              :       end if
     282              : 
     283              :       call Locate_lnRS(lnRS, &
     284              :          fq% nlnRS, fq% lnRS_min, fq% dlnRS, &
     285            0 :          iRS, lnRS0, lnRS1)
     286              :       call Locate_lnGAME(lnGAME, &
     287              :          fq% nlnGAME, fq% lnGAME_min, fq% dlnGAME, &
     288            0 :          jGAME, lnGAME0, lnGAME1)
     289              : 
     290              :       call Do_Interpolations( &
     291              :          1, nvals_FSCRliq8, nvals_FSCRliq8, nvals_FSCRliq8, &
     292              :          fq% nlnRS, fq% lnRSs, fq% nlnGAME, fq% lnGAMEs, fq% tbl1, &
     293              :          iRS, jGAME, lnRS0, lnRS, lnRS1, lnGAME0, lnGAME, lnGAME1, &
     294            0 :          fval, df_dlnRS, df_dlnGAME, ierr)
     295            0 :       if (ierr /= 0) then
     296            0 :          write(*,1) 'Do_Interpolations failed in get_FSCRliq8'
     297            0 :          return
     298              :       end if
     299              : 
     300            0 :       FSCR = fval(iFSCR); dFSCR_dlnRS = df_dlnRS(iFSCR); dFSCR_dlnGAME = df_dlnGAME(iFSCR)
     301            0 :       USCR = fval(iUSCR); dUSCR_dlnRS = df_dlnRS(iUSCR); dUSCR_dlnGAME = df_dlnGAME(iUSCR)
     302            0 :       PSCR = fval(iPSCR); dPSCR_dlnRS = df_dlnRS(iPSCR); dPSCR_dlnGAME = df_dlnGAME(iPSCR)
     303            0 :       CVSCR = fval(iCVSCR); dCVSCR_dlnRS = df_dlnRS(iCVSCR); dCVSCR_dlnGAME = df_dlnGAME(iCVSCR)
     304            0 :       PDTSCR = fval(iPDTSCR); dPDTSCR_dlnRS = df_dlnRS(iPDTSCR); dPDTSCR_dlnGAME = df_dlnGAME(iPDTSCR)
     305            0 :       PDRSCR = fval(iPDRSCR); dPDRSCR_dlnRS = df_dlnRS(iPDRSCR); dPDRSCR_dlnGAME = df_dlnGAME(iPDRSCR)
     306              : 
     307              :    end subroutine get_FSCRliq8
     308              : 
     309              : 
     310            0 :    subroutine get_EXCOR7(RS, GAME, &
     311              :          FXC, dFXC_dlnRS, dFXC_dlnGAME, &
     312              :          UXC, dUXC_dlnRS, dUXC_dlnGAME, &
     313              :          PXC, dPXC_dlnRS, dPXC_dlnGAME, &
     314              :          CVXC, dCVXC_dlnRS, dCVXC_dlnGAME, &
     315              :          SXC, dSXC_dlnRS, dSXC_dlnGAME, &
     316              :          PDTXC, dPDTXC_dlnRS, dPDTXC_dlnGAME, &
     317              :          PDRXC, dPDRXC_dlnRS, dPDRXC_dlnGAME, &
     318              :          skip, ierr)
     319              :       real(dp), intent(in) :: RS, GAME
     320              :       real(dp), intent(out) :: &
     321              :          FXC, dFXC_dlnRS, dFXC_dlnGAME, &
     322              :          UXC, dUXC_dlnRS, dUXC_dlnGAME, &
     323              :          PXC, dPXC_dlnRS, dPXC_dlnGAME, &
     324              :          CVXC, dCVXC_dlnRS, dCVXC_dlnGAME, &
     325              :          SXC, dSXC_dlnRS, dSXC_dlnGAME, &
     326              :          PDTXC, dPDTXC_dlnRS, dPDTXC_dlnGAME, &
     327              :          PDRXC, dPDRXC_dlnRS, dPDRXC_dlnGAME
     328              :       logical, intent(out) :: skip
     329              :       integer, intent(out) :: ierr
     330              : 
     331              :       integer :: iRS, jGAME
     332            0 :       real(dp) :: lnRS, lnRS0, lnRS1, lnGAME, lnGAME0, lnGAME1
     333            0 :       real(dp), dimension(nvals_EXCOR7) :: fval, df_dlnRS, df_dlnGAME
     334              :       type (eosPC_Support_Info), pointer :: fq
     335              :       include 'formats'
     336            0 :       ierr = 0
     337            0 :       skip = .false.
     338              : 
     339            0 :       fq => EXCOR7_data
     340              : 
     341            0 :       if (.not. EXCOR7_table_loaded) then
     342            0 : !$OMP CRITICAL(eosPC_EXCOR7_support_load)
     343            0 :          if (.not. EXCOR7_table_loaded) then
     344            0 :             call load_eosPC_support_Info(fq,0,ierr)
     345            0 :             if (ierr == 0) EXCOR7_table_loaded = .true.
     346              :          end if
     347              : !$OMP END CRITICAL(eosPC_EXCOR7_support_load)
     348            0 :          if (ierr /= 0) return
     349              :       end if
     350              : 
     351              :       ! get interpolation results
     352            0 :       lnRS = log(RS)
     353            0 :       lnGAME = log(GAME)
     354              :       if (lnRS < fq% lnRS_min .or. lnRS > fq% lnRS_max .or. &
     355            0 :           lnGAME < fq% lnGAME_min .or. lnGAME > fq% lnGAME_max) then
     356            0 :          skip = .true.
     357            0 :          return
     358              :       end if
     359              : 
     360              :       call Locate_lnRS(lnRS, &
     361            0 :          fq% nlnRS, fq% lnRS_min, fq% dlnRS, iRS, lnRS0, lnRS1)
     362              :       call Locate_lnGAME(lnGAME, &
     363            0 :          fq% nlnGAME, fq% lnGAME_min, fq% dlnGAME, jGAME, lnGAME0, lnGAME1)
     364              : 
     365              :       call Do_Interpolations( &
     366              :          1, nvals_EXCOR7, nvals_EXCOR7, nvals_EXCOR7, &
     367              :          fq% nlnRS, fq% lnRSs, fq% nlnGAME, fq% lnGAMEs, &
     368              :          fq% tbl1, iRS, jGAME, lnRS0, lnRS, lnRS1, lnGAME0, lnGAME, lnGAME1, &
     369            0 :          fval, df_dlnRS, df_dlnGAME, ierr)
     370            0 :       if (ierr /= 0) then
     371            0 :          write(*,1) 'Do_Interpolations failed in get_EXCOR7'
     372            0 :          return
     373              :       end if
     374              : 
     375            0 :       FXC = fval(jFXC); dFXC_dlnRS = df_dlnRS(jFXC); dFXC_dlnGAME = df_dlnGAME(jFXC)
     376            0 :       UXC = fval(jUXC); dUXC_dlnRS = df_dlnRS(jUXC); dUXC_dlnGAME = df_dlnGAME(jUXC)
     377            0 :       PXC = fval(jPXC); dPXC_dlnRS = df_dlnRS(jPXC); dPXC_dlnGAME = df_dlnGAME(jPXC)
     378            0 :       CVXC = fval(jCVXC); dCVXC_dlnRS = df_dlnRS(jCVXC); dCVXC_dlnGAME = df_dlnGAME(jCVXC)
     379            0 :       SXC = fval(jSXC); dSXC_dlnRS = df_dlnRS(jSXC); dSXC_dlnGAME = df_dlnGAME(jSXC)
     380            0 :       PDTXC = fval(jPDTXC); dPDTXC_dlnRS = df_dlnRS(jPDTXC); dPDTXC_dlnGAME = df_dlnGAME(jPDTXC)
     381            0 :       PDRXC = fval(jPDRXC); dPDRXC_dlnRS = df_dlnRS(jPDRXC); dPDRXC_dlnGAME = df_dlnGAME(jPDRXC)
     382              : 
     383              :    end subroutine get_EXCOR7
     384              : 
     385              : 
     386            0 :    subroutine Locate_lnRS( &
     387              :          lnRS, nlnRS, lnRS_min, dlnRS, iQ, lnRS0, lnRS1)
     388              :       real(dp), intent(inout) :: lnRS
     389              :       integer, intent(in) :: nlnRS
     390              :       real(dp), intent(in) :: lnRS_min, dlnRS
     391              :       integer, intent(out) :: iQ
     392              :       real(dp), intent(out) :: lnRS0, lnRS1
     393            0 :       iQ = int((lnRS - lnRS_min)/dlnRS + 1d-4) + 1
     394            0 :       if (iQ < 1 .or. iQ >= nlnRS) then
     395            0 :          if (iQ < 1) then
     396            0 :             iQ = 1
     397            0 :             lnRS0 = lnRS_min
     398            0 :             lnRS1 = lnRS0 + dlnRS
     399            0 :             lnRS = lnRS0
     400              :          else
     401            0 :             iQ = nlnRS-1
     402            0 :             lnRS0 = lnRS_min + (iQ-1)*dlnRS
     403            0 :             lnRS1 = lnRS0 + dlnRS
     404            0 :             lnRS = lnRS1
     405              :          end if
     406              :       else
     407            0 :          lnRS0 = lnRS_min + (iQ-1)*dlnRS
     408            0 :          lnRS1 = lnRS0 + dlnRS
     409              :       end if
     410            0 :    end subroutine Locate_lnRS
     411              : 
     412              : 
     413            0 :    subroutine Locate_lnGAME( &
     414              :          lnGAME, nlnGAME, lnGAME_min, dlnGAME, iQ, lnGAME0, lnGAME1)
     415              :       real(dp), intent(inout) :: lnGAME
     416              :       integer, intent(in) :: nlnGAME
     417              :       real(dp), intent(in) :: lnGAME_min, dlnGAME
     418              :       integer, intent(out) :: iQ
     419              :       real(dp), intent(out) :: lnGAME0, lnGAME1
     420            0 :       iQ = int((lnGAME - lnGAME_min)/dlnGAME + 1d-4) + 1
     421            0 :       if (iQ < 1 .or. iQ >= nlnGAME) then
     422            0 :          if (iQ < 1) then
     423            0 :             iQ = 1
     424            0 :             lnGAME0 = lnGAME_min
     425            0 :             lnGAME1 = lnGAME0 + dlnGAME
     426            0 :             lnGAME = lnGAME0
     427              :          else
     428            0 :             iQ = nlnGAME-1
     429            0 :             lnGAME0 = lnGAME_min + (iQ-1)*dlnGAME
     430            0 :             lnGAME1 = lnGAME0 + dlnGAME
     431            0 :             lnGAME = lnGAME1
     432              :          end if
     433              :       else
     434            0 :          lnGAME0 = lnGAME_min + (iQ-1)*dlnGAME
     435            0 :          lnGAME1 = lnGAME0 + dlnGAME
     436              :       end if
     437            0 :    end subroutine Locate_lnGAME
     438              : 
     439              : 
     440            0 :    subroutine Do_Interpolations( &
     441              :           nvlo, nvhi, nvals, n, nlnGAMI, x, ny, y, fin1, i, j, &
     442              :           x0, xget, x1, y0, yget, y1, &
     443            0 :           fval, df_dx, df_dy, ierr)
     444              :       integer, intent(in) :: nvlo, nvhi, nvals, n, nlnGAMI, ny
     445              :       real(dp), intent(in) :: x(:)  ! (nlnGAMI)
     446              :       real(dp), intent(in) :: y(:)  ! (ny)
     447              :       real(dp), intent(in), pointer :: fin1(:)  ! = (4,n,nlnGAMI,ny)
     448              :       integer, intent(in) :: i, j           ! target cell in f
     449              :       real(dp), intent(in) :: x0, xget, x1      ! x0 <= xget <= x1;  x0 = xs(i), x1 = xs(i+1)
     450              :       real(dp), intent(in) :: y0, yget, y1      ! y0 <= yget <= y1;  y0 = ys(j), y1 = ys(j+1)
     451              :       real(dp), intent(inout), dimension(nvals) :: fval, df_dx, df_dy
     452              :       integer, intent(out) :: ierr
     453              : 
     454            0 :       real(dp) :: xp, xpi, xp2, xpi2, ax, axbar, bx, bxbar, cx, cxi, hx2, cxd, cxdi, hx, hxi
     455            0 :       real(dp) :: yp, ypi, yp2, ypi2, ay, aybar, by, bybar, cy, cyi, hy2, cyd, cydi, hy, hyi
     456            0 :       real(dp) :: sixth_hx2, sixth_hy2, z36th_hx2_hy2
     457            0 :       real(dp) :: sixth_hx, sixth_hxi_hy2, z36th_hx_hy2
     458            0 :       real(dp) :: sixth_hx2_hyi, sixth_hy, z36th_hx2_hy
     459              :       integer :: k, ip1, jp1
     460            0 :       real(dp), pointer :: fin(:,:,:,:)
     461              : 
     462              :       include 'formats'
     463              : 
     464            0 :       ierr = 0
     465              : 
     466              :       fin(1:4,1:n,1:nlnGAMI,1:ny) => &
     467            0 :          fin1(1:4*n*nlnGAMI*ny)
     468              : 
     469            0 :       hx=x1-x0
     470            0 :       hxi=1d0/hx
     471            0 :       hx2=hx*hx
     472              : 
     473            0 :       xp=(xget-x0)*hxi
     474              : 
     475            0 :       xpi=1d0-xp
     476            0 :       xp2=xp*xp
     477            0 :       xpi2=xpi*xpi
     478              : 
     479            0 :       ax=xp2*(3d0-2d0*xp)
     480            0 :       axbar=1d0-ax
     481              : 
     482            0 :       bx=-xp2*xpi
     483            0 :       bxbar=xpi2*xp
     484              : 
     485            0 :       cx=xp*(xp2-1d0)
     486            0 :       cxi=xpi*(xpi2-1d0)
     487            0 :       cxd=3d0*xp2-1d0
     488            0 :       cxdi=-3d0*xpi2+1d0
     489              : 
     490            0 :       hy=y1-y0
     491            0 :       hyi=1d0/hy
     492            0 :       hy2=hy*hy
     493              : 
     494            0 :       yp=(yget-y0)*hyi
     495              : 
     496            0 :       ypi=1d0-yp
     497            0 :       yp2=yp*yp
     498            0 :       ypi2=ypi*ypi
     499              : 
     500            0 :       ay=yp2*(3d0-2d0*yp)
     501            0 :       aybar=1d0-ay
     502              : 
     503            0 :       by=-yp2*ypi
     504            0 :       bybar=ypi2*yp
     505              : 
     506            0 :       cy=yp*(yp2-1d0)
     507            0 :       cyi=ypi*(ypi2-1d0)
     508            0 :       cyd=3d0*yp2-1d0
     509            0 :       cydi=-3d0*ypi2+1d0
     510              : 
     511            0 :       sixth_hx2 = one_sixth*hx2
     512            0 :       sixth_hy2 = one_sixth*hy2
     513            0 :       z36th_hx2_hy2 = sixth_hx2*sixth_hy2
     514              : 
     515            0 :       sixth_hx = one_sixth*hx
     516            0 :       sixth_hxi_hy2 = one_sixth*hxi*hy2
     517            0 :       z36th_hx_hy2 = sixth_hx*sixth_hy2
     518              : 
     519            0 :       sixth_hx2_hyi = sixth_hx2*hyi
     520            0 :       sixth_hy = one_sixth*hy
     521            0 :       z36th_hx2_hy = sixth_hx2*sixth_hy
     522              : 
     523            0 :       ip1 = i+1
     524            0 :       jp1 = j+1
     525              : 
     526            0 :       !$omp simd
     527              :       do k = nvlo, nvhi
     528              :          ! bicubic spline interpolation
     529              : 
     530              :          ! f(1,i,j) = f(x(i),y(j))
     531              :          ! f(2,i,j) = d2f/dx2(x(i),y(j))
     532              :          ! f(3,i,j) = d2f/dy2(x(i),y(j))
     533              :          ! f(4,i,j) = d4f/dx2dy2(x(i),y(j))
     534              : 
     535              :          fval(k) = &
     536              :                xpi*( &
     537              :                   ypi*fin(1,k,i,j)  +yp*fin(1,k,i,jp1)) &
     538              :                   +xp*(ypi*fin(1,k,ip1,j)+yp*fin(1,k,ip1,jp1)) &
     539              :                +sixth_hx2*( &
     540              :                   cxi*(ypi*fin(2,k,i,j) +yp*fin(2,k,i,jp1))+ &
     541              :                   cx*(ypi*fin(2,k,ip1,j)+yp*fin(2,k,ip1,jp1))) &
     542              :                +sixth_hy2*( &
     543              :                   xpi*(cyi*fin(3,k,i,j) +cy*fin(3,k,i,jp1))+ &
     544              :                   xp*(cyi*fin(3,k,ip1,j)+cy*fin(3,k,ip1,jp1))) &
     545              :                +z36th_hx2_hy2*( &
     546              :                   cxi*(cyi*fin(4,k,i,j) +cy*fin(4,k,i,jp1))+ &
     547            0 :                   cx*(cyi*fin(4,k,ip1,j)+cy*fin(4,k,ip1,jp1)))
     548              : 
     549              :          ! derivatives of bicubic splines
     550              :          df_dx(k) = &
     551              :                hxi*( &
     552              :                   -(ypi*fin(1,k,i,j)  +yp*fin(1,k,i,jp1)) &
     553              :                   +(ypi*fin(1,k,ip1,j)+yp*fin(1,k,ip1,jp1))) &
     554              :                +sixth_hx*( &
     555              :                   cxdi*(ypi*fin(2,k,i,j) +yp*fin(2,k,i,jp1))+ &
     556              :                   cxd*(ypi*fin(2,k,ip1,j)+yp*fin(2,k,ip1,jp1))) &
     557              :                +sixth_hxi_hy2*( &
     558              :                   -(cyi*fin(3,k,i,j)  +cy*fin(3,k,i,jp1)) &
     559              :                   +(cyi*fin(3,k,ip1,j)+cy*fin(3,k,ip1,jp1))) &
     560              :                +z36th_hx_hy2*( &
     561              :                   cxdi*(cyi*fin(4,k,i,j) +cy*fin(4,k,i,jp1))+ &
     562            0 :                   cxd*(cyi*fin(4,k,ip1,j)+cy*fin(4,k,ip1,jp1)))
     563              : 
     564              :          df_dy(k) = &
     565              :                hyi*( &
     566              :                   xpi*(-fin(1,k,i,j) +fin(1,k,i,jp1))+ &
     567              :                   xp*(-fin(1,k,ip1,j)+fin(1,k,ip1,jp1))) &
     568              :                +sixth_hx2_hyi*( &
     569              :                   cxi*(-fin(2,k,i,j) +fin(2,k,i,jp1))+ &
     570              :                   cx*(-fin(2,k,ip1,j)+fin(2,k,ip1,jp1))) &
     571              :                +sixth_hy*( &
     572              :                   xpi*(cydi*fin(3,k,i,j) +cyd*fin(3,k,i,jp1))+ &
     573              :                   xp*(cydi*fin(3,k,ip1,j)+cyd*fin(3,k,ip1,jp1))) &
     574              :                +z36th_hx2_hy*( &
     575              :                   cxi*(cydi*fin(4,k,i,j) +cyd*fin(4,k,i,jp1))+ &
     576            0 :                   cx*(cydi*fin(4,k,ip1,j)+cyd*fin(4,k,ip1,jp1)))
     577              : 
     578              :       end do
     579              : 
     580            0 :    end subroutine Do_Interpolations
     581              : 
     582              : 
     583            0 :    subroutine load_eosPC_support_Info(fq, iZion, ierr)
     584              :       use const_def, only: mesa_data_dir
     585              :       use utils_lib, only: alloc_iounit, free_iounit
     586              :       use create_EXCOR7_table, only: do_create_EXCOR7_table
     587              :       use create_FSCRliq8_table, only: do_create_FSCRliq8_table
     588              :       type (eosPC_Support_Info), pointer :: fq
     589              :       integer, intent(in) :: iZion  ! 0 means EXCOR7
     590              :       integer, intent(out) :: ierr
     591              : 
     592              :       integer :: io_unit, n, j, i, iQ, nparams, nvals
     593              :       character (len=256) :: filename, fname, cache_fname, temp_cache_fname
     594              :       character (len=1000) :: message
     595            0 :       real(dp), pointer :: tbl2_1(:), tbl2(:,:,:)
     596            0 :       real(dp), target :: vec_ary(50)
     597              :       real(dp), pointer :: vec(:)
     598            0 :       real(dp) :: lnGAME, lnRS
     599              : 
     600              :       include 'formats'
     601            0 :       ierr = 0
     602            0 :       vec => vec_ary
     603              : 
     604            0 :       if (iZion == 0) then
     605            0 :          filename = 'EXCOR7'
     606            0 :       else if (iZion < 10) then
     607            0 :          write(filename,'(a,i1)') 'FSCRliq8_Zion_0', iZion
     608              :       else
     609            0 :          write(filename,'(a,i2)') 'FSCRliq8_Zion_', iZion
     610              :       end if
     611            0 :       fname = trim(mesa_data_dir) // '/eosPC_support_data/' // trim(filename) // '.data'
     612            0 :       cache_fname = trim(mesa_data_dir) // '/eosPC_support_data/cache/' // trim(filename) // '.bin'
     613            0 :       temp_cache_fname = trim(mesa_temp_caches_dir) // '/' // trim(filename) // '.bin'
     614              : 
     615            0 :       io_unit = alloc_iounit(ierr)
     616            0 :       if (ierr /= 0) then
     617            0 :          write(*,'(a)') 'failed to alloc_iounit'
     618            0 :          call mesa_error(__FILE__,__LINE__)
     619              :       end if
     620            0 :       open(unit=io_unit, FILE=trim(fname), ACTION='READ', STATUS='OLD', IOSTAT=ierr)
     621            0 :       if (ierr /= 0) then  ! need to open the table file
     622            0 :          ierr = 0
     623            0 :          if (iZion == 0) then
     624            0 :             call do_create_EXCOR7_table(fname)
     625              :          else
     626            0 :             call do_create_FSCRliq8_table(fname,iZion)
     627              :          end if
     628            0 :          open(unit=io_unit, FILE=trim(fname), ACTION='READ', STATUS='OLD', IOSTAT=ierr)
     629            0 :          if (ierr /= 0) then
     630            0 :             write(*,'(a)') 'failed to create ' // trim(fname)
     631            0 :             write(*,'(A)')
     632            0 :             call mesa_error(__FILE__,__LINE__)
     633              :          end if
     634              :       end if
     635              : 
     636            0 :       read(io_unit,*,iostat=ierr)  ! skip line 1
     637            0 :       if (ierr /= 0) return
     638              : 
     639            0 :       if (iZion == 0) then
     640            0 :          nparams = 8
     641            0 :          nvals = nvals_EXCOR7
     642              :       else
     643            0 :          nparams = 9
     644            0 :          nvals = nvals_FSCRliq8
     645              :       end if
     646            0 :       read(io_unit,'(a)',iostat=ierr) message  ! get parameters line
     647            0 :       if (ierr == 0) call str_to_vector(message, vec, n, ierr)
     648            0 :       if (ierr /= 0 .or. n < nparams) then
     649            0 :          write(*,'(a)') 'failed while reading ' // trim(fname)
     650            0 :          close(io_unit)
     651            0 :          ierr = -1
     652            0 :          return
     653              :       end if
     654              : 
     655            0 :       read(io_unit,*,iostat=ierr)  ! line 3
     656            0 :       if (ierr /= 0) return
     657              : 
     658            0 :       fq% Zion = iZion
     659            0 :       fq% nvals = nvals
     660            0 :       fq% nlnRS = int(vec(1))
     661            0 :       fq% lnRS_min = vec(2)*ln10
     662            0 :       fq% lnRS_max = vec(3)*ln10
     663            0 :       fq% dlnRS = vec(4)*ln10
     664              : 
     665            0 :       fq% nlnGAME = int(vec(5))
     666            0 :       fq% lnGAME_min = vec(6)*ln10
     667            0 :       fq% lnGAME_max = vec(7)*ln10
     668            0 :       fq% dlnGAME = vec(8)*ln10
     669              : 
     670            0 :       if (iZion > 0 .and. int(vec(9)) /= iZion) then
     671            0 :          write(*,*) 'bad value for Zion in file', int(vec(9)), iZion
     672            0 :          close(io_unit)
     673            0 :          ierr = -1
     674            0 :          return
     675              :       end if
     676              : 
     677              :       if (show_allocations) write(*,2) 'allocate pc_support', &
     678              :           4*nvals*fq% nlnRS*fq% nlnGAME + fq% nlnRS + fq% nlnGAME
     679              :       allocate(fq% tbl1(4*nvals*fq% nlnRS*fq% nlnGAME), &
     680            0 :          fq% lnRSs(fq% nlnRS), fq% lnGAMEs(fq% nlnGAME), STAT=ierr)
     681            0 :       if (ierr /= 0) return
     682              :       fq% tbl(1:4, 1:nvals, 1:fq% nlnRS, 1:fq% nlnGAME) =>  &
     683            0 :            fq% tbl1(1:4*nvals*fq% nlnRS*fq% nlnGAME)
     684              : 
     685            0 :       fq% lnRSs(1) = fq% lnRS_min
     686            0 :       do i = 2, fq% nlnRS-1
     687            0 :          fq% lnRSs(i) = fq% lnRSs(i-1) + fq% dlnRS
     688              :       end do
     689            0 :       fq% lnRSs(fq% nlnRS) = fq% lnRS_max
     690              : 
     691            0 :       fq% lnGAMEs(1) = fq% lnGAME_min
     692            0 :       do i = 2, fq% nlnGAME-1
     693            0 :          fq% lnGAMEs(i) = fq% lnGAMEs(i-1) + fq% dlnGAME
     694              :       end do
     695            0 :       fq% lnGAMEs(fq% nlnGAME) = fq% lnGAME_max
     696              : 
     697            0 :       if (use_cache_for_eos) then
     698            0 :          call Read_Cache(fq, cache_fname, ierr)
     699            0 :          if (ierr == 0) then  ! got it from the cache
     700            0 :             close(io_unit)
     701            0 :             call free_iounit(io_unit)
     702            0 :             return
     703              :          end if
     704            0 :          ierr = 0
     705              :       end if
     706              : 
     707            0 :       allocate(tbl2_1(nvals*fq% nlnRS*fq% nlnGAME), STAT=ierr)
     708            0 :       if (ierr /= 0) return
     709              : 
     710              :       tbl2(1:nvals, 1:fq% nlnRS, 1:fq% nlnGAME) =>  &
     711            0 :             tbl2_1(1:nvals*fq% nlnRS*fq% nlnGAME)
     712              : 
     713            0 :       do iQ=1,fq% nlnRS
     714              : 
     715            0 :          read(io_unit,*,iostat=ierr)
     716            0 :          if (failed('skip line1')) return
     717              : 
     718            0 :          read(io_unit,'(a)',iostat=ierr) message
     719            0 :          if (ierr == 0) call str_to_double(message, vec(1), ierr)
     720            0 :          if (failed('read lnRS')) return
     721            0 :          lnRS = vec(1)
     722              : 
     723            0 :          read(io_unit,*,iostat=ierr)
     724            0 :          if (failed('skip line2')) return
     725              : 
     726            0 :          read(io_unit,*,iostat=ierr)
     727            0 :          if (failed('skip line3')) return
     728              : 
     729            0 :          do i=1,fq% nlnGAME
     730              : 
     731            0 :             read(io_unit,'(a)',iostat=ierr) message
     732            0 :             if (failed('read line')) then
     733            0 :                write(*,'(a)') trim(message)
     734            0 :                write(*,*) trim(fname)
     735            0 :                write(*,*) 'iQ, i', iQ, i
     736            0 :                write(*,*) 'lnRS', lnRS
     737            0 :                write(*,*) 'bad input line?'
     738            0 :                call mesa_error(__FILE__,__LINE__)
     739              :             end if
     740              : 
     741            0 :             call str_to_vector(message, vec, n, ierr)
     742            0 :             if (ierr /= 0 .or. n < 1+nvals) then
     743            0 :                write(*,'(a)') trim(message)
     744            0 :                write(*,*) trim(fname)
     745            0 :                write(*,*) 'iQ, i', iQ, i
     746            0 :                write(*,*) 'lnRS', lnRS
     747            0 :                write(*,*) 'bad input line?'
     748            0 :                call mesa_error(__FILE__,__LINE__)
     749              :             end if
     750            0 :             lnGAME = vec(1)
     751            0 :             do j=1,nvals
     752            0 :                tbl2(j,iQ,i) = vec(1+j)
     753              :             end do
     754              : 
     755              :          end do
     756              : 
     757            0 :          if(iQ == fq% nlnRS) exit
     758            0 :          read(io_unit,*,iostat=ierr)
     759            0 :          if (failed('skip line4')) return
     760            0 :          read(io_unit,*,iostat=ierr)
     761            0 :          if (failed('skip line5')) return
     762              : 
     763              :       end do
     764              : 
     765            0 :       close(io_unit)
     766              : 
     767            0 :       call Make_Interpolation_Data(fq, nvals, tbl2_1, ierr)
     768            0 :       deallocate(tbl2_1)
     769            0 :       if (failed('Make_Interpolation_Data')) return
     770              : 
     771            0 :       call Check_Interpolation_Data
     772              : 
     773            0 :       if (.not. use_cache_for_eos) then
     774            0 :          call free_iounit(io_unit)
     775            0 :          return
     776              :       end if
     777              : 
     778              :       open(unit=io_unit, &
     779              :          file=trim(switch_str(temp_cache_fname, cache_fname, use_mesa_temp_cache)), &
     780            0 :          iostat=ierr, action='write', form='unformatted')
     781            0 :       if (ierr == 0) then
     782            0 :          write(*,'(a)') ' write ' // trim(cache_fname)
     783              :          write(io_unit)  &
     784            0 :             fq% Zion, fq% nlnGAME, fq% lnGAME_min, fq% lnGAME_max, fq% dlnGAME,  &
     785            0 :             fq% nlnRS, fq% lnRS_min, fq% lnRS_max, fq% dlnRS
     786            0 :          write(io_unit) fq% tbl1(1:4*nvals*fq% nlnRS*fq% nlnGAME)
     787            0 :          close(io_unit)
     788            0 :          if (use_mesa_temp_cache) call mv(temp_cache_fname, cache_fname, .true.)
     789              :       end if
     790            0 :       call free_iounit(io_unit)
     791              : 
     792            0 :       if (iZion == 0) then
     793            0 :          EXCOR7_table_loaded = .true.
     794              :       else
     795            0 :          FSCRliq8_Zion_loaded(iZion) = .true.
     796              :       end if
     797              : 
     798              :       contains
     799              : 
     800            0 :       subroutine Check_Interpolation_Data
     801              :          integer :: i, j, iQ, jtemp
     802            0 :          do i = 1, 4
     803            0 :             do j = 1, nvals
     804            0 :                do iQ = 1, fq% nlnRS
     805            0 :                   do jtemp = 1, fq% nlnGAME
     806            0 :                      if (is_bad(fq% tbl(i,j,iQ,jtemp))) then
     807            0 :                         fq% tbl(i,j,iQ,jtemp) = 0
     808              :                      end if
     809              :                   end do
     810              :                end do
     811              :             end do
     812              :          end do
     813            0 :       end subroutine Check_Interpolation_Data
     814              : 
     815            0 :       logical function failed(str)
     816              :          character (len=*), intent(in) :: str
     817            0 :          failed = (ierr /= 0)
     818            0 :          if (failed) write(*,*) 'load_eosPC_support_Info failed: ' // trim(str)
     819            0 :          if (failed) call mesa_error(__FILE__,__LINE__,'load_eosPC_support_Info')
     820            0 :       end function failed
     821              : 
     822              :    end subroutine load_eosPC_support_Info
     823              : 
     824              : 
     825            0 :    subroutine Make_Interpolation_Data(fq, nvals, tbl2_1, ierr)
     826              :       use interp_2d_lib_db
     827              :       type (eosPC_Support_Info), pointer :: fq
     828              :       integer, intent(in) :: nvals
     829              :       real(dp), pointer :: tbl2_1(:)  ! =(nvals, nlnRS, nlnGAME)
     830              :       integer, intent(out) :: ierr
     831              : 
     832            0 :       real(dp), allocatable, target :: f1_ary(:)  ! data & spline coefficients
     833            0 :       real(dp), pointer :: f1(:), f(:,:,:), tbl2(:,:,:)
     834              :       integer :: ibcxmin                 ! bc flag for x=xmin
     835            0 :       real(dp) :: bcxmin(fq% nlnGAME)    ! bc data vs. y at x=xmin
     836              :       integer :: ibcxmax                 ! bc flag for x=xmax
     837            0 :       real(dp) :: bcxmax(fq% nlnGAME)    ! bc data vs. y at x=xmax
     838              :       integer :: ibcymin                 ! bc flag for y=ymin
     839            0 :       real(dp) :: bcymin(fq% nlnRS)      ! bc data vs. x at y=ymin
     840              :       integer :: ibcymax                 ! bc flag for y=ymax
     841            0 :       real(dp) :: bcymax(fq% nlnRS)      ! bc data vs. x at y=ymax
     842              :       integer :: ili_lnRSs        ! =1: logRho grid is "nearly" equally spaced
     843              :       integer :: ili_lnGAMEs      ! =1: lnGAME grid is "nearly" equally spaced
     844              :       integer :: ier              ! =0 on exit if there is no error.
     845              : 
     846              :       integer :: v, i, j
     847              : 
     848              :       include 'formats'
     849              : 
     850            0 :       ierr = 0
     851              : 
     852              :       ! just use "not a knot" bc's at edges of tables
     853            0 :       ibcxmin = 0; bcxmin(:) = 0
     854            0 :       ibcxmax = 0; bcxmax(:) = 0
     855            0 :       ibcymin = 0; bcymin(:) = 0
     856            0 :       ibcymax = 0; bcymax(:) = 0
     857              : 
     858              :       tbl2(1:nvals, 1:fq% nlnRS, 1:fq% nlnGAME) =>  &
     859            0 :             tbl2_1(1:nvals*fq% nlnRS*fq% nlnGAME)
     860              :       ! copy file variables to internal interpolation tables
     861            0 :       do j=1,fq% nlnGAME
     862            0 :          do i=1,fq% nlnRS
     863            0 :             do v = 1, nvals
     864            0 :                fq% tbl(1,v,i,j) = tbl2(v,i,j)
     865              :             end do
     866              :          end do
     867              :       end do
     868              : 
     869            0 :       allocate(f1_ary(4 * fq% nlnRS * fq% nlnGAME))
     870              : 
     871            0 :       f1 => f1_ary
     872              :       f(1:4, 1:fq% nlnRS, 1:fq% nlnGAME) => &
     873            0 :             f1_ary(1:4*fq% nlnRS*fq% nlnGAME)
     874              : 
     875              :       ! create tables for bicubic spline interpolation
     876            0 :       do v = 1, nvals
     877            0 :          do i=1,fq% nlnRS
     878            0 :             do j=1,fq% nlnGAME
     879            0 :                f(1,i,j) = fq% tbl(1,v,i,j)
     880              :             end do
     881              :          end do
     882              :          call interp_mkbicub_db( &
     883              :                fq% lnRSs,fq% nlnRS,fq% lnGAMEs,fq% nlnGAME,f1,fq% nlnRS, &
     884              :                ibcxmin,bcxmin,ibcxmax,bcxmax, &
     885              :                ibcymin,bcymin,ibcymax,bcymax, &
     886            0 :                ili_lnRSs,ili_lnGAMEs,ier)
     887            0 :          if (ier /= 0) then
     888            0 :             write(*,*) 'interp_mkbicub_db error happened for EXCOR7 value', v
     889            0 :             ierr = 3
     890            0 :             return
     891              :          end if
     892            0 :          do i=1,fq% nlnRS
     893            0 :             do j=1,fq% nlnGAME
     894            0 :                fq% tbl(2,v,i,j) = f(2,i,j)
     895            0 :                fq% tbl(3,v,i,j) = f(3,i,j)
     896            0 :                fq% tbl(4,v,i,j) = f(4,i,j)
     897              :             end do
     898              :          end do
     899              :       end do
     900              : 
     901            0 :    end subroutine Make_Interpolation_Data
     902              : 
     903              : 
     904            0 :    subroutine Read_Cache(fq, cache_fname, ierr)
     905              :       use utils_lib, only: alloc_iounit, free_iounit
     906              :       type (eosPC_Support_Info), pointer :: fq
     907              :       character (*), intent(in) :: cache_fname
     908              :       integer, intent(out) :: ierr
     909              : 
     910            0 :       real(dp) :: lnGAME_min_in, lnGAME_max_in, dlnGAME_in,  &
     911            0 :             lnRS_min_in, lnRS_max_in, dlnRS_in
     912              :       integer :: Zion_in, nlnRS_in, nlnGAME_in, io_unit
     913              :       real(dp), parameter :: tiny = 1d-10
     914              : 
     915              :       include 'formats'
     916              : 
     917              :       ierr = 0
     918              : 
     919            0 :       io_unit = alloc_iounit(ierr)
     920            0 :       if (ierr /= 0) then
     921            0 :          write(*,'(a)') 'failed to alloc_iounit'
     922            0 :          call mesa_error(__FILE__,__LINE__)
     923              :       end if
     924              :       open(unit=io_unit, file=trim(cache_fname), action='read', &
     925            0 :             status='old', iostat=ierr, form='unformatted')
     926            0 :       if (ierr /= 0) then
     927            0 :          call free_iounit(io_unit)
     928            0 :          return
     929              :       end if
     930              : 
     931              :       !write(*,'(a)') 'read ' // trim(cache_fname)
     932              : 
     933              :       read(io_unit, iostat=ierr)  &
     934            0 :             Zion_in, nlnGAME_in, lnGAME_min_in, lnGAME_max_in, dlnGAME_in,  &
     935            0 :             nlnRS_in, lnRS_min_in, lnRS_max_in, dlnRS_in
     936            0 :       if (ierr /= 0) then
     937            0 :          write(*,*) 'read cache failed'
     938              :       end if
     939              : 
     940            0 :       if (fq% Zion /= Zion_in) then
     941            0 :          ierr = 1
     942            0 :          write(*,*) 'read cache failed for Zion'
     943              :       end if
     944            0 :       if (fq% nlnRS /= nlnRS_in) then
     945            0 :          ierr = 1
     946            0 :          write(*,*) 'read cache failed for nlnRS'
     947              :       end if
     948            0 :       if (fq% nlnGAME /= nlnGAME_in) then
     949            0 :          ierr = 1
     950            0 :          write(*,*) 'read cache failed for nlnGAME'
     951              :       end if
     952            0 :       if (abs(fq% lnGAME_min-lnGAME_min_in) > tiny) then
     953            0 :          ierr = 1
     954            0 :          write(*,*) 'read cache failed for eos_lnGAME_min'
     955              :       end if
     956            0 :       if (abs(fq% lnGAME_max-lnGAME_max_in) > tiny) then
     957            0 :          ierr = 1
     958            0 :          write(*,*) 'read cache failed for eos_lnGAME_max'
     959              :       end if
     960            0 :       if (abs(fq% dlnGAME-dlnGAME_in) > tiny) then
     961            0 :          ierr = 1
     962            0 :          write(*,*) 'read cache failed for eos_dlnGAME'
     963              :       end if
     964            0 :       if (abs(fq% lnRS_min-lnRS_min_in) > tiny) then
     965            0 :          ierr = 1
     966            0 :          write(*,*) 'read cache failed for eos_lnRS_min'
     967              :       end if
     968            0 :       if (abs(fq% lnRS_max-lnRS_max_in) > tiny) then
     969            0 :          ierr = 1
     970            0 :          write(*,*) 'read cache failed for eos_lnRS_max'
     971              :       end if
     972            0 :       if (abs(fq% dlnRS-dlnRS_in) > tiny) then
     973            0 :          ierr = 1
     974            0 :          write(*,*) 'read cache failed for eos_dlnRS'
     975              :       end if
     976              : 
     977            0 :       if (ierr /= 0) then
     978            0 :          write(*,*) 'read cache file failed 1'
     979            0 :          call mesa_error(__FILE__,__LINE__,'Read_Cache')
     980            0 :          close(io_unit); return
     981              :       end if
     982              : 
     983              :       read(io_unit, iostat=ierr) &
     984            0 :          fq% tbl1(1:4*fq% nvals*fq% nlnRS*fq% nlnGAME)
     985            0 :       if (ierr /= 0) then
     986            0 :          write(*,*) 'read cache file failed 2'
     987            0 :          call mesa_error(__FILE__,__LINE__,'Read_Cache')
     988              :       end if
     989              : 
     990            0 :       close(io_unit)
     991            0 :       call free_iounit(io_unit)
     992              : 
     993              :    end subroutine Read_Cache
     994              : 
     995              : 
     996              : ! ==================  ELECTRON-ION COULOMB LIQUID  =================== *
     997            0 :       subroutine FITION9(GAMI, &
     998              :            FION,UION,PION,CVii,PDTii,PDRii)
     999              : !                                                       Version 11.09.08
    1000              : ! Non-ideal contributions to thermodynamic functions of classical OCP,
    1001              : !       corrected at small density for a mixture.
    1002              : !   Stems from FITION00 v.24.05.00.
    1003              : ! Input: GAMI - ion coupling parameter
    1004              : ! Output: FION - ii free energy / N_i kT
    1005              : !         UION - ii internal energy / N_i kT
    1006              : !         PION - ii pressure / n_i kT
    1007              : !         CVii - ii heat capacity / N_i k
    1008              : !         PDTii = PION + d(PION)/d ln T = (1/N_i kT)*(d P_{ii}/d ln T)
    1009              : !         PDRii = PION + d(PION)/d ln\rho
    1010              : !   Parameters adjusted to Caillol (1999).
    1011              :       real(dp), intent(in) :: GAMI
    1012              :       real(dp), intent(out) :: FION, UION, PION, CVii, PDTii, PDRii
    1013            0 :       real(dp) :: F0, U0
    1014              : 
    1015              :       real(dp), parameter :: A1=-.907347d0
    1016              :       real(dp), parameter :: A2=.62849d0
    1017              :       real(dp) :: A3
    1018              :       real(dp), parameter :: C1=.004500d0
    1019              :       real(dp), parameter :: G1=170.0d0
    1020              :       real(dp), parameter :: C2=-8.4d-5
    1021              :       real(dp), parameter :: G2=.0037d0
    1022              :       real(dp), parameter :: SQ32=.8660254038d0  ! SQ32=sqrt(3)/2
    1023              : 
    1024            0 :       A3=-SQ32-A1/sqrt(A2)
    1025              :       F0=A1*(sqrt(GAMI*(A2+GAMI)) &
    1026              :          - A2*log(sqrt(GAMI/A2)+sqrt(1d0+GAMI/A2))) &
    1027            0 :          + 2d0*A3*(sqrt(GAMI)-atan(sqrt(GAMI)))
    1028            0 :       U0=pow3(sqrt(GAMI))*(A1/sqrt(A2+GAMI)+A3/(1.d0+GAMI))
    1029              : !   This is the zeroth approximation. Correction:
    1030            0 :       UION=U0+C1*GAMI*GAMI/(G1+GAMI)+C2*GAMI*GAMI/(G2+GAMI*GAMI)
    1031              :       FION=F0+C1*(GAMI-G1*log(1.d0+GAMI/G1)) &
    1032            0 :          + C2/2d0*log(1.d0+GAMI*GAMI/G2)
    1033              :       CVii=-0.5d0*pow3(sqrt(GAMI))*(A1*A2/pow3(sqrt(A2+GAMI)) &
    1034              :          + A3*(1.d0-GAMI)/pow2(1.d0+GAMI)) &
    1035            0 :          - GAMI*GAMI*(C1*G1/pow2(G1+GAMI)+C2*(G2-GAMI*GAMI)/pow2(G2+GAMI*GAMI))
    1036            0 :       PION=UION/3.0d0
    1037            0 :       PDRii=(4.0d0*UION-CVii)/9.0d0  ! p_{ii} + d p_{ii} / d ln\rho
    1038            0 :       PDTii=CVii/3.0d0  ! p_{ii} + d p_{ii} / d ln T
    1039            0 :       return
    1040              :       end subroutine FITION9
    1041              : 
    1042              : 
    1043              :    end module pc_support
        

Generated by: LCOV version 2.0-1