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

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2020  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 hydro_rsp2
      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 :: do1_rsp2_L_eqn
      34              :       public :: do1_turbulent_energy_eqn
      35              :       public :: do1_rsp2_Hp_eqn
      36              :       public :: compute_Eq_cell
      37              :       public :: compute_Uq_face
      38              :       public :: set_RSP2_vars
      39              :       public :: Hp_face_for_rsp2_val
      40              :       public :: Hp_face_for_rsp2_eqn, set_etrb_start_vars
      41              :       public :: RSP2_adjust_vars_before_call_solver
      42              :       public :: get_RSP2_alfa_beta_face_weights
      43              : 
      44              :       real(dp), parameter :: &
      45              :          x_ALFAP = 2.d0/3.d0, &  ! Ptrb
      46              :          x_ALFAS = (1.d0/2.d0)*sqrt_2_div_3, &  ! PII_face and Lc
      47              :          x_ALFAC = (1.d0/2.d0)*sqrt_2_div_3, &  ! Lc
      48              :          x_CEDE  = (8.d0/3.d0)*sqrt_2_div_3, &  ! DAMP
      49              :          x_GAMMAR = 2.d0*sqrt(3.d0)  ! DAMPR
      50              : 
      51              :       contains
      52              : 
      53            0 :       subroutine set_RSP2_vars(s,ierr)
      54              :          type (star_info), pointer :: s
      55              :          integer, intent(out) :: ierr
      56              :          type(auto_diff_real_star_order1) :: x
      57              :          integer :: k, op_err
      58              :          include 'formats'
      59            0 :          ierr = 0
      60            0 :          op_err = 0
      61            0 :          !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
      62              :          do k=1,s%nz
      63              :             ! Hp_face(k) <= 0 means it needs to be set.  e.g., after read file
      64              :             if (s% Hp_face(k) <= 0) then
      65              :                s% Hp_face(k) = get_scale_height_face_val(s,k)
      66              :                s% xh(s% i_Hp,k) = s% Hp_face(k)
      67              :             end if
      68              :             x = compute_Y_face(s, k, op_err)
      69              :             if (op_err /= 0) ierr = op_err
      70              :             x = compute_PII_face(s, k, op_err)
      71              :             if (op_err /= 0) ierr = op_err
      72              :             !Pvsc           skip?
      73              :          end do
      74              :          !$OMP END PARALLEL DO
      75            0 :          if (ierr /= 0) then
      76            0 :             if (s% report_ierr) write(*,2) 'failed in set_RSP2_vars loop 1', s% model_number
      77            0 :             return
      78              :          end if
      79            0 :          !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
      80              :          do k=1,s% nz
      81              :             x = compute_Chi_cell(s, k, op_err)
      82              :             if (op_err /= 0) ierr = op_err
      83              :             x = compute_Eq_cell(s, k, op_err)
      84              :             if (op_err /= 0) ierr = op_err
      85              :             x = compute_C(s, k, op_err)  ! COUPL
      86              :             if (op_err /= 0) ierr = op_err
      87              :             x = compute_L_face(s, k, op_err)  ! Lr, Lt, Lc
      88              :             if (op_err /= 0) ierr = op_err
      89              :          end do
      90              :          !$OMP END PARALLEL DO
      91            0 :          if (ierr /= 0) then
      92            0 :             if (s% report_ierr) write(*,2) 'failed in set_RSP2_vars loop 2', s% model_number
      93            0 :             return
      94              :          end if
      95            0 :          do k = 1, s% RSP2_num_outermost_cells_forced_nonturbulent
      96            0 :             s% Eq(k) = 0d0; s% Eq_ad(k) = 0d0
      97            0 :             s% Chi(k) = 0d0; s% Chi_ad(k) = 0d0
      98            0 :             s% COUPL(k) = 0d0; s% COUPL_ad(k) = 0d0
      99              :             !s% Ptrb(k) = 0d0;
     100            0 :             s% Lc(k) = 0d0; s% Lc_ad(k) = 0d0
     101            0 :             s% Lt(k) = 0d0; s% Lt_ad(k) = 0d0
     102              :          end do
     103            0 :          do k = s% nz + 1 - int(s% nz/s% RSP2_nz_div_IBOTOM) , s% nz
     104            0 :             s% Eq(k) = 0d0; s% Eq_ad(k) = 0d0
     105            0 :             s% Chi(k) = 0d0; s% Chi_ad(k) = 0d0
     106            0 :             s% COUPL(k) = 0d0; s% COUPL_ad(k) = 0d0
     107              :             !s% Ptrb(k) = 0d0;
     108            0 :             s% Lc(k) = 0d0; s% Lc_ad(k) = 0d0
     109            0 :             s% Lt(k) = 0d0; s% Lt_ad(k) = 0d0
     110              :          end do
     111              :       end subroutine set_RSP2_vars
     112              : 
     113              : 
     114            0 :       subroutine do1_rsp2_L_eqn(s, k, nvar, ierr)
     115              :          use star_utils, only: save_eqn_residual_info
     116              :          type (star_info), pointer :: s
     117              :          integer, intent(in) :: k, nvar
     118              :          integer, intent(out) :: ierr
     119              :          type(auto_diff_real_star_order1) ::  &
     120              :             L_expected, L_actual,resid
     121            0 :          real(dp) :: scale, residual, L_start_max
     122              :          logical :: test_partials
     123              :          include 'formats'
     124              : 
     125              :          !test_partials = (k == s% solver_test_partials_k)
     126            0 :          test_partials = .false.
     127            0 :          if (.not. s% RSP2_flag) then
     128            0 :             ierr = -1
     129            0 :             return
     130              :          end if
     131              : 
     132            0 :          ierr = 0
     133              :          !L_expected = compute_L_face(s, k, ierr)
     134              :          !if (ierr /= 0) return
     135            0 :          L_expected = s% Lr_ad(k) + s% Lc_ad(k) + s% Lt_ad(k)
     136            0 :          L_actual = wrap_L_00(s, k)
     137            0 :          L_start_max = maxval(s% L_start(1:s% nz))
     138            0 :          scale = 1d0/L_start_max
     139            0 :          if (is_bad(scale)) then
     140            0 :             write(*,2) 'do1_rsp2_L_eqn scale', k, scale
     141            0 :             call mesa_error(__FILE__,__LINE__,'do1_rsp2_L_eqn')
     142              :          end if
     143            0 :          resid = (L_expected - L_actual)*scale
     144              : 
     145            0 :          residual = resid%val
     146            0 :          s% equ(s% i_equL, k) = residual
     147              :          if (test_partials) then
     148              :             s% solver_test_partials_val = residual
     149              :          end if
     150              : 
     151            0 :          call save_eqn_residual_info(s, k, nvar, s% i_equL, resid, 'do1_rsp2_L_eqn', ierr)
     152            0 :          if (ierr /= 0) return
     153              : 
     154              :          if (test_partials) then
     155              :             s% solver_test_partials_var = s% i_lnR
     156              :             s% solver_test_partials_dval_dx = resid%d1Array(i_lnR_00)
     157              :             write(*,4) 'do1_rsp2_L_eqn', s% solver_test_partials_var
     158              :          end if
     159            0 :       end subroutine do1_rsp2_L_eqn
     160              : 
     161              : 
     162            0 :       subroutine do1_rsp2_Hp_eqn(s, k, nvar, ierr)
     163            0 :          use star_utils, only: save_eqn_residual_info
     164              :          type (star_info), pointer :: s
     165              :          integer, intent(in) :: k, nvar
     166              :          integer, intent(out) :: ierr
     167              :          type(auto_diff_real_star_order1) ::  &
     168              :             Hp_expected, Hp_actual,resid
     169            0 :          real(dp) :: residual, Hp_start
     170              :          logical :: test_partials
     171              :          include 'formats'
     172              :          !test_partials = (k == s% solver_test_partials_k)
     173            0 :          test_partials = .false.
     174              : 
     175            0 :          if (.not. s% RSP2_flag) then
     176            0 :             ierr = -1
     177            0 :             return
     178              :          end if
     179              : 
     180              :          ierr = 0
     181            0 :          Hp_expected = Hp_face_for_rsp2_eqn(s, k, ierr)
     182            0 :          if (ierr /= 0) return
     183            0 :          Hp_actual = wrap_Hp_00(s, k)
     184            0 :          Hp_start = s% Hp_face_start(k)
     185            0 :          resid = (Hp_expected - Hp_actual)/max(Hp_expected,Hp_actual)
     186              : 
     187            0 :          residual = resid%val
     188            0 :          s% equ(s% i_equ_Hp, k) = residual
     189              :          if (test_partials) then
     190              :             s% solver_test_partials_val = residual
     191              :          end if
     192              : 
     193            0 :          if (residual > 1d3) then
     194            0 :          !$omp critical (hydro_rsp2_1)
     195            0 :             write(*,2) 'residual', k, residual
     196            0 :             write(*,2) 'Hp_expected', k, Hp_expected%val
     197            0 :             write(*,2) 'Hp_actual', k, Hp_actual%val
     198            0 :             call mesa_error(__FILE__,__LINE__,'do1_rsp2_Hp_eqn')
     199              :          !$omp end critical (hydro_rsp2_1)
     200              :          end if
     201              : 
     202            0 :          call save_eqn_residual_info(s, k, nvar, s% i_equ_Hp, resid, 'do1_rsp2_Hp_eqn', ierr)
     203            0 :          if (ierr /= 0) return
     204              : 
     205              :          if (test_partials) then
     206              :             s% solver_test_partials_var = s% i_lnR
     207              :             s% solver_test_partials_dval_dx = resid%d1Array(i_lnR_00)
     208              :             write(*,4) 'do1_rsp2_Hp_eqn', s% solver_test_partials_var
     209              :          end if
     210              : 
     211            0 :       end subroutine do1_rsp2_Hp_eqn
     212              : 
     213              : 
     214            0 :       real(dp) function Hp_face_for_rsp2_val(s, k, ierr) result(Hp_face)  ! cm
     215              :          type (star_info), pointer :: s
     216              :          integer, intent(in) :: k
     217              :          integer, intent(out) :: ierr
     218              :          type(auto_diff_real_star_order1) :: Hp_face_ad
     219              :          ierr = 0
     220            0 :          Hp_face_ad = Hp_face_for_rsp2_eqn(s, k, ierr)
     221            0 :          if (ierr /= 0) return
     222            0 :          Hp_face = Hp_face_ad%val
     223            0 :       end function Hp_face_for_rsp2_val
     224              : 
     225              : 
     226            0 :       function Hp_face_for_rsp2_eqn(s, k, ierr) result(Hp_face)  ! cm
     227              :          type (star_info), pointer :: s
     228              :          integer, intent(in) :: k
     229              :          integer, intent(out) :: ierr
     230              :          type(auto_diff_real_star_order1) :: Hp_face
     231              :          type(auto_diff_real_star_order1) :: &
     232              :             rho_face, area, dlnPeos, &
     233              :             r_00, Peos_00, d_00, Peos_m1, d_m1, Peos_div_rho, &
     234              :             d_face, Peos_face, alt_Hp_face, A
     235            0 :          real(dp) :: alfa, beta
     236              :          include 'formats'
     237            0 :          ierr = 0
     238            0 :          if (k > s% nz) then
     239            0 :             Hp_face = 1d0  ! not used
     240            0 :             return
     241              :          end if
     242            0 :          if (k > 1 .and. .not. s% RSP2_assume_HSE) then
     243            0 :             call get_RSP2_alfa_beta_face_weights(s, k, alfa, beta)
     244            0 :             rho_face = alfa*wrap_d_00(s,k) + beta*wrap_d_m1(s,k)
     245            0 :             area = 4d0*pi*pow2(wrap_r_00(s,k))
     246            0 :             dlnPeos = wrap_lnPeos_m1(s,k) - wrap_lnPeos_00(s,k)
     247            0 :             Hp_face = -s% dm_bar(k)/(area*rho_face*dlnPeos)
     248              :          else
     249            0 :             r_00 = wrap_r_00(s, k)  ! not time-centered in RSP
     250            0 :             d_00 = wrap_d_00(s, k)
     251            0 :             Peos_00 = wrap_Peos_00(s, k)
     252            0 :             if (k == 1) then
     253            0 :                Peos_div_rho = Peos_00/d_00
     254            0 :                Hp_face = pow2(r_00)*Peos_div_rho/(s% cgrav(k)*s% m(k))
     255              :             else
     256            0 :                d_m1 = wrap_d_m1(s, k)
     257            0 :                Peos_m1 = wrap_Peos_m1(s, k)
     258            0 :                call get_RSP2_alfa_beta_face_weights(s, k, alfa, beta)
     259            0 :                Peos_div_rho = alfa*Peos_00/d_00 + beta*Peos_m1/d_m1
     260            0 :                Hp_face = pow2(r_00)*Peos_div_rho/(s% cgrav(k)*s% m(k))
     261            0 :                if (k==-104) then
     262            0 :                   write(*,3) 'RSP2 Hp P_div_rho Pdrho_00 Pdrho_m1', k, s% solver_iter, &
     263            0 :                      Hp_face%val, Peos_div_rho%val, Peos_00%val/d_00%val, Peos_m1%val/d_m1%val
     264              :                   !write(*,3) 'RSP2 Hp r2_div_Gm r_start r', k, s% solver_iter, &
     265              :                   !   Hp_face%val, pow2(r_00%val)/(s% cgrav(k)*s% m(k)), &
     266              :                   !   s% r_start(k), r_00%val
     267              :                end if
     268            0 :                if (s% alt_scale_height_flag) then
     269            0 :                   call mesa_error(__FILE__,__LINE__,'Hp_face_for_rsp2_eqn: cannot use alt_scale_height_flag')
     270              :                   ! consider sound speed*hydro time scale as an alternative scale height
     271            0 :                   d_face = alfa*d_00 + beta*d_m1
     272            0 :                   Peos_face = alfa*Peos_00 + beta*Peos_m1
     273            0 :                   alt_Hp_face = sqrt(Peos_face/s% cgrav(k))/d_face
     274            0 :                   if (alt_Hp_face%val < Hp_face%val) then  ! blend
     275            0 :                      A = pow2(alt_Hp_face/Hp_face)  ! 0 <= A%val < 1
     276            0 :                      Hp_face = A*Hp_face + (1d0 - A)*alt_Hp_face
     277              :                   end if
     278              :                end if
     279              :             end if
     280              :          end if
     281            0 :       end function Hp_face_for_rsp2_eqn
     282              : 
     283              : 
     284            0 :       subroutine do1_turbulent_energy_eqn(s, k, nvar, ierr)
     285              :          use star_utils, only: set_energy_eqn_scal, save_eqn_residual_info
     286              :          type (star_info), pointer :: s
     287              :          integer, intent(in) :: k, nvar
     288              :          integer, intent(out) :: ierr
     289              :          ! for OLD WAY
     290              :          type(auto_diff_real_star_order1) :: &
     291              :             d_turbulent_energy_ad, Ptrb_dV_ad, dt_C_ad, dt_Eq_ad
     292              :          type(auto_diff_real_star_order1) :: w_00
     293              :          type(auto_diff_real_star_order1) :: tst, resid_ad, dt_dLt_dm_ad
     294              :          type(accurate_auto_diff_real_star_order1) :: esum_ad
     295              :          logical :: non_turbulent_cell, test_partials
     296            0 :          real(dp) :: residual, scal
     297              :          include 'formats'
     298              :          !test_partials = (k == s% solver_test_partials_k)
     299            0 :          test_partials = .false.
     300              : 
     301            0 :          ierr = 0
     302            0 :          w_00 = wrap_w_00(s,k)
     303              : 
     304              :          non_turbulent_cell = &
     305              :             s% mixing_length_alpha == 0d0 .or. &
     306              :             k <= s% RSP2_num_outermost_cells_forced_nonturbulent .or. &
     307            0 :             k > s% nz - int(s% nz/s% RSP2_nz_div_IBOTOM)
     308            0 :          if (.not. s% RSP2_flag) then
     309            0 :             resid_ad = w_00 - s% w_start(k)  ! just hold w constant when not using RSP2
     310            0 :          else if (non_turbulent_cell) then
     311            0 :             resid_ad = w_00/s% csound(k)  ! make w = 0
     312              :          else
     313            0 :             call setup_d_turbulent_energy(ierr); if (ierr /= 0) return  ! erg g^-1 = cm^2 s^-2
     314            0 :             call setup_Ptrb_dV_ad(ierr); if (ierr /= 0) return  ! erg g^-1
     315            0 :             call setup_dt_dLt_dm_ad(ierr); if (ierr /= 0) return  ! erg g^-1
     316            0 :             call setup_dt_C_ad(ierr); if (ierr /= 0) return  ! erg g^-1
     317            0 :             call setup_dt_Eq_ad(ierr); if (ierr /= 0) return  ! erg g^-1
     318            0 :             call set_energy_eqn_scal(s, k, scal, ierr); if (ierr /= 0) return  ! 1/(erg g^-1 s^-1)
     319              :             ! sum terms in esum_ad using accurate_auto_diff_real_star_order1
     320            0 :             esum_ad = d_turbulent_energy_ad + Ptrb_dV_ad + dt_dLt_dm_ad - dt_C_ad - dt_Eq_ad  ! erg g^-1
     321            0 :             resid_ad = esum_ad
     322              : 
     323            0 :             if (k==-35 .and. s% solver_iter == 1) then
     324            0 :                   write(*,3) 'RSP2 w dEt PdV dtC dtEq', k, s% solver_iter, &
     325            0 :                      w_00%val, d_turbulent_energy_ad%val, Ptrb_dV_ad%val, dt_C_ad%val, dt_Eq_ad%val
     326              :             end if
     327              : 
     328            0 :             resid_ad = resid_ad*scal/s%dt  ! to make residual unitless, must cancel out the dt in scal
     329              : 
     330              :          end if
     331              : 
     332            0 :          residual = resid_ad%val
     333            0 :          s% equ(s% i_detrb_dt, k) = residual
     334              : 
     335              :          if (test_partials) then
     336              :             tst = residual
     337              :             s% solver_test_partials_val = tst%val
     338              :             if (s% solver_iter == 12) &
     339              :                write(*,*) 'do1_turbulent_energy_eqn', s% solver_test_partials_var, s% lnd(k), tst%val
     340              :          end if
     341              : 
     342            0 :          call save_eqn_residual_info(s, k, nvar, s% i_detrb_dt, resid_ad, 'do1_turbulent_energy_eqn', ierr)
     343            0 :          if (ierr /= 0) return
     344              : 
     345            0 :          if (test_partials) then
     346              :             s% solver_test_partials_var = s% i_lnd
     347              :             s% solver_test_partials_dval_dx = tst%d1Array(i_lnd_00)     ! xi0 good , xi1 partial 0, xi2 good.  Af horrible.'
     348              :             write(*,*) 'do1_turbulent_energy_eqn', s% solver_test_partials_var, s% lnd(k)/ln10, tst%val
     349              :          end if
     350              : 
     351              :          contains
     352              : 
     353            0 :          subroutine setup_d_turbulent_energy(ierr)  ! erg g^-1
     354              :             integer, intent(out) :: ierr
     355            0 :             ierr = 0
     356            0 :             d_turbulent_energy_ad = wrap_etrb_00(s,k) - get_etrb_start(s,k)
     357            0 :          end subroutine setup_d_turbulent_energy
     358              : 
     359              :          ! Ptrb_dV_ad = Ptrb_ad*dV_ad
     360            0 :          subroutine setup_Ptrb_dV_ad(ierr)  ! erg g^-1
     361              :             use star_utils, only: calc_Ptrb_ad_tw
     362              :             integer, intent(out) :: ierr
     363              :             type(auto_diff_real_star_order1) :: Ptrb_ad, PT0, dV_ad, d_00
     364            0 :             call calc_Ptrb_ad_tw(s, k, Ptrb_ad, PT0, ierr)
     365            0 :             if (ierr /= 0) return
     366            0 :             d_00 = wrap_d_00(s,k)
     367            0 :             dV_ad = 1d0/d_00 - 1d0/s% rho_start(k)
     368            0 :             Ptrb_dV_ad = Ptrb_ad*dV_ad  ! erg cm^-3 cm^-3 g^-1 = erg g^-1
     369            0 :          end subroutine setup_Ptrb_dV_ad
     370              : 
     371            0 :          subroutine setup_dt_dLt_dm_ad(ierr)  ! erg g^-1
     372              :             integer, intent(out) :: ierr
     373              :             type(auto_diff_real_star_order1) :: Lt_00, Lt_p1
     374              :             real(dp) :: L_theta
     375              :             include 'formats'
     376            0 :             ierr = 0
     377            0 :             if (s% using_velocity_time_centering .and. &
     378              :                      s% include_L_in_velocity_time_centering) then
     379            0 :                L_theta = s% L_theta_for_velocity_time_centering
     380              :             else
     381            0 :                L_theta = 1d0
     382              :             end if
     383            0 :             Lt_00 = L_theta*s% Lt_ad(k) + (1d0 - L_theta)*s% Lt_start(k)
     384            0 :             if (k == s% nz) then
     385            0 :                Lt_p1 = 0d0
     386              :             else
     387            0 :                Lt_p1 = L_theta*shift_p1(s% Lt_ad(k+1)) + (1d0 - L_theta)*s% Lt_start(k+1)
     388            0 :                if (ierr /= 0) return
     389              :             end if
     390            0 :             dt_dLt_dm_ad = (Lt_00 - Lt_p1)*s%dt/s%dm(k)
     391            0 :          end subroutine setup_dt_dLt_dm_ad
     392              : 
     393            0 :          subroutine setup_dt_C_ad(ierr)  ! erg g^-1
     394              :             integer, intent(out) :: ierr
     395              :             type(auto_diff_real_star_order1) :: C
     396            0 :             C = s% COUPL_ad(k)  ! compute_C(s, k, ierr) ! erg g^-1 s^-1
     397            0 :             if (ierr /= 0) return
     398            0 :             dt_C_ad = s%dt*C
     399              :          end subroutine setup_dt_C_ad
     400              : 
     401            0 :          subroutine setup_dt_Eq_ad(ierr)  ! erg g^-1
     402              :             integer, intent(out) :: ierr
     403              :             type(auto_diff_real_star_order1) :: Eq_cell
     404            0 :             Eq_cell = s% Eq_ad(k)  ! compute_Eq_cell(s, k, ierr) ! erg g^-1 s^-1
     405            0 :             if (ierr /= 0) return
     406            0 :             dt_Eq_ad = s%dt*Eq_cell
     407              :          end subroutine setup_dt_Eq_ad
     408              : 
     409              :       end subroutine do1_turbulent_energy_eqn
     410              : 
     411              : 
     412            0 :       subroutine get_RSP2_alfa_beta_face_weights(s, k, alfa, beta)
     413              :          type (star_info), pointer :: s
     414              :          integer, intent(in) :: k
     415              :          real(dp), intent(out) :: alfa, beta
     416              :          ! face_value = alfa*cell_value(k) + beta*cell_value(k-1)
     417            0 :          if (k == 1) call mesa_error(__FILE__,__LINE__,'bad k==1 for get_RSP2_alfa_beta_face_weights')
     418            0 :          if (s% RSP2_use_mass_interp_face_values) then
     419            0 :             alfa = s% dq(k-1)/(s% dq(k-1) + s% dq(k))
     420            0 :             beta = 1d0 - alfa
     421              :          else
     422            0 :             alfa = 0.5d0
     423            0 :             beta = 0.5d0
     424              :          end if
     425            0 :       end subroutine get_RSP2_alfa_beta_face_weights
     426              : 
     427              : 
     428            0 :       function compute_Y_face(s, k, ierr) result(Y_face)  ! superadiabatic gradient [unitless]
     429              :          type (star_info), pointer :: s
     430              :          integer, intent(in) :: k
     431              :          integer, intent(out) :: ierr
     432              :          type(auto_diff_real_star_order1) :: Y_face
     433              :          type(auto_diff_real_star_order1) :: Hp_face, Y1, Y2, QQ_div_Cp_face, &
     434              :             r_00, d_00, Peos_00, Cp_00, T_00, chiT_00, chiRho_00, QQ_00, lnT_00, &
     435              :             r_m1, d_m1, Peos_m1, Cp_m1, T_m1, chiT_m1, chiRho_m1, QQ_m1, lnT_m1, &
     436              :             dlnT_dlnP, grad_ad_00, grad_ad_m1, grad_ad_face, dlnT, dlnP, alt_Y_face
     437            0 :          real(dp) :: dm_bar, alfa, beta
     438              :          include 'formats'
     439            0 :          ierr = 0
     440              : 
     441            0 :          if (k > s% nz) then
     442            0 :             Y_face = 0d0
     443            0 :             return
     444              :          end if
     445              : 
     446            0 :          if (k == 1 .or. s% mixing_length_alpha == 0d0) then
     447            0 :             Y_face = 0d0
     448            0 :             s% Y_face(k) = 0d0
     449            0 :             s% Y_face_ad(k) = 0d0
     450            0 :             return
     451              :          end if
     452              : 
     453            0 :          call get_RSP2_alfa_beta_face_weights(s, k, alfa, beta)
     454              : 
     455            0 :          if (s% RSP2_use_RSP_eqn_for_Y_face) then
     456              : 
     457            0 :             dm_bar = s% dm_bar(k)
     458            0 :             Hp_face = wrap_Hp_00(s,k)
     459            0 :             r_00 = wrap_r_00(s, k)
     460            0 :             d_00 = wrap_d_00(s, k)
     461            0 :             Peos_00 = wrap_Peos_00(s, k)
     462            0 :             Cp_00 = wrap_Cp_00(s, k)
     463            0 :             T_00 = wrap_T_00(s, k)
     464            0 :             chiT_00 = wrap_chiT_00(s, k)
     465            0 :             chiRho_00 = wrap_chiRho_00(s, k)
     466            0 :             QQ_00 = chiT_00/(d_00*T_00*chiRho_00)
     467            0 :             lnT_00 = wrap_lnT_00(s,k)
     468              : 
     469            0 :             r_m1 = wrap_r_m1(s, k)
     470            0 :             d_m1 = wrap_d_m1(s, k)
     471            0 :             Peos_m1 = wrap_Peos_m1(s, k)
     472            0 :             Cp_m1 = wrap_Cp_m1(s, k)
     473            0 :             T_m1 = wrap_T_m1(s, k)
     474            0 :             chiT_m1 = wrap_chiT_m1(s, k)
     475            0 :             chiRho_m1 = wrap_chiRho_m1(s, k)
     476            0 :             QQ_m1 = chiT_m1/(d_m1*T_m1*chiRho_m1)
     477            0 :             lnT_m1 = wrap_lnT_m1(s,k)
     478            0 :             QQ_div_Cp_face = alfa*QQ_00/Cp_00 + beta*QQ_m1/Cp_m1
     479              :             ! QQ units (g cm^-3 K)^-1 = g^-1 cm^3 K^-1
     480              :             ! Cp units erg g^-1 K^-1 = g cm^2 s^-2 g^-1 K^-1 = cm^2 s^-2 K^-1
     481              :             ! QQ/Cp units = (g^-1 cm^3 K^-1)/(cm^2 s^-2 K^-1)
     482              :             !  = g^-1 cm^3 K^-1 cm^-2 s^2 K
     483              :             !  = g^-1 cm s^2
     484              :             ! P units = erg cm^-3 = g cm^2 s^-2 cm^-3 = g cm^-1 s^-2
     485              :             ! QQ/Cp*P is unitless.
     486              : 
     487            0 :             Y1 = QQ_div_Cp_face*(Peos_m1 - Peos_00) - (lnT_m1 - lnT_00)
     488              :             ! Y1 unitless
     489              : 
     490            0 :             Y2 = 4d0*pi*pow2(r_00)*Hp_face*2d0/(1d0/d_00 + 1d0/d_m1)/dm_bar
     491              :             ! units = cm^2 cm / (cm^3 g^-1) / g
     492              :             !       = cm^2 cm cm^-3 g g^-1 = unitless
     493              : 
     494            0 :             Y_face = Y1*Y2  ! unitless
     495              : 
     496            0 :             if (k==-35) then
     497            0 :                write(*,3) 'RSP2 Y_face Y1 Y2', k, s% solver_iter, s% Y_face(k), Y1%val, Y2%val
     498            0 :                write(*,3) 'Peos', k, s% solver_iter, Peos_00%val
     499            0 :                write(*,3) 'Peos', k-1, s% solver_iter, Peos_m1%val
     500            0 :                write(*,3) 'QQ', k, s% solver_iter, QQ_00%val
     501            0 :                write(*,3) 'QQ', k-1, s% solver_iter, QQ_m1%val
     502            0 :                write(*,3) 'Cp', k, s% solver_iter, Cp_00%val
     503            0 :                write(*,3) 'Cp', k-1, s% solver_iter, Cp_m1%val
     504            0 :                write(*,3) 'lgT', k, s% solver_iter, lnT_00%val/ln10
     505            0 :                write(*,3) 'lgT', k-1, s% solver_iter, lnT_m1%val/ln10
     506            0 :                write(*,3) 'lgd', k, s% solver_iter, s% lnd(k)/ln10
     507            0 :                write(*,3) 'lgd', k-1, s% solver_iter, s% lnd(k-1)/ln10
     508              :                !call mesa_error(__FILE__,__LINE__,'compute_Y_face')
     509              :             end if
     510              : 
     511              :          else
     512              : 
     513            0 :             grad_ad_00 = wrap_grad_ad_00(s,k)
     514            0 :             grad_ad_m1 = wrap_grad_ad_m1(s,k)
     515            0 :             grad_ad_face = alfa*grad_ad_00 + beta*grad_ad_m1
     516            0 :             dlnT = wrap_lnT_m1(s,k) - wrap_lnT_00(s,k)
     517            0 :             dlnP = wrap_lnPeos_m1(s,k) - wrap_lnPeos_00(s,k)
     518            0 :             dlnT_dlnP = dlnT/dlnP
     519            0 :             if (is_bad(dlnT_dlnP%val)) then
     520            0 :                alt_Y_face = 0d0
     521            0 :             else if (s% use_Ledoux_criterion .and. s% calculate_Brunt_B) then
     522              :                ! gradL = grada + gradL_composition_term
     523            0 :                alt_Y_face = dlnT_dlnP - (grad_ad_face + s% gradL_composition_term(k))
     524              :             else
     525            0 :                alt_Y_face = dlnT_dlnP - grad_ad_face
     526              :             end if
     527            0 :             if (is_bad(alt_Y_face%val)) alt_Y_face = 0
     528            0 :             Y_face = alt_Y_face
     529              : 
     530              :          end if
     531              : 
     532            0 :          s% Y_face_ad(k) = Y_face
     533            0 :          s% Y_face(k) = Y_face%val
     534              : 
     535            0 :       end function compute_Y_face
     536              : 
     537              : 
     538            0 :       function compute_PII_face(s, k, ierr) result(PII_face)  ! ergs g^-1 K^-1 (like Cp)
     539              :          type (star_info), pointer :: s
     540              :          integer, intent(in) :: k
     541              :          type(auto_diff_real_star_order1) :: PII_face
     542              :          integer, intent(out) :: ierr
     543              :          type(auto_diff_real_star_order1) :: Cp_00, Cp_m1, Cp_face, Y_face
     544            0 :          real(dp) :: ALFAS_ALFA, alfa, beta
     545              :          include 'formats'
     546            0 :          ierr = 0
     547            0 :          if (k > s% nz) then
     548            0 :             PII_face = 0d0
     549            0 :             return
     550              :          end if
     551            0 :          if (k == 1 .or. s% mixing_length_alpha == 0d0 .or. &
     552              :                k == s% nz) then  ! just skip k == nz to be like RSP
     553            0 :             PII_face = 0d0
     554            0 :             s% PII(k) = 0d0
     555            0 :             s% PII_ad(k) = 0d0
     556            0 :             return
     557              :          end if
     558            0 :          Y_face = s% Y_face_ad(k)  ! compute_Y_face(s, k, ierr)
     559            0 :          if (ierr /= 0) return
     560            0 :          Cp_00 = wrap_Cp_00(s, k)
     561            0 :          Cp_m1 = wrap_Cp_m1(s, k)
     562            0 :          call get_RSP2_alfa_beta_face_weights(s, k, alfa, beta)
     563            0 :          Cp_face = alfa*Cp_00 + beta*Cp_m1  ! ergs g^-1 K^-1
     564            0 :          ALFAS_ALFA = x_ALFAS*s% mixing_length_alpha
     565            0 :          PII_face = ALFAS_ALFA*Cp_face*Y_face
     566            0 :          s% PII(k) = PII_face%val
     567            0 :          s% PII_ad(k) = PII_face
     568            0 :          if (k == -2 .and. s% PII(k) < 0d0) then
     569            0 :             write(*,2) 's% PII(k)', k, s% PII(k)
     570            0 :             write(*,2) 'Cp_face', k, Cp_face%val
     571            0 :             write(*,2) 'Y_face', k, Y_face%val
     572              :             !write(*,2) 'PII_face%val', k, PII_face%val
     573              :             !write(*,2) 'T_rho_face%val', k, T_rho_face%val
     574              :             !write(*,2) '', k,
     575              :             !write(*,2) '', k,
     576            0 :             call mesa_error(__FILE__,__LINE__,'compute_PII_face')
     577              :          end if
     578            0 :       end function compute_PII_face
     579              : 
     580              : 
     581            0 :       function compute_d_v_div_r(s, k, ierr) result(d_v_div_r)  ! s^-1
     582              :          type (star_info), pointer :: s
     583              :          integer, intent(in) :: k
     584              :          type(auto_diff_real_star_order1) :: d_v_div_r
     585              :          integer, intent(out) :: ierr
     586              :          type(auto_diff_real_star_order1) :: v_00, v_p1, r_00, r_p1
     587              :          include 'formats'
     588            0 :          ierr = 0
     589            0 :          v_00 = wrap_v_00(s,k)
     590            0 :          v_p1 = wrap_v_p1(s,k)
     591            0 :          r_00 = wrap_r_00(s,k)
     592            0 :          r_p1 = wrap_r_p1(s,k)
     593            0 :          if (r_p1%val == 0d0) r_p1 = 1d0
     594            0 :          d_v_div_r = v_00/r_00 - v_p1/r_p1  ! units s^-1
     595            0 :       end function compute_d_v_div_r
     596              : 
     597              : 
     598            0 :       function compute_d_v_div_r_opt_time_center(s, k, ierr) result(d_v_div_r)  ! s^-1
     599              :          type (star_info), pointer :: s
     600              :          integer, intent(in) :: k
     601              :          type(auto_diff_real_star_order1) :: d_v_div_r
     602              :          integer, intent(out) :: ierr
     603              :          type(auto_diff_real_star_order1) :: v_00, v_p1, r_00, r_p1
     604              :          include 'formats'
     605            0 :          ierr = 0
     606            0 :          v_00 = wrap_opt_time_center_v_00(s,k)
     607            0 :          v_p1 = wrap_opt_time_center_v_p1(s,k)
     608            0 :          r_00 = wrap_opt_time_center_r_00(s,k)
     609            0 :          r_p1 = wrap_opt_time_center_r_p1(s,k)
     610            0 :          if (r_p1%val == 0d0) r_p1 = 1d0
     611            0 :          d_v_div_r = v_00/r_00 - v_p1/r_p1  ! units s^-1
     612            0 :       end function compute_d_v_div_r_opt_time_center
     613              : 
     614              : 
     615            0 :       function wrap_Hp_cell(s, k) result(Hp_cell)  ! cm
     616              :          type (star_info), pointer :: s
     617              :          integer, intent(in) :: k
     618              :          type(auto_diff_real_star_order1) :: Hp_cell
     619            0 :          Hp_cell = 0.5d0*(wrap_Hp_00(s,k) + wrap_Hp_p1(s,k))
     620            0 :       end function wrap_Hp_cell
     621              : 
     622              : 
     623            0 :       function Hp_cell_for_Chi(s, k, ierr) result(Hp_cell)  ! cm
     624              :          type (star_info), pointer :: s
     625              :          integer, intent(in) :: k
     626              :          integer, intent(out) :: ierr
     627              :          type(auto_diff_real_star_order1) :: Hp_cell
     628              :          type(auto_diff_real_star_order1) :: d_00, Peos_00, rmid
     629            0 :          real(dp) :: mmid, cgrav_mid
     630              :          include 'formats'
     631            0 :          ierr = 0
     632              : 
     633            0 :          Hp_cell = wrap_Hp_cell(s, k)
     634            0 :          return
     635              : 
     636              :          d_00 = wrap_d_00(s, k)
     637              :          Peos_00 = wrap_Peos_00(s, k)
     638              :          if (k < s% nz) then
     639              :             rmid = 0.5d0*(wrap_r_00(s,k) + wrap_r_p1(s,k))
     640              :             mmid = 0.5d0*(s% m(k) + s% m(k+1))
     641              :             cgrav_mid = 0.5d0*(s% cgrav(k) + s% cgrav(k+1))
     642              :          else
     643              :             rmid = 0.5d0*(wrap_r_00(s,k) + s% r_center)
     644              :             mmid = 0.5d0*(s% m(k) + s% m_center)
     645              :             cgrav_mid = s% cgrav(k)
     646              :          end if
     647              :          Hp_cell = pow2(rmid)*Peos_00/(d_00*cgrav_mid*mmid)
     648              :          if (s% alt_scale_height_flag) then
     649              :             call mesa_error(__FILE__,__LINE__,'Hp_cell_for_Chi: cannot use alt_scale_height_flag')
     650              :          end if
     651              :       end function Hp_cell_for_Chi
     652              : 
     653              : 
     654            0 :       function compute_Chi_cell(s, k, ierr) result(Chi_cell)
     655              :          ! eddy viscosity energy (Kuhfuss 1986) [erg]
     656              :          type (star_info), pointer :: s
     657              :          integer, intent(in) :: k
     658              :          type(auto_diff_real_star_order1) :: Chi_cell
     659              :          integer, intent(out) :: ierr
     660              :          type(auto_diff_real_star_order1) :: &
     661              :             rho2, r6_cell, d_v_div_r, Hp_cell, w_00, d_00, r_00, r_p1
     662            0 :          real(dp) :: f, ALFAM_ALFA
     663              :          include 'formats'
     664            0 :          ierr = 0
     665            0 :          ALFAM_ALFA = s% RSP2_alfam*s% mixing_length_alpha
     666              :          if (ALFAM_ALFA == 0d0 .or. &
     667            0 :                k <= s% RSP2_num_outermost_cells_forced_nonturbulent .or. &
     668              :                k > s% nz - int(s% nz/s% RSP2_nz_div_IBOTOM)) then
     669            0 :             Chi_cell = 0d0
     670            0 :             if (k >= 1 .and. k <= s% nz) then
     671            0 :                s% Chi(k) = 0d0
     672            0 :                s% Chi_ad(k) = 0d0
     673              :             end if
     674              :          else
     675            0 :             Hp_cell = Hp_cell_for_Chi(s, k, ierr)
     676            0 :             if (ierr /= 0) return
     677            0 :             d_v_div_r = compute_d_v_div_r(s, k, ierr)
     678            0 :             if (ierr /= 0) return
     679            0 :             w_00 = wrap_w_00(s,k)
     680            0 :             d_00 = wrap_d_00(s,k)
     681            0 :             f = (16d0/3d0)*pi*ALFAM_ALFA/s% dm(k)
     682            0 :             rho2 = pow2(d_00)
     683            0 :             r_00 = wrap_r_00(s,k)
     684            0 :             r_p1 = wrap_r_p1(s,k)
     685            0 :             r6_cell = 0.5d0*(pow6(r_00) + pow6(r_p1))
     686            0 :             Chi_cell = f*rho2*r6_cell*d_v_div_r*Hp_cell*w_00
     687              :             ! units = g^-1 cm s^-1 g^2 cm^-6 cm^6 s^-1 cm
     688              :             !       = g cm^2 s^-2
     689              :             !       = erg
     690              :          end if
     691            0 :          s% Chi(k) = Chi_cell%val
     692            0 :          s% Chi_ad(k) = Chi_cell
     693              : 
     694            0 :       end function compute_Chi_cell
     695              : 
     696              : 
     697            0 :       function compute_Eq_cell(s, k, ierr) result(Eq_cell)  ! erg g^-1 s^-1
     698              :          type (star_info), pointer :: s
     699              :          integer, intent(in) :: k
     700              :          type(auto_diff_real_star_order1) :: Eq_cell
     701              :          integer, intent(out) :: ierr
     702              :          type(auto_diff_real_star_order1) :: d_v_div_r, Chi_cell
     703              :          include 'formats'
     704            0 :          ierr = 0
     705              :          if (s% mixing_length_alpha == 0d0 .or. &
     706            0 :              k <= s% RSP2_num_outermost_cells_forced_nonturbulent .or. &
     707              :              k > s% nz - int(s% nz/s% RSP2_nz_div_IBOTOM)) then
     708            0 :             Eq_cell = 0d0
     709            0 :             if (k >= 1 .and. k <= s% nz) s% Eq_ad(k) = 0d0
     710              :          else
     711            0 :             Chi_cell = s% Chi_ad(k)  ! compute_Chi_cell(s,k,ierr)
     712            0 :             if (ierr /= 0) return
     713            0 :             d_v_div_r = compute_d_v_div_r_opt_time_center(s, k, ierr)
     714            0 :             if (ierr /= 0) return
     715            0 :             Eq_cell = 4d0*pi*Chi_cell*d_v_div_r/s% dm(k)  ! erg s^-1 g^-1
     716              :          end if
     717            0 :          s% Eq(k) = Eq_cell%val
     718            0 :          s% Eq_ad(k) = Eq_cell
     719            0 :       end function compute_Eq_cell
     720              : 
     721              : 
     722            0 :       function compute_Uq_face(s, k, ierr) result(Uq_face)  ! cm s^-2, acceleration
     723              :          type (star_info), pointer :: s
     724              :          integer, intent(in) :: k
     725              :          type(auto_diff_real_star_order1) :: Uq_face
     726              :          integer, intent(out) :: ierr
     727              :          type(auto_diff_real_star_order1) :: Chi_00, Chi_m1, r_00
     728              :          include 'formats'
     729            0 :          ierr = 0
     730              :          if (s% mixing_length_alpha == 0d0 .or. &
     731            0 :              k <= s% RSP2_num_outermost_cells_forced_nonturbulent .or. &
     732              :              k > s% nz - int(s% nz/s% RSP2_nz_div_IBOTOM)) then
     733            0 :             Uq_face = 0d0
     734              :          else
     735            0 :             r_00 = wrap_opt_time_center_r_00(s,k)
     736            0 :             Chi_00 = s% Chi_ad(k)  ! compute_Chi_cell(s,k,ierr)
     737            0 :             if (k > 1) then
     738              :                !Chi_m1 = shift_m1(compute_Chi_cell(s,k-1,ierr))
     739            0 :                Chi_m1 = shift_m1(s% Chi_ad(k-1))
     740            0 :                if (ierr /= 0) return
     741              :             else
     742            0 :                Chi_m1 = 0d0
     743              :             end if
     744            0 :             Uq_face = 4d0*pi*(Chi_m1 - Chi_00)/(r_00*s% dm_bar(k))
     745              : 
     746            0 :             if (k==-56) then
     747            0 :                write(*,3) 'RSP2 Uq chi_m1 chi_00 r', k, s% solver_iter, &
     748            0 :                   Uq_face%val, Chi_m1%val, Chi_00%val, r_00%val
     749              :             end if
     750              : 
     751              :          end if
     752              :          ! erg g^-1 cm^-1 = g cm^2 s^-2 g^-1 cm^-1 = cm s^-2, acceleration
     753            0 :          s% Uq(k) = Uq_face%val
     754            0 :       end function compute_Uq_face
     755              : 
     756              : 
     757            0 :       function compute_Source(s, k, ierr) result(Source)  ! erg g^-1 s^-1
     758              :          type (star_info), pointer :: s
     759              :          integer, intent(in) :: k
     760              :          type(auto_diff_real_star_order1) :: Source
     761              :          ! source_div_w assumes RSP2_source_seed == 0
     762              :          integer, intent(out) :: ierr
     763              :          type(auto_diff_real_star_order1) :: &
     764              :             w_00, T_00, d_00, Peos_00, Cp_00, chiT_00, chiRho_00, QQ_00, &
     765              :             Hp_face_00, Hp_face_p1, PII_face_00, PII_face_p1, PII_div_Hp_cell, &
     766              :             P_QQ_div_Cp
     767              :          include 'formats'
     768            0 :          ierr = 0
     769            0 :          w_00 = wrap_w_00(s, k)
     770            0 :          T_00 = wrap_T_00(s, k)
     771            0 :          d_00 = wrap_d_00(s, k)
     772            0 :          Peos_00 = wrap_Peos_00(s, k)
     773            0 :          Cp_00 = wrap_Cp_00(s, k)
     774            0 :          chiT_00 = wrap_chiT_00(s, k)
     775            0 :          chiRho_00 = wrap_chiRho_00(s, k)
     776            0 :          QQ_00 = chiT_00/(d_00*T_00*chiRho_00)
     777              : 
     778            0 :          Hp_face_00 = wrap_Hp_00(s,k)
     779            0 :          PII_face_00 = s% PII_ad(k)  ! compute_PII_face(s, k, ierr)
     780            0 :          if (ierr /= 0) return
     781              : 
     782            0 :          if (k == s% nz) then
     783            0 :             PII_div_Hp_cell = PII_face_00/Hp_face_00
     784              :          else
     785            0 :             Hp_face_p1 = wrap_Hp_p1(s,k)
     786            0 :             if (ierr /= 0) return
     787              :             !PII_face_p1 = shift_p1(compute_PII_face(s, k+1, ierr))
     788            0 :             PII_face_p1 = shift_p1(s% PII_ad(k+1))
     789            0 :             if (ierr /= 0) return
     790            0 :             PII_div_Hp_cell = 0.5d0*(PII_face_00/Hp_face_00 + PII_face_p1/Hp_face_p1)
     791              :          end if
     792              : 
     793              :          ! Peos_00*QQ_00/Cp_00 = grad_ad if all perfect.
     794              :          !grad_ad_00 = wrap_grad_ad_00(s, k)
     795            0 :          P_QQ_div_Cp = Peos_00*QQ_00/Cp_00  ! use this to be same as RSP
     796            0 :          Source = (w_00 + s% RSP2_source_seed)*PII_div_Hp_cell*T_00*P_QQ_div_Cp
     797              : 
     798              :          ! PII units same as Cp = erg g^-1 K^-1
     799              :          ! P*QQ/Cp is unitless (see Y_face)
     800              :          ! Source units = (erg g^-1 K^-1) cm^-1 cm s^-1 K
     801              :          !     = erg g^-1 s^-1
     802              : 
     803            0 :          if (k==-109) then
     804            0 :             write(*,3) 'RSP2 Source w PII_div_Hp T_P_QQ_div_Cp', k, s% solver_iter, &
     805            0 :                Source%val, w_00%val, PII_div_Hp_cell%val, T_00%val*P_QQ_div_Cp% val
     806              :             !write(*,3) 'RSP2 PII_00 PII_p1 Hp_00 Hp_p1', k, s% solver_iter, &
     807              :             !   PII_face_00%val, PII_face_p1%val, Hp_face_00%val, Hp_face_p1%val
     808              :          end if
     809            0 :          s% SOURCE(k) = Source%val
     810              : 
     811            0 :       end function compute_Source
     812              : 
     813              : 
     814            0 :       function compute_D(s, k, ierr) result(D)  ! erg g^-1 s^-1
     815              :          type (star_info), pointer :: s
     816              :          integer, intent(in) :: k
     817              :          type(auto_diff_real_star_order1) :: D
     818              :          type(auto_diff_real_star_order1) :: dw3, w_00
     819              :          integer, intent(out) :: ierr
     820              :          type(auto_diff_real_star_order1) :: Hp_cell
     821              :          include 'formats'
     822            0 :          ierr = 0
     823            0 :          if (s% mixing_length_alpha == 0d0) then
     824            0 :             D = 0d0
     825              :          else
     826            0 :             Hp_cell = wrap_Hp_cell(s,k)
     827            0 :             w_00 = wrap_w_00(s,k)
     828            0 :             dw3 = pow3(w_00) - pow3(s% RSP2_w_min_for_damping)
     829            0 :             D = (s% RSP2_alfad*x_CEDE/s% mixing_length_alpha)*dw3/Hp_cell
     830              :             ! units cm^3 s^-3 cm^-1 = cm^2 s^-3 = erg g^-1 s^-1
     831              :          end if
     832            0 :          if (k==-50) then
     833            0 :             write(*,3) 'RSP2 DAMP w Hp_cell dw3', k, s% solver_iter, &
     834            0 :                D%val, w_00%val, Hp_cell%val, dw3% val
     835              :          end if
     836            0 :          s% DAMP(k) = D%val
     837            0 :       end function compute_D
     838              : 
     839              : 
     840            0 :       function compute_Dr(s, k, ierr) result(Dr)  ! erg g^-1 s^-1 = cm^2 s^-3
     841              :          type (star_info), pointer :: s
     842              :          integer, intent(in) :: k
     843              :          type(auto_diff_real_star_order1) :: Dr
     844              :          integer, intent(out) :: ierr
     845              :          type(auto_diff_real_star_order1) :: &
     846              :             w_00, T_00, d_00, Cp_00, kap_00, Hp_cell, POM2
     847            0 :          real(dp) :: gammar, alpha, POM
     848              :          include 'formats'
     849            0 :          ierr = 0
     850            0 :          alpha = s% mixing_length_alpha
     851            0 :          gammar = s% RSP2_alfar*x_GAMMAR
     852            0 :          if (gammar == 0d0) then
     853            0 :             Dr = 0d0
     854            0 :             s% DAMPR(k) = 0d0
     855            0 :             return
     856              :          end if
     857            0 :          w_00 = wrap_w_00(s,k)
     858            0 :          T_00 = wrap_T_00(s,k)
     859            0 :          d_00 = wrap_d_00(s,k)
     860            0 :          Cp_00 = wrap_Cp_00(s,k)
     861            0 :          kap_00 = wrap_kap_00(s,k)
     862            0 :          Hp_cell = wrap_Hp_cell(s,k)
     863            0 :          POM = 4d0*boltz_sigma*pow2(gammar/alpha)  ! erg cm^-2 K^-4 s^-1
     864            0 :          POM2 = pow3(T_00)/(pow2(d_00)*Cp_00*kap_00)
     865              :             ! K^3 / ((g cm^-3)^2 (erg g^-1 K^-1) (cm^2 g^-1))
     866              :             ! K^3 / (cm^-4 erg K^-1) = K^4 cm^4 erg^-1
     867            0 :          Dr = get_etrb(s,k)*POM*POM2/pow2(Hp_cell)
     868              :          ! (erg cm^-2 K^-4 s^-1) (K^4 cm^4 erg^-1) cm^2 s^-2 cm^-2
     869              :          ! cm^2 s^-3 = erg g^-1 s^-1
     870            0 :          s% DAMPR(k) = Dr%val
     871            0 :       end function compute_Dr
     872              : 
     873              : 
     874            0 :       function compute_C(s, k, ierr) result(C)  ! erg g^-1 s^-1
     875              :          type (star_info), pointer :: s
     876              :          integer, intent(in) :: k
     877              :          type(auto_diff_real_star_order1) :: C
     878              :          integer, intent(out) :: ierr
     879              :          type(auto_diff_real_star_order1) :: Source, D, Dr
     880              :          if (s% mixing_length_alpha == 0d0 .or. &
     881            0 :              k <= s% RSP2_num_outermost_cells_forced_nonturbulent .or. &
     882              :              k > s% nz - int(s% nz/s% RSP2_nz_div_IBOTOM)) then
     883            0 :             if (k >= 1 .and. k <= s% nz) then
     884            0 :                s% SOURCE(k) = 0d0
     885            0 :                s% DAMP(k) = 0d0
     886            0 :                s% DAMPR(k) = 0d0
     887            0 :                s% COUPL(k) = 0d0
     888            0 :                s% COUPL_ad(k) = 0d0
     889              :             end if
     890            0 :             C = 0d0
     891            0 :             return
     892              :          end if
     893            0 :          Source = compute_Source(s, k, ierr)
     894            0 :          if (ierr /= 0) return
     895            0 :          D = compute_D(s, k, ierr)
     896            0 :          if (ierr /= 0) return
     897            0 :          Dr = compute_Dr(s, k, ierr)
     898            0 :          if (ierr /= 0) return
     899            0 :          C = Source - D - Dr
     900            0 :          s% COUPL(k) = C%val
     901            0 :          s% COUPL_ad(k) = C
     902            0 :       end function compute_C
     903              : 
     904              : 
     905            0 :       function compute_L_face(s, k, ierr) result(L_face)  ! erg s^-1
     906              :          type (star_info), pointer :: s
     907              :          integer, intent(in) :: k
     908              :          type(auto_diff_real_star_order1) :: L_face
     909              :          integer, intent(out) :: ierr
     910              :          type(auto_diff_real_star_order1) :: Lr, Lc, Lt
     911            0 :          call compute_L_terms(s, k, L_face, Lr, Lc, Lt, ierr)
     912            0 :       end function compute_L_face
     913              : 
     914              : 
     915            0 :       subroutine compute_L_terms(s, k, L, Lr, Lc, Lt, ierr)
     916              :          type (star_info), pointer, intent(in) :: s
     917              :          integer, intent(in) :: k
     918              :          type(auto_diff_real_star_order1), intent(out) :: L, Lr, Lc, Lt
     919              :          integer, intent(out) :: ierr
     920              :          include 'formats'
     921            0 :          ierr = 0
     922            0 :          if (k > s% nz) then
     923            0 :             L = 0d0
     924            0 :             L%val = s% L_center
     925            0 :             Lr = 0d0
     926            0 :             Lc = 0d0
     927            0 :             Lt = 0d0
     928            0 :             return
     929              :          end if
     930            0 :          Lr = compute_Lr(s, k, ierr)
     931            0 :          if (ierr /= 0) return
     932            0 :          if (k == 1) then
     933            0 :             Lc = 0d0
     934            0 :             Lt = 0d0
     935              :          else
     936            0 :             Lc = compute_Lc(s, k, ierr)
     937            0 :             if (ierr /= 0) return
     938            0 :             Lt = compute_Lt(s, k, ierr)
     939            0 :             if (ierr /= 0) return
     940              :          end if
     941            0 :          L = Lr + Lc + Lt
     942            0 :          s% Lr_ad(k) = Lr
     943            0 :          s% Lc_ad(k) = Lc
     944            0 :          s% Lt_ad(k) = Lt
     945              :       end subroutine compute_L_terms
     946              : 
     947              : 
     948            0 :       function compute_Lr(s, k, ierr) result(Lr)  ! erg s^-1
     949              :          type (star_info), pointer :: s
     950              :          integer, intent(in) :: k
     951              :          type(auto_diff_real_star_order1) :: Lr
     952              :          integer, intent(out) :: ierr
     953              :          type(auto_diff_real_star_order1) :: &
     954              :             r_00, area, T_00, T400, Erad, T_m1, T4m1, &
     955              :             kap_00, kap_m1, kap_face, diff_T4_div_kap, BW, BK
     956            0 :          real(dp) :: alfa
     957              :          include 'formats'
     958            0 :          ierr = 0
     959            0 :          if (k > s% nz) then
     960            0 :             Lr = s% L_center
     961              :          else
     962            0 :             r_00 = wrap_r_00(s,k)  ! not time centered
     963            0 :             area = 4d0*pi*pow2(r_00)
     964            0 :             T_00 = wrap_T_00(s,k)
     965            0 :             T400 = pow4(T_00)
     966            0 :             if (k == 1) then  ! Lr(1) proportional to Erad in cell(1)
     967            0 :                Erad = crad * T400
     968            0 :                Lr = s% RSP2_Lsurf_factor * area * clight * Erad
     969            0 :                s% Lr(k) = Lr%val
     970            0 :                return
     971              :             end if
     972            0 :             T_m1 = wrap_T_m1(s,k)
     973            0 :             T4m1 = pow4(T_m1)
     974            0 :             alfa = s% dq(k-1)/(s% dq(k-1) + s% dq(k))
     975            0 :             kap_00 = wrap_kap_00(s,k)
     976            0 :             kap_m1 = wrap_kap_m1(s,k)
     977            0 :             kap_face = alfa*kap_00 + (1d0 - alfa)*kap_m1
     978            0 :             diff_T4_div_kap = (T4m1 - T400)/kap_face
     979              : 
     980            0 :             if (s% RSP2_use_Stellingwerf_Lr) then  ! RSP style
     981            0 :                BW = log(T4m1/T400)
     982            0 :                if (abs(BW%val) > 1d-20) then
     983            0 :                   BK = log(kap_m1/kap_00)
     984            0 :                   if (abs(1d0 - BK%val/BW%val) > 1d-15 .and. abs(BW%val - BK%val) > 1d-15) then
     985            0 :                      diff_T4_div_kap = (T4m1/kap_m1 - T400/kap_00)/(1d0 - BK/BW)
     986              :                   end if
     987              :                end if
     988              :             end if
     989            0 :             Lr = -crad*clight/3d0*diff_T4_div_kap*pow2(area)/s% dm_bar(k)
     990              :             ! units (erg cm^-3 K^-4) (cm s^-1) (K^4 cm^-2 g cm^4) g^-1 = erg s^-1
     991              : 
     992              :             !s% xtra1_array(k) = s% T_start(k)
     993              :             !s% xtra2_array(k) = T4m1%val - T400%val
     994              :             !s% xtra3_array(k) = kap_face%val
     995              :             !s% xtra4_array(k) = diff_T4_div_kap%val
     996              :             !s% xtra5_array(k) = Lr%val/Lsun
     997              :             !s% xtra6_array(k) = 1
     998              : 
     999              :          end if
    1000            0 :          s% Lr(k) = Lr%val
    1001            0 :       end function compute_Lr
    1002              : 
    1003              : 
    1004            0 :       function compute_Lc(s, k, ierr) result(Lc)  ! erg s^-1
    1005              :          type (star_info), pointer :: s
    1006              :          integer, intent(in) :: k
    1007              :          type(auto_diff_real_star_order1) :: Lc
    1008              :          integer, intent(out) :: ierr
    1009              :          type(auto_diff_real_star_order1) :: Lc_div_w_face
    1010            0 :          Lc = compute_Lc_terms(s, k, Lc_div_w_face, ierr)
    1011            0 :          s% Lc(k) = Lc%val
    1012            0 :       end function compute_Lc
    1013              : 
    1014              : 
    1015            0 :       function compute_Lc_terms(s, k, Lc_div_w_face, ierr) result(Lc)
    1016              :          type (star_info), pointer :: s
    1017              :          integer, intent(in) :: k
    1018              :          type(auto_diff_real_star_order1) :: Lc, Lc_div_w_face
    1019              :          integer, intent(out) :: ierr
    1020              :          type(auto_diff_real_star_order1) :: r_00, area, &
    1021              :             T_m1, T_00, d_m1, d_00, w_m1, w_00, T_rho_face, PII_face, w_face
    1022            0 :          real(dp) :: ALFAC, ALFAS, alfa, beta
    1023              :          include 'formats'
    1024            0 :          ierr = 0
    1025              :          if (s% mixing_length_alpha == 0d0 .or. &
    1026            0 :              k <= s% RSP2_num_outermost_cells_forced_nonturbulent .or. &
    1027              :              k > s% nz - int(s% nz/s% RSP2_nz_div_IBOTOM)) then
    1028            0 :             Lc = 0d0
    1029            0 :             Lc_div_w_face = 1
    1030            0 :             return
    1031              :          end if
    1032            0 :          r_00 = wrap_r_00(s, k)
    1033            0 :          area = 4d0*pi*pow2(r_00)
    1034            0 :          T_m1 = wrap_T_m1(s, k)
    1035            0 :          T_00 = wrap_T_00(s, k)
    1036            0 :          d_m1 = wrap_d_m1(s, k)
    1037            0 :          d_00 = wrap_d_00(s, k)
    1038            0 :          w_m1 = wrap_w_m1(s, k)
    1039            0 :          w_00 = wrap_w_00(s, k)
    1040            0 :          call get_RSP2_alfa_beta_face_weights(s, k, alfa, beta)
    1041            0 :          T_rho_face = alfa*T_00*d_00 + beta*T_m1*d_m1
    1042            0 :          PII_face = s% PII_ad(k)  ! compute_PII_face(s, k, ierr)
    1043            0 :          w_face = alfa*w_00 + beta*w_m1
    1044            0 :          ALFAC = x_ALFAC
    1045            0 :          ALFAS = x_ALFAS
    1046            0 :          Lc_div_w_face = area*(ALFAC/ALFAS)*T_rho_face*PII_face
    1047              :          ! units = cm^2 K g cm^-3 ergs g^-1 K^-1 = ergs cm^-1
    1048            0 :          Lc = w_face*Lc_div_w_face
    1049              :          ! units = cm s^-1 ergs cm^-1 = ergs s^-1
    1050            0 :          if (k == -458) then
    1051            0 :             write(*,2) 'Lc%val', k, Lc%val
    1052            0 :             write(*,2) 'w_face%val', k, w_face%val
    1053            0 :             write(*,2) 'Lc_div_w_face', k, Lc_div_w_face%val
    1054            0 :             write(*,2) 'PII_face%val', k, PII_face%val
    1055            0 :             write(*,2) 'T_rho_face%val', k, T_rho_face%val
    1056              :             !write(*,2) '', k,
    1057              :             !write(*,2) '', k,
    1058            0 :             call mesa_error(__FILE__,__LINE__,'compute_Lc_terms')
    1059              :          end if
    1060            0 :       end function compute_Lc_terms
    1061              : 
    1062              : 
    1063            0 :       function compute_Lt(s, k, ierr) result(Lt)  ! erg s^-1
    1064              :          type (star_info), pointer :: s
    1065              :          integer, intent(in) :: k
    1066              :          type(auto_diff_real_star_order1) :: Lt
    1067              :          integer, intent(out) :: ierr
    1068              :          type(auto_diff_real_star_order1) :: r_00, area2, d_m1, d_00, &
    1069              :             rho2_face, Hp_face, w_m1, w_00, w_face, etrb_m1, etrb_00
    1070            0 :          real(dp) :: alpha_alpha_t, alfa, beta
    1071              :          include 'formats'
    1072            0 :          ierr = 0
    1073            0 :          if (k > s% nz) then
    1074            0 :             Lt = 0d0
    1075            0 :             return
    1076              :          end if
    1077            0 :          alpha_alpha_t = s% mixing_length_alpha*s% RSP2_alfat
    1078              :          if (alpha_alpha_t == 0d0 .or. &
    1079            0 :              k <= s% RSP2_num_outermost_cells_forced_nonturbulent .or. &
    1080              :              k > s% nz - int(s% nz/s% RSP2_nz_div_IBOTOM)) then
    1081            0 :             Lt = 0d0
    1082            0 :             s% Lt(k) = 0d0
    1083            0 :             return
    1084              :          end if
    1085            0 :          r_00 = wrap_r_00(s,k)
    1086            0 :          area2 = pow2(4d0*pi*pow2(r_00))
    1087            0 :          d_m1 = wrap_d_m1(s,k)
    1088            0 :          d_00 = wrap_d_00(s,k)
    1089            0 :          call get_RSP2_alfa_beta_face_weights(s, k, alfa, beta)
    1090            0 :          rho2_face = alfa*pow2(d_00) + beta*pow2(d_m1)
    1091            0 :          w_m1 = wrap_w_m1(s,k)
    1092            0 :          w_00 = wrap_w_00(s,k)
    1093            0 :          w_face = alfa*w_00 + beta*w_m1
    1094            0 :          etrb_m1 = wrap_etrb_m1(s,k)
    1095            0 :          etrb_00 = wrap_etrb_00(s,k)
    1096            0 :          Hp_face = wrap_Hp_00(s,k)
    1097              :          ! Ft = - alpha_t * rho_face * alpha * Hp_face * w_face * detrb/dr (thesis eqn 2.44)
    1098              :          ! replace dr by dm_bar/(area*rho_face)
    1099              :          ! Ft = - alpha_alpha_t * rho_face * Hp_face * w_face * (area*rho_face) * detrb/dm_bar
    1100              :          ! Lt = area * Ft
    1101              :          ! Lt = -alpha_alpha_t * (area*rho_face)**2 * Hp_face * w_face * (etrb(k-1) - etrb(k))/dm_bar
    1102            0 :          Lt = - alpha_alpha_t * area2 * rho2_face * Hp_face * w_face * (etrb_m1 - etrb_00) / s% dm_bar(k)
    1103              :          ! units = (cm^4) (g^2 cm^-6) (cm) (cm s^-1) (ergs g^-1) g^-1 = erg s^-1
    1104            0 :          s% Lt(k) = Lt%val
    1105            0 :       end function compute_Lt
    1106              : 
    1107              : 
    1108            0 :       subroutine set_etrb_start_vars(s, ierr)
    1109              :          type (star_info), pointer :: s
    1110              :          integer, intent(out) :: ierr
    1111              :          integer :: k
    1112              :          type(auto_diff_real_star_order1) :: Y_face, Lt
    1113              :          include 'formats'
    1114            0 :          ierr = 0
    1115            0 :          do k=1,s%nz
    1116            0 :             Y_face = compute_Y_face(s, k, ierr)
    1117            0 :             if (ierr /= 0) return
    1118            0 :             s% Y_face_start(k) = Y_face%val
    1119            0 :             Lt = compute_Lt(s, k, ierr)
    1120            0 :             if (ierr /= 0) return
    1121            0 :             s% Lt_start(k) = Lt%val
    1122            0 :             s% w_start(k) = s% w(k)
    1123            0 :             s% Hp_face_start(k) = s% Hp_face(k)
    1124              :          end do
    1125              :       end subroutine set_etrb_start_vars
    1126              : 
    1127              : 
    1128            0 :       subroutine RSP2_adjust_vars_before_call_solver(s, ierr)  ! replaces check_omega in RSP
    1129              :          ! JAK OKRESLIC OMEGA DLA PIERWSZEJ ITERACJI
    1130              :          use micro, only: do_eos_for_cell
    1131              :          type (star_info), pointer :: s
    1132              :          integer, intent(out) :: ierr
    1133            0 :          real(dp) :: PII_div_Hp, QQ, SOURCE, Hp_cell, DAMP, POM, POM2, DAMPR, del, soln
    1134              :          !type(auto_diff_real_star_order1) :: x
    1135              :          integer :: k
    1136              :          include 'formats'
    1137            0 :          ierr = 0
    1138            0 :          if (s% mixing_length_alpha == 0d0) return
    1139              : 
    1140            0 :          !$OMP PARALLEL DO PRIVATE(k,PII_div_Hp,QQ,SOURCE,Hp_cell,DAMP,POM,POM2,DAMPR,del,soln) SCHEDULE(dynamic,2)
    1141              :          do k=s% RSP2_num_outermost_cells_forced_nonturbulent+1, &
    1142              :                s% nz - max(1,int(s% nz/s% RSP_nz_div_IBOTOM))
    1143              : 
    1144              :             if (s% w(k) > s% RSP2_w_min_for_damping) cycle
    1145              : 
    1146              :             PII_div_Hp = 0.5d0*(s% PII(k)/s% Hp_face(k) + s% PII(k+1)/s% Hp_face(k+1))
    1147              :             QQ = s% chiT(k)/(s% rho(k)*s% T(k)*s% chiRho(k))
    1148              :             SOURCE = PII_div_Hp*s% T(k)*s% Peos(k)*QQ/s% Cp(k)
    1149              : 
    1150              :             Hp_cell = 0.5d0*(s% Hp_face(k) + s% Hp_face(k+1))
    1151              :             DAMP = (s% RSP2_alfad*x_CEDE/s% mixing_length_alpha)/Hp_cell
    1152              : 
    1153              :             POM = 4d0*boltz_sigma*pow2(s% RSP2_alfar*x_GAMMAR/s% mixing_length_alpha)
    1154              :             POM2 = pow3(s% T(k))/(pow2(s% rho(k))*s% Cp(k)*s% opacity(k))
    1155              :             DAMPR = POM*POM2/pow2(Hp_cell)
    1156              : 
    1157              :             del = pow2(DAMPR) + 4d0*DAMP*SOURCE
    1158              : 
    1159              :             if (k==-35) then
    1160              :                write(*,2) 'del', k, del
    1161              :                write(*,2) 'DAMPR', k, DAMPR
    1162              :                write(*,2) 'DAMP', k, DAMP
    1163              :                write(*,2) 'SOURCE', k, SOURCE
    1164              :                write(*,2) 'POM', k, PII_div_Hp
    1165              :                write(*,2) 'POM2', k, s% T(k)*s% Peos(k)*QQ/s% Cp(k)
    1166              :                write(*,2) 's% Hp_face(k)', k, s% Hp_face(k)
    1167              :                write(*,2) 's% Hp_face(k+1)', k+1, s% Hp_face(k+1)
    1168              :                write(*,2) 's% PII(k)', k, s% PII(k)
    1169              :                write(*,2) 's% PII(k+1)', k+1, s% PII(k+1)
    1170              :                write(*,2) 's% Y_face(k)', k, s% Y_face(k)
    1171              :                write(*,2) 's% Y_face(k+1)', k+1, s% Y_face(k+1)
    1172              :             end if
    1173              : 
    1174              :             if (del < 0d0) cycle
    1175              :             soln = (-DAMPR + sqrt(del))/(2d0*DAMP)
    1176              :             if (k==-35) write(*,2) 'soln', k, soln
    1177              :             if (soln > 0d0) then
    1178              :                ! i tried soln = sqrt(soln) here. helps solver convergence, but hurts the model results.
    1179              :                if (s% RSP2_report_adjust_w) &
    1180              :                   write(*,3) 'RSP2_adjust_vars_before_call_solver w', k, s% model_number, s% w(k), soln
    1181              :                s% w(k) = soln
    1182              :             end if
    1183              : 
    1184              :          end do
    1185              :          !$OMP END PARALLEL DO
    1186            0 :       end subroutine RSP2_adjust_vars_before_call_solver
    1187              : 
    1188              :       end module hydro_rsp2
        

Generated by: LCOV version 2.0-1