LCOV - code coverage report
Current view: top level - star/private - mix_info.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 34.6 % 1272 440
Test Date: 2025-12-14 16:52:03 Functions: 61.1 % 36 22

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2011-2019  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              :       module mix_info
      21              : 
      22              :       use const_def, only: dp, i8, ln10, pi4, msun, no_mixing, &
      23              :                            minimum_mixing, &
      24              :                            rayleigh_taylor_mixing, &
      25              :                            convective_mixing, &
      26              :                            semiconvective_mixing, &
      27              :                            overshoot_mixing, &
      28              :                            thermohaline_mixing, &
      29              :                            rotation_mixing
      30              :       use num_lib
      31              :       use utils_lib
      32              :       use star_private_def
      33              : 
      34              :       implicit none
      35              : 
      36              :       private
      37              :       public :: set_mixing_info
      38              :       public :: set_RTI_mixing_info
      39              :       public :: do_smoothing_by_mass
      40              :       public :: update_rotation_mixing_info
      41              :       public :: set_dPdr_dRhodr_info
      42              :       public :: get_convection_sigmas
      43              :       public :: set_dxdt_mix
      44              :       public :: set_cz_bdy_mass
      45              : 
      46              :       contains
      47              : 
      48           33 :       subroutine set_mixing_info(s, skip_set_cz_bdy_mass, ierr)
      49              :          ! set convection variables cdc and conv_vel starting from local MLT results.
      50              :          ! overshooting can also be added.    and rotation mixing.
      51              :          use rates_def, only: i_rate
      52              :          use chem_def, only: ipp, icno, i3alf, ih1, ihe4, ic12
      53              :          use star_utils, only: start_time, update_time
      54              :          use overshoot, only: add_overshooting
      55              :          use predictive_mix, only: add_predictive_mixing
      56              :          use auto_diff_support, only: get_RSP2_conv_velocity
      57              :          type (star_info), pointer :: s
      58              :          logical, intent(in) :: skip_set_cz_bdy_mass
      59              :          integer, intent(out) :: ierr
      60              : 
      61              :          integer :: nz, k, max_conv_bdy, max_mix_bdy, k_Tmax, i_h1, i_he4, i_c12
      62           33 :          real(dp) :: rho_face, f, Tmax, min_conv_vel_for_convective_mixing_type, &
      63           33 :             region_bottom_q, region_top_q, L_val
      64           33 :          real(dp), allocatable, dimension(:) :: eps_h, eps_he, eps_z, cdc_factor
      65              : 
      66              :          logical :: RSP2_or_RSP
      67              : 
      68              :          integer(i8) :: time0
      69           33 :          real(dp) :: total
      70              : 
      71              :          include 'formats'
      72              : 
      73           33 :          ierr = 0
      74           33 :          nz = s% nz
      75              : 
      76           33 :          min_conv_vel_for_convective_mixing_type = 1d0  ! make this a control parameter
      77              : 
      78           33 :          RSP2_or_RSP = s% RSP_flag .or. s% RSP2_flag
      79              : 
      80           33 :          if (s% doing_timing) call start_time(s, time0, total)
      81              : 
      82           33 :          if (s% RTI_flag) then
      83            0 :             call set_RTI_mixing_info(s, ierr)
      84            0 :             if (failed('set_RTI_mixing_info')) return
      85            0 :             call set_dPdr_dRhodr_info(s, ierr)
      86            0 :             if (failed('set_dPdr_dRhodr_info')) return
      87              :          end if
      88              : 
      89           33 :          max_conv_bdy = 10  ! will automatically be increased if necessary
      90           33 :          max_mix_bdy = 10  ! will automatically be increased if necessary
      91              : 
      92           33 :          s% num_conv_boundaries = 0
      93           33 :          if (.not. associated(s% conv_bdy_loc)) allocate(s% conv_bdy_loc(max_conv_bdy))
      94           33 :          if (.not. associated(s% conv_bdy_q)) allocate(s% conv_bdy_q(max_conv_bdy))
      95           33 :          if (.not. associated(s% top_conv_bdy)) allocate(s% top_conv_bdy(max_conv_bdy))
      96           33 :          if (.not. associated(s% burn_h_conv_region)) allocate(s% burn_h_conv_region(max_conv_bdy))
      97           33 :          if (.not. associated(s% burn_he_conv_region)) allocate(s% burn_he_conv_region(max_conv_bdy))
      98           33 :          if (.not. associated(s% burn_z_conv_region)) allocate(s% burn_z_conv_region(max_conv_bdy))
      99              : 
     100           33 :          s% num_mix_boundaries = 0
     101           33 :          if (.not. associated(s% mix_bdy_loc)) allocate(s% mix_bdy_loc(max_mix_bdy))
     102           33 :          if (.not. associated(s% mix_bdy_q)) allocate(s% mix_bdy_q(max_mix_bdy))
     103           33 :          if (.not. associated(s% top_mix_bdy)) allocate(s% top_mix_bdy(max_mix_bdy))
     104           33 :          if (.not. associated(s% burn_h_mix_region)) allocate(s% burn_h_mix_region(max_mix_bdy))
     105           33 :          if (.not. associated(s% burn_he_mix_region)) allocate(s% burn_he_mix_region(max_mix_bdy))
     106           33 :          if (.not. associated(s% burn_z_mix_region)) allocate(s% burn_z_mix_region(max_mix_bdy))
     107              : 
     108           33 :          allocate(eps_h(nz), eps_he(nz), eps_z(nz), cdc_factor(nz))
     109              : 
     110           33 :          if (.not. RSP2_or_RSP) then
     111        40766 :             do k = 1, nz
     112        40766 :                s% mixing_type(k) = s% mlt_mixing_type(k)
     113              :             end do
     114              :          end if
     115              : 
     116           33 :          cdc_factor(1) = 1d0
     117        40733 :          do k = 2, nz
     118              :             rho_face = (s% dq(k-1)*s% rho(k) + s% dq(k)*s% rho(k-1))/&
     119        40700 :                            (s% dq(k-1) + s% dq(k))
     120        40700 :             f = pi4*s% r(k)*s% r(k)*rho_face
     121        40733 :             cdc_factor(k) = f*f
     122              :          end do
     123              : 
     124           33 :          if (s% RSP_flag) then
     125            0 :             do k = 1, nz
     126            0 :                s% mixing_type(k) = no_mixing
     127            0 :                s% D_mix(k) = 0d0
     128            0 :                s% cdc(k) = 0d0
     129            0 :                s% conv_vel(k) = 0d0
     130              :             end do
     131           33 :          else if (s% RSP2_flag) then
     132            0 :             do k = 1, nz
     133            0 :                s% conv_vel(k) = get_RSP2_conv_velocity(s,k)
     134            0 :                s% D_mix(k) = s% conv_vel(k)*s% mixing_length_alpha*s% Hp_face(k)/3d0
     135            0 :                s% cdc(k) = cdc_factor(k)*s% D_mix(k)
     136            0 :                L_val = max(1d-99,abs(s% L(k)))
     137            0 :                if (abs(s% Lt(k)) > &
     138            0 :                      L_val*s% RSP2_min_Lt_div_L_for_overshooting_mixing_type) then
     139            0 :                   s% mixing_type(k) = overshoot_mixing
     140            0 :                else if (abs(s% Lc(k)) > &
     141              :                      L_val*s% RSP2_min_Lc_div_L_for_convective_mixing_type) then
     142            0 :                   s% mixing_type(k) = convective_mixing
     143              :                else
     144            0 :                   s% mixing_type(k) = no_mixing
     145              :                end if
     146              :             end do
     147              :          else
     148        40766 :             do k = 1, nz
     149        40733 :                s% D_mix(k) = s% mlt_D(k)
     150        40733 :                s% cdc(k) = s% mlt_cdc(k)
     151        40766 :                s% conv_vel(k) = s% mlt_vc(k)
     152              :             end do
     153              :          end if
     154              : 
     155           33 :          call check('after get mlt_D')
     156              : 
     157           33 :          if (s% remove_mixing_glitches .and. .not. RSP2_or_RSP) then
     158              : 
     159           33 :             call remove_tiny_mixing(s, ierr)
     160           33 :             if (failed('remove_tiny_mixing')) return
     161              : 
     162           33 :             call remove_mixing_singletons(s, ierr)
     163           33 :             if (failed('remove_mixing_singletons')) return
     164              : 
     165           33 :             call close_convection_gaps(s, ierr)
     166           33 :             if (failed('close_convection_gaps')) return
     167              : 
     168           33 :             call close_thermohaline_gaps(s, ierr)
     169           33 :             if (failed('close_thermohaline_gaps')) return
     170              : 
     171           33 :             call remove_thermohaline_dropouts(s, ierr)
     172           33 :             if (failed('remove_thermohaline_dropouts')) return
     173              : 
     174           33 :             call close_semiconvection_gaps(s, ierr)
     175           33 :             if (failed('close_semiconvection_gaps')) return
     176              : 
     177           33 :             call remove_embedded_semiconvection(s, ierr)
     178           33 :               if (failed('remove_embedded_semiconvection')) return
     179              : 
     180              :          end if
     181              : 
     182           33 :          call check('after get remove_mixing_glitches')
     183              : 
     184           33 :          call do_mix_envelope(s)
     185              : 
     186        40766 :          do k=1,s% nz
     187              :             eps_h(k) = s% eps_nuc_categories(ipp,k) + &
     188        40733 :                        s% eps_nuc_categories(icno,k)
     189        40733 :             eps_he(k) = s% eps_nuc_categories(i3alf,k)
     190        40766 :             eps_z(k) = s% eps_nuc(k) - (eps_h(k) + eps_he(k))
     191              :          end do
     192              : 
     193           33 :          if (.not. s% RSP_flag) then
     194              : 
     195           33 :             call set_cz_boundary_info(s, ierr)
     196           33 :             if (failed('set_cz_boundary_info')) return
     197              : 
     198              :             call locate_convection_boundaries( &
     199              :                s, nz, eps_h, eps_he, eps_z, s% mstar, &
     200           33 :                s% q, s% cdc, ierr)
     201           33 :             if (failed('locate_convection_boundaries')) return
     202              : 
     203           33 :             call add_predictive_mixing(s, ierr)
     204           33 :             if (failed('add_predictive_mixing')) return
     205              : 
     206              :          end if
     207              : 
     208           33 :          call check('after add_predictive_mixing')
     209              : 
     210              :          ! NB: re-call locate_convection_boundaries to take into
     211              :          ! account changes from add_predictive_mixing
     212              : 
     213           33 :          if (.not. s% RSP_flag) then
     214              : 
     215              :             call locate_convection_boundaries( &
     216              :                s, nz, eps_h, eps_he, eps_z, s% mstar, &
     217           33 :                s% q, s% cdc, ierr)
     218           33 :             if (failed('locate_convection_boundaries')) return
     219              : 
     220           33 :             call locate_mixing_boundaries(s, eps_h, eps_he, eps_z, ierr)
     221           33 :             if (failed('locate_mixing_boundaries')) return
     222              : 
     223           33 :             call add_overshooting(s, ierr)
     224           33 :             if (failed('add_overshooting')) return
     225              : 
     226              :          end if
     227              : 
     228           33 :          call check('after add_overshooting')
     229              : 
     230           33 :          call add_RTI_turbulence(s, ierr)
     231           33 :          if (failed('add_RTI_turbulence')) return
     232              : 
     233           33 :          call s% other_after_set_mixing_info(s% id, ierr)
     234           33 :          if (failed('other_after_set_mixing_info')) return
     235              : 
     236           33 :          if (.not. (skip_set_cz_bdy_mass .or. RSP2_or_RSP)) then
     237           11 :             call set_cz_bdy_mass(s, ierr)
     238           11 :             if (failed('set_cz_bdy_mass')) return
     239              :          end if
     240              : 
     241           33 :          if (s% set_min_D_mix .and. s% ye(nz) >= s% min_center_Ye_for_min_D_mix) then
     242            0 :             do k=1,nz
     243            0 :                if (s% D_mix(k) >= s% min_D_mix) cycle
     244            0 :                if (s% m(k) > s% mass_upper_limit_for_min_D_mix*Msun) cycle
     245            0 :                if (s% m(k) < s% mass_lower_limit_for_min_D_mix*Msun) cycle
     246            0 :                s% D_mix(k) = s% min_D_mix
     247            0 :                s% mixing_type(k) = minimum_mixing
     248              :             end do
     249              :          end if
     250              : 
     251           33 :          if (s% set_min_D_mix_below_Tmax) then
     252            0 :             Tmax = -1
     253            0 :             k_Tmax = -1
     254            0 :             do k=1,nz
     255            0 :                if (s% T(k) > Tmax) then
     256            0 :                   Tmax = s% T(k)
     257            0 :                   k_Tmax = k
     258              :                end if
     259              :             end do
     260            0 :             do k=k_Tmax+1,nz
     261            0 :                if (s% D_mix(k) >= s% min_D_mix_below_Tmax) cycle
     262            0 :                s% D_mix(k) = s% min_D_mix_below_Tmax
     263            0 :                s% mixing_type(k) = minimum_mixing
     264              :             end do
     265              :          end if
     266              : 
     267           33 :          if (s% set_min_D_mix_in_H_He) then
     268            0 :             do k=1,nz
     269            0 :                if (s% X(k) + s% Y(k) < 0.5d0) exit
     270            0 :                if (s% D_mix(k) >= s% min_D_mix_in_H_He) cycle
     271            0 :                s% D_mix(k) = s% min_D_mix_in_H_He
     272            0 :                s% mixing_type(k) = minimum_mixing
     273              :             end do
     274              :          end if
     275              : 
     276           33 :          if (s% use_other_D_mix) then
     277            0 :             call s% other_D_mix(s% id, ierr)
     278            0 :             if (failed('other_D_mix')) return
     279              :          end if
     280              : 
     281        40766 :          do k=1,nz
     282        40766 :             s% D_mix_non_rotation(k) = s% D_mix(k)
     283              :          end do
     284              : 
     285           33 :          call check('before rotation_flag')
     286              : 
     287           33 :          if (s% rotation_flag) then
     288              : 
     289            0 :             call update_rotation_mixing_info(s,ierr)
     290            0 :             if (failed('update_rotation_mixing_info')) return
     291              : 
     292            0 :             do k = 2, nz
     293            0 :                if (s% D_mix(k) < 1d-10) s% D_mix(k) = 0d0
     294            0 :                s% cdc(k) = s% D_mix(k)*cdc_factor(k)
     295            0 :                if (s% D_mix(k) /= 0 .and. s% D_mix_non_rotation(k) < s% D_mix_rotation(k)) then
     296            0 :                   s% mixing_type(k) = rotation_mixing
     297              :                end if
     298              :             end do
     299            0 :             s% cdc(1) = s% cdc(2)
     300              : 
     301              :          end if
     302              : 
     303           33 :          call check('after update_rotation_mixing_info')
     304              : 
     305           33 :          region_bottom_q = s% D_mix_zero_region_bottom_q
     306           33 :          region_top_q = s% D_mix_zero_region_top_q
     307              : 
     308           33 :          if (s% dq_D_mix_zero_at_H_He_crossover > 0d0) then
     309            0 :             i_h1 = s% net_iso(ih1)
     310            0 :             i_he4 = s% net_iso(ihe4)
     311            0 :             if (i_h1 > 0 .and. i_he4 > 0) then
     312            0 :                do k=2,nz
     313            0 :                   if (s% xa(i_h1,k-1) > s% xa(i_he4,k-1) .and. &
     314            0 :                       s% xa(i_h1,k) <= s% xa(i_he4,k)) then  ! crossover
     315              :                      region_bottom_q = &
     316            0 :                         s% q(k) - 0.5d0*s% dq_D_mix_zero_at_H_He_crossover
     317              :                      region_top_q = &
     318            0 :                         s% q(k) + 0.5d0*s% dq_D_mix_zero_at_H_He_crossover
     319            0 :                      exit
     320              :                   end if
     321              :                end do
     322              :             end if
     323              :          end if
     324              : 
     325           33 :          if (region_bottom_q < region_top_q) then
     326            0 :             do k=2,nz
     327            0 :                if (s% q(k) >= region_bottom_q .and. s% q(k) <= region_top_q) then
     328            0 :                   s% D_mix(k) = 0d0
     329            0 :                   s% mixing_type(k) = no_mixing
     330              :                end if
     331              :             end do
     332              :          end if
     333              : 
     334           33 :          region_bottom_q = 1d99
     335           33 :          region_top_q = -1d99
     336           33 :          if (s% dq_D_mix_zero_at_H_C_crossover > 0d0) then
     337            0 :             i_h1 = s% net_iso(ih1)
     338            0 :             i_c12 = s% net_iso(ic12)
     339            0 :             if (i_h1 > 0 .and. i_c12 > 0) then
     340            0 :                do k=2,nz
     341            0 :                   if (s% xa(i_h1,k-1) > s% xa(i_c12,k-1) .and. &
     342            0 :                       s% xa(i_h1,k) <= s% xa(i_c12,k)) then  ! crossover
     343              :                      region_bottom_q = &
     344            0 :                         s% q(k) - 0.5d0*s% dq_D_mix_zero_at_H_C_crossover
     345              :                      region_top_q = &
     346            0 :                         s% q(k) + 0.5d0*s% dq_D_mix_zero_at_H_C_crossover
     347            0 :                      exit
     348              :                   end if
     349              :                end do
     350              :             end if
     351              :          end if
     352              : 
     353            0 :          if (region_bottom_q < region_top_q) then
     354            0 :             do k=2,nz
     355            0 :                if (s% q(k) >= region_bottom_q .and. s% q(k) <= region_top_q) then
     356            0 :                   s% D_mix(k) = 0d0
     357            0 :                   s% mixing_type(k) = no_mixing
     358              :                end if
     359              :             end do
     360              :          end if
     361              : 
     362              :          ! as last thing, update conv_vel from D_mix and mixing length.
     363              :          ! this updates the effective conv vel for rotation and overshooting effects
     364        40733 :          do k=2,nz
     365        40733 :             if (s% alpha_mlt(k)*s% scale_height(k) > 0) then
     366              :                s% conv_vel(k) = &
     367        40700 :                   3d0*s% D_mix(k)/(s% alpha_mlt(k)*s% scale_height(k))
     368              :             else
     369            0 :                s% conv_vel(k) = 0
     370              :             end if
     371              :          end do
     372              : 
     373              :          ! set these just for plotting.  not used.
     374           33 :          s% mixing_type(1) = s% mixing_type(2)
     375           33 :          s% D_mix(1) = s% D_mix(2)
     376           33 :          s% conv_vel(1) = 0d0
     377              : 
     378           33 :          call check('final')
     379           33 :          if (failed('set_mixing_info')) return
     380              : 
     381           33 :          if (s% doing_timing) &
     382            0 :             call update_time(s, time0, total, s% time_set_mixing_info)
     383              : 
     384           99 :          s% have_mixing_info = .true.
     385              : 
     386              :          contains
     387              : 
     388          539 :          logical function failed(str)
     389              :             character (len=*), intent(in) :: str
     390          539 :             if (ierr == 0) then
     391              :                failed = .false.
     392              :                return
     393              :             end if
     394            0 :             if (s% report_ierr) &
     395            0 :                write(*,*) 'set_mixing_info failed in call to ' // trim(str)
     396              :             failed = .true.
     397           33 :          end function failed
     398              : 
     399          231 :          subroutine check(str)
     400              :             character(len=*) :: str
     401              :             integer :: k
     402              :             include 'formats'
     403       285362 :             do k = 1, s% nz
     404       285362 :                if (is_bad_num(s% D_mix(k))) then
     405            0 :                   ierr = -1
     406            0 :                   if (s% report_ierr) then
     407            0 :                      write(*,3) trim(str) // ' mixing_type, D_mix', k, s% mixing_type(k), s% D_mix(k)
     408            0 :                      if (s% rotation_flag) then
     409            0 :                         if (is_bad_num(s% D_mix_non_rotation(k))) &
     410            0 :                            write(*,2) 's% D_mix_non_rotation(k)', k, s% D_mix_non_rotation(k)
     411            0 :                         if (is_bad_num(s% D_visc(k))) write(*,2) 's% D_visc(k)', k, s% D_visc(k)
     412            0 :                         if (is_bad_num(s% D_DSI(k))) write(*,2) 's% D_DSI(k)', k, s% D_DSI(k)
     413            0 :                         if (is_bad_num(s% D_SH(k))) write(*,2) 's% D_SH(k)', k, s% D_SH(k)
     414            0 :                         if (is_bad_num(s% D_SSI(k))) write(*,2) 's% D_SSI(k)', k, s% D_SSI(k)
     415            0 :                         if (is_bad_num(s% D_ES(k))) write(*,2) 's% D_ES(k)', k, s% D_ES(k)
     416            0 :                         if (is_bad_num(s% D_GSF(k))) write(*,2) 's% D_GSF(k)', k, s% D_GSF(k)
     417            0 :                         if (is_bad_num(s% D_ST(k))) write(*,2) 's% D_ST(k)', k, s% D_ST(k)
     418              :                      end if
     419              :                   end if
     420            0 :                   if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'set mixing info')
     421              :                end if
     422              :             end do
     423          231 :          end subroutine check
     424              : 
     425              :       end subroutine set_mixing_info
     426              : 
     427              : 
     428           33 :       subroutine set_cz_boundary_info(s, ierr)
     429              :          type (star_info), pointer :: s
     430              :          integer, intent(out) :: ierr
     431              : 
     432              :          integer :: k, mt1, mt2, nz
     433           33 :          real(dp) :: dg0, dg1
     434              : 
     435              :          include 'formats'
     436              : 
     437              :          ! NOTE: this routine must be called BEFORE overshooting is done.
     438              : 
     439              :          ! convective zone boundary is where gradL = gradr
     440              :          ! semi-convective zone boundary is where grada_face = gradr
     441              : 
     442           33 :          ierr = 0
     443           33 :          nz = s% nz
     444        40766 :          s% cz_bdy_dq(1:nz) = 0d0
     445              : 
     446        40733 :          do k = 2, nz
     447        40700 :             mt1 = s% mixing_type(k-1)
     448        40700 :             mt2 = s% mixing_type(k)
     449        40700 :             if (mt1 == mt2) cycle
     450          105 :             if (mt2 == convective_mixing .or. mt1 == convective_mixing) then
     451          105 :                dg0 = s% gradL(k-1) - s% gradr(k-1)
     452          105 :                dg1 = s% gradL(k) - s% gradr(k)
     453            0 :             else if (mt2 == semiconvective_mixing .or. mt1 == semiconvective_mixing) then
     454            0 :                dg0 = s% grada_face(k-1) - s% gradr(k-1)
     455            0 :                dg1 = s% grada_face(k) - s% gradr(k)
     456              :             else
     457              :                cycle
     458              :             end if
     459          105 :             if (dg0*dg1 >= 0) cycle
     460          105 :             s% cz_bdy_dq(k-1) = find0(0d0,dg0,s% dq(k-1),dg1)
     461          138 :             if (s% cz_bdy_dq(k-1) < 0d0 .or. s% cz_bdy_dq(k-1) > s% dq(k-1)) then
     462            0 :                write(*,2) 'bad cz_bdy_dq', k-1, s% cz_bdy_dq(k-1), s% dq(k-1)
     463            0 :                call mesa_error(__FILE__,__LINE__,'set_cz_boundary_info')
     464            0 :                ierr = -1
     465            0 :                return
     466              :             end if
     467              :          end do
     468              : 
     469              :       end subroutine set_cz_boundary_info
     470              : 
     471              : 
     472           11 :       subroutine set_cz_bdy_mass(s, ierr)
     473              :          type (star_info), pointer :: s
     474              :          integer, intent(out) :: ierr
     475              : 
     476              :          logical :: in_convective_region
     477              :          integer :: k, j, nz
     478              :          logical, parameter :: dbg = .false.
     479              : 
     480              :          include 'formats'
     481           11 :          ierr = 0
     482           11 :          nz = s% nz
     483              : 
     484         1111 :          s% cz_top_mass(:) = s% mstar
     485         1111 :          s% cz_bot_mass(:) = s% mstar
     486              : 
     487           11 :          s% n_conv_regions = 0
     488           11 :          in_convective_region = (s% mixing_type(nz) == convective_mixing)
     489           11 :          if (in_convective_region) then
     490           11 :             s% n_conv_regions = 1
     491           11 :             s% cz_bot_mass(1) = s% M_center
     492              :          end if
     493              : 
     494              :          if (dbg) write(*,*) 'initial in_convective_region', in_convective_region
     495              : 
     496        13076 :          do k=nz-1, 2, -1
     497        13076 :             if (in_convective_region) then
     498         1894 :                if (s% mixing_type(k) /= convective_mixing) then  ! top of convective region
     499              :                   s% cz_top_mass(s% n_conv_regions) = &
     500           23 :                      s% M_center + (s% q(k) - s% cz_bdy_dq(k))*s% xmstar
     501           23 :                   in_convective_region = .false.
     502              :                end if
     503              :             else
     504        11171 :                if (s% mixing_type(k) == convective_mixing) then  ! bottom of convective region
     505           12 :                   if (s% n_conv_regions < max_num_mixing_regions) then
     506           12 :                      s% n_conv_regions = s% n_conv_regions + 1
     507              :                      s% cz_bot_mass(s% n_conv_regions) = &
     508           12 :                         s% M_center + (s% q(k) - s% cz_bdy_dq(k))*s% xmstar
     509              :                   end if
     510              :                   in_convective_region = .true.
     511              :                end if
     512              :             end if
     513              :          end do
     514           11 :          if (in_convective_region) then
     515            0 :             s% cz_top_mass(s% n_conv_regions) = s% mstar
     516              :          end if
     517              : 
     518           11 :          s% have_new_cz_bdy_info = .true.
     519              : 
     520              :          if (dbg) then
     521              :             write(*,'(A)')
     522              :             write(*,2) 'set_mixing_info s% n_conv_regions', s% n_conv_regions
     523              :             do j = 1, s% n_conv_regions
     524              :                write(*,2) 'conv region', j, s% cz_bot_mass(j)/Msun, s% cz_top_mass(j)/Msun
     525              :             end do
     526              :             write(*,'(A)')
     527              :          end if
     528              : 
     529           11 :       end subroutine set_cz_bdy_mass
     530              : 
     531              : 
     532           66 :       subroutine locate_convection_boundaries( &
     533           66 :             s, nz, eps_h, eps_he, eps_z, mstar, q, cdc, ierr)
     534              :          type (star_info), pointer :: s
     535              :          integer, intent(in) :: nz
     536              :          real(dp), dimension(:), intent(in) :: eps_h, eps_he, eps_z
     537              :          real(dp), intent(in) :: mstar
     538              :          real(dp), pointer, dimension(:) :: q, cdc
     539              :          integer, intent(out) :: ierr
     540              : 
     541              :          logical :: in_convective_region
     542              :          integer :: k, k_bot, i, j, iounit, max_conv_bdy
     543           66 :          real(dp) :: turnover_time, bot_Hp, bot_r, top_Hp, top_r, dr
     544              : 
     545              :          logical :: dbg
     546              :          logical, parameter :: write_debug = .false.
     547              : 
     548              :          include 'formats'
     549              : 
     550           66 :          ierr = 0
     551           66 :          dbg = .false.
     552              : 
     553              :          if (write_debug) then
     554              :             open(newunit=iounit, file=trim('debug.data'), action='write', iostat=ierr)
     555              :             if (ierr /= 0) then
     556              :                write(*, *) 'open debug.data failed'
     557              :                return
     558              :             end if
     559              :             write(*,*) 'write debug.data'
     560              :             write(iounit,*) 'nz', nz
     561              :             write(iounit,1) 'mstar', mstar
     562              :             do k=1,nz
     563              :                write(iounit,2) 'q', k, q(k)
     564              :                write(iounit,2) 'cdc', k, cdc(k)
     565              :                write(iounit,2) 'eps_h', k, eps_h(k)
     566              :                write(iounit,2) 'eps_he', k, eps_he(k)
     567              :                write(iounit,2) 'eps_z', k, eps_z(k)
     568              :             end do
     569              :          end if
     570              : 
     571           66 :          max_conv_bdy = size(s% conv_bdy_q, dim=1)
     572          726 :          s% conv_bdy_q(:) = 0
     573          726 :          s% conv_bdy_loc(:) = 0
     574          726 :          s% top_conv_bdy(:) = .false.
     575          726 :          s% burn_h_conv_region(:) = .false.
     576          726 :          s% burn_he_conv_region(:) = .false.
     577          726 :          s% burn_z_conv_region(:) = .false.
     578           66 :          bot_Hp = 0; bot_r = 0; top_Hp = 0; top_r = 0; dr = 0
     579              : 
     580           66 :          s% num_conv_boundaries = 0
     581           66 :          in_convective_region = (s% mixing_type(nz) == convective_mixing)
     582           66 :          k_bot = nz
     583           66 :          turnover_time = 0
     584              : 
     585        81400 :          do k=nz-1, 2, -1
     586        81400 :             if (in_convective_region) then
     587        12002 :                if (s% mixing_type(k) /= convective_mixing) then
     588          138 :                   call end_of_convective_region
     589        81334 :                else if(s% conv_vel(k) /= 0d0) then
     590        81334 :                   turnover_time = turnover_time + (s% rmid(k-1) - s% rmid(k))/s% conv_vel(k)
     591              :                end if
     592              :             else  ! in non-convective region
     593        69332 :                if (s% mixing_type(k) == convective_mixing) then  ! start of a convective region
     594           72 :                   if (s% num_conv_boundaries == max_conv_bdy) then
     595            0 :                      call realloc(ierr)
     596            0 :                      if (ierr /= 0) then
     597              :                         return
     598              :                      end if
     599              :                   end if
     600           72 :                   s% num_conv_boundaries = s% num_conv_boundaries+1
     601           72 :                   i = s% num_conv_boundaries
     602           72 :                   k_bot = k+1
     603           72 :                   if (k == 1) then
     604            0 :                      s% conv_bdy_q(i) = 1
     605              :                   else  ! bottom of region is between k+1 and k
     606           72 :                      s% conv_bdy_q(i) = s% q(k) - s% cz_bdy_dq(k)
     607              :                   end if
     608           72 :                   s% top_conv_bdy(i) = .false.
     609           72 :                   s% conv_bdy_loc(i) = k_bot
     610              :                      ! bottom of region is between k_bot and k_bot-1
     611           72 :                   in_convective_region = .true.
     612           72 :                   bot_r = s% r(k_bot)
     613              :                   !bot_Hp = scale_height(s,k_bot,.true.)
     614           72 :                   bot_Hp = s% scale_height(k_bot)
     615           72 :                   turnover_time = 0
     616              :                end if
     617              :             end if
     618              :          end do
     619              : 
     620           66 :          if (in_convective_region) then
     621            0 :             k = 1  ! end at top
     622            0 :             call end_of_convective_region
     623              :          end if
     624              : 
     625              :          if (write_debug) then
     626              :             write(iounit,*) 's% num_conv_boundaries', s% num_conv_boundaries
     627              :             do j=1,s% num_conv_boundaries
     628              :                write(iounit,2) 's% conv_bdy_q', j, s% conv_bdy_q(j)
     629              :                write(iounit,*) 's% top_conv_bdy', j, s% top_conv_bdy(j)
     630              :                write(iounit,*) 's% burn_h_conv_region', j, s% burn_h_conv_region(j)
     631              :                write(iounit,*) 's% burn_he_conv_region', j, s% burn_he_conv_region(j)
     632              :                write(iounit,*) 's% burn_z_conv_region', j, s% burn_z_conv_region(j)
     633              :                write(iounit,*) 's% conv_bdy_loc', j, s% conv_bdy_loc(j)
     634              :             end do
     635              :             close(iounit)
     636              :          end if
     637              : 
     638              :          if (dbg) then
     639              :             write(*,*) 's% num_conv_boundaries', s% num_conv_boundaries
     640              :             do j=1,s% num_conv_boundaries
     641              :                write(*,*) 's% conv_bdy_q', j, s% conv_bdy_q(j)
     642              :                write(*,*) 's% top_conv_bdy', j, s% top_conv_bdy(j)
     643              :                write(*,*) 's% burn_h_conv_region', j, s% burn_h_conv_region(j)
     644              :                write(*,*) 's% burn_he_conv_region', j, s% burn_he_conv_region(j)
     645              :                write(*,*) 's% burn_z_conv_region', j, s% burn_z_conv_region(j)
     646              :                write(*,*) 's% conv_bdy_loc', j, s% conv_bdy_loc(j)
     647              :                write(*,*) 'mixing type', s% mixing_type(s% conv_bdy_loc(j)-3:s% conv_bdy_loc(j)+3)
     648              :             end do
     649              :             write(*,'(A)')
     650              :             write(*,3) 'mixing_type', 1152, s% mixing_type(1152)
     651              :             call mesa_error(__FILE__,__LINE__,'locate_convection_boundaries')
     652              :          end if
     653              : 
     654              : 
     655              :          contains
     656              : 
     657              : 
     658          138 :          subroutine end_of_convective_region()
     659              :             integer :: max_logT_loc, kk
     660          138 :             real(dp) :: max_logT, max_X, max_Y, Hp, max_eps
     661              :             logical :: end_dbg
     662              : 
     663              :             9 format(a40, 3i7, 99(1pd26.16))
     664              :             include 'formats'
     665              : 
     666          138 :             in_convective_region = .false.
     667              : 
     668          138 :             end_dbg = .false.
     669              : 
     670          138 :             top_r = s% r(k)
     671          138 :             top_Hp = s% scale_height(k)
     672          138 :             dr = top_r - bot_r
     673          138 :             Hp = (bot_Hp + top_Hp)/2
     674              : 
     675          138 :             if (dr/Hp < s% prune_bad_cz_min_Hp_height .and. s% prune_bad_cz_min_Hp_height > 0) then
     676            0 :                max_eps = maxval(eps_h(k:k_bot) + eps_he(k:k_bot) + eps_z(k:k_bot))
     677              :                if (end_dbg) write(*,3) 'max_eps', k, k_bot, max_eps, &
     678              :                   exp10(s% prune_bad_cz_min_log_eps_nuc)
     679              :                if (max_eps < exp10(s% prune_bad_cz_min_log_eps_nuc) &
     680            0 :                      .and. all(s% mixing_type(k+1:k_bot-1) /= thermohaline_mixing)) then
     681            0 :                   do kk = k, k_bot  ! this includes the radiative points at boundaries
     682            0 :                      call set_use_gradr(s,kk)
     683            0 :                      s% cdc(kk) = 0
     684            0 :                      s% D_mix(kk) = 0
     685            0 :                      s% conv_vel(kk) = 0
     686            0 :                      s% mixing_type(kk) = no_mixing
     687              :                   end do
     688            0 :                   if (s% num_conv_boundaries > 0) &
     689            0 :                      s% num_conv_boundaries = s% num_conv_boundaries-1
     690            0 :                   return
     691              :                end if
     692              :             end if
     693              : 
     694          138 :             if (s% num_conv_boundaries == max_conv_bdy) then
     695            0 :                call realloc(ierr)
     696            0 :                if (ierr /= 0) return
     697              :             end if
     698              : 
     699          138 :             s% num_conv_boundaries = s% num_conv_boundaries+1
     700          138 :             i = s% num_conv_boundaries
     701              : 
     702              :             ! check for burning in region
     703          138 :             max_logT = -1d99
     704          138 :             max_X = 0d0
     705          138 :             max_Y = 0d0
     706          138 :             max_logT_loc = 0
     707        12422 :             do kk=k,min(nz,k_bot+1)
     708        12284 :                if (s% lnT(kk)/ln10 > max_logT) then
     709        12284 :                   max_logT = s% lnT(kk)/ln10
     710        12284 :                   max_logT_loc = kk
     711              :                end if
     712        12284 :                if (s% X(kk) > max_X) then
     713          138 :                   max_X = s% X(kk)
     714              :                end if
     715        12422 :                if (s% Y(kk) > max_Y) then
     716        10058 :                   max_Y = s% Y(kk)
     717              :                end if
     718              :             end do
     719              :             if (max_logT > s% burn_z_mix_region_logT &
     720          138 :                   .and. max_Y < s% max_Y_for_burn_z_mix_region) then
     721            0 :                s% burn_z_conv_region(i) = .true.
     722            0 :                if (i > 1) s% burn_z_conv_region(i-1) = .true.
     723              :                !write(*,*) 'burn z mix region', i, &
     724              :                !   s% burn_z_mix_region_logT, max_logT, s% m(max_logT_loc)/Msun
     725              :             else if (max_logT > s% burn_he_mix_region_logT &
     726          138 :                   .and. max_X < s% max_X_for_burn_he_mix_region) then
     727            0 :                s% burn_he_conv_region(i) = .true.
     728            0 :                if (i > 1) s% burn_he_conv_region(i-1) = .true.
     729              :                !write(*,*) 'burn he mix region', i, &
     730              :                !   s% burn_he_mix_region_logT, max_logT, s% m(max_logT_loc)/Msun
     731          138 :             else if (max_logT > s% burn_h_mix_region_logT) then
     732           66 :                s% burn_h_conv_region(i) = .true.
     733           66 :                if (i > 1) s% burn_h_conv_region(i-1) = .true.
     734              :                !write(*,*) 'burn h mix region', i, &
     735              :                !   s% burn_h_mix_region_logT, max_logT, s% m(max_logT_loc)/Msun
     736              :             end if
     737              : 
     738          138 :             if (k == 1) then
     739            0 :                s% conv_bdy_q(i) = 1
     740              :             else
     741              :                ! top of region is between k+1 and k
     742          138 :                s% conv_bdy_q(i) = s% q(k) - s% cz_bdy_dq(k)
     743              :             end if
     744          138 :             s% top_conv_bdy(i) = .true.
     745          138 :             s% conv_bdy_loc(i) = k
     746              : 
     747              :          end subroutine end_of_convective_region
     748              : 
     749              : 
     750            0 :          subroutine realloc(ierr)
     751              :             use utils_lib
     752              :             integer, intent(out) :: ierr
     753              : 
     754              :             integer :: sz
     755              : 
     756            0 :             sz = size(s% conv_bdy_q, dim=1)
     757              : 
     758              :             ierr = 0
     759            0 :             max_conv_bdy = 2*(10+max_conv_bdy)
     760              : 
     761            0 :             call realloc_double(s% conv_bdy_q,max_conv_bdy,ierr)
     762            0 :             if (ierr /= 0) return
     763              : 
     764            0 :             call realloc_integer(s% conv_bdy_loc,max_conv_bdy,ierr)
     765            0 :             if (ierr /= 0) return
     766              : 
     767            0 :             call realloc_logical(s% top_conv_bdy,max_conv_bdy,ierr)
     768            0 :             if (ierr /= 0) return
     769              : 
     770            0 :             call realloc_logical(s% burn_h_conv_region,max_conv_bdy,ierr)
     771            0 :             if (ierr /= 0) return
     772              : 
     773            0 :             call realloc_logical(s% burn_he_conv_region,max_conv_bdy,ierr)
     774            0 :             if (ierr /= 0) return
     775              : 
     776            0 :             call realloc_logical(s% burn_z_conv_region,max_conv_bdy,ierr)
     777            0 :             if (ierr /= 0) return
     778              : 
     779            0 :             s% conv_bdy_q(sz+1:max_conv_bdy) = 0
     780            0 :             s% conv_bdy_loc(sz+1:max_conv_bdy) = 0
     781            0 :             s% top_conv_bdy(sz+1:max_conv_bdy) = .false.
     782            0 :             s% burn_h_conv_region(sz+1:max_conv_bdy) = .false.
     783            0 :             s% burn_he_conv_region(sz+1:max_conv_bdy) = .false.
     784            0 :             s% burn_z_conv_region(sz+1:max_conv_bdy) = .false.
     785              : 
     786              :          end subroutine realloc
     787              : 
     788              :       end subroutine locate_convection_boundaries
     789              : 
     790              : 
     791           30 :       subroutine set_use_gradr(s,k)
     792              :          use turb_info, only: switch_to_radiative
     793              :          type (star_info), pointer :: s
     794              :          integer, intent(in) :: k
     795           30 :          call switch_to_radiative(s,k)
     796           30 :       end subroutine set_use_gradr
     797              : 
     798              : 
     799           33 :       subroutine locate_mixing_boundaries(s, eps_h, eps_he, eps_z, ierr)
     800              :          type (star_info), pointer :: s
     801              :          real(dp), dimension(:), intent(in) :: eps_h, eps_he, eps_z
     802              :          integer, intent(out) :: ierr
     803              : 
     804              :          logical :: in_mixing_region
     805              :          integer :: k, k_bot, i, max_mix_bdy, nz
     806              : 
     807              :          logical, parameter :: dbg = .false.
     808              : 
     809              :          include 'formats'
     810              : 
     811           33 :          ierr = 0
     812           33 :          nz = s% nz
     813              : 
     814           33 :          max_mix_bdy = size(s% mix_bdy_q, dim=1)
     815          363 :          s% mix_bdy_q(:) = 0
     816          363 :          s% mix_bdy_loc(:) = 0
     817          363 :          s% top_mix_bdy(:) = .false.
     818          363 :          s% burn_h_mix_region(:) = .false.
     819          363 :          s% burn_he_mix_region(:) = .false.
     820          363 :          s% burn_z_mix_region(:) = .false.
     821              : 
     822           33 :          s% num_mix_boundaries = 0
     823           33 :          s% num_mix_regions = 0
     824           33 :          in_mixing_region = (s% mixing_type(nz) /= no_mixing)
     825           33 :          k_bot = nz
     826        40700 :          do k=nz-1, 2, -1
     827        40700 :             if (in_mixing_region) then
     828         6001 :                if (s% mixing_type(k) == no_mixing) call end_of_mixing_region
     829              :             else  ! in non-mixing region
     830        34666 :                if (s% mixing_type(k) /= no_mixing) then  ! start of a mixing region
     831           36 :                   if (s% num_mix_boundaries == max_mix_bdy) then
     832            0 :                      call realloc(ierr)
     833            0 :                      if (ierr /= 0) return
     834              :                   end if
     835           36 :                   s% num_mix_boundaries = s% num_mix_boundaries+1
     836           36 :                   i = s% num_mix_boundaries
     837           36 :                   k_bot = k+1
     838           36 :                   if (k == 1) then
     839            0 :                      s% mix_bdy_q(i) = 1
     840              :                   else  ! bottom of region is between k+1 and k
     841           36 :                      s% mix_bdy_q(i) = s% q(k) - s% cz_bdy_dq(k)
     842              :                   end if
     843           36 :                   s% top_mix_bdy(i) = .false.
     844           36 :                   s% mix_bdy_loc(i) = k_bot
     845           36 :                   in_mixing_region = .true.
     846              :                end if
     847              :             end if
     848              :          end do
     849              : 
     850           63 :          if (in_mixing_region) then
     851            0 :             k = 1  ! end at top
     852            0 :             call end_of_mixing_region
     853              :          end if
     854              : 
     855              : 
     856              :          !do i=1,s% num_conv_boundaries
     857              :          !   write(*,*) 'locate_mixing_boundaries region burn_h he z', i, &
     858              :          !      s% burn_h_mix_region(i), s% burn_he_conv_region(i), s% burn_z_conv_region(i)
     859              :          !end do
     860              : 
     861              :          contains
     862              : 
     863              : 
     864           69 :          subroutine end_of_mixing_region()
     865              :             integer :: kk, max_logT_loc
     866           69 :             real(dp) :: max_logT, max_X, max_Y
     867              : 
     868              :             9 format(a40, 3i7, 99(1pd26.16))
     869              :             include 'formats'
     870              : 
     871           69 :             in_mixing_region = .false.
     872              : 
     873           69 :             if (s% num_mix_boundaries == max_mix_bdy) then
     874            0 :                call realloc(ierr)
     875            0 :                if (ierr /= 0) return
     876              :             end if
     877              : 
     878           69 :             s% num_mix_regions = s% num_mix_regions+1
     879           69 :             s% num_mix_boundaries = s% num_mix_boundaries+1
     880           69 :             i = s% num_mix_boundaries
     881              : 
     882              :             ! check for burning in region
     883           69 :             max_logT = -1d99
     884           69 :             max_X = 0d0
     885           69 :             max_Y = 0d0
     886           69 :             max_logT_loc = 0
     887         6211 :             do kk=k,min(nz,k_bot+1)
     888         6142 :                if (s% lnT(kk)/ln10 > max_logT) then
     889         6142 :                   max_logT = s% lnT(kk)/ln10
     890         6142 :                   max_logT_loc = kk
     891              :                end if
     892         6142 :                if (s% X(kk) > max_X) then
     893           69 :                   max_X = s% X(kk)
     894              :                end if
     895         6211 :                if (s% Y(kk) > max_Y) then
     896         5029 :                   max_Y = s% Y(kk)
     897              :                end if
     898              :             end do
     899              :             if (max_logT > s% burn_z_mix_region_logT &
     900           69 :                   .and. max_Y < s% max_Y_for_burn_z_mix_region) then
     901            0 :                s% burn_z_mix_region(i) = .true.
     902            0 :                if (i > 1) s% burn_z_mix_region(i-1) = .true.
     903              :                !write(*,*) 'burn z mix region', i
     904              :             else if (max_logT > s% burn_he_mix_region_logT &
     905           69 :                   .and. max_X < s% max_X_for_burn_he_mix_region) then
     906            0 :                s% burn_he_mix_region(i) = .true.
     907            0 :                if (i > 1) s% burn_he_mix_region(i-1) = .true.
     908              :                !write(*,*) 'burn he mix region', i
     909           69 :             else if (max_logT > s% burn_h_mix_region_logT) then
     910           33 :                s% burn_h_mix_region(i) = .true.
     911           33 :                if (i > 1) s% burn_h_mix_region(i-1) = .true.
     912              :                !write(*,*) 'burn h mix region', i
     913              :             end if
     914              : 
     915           69 :             if (k == 1) then
     916            0 :                s% mix_bdy_q(i) = 1
     917              :             else
     918              :                ! top of region is between k+1 and k
     919           69 :                s% mix_bdy_q(i) = s% q(k) - s% cz_bdy_dq(k)
     920              :             end if
     921           69 :             s% top_mix_bdy(i) = .true.
     922           69 :             s% mix_bdy_loc(i) = k
     923              : 
     924              :          end subroutine end_of_mixing_region
     925              : 
     926              : 
     927            0 :          subroutine realloc(ierr)
     928              :             use utils_lib
     929              :             integer, intent(out) :: ierr
     930              : 
     931              :             integer :: sz
     932              : 
     933            0 :             sz = size(s% mix_bdy_q, dim=1)
     934              : 
     935              :             ierr = 0
     936            0 :             max_mix_bdy = 2*(10+max_mix_bdy)
     937              : 
     938            0 :             call realloc_double(s% mix_bdy_q,max_mix_bdy,ierr)
     939            0 :             if (ierr /= 0) return
     940              : 
     941            0 :             call realloc_integer(s% mix_bdy_loc,max_mix_bdy,ierr)
     942            0 :             if (ierr /= 0) return
     943              : 
     944            0 :             call realloc_logical(s% top_mix_bdy,max_mix_bdy,ierr)
     945            0 :             if (ierr /= 0) return
     946              : 
     947            0 :             call realloc_logical(s% burn_h_mix_region,max_mix_bdy,ierr)
     948            0 :             if (ierr /= 0) return
     949              : 
     950            0 :             call realloc_logical(s% burn_he_mix_region,max_mix_bdy,ierr)
     951            0 :             if (ierr /= 0) return
     952              : 
     953            0 :             call realloc_logical(s% burn_z_mix_region,max_mix_bdy,ierr)
     954            0 :             if (ierr /= 0) return
     955              : 
     956            0 :             s% mix_bdy_q(sz+1:max_mix_bdy) = 0
     957            0 :             s% mix_bdy_loc(sz+1:max_mix_bdy) = 0
     958            0 :             s% top_mix_bdy(sz+1:max_mix_bdy) = .false.
     959            0 :             s% burn_h_mix_region(sz+1:max_mix_bdy) = .false.
     960            0 :             s% burn_he_mix_region(sz+1:max_mix_bdy) = .false.
     961            0 :             s% burn_z_mix_region(sz+1:max_mix_bdy) = .false.
     962              : 
     963              :          end subroutine realloc
     964              : 
     965              : 
     966              :       end subroutine locate_mixing_boundaries
     967              : 
     968              : 
     969           33 :       subroutine remove_tiny_mixing(s, ierr)
     970              :          type (star_info), pointer :: s
     971              :          integer, intent(out) :: ierr
     972              : 
     973              :          integer :: k, nz
     974              :          logical, parameter :: dbg = .false.
     975           33 :          real(dp) :: tiny
     976              : 
     977              :          include 'formats'
     978              : 
     979              :          if (dbg) write(*,*) 'remove_tiny_mixing'
     980              : 
     981           33 :          ierr = 0
     982           33 :          nz = s% nz
     983              : 
     984           33 :          tiny = s% clip_D_limit
     985        40766 :          do k=1,nz
     986        40766 :             if (s% D_mix(k) < tiny) then
     987            0 :                s% cdc(k) = 0
     988            0 :                s% D_mix(k) = 0
     989            0 :                s% conv_vel(k) = 0
     990            0 :                s% mixing_type(k) = no_mixing
     991              :             end if
     992              :          end do
     993              : 
     994           33 :       end subroutine remove_tiny_mixing
     995              : 
     996              : 
     997              :       ! remove single point mixing or non-mixing regions
     998              :       ! NOTE: does not remove thermohaline singletons
     999           33 :       subroutine remove_mixing_singletons(s, ierr)
    1000              :          !use star_utils, only: scale_height
    1001              :          type (star_info), pointer :: s
    1002              :          integer, intent(out) :: ierr
    1003              : 
    1004              :          integer :: k, nz
    1005              :          logical, parameter :: dbg = .false.
    1006           33 :          real(dp) :: lambda
    1007              : 
    1008              :          include 'formats'
    1009              : 
    1010              :          if (dbg) write(*,*) 'remove_mixing_singletons'
    1011              : 
    1012           33 :          ierr = 0
    1013           33 :          nz = s% nz
    1014              : 
    1015        40700 :          do k=2,nz-1
    1016        40700 :             if (s% cdc(k) == 0) then
    1017        34669 :                if (s% cdc(k-1) /= 0 .and. s% cdc(k+1) /= 0) then
    1018            0 :                   s% cdc(k) = (s% cdc(k-1) + s% cdc(k+1))/2
    1019            0 :                   s% D_mix(k) = s% cdc(k)/pow2(pi4*s% r(k)*s% r(k)*s% rho(k))
    1020              :                   lambda = s% alpha_mlt(k)* &
    1021            0 :                      (s% scale_height(k-1) + s% scale_height(k+1))/2
    1022            0 :                   s% conv_vel(k) = 3*s% D_mix(k)/lambda
    1023            0 :                   s% mixing_type(k) = max(s% mixing_type(k-1), s% mixing_type(k+1))
    1024              :                if (dbg) write(*,3) 'remove radiative singleton', k, nz
    1025              :                end if
    1026         5998 :             else if (s% okay_to_remove_mixing_singleton) then
    1027         5998 :                if (s% cdc(k-1) == 0 .and. s% cdc(k+1) == 0) then
    1028           30 :                   call set_use_gradr(s,k)
    1029           30 :                   s% cdc(k) = 0
    1030           30 :                   s% D_mix(k) = 0
    1031           30 :                   s% conv_vel(k) = 0
    1032           30 :                   s% mixing_type(k) = no_mixing
    1033              :                   if (dbg) write(*,3) 'remove mixing singleton', k, nz
    1034              :                end if
    1035              :             end if
    1036              :          end do
    1037              : 
    1038           33 :          if (s% cdc(1) == 0) then
    1039           33 :             if (s% cdc(2) /= 0) then
    1040            0 :                s% cdc(1) = s% cdc(2)
    1041            0 :                s% D_mix(1) = s% D_mix(2)
    1042            0 :                s% conv_vel(1) = s% conv_vel(2)
    1043            0 :                s% mixing_type(1) = s% mixing_type(2)
    1044              :                if (dbg) write(*,3) 'remove radiative singleton', 1, nz
    1045              :             end if
    1046              :          else
    1047            0 :             if (s% cdc(2) == 0) then
    1048            0 :                call set_use_gradr(s,1)
    1049            0 :                s% cdc(1) = 0
    1050            0 :                s% D_mix(1) = 0
    1051            0 :                s% conv_vel(1) = 0
    1052            0 :                s% mixing_type(1) = no_mixing
    1053              :                if (dbg) write(*,2) 'remove mixing singleton', 1
    1054              :             end if
    1055              :          end if
    1056              : 
    1057           33 :          if (s% cdc(nz) == 0) then
    1058            0 :             if (s% cdc(nz-1) /= 0) then
    1059            0 :                s% cdc(nz) = s% cdc(nz-1)
    1060            0 :                s% D_mix(nz) = s% D_mix(nz-1)
    1061            0 :                s% conv_vel(nz) = s% conv_vel(nz-1)
    1062            0 :                s% mixing_type(nz) = s% mixing_type(nz-1)
    1063              :                if (dbg) write(*,2) 'remove radiative singleton: s% cdc(nz-1)', nz, s% cdc(nz-1)
    1064              :             end if
    1065              :          else
    1066           33 :             if (s% cdc(nz-1) == 0) then
    1067            0 :                call set_use_gradr(s,nz)
    1068            0 :                s% cdc(nz) = 0
    1069            0 :                s% D_mix(nz) = 0
    1070            0 :                s% conv_vel(nz) = 0
    1071            0 :                s% mixing_type(nz) = no_mixing
    1072              :                if (dbg) write(*,2) 'remove mixing singleton: s% cdc(nz)', nz, s% cdc(nz)
    1073              :             end if
    1074              :          end if
    1075              : 
    1076           33 :       end subroutine remove_mixing_singletons
    1077              : 
    1078              : 
    1079           33 :       subroutine close_convection_gaps(s, ierr)
    1080              :          type (star_info), pointer :: s
    1081              :          integer, intent(out) :: ierr
    1082           33 :          if (s% use_other_close_gaps) then
    1083            0 :             call s% other_close_gaps(s% id, convective_mixing, s% min_convective_gap, ierr)
    1084              :          else
    1085           33 :             call close_gaps(s, convective_mixing, s% min_convective_gap, ierr)
    1086              :          end if
    1087           33 :       end subroutine close_convection_gaps
    1088              : 
    1089              : 
    1090           33 :       subroutine close_thermohaline_gaps(s, ierr)
    1091              :          type (star_info), pointer :: s
    1092              :          integer, intent(out) :: ierr
    1093           33 :          if (s% use_other_close_gaps) then
    1094            0 :             call s% other_close_gaps(s% id, thermohaline_mixing, s% min_thermohaline_gap, ierr)
    1095              :          else
    1096           33 :             call close_gaps(s, thermohaline_mixing, s% min_thermohaline_gap, ierr)
    1097              :          end if
    1098           33 :       end subroutine close_thermohaline_gaps
    1099              : 
    1100              : 
    1101           33 :       subroutine close_semiconvection_gaps(s, ierr)
    1102              :          type (star_info), pointer :: s
    1103              :          integer, intent(out) :: ierr
    1104           33 :          if (s% use_other_close_gaps) then
    1105            0 :             call s% other_close_gaps(s% id, semiconvective_mixing, s% min_semiconvection_gap, ierr)
    1106              :          else
    1107           33 :             call close_gaps(s, semiconvective_mixing, s% min_semiconvection_gap, ierr)
    1108              :          end if
    1109           33 :       end subroutine close_semiconvection_gaps
    1110              : 
    1111              : 
    1112           99 :       subroutine close_gaps(s, mix_type, min_gap, ierr)
    1113              :          type (star_info), pointer :: s
    1114              :          integer, intent(in) :: mix_type
    1115              :          real(dp), intent(in) :: min_gap
    1116              :          integer, intent(out) :: ierr
    1117              : 
    1118              :          integer :: k, nz
    1119              :          logical :: in_region, dbg
    1120           99 :          real(dp) :: rtop, rbot, Hp
    1121              :          integer :: ktop, kbot  ! k's for gap
    1122              :          include 'formats'
    1123              : 
    1124           99 :          dbg = .false.
    1125              :          !dbg = (mix_type == convective_mixing)
    1126              :          if (dbg) write(*,*) 'close_gaps convective_mixing'
    1127              :          if (dbg) write(*,3) 'mixing_type', 1152, s% mixing_type(1152)
    1128           99 :          ierr = 0
    1129           99 :          if (min_gap < 0) return
    1130            0 :          nz = s% nz
    1131            0 :          in_region = (s% mixing_type(nz) == mix_type)
    1132            0 :          rbot = 0
    1133            0 :          kbot = nz
    1134            0 :          do k=nz-1, 2, -1
    1135            0 :             if (in_region) then
    1136            0 :                if (s% mixing_type(k) /= mix_type) then  ! end of region
    1137            0 :                   kbot = k+1
    1138            0 :                   rbot = s% r(kbot)
    1139            0 :                   in_region = .false.
    1140              :                   if (dbg) write(*,2) 'end of region', kbot, rbot
    1141              :                end if
    1142              :             else
    1143            0 :                if (s% mixing_type(k) == mix_type) then  ! start of region
    1144            0 :                   ktop = k
    1145            0 :                   rtop = s% r(ktop)
    1146            0 :                   Hp = s% Peos(ktop)/(s% rho(ktop)*s% grav(ktop))
    1147              :                   if (dbg) write(*,2) 'start of region', ktop, rtop
    1148              :                   if (dbg) write(*,1) 'rtop - rbot < Hp*min_gap', (rtop - rbot) - Hp*min_gap, &
    1149              :                      rtop - rbot, Hp*min_gap, Hp, min_gap, (rtop-rbot)/Hp
    1150            0 :                   if (rtop - rbot < Hp*min_gap) then
    1151            0 :                      if (kbot < nz) then
    1152            0 :                         s% cdc(ktop+1:kbot-1) = (s% cdc(ktop) + s% cdc(kbot))/2
    1153              :                         s% D_mix(ktop+1:kbot-1) = &
    1154            0 :                            (s% D_mix(ktop) + s% D_mix(kbot))/2
    1155            0 :                         s% conv_vel(ktop+1:kbot-1) = (s% conv_vel(ktop) + s% conv_vel(kbot))/2
    1156            0 :                         s% mixing_type(ktop+1:kbot-1) = mix_type
    1157              :                         if (dbg) write(*,3) 'close mixing gap', &
    1158              :                               ktop+1, kbot-1, (rtop - rbot)/Hp, rtop - rbot, Hp
    1159              :                      else
    1160            0 :                         s% cdc(ktop+1:kbot) = s% cdc(ktop)
    1161            0 :                         s% D_mix(ktop+1:kbot) = s% D_mix(ktop)
    1162            0 :                         s% conv_vel(ktop+1:kbot) = s% conv_vel(ktop)
    1163            0 :                         s% mixing_type(ktop+1:kbot) = mix_type
    1164              :                         if (dbg) write(*,3) 'close mixing gap', &
    1165              :                            ktop+1, kbot, (rtop - rbot)/Hp, rtop - rbot, Hp
    1166              :                      end if
    1167              :                   end if
    1168              :                   in_region = .true.
    1169              :                end if
    1170              :             end if
    1171              :          end do
    1172              :          if (dbg) write(*,3) 'mixing_type', 1152, s% mixing_type(1152)
    1173              :          if (dbg) write(*,*) 'done close_gaps'
    1174              :          !if (dbg) call mesa_error(__FILE__,__LINE__,'done close_gaps')
    1175              : 
    1176              :       end subroutine close_gaps
    1177              : 
    1178              : 
    1179              :       ! if find radiative region embedded in thermohaline,
    1180              :       ! and max(gradL - grada) in region is < 1d-3
    1181              :       ! and region height is < min_thermohaline_dropout
    1182              :       ! then convert the region to thermohaline
    1183           33 :       subroutine remove_thermohaline_dropouts(s, ierr)
    1184              :          type (star_info), pointer :: s
    1185              :          integer, intent(out) :: ierr
    1186              : 
    1187              :          integer :: k, nz, j
    1188              :          logical :: in_region
    1189           33 :          real(dp) :: rtop, rbot, Hp, q_upper, q_lower, alfa, beta
    1190              :          integer :: ktop, kbot  ! k's for gap
    1191              :          logical :: all_small
    1192              :          logical, parameter :: dbg = .false.
    1193              :          include 'formats'
    1194           33 :          ierr = 0
    1195           33 :          nz = s% nz
    1196           33 :          rbot = s% r(nz)
    1197           33 :          kbot = nz-1
    1198           33 :          in_region = (s% mixing_type(kbot) == no_mixing)
    1199           33 :          all_small = .false.
    1200        40667 :          do k=nz-2, 2, -1
    1201        40667 :             if (in_region) then
    1202        34666 :                if (s% mixing_type(k) == no_mixing) then  ! check if okay
    1203        34630 :                   if (s% gradL(k) - s% grada_face(k) > s% max_dropout_gradL_sub_grada) &
    1204            0 :                      all_small = .false.
    1205              :                else  ! end of radiative region
    1206           36 :                   ktop = k+1
    1207           36 :                   rtop = s% r(ktop)
    1208           36 :                   Hp = s% Peos(ktop)/(s% rho(ktop)*s% grav(ktop))
    1209           36 :                   q_upper = s% q(ktop-1)
    1210           36 :                   q_lower = s% q(kbot+1)
    1211              :                   if (rtop - rbot < Hp*s% min_thermohaline_dropout .and. &
    1212              :                       s% mixing_type(ktop-1) == thermohaline_mixing .and. &
    1213              :                       s% mixing_type(kbot+1) == thermohaline_mixing .and. &
    1214           36 :                       q_upper - q_lower > 1d-20 .and. all_small) then
    1215            0 :                      do j = ktop, kbot  ! interpolate in q
    1216            0 :                         alfa = (s% q(j) - q_lower)/(q_upper - q_lower)
    1217            0 :                         beta = 1 - alfa
    1218            0 :                         s% cdc(j) = alfa*s% cdc(ktop-1) + beta*s% cdc(kbot+1)
    1219            0 :                         s% D_mix(j) = alfa*s% D_mix(ktop-1) + beta*s% D_mix(kbot+1)
    1220            0 :                         s% conv_vel(j) = alfa*s% conv_vel(ktop-1) + beta*s% conv_vel(kbot+1)
    1221            0 :                         s% mixing_type(j) = thermohaline_mixing
    1222              :                      end do
    1223              :                   end if
    1224              :                   in_region = .false.
    1225              :                end if
    1226              :             else
    1227         5968 :                if (s% mixing_type(k) == no_mixing) then  ! start of region
    1228           69 :                   kbot = k
    1229           69 :                   rbot = s% r(kbot)
    1230           69 :                   in_region = .true.
    1231              :                   all_small = &
    1232           69 :                      (s% gradL(k) - s% grada_face(k) <= s% max_dropout_gradL_sub_grada)
    1233              :                end if
    1234              :             end if
    1235              :          end do
    1236              : 
    1237           33 :       end subroutine remove_thermohaline_dropouts
    1238              : 
    1239              : 
    1240           33 :       subroutine remove_embedded_semiconvection(s, ierr)
    1241              :          type (star_info), pointer :: s
    1242              :          integer, intent(out) :: ierr
    1243              : 
    1244              :          integer :: k, nz
    1245              :          logical :: in_region
    1246              :          integer :: kbot, ktop
    1247              : 
    1248              :          logical, parameter :: dbg = .false.
    1249              : 
    1250              :          include 'formats'
    1251              : 
    1252           33 :          ierr = 0
    1253           33 :          if (.not. s% remove_embedded_semiconvection) return
    1254              : 
    1255            0 :          nz = s% nz
    1256              : 
    1257            0 :          in_region = check(nz)
    1258            0 :          kbot = nz
    1259            0 :          do k=nz-1, 2, -1
    1260            0 :             if (in_region) then
    1261            0 :                if (.not. check(k)) then  ! end of region
    1262            0 :                   ktop = k+1
    1263            0 :                   in_region = .false.
    1264            0 :                   call clean_region
    1265              :                end if
    1266              :             else  ! not in region
    1267            0 :                if (check(k)) then  ! start of region
    1268            0 :                   kbot = k
    1269            0 :                   in_region = .true.
    1270              :                end if
    1271              :             end if
    1272              :          end do
    1273              : 
    1274            0 :          if (in_region) then
    1275            0 :             ktop = 1
    1276            0 :             call clean_region
    1277              :          end if
    1278              : 
    1279              : 
    1280              :          contains
    1281              : 
    1282              : 
    1283            0 :          subroutine clean_region
    1284              :             integer :: kbot1, ktop1
    1285              :             include 'formats'
    1286              :             if (dbg) write(*,3) 'clean_region semiconvective', kbot, ktop
    1287              :             ! move top to below top convective region
    1288            0 :             do while (s% mixing_type(ktop) == convective_mixing)
    1289            0 :                ktop = ktop + 1
    1290            0 :                if (ktop >= kbot) return
    1291              :             end do
    1292              :             if (dbg) write(*,2) 'new ktop 1', ktop
    1293              :             ! move top to below top semiconvective region
    1294            0 :             do while (s% mixing_type(ktop) == semiconvective_mixing)
    1295            0 :                ktop = ktop + 1
    1296            0 :                if (ktop >= kbot) return
    1297              :             end do
    1298              :             if (dbg) write(*,2) 'new ktop 2', ktop
    1299              :             ! move bot to above bottom convective region
    1300            0 :             do while (s% mixing_type(kbot) == convective_mixing)
    1301            0 :                kbot = kbot - 1
    1302            0 :                if (ktop >= kbot) return
    1303              :             end do
    1304              :             if (dbg) write(*,2) 'new kbot 1', kbot
    1305              :             ! move bot to above bottom semiconvective region
    1306            0 :             do while (s% mixing_type(kbot) == semiconvective_mixing)
    1307            0 :                kbot = kbot - 1
    1308            0 :                if (ktop >= kbot) return
    1309              :             end do
    1310              :             if (dbg) write(*,2) 'new kbot 2', kbot
    1311              :             ! convert any semiconvective region between kbot and ktop
    1312              :             kbot1 = kbot
    1313            0 :             do while (kbot1 > ktop)
    1314              :                ! move kbot1 to bottom of next semiconvective region
    1315            0 :                do while (s% mixing_type(kbot1) == convective_mixing)
    1316            0 :                   kbot1 = kbot1 - 1
    1317            0 :                   if (kbot1 <= ktop) return
    1318              :                end do
    1319              :                ktop1 = kbot1
    1320              :                ! move ktop1 to top of semiconvective region
    1321            0 :                do while (s% mixing_type(ktop1) == semiconvective_mixing)
    1322            0 :                   ktop1 = ktop1 - 1
    1323            0 :                   if (ktop1 <= ktop) return
    1324              :                end do
    1325            0 :                s% D_mix(ktop1+1:kbot1) = s% D_mix(ktop1)
    1326            0 :                s% mixing_type(ktop1+1:kbot1) = convective_mixing
    1327            0 :                s% conv_vel(ktop1+1:kbot1) = s% conv_vel(ktop1)
    1328              :                if (dbg) write(*,3) 'merge semiconvective island', kbot1, ktop1+1
    1329            0 :                kbot1 = ktop1
    1330              :             end do
    1331              :          end subroutine clean_region
    1332              : 
    1333              : 
    1334            0 :          logical function check(k)
    1335              :             integer, intent(in) :: k
    1336              :             check = &
    1337              :                (s% mixing_type(k) == semiconvective_mixing) .or. &
    1338            0 :                (s% mixing_type(k) == convective_mixing)
    1339            0 :          end function check
    1340              : 
    1341              :       end subroutine remove_embedded_semiconvection
    1342              : 
    1343              : 
    1344           33 :       subroutine do_mix_envelope(s)
    1345              :          type (star_info), pointer :: s
    1346           33 :          real(dp) :: T_mix_limit
    1347              :          integer :: j, k, i, nz
    1348              : 
    1349              :          include 'formats'
    1350              : 
    1351           33 :          T_mix_limit = s% T_mix_limit
    1352              :          !write(*,1) 'T_mix_limit', T_mix_limit
    1353           33 :          if (T_mix_limit <= 0) return
    1354            0 :          nz = s% nz
    1355            0 :          j = 0
    1356            0 :          do k = 1, nz  ! search inward until find T >= T_mix_limit
    1357            0 :             if (s% T(k) >= T_mix_limit) then
    1358              :                j = k; exit
    1359              :             end if
    1360              :          end do
    1361            0 :          if (j==0) j=nz  ! all T < T_mix_limit
    1362              :          ! find base of innermost convection that has T < T_mix_limit
    1363            0 :          i = 0
    1364            0 :          do k = j, 1, -1
    1365            0 :             if (s% mixing_type(k) == convective_mixing) then
    1366              :                i = k; exit
    1367              :             end if
    1368              :          end do
    1369            0 :          if (i == 0) then
    1370              :             return  ! no convection in region with T < T_mix_limit
    1371              :          end if
    1372              :          ! extend convection region to surface
    1373            0 :          j = maxloc(s% cdc(1:i), dim=1)
    1374            0 :          s% conv_vel(1:i) = s% conv_vel(j)
    1375            0 :          s% cdc(1:i) = s% cdc(j)
    1376            0 :          do k = 1,i
    1377            0 :             s% D_mix(k) = s% D_mix(j)
    1378              :          end do
    1379            0 :          s% mixing_type(1:i) = convective_mixing
    1380              : 
    1381              :       end subroutine do_mix_envelope
    1382              : 
    1383              : 
    1384           11 :       subroutine get_convection_sigmas(s, dt, ierr)
    1385              :          type (star_info), pointer :: s
    1386              :          real(dp), intent(in) :: dt
    1387              :          integer, intent(out) :: ierr
    1388              : 
    1389              :          integer :: nz, k, j, species, ktop, kbot, bdy
    1390           11 :          real(dp) :: sig_term_limit  ! sig_term_limit is used to help convergence
    1391              : 
    1392           11 :          real(dp) :: siglim, xmstar, dq00, dqm1, cdcterm, dmavg, rho_face, &
    1393           11 :             cdc, max_sig, D, xm1, x00, dm, dX, X, cushion, limit, &
    1394           11 :             Tc, full_off, full_on, qbot, qtop, f1, f, alfa
    1395           11 :          real(dp), dimension(:), pointer :: sig, D_mix
    1396              : 
    1397              :          include 'formats'
    1398              : 
    1399           11 :          sig_term_limit = s% sig_term_limit
    1400              : 
    1401           11 :          ierr = 0
    1402           11 :          nz = s% nz
    1403           11 :          xmstar = s% xmstar
    1404           11 :          sig => s% sig
    1405           11 :          D_mix => s% D_mix
    1406              : 
    1407           11 :          sig(1) = 0d0
    1408        13087 :          do k = 2, nz
    1409        13076 :             D = D_mix(k)
    1410        13076 :             if (D == 0) then
    1411        11182 :                sig(k) = 0d0
    1412        11182 :                cycle
    1413              :             end if
    1414              :             rho_face = (s% dq(k-1)*s% rho(k) + s% dq(k)*s% rho(k-1))/ &
    1415         1894 :                         (s% dq(k-1) + s% dq(k))
    1416         1894 :             f1 = pi4*s% r(k)*s% r(k)*rho_face
    1417         1894 :             f = f1*f1
    1418         1894 :             cdc = D*f
    1419         1894 :             cdcterm = s% mix_factor*cdc
    1420         1894 :             dq00 = s% dq(k)
    1421         1894 :             dqm1 = s% dq(k-1)
    1422         1894 :             dmavg = xmstar*(dq00+dqm1)/2
    1423         1894 :             sig(k) = cdcterm/dmavg
    1424         1905 :             if (is_bad_num(sig(k))) then
    1425            0 :                if (s% stop_for_bad_nums) then
    1426            0 :                   write(*,2) 'sig(k)', k, sig(k)
    1427            0 :                   call mesa_error(__FILE__,__LINE__,'get_convection_sigmas')
    1428              :                end if
    1429            0 :                sig(k) = 1d99
    1430              :             end if
    1431              :          end do
    1432              : 
    1433              :          ! can get numerical problems unless limit sig
    1434        13109 :          max_sig = maxval(sig(1:nz))
    1435           22 :          if (max_sig < 1) return
    1436        13098 :          do k = 1, nz
    1437        13087 :             s% sig_raw(k) = sig(k)
    1438        13087 :             if (sig(k) == 0) cycle
    1439         1894 :             if (k > 1) then
    1440         1894 :                siglim = sig_term_limit*xmstar*min(s% dq(k),s% dq(k-1))/dt
    1441              :             else
    1442            0 :                siglim = sig_term_limit*xmstar*s% dq(k)/dt
    1443              :             end if
    1444         1905 :             if (sig(k) > siglim) sig(k) = siglim
    1445              :          end do
    1446              : 
    1447           11 :          species = s% species
    1448              :          ! limit sigma to avoid negative mass fractions
    1449           11 :          cushion = 10d0
    1450           11 :          Tc = s% T(s% nz)
    1451           11 :          full_off = s% Tcenter_max_for_sig_min_factor_full_off
    1452           11 :          if (Tc <= full_off) return
    1453            0 :          full_on = s% Tcenter_min_for_sig_min_factor_full_on
    1454            0 :          limit = s% sig_min_factor_for_high_Tcenter
    1455            0 :          if (Tc < full_on) then
    1456            0 :             alfa = (Tc - full_off)/(full_on - full_off)
    1457              :             ! limit is full on for alfa = 1 and limit is 1 for alfa = 0
    1458            0 :             limit = limit*alfa + (1d0 - alfa)
    1459              :          end if
    1460            0 :          if (limit >= 1d0 .or. s% num_mix_regions == 0) return
    1461              :          ! boundaries are in order from center to surface
    1462              :          ! no bottom boundary at loc=nz included if center is mixed
    1463              :          ! however, do include top boundary at loc=1 if surface is mixed
    1464            0 :          if (s% top_mix_bdy(1)) then
    1465            0 :             kbot = s% nz
    1466            0 :             qbot = 0d0
    1467            0 :             bdy = 1
    1468              :          else
    1469            0 :             kbot = s% mix_bdy_loc(1)
    1470            0 :             qbot = s% q(kbot)
    1471            0 :             bdy = 2
    1472              :          end if
    1473            0 :          if (.not. s% top_mix_bdy(bdy)) then
    1474            0 :             call mesa_error(__FILE__,__LINE__,'bad mix bdy info 1')
    1475              :          end if
    1476            0 :          ktop = s% mix_bdy_loc(bdy)
    1477            0 :          qtop = s% q(ktop)
    1478            0 :          call do1_region
    1479           11 :          do while (bdy < s% num_mix_boundaries)
    1480            0 :             bdy = bdy+1
    1481            0 :             if (s% top_mix_bdy(bdy)) then
    1482            0 :                call mesa_error(__FILE__,__LINE__,'bad mix bdy info 2')
    1483              :             end if
    1484            0 :             kbot = s% mix_bdy_loc(bdy)
    1485            0 :             qbot = s% q(kbot)
    1486            0 :             bdy = bdy+1
    1487            0 :             if (.not. s% top_mix_bdy(bdy)) then
    1488            0 :                call mesa_error(__FILE__,__LINE__,'bad mix bdy info 3')
    1489              :             end if
    1490            0 :             ktop = s% mix_bdy_loc(bdy)
    1491            0 :             qtop = s% q(ktop)
    1492            0 :             call do1_region
    1493              :          end do
    1494              : 
    1495              : 
    1496              :          contains
    1497              : 
    1498              : 
    1499            0 :          subroutine do1_region
    1500            0 :             real(dp) :: delta_m, max_lim, alfa, beta, delta_m_upper, delta_m_lower
    1501            0 :             delta_m = s% m(ktop) - s% m(kbot)
    1502            0 :             delta_m_upper = s% delta_m_upper_for_sig_min_factor
    1503            0 :             delta_m_lower = s% delta_m_lower_for_sig_min_factor
    1504            0 :             if (delta_m >= delta_m_upper) then
    1505            0 :                max_lim = 1d0
    1506            0 :             else if (delta_m <= delta_m_lower) then
    1507            0 :                max_lim = limit
    1508              :             else
    1509            0 :                alfa = (delta_m - delta_m_lower)/(delta_m_upper - delta_m_lower)
    1510            0 :                beta = 1d0 - alfa
    1511            0 :                max_lim = alfa + beta*limit
    1512              :             end if
    1513            0 :             do k=max(2,ktop),kbot
    1514              :                call do1(k, max_lim, &
    1515            0 :                   min(s% q(k) - qbot, qtop - s% q(k))*s% xmstar/Msun)
    1516              :             end do
    1517            0 :          end subroutine do1_region
    1518              : 
    1519              : 
    1520            0 :          subroutine do1(k, max_lim, delta_m_to_bdy)
    1521              :             integer, intent(in) :: k
    1522              :             real(dp), intent(in) :: max_lim, delta_m_to_bdy
    1523            0 :             real(dp) :: lim, max_delta_m_to_bdy
    1524              :             include 'formats'
    1525            0 :             siglim = sig(k)
    1526            0 :             if (siglim == 0d0) return
    1527              :             ! okay to increase limit up to max_lim
    1528            0 :             max_delta_m_to_bdy = s% max_delta_m_to_bdy_for_sig_min_factor
    1529            0 :             if (delta_m_to_bdy >= max_delta_m_to_bdy) return  ! no change in sig
    1530            0 :             lim = limit + (max_lim - limit)*delta_m_to_bdy/max_delta_m_to_bdy
    1531            0 :             if (lim >= 1d0) return
    1532            0 :             do j=1,species
    1533            0 :                xm1 = s% xa(j,k-1)
    1534            0 :                x00 = s% xa(j,k)
    1535            0 :                if (xm1 > x00) then
    1536            0 :                   X = xm1
    1537            0 :                   dX = xm1 - x00
    1538            0 :                   dm = s% dm(k-1)
    1539              :                else
    1540            0 :                   X = x00
    1541            0 :                   dX = x00 - xm1
    1542            0 :                   dm = s% dm(k)
    1543            0 :                   dX = -dX
    1544              :                end if
    1545            0 :                if (X < 1d-5) cycle
    1546            0 :                if (cushion*dt*dX*siglim > dm*X) then
    1547            0 :                   siglim = dm*X/(dt*dX*cushion)
    1548              :                end if
    1549              :             end do
    1550            0 :             if (siglim > lim*sig(k)) then
    1551            0 :                sig(k) = siglim
    1552              :             else
    1553            0 :                sig(k) = lim*sig(k)
    1554              :             end if
    1555              :          end subroutine do1
    1556              : 
    1557              : 
    1558              :       end subroutine get_convection_sigmas
    1559              : 
    1560              : 
    1561            0 :       subroutine update_rotation_mixing_info(s, ierr)
    1562              :          use rotation_mix_info, only: set_rotation_mixing_info
    1563              :          type (star_info), pointer :: s
    1564              :          integer, intent(out) :: ierr
    1565              : 
    1566              :          integer :: k, nz
    1567              :          logical :: set_min_am_nu_non_rot, okay
    1568              :          real(dp) :: &
    1569            0 :             am_nu_visc_factor, &
    1570            0 :             am_nu_DSI_factor, &
    1571            0 :             am_nu_SH_factor, &
    1572            0 :             am_nu_SSI_factor, &
    1573            0 :             am_nu_ES_factor, &
    1574            0 :             am_nu_GSF_factor, &
    1575            0 :             am_nu_ST_factor, &
    1576            0 :             f, lgT, full_off, full_on, &
    1577            0 :             full_off_tau, full_on_tau
    1578              :          real(dp), dimension(:), allocatable :: &  ! work vectors for tridiagonal solve
    1579            0 :             sig, rhs, d, du, dl, bp, vp, xp, x
    1580              : 
    1581              :          include 'formats'
    1582              : 
    1583            0 :          ierr = 0
    1584            0 :          nz = s% nz
    1585              : 
    1586            0 :          call set_rotation_mixing_info(s, ierr)
    1587            0 :          if (ierr /= 0) then
    1588            0 :             if (s% report_ierr) &
    1589            0 :                write(*,*) 'update_rotation_mixing_info failed in call to set_rotation_mixing_info'
    1590            0 :             return
    1591              :          end if
    1592              : 
    1593            0 :          call check('after set_rotation_mixing_info')
    1594            0 :          if (s% D_omega_flag) call check_D_omega('check_D_omega after set_rotation_mixing_info')
    1595              : 
    1596              :          ! include rotation part for mixing abundances
    1597            0 :          full_on = s% D_mix_rotation_max_logT_full_on
    1598            0 :          full_off = s% D_mix_rotation_min_logT_full_off
    1599              : 
    1600            0 :          full_on_tau = s% D_mix_rotation_min_tau_full_on
    1601            0 :          full_off_tau = s% D_mix_rotation_min_tau_full_off
    1602            0 :          do k = 2, nz
    1603              :             ! using tau to limit D_mix rotation in core regions
    1604            0 :             lgT = s% lnT(k)/ln10
    1605              :             if (lgT <= full_on) then
    1606            0 :                f = 1d0
    1607              :             else if (lgT >= full_off) then
    1608              :                f = 0d0
    1609              :             else  ! lgT > full_on and < full_off
    1610              :                f = (lgT - full_on) / (full_off - full_on)
    1611              :             end if
    1612              : 
    1613              :             ! using tau to limit D_mix rotation in surface regions
    1614            0 :             if (s% tau(k) >= full_on_tau) then
    1615              :                f = 1d0
    1616            0 :             else if (s% tau(k) <= full_off_tau) then
    1617              :                f = 0d0
    1618              :             else  ! tau > full_off_tau and < full_on_tau
    1619            0 :                f = (lgT - full_on) / (full_off - full_on)
    1620              :             end if
    1621              : 
    1622            0 :             if (s% D_omega_flag) then
    1623            0 :                s% D_mix_rotation(k) = f*s% am_D_mix_factor*s% D_omega(k)
    1624              :             else
    1625              :                s% D_mix_rotation(k) = &
    1626              :                   f*s% am_D_mix_factor *(  &
    1627              :                      ! note: have dropped viscosity from mixing
    1628              :                      s% D_DSI_factor * s% D_DSI(k)  + &
    1629              :                      s% D_SH_factor  * s% D_SH(k)   + &
    1630              :                      s% D_SSI_factor * s% D_SSI(k)  + &
    1631              :                      s% D_ES_factor  * s% D_ES(k)   + &
    1632              :                      s% D_GSF_factor * s% D_GSF(k)  + &
    1633            0 :                      s% D_ST_factor  * s% D_ST(k))
    1634              :             end if
    1635            0 :             s% D_mix(k) = s% D_mix_non_rotation(k) + s% D_mix_rotation(k)
    1636              :          end do
    1637              : 
    1638            0 :          call check('after include rotation part for mixing abundances')
    1639              : 
    1640            0 :          am_nu_DSI_factor = s% am_nu_DSI_factor
    1641            0 :          am_nu_SH_factor = s% am_nu_SH_factor
    1642            0 :          am_nu_SSI_factor = s% am_nu_SSI_factor
    1643            0 :          am_nu_ES_factor = s% am_nu_ES_factor
    1644            0 :          am_nu_GSF_factor = s% am_nu_GSF_factor
    1645            0 :          am_nu_ST_factor = s% am_nu_ST_factor
    1646            0 :          am_nu_visc_factor = s% am_nu_visc_factor
    1647              : 
    1648            0 :          if ((.not. s% am_nu_rot_flag) .and. &
    1649              :                (s% D_omega_flag .and. .not. s% job% use_D_omega_for_am_nu_rot)) then
    1650              :             ! check for any am_nu factors > 0 and not same as for D_omega
    1651            0 :             okay = .true.
    1652            0 :             if (am_nu_DSI_factor >= 0 .and. am_nu_DSI_factor /= s% D_DSI_factor) okay = .false.
    1653            0 :             if (am_nu_SH_factor >= 0 .and. am_nu_SH_factor /= s% D_SH_factor) okay = .false.
    1654            0 :             if (am_nu_SSI_factor >= 0 .and. am_nu_SSI_factor /= s% D_SSI_factor) okay = .false.
    1655            0 :             if (am_nu_DSI_factor >= 0 .and. am_nu_DSI_factor /= s% D_DSI_factor) okay = .false.
    1656            0 :             if (am_nu_ES_factor >= 0 .and. am_nu_ES_factor /= s% D_ES_factor) okay = .false.
    1657            0 :             if (am_nu_GSF_factor >= 0 .and. am_nu_GSF_factor /= s% D_GSF_factor) okay = .false.
    1658            0 :             if (am_nu_ST_factor >= 0 .and. am_nu_ST_factor /= s% D_ST_factor) okay = .false.
    1659            0 :             if (.not. okay) then
    1660            0 :                write(*,*) 'have an am_nu factor >= 0 and not same as corresponding D_omega factor'
    1661            0 :                write(*,*) 'so if want smoothing like D_omega, must set am_nu_rot_flag true'
    1662            0 :                write(*,*) 'please fix this'
    1663            0 :                ierr = -1
    1664            0 :                return
    1665              :             end if
    1666              :          end if
    1667              : 
    1668              :          ! If am_nu_..._factor < -1, use the D_..._factor
    1669            0 :          if (am_nu_DSI_factor < 0) am_nu_DSI_factor = s% D_DSI_factor
    1670            0 :          if (am_nu_SH_factor < 0) am_nu_SH_factor = s% D_SH_factor
    1671            0 :          if (am_nu_SSI_factor < 0) am_nu_SSI_factor = s% D_SSI_factor
    1672            0 :          if (am_nu_ES_factor < 0) am_nu_ES_factor = s% D_ES_factor
    1673            0 :          if (am_nu_GSF_factor < 0) am_nu_GSF_factor = s% D_GSF_factor
    1674            0 :          if (am_nu_ST_factor < 0) am_nu_ST_factor = s% D_ST_factor
    1675            0 :          if (am_nu_visc_factor < 0) am_nu_visc_factor = s% D_visc_factor
    1676              : 
    1677              :          ! set set_min_am_nu_non_rot to s% set_min_am_nu_non_rot if
    1678              :          ! ye > min_center_ye_for_min_am_nu_non_rot
    1679              :          ! and s% set_min_am_nu_non_rot
    1680              :          set_min_am_nu_non_rot = &
    1681              :             s% set_min_am_nu_non_rot .and. &
    1682              :             s% ye(nz) >= s% min_center_Ye_for_min_am_nu_non_rot .and. &
    1683            0 :             (.not. s% set_uniform_am_nu_non_rot)
    1684              : 
    1685            0 :          if (s% am_nu_rot_flag) then
    1686            0 :             call set_am_nu_rot(ierr)
    1687            0 :             if (ierr /= 0) return
    1688              :          end if
    1689              : 
    1690            0 :          do k=1,nz
    1691            0 :             if (s% set_uniform_am_nu_non_rot) then
    1692            0 :                s% am_nu_non_rot(k) = s% uniform_am_nu_non_rot
    1693              :             else
    1694              :                s% am_nu_non_rot(k) = s% am_nu_factor* &
    1695            0 :                   s% am_nu_non_rotation_factor*s% D_mix_non_rotation(k)
    1696              :             end if
    1697            0 :             if (set_min_am_nu_non_rot) &
    1698            0 :                s% am_nu_non_rot(k) = max(s% min_am_nu_non_rot, s% am_nu_non_rot(k))
    1699            0 :             if (s% am_nu_rot_flag) then
    1700              :                ! already have am_nu_rot(k) from calling set_am_nu_rot above
    1701            0 :             else if (s% D_omega_flag .and. s% job% use_D_omega_for_am_nu_rot) then
    1702            0 :                s% am_nu_rot(k) = s% am_nu_factor*s% D_omega(k)
    1703              :             else
    1704              :                s% am_nu_rot(k) = s% am_nu_factor * ( &
    1705              :                   am_nu_visc_factor*s% D_visc(k) + &
    1706              :                   am_nu_DSI_factor*s% D_DSI(k) + &
    1707              :                   am_nu_SH_factor*s% D_SH(k) + &
    1708              :                   am_nu_SSI_factor*s% D_SSI(k) + &
    1709              :                   am_nu_ES_factor*s% D_ES(k) + &
    1710              :                   am_nu_GSF_factor*s% D_GSF(k) + &
    1711            0 :                   am_nu_ST_factor*s% nu_ST(k))
    1712              :             end if
    1713            0 :             if (s% am_nu_rot(k) < 0d0) s% am_nu_rot(k) = 0d0
    1714              :             s% am_nu_omega(k) = &
    1715              :                s% am_nu_omega_non_rot_factor*s% am_nu_non_rot(k) + &
    1716            0 :                s% am_nu_omega_rot_factor*s% am_nu_rot(k)
    1717            0 :             if (s% am_nu_omega(k) < 0) then
    1718            0 :                ierr = -1
    1719            0 :                if (s% report_ierr) write(*,3) &
    1720            0 :                   'update_rotation_mixing_info: am_nu_omega(k) < 0', k, nz, s% am_nu_omega(k), &
    1721            0 :                   s% am_nu_non_rot(k), s% am_nu_rot(k), s% D_omega(k)
    1722            0 :                return
    1723              :             end if
    1724              :             s% am_nu_j(k) = &
    1725              :                s% am_nu_j_non_rot_factor*s% am_nu_non_rot(k) + &
    1726            0 :                s% am_nu_j_rot_factor*s% am_nu_rot(k)
    1727            0 :             if (s% am_nu_j(k) < 0) then
    1728            0 :                ierr = -1
    1729            0 :                if (s% report_ierr) write(*,3) &
    1730            0 :                   'update_rotation_mixing_info: am_nu_j(k) < 0', k, nz, s% am_nu_j(k), &
    1731            0 :                   s% am_nu_non_rot(k), s% am_nu_rot(k), s% D_omega(k)
    1732            0 :                return
    1733              :             end if
    1734              :          end do
    1735              : 
    1736            0 :          if (s% use_other_am_mixing) then
    1737            0 :             call s% other_am_mixing(s% id, ierr)
    1738            0 :             if (ierr /= 0) return
    1739              :          end if
    1740              : 
    1741              :          contains
    1742              : 
    1743            0 :          subroutine check(str)
    1744              :             character(len=*) :: str
    1745              :             integer :: k
    1746              :             include 'formats'
    1747            0 :             do k = 2, s% nz
    1748            0 :                if (is_bad_num(s% D_mix(k))) then
    1749            0 :                   ierr = -1
    1750            0 :                   if (s% report_ierr) then
    1751            0 :                      write(*,3) trim(str) // ' mixing_type, D_mix', k, s% mixing_type(k), s% D_mix(k)
    1752            0 :                      if (s% rotation_flag) then
    1753            0 :                         if (is_bad_num(s% D_mix_non_rotation(k))) &
    1754            0 :                            write(*,2) 's% D_mix_non_rotation(k)', k, s% D_mix_non_rotation(k)
    1755            0 :                         if (is_bad_num(s% D_visc(k))) write(*,2) 's% D_visc(k)', k, s% D_visc(k)
    1756            0 :                         if (is_bad_num(s% D_DSI(k))) write(*,2) 's% D_DSI(k)', k, s% D_DSI(k)
    1757            0 :                         if (is_bad_num(s% D_SH(k))) write(*,2) 's% D_SH(k)', k, s% D_SH(k)
    1758            0 :                         if (is_bad_num(s% D_SSI(k))) write(*,2) 's% D_SSI(k)', k, s% D_SSI(k)
    1759            0 :                         if (is_bad_num(s% D_ES(k))) write(*,2) 's% D_ES(k)', k, s% D_ES(k)
    1760            0 :                         if (is_bad_num(s% D_GSF(k))) write(*,2) 's% D_GSF(k)', k, s% D_GSF(k)
    1761            0 :                         if (is_bad_num(s% D_ST(k))) write(*,2) 's% D_ST(k)', k, s% D_ST(k)
    1762              :                      end if
    1763              :                   end if
    1764            0 :                   if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'set mixing info')
    1765              :                end if
    1766              :             end do
    1767            0 :          end subroutine check
    1768              : 
    1769            0 :          subroutine check_D_omega(str)
    1770              :             character(len=*) :: str
    1771              :             integer :: k
    1772              :             include 'formats'
    1773            0 :             do k = 2, s% nz
    1774            0 :                if (is_bad_num(s% D_omega(k))) then
    1775            0 :                   ierr = -1
    1776            0 :                   if (s% report_ierr) then
    1777            0 :                      write(*,3) trim(str) // ' mixing_type, D_omega', k, s% mixing_type(k), s% D_omega(k)
    1778            0 :                      write(*,*) 's% doing_finish_load_model', s% doing_finish_load_model
    1779            0 :                      if (s% rotation_flag) then
    1780            0 :                         if (is_bad_num(s% D_mix_non_rotation(k))) &
    1781            0 :                            write(*,2) 's% D_mix_non_rotation(k)', k, s% D_mix_non_rotation(k)
    1782            0 :                         if (is_bad_num(s% D_visc(k))) write(*,2) 's% D_visc(k)', k, s% D_visc(k)
    1783            0 :                         if (is_bad_num(s% D_DSI(k))) write(*,2) 's% D_DSI(k)', k, s% D_DSI(k)
    1784            0 :                         if (is_bad_num(s% D_SH(k))) write(*,2) 's% D_SH(k)', k, s% D_SH(k)
    1785            0 :                         if (is_bad_num(s% D_SSI(k))) write(*,2) 's% D_SSI(k)', k, s% D_SSI(k)
    1786            0 :                         if (is_bad_num(s% D_ES(k))) write(*,2) 's% D_ES(k)', k, s% D_ES(k)
    1787            0 :                         if (is_bad_num(s% D_GSF(k))) write(*,2) 's% D_GSF(k)', k, s% D_GSF(k)
    1788            0 :                         if (is_bad_num(s% D_ST(k))) write(*,2) 's% D_ST(k)', k, s% D_ST(k)
    1789              :                      end if
    1790              :                   end if
    1791            0 :                   if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'set mixing info')
    1792              :                end if
    1793              :             end do
    1794            0 :          end subroutine check_D_omega
    1795              : 
    1796            0 :          subroutine set_am_nu_rot(ierr)
    1797              :             use alloc
    1798              :             use rotation_mix_info, only: smooth_for_rotation
    1799              :             integer, intent(out) :: ierr
    1800              :             integer :: i, k, nz
    1801              :             real(dp) :: &
    1802            0 :                dt, rate, d_ddt_dm1, d_ddt_d00, d_ddt_dp1, m, &
    1803            0 :                d_dt, d_dt_in, d_dt_out, am_nu_rot_source
    1804              :             include 'formats'
    1805              : 
    1806            0 :             ierr = 0
    1807            0 :             nz = s% nz
    1808            0 :             dt = s% dt
    1809              : 
    1810            0 :             if (s% am_nu_rot_flag .and. s% doing_finish_load_model) then
    1811            0 :                do k=1,nz
    1812            0 :                   s% am_nu_rot(k) = 0d0
    1813              :                end do
    1814            0 :             else if (s% am_nu_rot_flag) then
    1815              : 
    1816            0 :                do k=1,nz
    1817            0 :                   if (s% q(k) <= s% max_q_for_nu_omega_zero_in_convection_region .and. &
    1818              :                       s% mixing_type(k) == convective_mixing) then
    1819            0 :                      s% am_nu_rot(k) = 0d0
    1820            0 :                      cycle
    1821              :                   end if
    1822              :                   am_nu_rot_source = s% am_nu_factor * ( &
    1823              :                      am_nu_visc_factor*s% D_visc(k) + &
    1824              :                      am_nu_DSI_factor*s% D_DSI(k) + &
    1825              :                      am_nu_SH_factor*s% D_SH(k) + &
    1826              :                      am_nu_SSI_factor*s% D_SSI(k) + &
    1827              :                      am_nu_ES_factor*s% D_ES(k) + &
    1828              :                      am_nu_GSF_factor*s% D_GSF(k) + &
    1829            0 :                      am_nu_ST_factor*s% nu_ST(k))
    1830            0 :                   if (is_bad(am_nu_rot_source)) then
    1831            0 :                      write(*,2) 'am_nu_rot_source', k, am_nu_rot_source
    1832            0 :                      call mesa_error(__FILE__,__LINE__,'set am_nu_rot')
    1833              :                   end if
    1834            0 :                   s% am_nu_rot(k) = am_nu_rot_source
    1835            0 :                   if (is_bad(s% am_nu_rot(k))) then
    1836            0 :                      write(*,2) 's% am_nu_rot(k)', k, s% am_nu_rot(k)
    1837            0 :                      write(*,2) 'am_nu_rot_source', k, am_nu_rot_source
    1838            0 :                      call mesa_error(__FILE__,__LINE__,'set am_nu_rot')
    1839              :                   end if
    1840              :                end do
    1841              : 
    1842            0 :                if (s% smooth_am_nu_rot > 0 .or. &
    1843              :                     (s% nu_omega_mixing_rate > 0d0 .and. s% dt > 0)) then
    1844              : 
    1845            0 :                   allocate(sig(nz), rhs(nz), d(nz), du(nz), dl(nz), bp(nz), vp(nz), xp(nz), x(nz))
    1846              : 
    1847            0 :                   if (s% smooth_am_nu_rot > 0) then
    1848            0 :                      call smooth_for_rotation(s, s% am_nu_rot, s% smooth_am_nu_rot, sig)
    1849              :                   end if
    1850              : 
    1851            0 :                   if (s% nu_omega_mixing_rate > 0d0 .and. s% dt > 0) then  ! mix am_nu_rot
    1852              : 
    1853            0 :                      rate = min(s% nu_omega_mixing_rate, 1d0/dt)
    1854            0 :                      do k=2,nz-1
    1855            0 :                         if (s% am_nu_rot(k) == 0 .or. s% am_nu_rot(k+1) == 0) then
    1856            0 :                            sig(k) = 0
    1857              :                         else if ((.not. s% nu_omega_mixing_across_convection_boundary) .and. &
    1858            0 :                            s% mixing_type(k) /= convective_mixing .and. &
    1859              :                                (s% mixing_type(k-1) == convective_mixing .or. &
    1860              :                                 s% mixing_type(k+1) == convective_mixing)) then
    1861            0 :                             sig(k) = 0
    1862              :                         else
    1863            0 :                            sig(k) = rate*dt
    1864              :                         end if
    1865              :                      end do
    1866            0 :                      sig(1) = 0
    1867            0 :                      sig(nz) = 0
    1868              : 
    1869            0 :                      do k=1,nz
    1870            0 :                         if (k < nz) then
    1871            0 :                            d_dt_in = sig(k)*(s% am_nu_rot(k+1) - s% am_nu_rot(k))
    1872              :                         else
    1873            0 :                            d_dt_in = -sig(k)*s% am_nu_rot(k)
    1874              :                         end if
    1875            0 :                         if (k > 1) then
    1876            0 :                            d_dt_out = sig(k-1)*(s% am_nu_rot(k) - s% am_nu_rot(k-1))
    1877            0 :                            d_ddt_dm1 = sig(k-1)
    1878            0 :                            d_ddt_d00 = -(sig(k-1) + sig(k))
    1879              :                         else
    1880            0 :                            d_dt_out = 0
    1881            0 :                            d_ddt_dm1 = 0
    1882            0 :                            d_ddt_d00 = -sig(k)
    1883              :                         end if
    1884            0 :                         d_dt = d_dt_in - d_dt_out
    1885            0 :                         d_ddt_dp1 = sig(k)
    1886            0 :                         rhs(k) = d_dt
    1887            0 :                         d(k) = 1d0 - d_ddt_d00
    1888            0 :                         if (k < nz) then
    1889            0 :                            du(k) = -d_ddt_dp1
    1890              :                         else
    1891            0 :                            du(k) = 0
    1892              :                         end if
    1893            0 :                         if (k > 1) dl(k-1) = -d_ddt_dm1
    1894              :                      end do
    1895            0 :                      dl(nz) = 0
    1896              : 
    1897              :                      ! solve tridiagonal
    1898            0 :                      bp(1) = d(1)
    1899            0 :                      vp(1) = rhs(1)
    1900            0 :                      do i = 2,nz
    1901            0 :                         if (bp(i-1) == 0) then
    1902            0 :                            write(*,*) 'failed in set_am_nu_rot', s% model_number
    1903            0 :                            call mesa_error(__FILE__,__LINE__,'mix_am_nu_rot')
    1904            0 :                            ierr = -1
    1905            0 :                            return
    1906              :                         end if
    1907            0 :                         m = dl(i-1)/bp(i-1)
    1908            0 :                         bp(i) = d(i) - m*du(i-1)
    1909            0 :                         vp(i) = rhs(i) - m*vp(i-1)
    1910              :                      end do
    1911            0 :                      xp(nz) = vp(nz)/bp(nz)
    1912            0 :                      x(nz) = xp(nz)
    1913            0 :                      do i = nz-1, 1, -1
    1914            0 :                         xp(i) = (vp(i) - du(i)*xp(i+1))/bp(i)
    1915            0 :                         x(i) = xp(i)
    1916              :                      end do
    1917              : 
    1918            0 :                      do k=2,nz
    1919            0 :                         if (is_bad(x(k))) then
    1920              :                            return
    1921              :                            write(*,3) 's% am_nu_rot(k) prev, x', k, &
    1922              :                               s% model_number, s% am_nu_rot(k), x(k), bp(i)
    1923              :                            call mesa_error(__FILE__,__LINE__,'mix_am_nu_rot')
    1924              :                         end if
    1925              :                      end do
    1926              : 
    1927              :                      ! update am_nu_rot
    1928            0 :                      do k=2,nz
    1929            0 :                         s% am_nu_rot(k) = s% am_nu_rot(k) + x(k)
    1930            0 :                         if (is_bad(s% am_nu_rot(k))) then
    1931            0 :                            write(*,3) 's% am_nu_rot(k)', k, s% model_number, s% am_nu_rot(k)
    1932            0 :                            call mesa_error(__FILE__,__LINE__,'mix_am_nu_rot')
    1933              :                         end if
    1934            0 :                         if (s% am_nu_rot(k) < 0d0) s% am_nu_rot(k) = 0d0
    1935              :                      end do
    1936            0 :                      s% am_nu_rot(1) = 0d0
    1937              : 
    1938              :                   end if
    1939              : 
    1940              :                end if
    1941              : 
    1942              :             end if
    1943              : 
    1944            0 :             if (s% am_nu_rot_flag) then  ! check
    1945            0 :                do k=1,nz
    1946            0 :                   if (is_bad(s% am_nu_rot(k))) then
    1947            0 :                      write(*,2) 'before return s% am_nu_rot(k)', k, s% am_nu_rot(k)
    1948            0 :                      call mesa_error(__FILE__,__LINE__,'set_am_nu_rot')
    1949              :                   end if
    1950            0 :                   if (s% am_nu_rot(k) < 0d0) s% am_nu_rot(k) = 0d0
    1951              :                end do
    1952              :             end if
    1953              : 
    1954            0 :          end subroutine set_am_nu_rot
    1955              : 
    1956              :       end subroutine update_rotation_mixing_info
    1957              : 
    1958              : 
    1959            0 :       subroutine set_RTI_mixing_info(s, ierr)
    1960              :          use chem_def, only: ih1
    1961              :          use star_utils, only: get_shock_info
    1962              :          type (star_info), pointer :: s
    1963              :          integer, intent(out) :: ierr
    1964              :          real(dp) :: &
    1965            0 :             C, alpha_face, f, v, &
    1966            0 :             min_dm, alfa, cs, r, shock_mass_start, &
    1967            0 :             log_max_boost, m_full_boost, m_no_boost, max_boost, &
    1968            0 :             dm_for_center_eta_nondecreasing, min_eta
    1969              :          integer :: k, nz, i_h1
    1970              :          include 'formats'
    1971            0 :          ierr = 0
    1972            0 :          if (.not. s% RTI_flag) return
    1973              : 
    1974            0 :          nz = s% nz
    1975              : 
    1976            0 :          s% eta_RTI(1:nz) = 0d0
    1977            0 :          s% etamid_RTI(1:nz) = 0d0
    1978            0 :          s% boost_for_eta_RTI(1:nz) = 0d0
    1979            0 :          s% sig_RTI(1:nz) = 0d0
    1980            0 :          s% sigmid_RTI(1:nz) = 0d0
    1981              : 
    1982            0 :          if (s% RTI_C <= 0d0) return
    1983              : 
    1984            0 :          i_h1 = s% net_iso(ih1)
    1985              : 
    1986            0 :          shock_mass_start = 1d99
    1987            0 :          do k = 1, nz
    1988            0 :             if (s% u_flag) then
    1989            0 :                v = s% u(k)
    1990              :             else
    1991            0 :                v = s% v(k)
    1992              :             end if
    1993            0 :             if (v > s% csound(k)) then
    1994            0 :                if (k > 1) shock_mass_start = s% m(k)  ! skip this after breakout
    1995              :                exit
    1996              :             end if
    1997              :          end do
    1998              : 
    1999            0 :          min_dm = s% RTI_min_dm_behind_shock_for_full_on*Msun
    2000            0 :          log_max_boost = s% RTI_log_max_boost
    2001            0 :          max_boost = exp10(log_max_boost)
    2002            0 :          m_full_boost = s% RTI_m_full_boost*Msun
    2003            0 :          m_no_boost = s% RTI_m_no_boost*Msun
    2004              : 
    2005            0 :          min_eta = -1d0
    2006            0 :          dm_for_center_eta_nondecreasing = Msun*s% RTI_dm_for_center_eta_nondecreasing
    2007              : 
    2008            0 :          do k=1,nz
    2009              : 
    2010            0 :             f = max(0d0, s% X(k) - s% RTI_C_X0_frac*s% surface_h1)
    2011            0 :             C = s% RTI_C*(1d0 + f*f*s% RTI_C_X_factor)
    2012              : 
    2013            0 :             if (s% m(k) < m_no_boost) then
    2014            0 :                if (s% m(k) <= m_full_boost) then
    2015            0 :                   C = C*max_boost
    2016              :                else
    2017            0 :                   alfa = (m_no_boost - s% m(k))/(m_no_boost - m_full_boost)
    2018            0 :                   C = C*exp10(alfa*log_max_boost)
    2019              :                end if
    2020              :             end if
    2021              : 
    2022            0 :             if (shock_mass_start - s% m(k) < min_dm) &
    2023            0 :                C = C*(shock_mass_start - s% m(k))/min_dm
    2024              : 
    2025            0 :             if (k > 1) then
    2026              :                alpha_face = &
    2027              :                   (s% dq(k-1)*s% alpha_RTI(k) + s% dq(k)*s% alpha_RTI(k-1))/ &
    2028            0 :                      (s% dq(k-1) + s% dq(k))
    2029            0 :                cs = s% csound_face(k)
    2030            0 :                r = s% r(k)
    2031            0 :                s% eta_RTI(k) = C*alpha_face*cs*r
    2032              : 
    2033            0 :                if (is_bad(s% eta_RTI(k)) .and. s% q(k) <= s% alpha_RTI_src_max_q) then
    2034            0 :                   ierr = -1
    2035            0 :                   return
    2036              :                   if (s% stop_for_bad_nums) then
    2037              :                      write(*,2) 's% eta_RTI(k)', k, s% eta_RTI(k)
    2038              :                      call mesa_error(__FILE__,__LINE__,'set_RTI_mixing_info')
    2039              :                   end if
    2040              :                end if
    2041              : 
    2042            0 :                if (s% m(k) - s% M_center <= dm_for_center_eta_nondecreasing) then
    2043            0 :                   if (min_eta < 0d0) then
    2044              :                      min_eta = s% eta_RTI(k)
    2045            0 :                   else if (min_eta > s% eta_RTI(k)) then
    2046            0 :                      s% eta_RTI(k) = min_eta
    2047              :                   end if
    2048              :                end if
    2049              : 
    2050              :             end if
    2051              : 
    2052            0 :             s% etamid_RTI(k) = max(min_eta, C*s% alpha_RTI(k)*s% csound(k)*s% rmid(k))
    2053            0 :             s% boost_for_eta_RTI(k) = C/s% RTI_C
    2054              : 
    2055            0 :             if (is_bad(s% etamid_RTI(k))) then
    2056            0 :                ierr = -1
    2057            0 :                return
    2058              :             end if
    2059              : 
    2060              :          end do
    2061              : 
    2062            0 :          call get_shock_info(s)
    2063              : 
    2064              :          ! sig_RTI(k) is mixing flow across face k in (gm sec^1)
    2065              :          call get_RTI_sigmas(s, s% sig_RTI, s% eta_RTI, &
    2066            0 :             s% rho_face, s% r, s% dm_bar, s% dt, ierr)
    2067            0 :          if (ierr /= 0) return
    2068              : 
    2069            0 :          if (s% v_flag) then
    2070              :             ! sigmid_RTI(k) is mixing flow at center k in (gm sec^1)
    2071              :             call get_RTI_sigmas(s, s% sigmid_RTI, s% etamid_RTI, &
    2072            0 :                s% rho, s% rmid, s% dm, s% dt, ierr)
    2073            0 :             if (ierr /= 0) return
    2074              :          end if
    2075              : 
    2076            0 :       end subroutine set_RTI_mixing_info
    2077              : 
    2078              : 
    2079            0 :       subroutine get_RTI_sigmas(s, sig, eta, rho, r, dm_bar, dt, ierr)
    2080              :          type (star_info), pointer :: s
    2081              :          real(dp), dimension(:) :: sig, eta, rho, r, dm_bar
    2082              :          real(dp), intent(in) :: dt
    2083              :          integer, intent(out) :: ierr
    2084              : 
    2085              :          integer :: nz, k
    2086            0 :          real(dp) :: D, f1, f, cdcterm, max_sig, &
    2087            0 :             siglim, sig_term_limit, xmstar
    2088              : 
    2089              :          include 'formats'
    2090              : 
    2091            0 :          ierr = 0
    2092            0 :          nz = s% nz
    2093            0 :          xmstar = s% xmstar
    2094            0 :          sig_term_limit = s% sig_term_limit
    2095              : 
    2096            0 :          sig(1) = 0d0
    2097            0 :          max_sig = 0d0
    2098            0 :          do k = 2, nz
    2099            0 :             D = eta(k)
    2100            0 :             if (D <= 0 .or. &
    2101              :                   (s% q(k) > s% shock_q .and. s% shock_q > 0d0)) then
    2102            0 :                sig(k) = 0d0
    2103            0 :                cycle
    2104              :             end if
    2105            0 :             f1 = pi4*r(k)*r(k)*rho(k)
    2106            0 :             f = f1*f1
    2107            0 :             cdcterm = s% mix_factor*D*f
    2108            0 :             sig(k) = cdcterm/dm_bar(k)
    2109            0 :             if (is_bad(sig(k))) then
    2110            0 :                if (s% stop_for_bad_nums) then
    2111            0 :                   write(*,2) 'sig(k)', k, sig(k)
    2112            0 :                   call mesa_error(__FILE__,__LINE__,'get_RTI_sigmas')
    2113              :                end if
    2114            0 :                sig(k) = 1d99
    2115              :             end if
    2116            0 :             if (sig(k) > max_sig) max_sig = sig(k)
    2117              :          end do
    2118              : 
    2119            0 :          if (max_sig < 1) return
    2120            0 :          do k = 1, nz
    2121            0 :             if (sig(k) == 0) cycle
    2122            0 :             siglim = sig_term_limit*dm_bar(k)/dt
    2123            0 :             if (sig(k) > siglim) sig(k) = siglim
    2124              :          end do
    2125              : 
    2126            0 :       end subroutine get_RTI_sigmas
    2127              : 
    2128              : 
    2129            0 :       subroutine set_dPdr_dRhodr_info(s, ierr)
    2130              :          type (star_info), pointer :: s
    2131              :          integer, intent(out) :: ierr
    2132            0 :          real(dp) :: rho, r00, alfa00, beta00, &
    2133            0 :             dr_m1, dr_00, c, d, am1, a00, ap1, v, rmid
    2134            0 :          real(dp), allocatable, dimension(:) :: dPdr, drhodr, P_face, rho_face
    2135              :          integer :: k, nz
    2136              :          logical, parameter :: do_slope_limiting = .false.
    2137              :          include 'formats'
    2138            0 :          ierr = 0
    2139            0 :          if (.not. s% RTI_flag) return
    2140            0 :          if (s% dPdr_dRhodr_info(1) >= 0d0) then
    2141            0 :             if (is_bad(s% dPdr_dRhodr_info(1))) call mesa_error(__FILE__,__LINE__,'set_dPdr_dRhodr_info')
    2142            0 :             return  ! already set this step
    2143              :          end if
    2144              : 
    2145            0 :          nz = s% nz
    2146              : 
    2147            0 :          allocate(dPdr(nz), drhodr(nz), P_face(nz), rho_face(nz))
    2148              : 
    2149            0 :          do k=2,nz
    2150            0 :             rho = s% rho(k)
    2151            0 :             r00 = s% r(k)
    2152            0 :             alfa00 = s% dq(k-1)/(s% dq(k-1) + s% dq(k))
    2153            0 :             beta00 = 1d0 - alfa00
    2154            0 :             P_face(k) = alfa00*s% Peos(k) + beta00*s% Peos(k-1)
    2155            0 :             rho_face(k) = alfa00*s% rho(k) + beta00*s% rho(k-1)
    2156              :          end do
    2157            0 :          P_face(1) = s% Peos(1)
    2158            0 :          rho_face(1) = s% rho(1)
    2159              : 
    2160            0 :          do k=1,nz
    2161            0 :             if (s% u_flag) then
    2162            0 :                v = s% u(k)
    2163              :             else
    2164            0 :                v = s% v(k)
    2165              :             end if
    2166            0 :             if (k == nz .or. k == 1 .or.  &
    2167              :                   (s% alpha_RTI_start(k) == 0d0 .and. &
    2168            0 :                      v/s% csound(k) < s% alpha_RTI_src_min_v_div_cs)) then
    2169            0 :                drhodr(k) = 0d0
    2170            0 :                dPdr(k) = 0d0
    2171              :             else if (do_slope_limiting) then
    2172              :                dr_m1 = s% r(k-1) - s% r(k)
    2173              :                dr_00 = s% r(k) - s% r(k+1)
    2174              :                dPdr(k) = slope_limit(P_face, k, dr_m1, dr_00)
    2175              :                drhodr(k) = slope_limit(rho_face, k, dr_m1, dr_00)
    2176              :             else
    2177              :                !dr_00 = s% r(k) - s% r(k+1)
    2178            0 :                rmid = 0.5d0*(s% r(k) + s% r(k+1))
    2179            0 :                dr_00 = s% dm(k)/(pi4*rmid*rmid*s% rho(k))  ! don't subtract r's to get dr
    2180            0 :                dPdr(k) = (P_face(k) - P_face(k+1))/dr_00
    2181            0 :                drhodr(k) = (rho_face(k) - rho_face(k+1))/dr_00
    2182              :             end if
    2183              :          end do
    2184              : 
    2185              :          ! smooth dPdr and drhodr
    2186            0 :          if (s% RTI_smooth_mass > 0d0 .and. s% RTI_smooth_iterations > 0) then
    2187              :             call do_smoothing_by_mass( &
    2188            0 :                s, s% RTI_smooth_mass, s% RTI_smooth_iterations, drhodr, ierr)
    2189            0 :             if (ierr /= 0) return
    2190              :             call do_smoothing_by_mass( &
    2191            0 :                s, s% RTI_smooth_mass, s% RTI_smooth_iterations, dPdr, ierr)
    2192            0 :             if (ierr /= 0) return
    2193            0 :          else if (s% RTI_smooth_fraction < 1d0) then
    2194            0 :             c = s% RTI_smooth_fraction
    2195            0 :             d = 0.5d0*(1d0 - c)
    2196            0 :             am1 = 0
    2197            0 :             a00 = dPdr(1)
    2198            0 :             ap1 = dPdr(2)
    2199            0 :             do k=2,nz-1
    2200            0 :                am1 = a00
    2201            0 :                a00 = ap1
    2202            0 :                ap1 = dPdr(k+1)
    2203            0 :                dPdr(k) = c*a00 + d*(am1 + ap1)
    2204              :             end do
    2205            0 :             dPdr(nz) = c*a00 + 2*d*am1
    2206            0 :             a00 = drhodr(1)
    2207            0 :             ap1 = drhodr(2)
    2208            0 :             do k=2,nz-1
    2209            0 :                am1 = a00
    2210            0 :                a00 = ap1
    2211            0 :                ap1 = drhodr(k+1)
    2212            0 :                if (am1 == 0d0 .and. a00 == 0d0) cycle
    2213            0 :                drhodr(k) = c*a00 + d*(am1 + ap1)
    2214              :             end do
    2215            0 :             drhodr(nz) = c*a00 + 2*d*am1
    2216              :          end if
    2217              : 
    2218              :          ! set
    2219            0 :          do k=1,nz
    2220            0 :             s% dPdr_info(k) = dPdr(k)
    2221            0 :             s% dRhodr_info(k) = drhodr(k)
    2222            0 :             s% dPdr_dRhodr_info(k) = min(0d0,dPdr(k)*drhodr(k))
    2223              :          end do
    2224              : 
    2225              :          contains
    2226              : 
    2227              :          real(dp) function slope_limit(v, k, dr_m1, dr_00)
    2228              :             real(dp), intent(in) :: v(:), dr_m1, dr_00
    2229              :             integer, intent(in) :: k
    2230              :             real(dp) :: s_00, s_p1
    2231              :             s_00 = (v(k-1) - v(k))/dr_m1
    2232              :             s_p1 = (v(k) - v(k+1))/dr_00
    2233              :             if (s_00*s_p1 < 0d0) then
    2234              :                slope_limit = 0d0
    2235              :             else if(abs(s_00) > abs(s_p1)) then
    2236              :                slope_limit = s_p1
    2237              :             else
    2238              :                slope_limit = s_00
    2239              :             end if
    2240              :          end function slope_limit
    2241              : 
    2242              :       end subroutine set_dPdr_dRhodr_info
    2243              : 
    2244              : 
    2245            0 :       subroutine do_smoothing_by_mass( &
    2246            0 :             s, smooth_mass, number_iterations, val, ierr)
    2247              :          type (star_info), pointer :: s
    2248              :          real(dp), intent(in) :: smooth_mass
    2249              :          integer, intent(in) :: number_iterations
    2250              :          real(dp) :: val(:)
    2251              :          integer, intent(out) :: ierr
    2252              :          integer :: nz, iter, k_center, k_inner, k_outer, k
    2253            0 :          real(dp) :: mlo, mhi, mmid, smooth_m, v, dm_half, mtotal, mass_from_cell
    2254            0 :          real(dp), allocatable :: work(:)
    2255              :          include 'formats'
    2256            0 :          ierr = 0
    2257            0 :          nz = s% nz
    2258            0 :          allocate(work(nz))
    2259            0 :          do k = 1, nz
    2260            0 :             work(k) = val(k)
    2261              :          end do
    2262            0 :          smooth_m = smooth_mass*Msun
    2263            0 :          dm_half = 0.5d0*smooth_m
    2264            0 :          do iter = 1, number_iterations
    2265            0 :             do k_center = nz-1, 2, -1
    2266            0 :                mmid = s% m(k_center) - 0.5d0*s% dm(k_center)
    2267            0 :                mlo = mmid - dm_half
    2268            0 :                mhi = mmid + dm_half
    2269            0 :                k_inner = k_center
    2270            0 :                v = 0d0
    2271            0 :                mtotal = 0d0
    2272            0 :                do k=k_center, nz, -1
    2273            0 :                   if (s% m(k) - 0.5d0*s% dm(k) <= mlo) then
    2274            0 :                      k_inner = k
    2275            0 :                      mass_from_cell = s% m(k) - mlo
    2276            0 :                      v = v + val(k)*mass_from_cell
    2277            0 :                      mtotal = mtotal + mass_from_cell
    2278            0 :                      exit
    2279              :                   end if
    2280              :                end do
    2281            0 :                k_outer = k_center
    2282            0 :                do k=k_center,1,-1
    2283            0 :                   if (s% m(k) >= mhi) then
    2284            0 :                      k_outer = k
    2285            0 :                      mass_from_cell = mhi - (s% m(k) - s% dm(k))
    2286            0 :                      v = v + val(k)*mass_from_cell
    2287            0 :                      mtotal = mtotal + mass_from_cell
    2288            0 :                      exit
    2289              :                   end if
    2290              :                end do
    2291            0 :                do k=k_outer+1,k_inner-1
    2292            0 :                   v = v + val(k)*s% dm(k)
    2293            0 :                   mtotal = mtotal + s% dm(k)
    2294              :                end do
    2295            0 :                if(mtotal>0d0) then
    2296            0 :                   work(k_center) = v/mtotal
    2297              :                else
    2298            0 :                   work(k_center) = 0d0
    2299              :                end if
    2300              :             end do
    2301            0 :             do k = 2, nz-1
    2302            0 :                val(k) = work(k)
    2303              :             end do
    2304              :          end do
    2305            0 :       end subroutine do_smoothing_by_mass
    2306              : 
    2307              : 
    2308           44 :       subroutine set_dxdt_mix(s)
    2309              :          type (star_info), pointer :: s
    2310           44 :          real(dp) :: x00, xp1, xm1, dx00, dxp1, dm, sig00, sigp1, &
    2311           44 :               flux00, dflux00_dxm1, dflux00_dx00, &
    2312           44 :               fluxp1, dfluxp1_dx00, dfluxp1_dxp1
    2313              :          integer :: j, k
    2314              :          include 'formats'
    2315              : 
    2316        52392 :          do k = 1, s% nz
    2317              : 
    2318        52348 :             dm = s% dm(k)
    2319        52348 :             sig00 = s% sig(k)
    2320              : 
    2321        52348 :             if (k < s% nz) then
    2322        52304 :                sigp1 = s% sig(k+1)
    2323              :             else
    2324              :                sigp1 = 0
    2325              :             end if
    2326              : 
    2327        52348 :             if (k > 1) then
    2328        52304 :                dflux00_dxm1 = -sig00
    2329        52304 :                dflux00_dx00 = sig00
    2330              :             else
    2331              :                dflux00_dxm1 = 0
    2332              :                dflux00_dx00 = 0
    2333              :             end if
    2334              : 
    2335        52348 :             if (k < s% nz) then
    2336        52304 :                dfluxp1_dx00 = -sigp1
    2337        52304 :                dfluxp1_dxp1 = sigp1
    2338              :             else
    2339              :                dfluxp1_dx00 = 0
    2340              :                dfluxp1_dxp1 = 0
    2341              :             end if
    2342              : 
    2343        52348 :             s% d_dxdt_mix_dx00(k) = (dfluxp1_dx00 - dflux00_dx00)/dm
    2344        52348 :             s% d_dxdt_mix_dxm1(k) = -dflux00_dxm1/dm
    2345        52348 :             s% d_dxdt_mix_dxp1(k) = dfluxp1_dxp1/dm
    2346              : 
    2347              : 
    2348       471176 :             do j=1, s% species
    2349       418784 :                x00 = s% xa(j,k)
    2350       418784 :                if (k > 1) then
    2351       418432 :                   xm1 = s% xa(j,k-1)
    2352       418432 :                   dx00 = xm1 - x00
    2353       418432 :                   flux00 = -sig00*dx00
    2354              :                else
    2355              :                   flux00 = 0
    2356              :                end if
    2357       418784 :                if (k < s% nz) then
    2358       418432 :                   xp1 = s% xa(j,k+1)
    2359       418432 :                   dxp1 = x00 - xp1
    2360       418432 :                   fluxp1 = -sigp1*dxp1
    2361              :                else
    2362              :                   fluxp1 = 0
    2363              :                end if
    2364       471132 :                s% dxdt_mix(j,k) = (fluxp1 - flux00)/dm
    2365              :             end do
    2366              : 
    2367              :          end do
    2368              : 
    2369           44 :       end subroutine set_dxdt_mix
    2370              : 
    2371              : 
    2372              : 
    2373           33 :       subroutine add_RTI_turbulence(s, ierr)
    2374              :          type (star_info), pointer :: s
    2375              :          integer, intent(out) :: ierr
    2376              : 
    2377              :          integer :: nz, k
    2378           33 :          real(dp) :: coeff, D, P_face, r_face, q_face, cdc, Hp, vc, &
    2379           33 :             alfa, beta, rho_face, lg_coeff, full_off, full_on, min_m
    2380              :          logical :: dbg
    2381              : 
    2382              :          include 'formats'
    2383              : 
    2384           33 :          dbg = .false.
    2385              : 
    2386           33 :          ierr = 0
    2387           33 :          nz = s% nz
    2388              : 
    2389           33 :          if (.not. s% RTI_flag) return
    2390              : 
    2391            0 :          coeff = s% composition_RTI_diffusion_factor
    2392            0 :          if (coeff <= 0) return
    2393            0 :          lg_coeff = log10(coeff)
    2394            0 :          full_off = s% min_M_RTI_factors_full_off*Msun
    2395            0 :          full_on = s% max_M_RTI_factors_full_on*Msun
    2396            0 :          min_m = s% RTI_min_m_for_D_mix_floor*Msun
    2397            0 :          do k = 2, nz
    2398            0 :             D = s% eta_RTI(k)
    2399            0 :             if (s% m(k) <= full_on) then
    2400            0 :                D = D*coeff
    2401            0 :             else if (s% m(k) < full_off) then
    2402              :                D = D*exp10( &
    2403            0 :                         lg_coeff*(full_off - s% m(k))/(full_off - full_on))
    2404              :             ! else full off, i.e., coeff = 1
    2405              :             end if
    2406            0 :             if (is_bad(D)) then
    2407            0 :                write(*,2) 'eta_RTI', k, D
    2408            0 :                if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'add_RTI_turbulence')
    2409            0 :                ierr = -1
    2410            0 :                cycle
    2411              :             end if
    2412            0 :             if (D < s% RTI_D_mix_floor .and. s% m(k) >= min_m) &
    2413            0 :                D = s% RTI_D_mix_floor
    2414            0 :             if (D > s% D_mix(k)) &
    2415            0 :                s% mixing_type(k) = rayleigh_taylor_mixing
    2416            0 :             D = D + s% D_mix(k)
    2417            0 :             alfa = s% dq(k-1)/(s% dq(k-1) + s% dq(k))
    2418            0 :             beta = 1 - alfa
    2419            0 :             rho_face = alfa*s% rho(k) + beta*s% rho(k-1)
    2420            0 :             P_face = alfa*s% Peos(k) + beta*s% Peos(k-1)
    2421            0 :             r_face = s% r(k)
    2422            0 :             q_face = s% q(k)
    2423            0 :             cdc = pow2(pi4*s% r(k)*s% r(k)*rho_face)*D  ! gm^2/sec
    2424            0 :             if (s% cgrav(k) <= 0) then
    2425            0 :                Hp = s% r(k)
    2426              :             else
    2427              :                Hp = P_face/(rho_face*s% cgrav(k)* &
    2428            0 :                   (s% M_center + s% xmstar*q_face)/(r_face*r_face))
    2429              :             end if
    2430            0 :             vc = 3*D/(s% alpha_mlt(k)*Hp)
    2431            0 :             s% cdc(k) = cdc
    2432            0 :             s% D_mix(k) = D
    2433            0 :             s% conv_vel(k) = vc
    2434              :          end do
    2435              : 
    2436              :       end subroutine add_RTI_turbulence
    2437              : 
    2438              :       end module mix_info
        

Generated by: LCOV version 2.0-1