LCOV - code coverage report
Current view: top level - kap/private - kap_eval.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 70.1 % 304 213
Test Date: 2025-05-08 18:23:42 Functions: 83.3 % 6 5

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2019  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              :       module kap_eval
      21              : 
      22              :       use utils_lib, only: is_bad, mesa_error
      23              :       use kap_def
      24              :       use const_def, only: dp, ln10, sige, me, kev, kerg, amu, clight
      25              :       use math_lib
      26              : 
      27              :       implicit none
      28              : 
      29              :       private
      30              :       public :: get_kap_results
      31              :       public :: combine_rad_with_conduction
      32              :       public :: get_kap_results_blend_t
      33              :       public :: compton_opacity
      34              : 
      35              :       contains
      36              : 
      37        86216 :       subroutine get_kap_Results( &
      38              :            rq, zbar, X, Z, XC, XN, XO, XNe, logRho, logT, &
      39              :            lnfree_e, d_lnfree_e_dlnRho, d_lnfree_e_dlnT, &
      40              :            eta, d_eta_dlnRho, d_eta_dlnT, &
      41              :            kap_fracs, kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
      42              :          use utils_lib, only: is_bad
      43              :          use auto_diff
      44              : 
      45              :          type (Kap_General_Info), pointer :: rq
      46              :          real(dp), intent(in) :: X, XC, XN, XO, XNe, Z, zbar
      47              :          real(dp), intent(in) :: logRho, logT
      48              :          real(dp), intent(in) :: lnfree_e, d_lnfree_e_dlnRho, d_lnfree_e_dlnT
      49              :          real(dp), intent(in) :: eta, d_eta_dlnRho, d_eta_dlnT
      50              :          real(dp), intent(out) :: kap_fracs(num_kap_fracs)
      51              :          real(dp), intent(out) :: kap  ! opacity
      52              :          real(dp), intent(out) :: dlnkap_dlnRho  ! partial derivative at constant T
      53              :          real(dp), intent(out) :: dlnkap_dlnT   ! partial derivative at constant Rho
      54              :          integer, intent(out) :: ierr  ! 0 means AOK.
      55              : 
      56        86216 :          real(dp) :: kap_rad, dlnkap_rad_dlnRho, dlnkap_rad_dlnT
      57        86216 :          real(dp) :: kap_compton, dlnkap_compton_dlnRho, dlnkap_compton_dlnT
      58              : 
      59        86216 :          real(dp) :: logT_Compton_blend_lo, logT_Compton_blend_hi
      60        86216 :          real(dp) :: logR_Compton_blend_lo, logR_Compton_blend_hi
      61              : 
      62              :          real(dp) :: Rho, T
      63              :          type(auto_diff_real_2var_order1) :: logT_auto, logRho_auto, logR_auto
      64              :          type(auto_diff_real_2var_order1) :: logkap_rad, logkap_compton
      65              :          type(auto_diff_real_2var_order1) :: blend_logT, blend_logR, blend
      66              : 
      67        86216 :          real(dp) :: frac_Type2, frac_highT, frac_lowT
      68              : 
      69              :          logical :: dbg
      70              : 
      71              :          include 'formats'
      72              : 
      73        86216 :          dbg = rq% dbg
      74        86216 :          if (dbg) dbg = &  ! check limits
      75              :             logT >= rq% logT_lo .and. logT <= rq% logT_hi .and. &
      76              :             logRho >= rq% logRho_lo .and. logRho <= rq% logRho_hi .and. &
      77              :             X >= rq% X_lo .and. X <= rq% X_hi .and. &
      78            0 :             Z >= rq% Z_lo .and. Z <= rq% Z_hi
      79              : 
      80              :          ! auto diff
      81              :          ! var1: logRho
      82              :          ! var2: logT
      83              : 
      84        86216 :          Rho = exp10(logRho)
      85        86216 :          logRho_auto% val = logRho
      86        86216 :          logRho_auto% d1val1 = 1d0
      87        86216 :          logRho_auto% d1val2 = 0d0
      88              : 
      89        86216 :          T = exp10(logT)
      90        86216 :          logT_auto% val = logT
      91        86216 :          logT_auto% d1val1 = 0d0
      92        86216 :          logT_auto% d1val2 = 1d0
      93              : 
      94        86216 :          logR_auto = logRho_auto - 3d0*logT_auto + 18d0
      95              : 
      96        86216 :          if (dbg) write(*,1) 'logRho', logRho
      97            0 :          if (dbg) write(*,1) 'logT', logT
      98        86216 :          if (dbg) write(*,1) 'logR', logR_auto% val
      99              : 
     100              :          ! initialize fracs
     101        86216 :          kap_fracs = 0
     102        86216 :          frac_Type2 = 0d0
     103        86216 :          frac_lowT = 0d0
     104        86216 :          frac_highT = 0d0
     105              : 
     106              :          ! blend to Compton at high T
     107        86216 :          logT_Compton_blend_hi = rq% logT_Compton_blend_hi
     108        86216 :          logT_Compton_blend_lo = logT_Compton_blend_hi - 0.50d0
     109              : 
     110              :          ! blend in logT
     111        86216 :          if (logT_auto >= logT_Compton_blend_hi) then
     112            0 :             blend_logT = 1d0
     113        86216 :          else if (logT_auto > logT_Compton_blend_lo .and. logT_auto <= logT_Compton_blend_hi) then
     114            0 :             blend_logT = (logT_auto - logT_Compton_blend_lo) / (logT_Compton_blend_hi - logT_Compton_blend_lo)
     115              :          else
     116        86216 :             blend_logT = 0d0
     117              :          end if
     118              :          ! quintic smoothing
     119        86216 :          blend_logT = -blend_logT*blend_logT*blend_logT*(-10d0 + blend_logT*(15d0 - 6d0*blend_logT))
     120              : 
     121              : 
     122              :          ! blend to Compton at low R
     123        86216 :          logR_Compton_blend_lo = rq% logR_Compton_blend_lo
     124        86216 :          logR_Compton_blend_hi = logR_Compton_blend_lo + 0.50d0
     125              : 
     126              :          ! blend in logR
     127        86216 :          if (logR_auto <= logR_Compton_blend_lo) then
     128            0 :             blend_logR = 1d0
     129        86216 :          else if (logR_auto > logR_Compton_blend_lo .and. logR_auto <= logR_Compton_blend_hi) then
     130            0 :             blend_logR = (logR_Compton_blend_hi - logR_auto) / (logR_Compton_blend_hi - logR_Compton_blend_lo)
     131              :          else
     132        86216 :             blend_logR = 0d0
     133              :          end if
     134              :          ! quintic smoothing
     135        86216 :          blend_logR = -blend_logR*blend_logR*blend_logR*(-10d0 + blend_logR*(15d0 - 6d0*blend_logR))
     136              : 
     137              : 
     138              :          ! smoothly combine blends
     139        86216 :          blend = 1d0 - (1d0-blend_logT)*(1d0-blend_logR)
     140        86216 :          kap_fracs(i_frac_Compton) = blend% val
     141              : 
     142              : 
     143        86216 :          if (blend > 0) then  ! at least some compton
     144              : 
     145            0 :             if (rq % use_other_compton_opacity) then
     146              :                call rq% other_compton_opacity(rq% handle, Rho, T, &
     147              :                   lnfree_e, d_lnfree_e_dlnRho, d_lnfree_e_dlnT, &
     148              :                   eta, d_eta_dlnRho, d_eta_dlnT, &
     149            0 :                   kap_compton, dlnkap_compton_dlnRho, dlnkap_compton_dlnT, ierr)
     150              :             else
     151              :                call Compton_Opacity(rq, Rho, T, &
     152              :                   lnfree_e, d_lnfree_e_dlnRho, d_lnfree_e_dlnT, &
     153              :                   eta, d_eta_dlnRho, d_eta_dlnT, &
     154            0 :                   kap_compton, dlnkap_compton_dlnRho, dlnkap_compton_dlnT, ierr)
     155              :             end if
     156              : 
     157            0 :             if (ierr /= 0) return
     158              : 
     159              :          else  ! no Compton
     160              : 
     161        86216 :             kap_compton = 1d-30
     162        86216 :             dlnkap_compton_dlnRho = 0d0
     163        86216 :             dlnkap_compton_dlnT = 0d0
     164              : 
     165              :          end if
     166              : 
     167              :          ! pack into auto_diff type
     168        86216 :          logkap_compton = log10(kap_compton)
     169        86216 :          logkap_compton% d1val1 = dlnkap_compton_dlnRho
     170        86216 :          logkap_compton% d1val2 = dlnkap_compton_dlnT
     171              : 
     172              : 
     173        86216 :          if (blend < 1) then  ! at least some tables
     174              : 
     175        86216 :             if (rq% use_other_radiative_opacity) then
     176              :                call rq% other_radiative_opacity( &
     177              :                   rq% handle, X, Z, XC, XN, XO, XNe, logRho, logT, &
     178              :                   frac_lowT, frac_highT, frac_Type2, &
     179            0 :                   kap_rad, dlnkap_rad_dlnRho, dlnkap_rad_dlnT, ierr)
     180              :             else
     181              :                call Get_kap_Results_blend_T( &
     182              :                   rq, X, Z, XC, XN, XO, XNe, logRho, logT, &
     183              :                   frac_lowT, frac_highT, frac_Type2, &
     184        86216 :                   kap_rad, dlnkap_rad_dlnRho, dlnkap_rad_dlnT, ierr)
     185              :             end if
     186        86216 :             if (ierr /= 0) return
     187              : 
     188              :             ! revise reported fractions based on Compton blend
     189        86216 :             frac_lowT = (1d0 - blend% val) * frac_lowT
     190        86216 :             frac_highT = (1d0 - blend% val) * frac_highT
     191              :             ! the value of frac_Type2 doesn't need revised if it represents
     192              :             ! the fraction of highT opacities provided by the Type2 tables
     193              :             ! frac_Type2 = (1d0 - blend% val) * frac_Type2
     194              : 
     195              :          else  ! no tables
     196              : 
     197            0 :             kap_rad = 1d-30
     198            0 :             dlnkap_rad_dlnRho = 0d0
     199            0 :             dlnkap_rad_dlnT = 0d0
     200              : 
     201              :          end if
     202              : 
     203              :          ! pack into auto_diff type
     204        86216 :          logkap_rad = log10(kap_rad)
     205        86216 :          logkap_rad% d1val1 = dlnkap_rad_dlnRho
     206        86216 :          logkap_rad% d1val2 = dlnkap_rad_dlnT
     207              : 
     208              :          ! pack kap_fracs from tables
     209        86216 :          kap_fracs(i_frac_lowT) = frac_lowT
     210        86216 :          kap_fracs(i_frac_highT) = frac_highT
     211        86216 :          kap_fracs(i_frac_Type2) = frac_Type2
     212              : 
     213              :          ! do blend
     214        86216 :          logkap_rad = blend * logkap_compton + (1d0 - blend) * logkap_rad
     215              : 
     216              :          ! unpack auto_diff
     217        86216 :          kap_rad = exp10(logkap_rad% val)
     218        86216 :          dlnkap_rad_dlnRho = logkap_rad% d1val1
     219        86216 :          dlnkap_rad_dlnT = logkap_rad% d1val2
     220              : 
     221              :          call combine_rad_with_conduction( &
     222              :             rq, logRho, logT, zbar, &
     223              :             kap_rad, dlnkap_rad_dlnRho, dlnkap_rad_dlnT, &
     224        86216 :             kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     225              : 
     226        86216 :       end subroutine get_kap_Results
     227              : 
     228              : 
     229        86416 :       subroutine get_kap_Results_blend_T( &
     230              :            rq, X, Z, XC, XN, XO, XNe, logRho_in, logT_in, &
     231              :            frac_lowT, frac_highT, frac_Type2, kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     232              : 
     233        86216 :         use kap_def
     234              :         use utils_lib, only: is_bad
     235              : 
     236              :         ! INPUT
     237              :         type (Kap_General_Info), pointer :: rq
     238              :         real(dp), intent(in) :: X, Z, XC, XN, XO, XNe  ! composition
     239              :         real(dp), intent(in) :: logRho_in  ! density
     240              :         real(dp), intent(in) :: logT_in  ! temperature
     241              : 
     242              :         ! OUTPUT
     243              :         real(dp), intent(out) :: frac_lowT, frac_highT, frac_Type2
     244              :         real(dp), intent(out) :: kap  ! opacity
     245              :         real(dp), intent(out) :: dlnkap_dlnRho  ! partial derivative at constant T
     246              :         real(dp), intent(out) :: dlnkap_dlnT   ! partial derivative at constant Rho
     247              :         integer, intent(out) :: ierr  ! 0 means AOK.
     248              : 
     249        86216 :         real(dp) :: logRho, Rho, logT, T
     250              :         real(dp) :: frac_Type1, dZ, frac_X, frac_dZ, &
     251              :              dXC, dXO, fC, fN, fO, fNe, fHeavy, ZHeavy, dXsum
     252              : 
     253        86216 :         real(dp) :: lowT_logT_max, logT_min
     254              : 
     255              :         logical :: clipped_Rho
     256              : 
     257              :         logical :: dbg
     258              : 
     259        86216 :         real(dp) :: alfa, beta, &
     260        86216 :              logKap, logKap1, logKap2, &
     261        86216 :              kap1, dlnkap1_dlnRho, dlnkap1_dlnT, &
     262        86216 :              kap2, dlnkap2_dlnRho, dlnkap2_dlnT, &
     263        86216 :              lower_bdy, upper_bdy, alfa0, d_alfa0_dlnT, &
     264        86216 :              d_alfa_dlnT, d_beta_dlnT, dkap_dlnT
     265              : 
     266              : 
     267              :         include 'formats'
     268              : 
     269        86216 :         dbg = .false.
     270              : 
     271        86216 :         logRho = logRho_in; Rho = exp10(logRho)
     272        86216 :         logT = logT_in; T = exp10(logT)
     273              : 
     274              :         if (dbg) write(*,1) 'Get_kap_blend_logT logT', logT
     275              : 
     276        86216 :         clipped_Rho = .false.
     277        86216 :         if (logRho < kap_min_logRho) then
     278            0 :            logRho = kap_min_logRho
     279            0 :            rho = exp10(kap_min_logRho)
     280            0 :            clipped_Rho = .true.
     281              :         end if
     282              : 
     283        86216 :         frac_lowT = 0d0
     284        86216 :         frac_highT = 0d0
     285              :         frac_Type2 = 0d0
     286              : 
     287        86216 :         if (rq% use_Type2_opacities .and. &
     288              :             associated(kap_co_z_tables(rq% kap_CO_option)% ar)) then
     289        86214 :            logT_min = kap_co_z_tables(rq% kap_CO_option)% ar(1)% x_tables(1)% logT_min
     290              :         else
     291            2 :            logT_min = kap_z_tables(rq% kap_option)% ar(1)% x_tables(1)% logT_min
     292              :         end if
     293              : 
     294        86216 :         lower_bdy = max(rq% kap_blend_logT_lower_bdy, logT_min)
     295              :         if (dbg) write(*,1) 'Get_kap_blend_logT lower_bdy', lower_bdy, &
     296              :              rq% kap_blend_logT_lower_bdy, logT_min
     297        86216 :         if (logT <= lower_bdy) then  ! all lowT
     298              :            if (dbg) write(*,1) 'all lowT'
     299              :            call Get_kap_lowT_Results(rq, &
     300              :                 X, Z, XC, XN, XO, XNe, logRho, logT, &
     301         5852 :                 frac_Type2, kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     302         5852 :            if (clipped_Rho) dlnkap_dlnRho = 0d0
     303         5852 :            frac_lowT = 1d0
     304        86116 :            return
     305              :         end if
     306              : 
     307              : 
     308        80364 :         select case (rq% kap_lowT_option)
     309              :         case (kap_lowT_kapCN)
     310            0 :            lowT_logT_max = kapCN_max_logT
     311              :         case (kap_lowT_AESOPUS)
     312            0 :            lowT_logT_max = kA % max_logT
     313              :         case default
     314        80364 :            lowT_logT_max = kap_lowT_z_tables(rq% kap_lowT_option)% ar(1)% x_tables(1)% logT_max
     315              :         end select
     316              : 
     317              : 
     318        80364 :         upper_bdy = min(rq% kap_blend_logT_upper_bdy, lowT_logT_max)
     319              :         if (dbg) write(*,1) 'Get_kap_blend_logT upper_bdy', upper_bdy, &
     320              :              rq% kap_blend_logT_upper_bdy, lowT_logT_max
     321        80364 :         if (logT >= upper_bdy) then  ! no lowT
     322              :            if (dbg) write(*,1) 'no lowT'
     323              :            call Get_kap_highT_Results(rq, &
     324              :                 X, Z, XC, XN, XO, XNe, logRho, logT, &
     325        80264 :                 frac_Type2, kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     326        80264 :            if (clipped_Rho) dlnkap_dlnRho = 0d0
     327        80264 :            frac_highT = 1d0
     328        80264 :            return
     329              :         end if
     330              : 
     331              :         ! in blend region
     332              : 
     333              :         call Get_kap_lowT_Results(rq, &
     334              :              X, Z, XC, XN, XO, XNe, logRho, logT, &
     335          100 :              frac_Type2, kap2, dlnkap2_dlnRho, dlnkap2_dlnT, ierr)
     336          100 :         if (clipped_Rho) dlnkap2_dlnRho = 0d0
     337          100 :         if (ierr /= 0) return
     338              : 
     339              :         call Get_kap_highT_Results(rq, &
     340              :              X, Z, XC, XN, XO, XNe, logRho, logT, &
     341          100 :              frac_Type2, kap1, dlnkap1_dlnRho, dlnkap1_dlnT, ierr)
     342          100 :         if (clipped_Rho) dlnkap1_dlnRho = 0d0
     343          100 :         if (ierr /= 0) return
     344              : 
     345          100 :         alfa0 = (logT - lower_bdy) / (upper_bdy - lower_bdy)
     346          100 :         d_alfa0_dlnT = 1d0/(upper_bdy - lower_bdy)/ln10
     347              : 
     348              :         ! must smooth the transitions near alfa = 0.0 and 1.0
     349              :         ! Rich Townsend's smoothing function for this
     350          100 :         alfa = -alfa0*alfa0*alfa0*(-10d0 + alfa0*(15d0 - 6d0*alfa0))
     351          100 :         d_alfa_dlnT = 30d0*(alfa0 - 1d0)*(alfa0 - 1d0)*alfa0*alfa0*d_alfa0_dlnT
     352              : 
     353          100 :         beta = 1d0 - alfa
     354          100 :         d_beta_dlnT = -d_alfa_dlnT
     355              : 
     356              : 
     357          100 :         logKap1 = log10(kap1); logKap2 = log10(kap2)
     358              : 
     359          100 :         logKap = alfa*logKap1 + beta*logKap2
     360          100 :         dlnkap_dlnRho = alfa*dlnkap1_dlnRho + beta*dlnkap2_dlnRho
     361              :         dlnkap_dlnT = &
     362              :              alfa*dlnkap1_dlnT + beta*dlnkap2_dlnT + &
     363          100 :              d_alfa_dlnT*logKap1*ln10 + d_beta_dlnT*logKap2*ln10
     364          100 :         kap = exp10(logKap)
     365              : 
     366          100 :         frac_lowT = beta
     367          100 :         frac_highT = alfa
     368              : 
     369              :         if (dbg) then
     370              :            write(*,1) 'alfa', alfa
     371              :            write(*,1) 'kap1 (lowT)', kap1
     372              :            write(*,1) 'beta', beta
     373              :            write(*,1) 'kap2 (highT)', kap2
     374              :            write(*,1) 'kap', kap
     375              :            write(*,'(A)')
     376              :         end if
     377              : 
     378              :         if (dbg) write(*,1) 'Get_kap_blend_logT kap', kap
     379              : 
     380              :       end subroutine get_kap_Results_blend_T
     381              : 
     382              : 
     383         5952 :       subroutine get_kap_lowT_Results( &
     384              :            rq, &
     385              :            X, Z, XC, XN, XO, XNe, logRho_in, logT_in, &
     386              :            frac_Type2, kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     387              : 
     388              :         use kap_def
     389              : 
     390              :         use kap_eval_fixed
     391              :         use kap_eval_co
     392              :         use kapcn
     393              :         use kap_aesopus
     394              : 
     395              :         use utils_lib, only: is_bad
     396              : 
     397              :         ! INPUT
     398              :         type (Kap_General_Info), pointer :: rq
     399              :         real(dp), intent(in) :: X, Z, XC, XN, XO, XNe  ! composition
     400              :         real(dp), intent(in) :: logRho_in  ! density
     401              :         real(dp), intent(in) :: logT_in  ! temperature
     402              :         ! free_e := total combined number per nucleon of free electrons and positrons
     403              : 
     404              :         ! OUTPUT
     405              :         real(dp), intent(out) :: frac_Type2
     406              :         real(dp), intent(out) :: kap  ! opacity
     407              :         real(dp), intent(out) :: dlnkap_dlnRho  ! partial derivative at constant T
     408              :         real(dp), intent(out) :: dlnkap_dlnT   ! partial derivative at constant Rho
     409              :         integer, intent(out) :: ierr  ! 0 means AOK.
     410              : 
     411              :         real(dp) :: logRho, Rho, logT, T
     412              :         real(dp) :: frac_Type1, Zbase, dZ, frac_X, frac_dZ, &
     413         5952 :              dXC, dXO, fCO, fC, fN, fO, fNe, fHeavy, ZHeavy, dXsum
     414              : 
     415         5952 :         real(dp) :: logKap
     416              : 
     417              :         logical, parameter :: dbg = .false.
     418              : 
     419         5952 :         ierr = -1  ! should be set by each case, otherwise something is wrong
     420         5952 :         frac_Type2 = 0d0
     421              : 
     422         5952 :         logRho = logRho_in; Rho = exp10(logRho)
     423         5952 :         logT = logT_in; T = exp10(logT)
     424              : 
     425         5952 :         Zbase = rq% Zbase
     426              : 
     427         5952 :         select case (rq% kap_lowT_option)
     428              : 
     429              :         case (kap_lowT_kapCN)
     430              :            if (dbg) write(*,*) 'Calling kapCN for lowT'
     431              : 
     432            0 :            if (Zbase < 0d0) then
     433            0 :               write(*,*) 'must supply Zbase for kapCN opacities', Zbase
     434            0 :               call mesa_error(__FILE__,__LINE__)
     435            0 :               ierr = -1
     436            0 :               return
     437              :            end if
     438              : 
     439            0 :            fC = XC / (kapCN_ZC * Zbase)
     440            0 :            fN = XN / (kapCN_ZN * Zbase)
     441              :            call kapCN_get(Zbase, X, fC, fN, logRho, logT, &
     442            2 :                 kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     443              : 
     444              :         case (kap_lowT_AESOPUS)
     445              :            if (dbg) write(*,*) 'Calling AESOPUS for lowT'
     446              : 
     447            2 :            if (Zbase < 0d0) then
     448            0 :               write(*,*) 'must supply Zbase for AESOPUS opacities', Zbase
     449            0 :               ierr = -1
     450            0 :               return
     451              :            end if
     452              : 
     453              :            call AESOPUS_get(Zbase, X, XC, XN, XO, logRho, logT, &
     454            2 :                 kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     455              : 
     456              : 
     457              :         case default
     458              :            if (rq% kap_lowT_option == kap_lowT_test) then
     459              :               if (dbg) write(*,*) 'Calling test for lowT'
     460              :            else if (rq% kap_lowT_option == kap_lowT_Freedman11) then
     461              :               if (dbg) write(*,*) 'Calling Freedman for lowT'
     462              :            else
     463              :               if (dbg) write(*,*) 'Calling Ferg for lowT'
     464              :            end if
     465              : 
     466              :            call Get1_kap_fixed_metal_Results( &
     467              :                 kap_lowT_z_tables(rq% kap_lowT_option)% ar, num_kap_lowT_Zs(rq% kap_lowT_option), rq, Z, X, Rho, logRho, T, logT, &
     468         5950 :                 logKap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     469         5954 :            kap = exp10(logKap)
     470              :         end select
     471              : 
     472              :         return
     473              : 
     474         5952 :       end subroutine get_kap_lowT_Results
     475              : 
     476              : 
     477        80364 :       subroutine get_kap_highT_Results(rq, &
     478              :            X, Z, XC_in, XN_in, XO_in, XNe_in, logRho_in, logT_in, &
     479              :            frac_Type2, kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     480              : 
     481         5952 :         use kap_def
     482              : 
     483              :         use kap_eval_fixed
     484              :         use kap_eval_co
     485              : 
     486              :         use utils_lib, only: is_bad
     487              : 
     488              :         ! INPUT
     489              :         type (Kap_General_Info), pointer :: rq
     490              :         real(dp), intent(in) :: X, Z, XC_in, XN_in, XO_in, XNe_in  ! composition
     491              :         real(dp), intent(in) :: logRho_in  ! density
     492              :         real(dp), intent(in) :: logT_in  ! temperature
     493              : 
     494              :         ! OUTPUT
     495              :         real(dp), intent(out) :: frac_Type2
     496              :         real(dp), intent(out) :: kap  ! opacity
     497              :         real(dp), intent(out) :: dlnkap_dlnRho  ! partial derivative at constant T
     498              :         real(dp), intent(out) :: dlnkap_dlnT   ! partial derivative at constant Rho
     499              :         integer, intent(out) :: ierr  ! 0 means AOK.
     500              : 
     501              :         real(dp) :: logRho, Rho, logT, T
     502        80364 :         real(dp) :: XC, XN, XO, XNe
     503        80364 :         real(dp) :: frac_Type1, Zbase, dZ, frac_X, frac_dZ, &
     504        80364 :              dXC, dXO, fC, fN, fO, fNe, fHeavy, ZHeavy, dXsum
     505              : 
     506        80364 :         real(dp) :: max_frac_Type2
     507              : 
     508        80364 :         real(dp) :: beta, kap_beta, logkap_beta, dlnkap_beta_dlnRho, dlnkap_beta_dlnT, &
     509        80364 :              alfa, kap_alfa, logkap_alfa, dlnkap_alfa_dlnRho, dlnkap_alfa_dlnT
     510              : 
     511              :         logical, parameter :: dbg = .false.
     512              : 
     513              :         include 'formats'
     514              : 
     515        80364 :         logRho = logRho_in; Rho = exp10(logRho)
     516        80364 :         logT = logT_in; T = exp10(logT)
     517              : 
     518        80364 :         Zbase = rq% Zbase
     519              : 
     520        80364 :         if (rq% use_Type2_opacities) then
     521        80362 :            if (Zbase < 0d0) then
     522            0 :               write(*,1) 'must supply Zbase for Type2 opacities', Zbase
     523            0 :               call mesa_error(__FILE__,__LINE__)
     524            0 :               ierr = -1
     525            0 :               return
     526              :            end if
     527              :         end if
     528              : 
     529        80364 :         if (rq% use_Type2_opacities) then
     530        80362 :            max_frac_Type2 = 1d0
     531        80362 :            XC = XC_in
     532        80362 :            XN = XN_in
     533        80362 :            XO = XO_in
     534        80362 :            XNe = XNe_in
     535              :         else
     536            2 :            max_frac_Type2 = 0d0
     537            2 :            XC = 0d0
     538            2 :            XN = 0d0
     539            2 :            XO = 0d0
     540            2 :            XNe = 0d0
     541              :         end if
     542              : 
     543              : 
     544        80364 :         dXC = 0d0
     545        80364 :         dxO = 0d0
     546        80364 :         frac_Type2 = max_frac_Type2
     547              : 
     548              : 
     549              :         ! Type2 opacities use a base metallicity and enhancements to C and O
     550              :         ! from the 3 definitions
     551              :         ! Z = Zbase + dXC + dXO ! total metals
     552              :         ! XC = dXC + base_fC*Zbase ! total mass fraction of carbon
     553              :         ! XO = dXO + base_fO*Zbase ! total mass fraction of oxygen
     554              :         ! we get expressions for the 3 parameters, Zbase, dXC, and dXO
     555              :         ! using the base values for fractions of C and O
     556              : 
     557        80364 :         if (frac_Type2 > 0d0 .and. &
     558              :             associated(kap_co_z_tables(rq% kap_CO_option)% ar)) then
     559              : 
     560        80362 :            fC = kap_co_z_tables(rq% kap_CO_option)% ar(1)% Zfrac_C
     561        80362 :            fN = kap_co_z_tables(rq% kap_CO_option)% ar(1)% Zfrac_N
     562        80362 :            fO = kap_co_z_tables(rq% kap_CO_option)% ar(1)% Zfrac_O
     563        80362 :            fNe = kap_co_z_tables(rq% kap_CO_option)% ar(1)% Zfrac_Ne
     564              : 
     565        80362 :            dXC = max(0d0, xC - fC*Zbase)
     566        80362 :            dXO = max(0d0, xO - fO*Zbase)
     567              : 
     568        80362 :            if (X >= rq% kap_Type2_full_off_X) then
     569        80360 :               frac_X = 0d0
     570            2 :            else if (X <= rq% kap_Type2_full_on_X) then
     571            2 :               frac_X = 1d0
     572              :            else  ! blend
     573              :               frac_X = (rq% kap_Type2_full_off_X - X) / &
     574            0 :                    (rq% kap_Type2_full_off_X - rq% kap_Type2_full_on_X)
     575              :            end if
     576              : 
     577        80362 :            dZ = Z - Zbase
     578        80362 :            if (dZ <= rq% kap_Type2_full_off_dZ) then
     579        80360 :               frac_dZ = 0d0
     580            2 :            else if (dZ >= rq% kap_Type2_full_on_dZ) then
     581            2 :               frac_dZ = 1d0
     582              :            else  ! blend
     583              :               frac_dZ = (rq% kap_Type2_full_off_dZ - dZ) / &
     584            0 :                    (rq% kap_Type2_full_off_dZ - rq% kap_Type2_full_on_dZ)
     585              :            end if
     586              : 
     587        80362 :            frac_Type2 = frac_Type2*frac_X*frac_dZ
     588        80362 :            if (frac_Type2 == 0d0) then
     589        80360 :               dXC = 0d0
     590        80360 :               dXO = 0d0
     591              :            end if
     592              : 
     593        80362 :            if (is_bad(dXC) .or. is_bad(dXO)) then
     594            0 :               write(*,1) 'X', X
     595            0 :               write(*,1) 'Z', Z
     596            0 :               write(*,1) 'Zbase', Zbase
     597            0 :               write(*,1) 'XC', XC
     598            0 :               write(*,1) 'XN', XN
     599            0 :               write(*,1) 'XO', XO
     600            0 :               write(*,1) 'XNe', XNe
     601            0 :               write(*,1) 'logRho', logRho
     602            0 :               write(*,1) 'logT', logT
     603            0 :               write(*,1) 'dXC', dXC
     604            0 :               write(*,1) 'dXO', dXO
     605            0 :               write(*,1) 'frac_X', frac_X
     606            0 :               write(*,1) 'frac_dZ', frac_dZ
     607            0 :               write(*,1) 'frac_Type2', frac_Type2
     608            0 :               ierr = -1
     609            0 :               return
     610              :            end if
     611              : 
     612              :         end if
     613              : 
     614        80364 :         frac_Type1 = 1d0 - frac_Type2
     615              :         if (dbg) then
     616              :            write(*,1) 'max_frac_Type2', max_frac_Type2
     617              :            write(*,1) 'frac_Type2', frac_Type2
     618              :            write(*,1) 'frac_Type1', frac_Type1
     619              :            write(*,'(A)')
     620              :            write(*,1) 'X', X
     621              :            write(*,1) 'dXC', dXC
     622              :            write(*,1) 'dXO', dXO
     623              :            write(*,1) 'Zbase', Zbase
     624              :         end if
     625              : 
     626              :         ! do blend
     627        80364 :         beta = frac_Type1
     628        80364 :         alfa = frac_Type2
     629              : 
     630        80364 :         if (beta > 0) then  ! get value from fixed metal tables
     631        80362 :            if (rq% use_Type2_opacities .and. rq% use_Zbase_for_Type1) then
     632              :               ! when Z > Zbase, use Zbase instead of Z.
     633              :               call Get1_kap_fixed_metal_Results( &
     634              :                    kap_z_tables(rq% kap_option)% ar, num_kap_Zs(rq% kap_option), rq, min(Z,Zbase), X, Rho, logRho, T, logT, &
     635        80360 :                    logkap_beta, dlnkap_beta_dlnRho, dlnkap_beta_dlnT, ierr)
     636              :            else
     637              :               call Get1_kap_fixed_metal_Results( &
     638              :                    kap_z_tables(rq% kap_option)% ar, num_kap_Zs(rq% kap_option), rq, Z, X, Rho, logRho, T, logT, &
     639            2 :                    logkap_beta, dlnkap_beta_dlnRho, dlnkap_beta_dlnT, ierr)
     640              :            end if
     641        80362 :            kap_beta = exp10(logkap_beta)
     642              :            if (dbg) then
     643              :               write(*,1) 'Get_kap_fixed_metal_Results'
     644              :               write(*,1) 'Z', Z
     645              :               write(*,1) 'X', X
     646              :               write(*,1) 'Rho', Rho
     647              :               write(*,1) 'logRho', logRho
     648              :               write(*,1) 'T', T
     649              :               write(*,1) 'logT', logT
     650              :               write(*,1) 'kap_beta', kap_beta
     651              :               write(*,1) 'beta', beta
     652              :               write(*,'(A)')
     653              :            end if
     654              :         else
     655            2 :            kap_beta = 0d0; dlnkap_beta_dlnRho = 0d0; dlnkap_beta_dlnT = 0d0
     656              :         end if
     657              : 
     658        80364 :         if (alfa > 0d0) then  ! get value from C/O enhanced tables
     659              :            call Get1_kap_CO_Results( &
     660              :                 rq, Zbase, X, dXC, dXO, Rho, logRho, T, logT, &
     661            2 :                 logkap_alfa, dlnkap_alfa_dlnRho, dlnkap_alfa_dlnT, ierr)
     662            2 :            kap_alfa = exp10(logkap_alfa)
     663              :            if (dbg) then
     664              :               write(*,1) 'Get_kap_CO_Results'
     665              :               write(*,1) 'Z', Z
     666              :               write(*,1) 'X', X
     667              :               write(*,1) 'Rho', Rho
     668              :               write(*,1) 'logRho', logRho
     669              :               write(*,1) 'T', T
     670              :               write(*,1) 'logT', logT
     671              :               write(*,1) 'kap_alfa', kap_alfa
     672              :               write(*,1) 'alfa', alfa
     673              :               write(*,'(A)')
     674              :            end if
     675              :         else
     676        80362 :            kap_alfa = 0d0; dlnkap_alfa_dlnRho = 0d0; dlnkap_alfa_dlnT = 0d0
     677              :         end if
     678              : 
     679        80364 :         kap = alfa*kap_alfa + beta*kap_beta
     680              :         if (dbg) then
     681              :            write(*,1) 'alfa', alfa
     682              :            write(*,1) 'kap_alfa (Type2)', kap_alfa
     683              :            write(*,1) 'beta', beta
     684              :            write(*,1) 'kap_beta (Type1)', kap_beta
     685              :            write(*,1) 'kap', kap
     686              :         end if
     687              : 
     688        80364 :         if (kap < 1d-30) then
     689            0 :            kap = 1d-30
     690            0 :            dlnkap_dlnRho = 0d0
     691            0 :            dlnkap_dlnT = 0d0
     692              :         else
     693        80364 :            dlnkap_dlnRho = (alfa*kap_alfa*dlnkap_alfa_dlnRho + beta*kap_beta*dlnkap_beta_dlnRho) / kap
     694        80364 :            dlnkap_dlnT = (alfa*kap_alfa*dlnkap_alfa_dlnT + beta*kap_beta*dlnkap_beta_dlnT) / kap
     695              :         end if
     696              : 
     697        80364 :       end subroutine get_kap_highT_Results
     698              : 
     699              : 
     700        86216 :       subroutine combine_rad_with_conduction( &
     701              :             rq, logRho, logT, zbar, &
     702              :             kap_rad, dlnkap_rad_dlnRho, dlnkap_rad_dlnT, &
     703              :             kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     704              : 
     705        80364 :          use condint, only: do_electron_conduction
     706              :          type (Kap_General_Info), pointer :: rq
     707              :          real(dp), intent(in) :: logRho, logT, zbar
     708              :          real(dp), intent(inout) :: kap_rad, dlnkap_rad_dlnRho, dlnkap_rad_dlnT
     709              :          real(dp), intent(out) :: kap, dlnkap_dlnRho, dlnkap_dlnT
     710              :          integer, intent(out) :: ierr  ! 0 means AOK.
     711              : 
     712        86216 :          real(dp) :: kap_ec, dlnkap_ec_dlnRho, dlnkap_ec_dlnT
     713              :          logical, parameter :: dbg = .false.
     714              : 
     715              :          include 'formats'
     716              : 
     717        86216 :          ierr = 0
     718              : 
     719        86216 :          if (.not. rq% include_electron_conduction) then
     720            0 :             kap = kap_rad
     721            0 :             dlnkap_dlnRho = dlnkap_rad_dlnRho
     722            0 :             dlnkap_dlnT = dlnkap_rad_dlnT
     723            0 :             return
     724              :          end if
     725              : 
     726        86216 :          if (rq% use_other_elect_cond_opacity) then
     727              :             call rq% other_elect_cond_opacity( &
     728              :                rq% handle, zbar, logRho, logT, &
     729            0 :                kap_ec, dlnkap_ec_dlnRho, dlnkap_ec_dlnT, ierr)
     730              :          else
     731              :             call do_electron_conduction( &
     732              :                rq, zbar, logRho, logT, &
     733        86216 :                kap_ec, dlnkap_ec_dlnRho, dlnkap_ec_dlnT, ierr)
     734              :          end if
     735        86216 :          if (ierr /= 0) return
     736              : 
     737        86216 :          if (is_bad(kap_ec)) then
     738            0 :             write(*,*) 'kap_ec', kap_ec
     739            0 :             call mesa_error(__FILE__,__LINE__,'combine_rad_with_conduction')
     740              :          end if
     741              :          if (dbg) write(*,1) 'kap_ec', kap_ec
     742              :          if (dbg) write(*,1) 'dlnkap_ec_dlnRho', dlnkap_ec_dlnRho
     743              :          if (dbg) write(*,1) 'dlnkap_ec_dlnT', dlnkap_ec_dlnT
     744              :          if (dbg) write(*,*)
     745              : 
     746        86216 :          kap = 1d0 / (1d0/kap_rad + 1d0/kap_ec)
     747              :          if (dbg) write(*,1) 'kap_rad', kap_rad
     748              :          if (dbg) write(*,1) 'kap', kap
     749              :          if (dbg) write(*,1) 'log10(kap)', log10(kap)
     750              : 
     751        86216 :          if (is_bad(kap)) then
     752            0 :             ierr = -1; return
     753              :             write(*,1) 'kap', kap
     754              :             call mesa_error(__FILE__,__LINE__,'Get_kap_Results')
     755              :          end if
     756              : 
     757        86216 :          dlnkap_dlnRho = (kap/kap_rad) * dlnkap_rad_dlnRho + (kap/kap_ec) * dlnkap_ec_dlnRho
     758              : 
     759        86216 :          if (is_bad(dlnkap_dlnRho)) then
     760            0 :             ierr = -1; return
     761              :             write(*,1) 'dlnkap_dlnRho', dlnkap_dlnRho
     762              :             write(*,1) 'kap', kap
     763              :             write(*,1) 'dkap_dlnRho', kap * dlnkap_dlnRho
     764              :             write(*,1) 'dkap_ec_dlnRho', kap_ec * dlnkap_ec_dlnRho
     765              :             write(*,1) 'dkap_rad_dlnRho', kap_rad * dlnkap_rad_dlnRho
     766              :             write(*,1) 'kap_rad', kap_rad
     767              :             write(*,1) 'kap_ec', kap_ec
     768              :             call mesa_error(__FILE__,__LINE__,'combine_rad_with_conduction')
     769              :          end if
     770              : 
     771        86216 :          dlnkap_dlnT = (kap/kap_rad) * dlnkap_rad_dlnT + (kap/kap_ec) * dlnkap_ec_dlnT
     772              : 
     773        86216 :          if (is_bad(dlnkap_dlnT)) then
     774            0 :             ierr = -1; return
     775              :             write(*,1) 'dlnkap_dlnT', dlnkap_dlnT
     776              :             write(*,1) 'kap', kap
     777              :             write(*,1) 'dkap_dlnT', kap * dlnkap_dlnT
     778              :             write(*,1) 'dkap_ec_dlnT', kap_ec * dlnkap_ec_dlnT
     779              :             write(*,1) 'dkap_rad_dlnT', kap_rad * dlnkap_rad_dlnT
     780              :             write(*,1) 'kap_rad', kap_rad
     781              :             write(*,1) 'kap_ec', kap_ec
     782              :             call mesa_error(__FILE__,__LINE__,'combine_rad_with_conduction')
     783              :          end if
     784              : 
     785              :          if (dbg) write(*,1) 'dlnkap_dlnRho', dlnkap_dlnRho
     786              :          if (dbg) write(*,1) 'dlnkap_dlnT', dlnkap_dlnT
     787              :          if (dbg) call mesa_error(__FILE__,__LINE__,'combine_rad_with_conduction')
     788              : 
     789              : 
     790        86216 :       end subroutine combine_rad_with_conduction
     791              : 
     792              : 
     793            0 :       subroutine Compton_Opacity(rq, &
     794              :             Rho_in, T_in, lnfree_e, d_lnfree_e_dlnRho, d_lnfree_e_dlnT, &
     795              :             eta_in, d_eta_dlnRho, d_eta_dlnT, &
     796              :             kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
     797        86216 :          use eos_lib
     798              :          use eos_def
     799              :          use auto_diff
     800              : 
     801              :          type (Kap_General_Info), pointer :: rq
     802              : 
     803              :          ! evaluates the poutanen 2017, apj 835, 119 fitting formula for the compton opacity.
     804              :          ! coefficients from table 1 between 2 and 300 kev
     805              : 
     806              :          real(dp), intent(in) :: Rho_in, T_in, lnfree_e, d_lnfree_e_dlnRho, d_lnfree_e_dlnT
     807              :          real(dp), intent(in) :: eta_in, d_eta_dlnRho, d_eta_dlnT
     808              :          real(dp), intent(out) :: kap, dlnkap_dlnRho, dlnkap_dlnT
     809              :          integer, intent(out) :: ierr
     810              : 
     811              :          type(auto_diff_real_2var_order1) :: T, rho, free_e, eta, kap_auto
     812              :          type(auto_diff_real_2var_order1) :: zeta, f1, f2, f3, alpha, tbr, theta, tkev, mfp
     813              : 
     814              :          real(dp) :: free_e_val
     815              : 
     816              :          ! poutanen table 1
     817              :          real(dp), parameter :: &
     818              :             t0     =  43.3d0, &
     819              :             alpha0 =  0.885d0, &
     820              :             c01    =  0.682d0, &
     821              :             c02    = -0.0454d0, &
     822              :             c11    =  0.240d0, &
     823              :             c12    =  0.0043d0, &
     824              :             c21    =  0.050d0, &
     825              :             c22    = -0.0067d0, &
     826              :             c31    = -0.037d0, &
     827              :             c32    =  0.0031d0
     828              : 
     829              :          include 'formats'
     830              : 
     831            0 :          ierr = 0
     832              : 
     833              :          ! set up auto diff
     834              :          ! var1: Rho
     835              :          ! var2: T
     836              : 
     837            0 :          Rho = Rho_in
     838              :          Rho% d1val1 = 1d0
     839              :          Rho% d1val2 = 0d0
     840              : 
     841            0 :          T = T_in
     842            0 :          T% d1val1 = 0d0
     843            0 :          T% d1val2 = 1d0
     844              : 
     845            0 :          free_e_val = exp(lnfree_e)
     846            0 :          free_e = free_e_val
     847            0 :          free_e % d1val1 = free_e_val*d_lnfree_e_dlnRho/Rho_in
     848            0 :          free_e % d1val2 = free_e_val*d_lnfree_e_dlnT/T_in
     849              : 
     850            0 :          eta = eta_in
     851            0 :          eta % d1val1 = d_eta_dlnRho/Rho_in
     852            0 :          eta % d1val2 = d_eta_dlnT/T_in
     853              : 
     854            0 :          theta = T * kerg / (me * clight * clight)
     855            0 :          tkev  = T * kev * 1.0d-3
     856            0 :          zeta  = exp(c01 * eta + c02 * eta*eta)
     857            0 :          f1    = 1.0d0 + c11 * zeta + c12 * zeta * zeta
     858            0 :          f2    = 1.0d0 + c21 * zeta + c22 * zeta * zeta
     859            0 :          f3    = 1.0d0 + c31 * zeta + c32 * zeta * zeta
     860            0 :          alpha = alpha0 * f3
     861            0 :          tbr   = t0 * f2
     862            0 :          mfp   = f1 * (1.0d0 + pow(tkev/tbr,alpha))
     863              : 
     864              :          ! equation 31
     865            0 :          kap_auto = sige*(free_e/amu)/mfp
     866              : 
     867              :          ! unpack auto_diff
     868            0 :          kap = kap_auto% val
     869            0 :          dlnkap_dlnRho = Rho% val * kap_auto% d1val1 / kap
     870            0 :          dlnkap_dlnT = T% val * kap_auto% d1val2 / kap
     871              : 
     872            0 :       end subroutine Compton_Opacity
     873              : 
     874              :       end module kap_eval
        

Generated by: LCOV version 2.0-1