LCOV - code coverage report
Current view: top level - star/private - winds.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 27.2 % 312 85
Test Date: 2025-05-08 18:23:42 Functions: 35.7 % 14 5

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2019  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              : 
      21              :       module winds
      22              : 
      23              :       use star_private_def
      24              :       use const_def, only: dp, ln10, rsun, msun, lsun, clight, crad, pi, pi4, secyer
      25              :       use chem_def, only: ih1, ihe4, ic12, ic13, in14, io16
      26              :       use utils_lib, only: is_bad
      27              : 
      28              :       implicit none
      29              : 
      30              :       private
      31              :       public :: set_mdot
      32              : 
      33              :       contains
      34              : 
      35           11 :       subroutine set_mdot(s, L_phot, M_phot, T_phot, ierr)
      36              :          use chem_def
      37              :          type (star_info), pointer :: s
      38              :          real(dp), intent(in) :: L_phot, M_phot, T_phot  ! photosphere values (cgs)
      39              :          integer, intent(out) :: ierr
      40              :          include 'formats'
      41              :          ierr = 0
      42           11 :          call do_set_mdot(s, L_phot, M_phot, T_phot, ierr)
      43           11 :          if (ierr /= 0) return
      44           11 :          if (s% use_other_adjust_mdot) then
      45            0 :             call s% other_adjust_mdot(s% id, ierr)
      46            0 :             if (ierr /= 0) then
      47            0 :                if (s% report_ierr) write(*, *) 'other_adjust_mdot'
      48            0 :                return
      49              :             end if
      50              :          end if
      51           11 :       end subroutine set_mdot
      52              : 
      53              : 
      54           11 :       subroutine do_set_mdot(s, L_phot, M_phot, T_phot, ierr)
      55           11 :          use chem_def
      56              :          type (star_info), pointer :: s
      57              :          real(dp), intent(in) :: L_phot, M_phot, T_phot  ! photosphere values (cgs)
      58              :          integer, intent(out) :: ierr
      59              : 
      60              :          integer :: h1, he4, nz
      61           11 :          real(dp) :: wind_mdot, wind, alfa, &
      62           11 :             X, Y, Z, w1, w2, T_high, T_low, L1, M1, R1, T1, &
      63           11 :             beta, divisor, &
      64           11 :             center_h1, center_he4, surface_h1, surface_he4, mdot, xfer_ratio, &
      65           11 :             L_div_Ledd, full_off, full_on, max_boost, super_eddington_boost, &
      66           11 :             hot_wind, cool_wind, H_env_mass, H_He_env_mass, He_layer_mass
      67              :          character (len=strlen) :: scheme
      68              :          logical :: using_wind_scheme_mdot, use_other
      69              :          real(dp), parameter :: Zsolar = 0.019d0  ! for Vink et al formula
      70              : 
      71              :          logical, parameter :: dbg = .false.
      72              : 
      73              :          include 'formats'
      74              : 
      75              :          if (dbg) write(*,1) 'enter set_mdot mass_change', s% mass_change
      76              : 
      77           11 :          ierr = 0
      78              : 
      79           11 :          xfer_ratio = 1d0
      80              : 
      81           11 :          L1 = L_phot
      82           11 :          M1 = M_phot
      83           11 :          T1 = T_phot
      84           11 :          R1 = sqrt(L1/(pi*crad*clight*T1*T1*T1*T1))  ! assume L1 and T1 for photosphere
      85              : 
      86           11 :          h1 = s% net_iso(ih1)
      87           11 :          he4 = s% net_iso(ihe4)
      88           11 :          nz = s% nz
      89           11 :          wind_mdot = 0
      90           11 :          using_wind_scheme_mdot = .false.
      91              : 
      92           11 :          call eval_super_eddington_wind(s, L1, M1, R1, ierr)
      93           11 :          if (ierr /= 0) then
      94            0 :             if (dbg .or. s% report_ierr) write(*, *) 'set_mdot: eval_super_eddington_wind ierr'
      95            0 :             return
      96              :          end if
      97              : 
      98           11 :          if (s% super_eddington_wind_mdot > wind_mdot) then
      99            0 :             wind_mdot = s% super_eddington_wind_mdot
     100              :             if (dbg) write(*,1) 'super eddington wind lg_Mdot', &
     101              :                log10(s% super_eddington_wind_mdot/(Msun/secyer))
     102              :          end if
     103              : 
     104           11 :          mdot = eval_rlo_wind(s, L1/Lsun, R1/Rsun, T1, xfer_ratio, ierr)  ! Msun/year
     105           11 :          mdot = mdot*Msun/secyer
     106           11 :          if (ierr /= 0) then
     107            0 :             if (dbg .or. s% report_ierr) write(*, *) 'set_mdot: eval_rlo_wind ierr'
     108            0 :             return
     109              :          end if
     110           11 :          s% doing_rlo_wind = (mdot /= 0)
     111              :          if (dbg) write(*,*) 's% doing_rlo_wind', s% doing_rlo_wind, mdot, wind_mdot
     112              : 
     113           11 :          if (s% doing_rlo_wind .and. mdot > wind_mdot) then
     114           11 :             wind_mdot = mdot
     115              :             if (dbg) write(*,1) 's% doing_rlo_wind mdot', wind_mdot
     116              :          end if
     117              : 
     118           11 :          if (h1 > 0) then
     119           11 :             center_h1 = s% xa(h1,nz)
     120           11 :             surface_h1 = s% xa(h1,1)
     121              :          else
     122            0 :             center_h1 = 0
     123            0 :             surface_h1 = 0
     124              :          end if
     125           11 :          if (he4 > 0) then
     126           11 :             center_he4 = s% xa(he4,nz)
     127           11 :             surface_he4 = s% xa(he4,1)
     128              :          else
     129            0 :             center_he4 = 0
     130            0 :             surface_he4 = 0
     131              :          end if
     132              : 
     133           11 :          if ((s% mass_change > 0 .and. wind_mdot == 0) .or. &
     134              :              (s% mass_change < 0 .and. -s% mass_change*Msun/secyer > wind_mdot)) then
     135              :             if (dbg) write(*,*) 'mass_change mdot', s% mass_change
     136            0 :             wind_mdot = -s% mass_change*Msun/secyer
     137            0 :             if (s% mass_change > 0 .and. xfer_ratio < 1d0) then
     138            0 :                write(*,1) 'almost full roche lobe: reduce mdot by xfer_ratio', xfer_ratio
     139            0 :                wind_mdot = wind_mdot*xfer_ratio
     140              :             end if
     141              :          end if
     142              : 
     143              :          !separate calls for hot and cool winds
     144           11 :          if(s% hot_wind_full_on_T < s% cool_wind_full_on_T)then
     145            0 :             ierr = -1
     146            0 :             write(*,*) ' *** set_mdot error: hot_wind_full_on_T < cool_wind_full_on_T '
     147            0 :             return
     148              :          end if
     149              : 
     150           11 :          if(T1 >= s% cool_wind_full_on_T)then  !do hot_wind calculation
     151           11 :             call eval_wind_for_scheme(s% hot_wind_scheme,hot_wind)
     152              :          else
     153            0 :             hot_wind = 0d0
     154              :          end if
     155              : 
     156           11 :          if(T1 <= s% hot_wind_full_on_T)then
     157            0 :             if (center_h1 < 0.01d0 .and. center_he4 < s% RGB_to_AGB_wind_switch) then
     158            0 :                scheme = s% cool_wind_AGB_scheme
     159              :                if (dbg) &
     160              :                   write(*,1) 'using cool_wind_AGB_scheme: "' // trim(scheme) // '"', &
     161            0 :                     center_h1, center_he4, s% RGB_to_AGB_wind_switch
     162              :             else
     163            0 :                scheme = s% cool_wind_RGB_scheme
     164              :                if (dbg) &
     165              :                   write(*,*) 'using cool_wind_RGB_scheme: "' // trim(scheme) // '"'
     166              :             end if
     167            0 :             call eval_wind_for_scheme(scheme, cool_wind)
     168              :          else
     169           11 :             cool_wind = 0d0
     170              :          end if
     171              : 
     172              :          !now combine the contributions of hot and cool winds
     173           11 :          if(T1 >= s% hot_wind_full_on_T)then
     174           11 :             wind = hot_wind
     175            0 :          else if(T1 <= s% cool_wind_full_on_T)then
     176            0 :             wind = cool_wind
     177            0 :          else if(s% hot_wind_full_on_T == s% cool_wind_full_on_T)then
     178            0 :             wind = 0.5d0*(hot_wind + cool_wind)
     179              :          else  ! blend
     180            0 :             divisor = s% hot_wind_full_on_T - s% cool_wind_full_on_T
     181            0 :             beta = min( (s% hot_wind_full_on_T - T1) / divisor, 1d0)
     182            0 :             alfa = 1d0 - beta
     183            0 :             wind = alfa*hot_wind + beta*cool_wind
     184              :          end if
     185              : 
     186           11 :          if (wind*Msun/secyer > abs(wind_mdot)) then
     187              :             using_wind_scheme_mdot = .true.
     188              :             if (dbg) write(*,1) 'use wind scheme mdot', wind*Msun/secyer, wind_mdot
     189              :             wind_mdot = wind*Msun/secyer
     190              :          end if
     191              : 
     192              :          if (dbg) write(*,1) 'wind_mdot 1', wind_mdot
     193              : 
     194              :          if (using_wind_scheme_mdot) then
     195            0 :             if (s% no_wind_if_no_rotation .and. .not. s% rotation_flag) then
     196            0 :                s% mstar_dot = 0
     197            0 :                if (s% trace_dt_control_mass_change) &
     198            0 :                   write(*,1) 'no_wind_if_no_rotation'
     199            0 :                return
     200              :             end if
     201            0 :             if (s% dt > 0 .and. s% dt < s% mass_change_full_on_dt) then
     202            0 :                if (s% dt <= s% mass_change_full_off_dt) then
     203            0 :                   s% mstar_dot = 0
     204            0 :                   if (s% trace_dt_control_mass_change .or. dbg) &
     205            0 :                      write(*,1) 'no wind: dt <= mass_change_full_off_dt'
     206            0 :                   return
     207              :                end if
     208              :                alfa = (s% dt - s% mass_change_full_off_dt)/ &
     209            0 :                         (s% mass_change_full_on_dt - s% mass_change_full_off_dt)
     210            0 :                if (s% trace_dt_control_mass_change .or. dbg) &
     211            0 :                   write(*,1) 'reduce wind: dt <= mass_change_full_on_dt', alfa
     212            0 :                wind_mdot = wind_mdot*alfa
     213              :             end if
     214              :          end if
     215              : 
     216           11 :          if (wind_mdot >= 0 .and. s% super_eddington_scaling_factor <= 0) then
     217              :             ! check for super eddington boost to wind
     218           11 :             L_div_Ledd = L1 / s% prev_Ledd
     219           11 :             full_off = s% wind_boost_full_off_L_div_Ledd
     220           11 :             if (L_div_Ledd > full_off) then
     221            0 :                full_on = s% wind_boost_full_on_L_div_Ledd
     222            0 :                max_boost = s% super_eddington_wind_max_boost
     223            0 :                if (L_div_Ledd >= full_on) then
     224            0 :                   super_eddington_boost = max_boost
     225              :                else
     226              :                   super_eddington_boost = &
     227            0 :                      1 + (max_boost-1)*(L_div_Ledd - full_off)/(full_on - full_off)
     228              :                end if
     229            0 :                wind_mdot = wind_mdot*super_eddington_boost
     230            0 :                if (s% trace_super_eddington_wind_boost .or. dbg) then
     231            0 :                   write(*,1) 'super eddington wind boost factor, L_div_Ledd', &
     232            0 :                      super_eddington_boost, L_div_Ledd
     233            0 :                   write(*,'(A)')
     234              :                end if
     235              :             end if
     236              :          end if
     237              : 
     238              :          if (dbg) write(*,1) 'wind_mdot 2', wind_mdot
     239              : 
     240           11 :          if (wind_mdot >= 0 .and. s% min_wind > 0 .and. &
     241              :                wind_mdot < s% min_wind*Msun/secyer) then
     242              :             if (dbg) write(*,1) 'use s% min_wind', s% min_wind
     243           11 :             wind_mdot = s% min_wind*Msun/secyer
     244              :          end if
     245              : 
     246              :          if (dbg) write(*,1) 'wind_mdot 3', wind_mdot
     247              : 
     248           11 :          if (wind_mdot >= 0 .and. s% max_wind > 0 .and. &
     249              :                wind_mdot > s% max_wind*Msun/secyer) then
     250              :             if (dbg) write(*,1) 'use s% max_wind', s% max_wind
     251           11 :             wind_mdot = s% max_wind*Msun/secyer
     252              :          end if
     253              :          if (dbg) write(*,1) 'wind_mdot 4', wind_mdot
     254              : 
     255              :          if (wind_mdot >= 0) then
     256           11 :             if (s% starting_T_center > s% max_T_center_for_any_mass_loss) then
     257              :                if (dbg) write(*,1) 'starting_T_center > max_T_center_for_any_mass_loss', &
     258              :                         s% starting_T_center, s% max_T_center_for_any_mass_loss
     259              :                wind_mdot = 0
     260           11 :             else if (s% starting_T_center > s% max_T_center_for_full_mass_loss) then
     261              :                if (dbg) write(*,1) 'starting_T_center > max_T_center_for_full_mass_loss', &
     262              :                         s% starting_T_center, s% max_T_center_for_full_mass_loss
     263              :                wind_mdot = wind_mdot* &
     264              :                   (s% max_T_center_for_any_mass_loss - s% starting_T_center)/ &
     265              :                   (s% max_T_center_for_any_mass_loss - &
     266            0 :                      s% max_T_center_for_full_mass_loss)
     267              :             end if
     268              :          end if
     269              :          if (dbg) write(*,1) 'wind_mdot 5', wind_mdot
     270              : 
     271           11 :          if (wind_mdot >= 0) then
     272           11 :              H_env_mass = s% star_mass - s% he_core_mass
     273           11 :              H_He_env_mass = s% star_mass - s% co_core_mass
     274           11 :              He_layer_mass = s% he_core_mass - s% co_core_mass
     275           11 :              if (s% wind_H_envelope_limit > 0 .and. &
     276              :                    H_env_mass < s% wind_H_envelope_limit) then
     277              :                 wind_mdot = 0
     278           11 :              else if (s% wind_H_He_envelope_limit > 0 .and. &
     279              :                    H_He_env_mass < s% wind_H_He_envelope_limit) then
     280              :                 wind_mdot = 0
     281           11 :              else if (s% wind_He_layer_limit > 0 .and. &
     282              :                    He_layer_mass < s% wind_He_layer_limit) then
     283            0 :                 wind_mdot = 0
     284              :              end if
     285              :          end if
     286              : 
     287           11 :          s% mstar_dot = -wind_mdot
     288              :          if (dbg) write(*,1) 'mstar_dot', s% mstar_dot
     289           11 :          if (s% mstar_dot < 0 .and. &
     290              :                (s% min_wind > 0 .or. &
     291              :                   using_wind_scheme_mdot .or. &
     292              :                      s% v_div_v_crit_avg_surf > 0.8d0)) then
     293            0 :             call rotation_enhancement(ierr)
     294            0 :             if (is_bad(s% rotational_mdot_boost)) then
     295            0 :                write(*,2) 'is_bad(s% rotational_mdot_boost)', s% model_number
     296            0 :                if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'winds: rotation_enhancement')
     297              :             end if
     298            0 :             if (ierr /= 0) then
     299            0 :                if (dbg .or. s% report_ierr) write(*, *) 'set_mdot: rotation_enhancement ierr'
     300            0 :                return
     301              :             end if
     302              :          end if
     303              : 
     304           11 :          s% explicit_mstar_dot = s% mstar_dot
     305              : 
     306           11 :          if (dbg) then
     307              :             write(*,1) 'final star_mdot', s% mstar_dot/(Msun/secyer)
     308              :             write(*,1) 'final lg abs s% mstar_dot/(Msun/secyer)', safe_log10(abs(s% mstar_dot/(Msun/secyer)))
     309              :             write(*,'(A)')
     310              :          end if
     311              : 
     312              :          contains
     313              : 
     314           11 :            subroutine eval_wind_for_scheme(scheme,wind)
     315              :              character(len=strlen) :: scheme
     316              :              real(dp), intent(out) :: wind
     317              :              include 'formats'
     318              : 
     319           11 :              use_other = (s% use_other_wind .or. scheme == 'other')
     320           11 :              if ((.not. use_other) .and. len_trim(scheme) == 0) then
     321           11 :                 wind = 0
     322              :              else
     323            0 :                 wind = 4d-13*(L1*R1/M1)/(Lsun*Rsun/Msun)  ! in Msun/year
     324              :                 if (dbg) write(*,1) 'wind', wind
     325            0 :                 if (wind <= 0 .or. is_bad_num(wind)) then
     326            0 :                    ierr = -1
     327            0 :                    write(*,*) 'bad value for wind :', wind,L1,R1,M1
     328              :                    if (dbg) call mesa_error(__FILE__,__LINE__,'debug: bad value for wind')
     329            0 :                    if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'winds')
     330            0 :                    return
     331              :                 end if
     332            0 :                 X = surface_h1
     333            0 :                 Y = surface_he4
     334              :                 ! use the Zbase as a proxy for Fe-group abundances
     335              :                 ! unlikely to change during the stellar evolution
     336            0 :                 if (s% kap_rq% Zbase >= 0) then
     337            0 :                    Z = s% kap_rq% Zbase
     338              :                 else
     339              :                    if (dbg) write(*,*) 'Zbase not set, using present-day Z for wind'
     340            0 :                    Z = 1 - (X + Y)
     341              :                 end if
     342              : 
     343            0 :                 if (use_other) then
     344              :                    if (dbg) write(*,*) 'call other_wind'
     345            0 :                    call s% other_wind(s% id, L1, M1, R1, T1, X, Y, Z, wind, ierr)
     346              :                    if (ierr /= 0) return
     347            0 :                 else if (scheme == 'Dutch') then
     348            0 :                    T_high = 11000
     349            0 :                    T_low = 10000
     350            0 :                    if (s% Dutch_scaling_factor == 0) then
     351            0 :                       wind = 0
     352            0 :                    else if (T1 <= T_low) then
     353            0 :                       call eval_lowT_Dutch(wind)
     354            0 :                    else if (T1 >= T_high) then
     355            0 :                       call eval_highT_Dutch(wind)
     356              :                    else  ! transition
     357              :                       call eval_lowT_Dutch(w1)
     358              :                       call eval_highT_Dutch(w2)
     359            0 :                       alfa = (T1 - T_low)/(T_high - T_low)
     360            0 :                       wind = (1-alfa)*w1 + alfa*w2
     361              :                    end if
     362            0 :                    wind = s% Dutch_scaling_factor * wind
     363            0 :                 else if (scheme == 'Reimers') then
     364            0 :                    wind = wind * s% Reimers_scaling_factor
     365              :                    if (dbg) then
     366              :                       write(*,1) 's% Reimers_scaling_factor', s% Reimers_scaling_factor
     367              :                       write(*,1) 'Reimers_wind', wind
     368              :                       write(*,1) 'L1/Lsun', L1/Lsun
     369              :                       write(*,1) 'R1/Rsun', R1/Rsun
     370              :                       write(*,1) 'M1/Msun', M1/Msun
     371              :                       write(*,1) 'Reimers_scaling_factorReimers_scaling_factor', s% Reimers_scaling_factor
     372              :                       write(*,1) 'wind', wind
     373              :                       write(*,1) 'log10 wind', log10(wind)
     374              :                       write(*,'(A)')
     375              :                       call mesa_error(__FILE__,__LINE__,'debug: winds')
     376              :                    end if
     377            0 :                 else if (scheme == 'Vink') then
     378            0 :                    call eval_Vink_wind(wind)
     379            0 :                    wind = wind * s% Vink_scaling_factor
     380              :                    if (dbg) write(*,1) 'Vink_wind', wind
     381              :                    if (dbg) write(*,1) 'Grafener_wind', wind
     382            0 :                 else if (scheme == 'Blocker') then
     383            0 :                    call eval_blocker_wind(wind)
     384              :                    if (dbg) write(*,1) 'Blocker_wind', wind
     385            0 :                 else if (scheme == 'de Jager') then
     386            0 :                    call eval_de_Jager_wind(wind)
     387            0 :                    wind = s% de_Jager_scaling_factor * wind
     388              :                    if (dbg) write(*,1) 'de_Jager_wind', wind
     389            0 :                 else if (scheme == 'van Loon') then
     390            0 :                    call eval_van_Loon_wind(wind)
     391            0 :                    wind = s% van_Loon_scaling_factor * wind
     392              :                    if (dbg) write(*,1) 'van_Loon_wind', wind
     393            0 :                 else if (scheme == 'Nieuwenhuijzen') then
     394            0 :                    call eval_Nieuwenhuijzen_wind(wind)
     395            0 :                    wind = s% Nieuwenhuijzen_scaling_factor * wind
     396              :                    if (dbg) write(*,1) 'Nieuwenhuijzen_wind', wind
     397            0 :                 else if (scheme == 'Bjorklund') then
     398            0 :                    call eval_Bjorklund_wind(wind)
     399            0 :                    wind = s% Bjorklund_scaling_factor * wind
     400              :                    if (dbg) write(*,1) 'Bjorklund_wind', wind
     401              :                 else
     402            0 :                    ierr = -1
     403            0 :                    write(*,*) 'unknown name for wind scheme : ' // trim(scheme)
     404              :                    if (dbg) call mesa_error(__FILE__,__LINE__,'debug: bad value for wind scheme')
     405            0 :                    return
     406              :                 end if
     407              :              end if
     408              : 
     409           11 :            end subroutine eval_wind_for_scheme
     410              : 
     411              : 
     412            0 :          subroutine rotation_enhancement(ierr)
     413              :             use star_utils, only: eval_kh_timescale
     414              :             integer, intent(out) :: ierr
     415              :             ! as in Heger, Langer, and Woosley, 2000, ApJ, 528:368-396.  section 2.6
     416              :             ! Mdot = Mdot_no_rotation/(1 - Osurf/Osurf_crit)^mdot_omega_power
     417              :             ! where Osurf = angular velocity at surface
     418              :             !       Osurf_crit^2 = (1 - Gamma_edd)*G*M/R_equatorial^3
     419              :             !       Gamma_edd = kappa*L/(4 pi c G M), Eddington factor
     420            0 :             real(dp) :: enhancement, wind_mdot, wind_mdot_lim, &
     421            0 :                kh_timescale, wind_mdot_prev, dmsfac, dmskhf
     422              : 
     423              :             include 'formats'
     424              : 
     425            0 :             ierr = 0
     426              : 
     427            0 :             if (.not. s% rotation_flag) return
     428            0 :             if (s% mdot_omega_power <= 0) return
     429            0 :             if (s% mstar_dot >= 0) return
     430              : 
     431            0 :             wind_mdot = -s% mstar_dot
     432              : 
     433            0 :             kh_timescale = eval_kh_timescale(s% cgrav(1), M1, R1, L1)
     434            0 :             dmskhf = s% rotational_mdot_kh_fac
     435            0 :             dmsfac = s% rotational_mdot_boost_fac
     436            0 :             wind_mdot_lim = min(dmskhf*M1/kh_timescale, wind_mdot*dmsfac)
     437              : 
     438            0 :             enhancement = pow(max(1d-22, 1d0 - s% v_div_v_crit_avg_surf), -s% mdot_omega_power)
     439            0 :             if (s% max_rotational_mdot_boost > 0 .and. &
     440              :                   enhancement > s% max_rotational_mdot_boost) then
     441            0 :                enhancement = s% max_rotational_mdot_boost
     442              :             end if
     443              : 
     444              :             if (enhancement > s% lim_trace_rotational_mdot_boost) then
     445              :                if (dbg) write(*,1) &
     446              :                   'mdot rotation enhancement factor for mdot, v_div_v_crit_avg_surf', &
     447              :                   enhancement, s% v_div_v_crit_avg_surf
     448              :             end if
     449              : 
     450            0 :             if (wind_mdot*enhancement < wind_mdot_lim) then
     451              :                wind_mdot = wind_mdot*enhancement
     452              :                if (dbg) write(*,2) 'wind_mdot = wind_mdot*enhancement', &
     453              :                   s% model_number, enhancement, &
     454              :                   log10(wind_mdot/(Msun/secyer)), log10(wind_mdot_lim/(Msun/secyer))
     455              :             else
     456            0 :                enhancement = wind_mdot_lim/wind_mdot
     457            0 :                wind_mdot = wind_mdot_lim
     458              :                if (dbg) write(*,2) 'wind_mdot = wind_mdot_lim', &
     459              :                   s% model_number, log10(wind_mdot/(Msun/secyer))
     460              :             end if
     461              : 
     462            0 :             wind_mdot_prev = -s% mstar_dot_old
     463            0 :             if (wind_mdot > 0 .and. wind_mdot_prev > 0) &
     464            0 :                wind_mdot = min(wind_mdot, s% max_mdot_jump_for_rotation*wind_mdot_prev)
     465              : 
     466              :             ! recheck max_wind
     467            0 :             if (wind_mdot >= 0 .and. s% max_wind > 0 .and. &
     468              :                   wind_mdot > s% max_wind*Msun/secyer) then
     469              :                if (dbg) write(*,1) 'use s% max_wind', s% max_wind
     470            0 :                wind_mdot = s% max_wind*Msun/secyer
     471              :             end if
     472              : 
     473            0 :             s% mstar_dot = -wind_mdot
     474            0 :             s% rotational_mdot_boost = enhancement
     475              : 
     476            0 :          end subroutine rotation_enhancement
     477              : 
     478              : 
     479            0 :          subroutine eval_Bjorklund_wind(w)
     480              :             real(dp), intent(inout) :: w
     481              :             real(dp), parameter :: Zbjork = 0.014d0
     482            0 :             real(dp) :: logw, Meff
     483              : 
     484              :             ! electron opacity is constant 0.34 in their models (Eq. 6)
     485            0 :             Meff = M1*(1d0 - 0.34d0*L1/(pi4*clight*s% cgrav(1)*M1))  ! effective mass
     486              : 
     487              :             ! eq 7 from Björklund et al, 2022, arXiv:2203.08218, accepted to A&A
     488              :             logw = - 5.52d0 &
     489              :                    + 2.39d0 * log10(L1/(1d6*Lsun)) &
     490              :                    - 1.48d0 * log10(Meff/(4.5d1*Msun)) &
     491              :                    + 2.12d0 * log10(T1/4.5d4) &
     492            0 :                    + (0.75d0 - 1.87d0 * log10(T1/4.5d4)) * log10(Z/Zbjork)
     493            0 :             w = exp10(logw)
     494              : 
     495            0 :          end subroutine eval_Bjorklund_wind
     496              : 
     497            0 :          subroutine eval_Vink_wind(w)
     498              :             real(dp), intent(inout) :: w
     499            0 :             real(dp) :: alfa, w1, w2, Teff_jump, logMdot, dT, vinf_div_vesc
     500              : 
     501              :             ! alfa = 1 for hot side, = 0 for cool side
     502            0 :             if (T1 > 27500d0) then
     503              :                alfa = 1
     504            0 :             else if (T1 < 22500d0) then
     505              :                alfa = 0
     506              :             else  ! use Vink et al 2001, eqns 14 and 15 to set "jump" temperature
     507            0 :                Teff_jump = 1d3*(61.2d0 + 2.59d0*(-13.636d0 + 0.889d0*log10(Z/Zsolar)))
     508            0 :                dT = 100d0
     509            0 :                if (T1 > Teff_jump + dT) then
     510              :                   alfa = 1
     511            0 :                else if (T1 < Teff_jump - dT) then
     512              :                   alfa = 0
     513              :                else
     514            0 :                   alfa = 0.5d0*(T1 - (Teff_jump - dT)) / dT
     515              :                end if
     516              :             end if
     517              : 
     518            0 :             if (alfa > 0) then  ! eval hot side wind (eqn 24)
     519            0 :                vinf_div_vesc = 2.6d0  ! this is the hot side galactic value
     520            0 :                vinf_div_vesc = vinf_div_vesc*pow(Z/Zsolar,0.13d0)  ! corrected for Z
     521              :                logMdot = &
     522              :                   - 6.697d0 &
     523              :                   + 2.194d0*log10(L1/Lsun/1d5) &
     524              :                   - 1.313d0*log10(M1/Msun/30d0) &
     525              :                   - 1.226d0*log10(vinf_div_vesc/2d0) &
     526              :                   + 0.933d0*log10(T1/4d4) &
     527              :                   - 10.92d0*pow2(log10(T1/4d4)) &
     528            0 :                   + 0.85d0*log10(Z/Zsolar)
     529            0 :                w1 = exp10(logMdot)
     530              :             else
     531              :                w1 = 0
     532              :             end if
     533              : 
     534            0 :             if (alfa < 1) then  ! eval cool side wind (eqn 25)
     535            0 :                vinf_div_vesc = 1.3d0  ! this is the cool side galactic value
     536            0 :                vinf_div_vesc = vinf_div_vesc*pow(Z/Zsolar,0.13d0)  ! corrected for Z
     537              :                logMdot = &
     538              :                   - 6.688d0 &
     539              :                   + 2.210d0*log10(L1/Lsun/1d5) &
     540              :                   - 1.339d0*log10(M1/Msun/30d0) &
     541              :                   - 1.601d0*log10(vinf_div_vesc/2d0) &
     542              :                   + 1.07d0*log10(T1/2d4) &
     543            0 :                   + 0.85d0*log10(Z/Zsolar)
     544            0 :                w2 = exp10(logMdot)
     545              :             else
     546              :                w2 = 0
     547              :             end if
     548              : 
     549            0 :             w = alfa*w1 + (1 - alfa)*w2
     550              : 
     551              :             if (dbg) write(*,*) 'vink wind', w
     552              : 
     553            0 :          end subroutine eval_Vink_wind
     554              : 
     555              : 
     556            0 :          subroutine eval_blocker_wind(w)
     557              :             real(dp), intent(inout) :: w
     558              :             w = w * s% Blocker_scaling_factor * &
     559            0 :                4.83d-9 * pow(M1/Msun,-2.1d0) * pow(L1/Lsun,2.7d0)
     560              :             if (dbg) write(*,*) 'blocker wind', w
     561            0 :          end subroutine eval_blocker_wind
     562              : 
     563              : 
     564            0 :          subroutine eval_highT_Dutch(w)
     565              :             real(dp), intent(out) :: w
     566              :             include 'formats'
     567            0 :             if (surface_h1 < 0.4d0) then  ! helium rich Wolf-Rayet star: Nugis & Lamers
     568            0 :                w = 1d-11 * pow(L1/Lsun,1.29d0) * pow(Y,1.7d0) * sqrt(Z)
     569              :                if (dbg) write(*,1) 'Dutch_wind = Nugis & Lamers', log10(wind)
     570              :             else
     571            0 :                call eval_Vink_wind(w)
     572              :             end if
     573            0 :          end subroutine eval_highT_Dutch
     574              : 
     575              : 
     576            0 :          subroutine eval_lowT_Dutch(w)
     577              :             real(dp), intent(out) :: w
     578              :             include 'formats'
     579            0 :             if (s% Dutch_wind_lowT_scheme == 'de Jager') then
     580            0 :                call eval_de_Jager_wind(w)
     581              :                if (dbg) write(*,1) 'Dutch_wind = de Jager', safe_log10(wind), T1, T_low, T_high
     582            0 :             else if (s% Dutch_wind_lowT_scheme == 'van Loon') then
     583            0 :                call eval_van_Loon_wind(w)
     584              :                if (dbg) write(*,1) 'Dutch_wind = van Loon', safe_log10(wind), T1, T_low, T_high
     585            0 :             else if (s% Dutch_wind_lowT_scheme == 'Nieuwenhuijzen') then
     586            0 :                call eval_Nieuwenhuijzen_wind(w)
     587              :                if (dbg) write(*,1) 'Dutch_wind = Nieuwenhuijzen', safe_log10(wind), T1, T_low, T_high
     588              :             else
     589              :                write(*,*) 'unknown value for Dutch_wind_lowT_scheme ' // &
     590            0 :                   trim(s% Dutch_wind_lowT_scheme)
     591            0 :                w = 0
     592              :             end if
     593            0 :          end subroutine eval_lowT_Dutch
     594              : 
     595              : 
     596            0 :          subroutine eval_de_Jager_wind(w)
     597              :             ! de Jager, C., Nieuwenhuijzen, H., & van der Hucht, K. A. 1988, A&AS, 72, 259.
     598              :             real(dp), intent(out) :: w
     599            0 :             real(dp) :: log10w
     600              :             include 'formats'
     601            0 :             log10w = 1.769d0*log10(L1/Lsun) - 1.676d0*log10(T1) - 8.158d0
     602            0 :             w = exp10(log10w)
     603              :             if (dbg) then
     604              :                write(*,1) 'de_Jager log10 wind', log10w
     605              :             end if
     606            0 :          end subroutine eval_de_Jager_wind
     607              : 
     608              : 
     609            0 :          subroutine eval_van_Loon_wind(w)
     610              :             ! van Loon et al. 2005, A&A, 438, 273
     611              :             real(dp), intent(out) :: w
     612            0 :             real(dp) :: log10w
     613              :             include 'formats'
     614            0 :             log10w = -5.65d0 + 1.05d0*log10(L1/(1d4*Lsun)) - 6.3d0*log10(T1/35d2)
     615            0 :             w = exp10(log10w)
     616            0 :          end subroutine eval_van_Loon_wind
     617              : 
     618              : 
     619            0 :          subroutine eval_Nieuwenhuijzen_wind(w)
     620              :             ! Nieuwenhuijzen, H.; de Jager, C. 1990, A&A, 231, 134 (eqn 2)
     621              :             real(dp), intent(out) :: w
     622            0 :             real(dp) :: log10w
     623              :             include 'formats'
     624              :             log10w = -14.02d0 + &
     625              :                      1.24d0*log10(L1/Lsun) + &
     626              :                      0.16d0*log10(M1/Msun) + &
     627            0 :                      0.81d0*log10(R1/Rsun)
     628            0 :             w = exp10(log10w)
     629              :             if (dbg) then
     630              :                write(*,1) 'Nieuwenhuijzen log10 wind', log10w
     631              :             end if
     632            0 :          end subroutine eval_Nieuwenhuijzen_wind
     633              : 
     634              :       end subroutine do_set_mdot
     635              : 
     636              : 
     637           11 :       subroutine eval_super_eddington_wind(s, L, M, R, ierr)
     638              :          type (star_info), pointer :: s
     639              :          real(dp), intent(in) :: L, M, R
     640              :          integer, intent(out) :: ierr
     641              : 
     642           11 :          real(dp) :: Ledd, Leff, vesc2
     643              :          include 'formats'
     644              : 
     645           11 :          ierr = 0
     646           11 :          s% super_eddington_wind_mdot = 0
     647           11 :          if (s% super_eddington_scaling_factor <= 0) return
     648              : 
     649            0 :          Ledd = s% prev_Ledd
     650            0 :          Leff = L/s% super_eddington_wind_Ledd_factor
     651            0 :          if (Leff <= Ledd) return
     652            0 :          vesc2 = 2d0 * s% cgrav(1)*M/R
     653            0 :          s% super_eddington_wind_mdot = s% super_eddington_scaling_factor*(Leff - Ledd)/(0.5d0 * vesc2)
     654            0 :          if (mod(s% model_number, s% terminal_interval) == 0) &
     655            0 :             write(*,'(a60,i12,1p2e12.4)') 'super eddington wind: lg_Mdot, L/Ledd', &
     656            0 :                s% model_number, log10(s% super_eddington_wind_mdot/(Msun/secyer)), L/Ledd
     657              : 
     658              :       end subroutine eval_super_eddington_wind
     659              : 
     660              : 
     661           11 :       real(dp) function eval_rlo_wind(s, L_surf, R, Teff, xfer_ratio, ierr)  ! value in Msun/year
     662              :          type (star_info), pointer :: s
     663              :          real(dp), intent(in) :: L_surf, R, Teff  ! Lsun, Rsun, K
     664              :          real(dp), intent(inout) :: xfer_ratio
     665              :          integer, intent(out) :: ierr
     666           11 :          real(dp) :: roche_lobe_radius  ! Rsun
     667           11 :          real(dp) :: ratio, scale_height, mdot
     668              :          include 'formats'
     669           11 :          ierr = 0
     670           11 :          eval_rlo_wind = 0
     671           11 :          if (s% rlo_scaling_factor <= 0) return
     672            0 :          if (L_surf < s% rlo_wind_min_L) return
     673            0 :          if (Teff > s% rlo_wind_max_Teff) return
     674            0 :          scale_height = s% rlo_wind_scale_height
     675            0 :          if (scale_height <= 0) then
     676            0 :             scale_height = s% Peos(1) / (s% cgrav(1)*s% m(1)*s% rho(1) / (s% r(1)**2)) / Rsun
     677              :          end if
     678            0 :          roche_lobe_radius = s% rlo_wind_roche_lobe_radius
     679            0 :          ratio = R/roche_lobe_radius
     680              :          !write(*,2) 'R/roche_lobe_radius', s% model_number, ratio
     681            0 :          if (ratio < 1) then
     682              :             ! check for reduction in transfer ratio for almost full Roche lobe
     683            0 :             if (ratio < s% roche_lobe_xfer_full_on) return
     684            0 :             if (ratio > s% roche_lobe_xfer_full_off) then
     685            0 :                xfer_ratio = 0
     686            0 :                return
     687              :             end if
     688              :             xfer_ratio = (s% roche_lobe_xfer_full_off - ratio) / &
     689            0 :                (s% roche_lobe_xfer_full_off - s% roche_lobe_xfer_full_on)
     690            0 :             xfer_ratio = 0.5d0*(1 - cospi(xfer_ratio))
     691            0 :             return
     692              :          end if
     693              :          mdot = s% rlo_wind_base_mdot* &
     694            0 :             exp(min(6*ln10,(R - roche_lobe_radius)/scale_height))
     695            0 :          eval_rlo_wind = s% rlo_scaling_factor*mdot  ! Msun/year
     696              : 
     697              :          !write(*,1) 's% rlo_wind_base_mdot', s% rlo_wind_base_mdot
     698              :          !write(*,1) 'R - roche_lobe_radius', R - roche_lobe_radius, R, roche_lobe_radius
     699              :          !write(*,1) 'scale_height', scale_height
     700              :          !write(*,1) 's% rlo_scaling_factor', s% rlo_scaling_factor
     701              :          !write(*,1) 'eval_rlo_wind, log eval_rlo_wind, R/R_L', log10(eval_rlo_wind), R/roche_lobe_radius
     702              : 
     703            0 :       end function eval_rlo_wind
     704              : 
     705              : 
     706              :       end module winds
        

Generated by: LCOV version 2.0-1