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

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2013-2022  Pablo Marchant, Matthias Fabry & The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              : module run_binary_support
      21              : 
      22              :    use star_lib
      23              :    use star_def
      24              :    use const_def, only: dp, i8, secday
      25              :    use utils_lib
      26              :    use binary_def
      27              :    use binary_private_def
      28              :    use binary_ctrls_io, only : do_one_binary_setup
      29              :    use binary_do_one_utils
      30              :    use binary_ce
      31              :    use binary_photos
      32              : 
      33              :    implicit none
      34              : 
      35              : contains
      36              : 
      37            0 :    subroutine do_run1_binary(tst, &
      38              :       ! star extras
      39              :       extras_controls, &
      40              :       ! binary extras
      41              :       extras_binary_controls, &
      42              :       ierr, &
      43              :       inlist_fname_arg)
      44              : 
      45              :       use binary_job_ctrls_io
      46              :       use binary_mdot, only : adjust_mdots, set_accretion_composition
      47              :       use binary_tides, only : sync_spin_orbit_torque
      48              :       use binary_evolve
      49              :       use mod_other_rlo_mdot
      50              :       use mod_other_implicit_rlo
      51              :       use mod_other_tsync
      52              :       use mod_other_sync_spin_to_orbit
      53              :       use mod_other_mdot_edd
      54              :       use mod_other_adjust_mdots
      55              :       use mod_other_accreted_material_j
      56              :       use mod_other_binary_jdot
      57              :       use mod_other_binary_wind_transfer
      58              :       use mod_other_binary_edot
      59              :       use mod_other_binary_ce
      60              :       use mod_other_binary_extras
      61              :       use mod_other_binary_photos
      62              :       use mod_other_e2
      63              :       use mod_other_pgbinary_plots
      64              :       use binary_timestep
      65              :       use binary_history
      66              :       use binary_history_specs
      67              :       use run_star_support
      68              :       use pgbinary, only : read_pgbinary_inlist, update_pgbinary_plots, &
      69              :          start_new_run_for_pgbinary, restart_run_for_pgbinary
      70              : 
      71              :       logical, intent(in) :: tst
      72              : 
      73              :       interface
      74              : 
      75              :          subroutine extras_controls(id, ierr)
      76              :             implicit none
      77              :             integer, intent(in) :: id
      78              :             integer, intent(out) :: ierr
      79              :          end subroutine extras_controls
      80              : 
      81              :          subroutine extras_binary_controls(binary_id, ierr)
      82              :             implicit none
      83              :             integer :: binary_id
      84              :             integer, intent(out) :: ierr
      85              :          end subroutine extras_binary_controls
      86              : 
      87              :       end interface
      88              : 
      89              :       integer, intent(out) :: ierr
      90              :       character (len = *) :: inlist_fname_arg
      91              :       optional inlist_fname_arg
      92              : 
      93              :       integer :: id, binary_id, i, j, k, l, i_prev, result, partial_result, &
      94              :          result_reason, model_number, iounit, binary_startup, model, num_stars
      95              :       type (star_info), pointer :: s
      96              :       character (len = 256) :: restart_filename, photo_filename
      97              :       integer(i8) :: time0, clock_rate
      98              :       logical :: doing_restart, first_try, continue_evolve_loop, &
      99              :           get_history_info, write_history, write_terminal, will_read_pgbinary_inlist
     100              :       type (binary_info), pointer :: b
     101              :       character (len = strlen) :: inlist_fname
     102              : 
     103              :       include 'formats'
     104              : 
     105            0 :       ierr = 0
     106            0 :       call system_clock(time0, clock_rate)
     107              : 
     108            0 :       call resolve_inlist_fname(inlist_fname, inlist_fname_arg)
     109            0 :       MESA_INLIST_RESOLVED = .true.  ! Now any call to resolve_inlist_fname will only return inlist_fname_arg or 'inlist'
     110              : 
     111              :       ! Find out if this is a restart
     112            0 :       open(newunit = iounit, file = '.restart', status = 'old', action = 'read', iostat = ierr)
     113            0 :       doing_restart = (ierr == 0)
     114            0 :       if (doing_restart) then
     115              :          ! photo_filename will be like 'x100'
     116              :          ! the photo for star 1 is '1_x100', for star 2 '2_x100' and for binary 'b_x100'
     117            0 :          read(iounit, '(a)', iostat = ierr) photo_filename
     118            0 :          if (ierr /= 0) then
     119            0 :             stop "Problem while reading restart info"
     120              :          end if
     121              :       else
     122              :          ierr = 0
     123              :       end if
     124              : 
     125            0 :       binary_id = alloc_binary(ierr)
     126            0 :       if (ierr /= 0) then
     127            0 :          write(*, *) 'failed in alloc_binary'
     128            0 :          return
     129              :       end if
     130              : 
     131            0 :       call binary_ptr(binary_id, b, ierr)
     132            0 :       if (ierr /= 0) then
     133            0 :          write(*, *) 'failed in binary_ptr'
     134            0 :          return
     135              :       end if
     136              : 
     137            0 :       if (.not. doing_restart) then
     138            0 :          b% model_number = 0
     139            0 :          b% model_number_old = 0
     140            0 :          b% binary_age = 0
     141            0 :          b% binary_age_old = 0
     142              :       end if
     143              : 
     144            0 :       call do_read_binary_job(b, inlist_fname, ierr)
     145            0 :       if (ierr /= 0) then
     146            0 :          write(*, *) 'failed in read_binary_job'
     147            0 :          return
     148              :       end if
     149              : 
     150            0 :       if (.not. b% job% evolve_both_stars .or. &
     151              :          ((b% job% change_initial_model_twins_flag .or. b% job% change_model_twins_flag) &
     152              :             .and. b% job% new_model_twins_flag)) then
     153            0 :          b% have_star_1 = .true.
     154            0 :          b% have_star_2 = .false.
     155              :       else
     156            0 :          b% have_star_1 = .true.
     157            0 :          b% have_star_2 = .true.
     158              :       end if
     159              : 
     160            0 :       write(*, '(A)')
     161            0 :       write(*, '(A)')
     162              : 
     163            0 :       result_reason = 0
     164              : 
     165              :       ! Setup null hooks
     166            0 :       b% other_rlo_mdot => null_other_rlo_mdot
     167            0 :       b% other_implicit_function_to_solve => null_other_implicit_function_to_solve
     168            0 :       b% other_check_implicit_rlo => null_other_check_implicit_rlo
     169            0 :       b% other_tsync => null_other_tsync
     170            0 :       b% other_sync_spin_to_orbit => null_other_sync_spin_to_orbit
     171            0 :       b% other_mdot_edd => null_other_mdot_edd
     172            0 :       b% other_adjust_mdots => null_other_adjust_mdots
     173            0 :       b% other_accreted_material_j => null_other_accreted_material_j
     174            0 :       b% other_jdot_gr => null_other_jdot_gr
     175            0 :       b% other_jdot_ml => null_other_jdot_ml
     176            0 :       b% other_jdot_ls => null_other_jdot_ls
     177            0 :       b% other_jdot_missing_wind => null_other_jdot_missing_wind
     178            0 :       b% other_jdot_mb => null_other_jdot_mb
     179            0 :       b% other_extra_jdot => null_other_extra_jdot
     180            0 :       b% other_binary_wind_transfer => null_other_binary_wind_transfer
     181            0 :       b% other_edot_tidal => null_other_edot_tidal
     182            0 :       b% other_edot_enhance => null_other_edot_enhance
     183            0 :       b% other_extra_edot => null_other_extra_edot
     184            0 :       b% other_CE_init => null_other_CE_init
     185            0 :       b% other_CE_rlo_mdot => null_other_CE_rlo_mdot
     186            0 :       b% other_CE_binary_evolve_step => null_other_CE_binary_evolve_step
     187            0 :       b% other_CE_binary_finish_step => null_other_CE_binary_finish_step
     188            0 :       b% other_e2 => null_other_e2
     189            0 :       b% other_pgbinary_plots_info => null_other_pgbinary_plots_info
     190              : 
     191            0 :       b% extras_binary_startup => null_extras_binary_startup
     192            0 :       b% extras_binary_start_step => null_extras_binary_start_step
     193            0 :       b% extras_binary_check_model => null_extras_binary_check_model
     194            0 :       b% extras_binary_finish_step => null_extras_binary_finish_step
     195            0 :       b% extras_binary_after_evolve => null_extras_binary_after_evolve
     196            0 :       b% how_many_extra_binary_history_columns => null_how_many_extra_binary_history_columns
     197            0 :       b% data_for_extra_binary_history_columns => null_data_for_extra_binary_history_columns
     198            0 :       b% how_many_extra_binary_history_header_items => null_how_many_extra_binary_history_header_items
     199            0 :       b% data_for_extra_binary_history_header_items => null_data_for_extra_binary_history_header_items
     200              : 
     201            0 :       b% other_binary_photo_read => default_other_binary_photo_read
     202            0 :       b% other_binary_photo_write => default_other_binary_photo_write
     203              : 
     204            0 :       b% ignore_hard_limits_this_step = .false.
     205              : 
     206            0 :       call do_one_binary_setup(b, inlist_fname, ierr)
     207              :       ! extras_binary_controls is defined in run_binary_extras.f and hooks can
     208              :       ! be specified there
     209            0 :       call extras_binary_controls(b% binary_id, ierr)
     210              : 
     211              :       ! load binary photo if this is a restart
     212            0 :       if (doing_restart) then
     213            0 :          restart_filename = trim(trim(b% photo_directory) // '/b_' // photo_filename)
     214            0 :          call binary_load_photo(b, restart_filename, ierr)
     215            0 :          if (failed('binary_load_photo', ierr)) return
     216              :       end if
     217              : 
     218            0 :       b% donor_id = -1
     219            0 :       b% accretor_id = -1
     220            0 :       do i = 1, 2
     221              : 
     222            0 :          if (i==1 .and. .not. b% have_star_1) then
     223              :             cycle
     224            0 :          else if (i==2 .and. .not. b% have_star_2) then
     225              :             cycle
     226              :          end if
     227              : 
     228            0 :          call do_read_star_job(b% job% inlist_names(i), ierr)
     229            0 :          if (failed('do_read_star_job', ierr)) return
     230              : 
     231            0 :          if (i==1) then
     232            0 :             restart_filename = trim('1_' // photo_filename)
     233              :          else
     234            0 :             restart_filename = trim('2_' // photo_filename)
     235              :          end if
     236              : 
     237              :          ! the star is initialized in this call
     238              :          call before_evolve_loop(.true., doing_restart, doing_restart, &
     239              :             binary_controls, extras_controls, &
     240              :             id_from_read_star_job, b% job% inlist_names(i), restart_filename, &
     241            0 :             .false., binary_id, id, ierr)
     242              : 
     243            0 :          if (ierr /= 0) return
     244              : 
     245            0 :          call star_ptr(id, s, ierr)
     246            0 :          if (failed('star_ptr', ierr)) return
     247            0 :          b% star_ids(i) = id
     248              : 
     249            0 :          s% include_binary_history_in_log_file = b% append_to_star_history
     250              : 
     251            0 :          s% how_many_binary_history_columns => how_many_binary_history_columns
     252            0 :          s% data_for_binary_history_columns => data_for_binary_history_columns
     253              : 
     254            0 :          s% how_many_extra_binary_history_columns => b% how_many_extra_binary_history_columns
     255            0 :          s% data_for_extra_binary_history_columns => b% data_for_extra_binary_history_columns
     256              : 
     257              :          ! additional settings for mass transfer and tides
     258            0 :          if (b% do_j_accretion) then
     259            0 :             s% use_accreted_material_j = .true.
     260              :          end if
     261            0 :          s% accrete_given_mass_fractions = .true.
     262            0 :          s% accrete_same_as_surface = .false.
     263            0 :          s% binary_other_torque => sync_spin_orbit_torque
     264              : 
     265            0 :          s% doing_timing = .false.
     266              : 
     267            0 :          write(*, '(A)')
     268            0 :          write(*, '(A)')
     269              : 
     270              :       end do
     271              : 
     272              :       ! Error if users set the saved model to the same filename
     273            0 :       if(b% have_star_1 .and. b% have_star_2) then
     274            0 :          if(b% s1% job% save_model_when_terminate .and. b% s2% job% save_model_when_terminate) then
     275            0 :             if(len_trim(b% s1% job% save_model_filename) > 0 .and. len_trim(b% s2% job% save_model_filename) >0) then
     276            0 :                if(trim(b% s1% job% save_model_filename) == trim(b% s2% job% save_model_filename)) then
     277            0 :                   write(*, *) "ERROR: Both stars are set to write save_model_filename to the same file"
     278            0 :                   call mesa_error(__FILE__, __LINE__)
     279              :                end if
     280              :             end if
     281              :          end if
     282              :       end if
     283              : 
     284              : 
     285              :       ! binary data must be initiated after stars, such that masses are available
     286              :       ! if using saved models
     287            0 :       call binarydata_init(b, doing_restart)
     288            0 :       call binary_private_def_init
     289            0 :       call binary_history_column_names_init(ierr)
     290            0 :       call set_binary_history_columns(b, b% job% binary_history_columns_file, .true., ierr)
     291              : 
     292              :       ! setup pgbinary
     293            0 :       if (.not. doing_restart) then
     294            0 :          call start_new_run_for_pgbinary(b, ierr)
     295            0 :          if (failed('start_new_run_for_pgbinary', ierr)) return
     296              :       else
     297            0 :          call restart_run_for_pgbinary(b, ierr)
     298            0 :          if (failed('restart_run_for_pgbinary', ierr)) return
     299              :       end if
     300              : 
     301            0 :       if (b% job% show_binary_log_description_at_start .and. .not. doing_restart) then
     302            0 :          write(*, '(A)')
     303            0 :          call do_show_binary_log_description(id, ierr)
     304            0 :          if (failed('show_log_description', ierr)) return
     305              :       end if
     306              : 
     307            0 :       if (b% point_mass_i /= 1 .and. b% do_initial_orbit_sync_1 .and. &
     308              :          .not. doing_restart) then
     309              :          call star_relax_uniform_omega(&
     310              :             b% s1% id, 0, (2 * pi) / b% period, b% s1% job% num_steps_to_relax_rotation, &
     311            0 :             b% s1% job% relax_omega_max_yrs_dt, ierr)
     312            0 :          if (ierr /= 0) then
     313            0 :             write(*, *) 'failed in initial orbital sync'
     314            0 :             return
     315              :          end if
     316              :       end if
     317              : 
     318            0 :       if (b% point_mass_i /= 2 .and. b% do_initial_orbit_sync_2 .and. &
     319              :          .not. doing_restart) then
     320              :          call star_relax_uniform_omega(&
     321              :             b% s2% id, 0, (2 * pi) / b% period, b% s2% job% num_steps_to_relax_rotation, &
     322            0 :             b% s2% job% relax_omega_max_yrs_dt, ierr)
     323            0 :          if (ierr /= 0) then
     324            0 :             write(*, *) 'failed in initial orbital sync'
     325            0 :             return
     326              :          end if
     327              :       end if
     328              : 
     329            0 :       continue_evolve_loop = .true.
     330            0 :       s% doing_timing = .false.
     331            0 :       i_prev = 0
     332              : 
     333            0 :       binary_startup = b% extras_binary_startup(b% binary_id, doing_restart, ierr)
     334            0 :       if (ierr /= 0) return
     335              : 
     336              :       ! perform changes specified by binary_job variables
     337            0 :       call do_binary_job_controls_after(b% binary_id, b, doing_restart, ierr)
     338            0 :       if (ierr /= 0) return
     339              : 
     340              :       ! setup things for common envelope in case of a restart
     341            0 :       if (doing_restart .and. b% CE_flag .and. b% CE_init) then
     342            0 :          call ce_init(b, doing_restart, ierr)
     343              :       end if
     344              : 
     345            0 :       evolve_loop : do while(continue_evolve_loop)  ! evolve one step per loop
     346              : 
     347            0 :          if (b% point_mass_i /= 0) then
     348              :             num_stars = 1
     349              :          else
     350            0 :             num_stars = 2
     351              :          end if
     352              : 
     353            0 :          do l = 1, num_stars
     354            0 :             if (l == 1 .and. b% point_mass_i == 1) then
     355              :                i = 2
     356              :             else
     357            0 :                i = l
     358              :             end if
     359              : 
     360            0 :             id = b% star_ids(i)
     361            0 :             call star_ptr(id, s, ierr)
     362            0 :             if (failed('star_ptr', ierr)) return
     363            0 :             call before_step_loop(id, ierr)
     364            0 :             if (ierr /= 0) return
     365              : 
     366            0 :             result = s% extras_start_step(id)
     367            0 :             if (result /= keep_going) then
     368            0 :                continue_evolve_loop = .false.
     369              :                exit evolve_loop
     370              :             end if
     371              :          end do
     372              : 
     373            0 :          first_try = .true.
     374            0 :          b% donor_started_implicit_wind = .false.
     375            0 :          b% num_tries = 0
     376              : 
     377            0 :          if (b% CE_flag .and. .not. b% CE_init) then
     378            0 :             call ce_init(b, .false., ierr)
     379            0 :             write(*, *) "CE flag is on!!"
     380              :          end if
     381              : 
     382            0 :          step_loop : do  ! may need to repeat this loop
     383              : 
     384            0 :             result = b% extras_binary_start_step(b% binary_id, ierr)
     385            0 :             if (ierr /= 0) then
     386            0 :                write(*, *) "error in extras_binary_start_step"
     387            0 :                return
     388              :             end if
     389            0 :             if (result /= keep_going) exit evolve_loop
     390              :             !update num_stars in case point_mass_i has changed
     391            0 :             if (b% point_mass_i /= 0) then
     392              :                num_stars = 1
     393              :             else
     394            0 :                num_stars = 2
     395              :             end if
     396              : 
     397            0 :             call set_donor_star(b)
     398            0 :             call set_star_timesteps(b)
     399            0 :             result = keep_going
     400              : 
     401              :             ! Store mtransfer_rate used in a step, as it is rewritten by binary_check_model and
     402              :             ! that can produce inconsistent output.
     403            0 :             b% step_mtransfer_rate = b% mtransfer_rate
     404              : 
     405            0 :             if (.not. b% CE_flag) then
     406              :                ! if donor reaches implicit wind limit during mass transfer, set was_in_implicit_wind_limit = .true.
     407              :                ! so that further iterations of the implicit wind do not start far off from the required mdot.
     408              :                ! system will likely detach suddenly, so set change_factor to double its maximum
     409            0 :                if (b% donor_started_implicit_wind) then
     410            0 :                   b% s_donor% was_in_implicit_wind_limit = .true.
     411            0 :                   b% change_factor = 2 * b% max_change_factor
     412              :                end if
     413              :             end if
     414              : 
     415            0 :             do l = 1, num_stars
     416              : 
     417            0 :                if (b% point_mass_i /= 0) then  ! if any point mass, evolve the other one
     418            0 :                   j = 3 - b% point_mass_i
     419              :                else  ! both stars
     420            0 :                   if (l == 1) then
     421            0 :                      j = b% d_i  ! evolve the donor first
     422              :                   else
     423            0 :                      j = b% a_i
     424              :                   end if
     425              :                end if
     426              : 
     427            0 :                id = b% star_ids(j)
     428              : 
     429              :                ! Avoid repeating the accretor when using the implicit scheme plus
     430              :                ! rotation and implicit winds. When this happens the accretor won't
     431              :                ! usually care about the result of the evolution of the donor.
     432            0 :                if (j == b% a_i .and. b% num_tries >0 .and. s% was_in_implicit_wind_limit) &
     433              :                   cycle
     434              : 
     435              :                ! fix sync timescales to zero. If synching stars these will be
     436              :                ! updated at each star_evolve_step
     437            0 :                if (j == 1) then
     438            0 :                   b% t_sync_1 = 0
     439            0 :                else if (j == 2) then
     440            0 :                   b% t_sync_2 = 0
     441              :                end if
     442              : 
     443              :                result = worst_result(result, &
     444            0 :                   star_evolve_step_part1(id, first_try))
     445              : 
     446              :             end do
     447              : 
     448              :             ! modify mdots to account for mass transfer
     449            0 :             call adjust_mdots(b)
     450              :             ! if both stars are accreting mass at this point, then there is
     451              :             ! something very wrong! If one star loses and the other gains mass,
     452              :             ! then the mass losing star must be evolved first
     453            0 :             k = b% d_i
     454            0 :             if (b% point_mass_i == 0 .and. b% s_donor% mstar_dot > 0) then
     455            0 :                if (b% s_accretor% mstar_dot > 0) then
     456            0 :                   write(*, *) "ERROR: both stars accreting, terminating evolution"
     457            0 :                   result = terminate
     458            0 :                   exit step_loop
     459              :                end if
     460            0 :                k = b% a_i  ! donor is gaining while accretor is losing, accretor plays donor in this step
     461            0 :             else if (b% point_mass_i /= 0 .and. b% s_donor% mstar_dot > 0) then
     462            0 :                write(*, *) "ERROR: donor accreting, terminating evolution"
     463            0 :                result = terminate
     464            0 :                exit step_loop
     465              :             end if
     466              : 
     467            0 :             if (result == keep_going) then
     468            0 :                do l = 1, num_stars
     469              :                   ! if there's any point mass, evolve the non-point mass, num_stars should be 1 here
     470              :                   ! so no risk of evolving things twice
     471            0 :                   if (b% point_mass_i /= 0) then
     472            0 :                      k = 3 - b% point_mass_i
     473              :                   else  ! two stars present
     474            0 :                      if (l == 1) then  ! evolve donor in first loop pass
     475            0 :                         j = k
     476              :                      else  ! evolve acc in second loop pass
     477            0 :                         j = 3 - k
     478              :                      end if
     479              :                   end if
     480            0 :                   id = b% star_ids(j)
     481              : 
     482            0 :                   if (j == b% a_i .and. b% num_tries >0 .and. s% was_in_implicit_wind_limit) &
     483              :                      cycle
     484              : 
     485              :                   ! set accretion composition
     486            0 :                   if (.not. b% CE_flag) then
     487            0 :                      if (i == 2) call set_accretion_composition(b, j)
     488              :                   end if
     489              : 
     490              :                   result = worst_result(result, &
     491            0 :                      star_evolve_step_part2(id, first_try))
     492              : 
     493              :                end do
     494              :             end if
     495              : 
     496              :             ! do not evolve binary step on failure, its unnecessary and some variables are not properly
     497              :             ! set when the newton solver fails.
     498            0 :             if (result == keep_going) then
     499            0 :                if (.not. b% CE_flag) then
     500            0 :                   result = worst_result(result, binary_evolve_step(b))
     501              :                else
     502            0 :                   result = worst_result(result, CE_binary_evolve_step(b))
     503              :                end if
     504              :             end if
     505              : 
     506            0 :             if (result == keep_going) then
     507            0 :                result = worst_result(result, binary_check_model(b))
     508              :             end if
     509              : 
     510            0 :             do l = 1, num_stars
     511            0 :                if (l == 1 .and. b% point_mass_i == 1) then
     512              :                   i = 2
     513              :                else
     514              :                   i = l
     515              :                end if
     516              :                if (i == 1 .and. b% point_mass_i == 1) i = 2
     517            0 :                if (result == keep_going) then
     518            0 :                   id = b% star_ids(i)
     519            0 :                   call star_ptr(id, s, ierr)
     520            0 :                   result = worst_result(result, s% extras_check_model(id))
     521            0 :                   result = worst_result(result, star_check_model(id))
     522              :                end if
     523              :             end do
     524              : 
     525            0 :             partial_result = b% extras_binary_check_model(b% binary_id)
     526            0 :             result = worst_result(result, partial_result)
     527              : 
     528              :             ! solve first binary timestep limit because star_pick_next_timestep needs it
     529              :             ! check redos as well to stop the implicit solver if a hard limit is hit
     530            0 :             if (result == keep_going .or. result == redo) then
     531            0 :                result = worst_result(result, binary_pick_next_timestep(b))
     532              :             end if
     533              : 
     534            0 :             if (result == keep_going) then
     535            0 :                do l = 1, num_stars
     536            0 :                   if (l == 1 .and. b% point_mass_i == 1) then
     537              :                      i = 2
     538              :                   else
     539            0 :                      i = l
     540              :                   end if
     541            0 :                   id = b% star_ids(i)
     542            0 :                   call star_ptr(id, s, ierr)
     543            0 :                   if (failed('star_ptr', ierr)) return
     544            0 :                   result = worst_result(result, star_pick_next_timestep(id))
     545              :                end do
     546              :             end if
     547            0 :             if (result == keep_going) then
     548              :                exit step_loop
     549              :             end if
     550              : 
     551            0 :             do l = 1, num_stars
     552            0 :                if (l == 1 .and. b% point_mass_i == 1) then
     553              :                   i = 2
     554              :                else
     555            0 :                   i = l
     556              :                end if
     557              : 
     558            0 :                id = b% star_ids(i)
     559            0 :                model_number = get_model_number(id, ierr)
     560            0 :                if (failed('get_model_number', ierr)) return
     561              : 
     562            0 :                result_reason = get_result_reason(id, ierr)
     563            0 :                if (result == retry) then
     564            0 :                   if (failed('get_result_reason', ierr)) return
     565            0 :                   if (s% job% report_retries) &
     566            0 :                      write(*, '(i6,3x,a,/)') model_number, &
     567            0 :                         'retry reason ' // trim(result_reason_str(result_reason))
     568              :                end if
     569              : 
     570              :             end do
     571              : 
     572            0 :             b% generations = b% s_donor% generations
     573            0 :             if (result == redo) then
     574            0 :                do l = 1, num_stars
     575            0 :                   if (l == 1 .and. b% point_mass_i == 1) then
     576              :                      i = 2
     577              :                   else
     578            0 :                      i = l
     579              :                   end if
     580            0 :                   id = b% star_ids(i)
     581              : 
     582              :                   ! Avoid repeating the accretor when using the implicit scheme plus
     583              :                   ! rotation and implicit winds. When this happens the accretor won't
     584              :                   ! usually care about the result of the evolution of the donor.
     585              : 
     586            0 :                   if (i == b% a_i .and. b% num_tries >0 .and. s% was_in_implicit_wind_limit) &
     587              :                      cycle
     588            0 :                   result = worst_result(result, star_prepare_to_redo(id))
     589              :                end do
     590            0 :                result = worst_result(result, binary_prepare_to_redo(b))
     591              :             end if
     592            0 :             if (result == retry) then
     593            0 :                do l = 1, num_stars
     594            0 :                   if (l == 1 .and. b% point_mass_i == 1) then
     595              :                      i = 2
     596              :                   else
     597            0 :                      i = l
     598              :                   end if
     599            0 :                   id = b% star_ids(i)
     600            0 :                   result = worst_result(result, star_prepare_to_retry(id))
     601              :                end do
     602            0 :                result = worst_result(result, binary_prepare_to_retry(b))
     603              :             end if
     604              : 
     605              :             !correct pointers to stars after retry
     606            0 :             if (b% d_i == 1) then
     607            0 :                if (b% have_star_1) then
     608            0 :                   b% s_donor => b% s1
     609            0 :                   if (b% point_mass_i == 0) then
     610            0 :                      if (b% have_star_2) then
     611            0 :                         b% s_accretor => b% s2
     612              :                      else
     613            0 :                         call mesa_error(__FILE__, __LINE__, 'ERROR: missing star pointer for accretor')
     614              :                      end if
     615              :                   end if
     616              :                else
     617            0 :                   call mesa_error(__FILE__, __LINE__, 'ERROR: missing star pointer for donor')
     618              :                end if
     619              :             else
     620            0 :                if (b% have_star_2) then
     621            0 :                   b% s_donor => b% s2
     622            0 :                   if (b% point_mass_i == 0) then
     623            0 :                      if (b% have_star_1) then
     624            0 :                         b% s_accretor => b% s1
     625              :                      else
     626            0 :                         call mesa_error(__FILE__, __LINE__, 'ERROR: missing star pointer for accretor')
     627              :                      end if
     628              :                   end if
     629              :                else
     630            0 :                   call mesa_error(__FILE__, __LINE__, 'ERROR: missing star pointer for donor')
     631              :                end if
     632              :             end if
     633              : 
     634            0 :             if (result == terminate) then
     635              :                continue_evolve_loop = .false.
     636              :                exit step_loop
     637              :             end if
     638            0 :             first_try = .false.
     639              : 
     640              :          end do step_loop
     641              : 
     642            0 :          partial_result = b% extras_binary_finish_step(b% binary_id)
     643            0 :          result = worst_result(result, partial_result)
     644              : 
     645            0 :          if(result == keep_going) result = binary_finish_step(b)
     646            0 :          if (b% CE_flag .and. b% CE_init .and. result == keep_going) then
     647            0 :             result = worst_result(result, CE_binary_finish_step(b))
     648              :          end if
     649              : 
     650            0 :          if (result == keep_going) then
     651              :             ! write terminal info
     652            0 :             model = b% model_number
     653            0 :             if (b% history_interval > 0) then
     654            0 :                write_history = (mod(model, b% history_interval) == 0)
     655              :             else
     656              :                write_history = .false.
     657              :             end if
     658            0 :             if (s% terminal_interval > 0) then
     659            0 :                write_terminal = (mod(model, b% terminal_interval) == 0)
     660              :             else
     661              :                write_terminal = .false.
     662              :             end if
     663            0 :             if (write_history) b% need_to_update_binary_history_now = .true.
     664            0 :             get_history_info = b% need_to_update_binary_history_now .or. write_terminal
     665              :             if (get_history_info) then
     666            0 :                if (b% write_header_frequency * b% terminal_interval > 0) then
     667              :                   if (mod(model, b% write_header_frequency * b% terminal_interval) == 0 &
     668            0 :                      .and. .not. b% doing_first_model_of_run) then
     669            0 :                      write(*, '(A)')
     670            0 :                      call write_binary_terminal_header(b)
     671              :                   end if
     672              :                end if
     673            0 :                if (write_terminal) call do_binary_terminal_summary(b)
     674            0 :                if (b% need_to_update_binary_history_now) call write_binary_history_info(b, ierr)
     675            0 :                b% need_to_update_binary_history_now = .false.
     676              :             end if
     677              :          end if
     678              : 
     679            0 :          do l = 1, num_stars
     680            0 :             if (l == 1 .and. b% point_mass_i == 1) then
     681              :                i = 2
     682              :             else
     683            0 :                i = l
     684              :             end if
     685            0 :             id = b% star_ids(i)
     686            0 :             call star_ptr(id, s, ierr)
     687            0 :             partial_result = result
     688              :             call after_step_loop(id, b% job% inlist_names(i), &
     689            0 :                .false., partial_result, ierr)
     690            0 :             if (ierr /= 0) return
     691            0 :             result = worst_result(result, partial_result)
     692              :          end do
     693              : 
     694              :          ! do pgbinary stuff
     695            0 :          if (result == keep_going .and. b% job% pgbinary_flag) then
     696            0 :             will_read_pgbinary_inlist = .false.
     697            0 :             if (b% pg% pgbinary_interval <= 0) then
     698              :                will_read_pgbinary_inlist = .true.
     699            0 :             else if(mod(b% model_number, b% pg% pgbinary_interval) == 0) then
     700              :                will_read_pgbinary_inlist = .true.
     701              :             end if
     702            0 :             if (will_read_pgbinary_inlist) then
     703            0 :                call read_pgbinary_inlist(b, inlist_fname, ierr)
     704            0 :                if (failed('read_pgbinary_controls', ierr)) return
     705              :             end if
     706              :          end if
     707            0 :          if (result == keep_going .and. b% job% pgbinary_flag) then
     708            0 :             call update_pgbinary_plots(b, .false., ierr)
     709            0 :             if (failed('update_pgbinary_plots', ierr)) return
     710              :          end if
     711              : 
     712            0 :          if (result /= keep_going) then
     713            0 :             if (result /= terminate) then
     714            0 :                write(*, 2) 'ERROR in result value in run_star_extras: model', &
     715            0 :                   s% model_number
     716            0 :                write(*, 2) 'result', result
     717            0 :                exit evolve_loop
     718              :             end if
     719            0 :             do l = 1, num_stars
     720            0 :                if (l == 1 .and. b% point_mass_i == 1) then
     721              :                   i = 2
     722              :                else
     723            0 :                   i = l
     724              :                end if
     725            0 :                id = b% star_ids(i)
     726            0 :                call star_ptr(id, s, ierr)
     727            0 :                if (s% result_reason == result_reason_normal) then
     728              : 
     729              :                   partial_result = result
     730              :                   call terminate_normal_evolve_loop(id, &
     731            0 :                      .false., partial_result, ierr)
     732            0 :                   if (ierr /= 0) return
     733            0 :                   result = worst_result(result, partial_result)
     734              : 
     735              :                end if
     736              :             end do
     737            0 :             call write_binary_history_info(b, ierr)
     738            0 :             call do_binary_terminal_summary(b)
     739            0 :             exit evolve_loop
     740              :          end if
     741              : 
     742            0 :          do l = 1, num_stars
     743            0 :             if (l == 1 .and. b% point_mass_i == 1) then
     744              :                i = 2
     745              :             else
     746            0 :                i = l
     747              :             end if
     748            0 :             id = b% star_ids(i)
     749            0 :             call star_ptr(id, s, ierr)
     750              : 
     751              :             call do_saves(&
     752            0 :                id, ierr)
     753            0 :             if (ierr /= 0) return
     754              : 
     755            0 :             if (s% doing_timing) then
     756            0 :                call system_clock(s% job% time1_extra, s% job% clock_rate)
     757              :                s% job% after_step_timing = s% job% after_step_timing + &
     758            0 :                   dble(s% job% time1_extra - s% job% time0_extra) / s% job% clock_rate
     759            0 :                s% job% check_time_end = eval_total_times(s% id, ierr)
     760              :                s% job% check_after_step_timing = s% job% check_after_step_timing + &
     761            0 :                   (s% job% check_time_end - s% job% check_time_start)
     762              :             end if
     763              :          end do
     764            0 :          if (b% photo_interval > 0 .and. mod(b% model_number, b% photo_interval) == 0) then
     765            0 :             call do_saves_for_binary(b, ierr)
     766            0 :             if (ierr /= 0) return
     767              :          end if
     768              : 
     769            0 :          if (b% doing_first_model_of_run) b% doing_first_model_of_run = .false.
     770              : 
     771              :       end do evolve_loop
     772              : 
     773              :       ! save photos at end of the run
     774            0 :       call do_saves_for_binary(b, ierr)
     775            0 :       if (ierr /= 0) return
     776              : 
     777              :       ! deallocate arrays used for calculation of phase dependent variables
     778            0 :       deallocate(b% theta_co, b% time_co, b% mdot_donor_theta)
     779            0 :       deallocate(b% edot_theta, b% e1, b% e2, b% e3)
     780              : 
     781            0 :       ierr = binary_after_evolve(b)
     782            0 :       if (ierr /= 0) then
     783            0 :          write(*, *) "Error in binary_after_evolve"
     784            0 :          return
     785              :       end if
     786            0 :       call b% extras_binary_after_evolve(b% binary_id, ierr)
     787            0 :       if (ierr /= 0) then
     788            0 :          write(*, *) "Error in extras_binary_after_evolve"
     789            0 :          return
     790              :       end if
     791              : 
     792            0 :       do i = 1, num_stars
     793            0 :          if (i == 1 .and. b% point_mass_i == 1) then
     794              :             l = 2
     795              :          else
     796            0 :             l = i
     797              :          end if
     798              : 
     799            0 :          id = b% star_ids(l)
     800              : 
     801            0 :          call star_ptr(id, s, ierr)
     802            0 :          if (failed('star_ptr', ierr)) then
     803            0 :             ierr = 0
     804            0 :             cycle
     805              :          end if
     806              : 
     807            0 :          call after_evolve_loop(id, .true., ierr)
     808              : 
     809            0 :          if (s% doing_timing) then
     810            0 :             call system_clock(s% job% time1_extra, s% job% clock_rate)
     811              :             s% job% after_step_timing = s% job% after_step_timing + &
     812            0 :                dble(s% job% time1_extra - s% job% time0_extra) / s% job% clock_rate
     813            0 :             s% job% check_time_end = eval_total_times(s% id, ierr)
     814              :             s% job% check_after_step_timing = s% job% check_after_step_timing + &
     815            0 :                (s% job% check_time_end - s% job% check_time_start)
     816              :          end if
     817              : 
     818              :       end do
     819              : 
     820            0 :       call starlib_shutdown
     821              : 
     822            0 :    end subroutine do_run1_binary
     823              : 
     824            0 :    integer function worst_result(result1, result2)
     825              :       integer, intent(in) :: result1, result2
     826              : 
     827            0 :       if(result1 == terminate .or. result2 == terminate) then
     828            0 :          worst_result = terminate
     829              :          return
     830              :       end if
     831              : 
     832            0 :       if(result1 == retry .or. result2 == retry) then
     833            0 :          worst_result = retry
     834              :          return
     835              :       end if
     836              : 
     837            0 :       if(result1 == redo .or. result2 == redo) then
     838            0 :          worst_result = redo
     839            0 :          return
     840              :       end if
     841              : 
     842            0 :       worst_result = keep_going
     843              :       return
     844              : 
     845            0 :    end function worst_result
     846              : 
     847            0 :    subroutine binary_controls(id, binary_id, ierr)
     848              :       integer, intent(in) :: id, binary_id
     849              :       integer, intent(out) :: ierr
     850              :       type (star_info), pointer :: s
     851              :       type (binary_info), pointer :: b
     852              :       ierr = 0
     853              : 
     854            0 :       call star_ptr(id, s, ierr)
     855            0 :       if (ierr /= 0) then
     856            0 :          write(*, *) 'failed in star_ptr'
     857            0 :          return
     858              :       end if
     859            0 :       call binary_ptr(binary_id, b, ierr)
     860            0 :       if (ierr /= 0) then
     861            0 :          write(*, *) 'failed in binary_ptr'
     862            0 :          return
     863              :       end if
     864              : 
     865            0 :       s% binary_id = binary_id
     866              :       ! binary takes care of writing photos
     867            0 :       s% photo_interval = -1
     868            0 :       s% job% save_photo_when_terminate = .false.
     869            0 :       s% photo_digits = b% photo_digits
     870              : 
     871            0 :       if (b% donor_id == -1) then
     872            0 :          b% donor_id = id
     873            0 :          b% s1 => s
     874            0 :          s% initial_mass = b% m1
     875              :       else
     876            0 :          b% accretor_id = id
     877            0 :          b% s2 => s
     878            0 :          s% initial_mass = b% m2
     879              :       end if
     880              :    end subroutine binary_controls
     881              : 
     882            0 :    subroutine do_binary_job_controls_after(binary_id, b, restart, ierr)
     883              :       use binary_utils
     884              :       use binary_evolve, only : binary_finish_step
     885              :       integer, intent(in) :: binary_id
     886              :       type (binary_info), pointer :: b
     887              :       logical, intent(in) :: restart
     888              :       integer, intent(out) :: ierr
     889              :       logical :: need_to_fix_generations
     890              : 
     891              :       ! If something is changed in here, fix generations to zero so a retry wont
     892              :       ! erase change
     893            0 :       need_to_fix_generations = .false.
     894              : 
     895            0 :       if (b% job% change_ignore_rlof_flag .or. &
     896              :          (b% job% change_initial_ignore_rlof_flag .and. .not. restart)) then
     897            0 :          if (b% job% new_ignore_rlof_flag .neqv. b% ignore_rlof_flag) then
     898            0 :             call set_ignore_rlof_flag(binary_id, b% job% new_ignore_rlof_flag, ierr)
     899            0 :             if (ierr /= 0) then
     900            0 :                write(*, *) "error in set_ignore_rlof_flag"
     901            0 :                return
     902              :             end if
     903              :             need_to_fix_generations = .true.
     904              :          end if
     905              :       end if
     906              : 
     907            0 :       if (b% job% change_model_twins_flag .or. &
     908              :          (b% job% change_initial_model_twins_flag .and. .not. restart)) then
     909            0 :          if (b% job% new_model_twins_flag .neqv. b% model_twins_flag) then
     910            0 :             call set_model_twins_flag(binary_id, b% job% new_model_twins_flag, ierr)
     911            0 :             if (ierr /= 0) then
     912            0 :                write(*, *) "error in set_model_twins_flag"
     913            0 :                return
     914              :             end if
     915              :             need_to_fix_generations = .true.
     916              :          end if
     917              :       end if
     918              : 
     919            0 :       if (b% job% change_point_mass_i .or. &
     920              :          (b% job% change_initial_point_mass_i .and. .not. restart)) then
     921            0 :          if (b% job% new_point_mass_i /= b% point_mass_i) then
     922            0 :             call set_point_mass_i(binary_id, b% job% new_point_mass_i, ierr)
     923            0 :             if (ierr /= 0) then
     924            0 :                write(*, *) "error in set_point_mass_i"
     925            0 :                return
     926              :             end if
     927              :             need_to_fix_generations = .true.
     928              :          end if
     929              :       end if
     930              : 
     931            0 :       if (b% job% change_m1 .or. &
     932              :          (b% job% change_initial_m1 .and. .not. restart)) then
     933            0 :          if (b% m(1) /= b% job% new_m1) then
     934            0 :             call set_m1(binary_id, b% job% new_m1, ierr)
     935            0 :             if (ierr /= 0) then
     936            0 :                write(*, *) "error in set_m1"
     937            0 :                return
     938              :             end if
     939              :             need_to_fix_generations = .true.
     940              :          end if
     941              :       end if
     942              : 
     943            0 :       if (b% job% change_m2 .or. &
     944              :          (b% job% change_initial_m2 .and. .not. restart)) then
     945            0 :          if (b% m(2) /= b% job% new_m2) then
     946            0 :             call set_m2(binary_id, b% job% new_m2, ierr)
     947            0 :             if (ierr /= 0) then
     948            0 :                write(*, *) "error in set_m2"
     949            0 :                return
     950              :             end if
     951              :             need_to_fix_generations = .true.
     952              :          end if
     953              :       end if
     954              : 
     955            0 :       if (b% job% change_period_eccentricity .or. &
     956              :          (b% job% change_initial_period_eccentricity .and. .not. restart)) then
     957            0 :          if (b% period /= b% job% new_period * secday .or. &
     958              :             b% eccentricity /= b% job% new_eccentricity) then
     959              :             call set_period_eccentricity(binary_id, &
     960            0 :                b% job% new_period * secday, b% job% new_eccentricity, ierr)
     961            0 :             if (ierr /= 0) then
     962            0 :                write(*, *) "error in set_period_eccentricity"
     963            0 :                return
     964              :             end if
     965              :             need_to_fix_generations = .true.
     966              :          end if
     967              :       end if
     968              : 
     969            0 :       if (b% job% change_separation_eccentricity .or. &
     970              :          (b% job% change_initial_separation_eccentricity .and. .not. restart)) then
     971            0 :          if (b% separation /= b% job% new_separation * Rsun .or. &
     972              :             b% eccentricity /= b% job% new_eccentricity) then
     973              :             call set_separation_eccentricity(binary_id, &
     974            0 :                b% job% new_separation * Rsun, b% job% new_eccentricity, ierr)
     975            0 :             if (ierr /= 0) then
     976            0 :                write(*, *) "error in set_separation_eccentricity"
     977            0 :                return
     978              :             end if
     979              :             need_to_fix_generations = .true.
     980              :          end if
     981              :       end if
     982              : 
     983            0 :       if (need_to_fix_generations) then
     984            0 :          if (b% point_mass_i /= 1) then
     985            0 :             b% s1% generations = 0
     986              :          end if
     987            0 :          if (b% point_mass_i /= 2) then
     988            0 :             b% s2% generations = 0
     989              :          end if
     990            0 :          b% generations = 0
     991              : 
     992              :          ! this updates 'old' values in case there is a retry on the first step
     993            0 :          ierr = binary_finish_step(b)
     994              : 
     995            0 :          if (ierr == keep_going) then
     996            0 :             ierr = 0
     997              :          else
     998            0 :             ierr = -1
     999              :          end if
    1000              :       end if
    1001              : 
    1002            0 :    end subroutine do_binary_job_controls_after
    1003              : 
    1004              : end module run_binary_support
        

Generated by: LCOV version 2.0-1