LCOV - code coverage report
Current view: top level - binary/private - binary_evolve.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 394 0
Test Date: 2025-10-14 06:41:40 Functions: 0.0 % 9 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_evolve
      22              : 
      23              :       use const_def, only: dp, pi, msun, rsun, secyer, secday, one_third, standard_cgrav
      24              :       use math_lib
      25              :       use star_lib
      26              :       use star_def
      27              :       use binary_def
      28              :       use binary_utils, only: eval_rlobe, set_angular_momentum_j, &
      29              :          set_separation_eccentricity, set_period_eccentricity
      30              : 
      31              :       implicit none
      32              : 
      33              :       contains
      34              : 
      35            0 :          subroutine binarydata_init(b, doing_restart)
      36              :          use utils_lib, only: is_bad
      37              :          type (binary_info), pointer :: b
      38              :          logical, intent(in) :: doing_restart
      39              :          integer :: finish_step_result
      40              :          integer :: i, ierr
      41            0 :          real(dp) :: r_isco, Z1, Z2
      42              :          include 'formats'
      43              : 
      44            0 :          b% evolve_both_stars = b% job% evolve_both_stars
      45            0 :          b% warn_binary_extra = b% job% warn_binary_extra
      46              : 
      47              :          ! Initialize arrays for phase dependent calculations
      48              :          allocate(b% theta_co(b% anomaly_steps), b% time_co(b% anomaly_steps), &
      49            0 :             b% mdot_donor_theta(b% anomaly_steps))
      50              :          allocate(b% edot_theta(b% anomaly_steps), b% e1(b% anomaly_steps), &
      51            0 :             b% e2(b% anomaly_steps), b% e3(b% anomaly_steps))
      52              : 
      53            0 :          if (.not. doing_restart) then
      54            0 :             if (.not. b% evolve_both_stars) then
      55            0 :                b% point_mass_i = 2
      56              :             else if ((b% job% change_initial_model_twins_flag .or. b% job% change_model_twins_flag) &
      57            0 :                   .and. b% job% new_model_twins_flag) then
      58            0 :                b% point_mass_i = 2
      59              :             else
      60            0 :                b% point_mass_i = 0
      61              :             end if
      62              : 
      63            0 :             b% doing_first_model_of_run = .true.
      64            0 :             b% open_new_history_file = .true.
      65              : 
      66            0 :             b% s_donor => b% s1
      67            0 :             b% s_accretor => b% s2
      68            0 :             b% d_i = 1
      69            0 :             b% a_i = 2
      70              : 
      71            0 :             b% max_timestep = 1d99
      72            0 :             b% change_factor = b% initial_change_factor
      73              : 
      74            0 :             if (b% point_mass_i /= 1) then
      75            0 :                initial_mass(1) = b% s1% mstar / Msun
      76              :             else
      77            0 :                initial_mass(1) = b% m1
      78              :             end if
      79            0 :             if (b% point_mass_i /= 2) then
      80            0 :                initial_mass(2) = b% s2% mstar / Msun
      81              :             else
      82            0 :                if (.not. b% model_twins_flag) then
      83            0 :                   initial_mass(2) = b% m2
      84              :                else
      85            0 :                   initial_mass(2) = initial_mass(1)
      86              :                end if
      87              :             end if
      88              : 
      89            0 :             b% m(1) = initial_mass(1)*Msun
      90            0 :             b% m(2) = initial_mass(2)*Msun
      91            0 :             if (b% point_mass_i /= 1) then
      92            0 :                b% r(1) = Rsun*b% s1% photosphere_r
      93              :             else
      94            0 :                b% r(1) = 0
      95              :             end if
      96            0 :             if (b% point_mass_i /= 2) then
      97            0 :                b% r(2) = Rsun*b% s2% photosphere_r
      98              :             else
      99            0 :                if (.not. b% model_twins_flag) then
     100            0 :                   b% r(2) = 0
     101              :                else
     102            0 :                   b% r(2) = b% r(1)
     103              :                end if
     104              :             end if
     105              : 
     106            0 :             if (b% initial_period_in_days <= 0) then  ! calculate from initial_separation_in_Rsuns
     107              :                call set_separation_eccentricity(b% binary_id, &
     108            0 :                   b% initial_separation_in_Rsuns*Rsun, b% initial_eccentricity, ierr)
     109            0 :                   if (ierr /= 0) then
     110            0 :                      return
     111              :                   end if
     112              :             else
     113              :                call set_period_eccentricity(b% binary_id, &
     114            0 :                   b% initial_period_in_days*secday, b% initial_eccentricity, ierr)
     115            0 :                   if (ierr /= 0) then
     116              :                      return
     117              :                   end if
     118              :             end if
     119              : 
     120              :          ! Set all parameters necessary for integration over the binary orbit
     121              :          ! 1) true anomaly = polar angle from periastron 0 -> 2pi
     122            0 :             do i = 1,b% anomaly_steps
     123            0 :                b% theta_co(i) = (i-1) * (2 * pi) / b% anomaly_steps
     124              :             end do
     125              :             ! 2) time between periastron and polar angle theta 0 -> 1 (fraction of the
     126              :             !    orbital period)
     127            0 :             do i = 1,b% anomaly_steps  ! time between periastron and polar angle theta
     128              :                b% time_co(i) = ( 2 * atan( sqrt( (1-b% eccentricity)/(1 + b% eccentricity) ) * &
     129              :                                tan(b% theta_co(i)/2d0) ) - b% eccentricity * &
     130              :                                sqrt(1 - pow2(b% eccentricity)) * sin(b% theta_co(i)) / &
     131            0 :                                (1 + b% eccentricity * cos(b% theta_co(i)) ) ) /2.d0 /pi
     132            0 :                if (i > b% anomaly_steps/2+1) then
     133            0 :                   b% time_co(i) = b% time_co(i) + b% time_co(b% anomaly_steps/2+1) * 2
     134              :                end if
     135              :             end do
     136              : 
     137            0 :             if (is_bad(b% rl_relative_gap(1))) call mesa_error(__FILE__,__LINE__,'binarydata_init')
     138            0 :             if (is_bad(b% rl_relative_gap(2))) call mesa_error(__FILE__,__LINE__,'binarydata_init')
     139            0 :             b% using_jdot_mb(1) = .false.
     140            0 :             b% using_jdot_mb(2) = .false.
     141              : 
     142            0 :             if (b% point_mass_i /= 0) then
     143              :                ! this part is only relevant for BH accretors
     144            0 :                if (b% initial_bh_spin < 0d0) then
     145            0 :                   b% initial_bh_spin = 0d0
     146            0 :                   write(*,*) "initial_bh_spin is smaller than zero. It has been set to zero."
     147            0 :                else if (b% initial_bh_spin > 1d0) then
     148            0 :                   b% initial_bh_spin = 1d0
     149            0 :                   write(*,*) "initial_bh_spin is larger than one. It has been set to one."
     150              :                end if
     151              :                ! compute isco radius from eq. 2.21 of Bardeen et al. (1972), ApJ, 178, 347
     152              :                Z1 = 1d0 + pow(1d0 - pow2(b% initial_bh_spin),one_third) &
     153            0 :                   * (pow(1d0 + b% initial_bh_spin,one_third) + pow(1d0 - b% initial_bh_spin,one_third))
     154            0 :                Z2 = sqrt(3d0*pow2(b% initial_bh_spin) + pow2(Z1))
     155            0 :                r_isco = 3d0 + Z2 - sqrt((3d0 - Z1)*(3d0 + Z1 + 2d0*Z2))
     156              :                ! compute equivalent mass at zero spin from eq. (3+1/2) (ie. the equation between (3) and (4))
     157              :                ! of Bardeen (1970), Nature, 226, 65, taking values with subscript zero to correspond to
     158              :                ! zero spin (r_isco = 6).
     159            0 :                b% eq_initial_bh_mass = b% m(b% point_mass_i) * sqrt(r_isco/6d0)
     160              :             end if
     161              : 
     162            0 :             write(*,'(A)')
     163            0 :             write(*,1) 'm2', b% m2
     164            0 :             write(*,1) 'm1', b% m1
     165            0 :             write(*,1) 'initial_period_in_days', b% initial_period_in_days
     166            0 :             write(*,1) 'initial_separation_in_Rsun', b% separation/Rsun
     167            0 :             write(*,1) 'jdot_multiplier', b% jdot_multiplier
     168            0 :             write(*,1) 'fr', b% fr
     169            0 :             write(*,'(A)')
     170              : 
     171            0 :             min_binary_period = b% period
     172            0 :             b% min_binary_separation = b% separation
     173            0 :             initial_binary_period = b% period
     174              : 
     175            0 :             b% ixtra(:) = 0
     176            0 :             b% xtra(:) = 0d0
     177            0 :             b% lxtra(:) = .false.
     178              : 
     179            0 :             b% CE_num1 = 0
     180            0 :             b% CE_num2 = 0
     181            0 :             b% CE_lambda1 = 0d0
     182            0 :             b% CE_lambda2 = 0d0
     183            0 :             b% CE_Ebind1 = 0d0
     184            0 :             b% CE_Ebind2 = 0d0
     185            0 :             b% mtransfer_rate = 0d0
     186              : 
     187            0 :             b% num_tries = 0
     188              : 
     189            0 :             finish_step_result = binary_finish_step(b)
     190              :          else
     191            0 :             if (b% d_i == b% point_mass_i) then
     192            0 :                write(*,*) "WARNING: restart has donor star set as point mass"
     193            0 :                write(*,*) "switching donor"
     194            0 :                b% d_i = b% a_i
     195            0 :                b% a_i = b% point_mass_i
     196              :             end if
     197            0 :             if (b% d_i == 1) then
     198            0 :                b% s_donor => b% s1
     199            0 :                b% s_accretor => b% s2
     200              :             else
     201            0 :                b% s_donor => b% s2
     202            0 :                b% s_accretor => b% s1
     203              :             end if
     204              :          end if
     205              : 
     206              :       end subroutine binarydata_init
     207              : 
     208            0 :       subroutine set_donor_star(b)
     209              :          type (binary_info), pointer :: b
     210              :          logical :: switch_donor
     211            0 :          real(dp) :: mdot_hi_temp
     212              :          include 'formats'
     213              : 
     214            0 :          switch_donor = .false.
     215              : 
     216            0 :          if (b% keep_donor_fixed .and. b% mdot_scheme /= "contact") return
     217              : 
     218              :          if (b% mdot_scheme == "roche_lobe" .and. &
     219            0 :             abs(b% mtransfer_rate/(Msun/secyer)) < b% mdot_limit_donor_switch .and. &
     220              :             b% rl_relative_gap_old(b% a_i) > b% rl_relative_gap_old(b% d_i)) then
     221              :             switch_donor = .true.
     222            0 :          else if (b% mtransfer_rate > 0d0) then
     223            0 :             switch_donor = .true.
     224            0 :             b% mtransfer_rate = - b% mtransfer_rate
     225            0 :             mdot_hi_temp = b% mdot_hi
     226            0 :             b% mdot_hi = - b% mdot_lo
     227            0 :             b% mdot_lo = - mdot_hi_temp
     228            0 :             if (.not. b% have_mdot_lo) then
     229            0 :                b% have_mdot_hi = .false.
     230              :             end if
     231            0 :             b% have_mdot_lo = .true.
     232            0 :             b% fixed_delta_mdot = b% fixed_delta_mdot / 2.0d0
     233              :          else if (b% mdot_scheme == "contact" .and. &
     234              :             b% rl_relative_gap_old(b% a_i) > b% rl_relative_gap_old(b% d_i) .and. &
     235              :             b% rl_relative_gap_old(b% a_i) < - b% implicit_scheme_tolerance .and. &
     236            0 :             b% rl_relative_gap_old(b% d_i) < - b% implicit_scheme_tolerance .and. &
     237              :             abs(b% mtransfer_rate/(Msun/secyer)) < b% mdot_limit_donor_switch) then
     238              :             switch_donor = .true.
     239              :          end if
     240              : 
     241              :          if (switch_donor) then
     242            0 :             if (b% report_rlo_solver_progress) write(*,*) "switching donor"
     243            0 :             if (b% d_i == 2) then
     244            0 :                b% d_i = 1
     245            0 :                b% a_i = 2
     246            0 :                b% s_donor => b% s1
     247            0 :                b% s_accretor => b% s2
     248              :             else
     249            0 :                b% d_i = 2
     250            0 :                b% a_i = 1
     251            0 :                b% s_donor => b% s2
     252            0 :                b% s_accretor => b% s1
     253              :             end if
     254              :          end if
     255              :       end subroutine set_donor_star
     256              : 
     257            0 :       integer function binary_evolve_step(b)
     258              :          use utils_lib, only: is_bad
     259              :          use binary_jdot, only: get_jdot
     260              :          use binary_edot, only: get_edot
     261              :          type(binary_info), pointer :: b
     262              :          integer :: i
     263              : 
     264              :          include 'formats'
     265              : 
     266              :          ! store the final mdots used for each star
     267              :          ! for a point mass accretor this is already set in the subroutine adjust_mdots of binary_mdot
     268            0 :          b% component_mdot(b% d_i) = b% s_donor% mstar_dot
     269            0 :          if (b% point_mass_i == 0) then
     270            0 :             b% component_mdot(b% a_i) = b% s_accretor% mstar_dot
     271            0 :          else if (b% model_twins_flag) then
     272            0 :             b% component_mdot(b% a_i) = b% component_mdot(b% d_i)
     273              :          end if
     274              : 
     275            0 :          b% m(b% d_i) = b% s_donor% mstar
     276            0 :          b% time_step = b% s_donor% time_step
     277            0 :          if (b% point_mass_i == 0) then
     278            0 :             b% m(b% a_i) = b% s_accretor% mstar
     279            0 :          else if (.not. b% model_twins_flag) then
     280            0 :             b% m(b% a_i) = b% m(b% a_i) + b% component_mdot(b% a_i)*b% s_donor% dt
     281              :          else
     282            0 :             b% m(b% a_i) = b% m(b% d_i)
     283              :          end if
     284              : 
     285            0 :          if (b% point_mass_i /= 1) then
     286            0 :             b% r(1) = Rsun*b% s1% photosphere_r
     287              :          else
     288            0 :             b% r(1) = 0
     289              :          end if
     290            0 :          if (b% point_mass_i /= 2) then
     291            0 :             b% r(2) = Rsun*b% s2% photosphere_r
     292            0 :          else if (.not. b% model_twins_flag) then
     293            0 :             b% r(2) = 0
     294              :          else
     295            0 :             b% r(2) = b% r(1)
     296              :          end if
     297              : 
     298              :          ! solve the winds in the system for jdot calculation,
     299              :          ! these don't include mass lost due to mass_transfer_efficiency < 1.0
     300              :          ! Since s% mstar_dot is not just mass loss, but includes the contribution from
     301              :          ! RLO mass transfer and wind mass transfer from the other component, these
     302              :          ! need to be removed to get the actual wind. Also, the fraction of the wind
     303              :          ! that is fransferred to the other component does not leave the system, and
     304              :          ! needs to be removed as well.
     305              :          b% mdot_system_wind(b% d_i) = b% s_donor% mstar_dot - b% mtransfer_rate &
     306            0 :             + b% mdot_wind_transfer(b% a_i) - b% mdot_wind_transfer(b% d_i)
     307            0 :          if (b% point_mass_i == 0) then
     308              :             b% mdot_system_wind(b% a_i) = b% s_accretor% mstar_dot &
     309              :                 + b% mtransfer_rate * b% fixed_xfer_fraction + b% mdot_wind_transfer(b% d_i) &
     310            0 :                 - b% mdot_wind_transfer(b% a_i)
     311              :          else
     312            0 :             if (.not. b% model_twins_flag) then
     313            0 :                b% mdot_system_wind(b% a_i) = 0.0d0
     314              :             else
     315            0 :                b% mdot_system_wind(b% a_i) = b% mdot_system_wind(b% d_i)
     316              :             end if
     317              :          end if
     318              : 
     319              :          ! get jdot and update orbital J
     320            0 :          b% jdot = get_jdot(b)
     321            0 :          b% angular_momentum_j = b% angular_momentum_j + b% jdot*b% time_step*secyer
     322              : 
     323            0 :          if (b% angular_momentum_j <= 0) then
     324            0 :             write(*,*) 'Retry due to negative angular_momentum_j', b% angular_momentum_j
     325            0 :             b% have_to_reduce_timestep_due_to_j = .true.
     326            0 :             binary_evolve_step = retry
     327            0 :             return
     328              :          end if
     329              : 
     330              :          ! update the eccentricity (ignore in first step)
     331            0 :          if (.not. b% doing_first_model_of_run) then
     332            0 :             b% eccentricity = b% eccentricity + get_edot(b) *b% time_step*secyer
     333            0 :             if (b% eccentricity < b% min_eccentricity) b% eccentricity = b% min_eccentricity
     334            0 :             if (b% eccentricity > b% max_eccentricity) b% eccentricity = b% max_eccentricity
     335              :          else
     336            0 :             b% edot_tidal = 0d0
     337            0 :             b% edot_enhance = 0d0
     338            0 :             b% extra_edot = 0d0
     339            0 :             b% edot = 0d0
     340              :          end if
     341              : 
     342              :          !use new eccentricity to calculate new time coordinate
     343            0 :          do i = 1,b% anomaly_steps  ! time between periastron and polar angle theta
     344              :             b% time_co(i) = ( 2 * atan( sqrt( (1-b% eccentricity)/(1 + b% eccentricity) ) * &
     345              :                             tan(b% theta_co(i)/2d0) ) - b% eccentricity * &
     346              :                             sqrt(1 - pow2(b% eccentricity)) * sin(b% theta_co(i)) / &
     347            0 :                             (1 + b% eccentricity * cos(b% theta_co(i)) ) ) /2.d0 /pi
     348            0 :             if (i > b% anomaly_steps/2+1) then
     349            0 :                b% time_co(i) = b% time_co(i) + b% time_co(b% anomaly_steps/2+1) * 2
     350              :             end if
     351              :          end do
     352              : 
     353              :          ! use the new j to calculate new separation
     354              :          b% separation = (pow2(b% angular_momentum_j/(b% m(1)*b% m(2)))) *&
     355            0 :              (b% m(1)+b% m(2)) / standard_cgrav * 1 / (1 - pow2(b% eccentricity))
     356            0 :          if (b% separation < b% min_binary_separation) &
     357            0 :             b% min_binary_separation = b% separation
     358              : 
     359              :          b% period = 2*pi*sqrt(pow3(b% separation)/&
     360            0 :                (standard_cgrav*(b% m(1)+b% m(2))))
     361            0 :          if (b% period < min_binary_period) min_binary_period = b% period
     362              : 
     363              :          ! use the new separation to calculate the new roche lobe radius
     364              : 
     365            0 :          b% rl(1) = eval_rlobe(b% m(1), b% m(2), b% separation)
     366            0 :          b% rl(2) = eval_rlobe(b% m(2), b% m(1), b% separation)
     367              :          b% rl_relative_gap(1) = (b% r(1) - b% rl(1) * (1 - b% eccentricity) ) / &
     368            0 :              b% rl(1) / (1 - b% eccentricity)  ! gap < 0 means out of contact
     369              :          b% rl_relative_gap(2) = (b% r(2) - b% rl(2) * (1 - b% eccentricity) ) / &
     370            0 :              b% rl(2) / (1 - b% eccentricity)  ! gap < 0 means out of contact
     371              : 
     372            0 :          if (is_bad(b% rl_relative_gap(1)) .or. is_bad(b% rl_relative_gap(2))) then
     373            0 :             write(*,*) "rl_relative_gap for each component", b% rl_relative_gap(1), b% rl_relative_gap(2)
     374            0 :             write(*,*) "rl for each component", b% rl(1), b% rl(2)
     375            0 :             write(*,*) "r for each component", b% r(1), b% r(2)
     376            0 :             write(*,*) "m for each component", b% m(1), b% m(2)
     377            0 :             write(*,*) "separation, angular momentum", b% separation, b% angular_momentum_j
     378            0 :             write(*,*) "jdot, jdot_mb, jdot_gr, jdot_ml:", b% jdot, b% jdot_mb, b% jdot_gr, b% jdot_ml
     379            0 :             write(*,*) "jdot_ls, jdot_missing_wind, extra_jdot:", b% jdot_ls, b% jdot_missing_wind, b% extra_jdot
     380            0 :             write(*,*) 'error solving rl_rel_gap'
     381            0 :             binary_evolve_step = retry
     382            0 :             return
     383              :          end if
     384              : 
     385            0 :          b% model_number = b% model_number + 1
     386            0 :          b% binary_age = b% binary_age + b% time_step
     387              : 
     388            0 :          binary_evolve_step = keep_going
     389              : 
     390            0 :       end function binary_evolve_step
     391              : 
     392            0 :       integer function binary_check_model(b)
     393            0 :          use binary_mdot, only: rlo_mdot, check_implicit_rlo
     394              :          use binary_irradiation
     395              :          type (binary_info), pointer :: b
     396              : 
     397              :          integer :: ierr, id
     398              :          logical :: implicit_rlo
     399            0 :          real(dp) :: new_mdot, q
     400              : 
     401              : 
     402              :          include 'formats'
     403              : 
     404            0 :          binary_check_model = retry
     405            0 :          ierr = 0
     406              : 
     407            0 :          implicit_rlo = (b% max_tries_to_achieve > 0 .and. b% implicit_scheme_tolerance > 0d0)
     408              : 
     409            0 :          binary_check_model = keep_going
     410              : 
     411            0 :          if (.not. b% ignore_rlof_flag) then
     412            0 :             if (implicit_rlo) then  ! check agreement between new r and new rl
     413            0 :                if (.not. b% use_other_check_implicit_rlo) then
     414            0 :                   binary_check_model = check_implicit_rlo(b% binary_id, new_mdot)
     415              :                else
     416            0 :                   binary_check_model = b% other_check_implicit_rlo(b% binary_id, new_mdot)
     417              :                end if
     418            0 :                if (binary_check_model == keep_going) then
     419            0 :                   b% donor_started_implicit_wind = .false.
     420              :                end if
     421              :                b% donor_started_implicit_wind = b% donor_started_implicit_wind .or. &
     422            0 :                   b% s_donor% was_in_implicit_wind_limit
     423              :             else
     424            0 :                if (.not. b% use_other_rlo_mdot) then
     425            0 :                   call rlo_mdot(b% binary_id, new_mdot, ierr)  ! grams per second
     426            0 :                   if (ierr /= 0) then
     427            0 :                      write(*,*) 'failed in rlo_mdot'
     428            0 :                      binary_check_model = retry
     429            0 :                      return
     430              :                   end if
     431              :                else
     432            0 :                   call b% other_rlo_mdot(b% binary_id, new_mdot, ierr)
     433            0 :                   if (ierr /= 0) then
     434            0 :                      write(*,*) 'failed in other rlo_mdot'
     435            0 :                      binary_check_model = retry
     436            0 :                      return
     437              :                   end if
     438              :                end if
     439            0 :                if (new_mdot > 0) then
     440            0 :                   new_mdot = 0.0d0
     441            0 :                   write(*,*) "WARNING: explicit computation of mass transfer results in accreting donor"
     442            0 :                   write(*,*) "Not transferring mass"
     443              :                end if
     444              :                ! smooth out the changes in mdot
     445            0 :                new_mdot = b% cur_mdot_frac*b% mtransfer_rate + (1-b% cur_mdot_frac)*new_mdot
     446            0 :                if (-new_mdot/(Msun/secyer) > b% max_explicit_abs_mdot) new_mdot = -b% max_explicit_abs_mdot*Msun/secyer
     447              :             end if
     448            0 :             b% mtransfer_rate = new_mdot
     449              :          else
     450            0 :             b% mtransfer_rate = 0d0
     451              :          end if
     452            0 :          call adjust_irradiation(b)
     453              : 
     454            0 :          if (.not. b% CE_flag) then
     455              :             if ((b% point_mass_i == 0 .or. b% model_twins_flag) &
     456            0 :                   .and. b% rl_relative_gap(b% a_i) >= 0.0d0) then
     457            0 :                if (b% rl_relative_gap(b% a_i) >= b% accretor_overflow_terminate) then
     458            0 :                   binary_check_model = terminate
     459            0 :                   b% s_donor% termination_code = t_xtra1
     460              :                   termination_code_str(t_xtra1) = &
     461            0 :                       "Terminate because accretor (r-rl)/rl > accretor_overflow_terminate"
     462              :                end if
     463              :             end if
     464              :             if (b% doing_first_model_of_run .and. b% terminate_if_initial_overflow &
     465            0 :                   .and. (.not. b% ignore_rlof_flag .or. b% model_twins_flag)) then
     466              :                if (b% rl_relative_gap(b% d_i) >= 0.0d0 &
     467            0 :                      .or. (b% point_mass_i == 0 .and. b% rl_relative_gap(b% a_i) >= 0.0d0)) then
     468            0 :                   binary_check_model = terminate
     469            0 :                   b% s_donor% termination_code = t_xtra1
     470              :                   termination_code_str(t_xtra1) = &
     471            0 :                       "Terminate because of overflowing initial model"
     472              :                end if
     473              :             end if
     474              :             if ((b% point_mass_i == 0 .or. b% model_twins_flag) &
     475            0 :                   .and. b% terminate_if_L2_overflow) then
     476            0 :                if (b% m(1) > b% m(2)) then
     477            0 :                   q = b% m(2) / b% m(1)
     478            0 :                   id = 2
     479              :                else
     480            0 :                   q = b% m(1) / b% m(2)
     481            0 :                   id = 1
     482              :                end if
     483            0 :                if (b% rl_relative_gap(id) > 0.29858997d0*atan(1.83530121d0*pow(q,0.39661426d0))) then
     484            0 :                   binary_check_model = terminate
     485            0 :                   b% s_donor% termination_code = t_xtra1
     486              :                   termination_code_str(t_xtra1) = &
     487            0 :                       "Terminate because of L2 overflow"
     488              :                end if
     489              :             end if
     490              : 
     491            0 :             if (b% mtransfer_rate == -b% max_implicit_abs_mdot*Msun/secyer .and. &
     492              :                b% CE_begin_at_max_implicit_abs_mdot) then
     493            0 :                b% CE_flag = .true.
     494            0 :                b% CE_init = .false.
     495            0 :                binary_check_model = keep_going
     496              :             end if
     497              :          end if
     498              : 
     499            0 :       end function binary_check_model
     500              : 
     501            0 :       integer function binary_finish_step(b)
     502              :          type (binary_info), pointer :: b
     503              : 
     504            0 :          binary_finish_step = keep_going
     505              :          ! update change factor in case mtransfer_rate has changed
     506            0 :          if(.not. b% doing_first_model_of_run) then
     507              :             if(b% mtransfer_rate_old /= b% mtransfer_rate .and. &
     508            0 :                b% mtransfer_rate /= 0 .and. b% mtransfer_rate_old /= 0) then
     509            0 :                if(b% mtransfer_rate < b% mtransfer_rate_old) then
     510              :                   b% change_factor = b% change_factor*(1d0-b% implicit_lambda) + b% implicit_lambda* &
     511            0 :                      (1+b% change_factor_fraction*(b% mtransfer_rate/b% mtransfer_rate_old-1))
     512              :                else
     513              :                   b% change_factor = b% change_factor*(1d0-b% implicit_lambda) + b% implicit_lambda* &
     514            0 :                      (1+b% change_factor_fraction*(b% mtransfer_rate_old/b% mtransfer_rate-1))
     515              :                end if
     516            0 :                if(b% change_factor > b% max_change_factor) b% change_factor = b% max_change_factor
     517            0 :                if(b% change_factor < b% min_change_factor) b% change_factor = b% min_change_factor
     518              :             end if
     519              :          end if
     520              : 
     521              :          ! store all variables into "old"
     522              : 
     523            0 :          b% model_number_old = b% model_number
     524            0 :          b% binary_age_old = b% binary_age
     525            0 :          b% mtransfer_rate_old = b% mtransfer_rate
     526            0 :          b% angular_momentum_j_old = b% angular_momentum_j
     527            0 :          b% separation_old = b% separation
     528            0 :          b% eccentricity_old = b% eccentricity
     529            0 :          b% dt_old = b% dt
     530            0 :          b% env_old(1) = b% env(1)
     531            0 :          b% env_old(2) = b% env(2)
     532            0 :          b% period_old = b% period
     533            0 :          b% rl_relative_gap_old(1) = b% rl_relative_gap(1)
     534            0 :          b% rl_relative_gap_old(2) = b% rl_relative_gap(2)
     535            0 :          b% r_old(1) = b% r(1)
     536            0 :          b% r_old(2) = b% r(2)
     537            0 :          b% rl_old(1) = b% rl(1)
     538            0 :          b% rl_old(2) = b% rl(2)
     539            0 :          b% m_old(1) = b% m(1)
     540            0 :          b% m_old(2) = b% m(2)
     541            0 :          b% using_jdot_mb_old = b% using_jdot_mb
     542            0 :          b% max_timestep_old = b% max_timestep
     543            0 :          b% change_factor_old = b% change_factor
     544              : 
     545            0 :          b% d_i_old = b% d_i
     546            0 :          b% a_i_old = b% a_i
     547            0 :          b% point_mass_i_old = b% point_mass_i
     548              : 
     549            0 :          b% ignore_rlof_flag_old = b% ignore_rlof_flag
     550            0 :          b% model_twins_flag_old = b% model_twins_flag
     551              : 
     552            0 :          b% CE_flag_old = b% CE_flag
     553            0 :          b% CE_init_old = b% CE_init
     554              : 
     555            0 :          b% CE_num1_old = b% CE_num1
     556            0 :          b% CE_num2_old = b% CE_num2
     557            0 :          b% CE_lambda1_old = b% CE_lambda1
     558            0 :          b% CE_lambda2_old = b% CE_lambda2
     559            0 :          b% CE_Ebind1_old = b% CE_Ebind1
     560            0 :          b% CE_Ebind2_old = b% CE_Ebind2
     561            0 :          b% CE_years_detached_old = b% CE_years_detached
     562              : 
     563            0 :          b% dt_why_reason_old = b% dt_why_reason
     564              : 
     565              :          !set all xtra variables
     566            0 :          b% ixtra_old(:) = b% ixtra(:)
     567            0 :          b% xtra_old(:) = b% xtra(:)
     568            0 :          b% lxtra_old(:) = b% lxtra(:)
     569              : 
     570            0 :       end function binary_finish_step
     571              : 
     572            0 :       integer function binary_prepare_to_redo(b)
     573              :          type (binary_info), pointer :: b
     574              : 
     575            0 :          binary_prepare_to_redo = redo
     576            0 :          call binary_set_current_to_old(b)
     577              : 
     578            0 :       end function binary_prepare_to_redo
     579              : 
     580            0 :       integer function binary_prepare_to_retry(b)
     581              :          type (binary_info), pointer :: b
     582              : 
     583            0 :          b% num_tries = 0
     584              :          ! this call takes care of restoring variables
     585            0 :          call binary_set_current_to_old(b)
     586            0 :          binary_prepare_to_retry = retry
     587              : 
     588            0 :       end function binary_prepare_to_retry
     589              : 
     590            0 :       subroutine binary_set_current_to_old(b)
     591              :          type (binary_info), pointer :: b
     592              :          ! restore variables
     593            0 :          b% model_number = b% model_number_old
     594            0 :          b% binary_age = b% binary_age_old
     595              :          ! do not restore mtransfer_rate during implicit rlo
     596            0 :          if (b% num_tries == 0) b% mtransfer_rate = b% mtransfer_rate_old
     597            0 :          b% angular_momentum_j = b% angular_momentum_j_old
     598            0 :          b% separation = b% separation_old
     599            0 :          b% eccentricity = b% eccentricity_old
     600            0 :          b% dt = b% dt_old
     601            0 :          b% env(1) = b% env_old(1)
     602            0 :          b% env(2) = b% env_old(2)
     603            0 :          b% period = b% period_old
     604            0 :          b% rl_relative_gap(1) = b% rl_relative_gap_old(1)
     605            0 :          b% rl_relative_gap(2) = b% rl_relative_gap_old(2)
     606            0 :          b% r(1) = b% r_old(1)
     607            0 :          b% r(2) = b% r_old(2)
     608            0 :          b% rl(1) = b% rl_old(1)
     609            0 :          b% rl(2) = b% rl_old(2)
     610            0 :          b% m(1) = b% m_old(1)
     611            0 :          b% m(2) = b% m_old(2)
     612            0 :          b% using_jdot_mb = b% using_jdot_mb_old
     613            0 :          b% max_timestep = b% max_timestep_old
     614              : 
     615              :          ! the following need to be kept constant during implicit mdot
     616            0 :          if (b% num_tries == 0) then
     617            0 :             b% change_factor = b% change_factor_old
     618            0 :             b% d_i = b% d_i_old
     619            0 :             b% a_i = b% a_i_old
     620            0 :             b% point_mass_i = b% point_mass_i_old
     621            0 :             b% ignore_rlof_flag = b% ignore_rlof_flag_old
     622            0 :             b% model_twins_flag = b% model_twins_flag_old
     623            0 :             b% CE_flag = b% CE_flag_old
     624            0 :             b% CE_init = b% CE_init_old
     625              :          end if
     626              : 
     627            0 :          b% CE_num1 = b% CE_num1_old
     628            0 :          b% CE_num2 = b% CE_num2_old
     629            0 :          b% CE_lambda1 = b% CE_lambda1_old
     630            0 :          b% CE_lambda2 = b% CE_lambda2_old
     631            0 :          b% CE_Ebind1 = b% CE_Ebind1_old
     632            0 :          b% CE_Ebind2 = b% CE_Ebind2_old
     633            0 :          b% CE_years_detached = b% CE_years_detached_old
     634              : 
     635            0 :          b% dt_why_reason = b% dt_why_reason_old
     636              : 
     637              :          !set all xtra variables
     638            0 :          b% ixtra(:) = b% ixtra_old(:)
     639            0 :          b% xtra(:) = b% xtra_old(:)
     640            0 :          b% lxtra(:) = b% lxtra_old(:)
     641            0 :       end subroutine binary_set_current_to_old
     642              : 
     643            0 :       integer function binary_after_evolve(b)
     644              :          type (binary_info), pointer :: b
     645            0 :          binary_after_evolve = keep_going
     646              : 
     647              :          !take care of deallocating binary arrays here
     648            0 :          if (associated(b% theta_co)) then
     649            0 :             deallocate(b% theta_co)
     650            0 :             nullify(b% theta_co)
     651              :          end if
     652            0 :          if (associated(b% time_co)) then
     653            0 :             deallocate(b% time_co)
     654            0 :             nullify(b% time_co)
     655              :          end if
     656            0 :          if (associated(b% mdot_donor_theta)) then
     657            0 :             deallocate(b% mdot_donor_theta)
     658            0 :             nullify(b% mdot_donor_theta)
     659              :          end if
     660            0 :          if (associated(b% edot_theta)) then
     661            0 :             deallocate(b% edot_theta)
     662            0 :             nullify(b% edot_theta)
     663              :          end if
     664            0 :          if (associated(b% e1)) then
     665            0 :             deallocate(b% e1)
     666            0 :             nullify(b% e1)
     667              :          end if
     668            0 :          if (associated(b% e2)) then
     669            0 :             deallocate(b% e2)
     670            0 :             nullify(b% e2)
     671              :          end if
     672            0 :          if (associated(b% CE_m)) then
     673            0 :             deallocate(b% CE_m)
     674            0 :             nullify(b% CE_m)
     675              :          end if
     676            0 :          if (associated(b% CE_entropy)) then
     677            0 :             deallocate(b% CE_entropy)
     678            0 :             nullify(b% CE_entropy)
     679              :          end if
     680            0 :          if (associated(b% CE_U_in)) then
     681            0 :             deallocate(b% CE_U_in)
     682            0 :             nullify(b% CE_U_in)
     683              :          end if
     684            0 :          if (associated(b% CE_U_out)) then
     685            0 :             deallocate(b% CE_U_out)
     686            0 :             nullify(b% CE_U_out)
     687              :          end if
     688            0 :          if (associated(b% CE_Omega_in)) then
     689            0 :             deallocate(b% CE_Omega_in)
     690            0 :             nullify(b% CE_Omega_in)
     691              :          end if
     692            0 :          if (associated(b% CE_Omega_out)) then
     693            0 :             deallocate(b% CE_Omega_out)
     694            0 :             nullify(b% CE_Omega_out)
     695              :          end if
     696            0 :       end function binary_after_evolve
     697              : 
     698              :       end module binary_evolve
        

Generated by: LCOV version 2.0-1