LCOV - code coverage report
Current view: top level - binary/private - binary_mdot.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 508 0
Test Date: 2025-10-14 06:41:40 Functions: 0.0 % 14 0

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2019  Pablo Marchant & 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 binary_mdot
      22              : 
      23              :       use const_def, only: dp, pi, pi4, clight, one_third, kerg, mp
      24              :       use math_lib
      25              :       use star_lib
      26              :       use star_def
      27              :       use binary_def
      28              :       use binary_wind
      29              :       use binary_ce
      30              :       use utils_lib, only: mesa_error
      31              : 
      32              :       implicit none
      33              : 
      34              :       contains
      35              : 
      36            0 :       integer function check_implicit_rlo(binary_id, new_mdot)
      37              :          integer, intent(in) :: binary_id
      38              :          real(dp), intent(out) :: new_mdot
      39              : 
      40              :          type (binary_info), pointer :: b
      41              :          type (star_info), pointer :: s
      42            0 :          real(dp) :: function_to_solve, explicit_mdot, q, slope_contact
      43              :          integer :: ierr
      44              :          logical :: use_sum, detached
      45              :          character (len=90) :: rlo_result
      46              : 
      47              :          include 'formats'
      48              :          ierr = 0
      49            0 :          call binary_ptr(binary_id, b, ierr)
      50            0 :          if (ierr /= 0) then
      51            0 :             write(*,*) 'failed in binary_ptr'
      52            0 :             return
      53              :          end if
      54            0 :          s => b% s_donor
      55            0 :          use_sum = .false.
      56            0 :          detached = .false.
      57              : 
      58              :          ! NOTE: keep in mind that for mass loss, mdot is negative.
      59              :          ! b% mtransfer_rate will be considered valid if function_to_solve = 0
      60              :          ! within the tolerance given by b% implicit_scheme_tolerance, i.e.
      61              :          ! |function_to_solve| < b% implicit_scheme_tolerance.
      62              :          !
      63              :          ! For the roche_lobe scheme, function_to_solve is set such that solutions
      64              :          ! will satisfy 0 > (r-rl)/rl > - b% implicit_scheme_tolerance. If
      65              :          ! (r-rl)/rl < 0
      66              :          ! and the new mass transfer rate that was attempted satisfies
      67              :          ! |new_mdot| < b% roche_min_mdot*Msun/secyer
      68              :          ! then the system is considered to be detached and mass loss is turned off.
      69              :          !
      70              :          ! For other schemes, function_to_solve is chosen as the difference between
      71              :          ! b% mtransfer_rate and the explicit transfer rate, divided by the
      72              :          ! explicit transfer rate.
      73              : 
      74            0 :          check_implicit_rlo = keep_going
      75            0 :          new_mdot = b% mtransfer_rate
      76            0 :          b% num_tries = b% num_tries + 1
      77            0 :          rlo_result = "missing message"
      78              : 
      79            0 :          if(b% report_rlo_solver_progress .and. b% num_tries == 1) then
      80              :             write(*,'(a)') &
      81              :                '  binary_step rlo_iter di ch_fact  curr_mdot' // &
      82            0 :                '  next_mdot    mdot_up   mdot_low    rl_gap1    rl_gap2          f              result'
      83              :             write(*,'(a)') &
      84              :                '  __________________________________________' // &
      85            0 :                '______________________________________________________________________________________'
      86              :          end if
      87              : 
      88            0 :          if (b% use_other_implicit_function_to_solve) then
      89              :             call b% other_implicit_function_to_solve(b% binary_id, &
      90            0 :                function_to_solve, use_sum, detached, ierr)
      91            0 :             if (ierr /= 0) then
      92            0 :                write(*,*) 'failed in other_implicit_function_to_solve'
      93            0 :                check_implicit_rlo = retry
      94            0 :                return
      95              :             end if
      96            0 :             if (detached) then
      97            0 :                if (b% report_rlo_solver_progress) then
      98            0 :                   rlo_result = 'OK (detached)'
      99            0 :                   call report_rlo_iter
     100              :                end if
     101              :             end if
     102            0 :          else if (b% mdot_scheme == "roche_lobe" .and. .not. b% use_other_rlo_mdot) then
     103              :             function_to_solve = (b% rl_relative_gap(b% d_i) &
     104            0 :                 + b% implicit_scheme_tolerance/2.0d0) * 2.0d0
     105              : 
     106            0 :             if (function_to_solve < 0 .and. abs(b% mtransfer_rate) == 0) then
     107            0 :                if (b% report_rlo_solver_progress) then
     108            0 :                   rlo_result = 'OK (detached)'
     109            0 :                   call report_rlo_iter
     110              :                end if
     111            0 :                detached = .true.
     112              :             end if
     113            0 :          else if (b% mdot_scheme == "contact" .and. .not. b% use_other_rlo_mdot .and. .not. b% CE_flag) then
     114            0 :             if (b% point_mass_i /= 0) then
     115            0 :                new_mdot = 0d0
     116            0 :                write(*,*) "WARNING: contact scheme requires evolve_both_stars=.true."
     117            0 :                write(*,*) "Not transferring mass"
     118            0 :                return
     119              :             end if
     120            0 :             q = b% m(b% a_i) / b% m(b% d_i)
     121            0 :             slope_contact = pow(q, -0.52d0)
     122              :             ! If accretor is overflowing its Roche lobe, then the contact scheme needs to be used.
     123              :             ! Otherwise, if accretor radius is (within tolerance) below the equipotential
     124              :             ! of the donor, or donor is below tolerance for detachment, then use regular roche_lobe scheme.
     125            0 :             if (b% rl_relative_gap(b% a_i) < 0 .and. &
     126              :                 (b% rl_relative_gap(b% d_i)*slope_contact - b% rl_relative_gap(b% a_i) &
     127              :                  > b% implicit_scheme_tolerance .or. &
     128              :                  b% rl_relative_gap(b% d_i) < - b% implicit_scheme_tolerance)) then
     129              : 
     130              :                function_to_solve = (b% rl_relative_gap(b% d_i) &
     131            0 :                    + b% implicit_scheme_tolerance/2.0d0) * 2.0d0
     132              : 
     133            0 :                if (function_to_solve < 0 .and. abs(b% mtransfer_rate) == 0) then
     134            0 :                   if (b% report_rlo_solver_progress) then
     135            0 :                      rlo_result = 'OK (detached)'
     136            0 :                      call report_rlo_iter
     137              :                   end if
     138            0 :                   detached = .true.
     139              :                end if
     140              :             else
     141            0 :                if (q < 1d0) then
     142            0 :                   function_to_solve = (b% rl_relative_gap(b% d_i)*slope_contact - b% rl_relative_gap(b% a_i))
     143              :                else
     144            0 :                   function_to_solve = (b% rl_relative_gap(b% d_i) - b% rl_relative_gap(b% a_i)/slope_contact)
     145              :                end if
     146            0 :                use_sum = .true.
     147              :             end if
     148              :          else
     149            0 :             if (b% CE_flag) then
     150            0 :                call CE_rlo_mdot(b% binary_id, explicit_mdot, ierr)
     151            0 :                if (ierr /= 0) then
     152            0 :                   write(*,*) 'failed in CE_rlo_mdot'
     153            0 :                   check_implicit_rlo = retry
     154            0 :                   return
     155              :                end if
     156            0 :             else if (.not. b% use_other_rlo_mdot) then
     157            0 :                call rlo_mdot(b% binary_id, explicit_mdot, ierr)
     158            0 :                if (ierr /= 0) then
     159            0 :                   write(*,*) 'failed in rlo_mdot'
     160            0 :                   check_implicit_rlo = retry
     161            0 :                   return
     162              :                end if
     163              :             else
     164            0 :                call b% other_rlo_mdot(b% binary_id, explicit_mdot, ierr)
     165            0 :                if (ierr /= 0) then
     166            0 :                   write(*,*) 'failed in other_rlo_mdot'
     167            0 :                   check_implicit_rlo = retry
     168            0 :                   return
     169              :                end if
     170              :             end if
     171            0 :             if (explicit_mdot > 0d0) then
     172            0 :                new_mdot = 0d0
     173            0 :                write(*,*) "WARNING: explicit computation of mass transfer results in accreting donor"
     174            0 :                write(*,*) "Not transferring mass"
     175            0 :                return
     176              :             end if
     177            0 :             function_to_solve = 0d0
     178            0 :             if(explicit_mdot /= 0d0) then
     179            0 :                function_to_solve = (explicit_mdot - new_mdot) / explicit_mdot
     180            0 :             else if (new_mdot /= 0d0) then
     181            0 :                function_to_solve = (explicit_mdot - new_mdot) / new_mdot
     182              :             end if
     183            0 :             if (abs(explicit_mdot) <= b% min_mdot_for_implicit*Msun/secyer .and. &
     184              :                abs(new_mdot) <= b% min_mdot_for_implicit*Msun/secyer) then
     185            0 :                new_mdot = explicit_mdot
     186            0 :                if (b% report_rlo_solver_progress) then
     187            0 :                   rlo_result = 'OK (explicit)'
     188            0 :                   call report_rlo_iter
     189              :                end if
     190            0 :                return
     191              :             end if
     192              :          end if
     193              : 
     194            0 :          if (detached) return
     195              : 
     196            0 :          if (abs(function_to_solve) <= b% implicit_scheme_tolerance) then
     197            0 :             if (b% report_rlo_solver_progress) then
     198            0 :                rlo_result = 'OK (in tol)'
     199            0 :                call report_rlo_iter
     200            0 :                write(*,'(A)')
     201              :             end if
     202            0 :             return
     203              :          end if
     204              : 
     205            0 :          if (b% num_tries > b% max_tries_to_achieve) then
     206            0 :             check_implicit_rlo = retry
     207            0 :             if (b% report_rlo_solver_progress) then
     208            0 :                rlo_result = 'retry (>max tries)'
     209            0 :                call report_rlo_iter
     210              :             end if
     211            0 :             return
     212              :          end if
     213              : 
     214            0 :          if (b% num_tries == 1) then
     215            0 :             b% have_mdot_lo = .false.
     216            0 :             b% have_mdot_hi = .false.
     217            0 :             b% mdot_lo = 0
     218            0 :             b% mdot_hi = 0
     219            0 :             b% fixed_delta_mdot = b% mtransfer_rate * (1 - b% change_factor)
     220              :          end if
     221              : 
     222            0 :          new_mdot = pick_mdot_for_implicit_rlo(b, function_to_solve, b% mtransfer_rate, use_sum, ierr)
     223              : 
     224              :          !if this iteration is done using the maximum mass transfer rate,
     225              :          !and the mass transfer rate increases in the following iteration,
     226              :          !then stop at this point and accept the step
     227              :          !NOTE: both b% mtransfer_rate and new_mdot are negative
     228              :          if (b% mtransfer_rate == -b% max_implicit_abs_mdot*Msun/secyer &
     229            0 :             .and. b% mtransfer_rate > new_mdot) then
     230            0 :             if (b% report_rlo_solver_progress) then
     231            0 :                rlo_result = 'OK (max mdot)'
     232            0 :                call report_rlo_iter
     233              :             end if
     234            0 :             new_mdot = - b% max_implicit_abs_mdot*Msun/secyer
     235            0 :             return
     236              :          end if
     237            0 :          if (-new_mdot > b% max_implicit_abs_mdot*Msun/secyer) then
     238              :             !limit to maximum mdot, following iteration will be made
     239              :             !using this value
     240            0 :             new_mdot = - b% max_implicit_abs_mdot*Msun/secyer
     241              :          end if
     242              : 
     243            0 :          if (ierr /= 0) then
     244            0 :             check_implicit_rlo = retry
     245            0 :             if (b% report_rlo_solver_progress) then
     246            0 :                rlo_result = 'retry (ierr)'
     247            0 :                call report_rlo_iter
     248              :             end if
     249            0 :             return
     250              :          end if
     251              : 
     252            0 :          if (-new_mdot < b% roche_min_mdot*Msun/secyer .and. function_to_solve < 0 .and. &
     253              :              (b% mdot_scheme == "roche_lobe" .or. (b% mdot_scheme == "contact" .and. &
     254              :              .not. use_sum))) then
     255            0 :             check_implicit_rlo = keep_going
     256            0 :             new_mdot = 0d0
     257            0 :             if (b% report_rlo_solver_progress) then
     258            0 :                rlo_result = 'OK (detachment)'
     259            0 :                call report_rlo_iter
     260              :             end if
     261            0 :             return
     262              :          end if
     263              : 
     264            0 :          if (b% have_mdot_hi .and. b% have_mdot_lo) then
     265            0 :             if (abs(b% mdot_hi - b% mdot_lo) < &
     266              :                   b% implicit_scheme_tiny_factor*min(abs(b% mdot_hi),abs(b% mdot_lo))) then
     267            0 :                if (b% report_rlo_solver_progress) then
     268            0 :                   rlo_result = 'OK (tiny change)'
     269            0 :                   call report_rlo_iter
     270              :                end if
     271            0 :                new_mdot = b% mtransfer_rate
     272            0 :                check_implicit_rlo = keep_going
     273            0 :                return
     274              :             end if
     275              :          end if
     276              : 
     277              :          ! boost change_factor every num_tries_for_increase_change_factor tries, to avoid
     278              :          ! implicit scheme from becoming stuck with sudden changes.
     279              :          if (b% num_tries_for_increase_change_factor > 0 .and. b% change_factor_increase > 1d0 &
     280            0 :             .and. .not. (b% have_mdot_lo .and. b% have_mdot_hi)) then
     281            0 :             if(mod(b% num_tries, b% num_tries_for_increase_change_factor) == 0) then
     282              :                b% change_factor = min(b% max_change_factor, &
     283            0 :                   b% change_factor_increase * b% change_factor)
     284              :             end if
     285              :          end if
     286            0 :          if (b% report_rlo_solver_progress) then
     287            0 :             rlo_result = 'redo'
     288            0 :             call report_rlo_iter
     289              :          end if
     290              : 
     291            0 :          check_implicit_rlo = redo
     292              : 
     293              :          contains
     294              : 
     295            0 :          subroutine report_rlo_iter
     296            0 :             real(dp) :: mdot_hi, mdot_lo
     297            0 :             if (.not. b% have_mdot_hi) then
     298            0 :                mdot_hi = huge(mdot_hi)
     299              :             else
     300            0 :                mdot_hi = -b% mdot_hi/Msun*secyer
     301              :             end if
     302            0 :             if (.not. b% have_mdot_lo) then
     303            0 :                mdot_lo = -huge(mdot_lo)
     304              :             else
     305            0 :                mdot_lo = -b% mdot_lo/Msun*secyer
     306              :             end if
     307              :             write(*,'(i13,i9,i3,f8.4,7(1pe11.3,0p),a20)') &
     308            0 :                b% model_number, &
     309            0 :                b% num_tries, &
     310            0 :                b% d_i, &
     311            0 :                b% change_factor, &
     312            0 :                -b% mtransfer_rate/Msun*secyer, &
     313            0 :                -new_mdot/Msun*secyer, &
     314            0 :                mdot_hi, &
     315            0 :                mdot_lo, &
     316            0 :                b% rl_relative_gap(1), &
     317            0 :                b% rl_relative_gap(2), &
     318            0 :                function_to_solve, &
     319            0 :                trim(rlo_result)
     320            0 :          end subroutine report_rlo_iter
     321              : 
     322              :       end function check_implicit_rlo
     323              : 
     324            0 :       real(dp) function pick_mdot_for_implicit_rlo( &
     325            0 :             b, new_function_to_solve, mdot_current, use_sum, ierr) result(mdot_next)
     326              :          use num_lib, only: find0_quadratic, find0
     327              :          type(binary_info), pointer :: b
     328              :          real(dp), intent(in) :: new_function_to_solve, mdot_current
     329              :          logical, intent(in) :: use_sum
     330              :          integer, intent(out) :: ierr
     331              : 
     332            0 :          real(dp) :: starting_mdot, current_change_factor
     333              :          logical :: do_cubic
     334              :          include 'formats'
     335              : 
     336              :          ! NOTE: keep in mind that for mass loss, mdot is negative
     337              : 
     338              : 
     339            0 :          starting_mdot = -b% starting_mdot*Msun/secyer
     340            0 :          current_change_factor = pow(b% change_factor, b% num_tries+1)
     341              : 
     342            0 :          if (.not.(b% solver_type == "cubic" .or. &
     343              :                    b% solver_type == "bisect" .or. &
     344              :                    b% solver_type == "both")) then
     345            0 :             write(*,*) "ERROR: unrecognized b% solver_type", trim(b% solver_type)
     346            0 :             write(*,*) "setting b% solver_type to 'both'"
     347            0 :             b% solver_type = "both"
     348              :          end if
     349              : 
     350            0 :          if (b% have_mdot_lo .and. b% have_mdot_hi) then
     351            0 :             ierr = 0
     352              :             do_cubic = (mod(b% num_tries,2)==0 .and. b% solver_type == "both") .or. &
     353            0 :                b% solver_type == "cubic"
     354              :             if (do_cubic) then
     355              :                mdot_next = find0_quadratic( &
     356              :                    b% mdot_lo, b% implicit_function_lo, &
     357              :                    mdot_current, new_function_to_solve, &
     358            0 :                    b% mdot_hi, b% implicit_function_hi, ierr)
     359            0 :                if (ierr /= 0) then
     360              :                   mdot_next = find0(b% mdot_lo, b% implicit_function_lo, &
     361            0 :                       b% mdot_hi, b% implicit_function_hi)
     362            0 :                   ierr = 0
     363              :                end if
     364              :             end if
     365            0 :             if (new_function_to_solve >= 0) then
     366            0 :                b% mdot_lo = mdot_current
     367            0 :                b% implicit_function_lo = new_function_to_solve
     368              :             else
     369            0 :                b% mdot_hi = mdot_current
     370            0 :                b% implicit_function_hi = new_function_to_solve
     371              :             end if
     372            0 :             if (.not. do_cubic) then
     373            0 :                mdot_next = (b% mdot_hi+b% mdot_lo)/2.0d0
     374              :             end if
     375            0 :          else if (b% have_mdot_lo) then  ! don't have mdot_hi
     376            0 :             if (new_function_to_solve < 0) then
     377            0 :                b% mdot_hi = mdot_current
     378            0 :                b% implicit_function_hi = new_function_to_solve
     379            0 :                b% have_mdot_hi = .true.
     380            0 :                mdot_next = (b% mdot_hi+b% mdot_lo)/2.0d0
     381              :                !mdot_next = find0(b% mdot_lo, b% implicit_function_lo, &
     382              :                !    b% mdot_hi, b% implicit_function_hi)
     383              :             else  ! still too low
     384            0 :                b% mdot_lo = mdot_current
     385            0 :                b% implicit_function_lo = new_function_to_solve
     386            0 :                mdot_next = b% mdot_lo*b% change_factor
     387              :             end if
     388            0 :          else if (b% have_mdot_hi) then  ! don't have mdot_lo
     389            0 :             if (new_function_to_solve >= 0) then
     390            0 :                b% mdot_lo = mdot_current
     391            0 :                b% implicit_function_lo = new_function_to_solve
     392            0 :                b% have_mdot_lo = .true.
     393            0 :                mdot_next = (b% mdot_hi+b% mdot_lo)/2.0d0
     394              :                !mdot_next = find0(b% mdot_lo, b% implicit_function_lo, &
     395              :                !    b% mdot_hi, b% implicit_function_hi)
     396              :             else  ! mdot still too high
     397            0 :                b% mdot_hi = mdot_current
     398            0 :                b% implicit_function_hi = new_function_to_solve
     399            0 :                if (use_sum .and. mod(b% num_tries, 2) == 0) then
     400            0 :                   mdot_next = b% mdot_hi + b% fixed_delta_mdot
     401              :                else
     402            0 :                   mdot_next = b% mdot_hi/b% change_factor
     403              :                end if
     404              :             end if
     405              :          else  ! don't have either
     406            0 :             if (mdot_current > starting_mdot .and. (.not. abs(mdot_current) > 0)) then  ! recall that both are negative
     407              :                mdot_next = starting_mdot
     408            0 :             else if (new_function_to_solve >= 0) then
     409            0 :                b% mdot_lo = mdot_current
     410            0 :                b% implicit_function_lo = new_function_to_solve
     411            0 :                b% have_mdot_lo = .true.
     412            0 :                mdot_next = b% mdot_lo*b% change_factor
     413              :             else
     414            0 :                b% mdot_hi = mdot_current
     415            0 :                b% implicit_function_hi = new_function_to_solve
     416            0 :                b% have_mdot_hi = .true.
     417            0 :                if (use_sum .and. mod(b% num_tries, 2) == 0) then
     418            0 :                   mdot_next = b% mdot_hi + b% fixed_delta_mdot
     419              :                else
     420            0 :                   mdot_next = b% mdot_hi/b% change_factor
     421              :                end if
     422              :             end if
     423              :          end if
     424              : 
     425            0 :       end function pick_mdot_for_implicit_rlo
     426              : 
     427              : 
     428            0 :       subroutine eval_mdot_edd(binary_id, mdot_edd, mdot_edd_eta, ierr)
     429            0 :          use utils_lib, only: is_bad
     430              : 
     431              :          integer, intent(in) :: binary_id
     432              :          real(dp), intent(out) :: mdot_edd  ! eddington accretion rate
     433              :          real(dp), intent(out) :: mdot_edd_eta  ! fraction of rest mass energy released as radiation
     434              :          integer, intent(out) :: ierr
     435              :          type(binary_info), pointer :: b
     436              :          include 'formats'
     437              : 
     438              :          ierr = 0
     439            0 :          call binary_ptr(binary_id, b, ierr)
     440            0 :          if (ierr /= 0) then
     441            0 :             write(*,*) 'failed in binary_ptr'
     442            0 :             return
     443              :          end if
     444              : 
     445            0 :          if (b% point_mass_i == 0) then
     446            0 :             if (b% limit_retention_by_mdot_edd) then
     447            0 :                write(*,*) "Default mdot_edd calculation cannot be used when evolving both stars"
     448            0 :                write(*,*) "Maybe you want to set limit_retention_by_mdot_edd=.false. in binary_controls?"
     449            0 :                write(*,*) "Setting mdot_edd to zero"
     450              :             end if
     451            0 :             mdot_edd = 0
     452            0 :             mdot_edd_eta = 0
     453            0 :             return
     454              :          end if
     455              : 
     456            0 :          if (b% use_this_for_mdot_edd_eta > 0) then
     457            0 :             mdot_edd_eta = b% use_this_for_mdot_edd_eta
     458              :          else
     459              :             ! eg., eq. (6) of Podsiadlowski, Rappaport & Han 2003, MNRAS, 341, 385
     460              :             mdot_edd_eta = 1d0 &
     461            0 :                  - sqrt(1d0 - pow2(min(b% m(b% a_i),sqrt(6d0)*b% eq_initial_bh_mass)/(3d0*b% eq_initial_bh_mass)))
     462              :          end if
     463              : 
     464            0 :          if (b% use_this_for_mdot_edd > 0) then
     465            0 :             mdot_edd = b% use_this_for_mdot_edd*(Msun/secyer)
     466              :          else
     467              :             ! eg., eq. (9) of Podsiadlowski, Rappaport & Han 2003, MNRAS, 341, 385
     468            0 :             if (.not. b% use_es_opacity_for_mdot_edd) then
     469              :                mdot_edd = pi4*standard_cgrav*b% m(b% a_i) &
     470            0 :                   /(clight*b% s_donor% opacity(1)*mdot_edd_eta)
     471              :             else
     472              :                mdot_edd = pi4*standard_cgrav*b% m(b% a_i)&
     473            0 :                   /(clight*0.2d0*(1d0+b% s_donor% surface_h1)*mdot_edd_eta)
     474              :             end if
     475              :          end if
     476              : 
     477            0 :          if (is_bad(mdot_edd_eta) .or. mdot_edd_eta<0) then
     478            0 :             write(*,*) "ERROR while computing mdot_edd_eta"
     479            0 :             ierr = -1
     480            0 :             write(*,*) "mdot_edd_eta, b% m(b% a_i), b% eq_initial_bh_mass", &
     481            0 :                mdot_edd_eta, b% m(b% a_i), b% eq_initial_bh_mass
     482            0 :             stop
     483              :          end if
     484              : 
     485            0 :          if (is_bad(mdot_edd) .or. mdot_edd<0) then
     486            0 :             write(*,*) "ERROR while computing mdot_edd"
     487            0 :             ierr = -1
     488            0 :             write(*,*) "mdot_edd, b% m(b% a_i), b% s_donor% opacity(1), b% s_donor% surface_h1", &
     489            0 :                mdot_edd, b% m(b% a_i), b% s_donor% opacity(1), b% s_donor% surface_h1
     490            0 :             stop
     491              :          end if
     492              : 
     493              :       end subroutine eval_mdot_edd
     494              : 
     495            0 :       subroutine adjust_mdots(b)
     496              :          use binary_wind, only: eval_wind_xfer_fractions
     497              :          type (binary_info), pointer :: b
     498              : 
     499              :          real(dp) :: actual_mtransfer_rate
     500              :          integer :: ierr
     501              : 
     502            0 :          actual_mtransfer_rate = 0d0
     503              : 
     504            0 :          if (b% use_other_adjust_mdots) then
     505            0 :             call b% other_adjust_mdots(b% binary_id, ierr)
     506            0 :             if (ierr /= 0) then
     507            0 :                write(*,*) "Error in other_adjust_mdots"
     508            0 :                stop
     509              :             end if
     510              :             return
     511              :          end if
     512              : 
     513              :          b% fixed_xfer_fraction = 1 - b% mass_transfer_alpha - b% mass_transfer_beta - &
     514            0 :             b% mass_transfer_delta
     515              : 
     516            0 :          if (.not. b% use_other_mdot_edd) then
     517            0 :             call eval_mdot_edd(b% binary_id, b% mdot_edd, b% mdot_edd_eta, ierr)
     518              :          else
     519            0 :             call b% other_mdot_edd(b% binary_id, b% mdot_edd, b% mdot_edd_eta, ierr)
     520              :          end if
     521              : 
     522              :          ! Add tidal enhancement of wind
     523            0 :          call Tout_enhance_wind(b, b% s_donor)
     524            0 :          if (b% point_mass_i == 0) then
     525              :             ! do not repeat if using the implicit wind
     526            0 :             if (.not. (b% num_tries >0 .and. b% s_accretor% was_in_implicit_wind_limit)) &
     527            0 :                call Tout_enhance_wind(b, b% s_accretor)
     528              :          end if
     529              : 
     530              :          ! solve wind mass transfer
     531              :          ! b% mdot_wind_transfer(b% d_i) is a negative number that gives the
     532              :          ! amount of mass transferred by unit time from the donor to the
     533              :          ! accretor.
     534            0 :          call eval_wind_xfer_fractions(b% binary_id, ierr)
     535            0 :          if (ierr/=0) then
     536            0 :             write(*,*) "Error in eval_wind_xfer_fractions"
     537            0 :             return
     538              :          end if
     539              :          b% mdot_wind_transfer(b% d_i) = b% s_donor% mstar_dot * &
     540            0 :             b% wind_xfer_fraction(b% d_i)
     541            0 :          if (b% point_mass_i == 0) then
     542              :             b% mdot_wind_transfer(b% a_i) = b% s_accretor% mstar_dot * &
     543            0 :                b% wind_xfer_fraction(b% a_i)
     544              :          else
     545            0 :             b% mdot_wind_transfer(b% a_i) = 0d0
     546              :          end if
     547              : 
     548              :          ! Set mdot for the donor
     549              :          b% s_donor% mstar_dot = b% s_donor% mstar_dot + b% mtransfer_rate - &
     550            0 :             b% mdot_wind_transfer(b% a_i)
     551              : 
     552              :          ! Set mdot for the accretor
     553            0 :          if (b% point_mass_i == 0 .and. .not. b% CE_flag) then
     554              :             ! do not repeat if using the implicit wind
     555            0 :             if (.not. (b% num_tries >0 .and. b% s_accretor% was_in_implicit_wind_limit)) then
     556            0 :                b% accretion_mode = 0
     557            0 :                b% acc_am_div_kep_am = 0.0d0
     558              :                b% s_accretor% mstar_dot = b% s_accretor% mstar_dot - &
     559            0 :                   b% mtransfer_rate*b% fixed_xfer_fraction - b% mdot_wind_transfer(b% d_i)
     560              : 
     561              :                !set angular momentum accretion as described in A.3.3 of de Mink et al. 2013
     562            0 :                if (b% do_j_accretion) then
     563            0 :                   if (.not. b% use_other_accreted_material_j) then
     564            0 :                      call eval_accreted_material_j(b% binary_id, ierr)
     565              :                   else
     566            0 :                      call b% other_accreted_material_j(b% binary_id, ierr)
     567              :                   end if
     568            0 :                   if (ierr /= 0) then
     569            0 :                      write(*,*) 'error in accreted_material_j'
     570            0 :                      return
     571              :                   end if
     572              :                end if
     573              :             end if
     574              : 
     575            0 :             b% accretion_luminosity = 0d0  !only set for point mass
     576              : 
     577            0 :          else if (.not. b% CE_flag) then
     578              :             ! accretor is a point mass
     579            0 :             if (.not. b% model_twins_flag) then
     580              :                !combine wind and RLOF mass transfer
     581            0 :                actual_mtransfer_rate = b% mtransfer_rate*b% fixed_xfer_fraction+b% mdot_wind_transfer(b% d_i)  !defined negative
     582            0 :                b% component_mdot(b% a_i) = -actual_mtransfer_rate
     583              :                ! restrict accretion to the Eddington limit
     584            0 :                if (b% limit_retention_by_mdot_edd .and. b% component_mdot(b% a_i) > b% mdot_edd) then
     585            0 :                   b% component_mdot(b% a_i) = b% mdot_edd  ! remove all accretion above the edd limit
     586              :                end if
     587              :                b% accretion_luminosity = &
     588            0 :                   b% mdot_edd_eta*b% component_mdot(b% a_i)*clight*clight
     589              :                ! remove rest mass radiated away
     590            0 :                if (b% use_radiation_corrected_transfer_rate) then
     591            0 :                   b% component_mdot(b% a_i) = (1 - b% mdot_edd_eta) * b% component_mdot(b% a_i)
     592              :                end if
     593              :             end if
     594              :          else
     595              :             !doing CE, just be sure to set mdot for a point mass to zero
     596            0 :             b % accretion_luminosity = 0d0
     597            0 :             if (b% point_mass_i /= 0) then
     598            0 :                b% component_mdot(b% a_i) = 0d0
     599              :             end if
     600              :          end if
     601              : 
     602              :          ! mdot_system_transfer is mass lost from the vicinity of each star
     603              :          ! due to inefficient rlof mass transfer, mdot_system_cct is mass lost
     604              :          ! from a circumbinary coplanar toroid.
     605            0 :          if (b% mtransfer_rate+b% mdot_wind_transfer(b% d_i) >= 0 .or. b% CE_flag) then
     606            0 :             b% mdot_system_transfer(b% d_i) = 0d0
     607            0 :             b% mdot_system_transfer(b% a_i) = 0d0
     608            0 :             b% mdot_system_cct = 0d0
     609              :          else
     610            0 :             b% mdot_system_transfer(b% d_i) = b% mtransfer_rate * b% mass_transfer_alpha
     611            0 :             b% mdot_system_cct = b% mtransfer_rate * b% mass_transfer_delta
     612            0 :             if (b% point_mass_i == 0 .or. b% model_twins_flag) then
     613            0 :                b% mdot_system_transfer(b% a_i) = b% mtransfer_rate * b% mass_transfer_beta
     614              :             else
     615              :                ! do not compute mass lost from the vicinity using just mass_transfer_beta, as
     616              :                ! mass transfer can be stopped also by going past the Eddington limit
     617              :                b% mdot_system_transfer(b% a_i) = (actual_mtransfer_rate + b% component_mdot(b% a_i)) &
     618            0 :                   + b% mtransfer_rate * b% mass_transfer_beta
     619              :             end if
     620              :          end if
     621              : 
     622            0 :       end subroutine adjust_mdots
     623              : 
     624            0 :       subroutine rlo_mdot(binary_id, mdot, ierr)  ! Adapted from a routine kindly provided by Anastasios Fragkos
     625              :          integer, intent(in) :: binary_id
     626              :          real(dp), intent(out) :: mdot
     627              :          integer, intent(out) :: ierr
     628              :          type (binary_info), pointer :: b
     629              : 
     630              :          include 'formats'
     631              : 
     632              :          ierr = 0
     633            0 :          call binary_ptr(binary_id, b, ierr)
     634            0 :          if (ierr /= 0) then
     635            0 :             write(*,*) 'failed in binary_ptr'
     636            0 :             return
     637              :          end if
     638              : 
     639            0 :          mdot = 0d0
     640              : 
     641            0 :          if (b% mdot_scheme == "roche_lobe") then
     642            0 :             write(*,*) "mdot_scheme = roche_lobe not applicable for explicit scheme"
     643            0 :             write(*,*) "Not transferring mass"
     644            0 :             mdot = 0
     645            0 :             return
     646            0 :          else if (b% mdot_scheme /= "Ritter" .and. b% mdot_scheme /= "Kolb" .and. b% mdot_scheme /= "Arras") then
     647            0 :             write(*,*) "mdot_scheme = " , b% mdot_scheme , " not recognized"
     648            0 :             write(*,*) "Not transferring mass"
     649            0 :             mdot = 0
     650            0 :             return
     651              :          end if
     652              : 
     653            0 :          if (b% mdot_scheme == "Kolb" .and. b% eccentricity <= 0.0d0) then
     654            0 :             call get_info_for_ritter(b)
     655            0 :             mdot = b% mdot_thin
     656            0 :             call get_info_for_kolb(b)
     657            0 :             mdot = mdot + b% mdot_thick
     658              : 
     659            0 :          else if (b% mdot_scheme == "Kolb" .and. b% eccentricity > 0.0d0) then
     660            0 :             call get_info_for_ritter_eccentric(b)
     661            0 :             mdot = b% mdot_thin
     662            0 :             call get_info_for_kolb_eccentric(b)
     663            0 :             mdot = mdot + b% mdot_thick
     664              : 
     665            0 :          else if (b% mdot_scheme == "Ritter" .and. b% eccentricity <= 0.0d0) then
     666            0 :             call get_info_for_ritter(b)
     667            0 :             mdot = b% mdot_thin
     668              : 
     669            0 :          else if (b% mdot_scheme == "Ritter" .and. b% eccentricity > 0.0d0) then
     670            0 :             call get_info_for_ritter_eccentric(b)
     671            0 :             mdot = b% mdot_thin
     672              : 
     673              :          end if
     674              : 
     675            0 :          if (b% mdot_scheme == "Arras") then
     676            0 :             if (b% eccentricity > 0d0) &
     677            0 :                write(*,*) "mdot_scheme = Arras is not properly implemented for e>0"
     678            0 :             call get_info_for_arras(b)
     679            0 :             mdot = b% mdot_thin
     680              : 
     681              :          end if
     682              : 
     683            0 :       end subroutine rlo_mdot
     684              : 
     685            0 :       subroutine get_info_for_ritter(b)
     686              :          type(binary_info), pointer :: b
     687            0 :          real(dp) :: F1, q, rho, p, grav, hp, v_th, rl3, q_temp
     688              :          include 'formats'
     689              : 
     690              :          !--------------------- Optically thin MT rate -----------------------------------------------
     691              :          ! As described in H. Ritter 1988, A&A 202,93-100 and U. Kolb and H. Ritter 1990, A&A 236,385-392
     692              : 
     693            0 :          rho = b% s_donor% rho(1)  ! density at surface in g/cm^3
     694            0 :          p = b% s_donor% Peos(1)  ! pressure at surface in dynes/cm^2
     695            0 :          grav = standard_cgrav*b% m(b% d_i)/pow2(b% r(b% d_i))  ! local gravitational acceleration
     696            0 :          hp = p/(grav*rho)  ! pressure scale height
     697            0 :          v_th = sqrt(kerg * b% s_donor% T(1) / (mp * b% s_donor% mu(1)))
     698              : 
     699            0 :          q = b% m(b% a_i)/b% m(b% d_i)  ! Mass ratio, as defined in Ritter 1988
     700              :                                        ! (Kolb & Ritter 1990 use the opposite!)
     701              :          ! consider range of validity for F1, do not extrapolate! Eq. A9 of Ritter 1988
     702            0 :          q_temp = min(max(q,0.5d0),10d0)
     703            0 :          F1 = (1.23d0  + 0.5D0* log10(q_temp))
     704            0 :          rl3 = (b% rl(b% d_i))*(b% rl(b% d_i))*(b% rl(b% d_i))
     705              :          b% mdot_thin0 = (2.0D0*pi/exp(0.5d0)) * v_th*v_th*v_th * &
     706            0 :              rl3/(standard_cgrav*b% m(b% d_i)) * rho * F1
     707              :          !Once again, do not extrapolate! Eq. (7) of Ritter 1988
     708            0 :          q_temp = min(max(q,0.04d0),20d0)
     709            0 :          if (q_temp < 1.0d0) then
     710            0 :             b% ritter_h = hp/( 0.954D0 + 0.025D0*log10(q_temp) - 0.038D0*pow2(log10(q_temp)) )
     711              :          else
     712            0 :             b% ritter_h = hp/( 0.954D0 + 0.039D0*log10(q_temp) + 0.114D0*pow2(log10(q_temp)) )
     713              :          end if
     714              : 
     715            0 :          b% ritter_exponent = (b% r(b% d_i)-b% rl(b% d_i))/b% ritter_h
     716              : 
     717            0 :          if (b% mdot_scheme == "Kolb") then
     718            0 :             if (b% ritter_exponent > 0) then
     719            0 :                b% mdot_thin = -b% mdot_thin0
     720              :             else
     721            0 :                b% mdot_thin = -b% mdot_thin0 * exp(b% ritter_exponent)
     722              :             end if
     723              :          else
     724            0 :             b% mdot_thin = -b% mdot_thin0 * exp(b% ritter_exponent)
     725              :          end if
     726              : 
     727            0 :       end subroutine get_info_for_ritter
     728              : 
     729            0 :       real(dp) function calculate_kolb_mdot_thick(b, indexR, rl_d) result(mdot_thick)
     730              :          real(dp), intent(in) :: rl_d
     731              :          integer, intent(in) :: indexR
     732            0 :          real(dp) :: F1, F3, G1, d_P, q, q_temp
     733              :          integer :: i
     734              :          type(binary_info), pointer :: b
     735              :          include 'formats'
     736              : 
     737              :          !--------------------- Optically thin MT rate -----------------------------------------------
     738              :          ! As described in Kolb and H. Ritter 1990, A&A 236,385-392
     739              : 
     740              :          ! compute integral in Eq. (A17 of Kolb & Ritter 1990)
     741            0 :          mdot_thick = 0d0
     742            0 :          do i=1,indexR-1
     743            0 :             G1 = b% s_donor% gamma1(i)
     744            0 :             F3 = sqrt(G1) * pow(2d0/(G1+1d0), (G1+1d0)/(2d0*G1-2d0))
     745              :             mdot_thick = mdot_thick + F3*sqrt(kerg * b% s_donor% T(i) / &
     746            0 :                (mp * b% s_donor% mu(i)))*(b% s_donor% Peos(i+1)-b% s_donor% Peos(i))
     747              :          end do
     748              :          ! only take a fraction of d_P for last cell
     749            0 :          G1 = b% s_donor% gamma1(i)
     750            0 :          F3 = sqrt(G1) * pow(2d0/(G1+1d0), (G1+1d0)/(2d0*G1-2d0))
     751              :          d_P = (b% s_donor% r(indexR) - rl_d) / &
     752            0 :             (b% s_donor% r(indexR) - b% s_donor% r(indexR+1)) * (b% s_donor% Peos(i+1)-b% s_donor% Peos(i))
     753            0 :          mdot_thick = mdot_thick + F3*sqrt(kerg * b% s_donor% T(i) / (mp*b% s_donor% mu(i)))*d_P
     754              : 
     755            0 :          q = b% m(b% a_i)/b% m(b% d_i)  ! Mass ratio, as defined in Ritter 1988
     756              :                                        ! (Kolb & Ritter 1990 use the opposite!)
     757              :          ! consider range of validity for F1, do not extrapolate! Eq. A9 of Ritter 1988
     758            0 :          q_temp = min(max(q,0.5d0),10d0)
     759            0 :          F1 = (1.23d0  + 0.5D0* log10(q_temp))
     760            0 :          mdot_thick = -2.0D0*pi*F1*rl_d*rl_d*rl_d/(standard_cgrav*b% m(b% d_i))*mdot_thick
     761              : 
     762            0 :       end function calculate_kolb_mdot_thick
     763              : 
     764            0 :       subroutine get_info_for_kolb(b)
     765              :          type(binary_info), pointer :: b
     766              :          integer :: i, indexR
     767              :          include 'formats'
     768              : 
     769              :          !--------------------- Optically thick MT rate -----------------------------------------------
     770              :          ! As described in H. Ritter 1988, A&A 202,93-100 and U. Kolb and H. Ritter 1990, A&A 236,385-392
     771              : 
     772              :          ! First we need to find how deep inside the star the Roche lobe reaches. In other words the mesh point of the star at which R=R_RL
     773            0 :          b% mdot_thick = 0d0
     774            0 :          indexR=-1
     775            0 :          if(b% r(b% d_i)-b% rl(b% d_i) > 0.0d0) then
     776              :             i=1
     777            0 :             do while (b% s_donor% r(i) > b% rl(b% d_i))
     778            0 :                i=i+1
     779              :             end do
     780              : 
     781            0 :             if (i == 1) then
     782              :                b% mdot_thick = 0d0
     783              :             else
     784            0 :                b% mdot_thick = calculate_kolb_mdot_thick(b, i-1, b% rl(b% d_i))
     785              :             end if
     786              :          end if
     787              : 
     788            0 :       end subroutine get_info_for_kolb
     789              : 
     790            0 :       subroutine get_info_for_arras(b)
     791              :          type(binary_info), pointer :: b
     792            0 :          real(dp) :: q, rho, p, grav, hp, v_th
     793            0 :          real(dp) :: area,Asl,G,ma,md,mfac1,mfac2,my_mdot_thin,my_ritter_exponent,Omega,&
     794            0 :             phi,phiL1,q13,rfac,rhoL1,rv,rvL1,sep
     795              :          include 'formats'
     796              : 
     797              :          !--------------------- Optically thin MT rate -----------------------------------------------
     798              :          ! Ritter 1988 but with better fits for the various formulas that work at extreme q
     799              : 
     800            0 :          rho = b% s_donor% rho(1)  ! density at surface in g/cm^3
     801            0 :          p = b% s_donor% Peos(1)  ! pressure at surface in dynes/cm^2
     802            0 :          grav = standard_cgrav*b% m(b% d_i)/pow2(b% r(b% d_i))  ! local gravitational acceleration
     803            0 :          hp = p/(grav*rho)  ! pressure scale height
     804            0 :          v_th = sqrt(kerg * b% s_donor% T(1) / (mp * b% s_donor% mu(1)))
     805              : 
     806            0 :          q = b% m(b% a_i) / b% m(b% d_i)
     807            0 :          G = standard_cgrav
     808            0 :          md = b% m(b% d_i)
     809            0 :          ma = b% m(b% a_i)
     810            0 :          sep = b% separation
     811            0 :          Omega = 2.d0*pi / b% period
     812            0 :          rvL1 = b% rl(b% d_i)
     813            0 :          rv = b% r(b% d_i)
     814            0 :          mfac1 = 1d0 + ma/md  ! (md+ma)/md
     815              :          ! mfac2 = ( (md+ma)**2 + 3d0*ma*(md+ma) + 9d0*ma**2 ) / md**2
     816            0 :          mfac2 = 1d0 + 5d0*ma/md + 13d0*ma*ma/(md*md)
     817            0 :          rfac=rvL1/sep
     818              :          phiL1 = - G*md/rvL1 &
     819            0 :               * ( 1.d0 +  mfac1*pow3(rfac)/3.d0 + 4.d0*mfac2*pow6(rfac)/45.d0  )
     820            0 :               rfac=rv/sep
     821              :          phi = - G*md/rv &
     822            0 :               * ( 1.d0 +  mfac1*pow3(rfac)/3.d0 + 4.d0*mfac2*pow6(rfac)/45.d0  )
     823            0 :          my_ritter_exponent = - (phiL1-phi)/(v_th*v_th)
     824            0 :          rhoL1 = rho/sqrt(exp(1.d0)) * exp( my_ritter_exponent )
     825            0 :               q13=pow(q,one_third)
     826            0 :               Asl = 4.d0 + 4.16d0/(-0.96d0 + q13 + 1.d0/q13)
     827            0 :          area = 2.d0 * pi * pow2(v_th/Omega) / sqrt( Asl*(Asl-1d0) )
     828            0 :          my_mdot_thin = - rhoL1 * v_th * area
     829            0 :          b% mdot_thin = my_mdot_thin
     830              : 
     831            0 :       end subroutine get_info_for_arras
     832              : 
     833            0 :       subroutine get_info_for_ritter_eccentric(b)
     834              :          type(binary_info), pointer :: b
     835              :          integer :: i
     836            0 :          real(dp) :: F1, q, q_temp, rho, p, grav, hp, v_th, dm
     837            0 :          real(dp), DIMENSION(b% anomaly_steps):: mdot0, mdot, Erit, rl_d
     838              :          include 'formats'
     839              : 
     840              :          ! Optically thin MT rate adapted for eccentric orbits
     841              :          ! As described in H. Ritter 1988, A&A 202,93-100 and U. Kolb and H. Ritter 1990, A&A 236,385-392
     842              : 
     843            0 :          rho = b% s_donor% rho(1)  ! density at surface in g/cm^3
     844            0 :          p = b% s_donor% Peos(1)  ! pressure at surface in dynes/cm^2
     845            0 :          grav = standard_cgrav*b% m(b% d_i)/pow2(b% r(b% d_i))  ! local gravitational acceleration
     846            0 :          hp = p/(grav*rho)  ! pressure scale height
     847            0 :          v_th = sqrt(kerg * b% s_donor% T(1) / (mp * b% s_donor% mu(1)))  ! kerg = Boltzmann's constant
     848              : 
     849              :          ! phase dependant RL radius
     850            0 :          do i = 1, b% anomaly_steps
     851              :             rl_d(i) = b% rl(b% d_i) * (1d0 - pow2(b% eccentricity)) / &
     852            0 :                  (1 + b% eccentricity * cos(b% theta_co(i)) )
     853              :          end do
     854              : 
     855            0 :          q = b% m(b% a_i)/b% m(b% d_i)  ! Mass ratio, as defined in Ritter 1988
     856              :                                        ! (Kolb & Ritter 1990 use the opposite!)
     857            0 :          q_temp = min(max(q,0.5d0),10d0)
     858            0 :          F1 = (1.23d0  + 0.5D0* log10(q_temp))
     859              : 
     860              :          mdot0 = (2.0D0*pi/exp(0.5d0)) * pow3(v_th) * rl_d*rl_d*rl_d / &
     861            0 :              (standard_cgrav*b% m(b% d_i)) * rho * F1
     862              : 
     863            0 :          q_temp = min(max(q,0.04d0),20d0)
     864            0 :          if (q_temp < 1.0d0) then
     865            0 :             b% ritter_h = hp/( 0.954D0 + 0.025D0*log10(q_temp) - 0.038D0*pow2(log10(q_temp)) )
     866              :          else
     867            0 :             b% ritter_h = hp/( 0.954D0 + 0.039D0*log10(q_temp) + 0.114D0*pow2(log10(q_temp)) )
     868              :          end if
     869              : 
     870            0 :          Erit = (b% r(b% d_i)- rl_d) / b% ritter_h
     871              : 
     872            0 :          if (b% mdot_scheme == "Kolb") then
     873            0 :             do i = 1,b% anomaly_steps
     874            0 :                if (Erit(i) > 0) then
     875            0 :                   mdot(i) = -1 * mdot0(i)
     876              :                else
     877            0 :                   mdot(i) = -1 * mdot0(i) * exp(Erit(i))
     878              :                end if
     879              :             end do
     880              :          else
     881            0 :             do i = 1,b% anomaly_steps
     882            0 :                mdot(i) = -1 * mdot0(i) * exp(Erit(i))
     883              :             end do
     884              :          end if
     885              : 
     886            0 :          b% mdot_donor_theta = mdot
     887              : 
     888              :          !integrate to get total massloss
     889              :          dm = 0d0
     890            0 :          do i = 2,b% anomaly_steps  ! trapezoidal integration
     891            0 :             dm = dm + 0.5d0 * (mdot(i-1) + mdot(i)) * (b% time_co(i) - b% time_co(i-1))
     892              :          end do
     893              : 
     894            0 :          b% mdot_thin = dm
     895              : 
     896            0 :       end subroutine get_info_for_ritter_eccentric
     897              : 
     898            0 :       subroutine get_info_for_kolb_eccentric(b)
     899              :          type(binary_info), pointer :: b
     900            0 :          real(dp) :: e, dm
     901              :          integer :: i, j
     902            0 :          real(dp), DIMENSION(b% anomaly_steps):: rl_d_i, mdot_thick_i
     903              :          include 'formats'
     904              : 
     905              :          ! Optically thick MT rate adapted for eccentric orbits
     906              :          ! As described in H. Ritter 1988, A&A 202,93-100 and U. Kolb and H. Ritter 1990, A&A 236,385-392
     907              : 
     908            0 :          b% mdot_thick = 0d0
     909            0 :          e = b% eccentricity
     910              : 
     911              :          ! If the radius of the donor is smaller as the smallest RL radius,
     912              :          ! there is only atmospheric RLOF, thus return.
     913            0 :          if ( b% r(b% d_i) < b% rl(b% d_i) * (1-e*e)/(1+e) ) then
     914              :             return
     915              :          end if
     916              : 
     917              :          ! For each point in the orbit calculate mdot_thick
     918            0 :          do i = 1,b% anomaly_steps
     919              :             ! phase dependent RL radius
     920              :             rl_d_i(i) = b% rl(b% d_i) * (1d0 - e*e) / &
     921            0 :                  (1 + e*cos(b% theta_co(i)) )
     922              : 
     923              :             ! find how deep in the star we are
     924            0 :             j=1
     925            0 :             do while (b% s_donor% r(j) > rl_d_i(i))
     926            0 :                j=j+1
     927              :             end do
     928              : 
     929              :             ! calculate mdot_thick
     930            0 :             if (j == 1) then
     931            0 :                mdot_thick_i(i) = 0d0
     932              :             else
     933            0 :                mdot_thick_i(i) = calculate_kolb_mdot_thick(b, j-1, rl_d_i(i))
     934              :             end if
     935              :          end do
     936              : 
     937            0 :          b% mdot_donor_theta = b% mdot_donor_theta + mdot_thick_i
     938              : 
     939              :          ! Integrate mdot_thick over the orbit
     940              :          dm = 0d0
     941            0 :          do i = 2,b% anomaly_steps  ! trapezoidal integration
     942              :             dm = dm + 0.5d0 * (mdot_thick_i(i-1) + mdot_thick_i(i)) * &
     943            0 :                               (b% time_co(i) - b% time_co(i-1))
     944              :          end do
     945              : 
     946            0 :          b% mdot_thick = dm
     947              : 
     948            0 :       end subroutine get_info_for_kolb_eccentric
     949              : 
     950            0 :       subroutine eval_accreted_material_j(binary_id, ierr)
     951              :          integer, intent(in) :: binary_id
     952              :          integer, intent(out) :: ierr
     953              :          type(binary_info), pointer :: b
     954            0 :          real(dp) :: qratio, min_r
     955              :          logical, parameter :: dbg = .false.
     956              :          include 'formats'
     957              : 
     958              :          ierr = 0
     959            0 :          call binary_ptr(binary_id, b, ierr)
     960            0 :          if (ierr /= 0) then
     961            0 :             write(*,*) 'failed in binary_ptr'
     962            0 :             return
     963              :          end if
     964            0 :          qratio = b% m(b% a_i) / b% m(b% d_i)
     965            0 :          qratio = min(max(qratio,0.0667d0),15d0)
     966            0 :          min_r = 0.0425d0*b% separation*pow(qratio+qratio*qratio, 0.25d0)
     967              : 
     968              :          !TODO: MUST USE EQUATORIAL RADIUS
     969              :          if (dbg) write(*,*) "radius, impact_radius, separation: ", &
     970              :              b% r(b% a_i), min_r/rsun, b% separation/rsun
     971            0 :          if (b% r(b% a_i) < min_r) then
     972            0 :             b% accretion_mode = 2
     973              :             b% s_accretor% accreted_material_j = &
     974            0 :                sqrt(standard_cgrav * b% m(b% a_i) * b% r(b% a_i))
     975              :          else
     976            0 :             b% accretion_mode = 1
     977              :             b% s_accretor% accreted_material_j = &
     978            0 :                sqrt(standard_cgrav * b% m(b% a_i) * 1.7d0*min_r)
     979              :          end if
     980              :          b% acc_am_div_kep_am = b% s_accretor% accreted_material_j / &
     981            0 :              sqrt(standard_cgrav * b% m(b% a_i) * b% r(b% a_i))
     982              : 
     983              :           !TODO: when using wind mass transfer donor star can end up
     984              :           ! with positive mdot, need to properly set jdot in that case
     985              : 
     986              :       end subroutine eval_accreted_material_j
     987              : 
     988            0 :       subroutine set_accretion_composition(b, acc_index)
     989              :          use chem_def, only: chem_isos
     990              :          type (binary_info), pointer :: b
     991              :          integer, intent(in) :: acc_index  ! index of star that gains mass
     992              : 
     993              :          integer :: j
     994              : 
     995            0 :          if (acc_index == b% a_i) then
     996              :             !set accreted material composition
     997            0 :             b% s_accretor% num_accretion_species = b% s_donor% species
     998              : 
     999            0 :             if(b% s_donor% species > size(b% s_accretor% accretion_species_id,dim=1)) then
    1000            0 :                call mesa_error(__FILE__,__LINE__,'Nuclear network is too large for accretor, increase max_num_accretion_species')
    1001              :             end if
    1002              : 
    1003            0 :             do j = 1, b% s_donor% species
    1004            0 :                b% s_accretor% accretion_species_id(j) = chem_isos% name(b% s_donor% chem_id(j))
    1005            0 :                b% s_accretor% accretion_species_xa(j) = b% s_donor% xa_removed(j)
    1006              :             end do
    1007              :          else
    1008              :             ! also for the donor to account for wind mass transfer
    1009            0 :             b% s_donor% num_accretion_species = b% s_accretor% species
    1010              : 
    1011            0 :             if(b% s_accretor% species > size(b% s_donor% accretion_species_id,dim=1)) then
    1012            0 :                call mesa_error(__FILE__,__LINE__,'Nuclear network is too large for donor, increase max_num_accretion_species')
    1013              :             end if
    1014              : 
    1015            0 :             do j = 1, b% s_accretor% species
    1016            0 :                b% s_donor% accretion_species_id(j) = chem_isos% name(b% s_accretor% chem_id(j))
    1017            0 :                b% s_donor% accretion_species_xa(j) = b% s_accretor% xa_removed(j)
    1018              :             end do
    1019              :          end if
    1020              : 
    1021            0 :       end subroutine set_accretion_composition
    1022              : 
    1023              :       end module binary_mdot
        

Generated by: LCOV version 2.0-1