LCOV - code coverage report
Current view: top level - star/private - tdc_hydro.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 248 0
Test Date: 2025-12-14 16:52:03 Functions: 0.0 % 15 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_Uq_face, compute_tdc_Eq_div_w_face, &
      35              :       get_TDC_alfa_beta_face_weights, set_viscosity_vars_TDC, compute_tdc_Uq_dm_cell
      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 :       if (.not. (s%v_flag .or. s%u_flag)) then ! set values 0 if not using v_flag or u_flag.
      50            0 :          do k = 1, s%nz
      51            0 :             s%Eq(k) = 0d0; s%Eq_ad(k) = 0d0
      52            0 :             s%Chi(k) = 0d0; s%Chi_ad(k) = 0d0
      53            0 :             s%Uq(k) = 0d0
      54              :          end do
      55            0 :          return
      56              :       end if
      57              : 
      58            0 :       !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
      59              :       do k = 1, s%nz
      60              :          ! Hp_face(k) <= 0 means it needs to be set.  e.g., after read file
      61              :          if (s%Hp_face(k) <= 0) then
      62              :             ! this scale height for face is already calculated in TDC
      63              :             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.
      64              :          end if
      65              :       end do
      66              :       !$OMP END PARALLEL DO
      67            0 :       if (ierr /= 0) then
      68            0 :          if (s%report_ierr) write (*, 2) 'failed in set_viscosity_vars_TDC loop 1', s%model_number
      69            0 :          return
      70              :       end if
      71            0 :       !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
      72              :       do k = 1, s%nz
      73              :          x = compute_Chi_div_w_face(s, k, op_err) ! Sets Chi_face
      74              :          if (op_err /= 0) ierr = op_err
      75              :          x = compute_tdc_Eq_div_w_face(s, k, op_err) ! Sets Eq_face
      76              :          if (op_err /= 0) ierr = op_err
      77              :          if (s% v_flag) then
      78              :             x = compute_tdc_Uq_face(s, k, op_err)
      79              :          else if (s% u_flag) then
      80              :             x = compute_tdc_Uq_dm_cell(s, k, op_err)
      81              :          end if
      82              :          if (op_err /= 0) ierr = op_err
      83              :       end do
      84              :       !$OMP END PARALLEL DO
      85            0 :       if (ierr /= 0) then
      86            0 :          if (s%report_ierr) write (*, 2) 'failed in set_viscosity_vars_TDC loop 2', s%model_number
      87            0 :          return
      88              :       end if
      89              :    end subroutine set_viscosity_vars_TDC
      90              : 
      91            0 :    subroutine get_TDC_alfa_beta_face_weights(s, k, alfa, beta)
      92              :       type(star_info), pointer :: s
      93              :       integer, intent(in) :: k
      94              :       real(dp), intent(out) :: alfa, beta
      95              :       ! face_value = alfa*cell_value(k) + beta*cell_value(k-1)
      96            0 :       if (k == 1) call mesa_error(__FILE__, __LINE__, 'bad k==1 for get_TDC_alfa_beta_face_weights')
      97            0 :       if (s%TDC_hydro_use_mass_interp_face_values) then
      98            0 :          alfa = s%dq(k - 1)/(s%dq(k - 1) + s%dq(k))
      99            0 :          beta = 1d0 - alfa
     100              :       else
     101            0 :          alfa = 0.5d0
     102            0 :          beta = 0.5d0
     103              :       end if
     104            0 :    end subroutine get_TDC_alfa_beta_face_weights
     105              : 
     106              : 
     107            0 :    function wrap_Hp_cell(s, k) result(Hp_cell)  ! cm , different than rsp2
     108              :       type(star_info), pointer :: s
     109              :       integer, intent(in) :: k
     110              :       type(auto_diff_real_star_order1) :: Hp1, Hp0, Hp_cell
     111            0 :       Hp0 = get_scale_height_face(s,k)
     112            0 :       Hp1 = 0d0
     113            0 :       if (k+1 < s%nz) then
     114            0 :          Hp1 = shift_p1(get_scale_height_face(s,k+1))
     115              :       end if
     116            0 :       Hp_cell = 0.5d0*(Hp0 + Hp1)
     117              :       !0.5d0*(wrap_Hp_00(s, k) + wrap_Hp_p1(s, k))
     118            0 :    end function wrap_Hp_cell
     119              : 
     120            0 :    function Hp_cell_for_Chi(s, k, ierr) result(Hp_cell)  ! cm
     121              :       type(star_info), pointer :: s
     122              :       integer, intent(in) :: k
     123              :       integer, intent(out) :: ierr
     124              :       type(auto_diff_real_star_order1) :: Hp_cell
     125              :       type(auto_diff_real_star_order1) :: d_00, Peos_00, rmid
     126            0 :       real(dp) :: mmid, cgrav_mid
     127              :       include 'formats'
     128            0 :       ierr = 0
     129              : 
     130            0 :       Hp_cell = wrap_Hp_cell(s, k)
     131            0 :       return ! below is skipped, for now.
     132              : 
     133              :       d_00 = wrap_d_00(s, k)
     134              :       Peos_00 = wrap_Peos_00(s, k)
     135              :       if (k < s%nz) then
     136              :          rmid = 0.5d0*(wrap_r_00(s, k) + wrap_r_p1(s, k))
     137              :          mmid = 0.5d0*(s%m(k) + s%m(k + 1))
     138              :          cgrav_mid = 0.5d0*(s%cgrav(k) + s%cgrav(k + 1))
     139              :       else
     140              :          rmid = 0.5d0*(wrap_r_00(s, k) + s%r_center)
     141              :          mmid = 0.5d0*(s%m(k) + s%m_center)
     142              :          cgrav_mid = s%cgrav(k)
     143              :       end if
     144              :       Hp_cell = pow2(rmid)*Peos_00/(d_00*cgrav_mid*mmid)
     145              :       if (s%alt_scale_height_flag) then
     146              :          call mesa_error(__FILE__, __LINE__, 'Hp_cell_for_Chi: cannot use alt_scale_height_flag')
     147              :       end if
     148              :    end function Hp_cell_for_Chi
     149              : 
     150              :    ! this function is only called internally in TDC_Uq_face, and for v_flag only.
     151            0 :    function compute_Chi_cell(s, k, ierr) result(Chi_cell) ! does not update s% Chi or Chi_ad
     152              :       ! eddy viscosity energy (Kuhfuss 1986) [erg]
     153              :       type(star_info), pointer :: s
     154              :       integer, intent(in) :: k
     155              :       type(auto_diff_real_star_order1) :: Chi_cell
     156              :       integer, intent(out) :: ierr
     157              :       type(auto_diff_real_star_order1) :: &
     158              :          rho2, r6_cell, d_v_div_r, Hp_cell, w_00, d_00, r_00, r_p1
     159            0 :       real(dp) :: f, ALFAM_ALFA
     160              :       logical :: dbg
     161              :       include 'formats'
     162            0 :       ierr = 0
     163            0 :       dbg = .false.
     164              : 
     165              :       ! check where we are getting alfam from.
     166            0 :       if (s%MLT_option == 'TDC' .and. .not. s%RSP2_flag) then
     167            0 :          ALFAM_ALFA = s%TDC_alpha_M*s%mixing_length_alpha
     168              :       else ! this is for safety, but probably is never called.
     169              :          ALFAM_ALFA = 0d0
     170              :       end if
     171              : 
     172              :       if (ALFAM_ALFA == 0d0 .or. &
     173            0 :           k <= s% TDC_num_outermost_cells_forced_nonturbulent .or. &
     174              :           k > s% nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     175            0 :          Chi_cell = 0d0
     176              :       else
     177            0 :          Hp_cell = Hp_cell_for_Chi(s, k, ierr)
     178            0 :          if (ierr /= 0) return
     179            0 :          if (s%TDC_use_density_form_for_eddy_viscosity) then
     180              :             ! new density derivative term
     181            0 :             d_v_div_r = compute_rho_form_of_d_v_div_r(s, k, ierr)
     182              :          else
     183            0 :             d_v_div_r = compute_d_v_div_r(s, k, ierr)
     184              :          end if
     185            0 :          if (ierr /= 0) return
     186              : 
     187              :          ! don't need to check if mlt_vc > 0 here.
     188            0 :          if (k < s% nz) then
     189            0 :             if (s% okay_to_set_mlt_vc .and. &
     190              :                s% TDC_alpha_M_use_explicit_mlt_vc_in_momentum_equation) then !add option for explicit mlt_vc, operator split in momentum eq.
     191            0 :                w_00 = 0.5d0*(s% mlt_vc_old(k) + s% mlt_vc_old(k+1))/sqrt_2_div_3! same as info%A0 from TDC
     192              :             else
     193            0 :                w_00 = 0.5d0*(s% mlt_vc_ad(k) + shift_p1(s% mlt_vc_ad(k+1)))/sqrt_2_div_3! same as info%A0 from TDC
     194              :             end if
     195              :          else
     196            0 :             if (s% okay_to_set_mlt_vc .and. &
     197              :                 s% TDC_alpha_M_use_explicit_mlt_vc_in_momentum_equation) then !add option for explicit mlt_vc, operator split in momentum eq.
     198            0 :                w_00 = 0.5d0*s% mlt_vc_old(k)/sqrt_2_div_3! same as info%A0 from TDC
     199              :             else
     200            0 :                w_00 = 0.5d0*s% mlt_vc_ad(k)/sqrt_2_div_3! same as info%A0 from TDC
     201              :             end if
     202              :          end if
     203            0 :          d_00 = wrap_d_00(s, k)
     204            0 :          f = (16d0/3d0)*pi*ALFAM_ALFA/s%dm(k)
     205            0 :          rho2 = pow2(d_00)
     206            0 :          r_00 = wrap_r_00(s, k)
     207            0 :          r_p1 = wrap_r_p1(s, k)
     208            0 :          r6_cell = 0.5d0*(pow6(r_00) + pow6(r_p1))
     209            0 :          Chi_cell = f*rho2*r6_cell*d_v_div_r*Hp_cell*w_00
     210              :          ! units = g^-1 cm s^-1 g^2 cm^-6 cm^6 s^-1 cm
     211              :          !       = g cm^2 s^-2
     212              :          !       = erg
     213              : 
     214              :       end if
     215              :       ! this is set in Chi_div_w_face
     216              :       !s%Chi(k) = Chi_cell%val
     217              :       !s%Chi_ad(k) = Chi_cell
     218              : 
     219              :       if (dbg .and. k == -100) then
     220              :          write (*, *) ' s% ALFAM_ALFA', ALFAM_ALFA
     221              :          write (*, *) 'Hp_cell', Hp_cell%val
     222              :          write (*, *) 'd_v_div_r', d_v_div_r%val
     223              :          write (*, *) ' f', f
     224              :          write (*, *) 'w_00', w_00%val
     225              :          write (*, *) 'd_00 ', d_00%val
     226              :          write (*, *) 'rho2 ', rho2%val
     227              :          write (*, *) 'r_00', r_00%val
     228              :          write (*, *) 'r_p1 ', r_p1%val
     229              :          write (*, *) 'r6_cell', r6_cell%val
     230              :       end if
     231            0 :    end function compute_Chi_cell
     232              : 
     233              :   ! face centered variables for tdc update below
     234            0 :    function compute_Chi_div_w_face(s, k, ierr) result(Chi_face)
     235              :    ! eddy viscosity energy (Kuhfuss 1986) [erg]
     236              :    type(star_info), pointer :: s
     237              :    integer, intent(in) :: k
     238              :    type(auto_diff_real_star_order1) :: Chi_face
     239              :    integer, intent(out) :: ierr
     240              :    type(auto_diff_real_star_order1) :: &
     241              :    rho2, r6_face, d_v_div_r, Hp_face, w_00, d_00, r_00, r_p1
     242            0 :    real(dp) :: f, ALFAM_ALFA, dmbar
     243              :    logical :: dbg
     244              :    include 'formats'
     245            0 :    ierr = 0
     246            0 :    dbg = .false.
     247              : 
     248              :    ! check where we are getting alfam from.
     249            0 :    if (s%MLT_option == 'TDC' .and. .not. s%RSP2_flag) then
     250            0 :       ALFAM_ALFA = s%TDC_alpha_M*s%mixing_length_alpha
     251              :    else ! this is for safety, but probably is never called.
     252              :       ALFAM_ALFA = 0d0
     253              :    end if
     254              : 
     255            0 :    if (ALFAM_ALFA == 0d0 .or. &
     256              :       k > s%nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     257            0 :       Chi_face = 0d0
     258              :    else
     259            0 :       Hp_face = get_scale_height_face(s,k) !Hp_cell_for_Chi(s, k, ierr)
     260            0 :       if (ierr /= 0) return
     261            0 :       if (s%TDC_use_density_form_for_eddy_viscosity) then
     262              :          ! new density derivative form
     263            0 :          d_v_div_r = compute_rho_form_of_d_v_div_r_face(s, k, ierr)
     264              :       else
     265            0 :          d_v_div_r = compute_d_v_div_r_face(s, k, ierr)
     266              :       end if
     267            0 :       if (ierr /= 0) return
     268              : 
     269            0 :       if (k >= 2) then
     270            0 :          dmbar = 0.5d0*(s% dm(k) + s% dm(k-1))
     271              :       else
     272            0 :          dmbar = 0.5d0*s% dm(k)
     273              :       end if
     274            0 :       d_00 = get_rho_face(s, k)
     275            0 :       f = (16d0/3d0)*pi*ALFAM_ALFA/dmbar
     276            0 :       rho2 = pow2(d_00)
     277            0 :       r_00 = wrap_r_00(s, k)
     278              :       !r_p1 = wrap_r_p1(s, k)
     279            0 :       r6_face = pow6(r_00) !0.5d0*(pow6(r_00) + pow6(r_p1))
     280            0 :       Chi_face = f*rho2*r6_face*d_v_div_r*Hp_face!*w_00
     281              :       ! units = g^-1 cm s^-1 g^2 cm^-6 cm^6 s^-1 cm * [s/cm] ! [1/w_00] = [s/cm]
     282              :       !       = g cm^2 s^-2 * [s/cm]
     283              :       !       = erg ! * [s / cm] - > [erg] * [s/cm]
     284              : 
     285              :    end if
     286              : 
     287              :    ! Chi_cell does not set Chi, we store Chi_face in s% Chi and s% Chi_ad
     288            0 :       if (s% okay_to_set_mlt_vc .and. &
     289              :          s% TDC_alpha_M_use_explicit_mlt_vc_in_momentum_equation) then !add option for explicit mlt_vc, operator split in momentum eq.
     290            0 :          w_00 = s% mlt_vc_old(k)/sqrt_2_div_3! same as info%A0 from TDC
     291              :       else
     292            0 :          w_00 = s% mlt_vc_ad(k)/sqrt_2_div_3! same as info%A0 from TDC
     293              :       end if
     294            0 :       s%Chi(k) = Chi_face%val*w_00%val
     295            0 :       s%Chi_ad(k) = Chi_face*w_00
     296              : 
     297              :       if (dbg .and. k == -100) then
     298              :       write (*, *) ' s% ALFAM_ALFA', ALFAM_ALFA
     299              :       write (*, *) 'Hp_face', Hp_face%val
     300              :       write (*, *) 'd_v_div_r', d_v_div_r%val
     301              :       write (*, *) ' f', f
     302              :       write (*, *) 'w_00', w_00%val
     303              :       write (*, *) 'd_00 ', d_00%val
     304              :       write (*, *) 'rho2 ', rho2%val
     305              :       write (*, *) 'r_00', r_00%val
     306              :       write (*, *) 'r_p1 ', r_p1%val
     307              :       write (*, *) 'r6_cell', r6_face%val
     308              :       end if
     309            0 :    end function compute_Chi_div_w_face
     310              : 
     311            0 :    function compute_tdc_Eq_div_w_face(s, k, ierr) result(Eq_face)  ! erg g^-1 s^-1 * (cm^-1 s^1)
     312              :    type(star_info), pointer :: s
     313              :    integer, intent(in) :: k
     314              :    type(auto_diff_real_star_order1) :: Eq_face
     315              :    integer, intent(out) :: ierr
     316              :    type(auto_diff_real_star_order1) :: d_v_div_r, Chi_face, w_00
     317            0 :    real(dp) :: dmbar
     318              :    include 'formats'
     319            0 :    ierr = 0
     320            0 :    if (s%mixing_length_alpha == 0d0 .or. &
     321              :    k > s%nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     322            0 :       Eq_face = 0d0
     323            0 :       if (k >= 1 .and. k <= s%nz) s%Eq_ad(k) = 0d0
     324              :    else
     325            0 :       Chi_face = compute_Chi_div_w_face(s,k,ierr)
     326            0 :       if (ierr /= 0) return
     327              : 
     328            0 :       if (s%TDC_use_density_form_for_eddy_viscosity) then
     329              :          ! new density derivative term
     330            0 :          d_v_div_r = compute_rho_form_of_d_v_div_r_face_opt_time_center(s, k, ierr)
     331              :       else
     332            0 :          d_v_div_r = compute_d_v_div_r_opt_time_center_face(s, k, ierr)
     333              :       end if
     334              : 
     335            0 :       if (k >= 2) then
     336            0 :          dmbar = 0.5d0*(s% dm(k) + s% dm(k-1))
     337              :       else
     338            0 :          dmbar = 0.5d0*s% dm(k)
     339              :       end if
     340              : 
     341            0 :       if (ierr /= 0) return
     342            0 :       Eq_face = 4d0*pi*Chi_face*d_v_div_r/dmbar  ! erg s^-1 g^-1 * (cm^-1 s^1)
     343              :    end if
     344              : 
     345              :    ! only for output, really only used for returning Eq to star pointers.
     346            0 :    if (s% okay_to_set_mlt_vc .and. &
     347              :       s% TDC_alpha_M_use_explicit_mlt_vc_in_momentum_equation) then !add option for explicit mlt_vc, operator split in momentum eq.
     348            0 :       w_00 = s% mlt_vc_old(k)/sqrt_2_div_3! same as info%A0 from TDC
     349              :    else
     350            0 :       w_00 = s% mlt_vc_ad(k)/sqrt_2_div_3! same as info%A0 from TDC
     351              :    end if
     352              : 
     353            0 :    s%Eq(k) = Eq_face%val * w_00%val
     354            0 :    s%Eq_ad(k) = Eq_face * w_00
     355            0 :    end function compute_tdc_Eq_div_w_face
     356              : 
     357              :    ! for v_flag only. face centered Uq for hydro_momentum
     358            0 :    function compute_tdc_Uq_face(s, k, ierr) result(Uq_face) !(v_flag only)  ! cm s^-2, acceleration
     359              :       type(star_info), pointer :: s
     360              :       integer, intent(in) :: k
     361              :       type(auto_diff_real_star_order1) :: Uq_face
     362              :       integer, intent(out) :: ierr
     363              :       type(auto_diff_real_star_order1) :: Chi_00, Chi_m1, r_00
     364              :       include 'formats'
     365            0 :       ierr = 0
     366              :       if (s%mixing_length_alpha == 0d0 .or. &
     367            0 :           k <= s% TDC_num_outermost_cells_forced_nonturbulent .or. &
     368              :           k > s%nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     369            0 :          Uq_face = 0d0
     370              :       else
     371            0 :          r_00 = wrap_opt_time_center_r_00(s, k)
     372              : 
     373              :          ! which do we adopt?
     374            0 :          Chi_00 = compute_Chi_cell(s, k, ierr)  ! s% Chi_ad(k) XXX
     375              : 
     376            0 :          if (k > 1) then
     377            0 :             Chi_m1 = shift_m1(compute_Chi_cell(s, k-1, ierr))
     378            0 :             if (ierr /= 0) return
     379              :          else
     380            0 :             Chi_m1 = 0d0
     381              :          end if
     382            0 :          Uq_face = 4d0*pi*(Chi_m1 - Chi_00)/(r_00*s%dm_bar(k))
     383              : 
     384            0 :          if (k == -56) then
     385            0 :             write (*, 3) 'TDC Uq chi_m1 chi_00 r', k, s%solver_iter, &
     386            0 :                Uq_face%val, Chi_m1%val, Chi_00%val, r_00%val
     387              :          end if
     388              : 
     389              :       end if
     390              :       ! erg g^-1 cm^-1 = g cm^2 s^-2 g^-1 cm^-1 = cm s^-2, acceleration
     391            0 :       s%Uq(k) = Uq_face%val
     392            0 :    end function compute_tdc_Uq_face
     393              : 
     394              :    ! for u_flag only. cell centered Uq as source for Reimann flux.
     395            0 :    function compute_tdc_Uq_dm_cell(s, k, ierr) result(Uq_cell)  ! cm s^-2, acceleration
     396              :       type(star_info), pointer :: s
     397              :       integer, intent(in) :: k
     398              :       integer, intent(out) :: ierr
     399              :       type(auto_diff_real_star_order1) :: Chi_00, Chi_p1, r_00, r_p1, w_00, w_p1, r_cell, Uq_cell
     400              :       include 'formats'
     401            0 :       ierr = 0
     402              :       if (s%mixing_length_alpha == 0d0 .or. &
     403            0 :           k <= s% TDC_num_outermost_cells_forced_nonturbulent .or. &
     404              :           k > s%nz - s% TDC_num_innermost_cells_forced_nonturbulent) then
     405            0 :          Uq_cell = 0d0
     406              :       else
     407            0 :          r_00 = wrap_opt_time_center_r_00(s, k)
     408            0 :          r_p1 = wrap_opt_time_center_r_p1(s, k)
     409            0 :          r_cell = 0.5d0*(r_00+r_p1) ! not staggered unlike terms inside chi_div_w_face
     410              : 
     411            0 :          if (s% okay_to_set_mlt_vc .and. &
     412              :             s% TDC_alpha_M_use_explicit_mlt_vc_in_momentum_equation) then
     413            0 :             w_00 = s% mlt_vc_old(k)/sqrt_2_div_3
     414              :          else
     415            0 :             w_00 = s% mlt_vc_ad(k)/sqrt_2_div_3
     416              :          end if
     417              : 
     418            0 :          Chi_00 = compute_Chi_div_w_face(s, k, ierr) * w_00
     419              : 
     420            0 :          if (k < s% nz) then
     421            0 :             if (s% okay_to_set_mlt_vc .and. &
     422              :                s% TDC_alpha_M_use_explicit_mlt_vc_in_momentum_equation) then
     423            0 :                w_p1 = s% mlt_vc_old(k+1)/sqrt_2_div_3
     424              :             else
     425            0 :                w_p1 = shift_p1(s% mlt_vc_ad(k+1))/sqrt_2_div_3
     426              :             end if
     427              : 
     428            0 :             Chi_p1 = shift_p1(compute_Chi_div_w_face(s, k+1, ierr))*w_p1
     429            0 :             if (ierr /= 0) return
     430              :          else
     431            0 :             Chi_p1 = 0d0
     432            0 :             w_p1 = 0d0
     433              :          end if
     434              : 
     435            0 :          Uq_cell = 4d0*pi*(Chi_00 - Chi_p1)/(r_cell) ! we have neglected the /dm here, because it is restored in the reimann flux calculation
     436              :          ! erg g^-1 cm^-1 = g cm^2 s^-2 g^-1 cm^-1 = cm s^-2 [g], acceleration*mass = Force
     437              : 
     438            0 :          if (k == -56) then
     439            0 :             write (*, 3) 'TDC Uq chi_m1 chi_00 r', k, s%solver_iter, &
     440            0 :                Uq_cell%val, Chi_p1%val, Chi_00%val, r_00%val
     441              :          end if
     442              : 
     443              :       end if
     444            0 :       s%Uq(k) = Uq_cell%val/ s% dm(k)
     445            0 :    end function compute_tdc_Uq_dm_cell
     446              : 
     447              : 
     448              : ! all the forms of d(v/r)/dr, below
     449            0 :    function compute_d_v_div_r(s, k, ierr) result(d_v_div_r)  ! s^-1
     450              :       type(star_info), pointer :: s
     451              :       integer, intent(in) :: k
     452              :       type(auto_diff_real_star_order1) :: d_v_div_r
     453              :       integer, intent(out) :: ierr
     454              :       type(auto_diff_real_star_order1) :: v_00, v_p1, r_00, r_p1, term1, term2
     455              :       logical :: dbg
     456              :       include 'formats'
     457            0 :       ierr = 0
     458            0 :       dbg = .false.
     459            0 :       v_00 = wrap_v_00(s, k)
     460            0 :       v_p1 = wrap_v_p1(s, k)
     461            0 :       r_00 = wrap_r_00(s, k)
     462            0 :       r_p1 = wrap_r_p1(s, k)
     463            0 :       if (r_p1%val == 0d0) r_p1 = 1d0
     464            0 :       d_v_div_r = v_00/r_00 - v_p1/r_p1 ! units s^-1
     465              : 
     466              :       ! Debugging output to trace values
     467              :       if (dbg .and. k == -63) then
     468              :          write (*, *) 'test d_v_div_r, k:', k
     469              :          write (*, *) 'v_00:', v_00%val, 'v_p1:', v_p1%val
     470              :          write (*, *) 'r_00:', r_00%val, 'r_p1:', r_p1%val
     471              :          write (*, *) 'd_v_div_r:', d_v_div_r%val
     472              :       end if
     473            0 :    end function compute_d_v_div_r
     474              : 
     475              :    function compute_d_v_div_r_opt_time_center(s, k, ierr) result(d_v_div_r)  ! s^-1
     476              :       type(star_info), pointer :: s
     477              :       integer, intent(in) :: k
     478              :       type(auto_diff_real_star_order1) :: d_v_div_r
     479              :       integer, intent(out) :: ierr
     480              :       type(auto_diff_real_star_order1) :: v_00, v_p1, r_00, r_p1
     481              :       include 'formats'
     482              :       ierr = 0
     483              :       v_00 = wrap_opt_time_center_v_00(s, k)
     484              :       v_p1 = wrap_opt_time_center_v_p1(s, k)
     485              :       r_00 = wrap_opt_time_center_r_00(s, k)
     486              :       r_p1 = wrap_opt_time_center_r_p1(s, k)
     487              :       if (r_p1%val == 0d0) r_p1 = 1d0
     488              :       d_v_div_r = v_00/r_00 - v_p1/r_p1  ! units s^-1
     489              :    end function compute_d_v_div_r_opt_time_center
     490              : 
     491            0 :    function compute_rho_form_of_d_v_div_r(s, k, ierr) result(d_v_div_r) ! used in Chi_cell
     492              :       type(star_info), pointer :: s
     493              :       integer, intent(in)  :: k
     494              :       integer, intent(out) :: ierr
     495              :       type(auto_diff_real_star_order1) :: d_v_div_r, v_00, v_p1
     496              :       type(auto_diff_real_star_order1) :: r_cell, rho_cell, v_cell, dlnrho_dt
     497            0 :       real(dp) :: dm_cell
     498            0 :       ierr = 0
     499              : 
     500            0 :       r_cell = 0.5d0*(wrap_r_00(s, k) + wrap_r_p1(s, k))
     501            0 :       rho_cell = wrap_d_00(s, k)
     502            0 :       if (s% u_flag) then
     503            0 :          v_cell = wrap_u_00(s,k)
     504              :       else ! v flag
     505            0 :          v_cell = 0.5d0*(wrap_v_00(s, k) + wrap_v_p1(s, k))
     506              :       end if
     507            0 :       v_00 = wrap_opt_time_center_v_00(s, k)
     508            0 :       v_p1 = wrap_opt_time_center_v_p1(s, k)
     509            0 :       dlnrho_dt = wrap_dxh_lnd(s, k)/s%dt    ! (∂/∂t)lnρ
     510            0 :       dm_cell = s%dm(k)                     ! cell mass
     511              : 
     512              :       ! density form
     513            0 :       d_v_div_r = -dm_cell/(4d0*pi*rho_cell)*(dlnrho_dt/pow3(r_cell) + 3d0*v_cell/pow4(r_cell))
     514              : 
     515              :       ! dm_cell*(1/r * du/dm - U/4/pi/rho/r^4), more sensitive to geometry
     516              :       !d_v_div_r = ((v_00 - v_p1) - dm_cell*v_cell/(4d0*pi*rho_cell*pow3(r_cell)))/r_cell
     517              : 
     518            0 :    end function compute_rho_form_of_d_v_div_r
     519              : 
     520            0 :    function compute_rho_form_of_d_v_div_r_face(s, k, ierr) result(d_v_div_r)
     521              :       type(star_info), pointer :: s
     522              :       integer, intent(in)  :: k
     523              :       integer, intent(out) :: ierr
     524              :       type(auto_diff_real_star_order1) :: d_v_div_r
     525              :       type(auto_diff_real_star_order1) :: r_face, rho_face, v_face, dlnrho_dt
     526            0 :       real(dp) :: dm_bar, alfa, beta
     527            0 :       ierr = 0
     528              : 
     529            0 :       r_face = wrap_r_00(s, k)
     530            0 :       rho_face = get_rho_face(s, k)
     531            0 :       v_face = wrap_v_00(s, k)   ! face-centered velocity
     532            0 :       if (k >= 2) then
     533            0 :          dm_bar = 0.5d0*(s% dm(k) + s% dm(k-1))
     534            0 :          call get_TDC_alfa_beta_face_weights(s, k, alfa, beta)
     535            0 :          dlnrho_dt = (alfa*wrap_dxh_lnd(s, k) + beta*shift_m1(wrap_dxh_lnd(s, k-1)))/s%dt    ! (∂/∂t)lnρ
     536              :       else
     537            0 :          dm_bar = 0.5d0*s% dm(k)
     538            0 :          dlnrho_dt = 0.5d0*wrap_dxh_lnd(s, k)/s%dt    ! (∂/∂t)lnρ
     539              :       end if
     540              : 
     541              :       ! density form
     542            0 :       d_v_div_r = -dm_bar/(4d0*pi*rho_face)*(dlnrho_dt/pow3(r_face) + 3d0*v_face/pow4(r_face))
     543              : 
     544              :       ! dm_bar*(1/r * du/dm - U/4/pi/rho/r^4), more sensitive to geometry
     545              :       !d_v_div_r = ((wrap_u_m1(s,k) - wrap_u_00(s,k)) - dm_bar*v_face/(4d0*pi*rho_face*pow3(r_face)))/r_face
     546              : 
     547            0 :    end function compute_rho_form_of_d_v_div_r_face
     548              : 
     549            0 :    function compute_rho_form_of_d_v_div_r_face_opt_time_center(s, k, ierr) result(d_v_div_r) ! s^-1
     550              :       type(star_info), pointer :: s
     551              :       integer, intent(in)  :: k
     552              :       integer, intent(out) :: ierr
     553              :       type(auto_diff_real_star_order1) :: d_v_div_r
     554              :       type(auto_diff_real_star_order1) :: r_face, rho_face, v_face, dlnrho_dt
     555            0 :       real(dp) :: dm_bar, alfa, beta
     556            0 :       ierr = 0
     557              : 
     558            0 :       r_face = wrap_opt_time_center_r_00(s, k)
     559            0 :       rho_face = get_rho_face(s, k)
     560            0 :       v_face = wrap_opt_time_center_v_00(s, k)   ! face-centered velocity
     561            0 :       if (k >= 2) then
     562            0 :          dm_bar = 0.5d0*(s% dm(k) + s% dm(k-1))
     563            0 :          call get_TDC_alfa_beta_face_weights(s, k, alfa, beta)
     564            0 :          dlnrho_dt = (alfa*wrap_dxh_lnd(s, k) + beta*shift_m1(wrap_dxh_lnd(s, k-1)))/s%dt    ! (∂/∂t)lnρ
     565              :       else
     566            0 :          dm_bar = 0.5d0*s% dm(k)
     567            0 :          dlnrho_dt = 0.5d0*wrap_dxh_lnd(s, k)/s%dt    ! (∂/∂t)lnρ
     568              :       end if
     569              : 
     570              :       ! density form
     571            0 :       d_v_div_r = -dm_bar/(4d0*pi*rho_face)*(dlnrho_dt/pow3(r_face) + 3d0*v_face/pow4(r_face))
     572              : 
     573              :       ! dm_bar*(1/r * du/dm - U/4/pi/rho/r^4), more sensitive to geometry
     574              :       !d_v_div_r = ((wrap_opt_time_center_u_m1(s,k) - wrap_opt_time_center_u_00(s,k)) - dm_bar*v_face/(4d0*pi*rho_face*pow3(r_face)))/r_face
     575              : 
     576            0 :    end function compute_rho_form_of_d_v_div_r_face_opt_time_center
     577              : 
     578            0 :    function compute_d_v_div_r_face(s, k, ierr) result(d_v_div_r)  ! s^-1
     579              :       type(star_info), pointer :: s
     580              :       integer, intent(in) :: k
     581              :       type(auto_diff_real_star_order1) :: d_v_div_r
     582              :       integer, intent(out) :: ierr
     583              :       type(auto_diff_real_star_order1) :: v_00, v_m1, r_00, r_m1, term1, term2
     584              :       logical :: dbg
     585              :       include 'formats'
     586            0 :       ierr = 0
     587            0 :       dbg = .false.
     588              : 
     589            0 :      if (s% v_flag) then
     590            0 :          v_00 = 0.5d0*(wrap_v_00(s, k) + wrap_v_p1(s, k))
     591            0 :          v_m1 = 0.5d0*(wrap_v_00(s, k) + wrap_v_m1(s, k))
     592            0 :      else if(s% u_flag) then
     593            0 :          v_00 = wrap_u_00(s,k)
     594            0 :          v_m1 = wrap_u_m1(s,k)
     595              :       end if
     596              : 
     597            0 :       if (s% v_flag) then
     598            0 :          r_00 = 0.5d0*(wrap_r_00(s, k) + wrap_r_p1(s, k))
     599            0 :          r_m1 = 0.5d0*(wrap_r_00(s, k) + wrap_r_m1(s, k))
     600            0 :       else if(s% u_flag) then ! stagger r for u_flag to retain tridiagonality.
     601            0 :          r_00 = wrap_r_00(s, k)
     602            0 :          r_m1 = wrap_r_m1(s, k)
     603              :       end if
     604              : 
     605            0 :       if (r_00%val == 0d0) r_00 = 1d0
     606            0 :       if (r_m1%val == 0d0) r_m1 = 1d0
     607            0 :       d_v_div_r = v_m1/r_m1 - v_00/r_00 ! units s^-1
     608              : 
     609              :       ! Debugging output to trace values
     610              :       if (dbg .and. k == -63) then
     611              :          write (*, *) 'test d_v_div_r, k:', k
     612              :          write (*, *) 'v_00:', v_00%val, 'v_p1:', v_m1%val
     613              :          write (*, *) 'r_00:', r_00%val, 'r_p1:', r_m1%val
     614              :          write (*, *) 'd_v_div_r:', d_v_div_r%val
     615              :       end if
     616            0 :    end function compute_d_v_div_r_face
     617              : 
     618            0 :    function compute_d_v_div_r_opt_time_center_face(s, k, ierr) result(d_v_div_r)  ! s^-1
     619              :       type(star_info), pointer :: s
     620              :       integer, intent(in) :: k
     621              :       type(auto_diff_real_star_order1) :: d_v_div_r
     622              :       integer, intent(out) :: ierr
     623              :       type(auto_diff_real_star_order1) :: v_00, v_m1, r_00, r_m1, term1, term2
     624              :       logical :: dbg
     625              :       include 'formats'
     626            0 :       ierr = 0
     627            0 :       dbg = .false.
     628              : 
     629            0 :      if (s% v_flag) then
     630            0 :          v_00 = 0.5d0 *(wrap_opt_time_center_v_00(s, k) + wrap_opt_time_center_v_p1(s, k))
     631            0 :          v_m1 = 0.5d0*(wrap_opt_time_center_v_00(s, k) + wrap_opt_time_center_v_m1(s, k))
     632            0 :      else if(s% u_flag) then
     633            0 :          v_00 = wrap_opt_time_center_u_00(s,k)
     634            0 :          v_m1 = wrap_opt_time_center_u_m1(s,k)
     635              :       end if
     636              : 
     637            0 :       if (s% v_flag) then
     638            0 :          r_00 = 0.5d0*(wrap_opt_time_center_r_00(s, k) + wrap_opt_time_center_r_p1(s, k))
     639            0 :          r_m1 = 0.5d0*(wrap_opt_time_center_r_00(s, k) + wrap_opt_time_center_r_m1(s, k))
     640            0 :       else if(s% u_flag) then ! stagger r for u_flag to retain tridiagonality.
     641            0 :          r_00 = wrap_opt_time_center_r_00(s, k)
     642            0 :          r_m1 = wrap_opt_time_center_r_m1(s, k)
     643              :       end if
     644              : 
     645            0 :       if (r_00%val == 0d0) r_00 = 1d0
     646            0 :       if (r_m1%val == 0d0) r_m1 = 1d0
     647            0 :       d_v_div_r = v_m1/r_m1 - v_00/r_00 ! units s^-1
     648              : 
     649              :       ! Debugging output to trace values
     650              :       if (dbg .and. k == -63) then
     651              :          write (*, *) 'test d_v_div_r, k:', k
     652              :          write (*, *) 'v_00:', v_00%val, 'v_p1:', v_m1%val
     653              :          write (*, *) 'r_00:', r_00%val, 'r_p1:', r_m1%val
     654              :          write (*, *) 'd_v_div_r:', d_v_div_r%val
     655              :       end if
     656            0 :    end function compute_d_v_div_r_opt_time_center_face
     657              : 
     658              : end module tdc_hydro
        

Generated by: LCOV version 2.0-1