LCOV - code coverage report
Current view: top level - star/private - tdc_hydro.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 237 0
Test Date: 2025-10-25 19:18:45 Functions: 0.0 % 17 0

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2025  Ebraheem Farag & 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 tdc_hydro
      21              : 
      22              :    use star_private_def
      23              :    use const_def, only: dp, boltz_sigma, pi, clight, crad, ln10
      24              :    use utils_lib, only: is_bad
      25              :    use auto_diff
      26              :    use auto_diff_support
      27              :    use accurate_sum_auto_diff_star_order1
      28              :    use star_utils
      29              : 
      30              :    implicit none
      31              : 
      32              :    private
      33              :    public :: &
      34              :       compute_tdc_Eq_cell, compute_tdc_Uq_face, compute_tdc_Eq_div_w_face, &
      35              :       get_RSP2_alfa_beta_face_weights, set_viscosity_vars_TDC
      36              : 
      37              : contains
      38              : 
      39              :    ! This routine is called to initialize eq and uq for TDC.
      40            0 :    subroutine set_viscosity_vars_TDC(s, ierr)
      41              :       type(star_info), pointer :: s
      42              :       integer, intent(out) :: ierr
      43              :       type(auto_diff_real_star_order1) :: x
      44              :       integer :: k, op_err
      45              :       include 'formats'
      46            0 :       ierr = 0
      47            0 :       op_err = 0
      48              : 
      49            0 :       !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
      50              :       do k = 1, s%nz
      51              :          ! Hp_face(k) <= 0 means it needs to be set.  e.g., after read file
      52              :          if (s%Hp_face(k) <= 0) then
      53              :             ! this scale height for face is already calculated in TDC
      54              :             s%Hp_face(k) = get_scale_height_face_val(s, k) ! because this is called before s% scale_height(k) is updated in mlt_vars.
      55              :          end if
      56              :       end do
      57              :       !$OMP END PARALLEL DO
      58            0 :       if (ierr /= 0) then
      59            0 :          if (s%report_ierr) write (*, 2) 'failed in set_viscosity_vars_TDC loop 1', s%model_number
      60            0 :          return
      61              :       end if
      62            0 :       !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
      63              :       do k = 1, s%nz
      64              :          x = compute_Chi_cell(s, k, op_err)
      65              :          if (op_err /= 0) ierr = op_err
      66              :          x = compute_tdc_Eq_cell(s, k, op_err)
      67              :          if (op_err /= 0) ierr = op_err
      68              :          x = compute_tdc_Uq_face(s, k, op_err)
      69              :          if (op_err /= 0) ierr = op_err
      70              :       end do
      71              :       !$OMP END PARALLEL DO
      72            0 :       if (ierr /= 0) then
      73            0 :          if (s%report_ierr) write (*, 2) 'failed in set_viscosity_vars_TDC loop 2', s%model_number
      74            0 :          return
      75              :       end if
      76            0 :       if (.not. (s%v_flag .or. s%u_flag)) then ! set values 0 if not using v_flag or u_flag.
      77            0 :          do k = 1, s%nz
      78            0 :             s%Eq(k) = 0d0; s%Eq_ad(k) = 0d0
      79            0 :             s%Chi(k) = 0d0; s%Chi_ad(k) = 0d0
      80            0 :             s%Uq(k) = 0d0
      81              :          end do
      82              :       end if
      83              :    end subroutine set_viscosity_vars_TDC
      84              : 
      85            0 :    subroutine get_RSP2_alfa_beta_face_weights(s, k, alfa, beta)
      86              :       type(star_info), pointer :: s
      87              :       integer, intent(in) :: k
      88              :       real(dp), intent(out) :: alfa, beta
      89              :       ! face_value = alfa*cell_value(k) + beta*cell_value(k-1)
      90            0 :       if (k == 1) call mesa_error(__FILE__, __LINE__, 'bad k==1 for get_RSP2_alfa_beta_face_weights')
      91            0 :       if (s%TDC_hydro_use_mass_interp_face_values) then
      92            0 :          alfa = s%dq(k - 1)/(s%dq(k - 1) + s%dq(k))
      93            0 :          beta = 1d0 - alfa
      94              :       else
      95            0 :          alfa = 0.5d0
      96            0 :          beta = 0.5d0
      97              :       end if
      98            0 :    end subroutine get_RSP2_alfa_beta_face_weights
      99              : 
     100            0 :    function compute_d_v_div_r(s, k, ierr) result(d_v_div_r)  ! s^-1
     101              :       type(star_info), pointer :: s
     102              :       integer, intent(in) :: k
     103              :       type(auto_diff_real_star_order1) :: d_v_div_r
     104              :       integer, intent(out) :: ierr
     105              :       type(auto_diff_real_star_order1) :: v_00, v_p1, r_00, r_p1, term1, term2
     106              :       logical :: dbg
     107              :       include 'formats'
     108            0 :       ierr = 0
     109            0 :       dbg = .false.
     110            0 :       v_00 = wrap_v_00(s, k)
     111            0 :       v_p1 = wrap_v_p1(s, k)
     112            0 :       r_00 = wrap_r_00(s, k)
     113            0 :       r_p1 = wrap_r_p1(s, k)
     114            0 :       if (r_p1%val == 0d0) r_p1 = 1d0
     115            0 :       d_v_div_r = v_00/r_00 - v_p1/r_p1 ! units s^-1
     116              : 
     117              :       ! Debugging output to trace values
     118              :       if (dbg .and. k == -63) then
     119              :          write (*, *) 'test d_v_div_r, k:', k
     120              :          write (*, *) 'v_00:', v_00%val, 'v_p1:', v_p1%val
     121              :          write (*, *) 'r_00:', r_00%val, 'r_p1:', r_p1%val
     122              :          write (*, *) 'd_v_div_r:', d_v_div_r%val
     123              :       end if
     124            0 :    end function compute_d_v_div_r
     125              : 
     126            0 :    function compute_rho_form_of_d_v_div_r(s, k, ierr) result(d_v_div_r)
     127              :       type(star_info), pointer :: s
     128              :       integer, intent(in)  :: k
     129              :       integer, intent(out) :: ierr
     130              :       type(auto_diff_real_star_order1) :: d_v_div_r
     131              :       type(auto_diff_real_star_order1) :: r_cell, rho_cell, v_cell, dlnrho_dt
     132              :       real(dp) :: dm_cell
     133            0 :       ierr = 0
     134              : 
     135            0 :       r_cell = 0.5d0*(wrap_r_00(s, k) + wrap_r_p1(s, k))
     136            0 :       rho_cell = wrap_d_00(s, k)
     137            0 :       v_cell = wrap_v_00(s, k)              ! cell-centred velocity (u_flag)
     138            0 :       dlnrho_dt = wrap_dxh_lnd(s, k)/s%dt    ! (∂/∂t)lnρ
     139            0 :       dm_cell = s%dm(k)                     ! cell mass
     140              : 
     141            0 :       d_v_div_r = -dm_cell/(4d0*pi*rho_cell)*(dlnrho_dt/pow3(r_cell) + 3d0*v_cell/pow4(r_cell))
     142            0 :    end function compute_rho_form_of_d_v_div_r
     143              : 
     144            0 :    function compute_rho_form_of_d_v_div_r_opt_time_center(s, k, ierr) result(d_v_div_r) ! s^-1
     145              :       type(star_info), pointer :: s
     146              :       integer, intent(in)  :: k
     147              :       integer, intent(out) :: ierr
     148              :       type(auto_diff_real_star_order1) :: d_v_div_r
     149              :       type(auto_diff_real_star_order1) :: r_cell, rho_cell, v_cell, dlnrho_dt
     150              :       real(dp) :: dm_cell
     151            0 :       ierr = 0
     152              : 
     153            0 :       r_cell = 0.5d0*(wrap_opt_time_center_r_00(s, k) + wrap_opt_time_center_r_p1(s, k))
     154            0 :       rho_cell = wrap_d_00(s, k)
     155            0 :       v_cell = wrap_opt_time_center_v_00(s, k)              ! cell-centred velocity (u_flag)
     156            0 :       dlnrho_dt = wrap_dxh_lnd(s, k)/s%dt    ! (∂/∂t)lnρ
     157            0 :       dm_cell = s%dm(k)                     ! cell mass
     158              : 
     159              :       d_v_div_r = -dm_cell/(4d0*pi*rho_cell)* &
     160              :                   (dlnrho_dt/pow3(r_cell) &
     161            0 :                    + 3d0*v_cell/pow4(r_cell))
     162            0 :    end function compute_rho_form_of_d_v_div_r_opt_time_center
     163              : 
     164              : 
     165            0 :    function compute_rho_form_of_d_v_div_r_face(s, k, ierr) result(d_v_div_r)
     166              :       type(star_info), pointer :: s
     167              :       integer, intent(in)  :: k
     168              :       integer, intent(out) :: ierr
     169              :       type(auto_diff_real_star_order1) :: d_v_div_r
     170              :       type(auto_diff_real_star_order1) :: r_face, rho_face, v_face, dlnrho_dt
     171            0 :       real(dp) :: dm_bar
     172            0 :       ierr = 0
     173              : 
     174            0 :       r_face = wrap_r_00(s, k)
     175            0 :       rho_face = get_rho_face(s, k)
     176            0 :       if (s% v_flag .and. .not. s% u_flag) then
     177            0 :          v_face =  wrap_v_00(s, k)   ! face-centred velocity (v_flag)
     178            0 :       else if (s% u_flag .and. .not. s% v_flag) then
     179            0 :          v_face = s% u_face_ad(k) ! reconstructed face velocity (u_flag)
     180              :       end if
     181            0 :       dlnrho_dt = 0.5d0*(wrap_dxh_lnd(s, k) + wrap_dxh_lnd(s, k+1))/s%dt    ! (∂/∂t)lnρ
     182              : 
     183            0 :       if (k >= 2) then
     184            0 :          dm_bar = 0.5d0*(s% dm(k) + s% dm(k-1))
     185              :       else
     186            0 :          dm_bar = 0.5d0*s% dm(k)
     187              :       end if
     188              : 
     189            0 :       d_v_div_r = -dm_bar/(4d0*pi*rho_face)*(dlnrho_dt/pow3(r_face) + 3d0*v_face/pow4(r_face))
     190            0 :    end function compute_rho_form_of_d_v_div_r_face
     191              : 
     192            0 :    function compute_rho_form_of_d_v_div_r_face_opt_time_center(s, k, ierr) result(d_v_div_r) ! s^-1
     193              :       type(star_info), pointer :: s
     194              :       integer, intent(in)  :: k
     195              :       integer, intent(out) :: ierr
     196              :       type(auto_diff_real_star_order1) :: d_v_div_r
     197              :       type(auto_diff_real_star_order1) :: r_face, rho_face, v_face, dlnrho_dt
     198            0 :       real(dp) :: dm_bar
     199            0 :       ierr = 0
     200              : 
     201            0 :       r_face = wrap_opt_time_center_r_00(s, k)
     202            0 :       rho_face = get_rho_face(s, k)
     203              : 
     204            0 :       if (s% v_flag .and. .not. s% u_flag) then
     205            0 :          v_face =  wrap_opt_time_center_v_00(s, k)   ! face-centred velocity (v_flag)
     206            0 :       else if (s% u_flag .and. .not. s% v_flag) then
     207            0 :          v_face = s% u_face_ad(k) ! reconstructed face velocity (u_flag)
     208              :       end if
     209            0 :       dlnrho_dt = 0.5d0*(wrap_dxh_lnd(s, k) + wrap_dxh_lnd(s, k+1))/s%dt    ! (∂/∂t)lnρ
     210              : 
     211            0 :       if (k >= 2) then
     212            0 :          dm_bar = 0.5d0*(s% dm(k) + s% dm(k-1))
     213              :       else
     214            0 :          dm_bar = 0.5d0*s% dm(k)
     215              :       end if
     216              : 
     217            0 :       d_v_div_r = -dm_bar/(4d0*pi*rho_face)*(dlnrho_dt/pow3(r_face) + 3d0*v_face/pow4(r_face))
     218            0 :    end function compute_rho_form_of_d_v_div_r_face_opt_time_center
     219              : 
     220              : 
     221            0 :    function compute_d_v_div_r_opt_time_center(s, k, ierr) result(d_v_div_r)  ! s^-1
     222              :       type(star_info), pointer :: s
     223              :       integer, intent(in) :: k
     224              :       type(auto_diff_real_star_order1) :: d_v_div_r
     225              :       integer, intent(out) :: ierr
     226              :       type(auto_diff_real_star_order1) :: v_00, v_p1, r_00, r_p1
     227              :       include 'formats'
     228            0 :       ierr = 0
     229            0 :       v_00 = wrap_opt_time_center_v_00(s, k)
     230            0 :       v_p1 = wrap_opt_time_center_v_p1(s, k)
     231            0 :       r_00 = wrap_opt_time_center_r_00(s, k)
     232            0 :       r_p1 = wrap_opt_time_center_r_p1(s, k)
     233            0 :       if (r_p1%val == 0d0) r_p1 = 1d0
     234            0 :       d_v_div_r = v_00/r_00 - v_p1/r_p1  ! units s^-1
     235            0 :    end function compute_d_v_div_r_opt_time_center
     236              : 
     237            0 :    function wrap_Hp_cell(s, k) result(Hp_cell)  ! cm , different than rsp2
     238              :       type(star_info), pointer :: s
     239              :       integer, intent(in) :: k
     240              :       type(auto_diff_real_star_order1) :: Hp1, Hp0, Hp_cell
     241            0 :       Hp0 = get_scale_height_face(s,k)
     242            0 :       Hp1 = 0d0
     243            0 :       if (k+1 < s%nz) then
     244            0 :          Hp1 = get_scale_height_face(s,k+1)
     245              :       end if
     246            0 :       Hp_cell = 0.5d0*(Hp0 + Hp1)
     247              :       !0.5d0*(wrap_Hp_00(s, k) + wrap_Hp_p1(s, k))
     248            0 :    end function wrap_Hp_cell
     249              : 
     250            0 :    function Hp_cell_for_Chi(s, k, ierr) result(Hp_cell)  ! cm
     251              :       type(star_info), pointer :: s
     252              :       integer, intent(in) :: k
     253              :       integer, intent(out) :: ierr
     254              :       type(auto_diff_real_star_order1) :: Hp_cell
     255              :       type(auto_diff_real_star_order1) :: d_00, Peos_00, rmid
     256            0 :       real(dp) :: mmid, cgrav_mid
     257              :       include 'formats'
     258            0 :       ierr = 0
     259              : 
     260            0 :       Hp_cell = wrap_Hp_cell(s, k)
     261            0 :       return ! below is skipped, for now.
     262              : 
     263              :       d_00 = wrap_d_00(s, k)
     264              :       Peos_00 = wrap_Peos_00(s, k)
     265              :       if (k < s%nz) then
     266              :          rmid = 0.5d0*(wrap_r_00(s, k) + wrap_r_p1(s, k))
     267              :          mmid = 0.5d0*(s%m(k) + s%m(k + 1))
     268              :          cgrav_mid = 0.5d0*(s%cgrav(k) + s%cgrav(k + 1))
     269              :       else
     270              :          rmid = 0.5d0*(wrap_r_00(s, k) + s%r_center)
     271              :          mmid = 0.5d0*(s%m(k) + s%m_center)
     272              :          cgrav_mid = s%cgrav(k)
     273              :       end if
     274              :       Hp_cell = pow2(rmid)*Peos_00/(d_00*cgrav_mid*mmid)
     275              :       if (s%alt_scale_height_flag) then
     276              :          call mesa_error(__FILE__, __LINE__, 'Hp_cell_for_Chi: cannot use alt_scale_height_flag')
     277              :       end if
     278              :    end function Hp_cell_for_Chi
     279              : 
     280            0 :    function compute_Chi_cell(s, k, ierr) result(Chi_cell)
     281              :       ! eddy viscosity energy (Kuhfuss 1986) [erg]
     282              :       type(star_info), pointer :: s
     283              :       integer, intent(in) :: k
     284              :       type(auto_diff_real_star_order1) :: Chi_cell
     285              :       integer, intent(out) :: ierr
     286              :       type(auto_diff_real_star_order1) :: &
     287              :          rho2, r6_cell, d_v_div_r, Hp_cell, w_00, d_00, r_00, r_p1
     288            0 :       real(dp) :: f, ALFAM_ALFA
     289              :       logical :: dbg
     290              :       include 'formats'
     291            0 :       ierr = 0
     292            0 :       dbg = .false.
     293              : 
     294              :       ! check where we are getting alfam from.
     295            0 :       if (s%MLT_option == 'TDC' .and. .not. s%RSP2_flag) then
     296            0 :          ALFAM_ALFA = s%alpha_TDC_DampM*s%mixing_length_alpha
     297              :       else ! this is for safety, but probably is never called.
     298              :          ALFAM_ALFA = 0d0
     299              :       end if
     300              : 
     301            0 :       if (ALFAM_ALFA == 0d0 .or. &
     302              :           k > s% nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     303            0 :          Chi_cell = 0d0
     304            0 :          if (k >= 1 .and. k <= s%nz) then
     305            0 :             s%Chi(k) = 0d0
     306            0 :             s%Chi_ad(k) = 0d0
     307              :          end if
     308              :       else
     309            0 :          Hp_cell = Hp_cell_for_Chi(s, k, ierr)
     310            0 :          if (ierr /= 0) return
     311            0 :          if (s%u_flag .or. s%TDC_use_density_form_for_eddy_viscosity) then
     312              :             ! new density derivative term
     313            0 :             d_v_div_r = compute_rho_form_of_d_v_div_r(s, k, ierr)
     314              :          else
     315            0 :             d_v_div_r = compute_d_v_div_r(s, k, ierr)
     316              :          end if
     317            0 :          if (ierr /= 0) return
     318              : 
     319              :          ! don't need to check if mlt_vc > 0 here.
     320            0 :          if (s%MLT_option == 'TDC' .and. .not. s%RSP2_flag) then
     321            0 :                w_00 = s% mlt_vc_ad(k)/sqrt_2_div_3! same as info%A0 from TDC
     322              :          else ! normal RSP2
     323            0 :             w_00 = wrap_w_00(s, k)
     324              :          end if
     325            0 :          d_00 = wrap_d_00(s, k)
     326            0 :          f = (16d0/3d0)*pi*ALFAM_ALFA/s%dm(k)
     327            0 :          rho2 = pow2(d_00)
     328            0 :          r_00 = wrap_r_00(s, k)
     329            0 :          r_p1 = wrap_r_p1(s, k)
     330            0 :          r6_cell = 0.5d0*(pow6(r_00) + pow6(r_p1))
     331            0 :          Chi_cell = f*rho2*r6_cell*d_v_div_r*Hp_cell*w_00
     332              :          ! units = g^-1 cm s^-1 g^2 cm^-6 cm^6 s^-1 cm
     333              :          !       = g cm^2 s^-2
     334              :          !       = erg
     335              : 
     336              :       end if
     337            0 :       s%Chi(k) = Chi_cell%val
     338            0 :       s%Chi_ad(k) = Chi_cell
     339              : 
     340              :       if (dbg .and. k == -100) then
     341              :          write (*, *) ' s% ALFAM_ALFA', ALFAM_ALFA
     342              :          write (*, *) 'Hp_cell', Hp_cell%val
     343              :          write (*, *) 'd_v_div_r', d_v_div_r%val
     344              :          write (*, *) ' f', f
     345              :          write (*, *) 'w_00', w_00%val
     346              :          write (*, *) 'd_00 ', d_00%val
     347              :          write (*, *) 'rho2 ', rho2%val
     348              :          write (*, *) 'r_00', r_00%val
     349              :          write (*, *) 'r_p1 ', r_p1%val
     350              :          write (*, *) 'r6_cell', r6_cell%val
     351              :       end if
     352            0 :    end function compute_Chi_cell
     353              : 
     354            0 :    function compute_tdc_Eq_cell(s, k, ierr) result(Eq_cell)  ! erg g^-1 s^-1
     355              :       type(star_info), pointer :: s
     356              :       integer, intent(in) :: k
     357              :       type(auto_diff_real_star_order1) :: Eq_cell
     358              :       integer, intent(out) :: ierr
     359              :       type(auto_diff_real_star_order1) :: d_v_div_r, Chi_cell
     360              :       include 'formats'
     361            0 :       ierr = 0
     362            0 :       if (s%mixing_length_alpha == 0d0 .or. &
     363              :           k > s% nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     364            0 :          Eq_cell = 0d0
     365            0 :          if (k >= 1 .and. k <= s%nz) s%Eq_ad(k) = 0d0
     366              :       else
     367            0 :          Chi_cell = s%Chi_ad(k)  ! compute_Chi_cell(s,k,ierr)
     368            0 :          if (ierr /= 0) return
     369              : 
     370            0 :          if (s%u_flag .or. s%TDC_use_density_form_for_eddy_viscosity) then
     371              :             ! new density derivative term
     372            0 :             d_v_div_r = compute_rho_form_of_d_v_div_r_opt_time_center(s, k, ierr)
     373              :          else
     374            0 :             d_v_div_r = compute_d_v_div_r_opt_time_center(s, k, ierr)
     375              :          end if
     376              : 
     377            0 :          if (ierr /= 0) return
     378            0 :          Eq_cell = 4d0*pi*Chi_cell*d_v_div_r/s%dm(k)  ! erg s^-1 g^-1
     379              :       end if
     380            0 :       s%Eq(k) = Eq_cell%val
     381            0 :       s%Eq_ad(k) = Eq_cell
     382            0 :    end function compute_tdc_Eq_cell
     383              : 
     384            0 :    function compute_tdc_Uq_face(s, k, ierr) result(Uq_face)  ! cm s^-2, acceleration
     385              :       type(star_info), pointer :: s
     386              :       integer, intent(in) :: k
     387              :       type(auto_diff_real_star_order1) :: Uq_face
     388              :       integer, intent(out) :: ierr
     389              :       type(auto_diff_real_star_order1) :: Chi_00, Chi_m1, r_00
     390              :       include 'formats'
     391            0 :       ierr = 0
     392              :       if (s%mixing_length_alpha == 0d0 .or. &
     393            0 :           k <= s%RSP2_num_outermost_cells_forced_nonturbulent .or. &
     394              :           k > s%nz - int(s%nz/s%RSP2_nz_div_IBOTOM)) then
     395            0 :          Uq_face = 0d0
     396              :       else
     397            0 :          r_00 = wrap_opt_time_center_r_00(s, k)
     398              : 
     399              :          ! which do we adopt?
     400            0 :          Chi_00 = compute_Chi_cell(s, k, ierr)  ! s% Chi_ad(k) XXX
     401              :          !Chi_00 = s% Chi_ad(k)  ! compute_Chi_cell(s,k,ierr)
     402              : 
     403            0 :          if (k > 1) then
     404            0 :             Chi_m1 = shift_m1(compute_Chi_cell(s, k - 1, ierr))
     405              :             !Chi_m1 = shift_m1(s% Chi_ad(k-1)) XXX
     406            0 :             if (ierr /= 0) return
     407              :          else
     408            0 :             Chi_m1 = 0d0
     409              :          end if
     410            0 :          Uq_face = 4d0*pi*(Chi_m1 - Chi_00)/(r_00*s%dm_bar(k))
     411              : 
     412            0 :          if (k == -56) then
     413            0 :             write (*, 3) 'RSP2 Uq chi_m1 chi_00 r', k, s%solver_iter, &
     414            0 :                Uq_face%val, Chi_m1%val, Chi_00%val, r_00%val
     415              :          end if
     416              : 
     417              :       end if
     418              :       ! erg g^-1 cm^-1 = g cm^2 s^-2 g^-1 cm^-1 = cm s^-2, acceleration
     419            0 :       s%Uq(k) = Uq_face%val
     420            0 :    end function compute_tdc_Uq_face
     421              : 
     422              :   ! face centered variables for tdc update below
     423            0 :    function compute_Chi_div_w_face(s, k, ierr) result(Chi_face)
     424              :    ! eddy viscosity energy (Kuhfuss 1986) [erg]
     425              :    type(star_info), pointer :: s
     426              :    integer, intent(in) :: k
     427              :    type(auto_diff_real_star_order1) :: Chi_face
     428              :    integer, intent(out) :: ierr
     429              :    type(auto_diff_real_star_order1) :: &
     430              :    rho2, r6_face, d_v_div_r, Hp_face, w_00, d_00, r_00, r_p1
     431            0 :    real(dp) :: f, ALFAM_ALFA, dmbar
     432              :    logical :: dbg
     433              :    include 'formats'
     434            0 :    ierr = 0
     435            0 :    dbg = .false.
     436              : 
     437              :    ! check where we are getting alfam from.
     438            0 :    if (s%MLT_option == 'TDC' .and. .not. s%RSP2_flag) then
     439            0 :       ALFAM_ALFA = s%alpha_TDC_DampM*s%mixing_length_alpha
     440              :    else ! this is for safety, but probably is never called.
     441              :       ALFAM_ALFA = 0d0
     442              :    end if
     443              : 
     444            0 :    if (ALFAM_ALFA == 0d0 .or. &
     445              :       k > s%nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     446            0 :       Chi_face = 0d0
     447            0 :       if (k >= 1 .and. k <= s%nz) then
     448            0 :          s%Chi(k) = 0d0
     449            0 :          s%Chi_ad(k) = 0d0
     450              :       end if
     451              :    else
     452            0 :       Hp_face = get_scale_height_face(s,k) !Hp_cell_for_Chi(s, k, ierr)
     453            0 :       if (ierr /= 0) return
     454            0 :       if (s%u_flag .or. s%TDC_use_density_form_for_eddy_viscosity) then
     455              :       ! new density derivative term
     456            0 :          d_v_div_r = compute_rho_form_of_d_v_div_r_face(s, k, ierr)
     457              :       else
     458            0 :          d_v_div_r = compute_d_v_div_r_face(s, k, ierr)
     459              :       end if
     460            0 :       if (ierr /= 0) return
     461              : 
     462            0 :       if (k >= 2) then
     463            0 :          dmbar = 0.5d0*(s% dm(k) + s% dm(k-1))
     464              :       else
     465            0 :          dmbar = 0.5d0*s% dm(k)
     466              :       end if
     467            0 :       d_00 = get_rho_face(s, k)
     468            0 :       f = (16d0/3d0)*pi*ALFAM_ALFA/dmbar
     469            0 :       rho2 = pow2(d_00)
     470            0 :       r_00 = wrap_r_00(s, k)
     471              :       !r_p1 = wrap_r_p1(s, k)
     472            0 :       r6_face = pow6(r_00) !0.5d0*(pow6(r_00) + pow6(r_p1))
     473            0 :       Chi_face = f*rho2*r6_face*d_v_div_r*Hp_face!*w_00
     474              :       ! units = g^-1 cm s^-1 g^2 cm^-6 cm^6 s^-1 cm
     475              :       !       = g cm^2 s^-2
     476              :       !       = erg ! * (s / cm) - > [erg] * 1/w00
     477              : 
     478              :    end if
     479              :    !s%Chi(k) = Chi_face%val
     480              :    !s%Chi_ad(k) = Chi_face
     481              : 
     482              :    if (dbg .and. k == -100) then
     483              :    write (*, *) ' s% ALFAM_ALFA', ALFAM_ALFA
     484              :    write (*, *) 'Hp_face', Hp_face%val
     485              :    write (*, *) 'd_v_div_r', d_v_div_r%val
     486              :    write (*, *) ' f', f
     487              :    write (*, *) 'w_00', w_00%val
     488              :    write (*, *) 'd_00 ', d_00%val
     489              :    write (*, *) 'rho2 ', rho2%val
     490              :    write (*, *) 'r_00', r_00%val
     491              :    write (*, *) 'r_p1 ', r_p1%val
     492              :    write (*, *) 'r6_cell', r6_face%val
     493              :    end if
     494            0 :    end function compute_Chi_div_w_face
     495              : 
     496              : 
     497              : 
     498            0 :    function compute_tdc_Eq_div_w_face(s, k, ierr) result(Eq_face)  ! erg g^-1 s^-1 * (cm^-1 s^1)
     499              :    type(star_info), pointer :: s
     500              :    integer, intent(in) :: k
     501              :    type(auto_diff_real_star_order1) :: Eq_face
     502              :    integer, intent(out) :: ierr
     503              :    type(auto_diff_real_star_order1) :: d_v_div_r, Chi_face
     504            0 :    real(dp) :: dmbar
     505              :    include 'formats'
     506            0 :    ierr = 0
     507            0 :    if (s%mixing_length_alpha == 0d0 .or. &
     508              :    k > s%nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     509            0 :       Eq_face = 0d0
     510            0 :       if (k >= 1 .and. k <= s%nz) s%Eq_ad(k) = 0d0
     511              :    else
     512            0 :       Chi_face = compute_Chi_div_w_face(s,k,ierr)
     513            0 :       if (ierr /= 0) return
     514              : 
     515            0 :       if (s%u_flag .or. s%TDC_use_density_form_for_eddy_viscosity) then
     516              :          ! new density derivative term
     517            0 :          d_v_div_r = compute_rho_form_of_d_v_div_r_face_opt_time_center(s, k, ierr)
     518              :       else
     519            0 :          d_v_div_r = compute_d_v_div_r_opt_time_center_face(s, k, ierr)
     520              :       end if
     521              : 
     522            0 :       if (k >= 2) then
     523            0 :          dmbar = 0.5d0*(s% dm(k) + s% dm(k-1))
     524              :       else
     525            0 :          dmbar = 0.5d0*s% dm(k)
     526              :       end if
     527              : 
     528            0 :       if (ierr /= 0) return
     529            0 :       Eq_face = 4d0*pi*Chi_face*d_v_div_r/dmbar  ! erg s^-1 g^-1 * (cm^-1 s^1)
     530              :    end if
     531              :    !s%Eq(k) = Eq_face%val
     532              :    !s%Eq_ad(k) = Eq_face
     533            0 :    end function compute_tdc_Eq_div_w_face
     534              : 
     535            0 :    function compute_d_v_div_r_face(s, k, ierr) result(d_v_div_r)  ! s^-1
     536              :       type(star_info), pointer :: s
     537              :       integer, intent(in) :: k
     538              :       type(auto_diff_real_star_order1) :: d_v_div_r
     539              :       integer, intent(out) :: ierr
     540              :       type(auto_diff_real_star_order1) :: v_00, v_p1, r_00, r_p1, term1, term2
     541              :       logical :: dbg
     542              :       include 'formats'
     543            0 :       ierr = 0
     544            0 :       dbg = .false.
     545              : 
     546            0 :       if (k >1) then
     547            0 :          v_00 = 0.5d0 * (wrap_v_00(s, k) + wrap_v_m1(s, k))
     548              :       else
     549            0 :          v_00 = 0.5d0 * wrap_v_00(s, k)
     550              :       end if
     551              : 
     552            0 :       v_p1 = 0.5d0 * (wrap_v_00(s, k) + wrap_v_p1(s, k))
     553              : 
     554            0 :       if (k >1) then
     555            0 :          r_00 = 0.5d0 * (wrap_r_00(s, k) + wrap_r_m1(s, k))
     556              :       else
     557            0 :          r_00 = 0.5d0 * wrap_r_00(s, k)
     558              :       end if
     559            0 :       r_p1 = 0.5d0*(wrap_r_00(s, k) + wrap_r_p1(s, k))
     560            0 :       if (r_p1%val == 0d0) r_p1 = 1d0
     561            0 :       d_v_div_r = v_00/r_00 - v_p1/r_p1 ! units s^-1
     562              : 
     563              :       ! Debugging output to trace values
     564              :       if (dbg .and. k == -63) then
     565              :          write (*, *) 'test d_v_div_r, k:', k
     566              :          write (*, *) 'v_00:', v_00%val, 'v_p1:', v_p1%val
     567              :          write (*, *) 'r_00:', r_00%val, 'r_p1:', r_p1%val
     568              :          write (*, *) 'd_v_div_r:', d_v_div_r%val
     569              :       end if
     570            0 :    end function compute_d_v_div_r_face
     571              : 
     572              : 
     573              : 
     574            0 :    function compute_d_v_div_r_opt_time_center_face(s, k, ierr) result(d_v_div_r)  ! s^-1
     575              :       type(star_info), pointer :: s
     576              :       integer, intent(in) :: k
     577              :       type(auto_diff_real_star_order1) :: d_v_div_r
     578              :       integer, intent(out) :: ierr
     579              :       type(auto_diff_real_star_order1) :: v_00, v_p1, r_00, r_p1
     580              :       include 'formats'
     581            0 :       ierr = 0
     582              : 
     583            0 :       if (k >1) then
     584            0 :          v_00 = 0.5d0 * (wrap_opt_time_center_v_00(s, k) + wrap_opt_time_center_v_m1(s, k))
     585              :       else
     586            0 :          v_00 = 0.5d0 * wrap_opt_time_center_v_00(s, k)
     587              :       end if
     588              : 
     589            0 :       v_p1 = 0.5d0 * (wrap_opt_time_center_v_00(s, k) + wrap_opt_time_center_v_p1(s, k))
     590              : 
     591            0 :       if (k >1) then
     592            0 :          r_00 = 0.5d0 * (wrap_opt_time_center_r_00(s, k) + wrap_opt_time_center_r_m1(s, k))
     593              :       else
     594            0 :          r_00 = 0.5d0 * wrap_opt_time_center_r_00(s, k)
     595              :       end if
     596            0 :       r_p1 = 0.5d0*(wrap_opt_time_center_r_00(s, k) + wrap_opt_time_center_r_p1(s, k))
     597            0 :       if (r_p1%val == 0d0) r_p1 = 1d0
     598            0 :       d_v_div_r = v_00/r_00 - v_p1/r_p1 ! units s^-1
     599              : 
     600            0 :       if (r_p1%val == 0d0) r_p1 = 1d0
     601            0 :       d_v_div_r = v_00/r_00 - v_p1/r_p1  ! units s^-1
     602            0 :    end function compute_d_v_div_r_opt_time_center_face
     603              : 
     604              : end module tdc_hydro
        

Generated by: LCOV version 2.0-1