LCOV - code coverage report
Current view: top level - star/private - evolve.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 32.5 % 1340 435
Test Date: 2025-06-06 17:08:43 Functions: 79.2 % 24 19

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2019  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              :       module evolve
      21              : 
      22              :       use star_private_def
      23              :       use const_def, only: dp, i8, pi, pi4, msun, lsun, crad, clight, secyer, secday
      24              :       use utils_lib, only: is_bad
      25              :       use star_utils
      26              :       use auto_diff_support
      27              : 
      28              :       implicit none
      29              : 
      30              :       private
      31              :       public :: do_evolve_step_part1
      32              :       public :: do_evolve_step_part2
      33              :       public :: pick_next_timestep
      34              :       public :: prepare_to_redo
      35              :       public :: prepare_to_retry
      36              :       public :: finish_step
      37              :       public :: set_age
      38              : 
      39              :       contains
      40              : 
      41           11 :       integer function do_evolve_step_part1(id, first_try)
      42              :          use alloc, only: fill_star_info_arrays_with_NaNs, &
      43              :             do_fill_arrays_with_NaNs, star_info_old_arrays
      44              :          logical, intent(in) :: first_try
      45              :          integer, intent(in) :: id
      46              :          type (star_info), pointer :: s
      47              :          integer :: ierr
      48              :          include 'formats'
      49              : 
      50           11 :          do_evolve_step_part1 = terminate
      51              :          ierr = 0
      52           11 :          call star_ptr(id, s, ierr)
      53           11 :          if (ierr /= 0) return
      54              : 
      55           11 :          if (s% trace_evolve) write(*,'(/,a)') 'start evolve step'
      56              : 
      57           11 :          if (is_bad(s% dt)) then
      58            0 :             write(*,1) 's% dt', s% dt
      59            0 :             call mesa_error(__FILE__,__LINE__,'do_evolve_step_part1')
      60              :          end if
      61              : 
      62           11 :          if (first_try .and. s% fill_arrays_with_NaNs .and. .not. s% RSP_flag) then
      63            0 :             if (mod(s% model_number, s% terminal_interval) == 0) &
      64            0 :                write(*,*) 'fill_arrays_with_NaNs at start of step'
      65            0 :             call test_set_undefined
      66            0 :             call fill_star_info_arrays_with_NaNs(s, ierr)
      67            0 :             if (ierr /= 0) return
      68            0 :             call star_info_old_arrays(s, do_fill_arrays_with_NaNs, ierr)
      69            0 :             if (ierr /= 0) return
      70              :          end if
      71           11 :          do_evolve_step_part1 = do_step_part1(id, first_try)
      72           11 :          s% total_step_attempts = s% total_step_attempts + 1
      73           11 :          if (s% doing_relax) &
      74            0 :             s% total_relax_step_attempts = s% total_relax_step_attempts + 1
      75           22 :          if (do_evolve_step_part1 == redo) then
      76            0 :             s% total_step_redos = s% total_step_redos + 1
      77            0 :             if (s% doing_relax) &
      78            0 :                s% total_relax_step_redos = s% total_relax_step_redos + 1
      79           11 :          else if (do_evolve_step_part1 == retry) then
      80            0 :             s% total_step_retries = s% total_step_retries + 1
      81            0 :             if (s% doing_relax) &
      82            0 :                s% total_relax_step_retries = s% total_relax_step_retries + 1
      83              :          end if
      84              : 
      85              :          contains
      86              : 
      87            0 :          subroutine test_set_undefined
      88              :             ! should include everything in star_data_step_work.inc
      89              :             ! may be missing some.  if so, please add them.
      90           11 :             use utils_lib, only: set_to_NaN
      91              :             integer :: j
      92              :             include 'formats'
      93              : 
      94            0 :             s% nz_old = -999
      95            0 :             s% model_number_old = -999
      96            0 :             s% prev_mesh_nz = -999
      97            0 :             s% num_conv_boundaries = -999
      98            0 :             s% num_mix_boundaries = -999
      99            0 :             s% num_mix_regions = -999
     100            0 :             s% num_mixing_regions = -999
     101            0 :             s% n_conv_regions = -999
     102            0 :             s% atm_structure_num_pts = -999
     103            0 :             s% generations = -999
     104            0 :             s% num_solver_iterations = -999
     105            0 :             s% num_diffusion_solver_iters = -999
     106            0 :             s% num_diffusion_solver_steps = -999
     107            0 :             s% num_rotation_solver_steps = -999
     108            0 :             s% result_reason = -999
     109            0 :             s% burner_num_threads = -999
     110            0 :             s% k_below_const_q = -999
     111            0 :             s% k_const_mass = -999
     112            0 :             s% k_for_test_CpT_absMdot_div_L = -999
     113            0 :             s% k_below_just_added = -999
     114            0 :             s% termination_code = -999
     115            0 :             s% dX_nuc_drop_max_k = -999
     116            0 :             s% dX_nuc_drop_max_j = -999
     117            0 :             s% solver_test_partials_var = -999
     118            0 :             s% solver_test_partials_dx_sink = -999
     119            0 :             s% n_conv_regions_old = -999
     120            0 :             do j=1,max_num_mixing_regions
     121            0 :                call set_to_NaN(s% cz_top_mass_old(j))
     122            0 :                call set_to_NaN(s% cz_bot_mass_old(j))
     123              :             end do
     124              : 
     125            0 :             do j=1,num_categories
     126            0 :                call set_to_NaN(s% L_by_category(j))
     127              :             end do
     128              : 
     129              :             ! sorted to help remove duplicates
     130            0 :             call set_to_NaN(s% L_center_old)
     131            0 :             call set_to_NaN(s% L_for_BB_outer_BC)
     132            0 :             call set_to_NaN(s% L_nuc_burn_total)
     133            0 :             call set_to_NaN(s% L_phot_old)
     134            0 :             call set_to_NaN(s% L_surf)
     135            0 :             call set_to_NaN(s% L_surf_old)
     136            0 :             call set_to_NaN(s% M_center_old)
     137            0 :             call set_to_NaN(s% R_center_old)
     138            0 :             call set_to_NaN(s% Teff_old)
     139            0 :             call set_to_NaN(s% acoustic_cutoff)
     140            0 :             call set_to_NaN(s% adjust_J_q)
     141            0 :             call set_to_NaN(s% adjust_mass_inner_frac_sub1)
     142            0 :             call set_to_NaN(s% adjust_mass_mid_frac_sub1)
     143            0 :             call set_to_NaN(s% adjust_mass_outer_frac_sub1)
     144            0 :             call set_to_NaN(s% angular_momentum_added)
     145            0 :             call set_to_NaN(s% angular_momentum_removed)
     146            0 :             call set_to_NaN(s% conv_mx1_bot)
     147            0 :             call set_to_NaN(s% conv_mx1_bot_r)
     148            0 :             call set_to_NaN(s% conv_mx1_top)
     149            0 :             call set_to_NaN(s% conv_mx1_top_r)
     150            0 :             call set_to_NaN(s% conv_mx2_bot)
     151            0 :             call set_to_NaN(s% conv_mx2_bot_r)
     152            0 :             call set_to_NaN(s% conv_mx2_top)
     153            0 :             call set_to_NaN(s% conv_mx2_top_r)
     154            0 :             call set_to_NaN(s% cumulative_energy_error_old)
     155            0 :             call set_to_NaN(s% cumulative_extra_heating_old)
     156            0 :             call set_to_NaN(s% d_vc_dv)
     157            0 :             call set_to_NaN(s% delta_Pg)
     158            0 :             call set_to_NaN(s% delta_nu)
     159            0 :             call set_to_NaN(s% dt_days)
     160            0 :             call set_to_NaN(s% dt_limit_ratio_old)
     161            0 :             call set_to_NaN(s% dt_old)
     162            0 :             call set_to_NaN(s% dt_start)
     163            0 :             call set_to_NaN(s% dt_years)
     164            0 :             call set_to_NaN(s% energy_change_from_do_adjust_mass_and_calculate_eps_mdot)
     165            0 :             call set_to_NaN(s% error_in_energy_conservation)
     166            0 :             call set_to_NaN(s% explicit_mstar_dot)
     167            0 :             call set_to_NaN(s% gradT_excess_max_lambda)
     168            0 :             call set_to_NaN(s% gradT_excess_min_beta)
     169            0 :             call set_to_NaN(s% h1_czb_mass)
     170            0 :             call set_to_NaN(s% initial_L_center)
     171            0 :             call set_to_NaN(s% initial_R_center)
     172            0 :             call set_to_NaN(s% initial_timestep)
     173            0 :             call set_to_NaN(s% initial_v_center)
     174            0 :             call set_to_NaN(s% max_conv_time_scale)
     175            0 :             call set_to_NaN(s% max_residual)
     176            0 :             call set_to_NaN(s% mdot_acoustic_surface)
     177            0 :             call set_to_NaN(s% mdot_adiabatic_surface)
     178            0 :             call set_to_NaN(s% mesh_adjust_IE_conservation)
     179            0 :             call set_to_NaN(s% mesh_adjust_KE_conservation)
     180            0 :             call set_to_NaN(s% mesh_adjust_PE_conservation)
     181            0 :             call set_to_NaN(s% min_conv_time_scale)
     182            0 :             call set_to_NaN(s% mstar_dot_old)
     183            0 :             call set_to_NaN(s% mstar_old)
     184            0 :             call set_to_NaN(s% mx1_bot)
     185            0 :             call set_to_NaN(s% mx1_bot_r)
     186            0 :             call set_to_NaN(s% mx1_top)
     187            0 :             call set_to_NaN(s% mx1_top_r)
     188            0 :             call set_to_NaN(s% mx2_bot)
     189            0 :             call set_to_NaN(s% mx2_bot_r)
     190            0 :             call set_to_NaN(s% mx2_top)
     191            0 :             call set_to_NaN(s% mx2_top_r)
     192            0 :             call set_to_NaN(s% non_epsnuc_energy_change_from_split_burn)
     193            0 :             call set_to_NaN(s% nu_max)
     194            0 :             call set_to_NaN(s% power_neutrinos)
     195            0 :             call set_to_NaN(s% power_nonnuc_neutrinos)
     196            0 :             call set_to_NaN(s% power_nuc_burn_old)
     197            0 :             call set_to_NaN(s% power_nuc_neutrinos)
     198            0 :             call set_to_NaN(s% prev_Ledd)
     199            0 :             call set_to_NaN(s% residual_norm)
     200            0 :             call set_to_NaN(s% rotational_mdot_boost)
     201            0 :             call set_to_NaN(s% shock_mass_start)
     202            0 :             call set_to_NaN(s% solver_test_partials_dval_dx)
     203            0 :             call set_to_NaN(s% solver_test_partials_val)
     204            0 :             call set_to_NaN(s% star_age)
     205            0 :             call set_to_NaN(s% starting_T_center)
     206            0 :             call set_to_NaN(s% super_eddington_wind_mdot)
     207            0 :             call set_to_NaN(s% surf_csound)
     208            0 :             call set_to_NaN(s% surf_r_equatorial)
     209            0 :             call set_to_NaN(s% surf_rho)
     210            0 :             call set_to_NaN(s% surface_cell_specific_total_energy_old)
     211            0 :             call set_to_NaN(s% tau_center)
     212            0 :             call set_to_NaN(s% time_days)
     213            0 :             call set_to_NaN(s% time_old)
     214            0 :             call set_to_NaN(s% time_step)
     215            0 :             call set_to_NaN(s% time_years)
     216            0 :             call set_to_NaN(s% total_WD_sedimentation_heating)
     217            0 :             call set_to_NaN(s% total_abs_angular_momentum)
     218            0 :             call set_to_NaN(s% total_angular_momentum)
     219            0 :             call set_to_NaN(s% total_angular_momentum_old)
     220            0 :             call set_to_NaN(s% total_energy)
     221            0 :             call set_to_NaN(s% total_energy_after_adjust_mass)
     222            0 :             call set_to_NaN(s% total_energy_before_adjust_mass)
     223            0 :             call set_to_NaN(s% total_energy_change_from_mdot)
     224            0 :             call set_to_NaN(s% total_energy_end)
     225            0 :             call set_to_NaN(s% total_energy_from_diffusion)
     226            0 :             call set_to_NaN(s% total_energy_from_phase_separation)
     227            0 :             call set_to_NaN(s% total_energy_old)
     228            0 :             call set_to_NaN(s% total_energy_sources_and_sinks)
     229            0 :             call set_to_NaN(s% total_energy_start)
     230            0 :             call set_to_NaN(s% total_eps_grav)
     231            0 :             call set_to_NaN(s% total_eps_mdot)
     232            0 :             call set_to_NaN(s% total_extra_heating)
     233            0 :             call set_to_NaN(s% total_gravitational_energy)
     234            0 :             call set_to_NaN(s% total_gravitational_energy_after_adjust_mass)
     235            0 :             call set_to_NaN(s% total_gravitational_energy_before_adjust_mass)
     236            0 :             call set_to_NaN(s% total_gravitational_energy_end)
     237            0 :             call set_to_NaN(s% total_gravitational_energy_initial)
     238            0 :             call set_to_NaN(s% total_gravitational_energy_old)
     239            0 :             call set_to_NaN(s% total_gravitational_energy_start)
     240            0 :             call set_to_NaN(s% total_internal_energy)
     241            0 :             call set_to_NaN(s% total_internal_energy_after_adjust_mass)
     242            0 :             call set_to_NaN(s% total_internal_energy_before_adjust_mass)
     243            0 :             call set_to_NaN(s% total_internal_energy_end)
     244            0 :             call set_to_NaN(s% total_internal_energy_initial)
     245            0 :             call set_to_NaN(s% total_internal_energy_old)
     246            0 :             call set_to_NaN(s% total_internal_energy_start)
     247            0 :             call set_to_NaN(s% total_irradiation_heating)
     248            0 :             call set_to_NaN(s% total_non_nuc_neu_cooling)
     249            0 :             call set_to_NaN(s% total_nuclear_heating)
     250            0 :             call set_to_NaN(s% total_radial_kinetic_energy)
     251            0 :             call set_to_NaN(s% total_radial_kinetic_energy_after_adjust_mass)
     252            0 :             call set_to_NaN(s% total_radial_kinetic_energy_before_adjust_mass)
     253            0 :             call set_to_NaN(s% total_radial_kinetic_energy_end)
     254            0 :             call set_to_NaN(s% total_radial_kinetic_energy_initial)
     255            0 :             call set_to_NaN(s% total_radial_kinetic_energy_old)
     256            0 :             call set_to_NaN(s% total_radial_kinetic_energy_start)
     257            0 :             call set_to_NaN(s% total_rotational_kinetic_energy)
     258            0 :             call set_to_NaN(s% total_rotational_kinetic_energy_after_adjust_mass)
     259            0 :             call set_to_NaN(s% total_rotational_kinetic_energy_before_adjust_mass)
     260            0 :             call set_to_NaN(s% total_rotational_kinetic_energy_end)
     261            0 :             call set_to_NaN(s% total_rotational_kinetic_energy_initial)
     262            0 :             call set_to_NaN(s% total_rotational_kinetic_energy_old)
     263            0 :             call set_to_NaN(s% total_rotational_kinetic_energy_start)
     264            0 :             call set_to_NaN(s% total_turbulent_energy)
     265            0 :             call set_to_NaN(s% total_turbulent_energy_after_adjust_mass)
     266            0 :             call set_to_NaN(s% total_turbulent_energy_before_adjust_mass)
     267            0 :             call set_to_NaN(s% total_turbulent_energy_end)
     268            0 :             call set_to_NaN(s% total_turbulent_energy_initial)
     269            0 :             call set_to_NaN(s% total_turbulent_energy_old)
     270            0 :             call set_to_NaN(s% total_turbulent_energy_start)
     271            0 :             call set_to_NaN(s% v_center_old)
     272            0 :             call set_to_NaN(s% virial_thm_P_avg)
     273            0 :             call set_to_NaN(s% work_inward_at_center)
     274            0 :             call set_to_NaN(s% work_outward_at_surface)
     275            0 :             call set_to_NaN(s% xmstar_old)
     276              : 
     277            0 :          end subroutine test_set_undefined
     278              : 
     279              :       end function do_evolve_step_part1
     280              : 
     281              : 
     282           11 :       integer function do_step_part1(id, first_try)
     283              :          use evolve_support, only: set_current_to_old
     284              :          use hydro_vars, only: set_vars
     285              :          use winds, only: set_mdot
     286              :          use alloc, only: check_sizes, fill_star_info_arrays_with_NaNs
     287              :          use do_one_utils, only: write_terminal_header
     288              :          use hydro_vars, only: set_vars_if_needed, set_vars, set_cgrav
     289              :          use mix_info, only: set_cz_bdy_mass
     290              :          use hydro_rotation, only: use_xh_to_update_i_rot, set_rotation_info
     291              :          use star_utils
     292              :          use report, only: do_report
     293              :          use rsp, only: rsp_total_energy_integrals
     294              :          logical, intent(in) :: first_try
     295              :          integer, intent(in) :: id
     296              : 
     297              :          type (star_info), pointer :: s
     298              :          integer :: ierr, k, nz
     299              :          integer(i8) :: time0, clock_rate
     300           11 :          real(dp) :: total_radiation
     301              : 
     302              :          logical, parameter :: dbg = .false.
     303              : 
     304              :          include 'formats'
     305              : 
     306           11 :          do_step_part1 = terminate
     307           11 :          ierr = 0
     308              :          call get_star_ptr(id, s, ierr)
     309           11 :          if (ierr /= 0) return
     310              : 
     311           11 :          s% termination_code = 0
     312           11 :          s% retry_message = ''
     313           11 :          s% doing_solver_iterations = .false.
     314           11 :          s% num_rotation_solver_steps = 0
     315           11 :          s% have_mixing_info = .false.
     316           11 :          s% rotational_mdot_boost = 0d0
     317           11 :          s% phase_sep_mixing_mass = -1d0  ! must be negative at start of step
     318           11 :          s% L_for_BB_outer_BC = -1  ! mark as not set
     319           11 :          s% need_to_setvars = .true.  ! always start fresh
     320           11 :          s% okay_to_set_mixing_info = .true.  ! set false by element diffusion
     321           11 :          s% okay_to_set_mlt_vc = .false.  ! don't change mlt_vc until have set mlt_vc_old
     322              : 
     323           11 :          if (s% timestep_hold > s% model_number + 10000) then
     324            0 :             write(*,3) 'ERROR: s% timestep_hold', s% timestep_hold, s% model_number
     325            0 :             call mesa_error(__FILE__,__LINE__,'do_step_part1')
     326              :          end if
     327              : 
     328           11 :          if (s% u_flag .and. s% v_flag) then
     329            0 :             write(*,*) 'must not have both u_flag and v_flag at the same time'
     330            0 :             return
     331              :          end if
     332              : 
     333           11 :          call reset_starting_vectors(s)
     334           11 :          nz = s% nz
     335              :          call set_qs(s, nz, s% q, s% dq, ierr)
     336           11 :          if (failed('set_qs')) return
     337           11 :          call set_m_and_dm(s)
     338           11 :          call set_dm_bar(s, nz, s% dm, s% dm_bar)
     339              : 
     340           11 :          if (s% rotation_flag) then
     341              :             call set_cgrav(s, ierr)
     342            0 :             if (failed('set_cgrav')) return
     343            0 :             call use_xh_to_update_i_rot(s)
     344            0 :             s% total_angular_momentum = total_angular_momentum(s)
     345              :             ! set r and rmid from xh
     346            0 :             do k=1,nz
     347            0 :                call get_r_and_lnR_from_xh(s, k, s% r(k), s% lnR(k))
     348              :             end do
     349            0 :             call set_rmid(s, 1, nz, ierr)
     350            0 :             if (failed('set_rmid')) return
     351            0 :             call set_rotation_info(s, .true., ierr)
     352            0 :             if (failed('set_rotation_info')) return
     353              :          end if
     354              : 
     355           11 :          if (s% doing_first_model_of_run) then
     356            1 :             if (s% do_history_file) then
     357            1 :                if (first_try) then
     358            1 :                   call write_terminal_header(s)
     359              :                else
     360            0 :                   write(*,1) '1st model retry log10(dt/yr)', log10(s% dt/secyer)
     361              :                end if
     362              :             end if
     363            1 :             call system_clock(time0,clock_rate)
     364            1 :             s% starting_system_clock_time = time0
     365            1 :             s% system_clock_rate = clock_rate
     366            1 :             s% initial_timestep = s% dt_next
     367            1 :             s% initial_L_center = s% L_center
     368            1 :             s% initial_R_center = s% R_center
     369            1 :             s% initial_v_center = s% v_center
     370            1 :             s% timestep_hold = -111
     371            1 :             if (first_try) s% model_number_old = s% model_number
     372              :          end if
     373              : 
     374           11 :          call system_clock(s% system_clock_at_start_of_step, clock_rate)
     375              : 
     376           11 :          if (first_try) then  ! i.e., not a redo or retry
     377           11 :             s% have_new_generation = .false.
     378           11 :             do_step_part1 = prepare_for_new_step(s)
     379           11 :             if (do_step_part1 /= keep_going) then
     380            0 :                if (s% report_ierr) &
     381            0 :                   write(*,*) 'do_step_part1: prepare_for_new_step'
     382            0 :                return
     383              :             end if
     384           11 :             s% have_new_generation = .true.
     385           11 :             s% have_new_cz_bdy_info = .false.
     386           11 :             if ((s% steps_before_use_velocity_time_centering == 0) .or. &
     387              :                 (s% steps_before_use_velocity_time_centering > 0 .and. &
     388              :                    s% model_number >= s% steps_before_use_velocity_time_centering)) &
     389            0 :                s% using_velocity_time_centering = .true.
     390           11 :             if (.not. s% doing_relax .and. s% steps_before_use_TDC > 0) then
     391            0 :                if (s% model_number >= s% steps_before_use_TDC) then
     392            0 :                   s% MLT_option = 'TDC'
     393              :                else
     394            0 :                   s% MLT_option = 'Cox'
     395              :                end if
     396              :             end if
     397              :          end if
     398              : 
     399           11 :          call reset_epsnuc_vectors(s)
     400              : 
     401           11 :          call set_current_to_old(s)
     402           11 :          do_step_part1 = prepare_for_new_try(s)
     403           11 :          if (do_step_part1 /= keep_going) then
     404            0 :             if (s% report_ierr) &
     405            0 :                write(*,*) 'do_step_part1: prepare_for_new_try'
     406            0 :             return
     407              :          end if
     408              : 
     409              :          call set_start_of_step_info(s, 'after prepare_for_new_try', ierr)  ! does set_vars_if_needed
     410           11 :          if (failed('set_start_of_step_info')) return
     411              : 
     412           11 :          if (.not. s% have_new_cz_bdy_info) then
     413              :             call set_cz_bdy_mass(s, ierr)
     414            0 :             if (failed('set_cz_bdy_mass')) return
     415              :          end if
     416              : 
     417           11 :          if (s% RSP_flag) then
     418            0 :             s% mstar_dot = 0
     419              :             call rsp_total_energy_integrals(s, &
     420              :                s% total_internal_energy_old, &
     421              :                s% total_gravitational_energy_old, &
     422              :                s% total_radial_kinetic_energy_old, &
     423              :                s% total_rotational_kinetic_energy_old, &
     424              :                s% total_turbulent_energy_old, &
     425            0 :                s% total_energy_old, total_radiation)
     426              :          else
     427           11 :             call set_mdot(s, s% L_phot*Lsun, s% mstar, s% Teff, ierr)
     428           11 :             if (failed('set_mdot')) return
     429              :             ! set energy info for new mesh
     430              :             call eval_total_energy_integrals(s, &
     431              :                s% total_internal_energy_old, &
     432              :                s% total_gravitational_energy_old, &
     433              :                s% total_radial_kinetic_energy_old, &
     434              :                s% total_rotational_kinetic_energy_old, &
     435              :                s% total_turbulent_energy_old, &
     436           11 :                s% total_energy_old)
     437              :          end if
     438              : 
     439           11 :          s% surface_cell_specific_total_energy_old = cell_specific_total_energy(s,1)
     440              : 
     441           45 :          if (.not. s% have_initial_energy_integrals) then
     442              :             s% total_internal_energy_initial = &
     443            1 :                s% total_internal_energy_old
     444              :             s% total_gravitational_energy_initial = &
     445            1 :                s% total_gravitational_energy_old
     446              :             s% total_radial_kinetic_energy_initial = &
     447            1 :                s% total_radial_kinetic_energy_old
     448              :             s% total_rotational_kinetic_energy_initial = &
     449            1 :                s% total_rotational_kinetic_energy_old
     450            1 :             s% total_turbulent_energy_initial = s% total_turbulent_energy_old
     451            1 :             s% total_energy_initial = s% total_energy_old
     452            1 :             s% have_initial_energy_integrals = .true.
     453              :          end if
     454              : 
     455              :          contains
     456              : 
     457           33 :          logical function failed(str)
     458              :             character (len=*), intent(in) :: str
     459           33 :             if (ierr == 0) then
     460           33 :                failed = .false.
     461              :                return
     462              :             end if
     463            0 :             failed = .true.
     464            0 :             do_step_part1 = retry
     465            0 :             if (s% report_ierr) write(*, *) 'do_step_part1 ' // trim(str)
     466            0 :             s% result_reason = nonzero_ierr
     467           11 :          end function failed
     468              : 
     469              :       end function do_step_part1
     470              : 
     471              : 
     472           11 :       integer function do_evolve_step_part2(id, first_try)
     473              :          logical, intent(in) :: first_try
     474              :          integer, intent(in) :: id
     475              :          type (star_info), pointer :: s
     476              :          integer :: ierr
     477           11 :          do_evolve_step_part2 = terminate
     478              :          ierr = 0
     479           11 :          call star_ptr(id, s, ierr)
     480           11 :          if (ierr /= 0) return
     481           11 :          do_evolve_step_part2 = do_step_part2(id, first_try)
     482           11 :          if (do_evolve_step_part2 == redo) then
     483            0 :             s% total_step_redos = s% total_step_redos + 1
     484            0 :             if (s% doing_relax) &
     485            0 :                s% total_relax_step_redos = s% total_relax_step_redos + 1
     486           11 :          else if (do_evolve_step_part2 == retry) then
     487            0 :             s% total_step_retries = s% total_step_retries + 1
     488            0 :             if (s% doing_relax) &
     489            0 :                s% total_relax_step_retries = s% total_relax_step_retries + 1
     490              :          else  ! keep_going or terminate both count as finished
     491           11 :             s% total_steps_finished = s% total_steps_finished + 1
     492           11 :             if (s% doing_relax) &
     493            0 :                s% total_relax_steps_finished = s% total_relax_steps_finished + 1
     494              :          end if
     495           11 :          if (s% trace_evolve) write(*,'(/,a)') 'done evolve step'
     496              :       end function do_evolve_step_part2
     497              : 
     498              : 
     499           11 :       integer function do_step_part2(id, first_try)
     500              :          use num_def
     501              :          use chem_def
     502              :          use report, only: do_report, set_power_info
     503              :          use adjust_mass, only: do_adjust_mass
     504              :          use element_diffusion, only: do_element_diffusion, finish_element_diffusion
     505              :          use phase_separation, only: do_phase_separation
     506              :          use conv_premix, only: do_conv_premix
     507              :          use evolve_support, only: set_current_to_old
     508              :          use eps_mdot, only: calculate_eps_mdot
     509              :          use struct_burn_mix, only: do_struct_burn_mix
     510              :          use hydro_vars, only: set_vars_if_needed, set_vars, set_final_vars, set_cgrav
     511              :          use star_utils, only: start_time, update_time, get_phot_info
     512              :          use solve_omega_mix, only: do_solve_omega_mix
     513              :          use mix_info, only: set_cz_bdy_mass, set_mixing_info
     514              :          use hydro_rotation, only: set_rotation_info, set_i_rot
     515              :          use winds, only: set_mdot
     516              :          use star_utils, only: &
     517              :             eval_integrated_total_energy_profile, eval_deltaM_total_energy_integrals, &
     518              :             set_phase_of_evolution, set_luminosity_by_category
     519              :          use profile
     520              : 
     521              :          logical, intent(in) :: first_try
     522              :          integer, intent(in) :: id
     523              : 
     524              :          type (star_info), pointer :: s
     525              :          integer :: ierr, &
     526              :             k, mdot_redo_cnt, max_mdot_redo_cnt, nz
     527              :          integer(i8) :: time0, clock_rate
     528              :          logical :: trace, skip_global_corr_coeff_limit, &
     529              :             have_too_large_wind_mdot, have_too_small_wind_mdot, &
     530              :             ignored_first_step, was_in_implicit_wind_limit
     531           11 :          real(dp) :: w_div_w_crit, w_div_w_crit_prev, mstar_dot, mstar_dot_prev, abs_mstar_delta, &
     532           11 :             explicit_mdot, max_wind_mdot, wind_mdot, r_phot, kh_timescale, dmskhf, dmsfac, &
     533           11 :             too_large_wind_mdot, too_small_wind_mdot, boost, mstar_dot_nxt, &
     534           11 :             surf_omega_div_omega_crit_limit, dt
     535              : 
     536              :          integer :: ph_k, mdot_action
     537           11 :          real(dp) :: implicit_mdot, ph_L, iwind_tolerance, iwind_lambda
     538           11 :          real(dp) :: dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, dummy7, dummy8
     539              :          integer :: iwind_redo_cnt, iwind_max_redo_cnt
     540              :          integer, parameter :: exit_loop = 1, cycle_loop = 0
     541              : 
     542              :          logical, parameter :: dbg = .false.
     543              : 
     544              :          include 'formats'
     545              : 
     546           11 :          ierr = 0
     547              :          call get_star_ptr(id, s, ierr)
     548           11 :          if (ierr /= 0) return
     549              : 
     550           11 :          if (s% dt <= 0d0) then
     551            0 :             do_step_part2 = terminate
     552            0 :             s% termination_code = t_dt_is_zero
     553            0 :             s% result_reason = dt_is_zero
     554            0 :             return
     555              :          end if
     556              : 
     557           11 :          time0 = s% starting_system_clock_time
     558           11 :          clock_rate = s% system_clock_rate
     559           11 :          trace = s% trace_evolve
     560           11 :          nz = s% nz
     561              : 
     562           11 :          call setup_for_implicit_mdot_loop
     563              : 
     564           44 :       implicit_mdot_loop: do
     565              : 
     566           11 :             dt = s% dt
     567           11 :             s% time = s% time_old + dt
     568           11 :             s% star_age = s% time/secyer
     569           11 :             s% okay_to_set_mixing_info = .true.
     570              : 
     571           11 :             if (s% v_center /= 0d0) then  ! adjust R_center
     572            0 :                s% R_center = s% R_center_old + dt*s% v_center
     573            0 :                if (s% R_center < 0d0) then
     574            0 :                   write(*,2) 's% R_center', s% model_number, s% R_center
     575            0 :                   do_step_part2 = retry
     576            0 :                   return
     577              :                end if
     578              :             end if
     579              : 
     580              :             call set_vars_if_needed(s, dt, 'start of implicit_mdot_loop', ierr)
     581           11 :             if (failed('set_vars_if_needed start of implicit_mdot_loop')) return
     582              : 
     583           22 :             if (s% RSP_flag) then
     584              : 
     585              :                call set_cgrav(s, ierr)
     586            0 :                if (failed('set_cgrav')) return
     587              : 
     588              :             else
     589              : 
     590              :                call do_adjust_mass(s, s% species, ierr)
     591           11 :                if (failed('do_adjust_mass')) return
     592           11 :                s% star_mdot = s% mstar_dot/(Msun/secyer)      ! dm/dt in msolar per year
     593              :                call set_vars_if_needed(s, dt, 'after do_adjust_mass', ierr)
     594           11 :                if (failed('set_vars_if_needed after do_adjust_mass')) return
     595              : 
     596           11 :                call calculate_eps_mdot(s, dt, ierr)
     597           11 :                if (failed('calculate_eps_mdot')) return
     598              : 
     599           11 :                if (s% mstar_dot /= 0d0) then
     600              :                   s% energy_change_from_do_adjust_mass_and_calculate_eps_mdot = &
     601            0 :                      s% total_energy_after_adjust_mass - s% total_energy_before_adjust_mass
     602              :                else
     603           11 :                   s% energy_change_from_do_adjust_mass_and_calculate_eps_mdot = 0d0
     604              :                end if
     605              : 
     606              :                call set_vars_if_needed(s, dt, 'after calculate_eps_mdot', ierr)
     607           11 :                if (failed('set_vars_if_needed after calculate_eps_mdot')) return
     608              : 
     609           11 :                if (s% do_conv_premix) then
     610            0 :                   do k=1,s% nz
     611            0 :                      s% eps_pre_mix(k) = s% energy(k)
     612              :                   end do
     613              :                   call do_conv_premix(s, ierr)
     614            0 :                   if (failed('do_conv_premix')) return
     615              :                   call set_vars_if_needed(s, dt, 'after do_conv_premix', ierr)
     616            0 :                   if (failed('set_vars_if_needed after do_conv_premix')) return
     617            0 :                   do k=1,s% nz  ! for use by energy equation
     618            0 :                      s% eps_pre_mix(k) = (s% eps_pre_mix(k) - s% energy(k)) / dt
     619              :                   end do
     620              :                end if
     621              : 
     622           11 :                if(s% do_phase_separation) then
     623              :                   call do_phase_separation(s, dt, ierr)
     624            0 :                   if (failed('do_phase_separation')) return
     625              : 
     626              :                   call set_vars_if_needed(s, dt, 'after phase separation', ierr)
     627            0 :                   if (failed('set_vars_if_needed after phase separation')) return
     628              :                else
     629           11 :                   s% crystal_core_boundary_mass = -1d0
     630              :                end if
     631              : 
     632           11 :                s% okay_to_set_mixing_info = .false.  ! no mixing changes in set_vars after this point
     633              : 
     634           11 :                if (s% do_element_diffusion) then
     635              :                   call do_element_diffusion(s, dt, ierr)
     636            0 :                   if (failed('do_element_diffusion')) return
     637              :                   call set_vars_if_needed(s, dt, 'after element diffusion', ierr)
     638            0 :                   if (failed('set_vars_if_needed after element diffusion')) return
     639            0 :                   call finish_element_diffusion(s,dt)  ! calculates eps_diffusion from energy changes
     640              :                   if (.false.) then
     641              :                      write(*,1) 'dt*dm*eps_diffusion/total_energy_old', &
     642              :                         dt*dot_product(s% dm(1:s% nz), s% eps_diffusion(1:s% nz))/s% total_energy_old
     643              :                   end if
     644              :                end if
     645              : 
     646              :             end if
     647              : 
     648           11 :             if (s% rotation_flag .and. s% premix_omega .and. .not. s% j_rot_flag) then
     649            0 :                do_step_part2 = do_solve_omega_mix(s, 0.5d0*dt)
     650            0 :                if (do_step_part2 /= keep_going) return
     651            0 :                call set_rotation_info(s, .false., ierr)
     652            0 :                if (failed('set_rotation_info')) return
     653              :                call set_vars_if_needed(s, dt, 'after do_solve_omega_mix', ierr)
     654            0 :                if (failed('after do_solve_omega_mix')) return
     655              :             end if
     656              : 
     657           11 :             if (s% use_other_pressure) then
     658            0 :                call s% other_pressure(s% id, ierr)
     659            0 :                if (failed('other_pressure returned ierr')) return
     660              :             end if
     661              :             call set_vars_if_needed(s, dt, 'after other_pressure', ierr)
     662           11 :             if (failed('set_vars_if_needed after other_pressure')) return
     663              : 
     664              :             call check_for_extra_heat(s, ierr)
     665           11 :             if (failed('check_for_extra_heat')) return
     666              :             call set_vars_if_needed(s, dt, 'after check_for_extra_heat', ierr)
     667           11 :             if (failed('set_vars_if_needed after check_for_extra_heat')) return
     668              : 
     669           11 :             if (.not. s% have_new_cz_bdy_info) then
     670              :                call set_cz_bdy_mass(s, ierr)
     671            0 :                if (failed('set_cz_bdy_mass')) return
     672              :             end if
     673              : 
     674              :             skip_global_corr_coeff_limit = (first_try .or. &
     675           11 :                 s% model_number_for_last_retry /= s% model_number)  ! last alternative is for redo's
     676              : 
     677           11 :             s% doing_struct_burn_mix = .true.
     678           11 :             do_step_part2 = do_struct_burn_mix(s, skip_global_corr_coeff_limit)
     679           11 :             s% doing_struct_burn_mix = .false.
     680           11 :             if (do_step_part2 /= keep_going) return
     681              :             ! when reach here, have taken the step successfully
     682              :             ! but might not satisfy the implicit mdot requirements.
     683              : 
     684           11 :             mdot_action = select_mdot_action(ierr)
     685           11 :             if (failed('select_mdot_action')) return
     686           11 :             if (do_step_part2 /= keep_going) return
     687           11 :             if (mdot_action == exit_loop) exit implicit_mdot_loop
     688           11 :             if (s% trace_evolve) write(*,*) 'cycle implicit_mdot_loop'
     689              : 
     690              :          end do implicit_mdot_loop
     691              : 
     692           11 :          s% solver_iter = 0  ! to indicate that no longer doing solver iterations
     693              : 
     694           11 :          if (.not. s% RSP_flag) then
     695              :             call set_final_vars(s, dt, ierr)
     696           11 :             if (failed('set_final_vars')) return
     697           11 :             if (s% okay_to_set_mlt_vc .and. .not. s% have_mlt_vc) then
     698            1 :                s% have_mlt_vc = .true.
     699              :             end if
     700           11 :             s% okay_to_set_mlt_vc = .false.
     701              :          end if
     702              : 
     703           11 :          if (.not. okay_energy_conservation()) return
     704              : 
     705           11 :          if (s% max_timestep_hi_T_limit > 0 .and. &
     706              :                s% max_years_for_timestep /= s% hi_T_max_years_for_timestep) then
     707            0 :             if (maxval(s% T(1:nz)) >= s% max_timestep_hi_T_limit) then
     708            0 :                write(*,1) 'switch to high T max timesteps'
     709            0 :                s% max_years_for_timestep = s% hi_T_max_years_for_timestep
     710            0 :                s% max_timestep = secyer*s% max_years_for_timestep
     711              :             end if
     712              :          end if
     713              : 
     714           11 :          call set_luminosity_by_category(s)  ! final values for use in selecting timestep
     715           11 :          call set_power_info(s)
     716              : 
     717           11 :          s% total_angular_momentum = total_angular_momentum(s)
     718              : 
     719              :          ! do_report needs to be called now because checks for redo and retry rely on
     720              :          ! data stored by do_report.
     721              :          call do_report(s, ierr)
     722           11 :          if (failed('do_report')) return
     723           11 :          call set_phase_of_evolution(s)
     724              : 
     725           11 :          call system_clock(time0,clock_rate)
     726           11 :          s% current_system_clock_time = time0
     727              :          s% total_elapsed_time = &
     728           33 :             dble(time0 - s% starting_system_clock_time)/dble(clock_rate)
     729              : 
     730              : 
     731              :          contains
     732              : 
     733              : 
     734          132 :          logical function failed(str)
     735              :             character (len=*), intent(in) :: str
     736          121 :             if (ierr == 0) then
     737          121 :                failed = .false.
     738              :                return
     739              :             end if
     740            0 :             failed = .true.
     741            0 :             do_step_part2 = retry
     742            0 :             if (s% report_ierr) write(*, *) 'do_step_part2: ' // trim(str)
     743            0 :             s% result_reason = nonzero_ierr
     744           11 :          end function failed
     745              : 
     746              : 
     747           11 :          subroutine setup_for_implicit_mdot_loop
     748              : 
     749           11 :             ignored_first_step = .false.
     750              : 
     751           11 :             mstar_dot = 0
     752           11 :             w_div_w_crit = -1
     753           11 :             surf_omega_div_omega_crit_limit = s% surf_omega_div_omega_crit_limit
     754           11 :             mdot_redo_cnt = 0
     755           11 :             max_mdot_redo_cnt = s% max_mdot_redo_cnt
     756              : 
     757           11 :             max_wind_mdot = 10*Msun/secyer
     758           11 :             have_too_large_wind_mdot = .false.
     759           11 :             have_too_small_wind_mdot = .false.
     760           11 :             too_large_wind_mdot = 0
     761           11 :             too_small_wind_mdot = 0
     762              : 
     763           11 :             explicit_mdot = s% mstar_dot
     764              : 
     765           11 :             was_in_implicit_wind_limit = s% was_in_implicit_wind_limit
     766           11 :             if(abs(s% mstar_dot_old) > 0) then
     767              :                if (was_in_implicit_wind_limit .and. &
     768            0 :                    s% generations == 2 .and. &
     769              :                    abs((s% mstar_dot-s% mstar_dot_old)/s% mstar_dot_old)+1 > &
     770              :                    s% mdot_revise_factor) then
     771            0 :                    write(*,*) "Skipping first step in implicit mdot"
     772            0 :                    s% mstar_dot = s% mstar_dot_old
     773            0 :                    mdot_redo_cnt = 1
     774            0 :                    ignored_first_step = .true.
     775              :                end if
     776              :             end if
     777              : 
     778           11 :             abs_mstar_delta = 0
     779              : 
     780           11 :             iwind_redo_cnt = 0
     781           11 :             iwind_max_redo_cnt = s% max_tries_for_implicit_wind
     782           11 :             iwind_tolerance = s% iwind_tolerance
     783           11 :             iwind_lambda = s% iwind_lambda
     784              : 
     785           11 :          end subroutine setup_for_implicit_mdot_loop
     786              : 
     787              : 
     788           11 :          integer function select_mdot_action(ierr)
     789              :             use hydro_rotation, only: set_surf_avg_rotation_info
     790              :             integer, intent(out) :: ierr
     791              :             include 'formats'
     792              : 
     793           11 :             select_mdot_action = exit_loop
     794           11 :             if (s% mstar_dot == 0 .or. max_mdot_redo_cnt <= 0) return
     795              :                ! the test of max_mdot_redo_cnt <= 0 belongs here.  it was erroneously placed
     796              :                ! after possible select_mdot_action = cycle_loop, return.  BP: Apr 25, 2021.
     797              : 
     798            0 :             if (iwind_redo_cnt < iwind_max_redo_cnt .and. iwind_lambda > 0d0) then
     799              :                ! check mdot calculated at end of step
     800              :                call get_phot_info(s, dummy1, dummy2, dummy3, ph_L, dummy4, dummy5, dummy6, dummy7, dummy8, ph_k)
     801            0 :                call set_mdot(s, ph_L, s% mstar, s% Teff, ierr)
     802            0 :                if (ierr /= 0) then
     803            0 :                   do_step_part2 = retry
     804            0 :                   s% result_reason = nonzero_ierr
     805            0 :                   if (s% report_ierr) write(*, *) 'do_step_part2: set_mdot ierr'
     806            0 :                   return
     807              :                end if
     808            0 :                implicit_mdot = s% mstar_dot
     809            0 :                if (abs(explicit_mdot - implicit_mdot) > &
     810              :                      abs(implicit_mdot)*iwind_tolerance) then
     811            0 :                   call set_current_to_old(s)  ! preparing for redo
     812              :                   s% mstar_dot = explicit_mdot + &
     813            0 :                      iwind_lambda*(implicit_mdot - explicit_mdot)
     814            0 :                   explicit_mdot = s% mstar_dot
     815            0 :                   do_step_part2 = prepare_for_new_try(s)
     816            0 :                   if (do_step_part2 /= keep_going) return
     817            0 :                   iwind_redo_cnt = iwind_redo_cnt + 1
     818            0 :                   select_mdot_action = cycle_loop
     819            0 :                   return
     820              :                end if
     821            0 :                iwind_max_redo_cnt = iwind_redo_cnt  ! done with implicit wind
     822              :             end if
     823              : 
     824            0 :             if (.not. s% rotation_flag) then
     825           11 :                select_mdot_action = exit_loop
     826              :                return
     827              :             end if
     828              : 
     829              :             ! check for omega > omega_crit
     830              : 
     831            0 :             mstar_dot_prev = mstar_dot
     832            0 :             mstar_dot = s% mstar_dot
     833            0 :             wind_mdot = -s% mstar_dot
     834              : 
     835            0 :             if (mdot_redo_cnt == 1 .or. ignored_first_step) then
     836              :                ! this is the 1st correction to mdot
     837            0 :                r_phot = sqrt(s% L(1)/(pi*crad*clight*pow4(s% Teff)))
     838            0 :                kh_timescale = eval_kh_timescale(s% cgrav(1), s% mstar, r_phot, s% L(1))
     839            0 :                dmskhf = s% rotational_mdot_kh_fac
     840            0 :                dmsfac = s% rotational_mdot_boost_fac
     841            0 :                max_wind_mdot = dmskhf*s% mstar/kh_timescale
     842            0 :                if (wind_mdot > 0) max_wind_mdot = min(max_wind_mdot, wind_mdot*dmsfac)
     843              :             end if
     844              : 
     845            0 :             w_div_w_crit_prev = w_div_w_crit
     846              :             ! check the new w_div_w_crit to make sure not too large
     847            0 :             call set_surf_avg_rotation_info(s)
     848            0 :             w_div_w_crit = s% w_div_w_crit_avg_surf
     849              : 
     850            0 :             if (wind_mdot >= max_wind_mdot) then
     851            0 :                if (mdot_redo_cnt == 0) then
     852            0 :                   write(*,*) 'cannot fix omega >= omega_crit -- mass loss already at max'
     853              :                else
     854            0 :                   write(*,2) 'retry: at max wind mass loss', s% model_number, &
     855            0 :                      log10(max_wind_mdot/(Msun/secyer))
     856            0 :                   do_step_part2 = retry
     857            0 :                   s% result_reason = nonzero_ierr
     858            0 :                   return
     859              :                end if
     860            0 :                write(*,'(A)')
     861            0 :                if (w_div_w_crit > surf_omega_div_omega_crit_limit) then
     862            0 :                   write(*,1) 'retry: w_div_w_crit > surf_omega_div_omega_crit_limit', &
     863            0 :                      w_div_w_crit, surf_omega_div_omega_crit_limit
     864            0 :                   do_step_part2 = retry
     865            0 :                   s% result_reason = nonzero_ierr
     866            0 :                   return
     867              :                end if
     868           11 :                select_mdot_action = exit_loop
     869              :                return
     870              :             end if
     871              : 
     872              :             ! NOTE: we assume that if surface omega/omega_crit (w_div_w_crit) is too large,
     873              :             ! then mass loss needs to be made larger to fix the problem.
     874              :             ! if that assumption is wrong,
     875              :             ! i.e. if bigger mass loss makes w_div_w_crit worse,
     876              :             ! then in an unstable situation and will remove mass until regain stability.
     877              : 
     878              :             if (w_div_w_crit <= surf_omega_div_omega_crit_limit &
     879            0 :                   .and. mdot_redo_cnt == 0) then
     880            0 :                s% was_in_implicit_wind_limit = .false.
     881            0 :                select_mdot_action = exit_loop
     882            0 :                return
     883              :             end if
     884              : 
     885              :             if (w_div_w_crit <= surf_omega_div_omega_crit_limit &
     886            0 :                   .and. s% mstar_dot == explicit_mdot) then
     887              :                !exit implicit_mdot_loop
     888           11 :                select_mdot_action = exit_loop
     889              :                return
     890              :                ! implicit scheme reached the limit set by the explicit_mdot;
     891              :                ! no problem; no redo required.
     892              :             end if
     893              : 
     894            0 :             s% was_in_implicit_wind_limit = .true.
     895              : 
     896            0 :             if (dt/secyer < s% min_years_dt_for_redo_mdot) then
     897              :                if (.true.) write(*,1) &
     898            0 :                   'dt too small for fix to fix w > w_crit; min_years_dt_for_redo_mdot', &
     899            0 :                   dt/secyer, s% min_years_dt_for_redo_mdot
     900            0 :                select_mdot_action = exit_loop
     901            0 :                return
     902              :             end if
     903              : 
     904              :             ! if get here, need to revise mdot to fix w_div_w_crit
     905              : 
     906            0 :             mdot_redo_cnt = mdot_redo_cnt + 1
     907              : 
     908            0 :             if (mdot_redo_cnt == 1) then  ! this is the 1st correction to mdot
     909              : 
     910            0 :                call set_current_to_old(s)
     911            0 :                do_step_part2 = prepare_for_new_try(s)
     912            0 :                if (do_step_part2 /= keep_going) return
     913              : 
     914            0 :                have_too_small_wind_mdot = .true.
     915            0 :                too_small_wind_mdot = wind_mdot
     916            0 :                if (s% mstar_dot < 0) then
     917            0 :                   s% mstar_dot = mstar_dot*s% mdot_revise_factor
     918              :                else
     919            0 :                   s% mstar_dot = mstar_dot/s% mdot_revise_factor
     920              :                end if
     921              : 
     922            0 :                if (-s% mstar_dot > max_wind_mdot) s% mstar_dot = -max_wind_mdot
     923              : 
     924            0 :                write(*,3) 'w > w_crit: revise mdot and redo', &
     925            0 :                   s% model_number, mdot_redo_cnt, w_div_w_crit, &
     926            0 :                   log10(abs(s% mstar_dot)/(Msun/secyer))
     927              : 
     928              :                !abs_mstar_delta = max(abs(s% mstar_dot), 1d-6*Msun/secyer)
     929            0 :                abs_mstar_delta = abs(s% mstar_dot)
     930              : 
     931            0 :                s% need_to_setvars = .true.
     932            0 :                select_mdot_action = cycle_loop
     933            0 :                return
     934              : 
     935            0 :             else if (mdot_redo_cnt == 2 .and. ignored_first_step) then
     936            0 :                abs_mstar_delta = abs(s% mstar_dot_old)
     937              :             end if
     938              : 
     939              :             ! have already done at least one correction -- check if okay now
     940              :             if (w_div_w_crit <= surf_omega_div_omega_crit_limit .and. &
     941            0 :                   have_too_small_wind_mdot .and. &
     942              :                   abs((wind_mdot-too_small_wind_mdot)/wind_mdot) < &
     943              :                      s% surf_omega_div_omega_crit_tol) then
     944            0 :                write(*,3) 'OKAY', s% model_number, mdot_redo_cnt, w_div_w_crit, &
     945            0 :                   log10(abs(s% mstar_dot)/(Msun/secyer))
     946            0 :                write(*,'(A)')
     947            0 :                select_mdot_action = exit_loop  ! in bounds so accept it
     948            0 :                return
     949              :             end if
     950              : 
     951            0 :             if (mdot_redo_cnt >= max_mdot_redo_cnt) then
     952            0 :                if (max_mdot_redo_cnt > 0) then
     953            0 :                   write(*,3) 'failed to fix w > w_crit: too many tries', &
     954            0 :                      s% model_number, mdot_redo_cnt, w_div_w_crit, &
     955            0 :                      log10(abs(s% mstar_dot)/(Msun/secyer))
     956            0 :                   do_step_part2 = retry
     957            0 :                   s% result_reason = nonzero_ierr
     958            0 :                   return
     959              :                end if
     960           11 :                select_mdot_action = exit_loop
     961              :                return
     962              :             end if
     963              : 
     964              :             if (w_div_w_crit > surf_omega_div_omega_crit_limit &
     965              :                   .and. w_div_w_crit_prev >= surf_omega_div_omega_crit_limit &
     966            0 :                   .and. -mstar_dot >= max_wind_mdot) then
     967            0 :                write(*,3) 'failed to fix w > w_crit', &
     968            0 :                   s% model_number, mdot_redo_cnt, w_div_w_crit, &
     969            0 :                   log10(abs(s% mstar_dot)/(Msun/secyer))
     970            0 :                write(*,'(A)')
     971            0 :                do_step_part2 = retry
     972            0 :                s% result_reason = nonzero_ierr
     973            0 :                return
     974              :             end if
     975              : 
     976            0 :             if (w_div_w_crit >= surf_omega_div_omega_crit_limit) then  ! wind too small
     977              :                !write(*,*) "entering too small wind mdot"
     978            0 :                if (.not. have_too_small_wind_mdot) then
     979              :                   !write(*,*) "setting too small wind mdot"
     980            0 :                   too_small_wind_mdot = wind_mdot
     981            0 :                   have_too_small_wind_mdot = .true.
     982            0 :                else if (wind_mdot > too_small_wind_mdot) then
     983              :                   !write(*,*) "changing too small wind mdot"
     984            0 :                   too_small_wind_mdot = wind_mdot
     985              :                end if
     986            0 :             else if (w_div_w_crit < surf_omega_div_omega_crit_limit) then  ! wind too large
     987              :                !write(*,*) "entering too large wind mdot"
     988            0 :                if (.not. have_too_large_wind_mdot) then
     989              :                   !write(*,*) "setting too large wind mdot"
     990            0 :                   too_large_wind_mdot = wind_mdot
     991            0 :                   have_too_large_wind_mdot = .true.
     992            0 :                else if (wind_mdot < too_large_wind_mdot) then
     993              :                   !write(*,*) "changing too large wind mdot"
     994            0 :                   too_large_wind_mdot = wind_mdot
     995              :                end if
     996              :             end if
     997              : 
     998            0 :             call set_current_to_old(s)
     999            0 :             do_step_part2 = prepare_for_new_try(s)
    1000            0 :             if (do_step_part2 /= keep_going) return
    1001              : 
    1002            0 :             if (have_too_large_wind_mdot .and. have_too_small_wind_mdot) then
    1003            0 :                if (abs((too_large_wind_mdot-too_small_wind_mdot)/too_large_wind_mdot) &
    1004              :                    < s% surf_omega_div_omega_crit_tol) then
    1005            0 :                   write(*,*) "too_large_wind_mdot good enough, using it"
    1006            0 :                   s% mstar_dot = -too_large_wind_mdot
    1007              :                else
    1008              :                   ! have bracketing mdots; bisect for next one.
    1009            0 :                   s% mstar_dot = -0.5d0*(too_large_wind_mdot + too_small_wind_mdot)
    1010            0 :                   write(*,3) 'fix w > w_crit: bisect mdots and redo', &
    1011            0 :                      s% model_number, mdot_redo_cnt, w_div_w_crit, &
    1012            0 :                      log10(abs(s% mstar_dot)/(Msun/secyer)), &
    1013            0 :                      log10(abs(too_large_wind_mdot)/(Msun/secyer)), &
    1014            0 :                      log10(abs(too_small_wind_mdot)/(Msun/secyer))
    1015              :                end if
    1016              : 
    1017              :             else  ! still have wind too small so boost it again
    1018            0 :                if (have_too_small_wind_mdot) then
    1019            0 :                   if (mod(mdot_redo_cnt,2) == 1) then
    1020            0 :                      boost = s% implicit_mdot_boost
    1021              :                      ! increase mass loss
    1022            0 :                      mstar_dot_nxt = mstar_dot - boost*abs_mstar_delta
    1023              :                   else
    1024            0 :                      if (mstar_dot < 0) then  ! increase mass loss
    1025            0 :                         mstar_dot_nxt = mstar_dot*s% mdot_revise_factor
    1026              :                      else  ! decrease mass gain
    1027            0 :                         mstar_dot_nxt = mstar_dot/s% mdot_revise_factor
    1028              :                      end if
    1029              :                   end if
    1030              :                else
    1031            0 :                   if (mod(mdot_redo_cnt,2) == 1) then
    1032            0 :                      boost = s% implicit_mdot_boost
    1033              :                      ! decrease mass loss
    1034            0 :                      mstar_dot_nxt = mstar_dot + boost*abs_mstar_delta
    1035              :                   else
    1036            0 :                      if (mstar_dot < 0) then  ! decrease mass loss
    1037            0 :                         mstar_dot_nxt = mstar_dot/s% mdot_revise_factor
    1038              :                      else  ! increase mass gain
    1039            0 :                         mstar_dot_nxt = mstar_dot*s% mdot_revise_factor
    1040              :                      end if
    1041              :                   end if
    1042              :                end if
    1043            0 :                if (mstar_dot_prev /= explicit_mdot) &
    1044            0 :                   mstar_dot_nxt = min(mstar_dot_nxt, explicit_mdot)
    1045            0 :                if (mstar_dot_nxt == explicit_mdot) &
    1046            0 :                   write(*,*) "implicit mdot: reached explicit_mdot"
    1047            0 :                s% mstar_dot = mstar_dot_nxt
    1048            0 :                if (-s% mstar_dot > max_wind_mdot) s% mstar_dot = -max_wind_mdot
    1049              :                !abs_mstar_delta = max(abs_mstar_delta, abs(s% mstar_dot))
    1050            0 :                write(*,3) 'fix w > w_crit: change mdot and redo', &
    1051            0 :                   s% model_number, mdot_redo_cnt, w_div_w_crit, &
    1052            0 :                   log10(abs(s% mstar_dot)/(Msun/secyer))
    1053              :             end if
    1054              : 
    1055           11 :             select_mdot_action = cycle_loop  ! cycle
    1056              : 
    1057           11 :          end function select_mdot_action
    1058              : 
    1059              : 
    1060              :          subroutine show_debug
    1061              :             integer :: k
    1062              :             real(dp) :: alfa, beta, gamma1, Cv, chiRho, chiT, Cp, grada, &
    1063              :                Pgas, Prad, P, opacity
    1064              :             include 'formats'
    1065              :             k = 1205
    1066              : 
    1067              :             alfa = s% dq(k-1)/(s% dq(k-1) + s% dq(k))
    1068              :             beta = 1 - alfa
    1069              : 
    1070              :             gamma1 = alfa*s% gamma1(k) + beta*s% gamma1(k-1)
    1071              :             Cv = alfa*s% Cv(k) + beta*s% Cv(k-1)
    1072              :             chiRho = alfa*s% chiRho(k) + beta*s% chiRho(k-1)
    1073              :             chiT = alfa*s% chiT(k) + beta*s% chiT(k-1)
    1074              :             Cp = alfa*s% Cp(k) + beta*s% Cp(k-1)
    1075              :             grada = alfa*s% grada(k) + beta*s% grada(k-1)
    1076              :             Pgas = alfa*s% Pgas(k) + beta*s% Pgas(k-1)
    1077              :             Prad = alfa*s% Prad(k) + beta*s% Prad(k-1)
    1078              :             P = alfa*s% Peos(k) + beta*s% Peos(k-1)
    1079              :             opacity = alfa*s% opacity(k) + beta*s% opacity(k-1)
    1080              : 
    1081              :             write(*,2) 'at end of step', s% model_number
    1082              :             write(*,2) 'gamma1', k, gamma1
    1083              :             write(*,2) 'Cv', k, Cv
    1084              :             write(*,2) 'chiRho', k, chiRho
    1085              :             write(*,2) 'chiT', k, chiT
    1086              :             write(*,2) 'Cp', k, Cp
    1087              :             write(*,2) 'grada', k, grada
    1088              :             write(*,2) 'Pgas', k, Pgas
    1089              :             write(*,2) 'Prad', k, Prad
    1090              :             write(*,2) 'P', k, P
    1091              :             write(*,2) 'opacity', k, opacity
    1092              :             write(*,2) 'L', k, s% L(k)
    1093              :             write(*,2) 'gradr', k, s% gradr(k)
    1094              :             write(*,2) 'gradr/grada', k, s% gradr(k)/grada
    1095              :             write(*,3) 'mixing_type', k, s% mixing_type(k)
    1096              :             write(*,'(A)')
    1097              : 
    1098           11 :          end subroutine show_debug
    1099              : 
    1100              : 
    1101           11 :          logical function okay_energy_conservation()
    1102              :             use rsp, only: rsp_total_energy_integrals
    1103              :             integer :: nz, k
    1104           11 :             real(dp) :: phase1_sources_and_sinks, phase2_sources_and_sinks, phase2_work, &
    1105           11 :                phase1_total_energy_from_mdot, phase2_total_energy_from_mdot, &
    1106           11 :                expected_sum_cell_others, expected_sum_cell_sources, L_theta, &
    1107           11 :                diff_total_gravitational_energy, diff_total_internal_energy, diff_total_kinetic_energy, &
    1108           11 :                diff_total_turbulent_energy, &
    1109           11 :                virial, total_radiation, L_surf, sum_cell_de, sum_cell_detrb, &
    1110           11 :                sum_cell_dke, sum_cell_dpe, sum_cell_dL, sum_cell_ergs_error, sum_cell_others, &
    1111           11 :                sum_cell_sources, sum_cell_terms, sum_cell_work, total_energy_from_pre_mixing,&
    1112           11 :                total_energy_from_fixed_m_grav
    1113              : 
    1114              :             include 'formats'
    1115              : 
    1116              : !   phase1 := from end of previous step until start of solver
    1117              : !   phase2 := from start of solver to end of step
    1118              : !
    1119              : !   total_energy_old = at beginning of phase1
    1120              : !   total_energy_start = at beginning of phase2
    1121              : !   total_energy_end = at end of phase2
    1122              : !
    1123              : !   phase1_energy_error = total_energy_start - (total_energy_old + phase1_sources_and_sinks)
    1124              : !   phase2_energy_error = total_energy_end - (total_energy_start + phase2_sources_and_sinks)
    1125              : !
    1126              : !   total_energy_sources_and_sinks = phase1_sources_and_sinks + phase2_sources_and_sinks
    1127              : !
    1128              : !   error_in_energy_conservation = total_energy_end - (total_energy_old + total_energy_sources_and_sinks)
    1129              : !
    1130              : !   equivalently, error_in_energy_conservation = phase1_energy_error + phase2_energy_error
    1131              : 
    1132              : 
    1133           11 :             okay_energy_conservation = .false.
    1134              : 
    1135           11 :             nz = s% nz
    1136           11 :             if (s% RSP_flag) then
    1137              :                call rsp_total_energy_integrals(s, &
    1138              :                   s% total_internal_energy_end, &
    1139              :                   s% total_gravitational_energy_end, &
    1140              :                   s% total_radial_kinetic_energy_end, &
    1141              :                   s% total_rotational_kinetic_energy_end, &
    1142              :                   s% total_turbulent_energy_end, &
    1143            0 :                   s% total_energy_end, total_radiation)
    1144            0 :                if (s% RSP_just_set_velocities) then  ! reset everything when 1st set velocities
    1145            0 :                   s% total_internal_energy_old = s% total_internal_energy_end
    1146            0 :                   s% total_gravitational_energy_old = s% total_gravitational_energy_end
    1147            0 :                   s% total_radial_kinetic_energy_old = s% total_radial_kinetic_energy_end
    1148            0 :                   s% total_rotational_kinetic_energy_old = s% total_rotational_kinetic_energy_end
    1149            0 :                   s% total_turbulent_energy_old = s% total_turbulent_energy_end
    1150            0 :                   s% total_energy_old = s% total_energy_end
    1151            0 :                   total_radiation = 0d0
    1152              :                end if
    1153              :             else
    1154              :                call eval_total_energy_integrals(s, &
    1155              :                   s% total_internal_energy_end, &
    1156              :                   s% total_gravitational_energy_end, &
    1157              :                   s% total_radial_kinetic_energy_end, &
    1158              :                   s% total_rotational_kinetic_energy_end, &
    1159              :                   s% total_turbulent_energy_end, &
    1160           11 :                   s% total_energy_end)
    1161              :             end if
    1162              : 
    1163           11 :             if (s% mstar_dot == 0d0) then
    1164           11 :                s% total_energy_change_from_mdot = 0d0
    1165           11 :                s% total_eps_mdot = 0d0
    1166              :             else
    1167              :                s% total_energy_change_from_mdot = &
    1168            0 :                   s% mstar_dot*dt*s% surface_cell_specific_total_energy_old
    1169            0 :                s% total_eps_mdot = dt*dot_product(s% dm(1:nz), s% eps_mdot(1:nz))
    1170              :             end if
    1171              : 
    1172        13098 :             virial = 3*sum(s% dm(1:nz)*s% Peos(1:nz)/s% rho(1:nz))
    1173           11 :             s% virial_thm_P_avg = virial
    1174              : 
    1175        13098 :             s% total_eps_grav = dt*dot_product(s% dm(1:nz), s% eps_grav_ad(1:nz)% val)
    1176              : 
    1177           11 :             if (s% u_flag .and. s% total_eps_grav /= 0d0) then
    1178            0 :                write(*,2) 'u_flag energy accounting ignores total_eps_grav', s% model_number, s% total_eps_grav
    1179            0 :                s% total_eps_grav = 0
    1180              :             end if
    1181              : 
    1182              :             ! notes from Adam:
    1183              :             ! When there are mass changes the total energy of the model changes.
    1184              :             ! We can split this change into three parts:
    1185              :             ! 1. Mass flows into or out of the model with some specific energy.
    1186              :             ! 2. There is work done at the surface of the model by pushing material past the pressure of the surface face.
    1187              :             ! 3. The mass in the model changes state. Near the surface matter changes to maintain the same rho(q) and T(q).
    1188              :             !    Below the surface regions there is a transition region where the state interpolates between fixed-m and fixed-q.
    1189              :             !    Still deeper the state is approximately maintained at fixed rho(m), T(m).
    1190              :             !
    1191              :             ! Change (1) is accounted for entirely by the term s% total_energy_change_from_mdot.
    1192              :             ! Change (2) is accounted for entirely by the term s% mdot_acoustic_surface.
    1193              :             !
    1194              :             ! Change (3) is accounted for by the term eps_mdot in the energy equation and the term
    1195              :             ! mdot_adiabatic_surface in the energy accounting.
    1196              :             !
    1197              :             ! The eps_mdot term accounts for the energy required to change the state of the matter
    1198              :             ! from its state before adjust_mass to its state after adjust_mass. Matter not present in the
    1199              :             ! model before adjust_mass is assumed to be in the same state as the surface cell, or else in the
    1200              :             ! state specified by the other_accreting_surface hook (if used). Matter not present in the model
    1201              :             ! after adjust_mass is in a state calculated by comparing the thermal and mass-loss time-scales,
    1202              :             ! and differences between this and the surface state are accounted for by the term mdot_adiabatic_surface.
    1203              :             !
    1204              :             ! By adding eps_mdot, we cause a change in energy during the Newton iterations which
    1205              :             ! cancels the change in (3). Thus eps_mdot does not enter into the energy *accounting*, just into
    1206              :             ! the energy equation. A consequence of this is that the sum
    1207              :             !
    1208              :             ! total_energy_change_from_mdot + (total energy before adjust_mass) + mdot_acoustic_surface
    1209              :             !
    1210              :             ! does not equal the total energy *after* adjust_mass and *before* the Newton iterations.
    1211              :             ! However it should equal the total energy at the end of the step.
    1212              : 
    1213              :             if (s% rotation_flag .and. &
    1214              :                   (s% use_other_torque .or. s% use_other_torque_implicit .or. &
    1215              :                      associated(s% binary_other_torque))) then
    1216              :                ! keep track of rotational kinetic energy
    1217              :             end if
    1218              : 
    1219           11 :             if (s% eps_nuc_factor == 0d0 .or. s% nonlocal_NiCo_decay_heat) then
    1220            0 :                s% total_nuclear_heating = 0d0
    1221           11 :             else if (s% op_split_burn) then
    1222            0 :                s% total_nuclear_heating = 0d0
    1223            0 :                do k = 1, nz
    1224            0 :                   if (s% T_start(k) >= s% op_split_burn_min_T) then
    1225              :                      s% total_nuclear_heating = s% total_nuclear_heating + &
    1226            0 :                         dt*s% dm(k)*s% burn_avg_epsnuc(k)
    1227              :                   else
    1228              :                      s% total_nuclear_heating = s% total_nuclear_heating + &
    1229            0 :                         dt*s% dm(k)*s% eps_nuc(k)
    1230              :                   end if
    1231              :                end do
    1232              :             else
    1233        13098 :                s% total_nuclear_heating = dt*dot_product(s% dm(1:nz), s% eps_nuc(1:nz))
    1234              :             end if
    1235              : 
    1236           11 :             if (s% RSP_flag) then
    1237            0 :                s% total_non_nuc_neu_cooling = 0d0
    1238            0 :                s% total_irradiation_heating = 0d0
    1239              :             else
    1240              :                s% total_non_nuc_neu_cooling = dt*0.5d0* &
    1241        13098 :                   sum((s% non_nuc_neu(1:nz) + s% non_nuc_neu_start(1:nz))*s% dm(1:nz))
    1242              :                s% total_irradiation_heating = &
    1243        13098 :                   dt*dot_product(s% dm(1:nz), s% irradiation_heat(1:nz))
    1244              :             end if
    1245              : 
    1246           11 :             s% total_WD_sedimentation_heating = 0d0
    1247           11 :             if (s% do_element_diffusion .and. s% do_WD_sedimentation_heating) then
    1248              :                s% total_WD_sedimentation_heating = &
    1249            0 :                   dt*dot_product(s% dm(1:nz), s% eps_WD_sedimentation(1:nz))
    1250              :             end if
    1251              : 
    1252           11 :             s% total_energy_from_diffusion = 0d0
    1253           11 :             if (s% do_element_diffusion .and. s% do_diffusion_heating) then
    1254              :                s% total_energy_from_diffusion = &
    1255            0 :                   dt*dot_product(s% dm(1:nz), s% eps_diffusion(1:nz))
    1256              :             end if
    1257              : 
    1258           11 :             total_energy_from_pre_mixing = 0d0
    1259           11 :             if (s% do_conv_premix) then
    1260              :                total_energy_from_pre_mixing = &
    1261            0 :                   dt*dot_product(s% dm(1:nz), s% eps_pre_mix(1:nz))
    1262              :             end if
    1263              : 
    1264           11 :             s% total_energy_from_phase_separation = 0d0
    1265           11 :             if (s% do_phase_separation) then
    1266              :                s% total_energy_from_phase_separation = &
    1267            0 :                   dt*dot_product(s% dm(1:nz), s% eps_phase_separation(1:nz))
    1268              :             end if
    1269              : 
    1270              :             phase2_total_energy_from_mdot = &
    1271        13098 :                dt*dot_product(s% dm(1:nz), s% eps_mdot(1:nz))
    1272              : 
    1273        13098 :             s% total_extra_heating = dt*dot_product(s% dm(1:nz), s% extra_heat(1:nz)%val)
    1274              : 
    1275           11 :             phase2_work = dt*(s% work_outward_at_surface - s% work_inward_at_center)
    1276              : 
    1277           11 :             if (.not. s% RSP_flag) then
    1278           11 :                if (s% using_velocity_time_centering .and. &
    1279              :                      s% include_L_in_velocity_time_centering) then
    1280            0 :                   L_theta = s% L_theta_for_velocity_time_centering
    1281              :                else
    1282              :                   L_theta = 1d0
    1283              :                end if
    1284           11 :                L_surf = L_theta*s% L(1) + (1d0 - L_theta)*s% L_start(1)
    1285           11 :                total_radiation = dt*(L_surf - s% L_center)
    1286              :             end if
    1287              : 
    1288              :             !note: phase1_total_energy_from_mdot = &
    1289              :             !     s% mdot_acoustic_surface &
    1290              :             !   + s% total_energy_change_from_mdot &
    1291              :             !   + s% mdot_adiabatic_surface &
    1292              :             !   - phase2_total_energy_from_mdot
    1293              : 
    1294              :             ! during the newton iterations, m_grav remains fixed,
    1295              :             ! even though the mass_corrections respond to the change in composition.
    1296              :             ! This means there is a term
    1297              :             !    -sum dm G Delta(m_grav) / r
    1298              :             ! being neglected.
    1299              :             ! after the iterations, we update m_grav before doing the energy accounting.
    1300              :             ! this changes the potential energy so we need to correct by that amount.
    1301           11 :             if (s% use_mass_corrections) then
    1302              :                total_energy_from_fixed_m_grav = &
    1303            0 :                     -dot_product(s% cgrav(1:nz)/s%r(1:nz)*(s%m_grav(1:nz)-s%m_grav_start(1:nz)), s% dm(1:nz))
    1304              :             else
    1305              :                total_energy_from_fixed_m_grav = 0
    1306              :             end if
    1307              : 
    1308              :             phase1_total_energy_from_mdot = &
    1309              :                  s% energy_change_from_do_adjust_mass_and_calculate_eps_mdot &
    1310           11 :                + s% mdot_adiabatic_surface  ! ??
    1311              : 
    1312              :             phase1_sources_and_sinks = &
    1313              :                  phase1_total_energy_from_mdot &
    1314              :                + total_energy_from_pre_mixing &
    1315              :                + s% total_energy_from_phase_separation &
    1316              :                + s% total_WD_sedimentation_heating &
    1317              :                + s% total_energy_from_diffusion &
    1318           11 :                + s% non_epsnuc_energy_change_from_split_burn
    1319              : 
    1320              :             phase2_sources_and_sinks = &
    1321              :                - total_energy_from_pre_mixing &
    1322              :                - s% total_energy_from_phase_separation &
    1323              :                - s% total_WD_sedimentation_heating &
    1324              :                - s% total_energy_from_diffusion &
    1325              :                + phase2_total_energy_from_mdot &
    1326              :                + s% total_nuclear_heating &
    1327              :                - s% total_non_nuc_neu_cooling &
    1328              :                + s% total_irradiation_heating &
    1329              :                + s% total_extra_heating &
    1330              :                - total_radiation &
    1331           11 :                - phase2_work
    1332              : 
    1333              :             s% total_energy_sources_and_sinks = &
    1334           11 :                phase1_sources_and_sinks + phase2_sources_and_sinks
    1335           11 :             if (is_bad(s% total_energy_sources_and_sinks)) then
    1336            0 :                write(*,2) 's% total_energy_sources_and_sinks', s% model_number, s% total_energy_sources_and_sinks
    1337            0 :                write(*,2) 'phase1_sources_and_sinks', s% model_number, phase1_sources_and_sinks
    1338            0 :                write(*,2) 'phase2_sources_and_sinks', s% model_number, phase2_sources_and_sinks
    1339            0 :                write(*,2) 'total_energy_from_pre_mixing', s% model_number, total_energy_from_pre_mixing
    1340            0 :                write(*,2) 's% total_WD_sedimentation_heating', s% model_number, s% total_WD_sedimentation_heating
    1341            0 :                write(*,2) 'phase2_total_energy_from_mdot', s% model_number, phase2_total_energy_from_mdot
    1342            0 :                write(*,2) 's% total_nuclear_heating', s% model_number, s% total_nuclear_heating
    1343            0 :                write(*,2) 's% total_non_nuc_neu_cooling', s% model_number, s% total_non_nuc_neu_cooling
    1344            0 :                write(*,2) 's% total_irradiation_heating', s% model_number, s% total_irradiation_heating
    1345            0 :                write(*,2) 's% total_extra_heating', s% model_number, s% total_extra_heating
    1346            0 :                write(*,2) 'phase2_work', s% model_number, phase2_work
    1347            0 :                write(*,2) 's% work_outward_at_surface', s% model_number, s% work_outward_at_surface
    1348            0 :                write(*,2) 's% work_inward_at_center', s% model_number, s% work_inward_at_center
    1349              :                !write(*,2) '', s% model_number,
    1350              :                !write(*,2) '', s% model_number,
    1351            0 :                call mesa_error(__FILE__,__LINE__,'okay_energy_conservation')
    1352              :             end if
    1353              : 
    1354              :             s% error_in_energy_conservation = &
    1355           11 :                s% total_energy_end - (s% total_energy_old + s% total_energy_sources_and_sinks)
    1356              : 
    1357           11 :             if (s% absolute_cumulative_energy_err) then
    1358              :                s% cumulative_energy_error = s% cumulative_energy_error_old + &
    1359           11 :                     abs(s% error_in_energy_conservation)
    1360              :             else
    1361              :                s% cumulative_energy_error = s% cumulative_energy_error_old + &
    1362            0 :                     s% error_in_energy_conservation
    1363              :             end if
    1364              : 
    1365           11 :             s% total_internal_energy = s% total_internal_energy_end
    1366           11 :             s% total_gravitational_energy = s% total_gravitational_energy_end
    1367           11 :             s% total_radial_kinetic_energy = s% total_radial_kinetic_energy_end
    1368           11 :             s% total_rotational_kinetic_energy = s% total_rotational_kinetic_energy_end
    1369           11 :             s% total_turbulent_energy = s% total_turbulent_energy_end
    1370           11 :             s% total_energy = s% total_energy_end
    1371              : 
    1372              :             ! provide info about non-conservation due to mass corrections
    1373           11 :             if (s% use_mass_corrections) then
    1374            0 :                write(*,2) 'INFO: use_mass_corrections incurred rel_E_err', &
    1375            0 :                           s% model_number, -total_energy_from_fixed_m_grav/s% total_energy
    1376              :             end if
    1377              : 
    1378              :             if (s% model_number == s% energy_conservation_dump_model_number &
    1379           11 :                   .and. .not. s% doing_relax) then
    1380              : 
    1381            0 :                write(*,'(A)')
    1382            0 :                write(*,2) 's% error_in_energy_conservation', s% model_number, s% error_in_energy_conservation
    1383            0 :                write(*,2) 'total_energy', s% model_number, s% total_energy
    1384            0 :                write(*,2) 'rel_E_err = error/total_energy', s% model_number, s% error_in_energy_conservation/s% total_energy
    1385            0 :                write(*,2) 'rel err phase1', s% model_number, &
    1386            0 :                   (s% total_energy_start - (s% total_energy_old + phase1_sources_and_sinks))/s% total_energy
    1387            0 :                write(*,2) 'rel err phase2', s% model_number, &
    1388            0 :                   (s% total_energy_end - (s% total_energy_start + phase2_sources_and_sinks))/s% total_energy
    1389            0 :                write(*,'(A)')
    1390            0 :                write(*,2) 's% total_energy_old', s% model_number, s% total_energy_old
    1391            0 :                write(*,2) 's% total_energy_start', s% model_number, s% total_energy_start
    1392            0 :                write(*,2) 's% total_energy_end', s% model_number, s% total_energy_end
    1393            0 :                write(*,2) 's% total_energy_sources_and_sinks', s% model_number, s% total_energy_sources_and_sinks
    1394            0 :                write(*,'(A)')
    1395              : 
    1396            0 :                if (trim(s% energy_eqn_option) == 'dedt') then
    1397              : 
    1398            0 :                   write(*,'(A)')
    1399            0 :                   write(*,*) 'for debugging phase1_sources_and_sinks'
    1400            0 :                   write(*,'(A)')
    1401            0 :                   write(*,2) 'total_energy_from_pre_mixing', s% model_number, total_energy_from_pre_mixing
    1402            0 :                   write(*,2) 's% total_WD_sedimentation_heating', s% model_number, s% total_WD_sedimentation_heating
    1403            0 :                   write(*,2) 's% total_energy_from_diffusion', s% model_number, s% total_energy_from_diffusion
    1404            0 :                   write(*,2) 's% non_epsnuc_energy_change_from_split_burn', &
    1405            0 :                               s% model_number, s% non_epsnuc_energy_change_from_split_burn
    1406            0 :                   write(*,2) 'phase2 sum cell dt*dm*eps_mdot', s% model_number, phase2_total_energy_from_mdot
    1407            0 :                   write(*,2) 'phase1_total_energy_from_mdot', s% model_number, phase1_total_energy_from_mdot
    1408            0 :                   write(*,2) 'from_do_adjust_mass_and_eps_mdot', s% model_number, &
    1409            0 :                      s% energy_change_from_do_adjust_mass_and_calculate_eps_mdot
    1410            0 :                   write(*,2) 's% mdot_acoustic_surface', s% model_number, s% mdot_acoustic_surface
    1411            0 :                   write(*,2) 's% mdot_adiabatic_surface', s% model_number, s% mdot_adiabatic_surface
    1412            0 :                   write(*,2) 'phase2_total_energy_from_mdot', s% model_number, phase2_total_energy_from_mdot
    1413              : 
    1414            0 :                   write(*,'(A)')
    1415            0 :                   write(*,2) 's% mdot_acoustic_surface', s% model_number, s% mdot_acoustic_surface
    1416            0 :                   write(*,2) 's% mdot_adiabatic_surface', s% model_number, s% mdot_adiabatic_surface
    1417            0 :                   write(*,2) 's% total_energy_change_from_mdot', s% model_number, s% total_energy_change_from_mdot
    1418            0 :                   write(*,2) 'phase1_sources_and_sinks', s% model_number, phase1_sources_and_sinks
    1419            0 :                   write(*,*)
    1420            0 :                   write(*,2) 'energy_start - energy_old', s% model_number, s% total_energy_start - s% total_energy_old
    1421            0 :                   write(*,2) 'err phase1_sources_and_sinks', s% model_number, &
    1422            0 :                       s% total_energy_start - (s% total_energy_old + phase1_sources_and_sinks)
    1423            0 :                   write(*,2) 'rel err phase1_sources_and_sinks', s% model_number, &
    1424            0 :                      (s% total_energy_start - (s% total_energy_old + phase1_sources_and_sinks))/s% total_energy
    1425            0 :                   write(*,'(A)')
    1426            0 :                   write(*,'(A)')
    1427              : 
    1428              : 
    1429            0 :                   write(*,*) 'for debugging phase2_sources_and_sinks'
    1430            0 :                   write(*,'(A)')
    1431              : 
    1432            0 :                   write(*,2) 's% total_nuclear_heating', s% model_number, s% total_nuclear_heating
    1433            0 :                   write(*,2) 's% total_non_nuc_neu_cooling', s% model_number, s% total_non_nuc_neu_cooling
    1434            0 :                   write(*,2) 's% total_irradiation_heating', s% model_number, s% total_irradiation_heating
    1435            0 :                   write(*,2) 's% total_extra_heating', s% model_number, s% total_extra_heating
    1436            0 :                   write(*,'(A)')
    1437            0 :                   write(*,2) 'total_energy_from_pre_mixing', s% model_number, total_energy_from_pre_mixing
    1438            0 :                   write(*,2) 's% total_WD_sedimentation_heating', s% model_number, s% total_WD_sedimentation_heating
    1439            0 :                   write(*,2) 's% total_energy_from_diffusion', s% model_number, s% total_energy_from_diffusion
    1440            0 :                   write(*,'(A)')
    1441            0 :                   write(*,2) 's% total_energy_change_from_mdot', s% model_number, s% total_energy_change_from_mdot
    1442            0 :                   write(*,2) 's% mdot_acoustic_surface', s% model_number, s% mdot_acoustic_surface
    1443            0 :                   write(*,2) 's% mdot_adiabatic_surface', s% model_number, s% mdot_adiabatic_surface
    1444              :                  ! write(*,2) 'phase2_total_energy_from_mdot', s% model_number, phase2_total_energy_from_mdot
    1445            0 :                   write(*,'(A)')
    1446            0 :                   write(*,2) 'phase2_work', s% model_number, phase2_work
    1447            0 :                   write(*,2) 'total_radiation', s% model_number, total_radiation
    1448            0 :                   write(*,2) 's% non_epsnuc_energy_change_from_split_burn', s% model_number, &
    1449            0 :                      s% non_epsnuc_energy_change_from_split_burn
    1450            0 :                   write(*,'(A)')
    1451              : 
    1452            0 :                   write(*,2) 's% work_outward_at_surface', s% model_number, s% work_outward_at_surface
    1453            0 :                   write(*,2) 's% work_inward_at_center', s% model_number, s% work_inward_at_center
    1454            0 :                   write(*,2) 'L_surf', s% model_number, L_surf
    1455            0 :                   write(*,2) 'L_center', s% model_number, s% L_center
    1456            0 :                   write(*,'(A)')
    1457              : 
    1458            0 :                   sum_cell_dL = dt*dot_product(s% dm(1:nz), s% dL_dm(1:nz))
    1459            0 :                   sum_cell_sources = dt*dot_product(s% dm(1:nz), s% energy_sources(1:nz))
    1460            0 :                   sum_cell_others = dt*dot_product(s% dm(1:nz), s% energy_others(1:nz))
    1461            0 :                   sum_cell_work = dt*dot_product(s% dm(1:nz), s% dwork_dm(1:nz))
    1462            0 :                   sum_cell_detrb = dt*dot_product(s% dm(1:nz), s% detrbdt(1:nz))
    1463            0 :                   sum_cell_dke = dt*dot_product(s% dm(1:nz), s% dkedt(1:nz))
    1464            0 :                   sum_cell_dpe = dt*dot_product(s% dm(1:nz), s% dpedt(1:nz))
    1465            0 :                   sum_cell_de = dt*dot_product(s% dm(1:nz), s% dedt(1:nz))
    1466              :                   sum_cell_terms = &
    1467              :                      - sum_cell_dL + sum_cell_sources + sum_cell_others - sum_cell_work &
    1468            0 :                      - sum_cell_detrb - sum_cell_dke - sum_cell_dpe - sum_cell_de
    1469            0 :                   sum_cell_terms = -sum_cell_terms  ! to make it the same sign as sum_cell_ergs_error
    1470            0 :                   sum_cell_ergs_error = sum(s% ergs_error(1:nz))
    1471              : 
    1472              :                   expected_sum_cell_others = &
    1473              :                      - total_energy_from_pre_mixing &
    1474              :                      - s% total_energy_from_phase_separation &
    1475              :                      - s% total_WD_sedimentation_heating &
    1476            0 :                      - s% total_energy_from_diffusion
    1477              :                   expected_sum_cell_sources = &
    1478              :                        phase2_total_energy_from_mdot &
    1479              :                      + s% total_nuclear_heating &
    1480              :                      - s% total_non_nuc_neu_cooling &
    1481              :                      + s% total_irradiation_heating &
    1482            0 :                      + s% total_extra_heating
    1483              : 
    1484              :                   !write(*,2) 'rel err sum all cell terms', s% model_number, &
    1485              :                   !   (phase2_sources_and_sinks - &
    1486              :                   !      (sum_cell_others + sum_cell_sources + sum_cell_dL + sum_cell_work))/s% total_energy
    1487            0 :                   write(*,2) 'rel err sum_cell_others', s% model_number, &
    1488            0 :                      (sum_cell_others - expected_sum_cell_others)/s% total_energy, &
    1489            0 :                      sum_cell_others, expected_sum_cell_others
    1490            0 :                   write(*,2) 'rel err sum_cell_sources', s% model_number, &
    1491            0 :                      (sum_cell_sources - expected_sum_cell_sources)/s% total_energy, &
    1492            0 :                      sum_cell_sources, expected_sum_cell_sources
    1493            0 :                   write(*,2) 'rel err sum_cell_dL', s% model_number, &
    1494            0 :                      (sum_cell_dL - total_radiation)/s% total_energy, sum_cell_dL, total_radiation
    1495            0 :                   write(*,2) 'rel err sum_cell_work', s% model_number, &
    1496            0 :                      (sum_cell_work - phase2_work)/s% total_energy, sum_cell_work, phase2_work
    1497            0 :                   write(*,'(A)')
    1498              : 
    1499              :                   diff_total_internal_energy = &
    1500            0 :                      s% total_internal_energy_end - s% total_internal_energy_start
    1501              :                   diff_total_gravitational_energy = &
    1502            0 :                      s% total_gravitational_energy_end - s% total_gravitational_energy_start
    1503              :                   diff_total_kinetic_energy = &
    1504            0 :                      s% total_radial_kinetic_energy_end - s% total_radial_kinetic_energy_start
    1505              :                   !diff_total_rotational_kinetic_energy = &
    1506              :                   !   s% total_rotational_kinetic_energy_end - s% total_rotational_kinetic_energy_start
    1507              :                   diff_total_turbulent_energy = &
    1508            0 :                      s% total_turbulent_energy_end - s% total_turbulent_energy_start
    1509              : 
    1510            0 :                   write(*,2) 'phase2 rel err sum_cell_de', s% model_number, &
    1511            0 :                      (sum_cell_de - diff_total_internal_energy)/s% total_energy, &
    1512            0 :                      sum_cell_de, diff_total_internal_energy
    1513            0 :                   write(*,2) 'phase2 rel err sum_cell_dpe', s% model_number, &
    1514            0 :                      (sum_cell_dpe - diff_total_gravitational_energy)/s% total_energy, &
    1515            0 :                      sum_cell_dpe, diff_total_gravitational_energy
    1516            0 :                   write(*,2) 'phase2 rel err sum_cell_dke', s% model_number, &
    1517            0 :                      (sum_cell_dke - diff_total_kinetic_energy)/s% total_energy, &
    1518            0 :                      sum_cell_dke, diff_total_kinetic_energy
    1519              :                   !write(*,2) 'rel err ', s% model_number, &
    1520              :                   !   ( - diff_total_rotational_kinetic_energy)/s% total_energy, &
    1521              :                   !   , diff_total_rotational_kinetic_energy
    1522            0 :                   write(*,2) 'rel err sum_cell_detrb', s% model_number, &
    1523            0 :                      (sum_cell_detrb - diff_total_turbulent_energy)/s% total_energy, &
    1524            0 :                      sum_cell_detrb, diff_total_turbulent_energy
    1525            0 :                   write(*,'(A)')
    1526              : 
    1527              : 
    1528            0 :                   write(*,2) 'expected rel sum_cell_ergs_error', s% model_number, &
    1529            0 :                      sum_cell_ergs_error/s% total_energy, &
    1530            0 :                      sum_cell_ergs_error, s% total_energy
    1531            0 :                   write(*,2) 'actual rel err phase2_sources_and_sinks', s% model_number, &
    1532            0 :                      (s% total_energy_end - (s% total_energy_start + phase2_sources_and_sinks))/s% total_energy
    1533            0 :                   write(*,2) 'actual/expected', s% model_number, &
    1534            0 :                      (s% total_energy_end - (s% total_energy_start + phase2_sources_and_sinks))/sum_cell_ergs_error
    1535            0 :                   write(*,2) 'total rel_E_err', s% model_number, &
    1536            0 :                      s% error_in_energy_conservation/s% total_energy, &
    1537            0 :                      s% error_in_energy_conservation, s% total_energy
    1538            0 :                   write(*,'(A)')
    1539              :                end if
    1540              : 
    1541            0 :                call mesa_error(__FILE__,__LINE__,'okay_energy_conservation')
    1542              : 
    1543              :             end if
    1544              : 
    1545              : 
    1546           11 :             if (is_bad_num(s% error_in_energy_conservation)) then
    1547            0 :                write(*,2) 's% error_in_energy_conservation', &
    1548            0 :                   s% model_number, s% error_in_energy_conservation
    1549            0 :                write(*,2) 's% total_energy_end', &
    1550            0 :                   s% model_number, s% total_energy_end
    1551            0 :                write(*,2) 's% total_energy_change_from_mdot', &
    1552            0 :                   s% model_number, s% total_energy_change_from_mdot
    1553            0 :                write(*,2) 's% total_energy_start', &
    1554            0 :                   s% model_number, s% total_energy_start
    1555            0 :                write(*,2) 's% total_energy_sources_and_sinks', &
    1556            0 :                   s% model_number, s% total_energy_sources_and_sinks
    1557            0 :                write(*,2) 's% total_nuclear_heating', s% model_number, s% total_nuclear_heating
    1558            0 :                write(*,2) 's% total_non_nuc_neu_cooling', s% model_number, s% total_non_nuc_neu_cooling
    1559            0 :                write(*,2) 's% total_irradiation_heating', s% model_number, s% total_irradiation_heating
    1560            0 :                write(*,2) 's% total_extra_heating', s% model_number, s% total_extra_heating
    1561            0 :                write(*,2) 'dt*L_surf', s% model_number, dt*L_surf
    1562            0 :                write(*,2) 'dt*L_center', s% model_number, dt*s% L_center
    1563            0 :                write(*,2) 'L_surf', s% model_number, L_surf
    1564            0 :                write(*,2) 's% Fr(1)', s% model_number, s% Fr(1)
    1565            0 :                write(*,2) 's% Lc(1)', s% model_number, s% Lc(1)
    1566            0 :                write(*,2) 's% Lt(1)', s% model_number, s% Lt(1)
    1567            0 :                write(*,2) 'sum L', s% model_number, s% Fr(1)*pi4*s% r(1)*s% r(1)+s% Lc(1)+s% Lt(1)
    1568            0 :                okay_energy_conservation = .false.
    1569            0 :                call mesa_error(__FILE__,__LINE__,'okay_energy_conservation')
    1570            0 :                return
    1571              :             end if
    1572              : 
    1573           11 :             if (is_bad_num(s% cumulative_energy_error)) then
    1574            0 :                write(*,2) 's% cumulative_energy_error', &
    1575            0 :                   s% model_number, s% cumulative_energy_error
    1576            0 :                write(*,2) 's% cumulative_energy_error_old', &
    1577            0 :                   s% model_number, s% cumulative_energy_error_old
    1578            0 :                write(*,2) 's% error_in_energy_conservation', &
    1579            0 :                   s% model_number, s% error_in_energy_conservation
    1580            0 :                write(*,2) 's% total_energy_sources_and_sinks', &
    1581            0 :                   s% model_number, s% total_energy_sources_and_sinks
    1582            0 :                write(*,2) 's% total_nuclear_heating', s% model_number, s% total_nuclear_heating
    1583            0 :                write(*,2) 's% total_non_nuc_neu_cooling', s% model_number, s% total_non_nuc_neu_cooling
    1584            0 :                write(*,2) 's% total_irradiation_heating', s% model_number, s% total_irradiation_heating
    1585            0 :                write(*,2) 's% total_extra_heating', s% model_number, s% total_extra_heating
    1586            0 :                write(*,2) 's% work_inward_at_center', s% model_number, s% work_inward_at_center
    1587            0 :                write(*,2) 's% work_outward_at_surface', s% model_number, s% work_outward_at_surface
    1588            0 :                write(*,2) 's% L_center', s% model_number, s% L_center
    1589            0 :                okay_energy_conservation = .false.
    1590            0 :                call mesa_error(__FILE__,__LINE__,'okay_energy_conservation')
    1591            0 :                return
    1592              :             end if
    1593              : 
    1594           11 :             okay_energy_conservation = .true.
    1595              : 
    1596           11 :          end function okay_energy_conservation
    1597              : 
    1598              :       end function do_step_part2
    1599              : 
    1600              : 
    1601              :       subroutine debug(str, s)
    1602              :          use chem_def
    1603              :          character (len=*), intent(in) :: str
    1604              :          type(star_info), pointer :: s
    1605              :          integer :: k, j
    1606              :          include 'formats'
    1607              : 
    1608              :          return
    1609              : 
    1610              :          if (.not. s% rotation_flag) return
    1611              :          k = 1
    1612              :          write(*,3) trim(str) // ' s% omega(k)', k, s% model_number, s% omega(k)
    1613              :          return
    1614              :          j = 2
    1615              :          !do j=1,1 !s% species
    1616              :             if (.true. .or. s% xa(j,k) > 1d-9) &
    1617              :                write(*,1) trim(str) // ' xin(net_iso(i' // &
    1618              :                   trim(chem_isos% name(s% chem_id(j))) // '))= ', &
    1619              :                   s% xa(j,k), s% abar(k)
    1620              :          !end do
    1621              :       end subroutine debug
    1622              : 
    1623              : 
    1624           11 :       subroutine check_for_extra_heat(s, ierr)
    1625              :          use hydro_vars, only: set_vars
    1626              :          use utils_lib, only: is_bad
    1627              :          type (star_info), pointer :: s
    1628              :          integer, intent(out) :: ierr
    1629              : 
    1630           11 :          real(dp) :: start_time, end_time, left_to_inject, &
    1631           11 :             q00, qp1, qmin, qmax, qtop, qbot, extra, dt, &
    1632           11 :             target_injection_time, target_injection_ergs, &
    1633           11 :             kap_gamma, tau_gamma_sum
    1634              :          integer :: k, nz, k1
    1635              : 
    1636              :          include 'formats'
    1637              : 
    1638           11 :          ierr = 0
    1639           11 :          if (s% use_other_energy_implicit) return
    1640              : 
    1641           11 :          nz = s% nz
    1642           11 :          dt = s% dt
    1643        13098 :          do k=1,nz
    1644        13098 :             s% extra_heat(k) = s% extra_power_source
    1645              :          end do
    1646              : 
    1647           11 :          if (s% use_other_energy) then
    1648            0 :             call s% other_energy(s% id, ierr)
    1649            0 :             if (ierr /= 0) then
    1650            0 :                if (s% report_ierr) &
    1651            0 :                   write(*, *) 'check_for_extra_heat: other_energy returned ierr', ierr
    1652            0 :                return
    1653              :             end if
    1654           11 :          else if (s% inject_uniform_extra_heat /= 0) then
    1655            0 :             qp1 = 0d0
    1656            0 :             qmin = s% min_q_for_uniform_extra_heat
    1657            0 :             qmax = s% max_q_for_uniform_extra_heat
    1658            0 :             extra = s% inject_uniform_extra_heat
    1659            0 :             do k=nz,1,-1
    1660            0 :                q00 = s% q(k)
    1661            0 :                if (qp1 >= qmin .and. q00 <= qmax) then  ! all inside of region
    1662            0 :                   s% extra_heat(k) = s% extra_heat(k) + extra
    1663              :                else
    1664            0 :                   qtop = min(q00, qmax)
    1665            0 :                   qbot = max(qp1, qmin)
    1666            0 :                   if (qtop > qbot) then  ! overlaps region
    1667            0 :                      s% extra_heat(k) = s% extra_heat(k) + extra*(qtop - qbot)/s% dq(k)
    1668              :                   end if
    1669              :                end if
    1670            0 :                qp1 = q00
    1671              :             end do
    1672            0 :             s% need_to_setvars = .true.
    1673           11 :          else if (s% nonlocal_NiCo_decay_heat) then
    1674            0 :             kap_gamma = s% nonlocal_NiCo_kap_gamma
    1675            0 :             do k1=1,nz
    1676              :                tau_gamma_sum = 0
    1677            0 :                do k=k1,1,-1  ! move eps_nuc outward from k1 to extra_heat at k
    1678              :                   tau_gamma_sum = tau_gamma_sum + &
    1679            0 :                      kap_gamma*s% dm(k)/(pi4*s% rmid(k)*s% rmid(k))
    1680            0 :                   if (tau_gamma_sum >= s% dtau_gamma_NiCo_decay_heat) then
    1681              :                      s% extra_heat(k) = s% extra_heat(k) + &
    1682            0 :                         s% eps_nuc(k1)*s% dm(k1)/s% dm(k)
    1683            0 :                      exit
    1684              :                   end if
    1685              :                end do
    1686              :             end do
    1687            0 :             s% need_to_setvars = .true.
    1688              :          end if
    1689              : 
    1690              :          if (s% inject_until_reach_model_with_total_energy <= s% total_energy_initial &
    1691           11 :                .or. dt <= 0d0 .or. s% total_mass_for_inject_extra_ergs_sec <= 0d0) return
    1692              : 
    1693            0 :          start_time = s% start_time_for_inject_extra_ergs_sec
    1694            0 :          if (s% time < start_time) return
    1695              : 
    1696            0 :          if (s% duration_for_inject_extra_ergs_sec > 0) then
    1697            0 :             end_time = start_time + s% duration_for_inject_extra_ergs_sec
    1698            0 :          else if (s% max_age_in_seconds > 0) then
    1699              :             end_time = s% max_age_in_seconds
    1700            0 :          else if (s% max_age_in_days > 0) then
    1701            0 :             end_time = s% max_age_in_days*secday
    1702              :          else
    1703            0 :             end_time = s% max_age*secyer
    1704              :          end if
    1705            0 :          if (s% time_old > end_time) return
    1706              : 
    1707              :          target_injection_ergs = &
    1708            0 :             s% inject_until_reach_model_with_total_energy - s% total_energy_initial
    1709            0 :          target_injection_time = end_time - start_time
    1710            0 :          s% inject_extra_ergs_sec = target_injection_ergs/target_injection_time
    1711              :          left_to_inject = &
    1712            0 :             s% inject_until_reach_model_with_total_energy - s% total_energy_old
    1713            0 :          qp1 = 0d0
    1714            0 :          qmin = max(0d0, Msun*s% base_of_inject_extra_ergs_sec - s% M_center)/s% xmstar
    1715            0 :          qmax = min(1d0, qmin + Msun*s% total_mass_for_inject_extra_ergs_sec/s% xmstar)
    1716            0 :          extra = s% inject_extra_ergs_sec/(s% xmstar*(qmax - qmin))
    1717            0 :          if (s% time > end_time .or. s% time_old < start_time) then
    1718            0 :             extra = extra*(min(s% time, end_time) - max(s% time_old, start_time))/dt
    1719              :          end if
    1720            0 :          if (left_to_inject < extra*dt*s% xmstar*(qmax - qmin)) then
    1721            0 :             extra = left_to_inject/(dt*s% xmstar*(qmax - qmin))
    1722              :          end if
    1723            0 :          if (is_bad(extra)) then
    1724            0 :             write(*,2) 'extra', s% model_number, extra
    1725            0 :             write(*,2) 'left_to_inject', s% model_number, left_to_inject
    1726            0 :             write(*,2) 's% total_energy_old', s% model_number, s% total_energy_old
    1727            0 :             call mesa_error(__FILE__,__LINE__,'check_for_extra_heat')
    1728              :          end if
    1729            0 :          do k=nz,1,-1
    1730            0 :             q00 = s% q(k)
    1731            0 :             if (qp1 >= qmin .and. q00 <= qmax) then  ! all inside of region
    1732            0 :                s% extra_heat(k) = s% extra_heat(k) + extra
    1733              :             else
    1734            0 :                qtop = min(q00, qmax)
    1735            0 :                qbot = max(qp1, qmin)
    1736            0 :                if (qtop > qbot) then  ! overlaps region
    1737            0 :                   s% extra_heat(k) = s% extra_heat(k) + extra*(qtop - qbot)/s% dq(k)
    1738              :                end if
    1739              :             end if
    1740            0 :             qp1 = q00
    1741              :          end do
    1742              : 
    1743           11 :       end subroutine check_for_extra_heat
    1744              : 
    1745              : 
    1746           21 :       subroutine set_start_of_step_info(s, str, ierr)
    1747           11 :          use report, only: do_report
    1748              :          use hydro_vars, only: set_vars_if_needed
    1749              :          use turb_info, only: set_gradT_excess_alpha
    1750              :          use star_utils, only: min_dr_div_cs, get_remnant_mass, &
    1751              :             total_angular_momentum, eval_Ledd, set_luminosity_by_category
    1752              : 
    1753              :          type (star_info), pointer :: s
    1754              :          character (len=*), intent(in) :: str
    1755              :          integer, intent(out) :: ierr
    1756              : 
    1757              :          logical :: trace
    1758              :          integer :: nz
    1759              : 
    1760              :          include 'formats'
    1761              : 
    1762           21 :          ierr = 0
    1763           21 :          trace = s% trace_evolve
    1764           21 :          nz = s% nz
    1765              : 
    1766           21 :          if (.not. s% RSP_flag) then
    1767           21 :             call set_vars_if_needed(s, s% dt, str, ierr)
    1768           21 :             if (failed('set_vars_if_needed')) return
    1769       226659 :             s% edv(1:s% species, 1:s% nz) = 0
    1770           21 :             call set_luminosity_by_category(s)
    1771           21 :             s% total_angular_momentum = total_angular_momentum(s)
    1772           21 :             call do_report(s, ierr)
    1773           21 :             if (failed('do_report ierr')) return
    1774              :          end if
    1775              : 
    1776              :          ! save a few things from start of step that will need later
    1777           21 :          if (s% rotation_flag) then
    1778            0 :             s% surf_r_equatorial = s% r_equatorial(1)
    1779              :          else
    1780           21 :             s% surf_r_equatorial = s% r(1)
    1781              :          end if
    1782           21 :          s% starting_T_center = s% T(nz)
    1783           21 :          s% surf_csound = s% csound(1)
    1784           21 :          s% surf_rho = s% rho(1)
    1785           21 :          s% prev_Ledd = eval_Ledd(s,ierr)
    1786           21 :          if (failed('eval_Ledd ierr')) return
    1787              : 
    1788           42 :          if (.not. s% RSP_flag) then
    1789           21 :             call set_gradT_excess_alpha(s, ierr)
    1790           21 :             if (failed('set_gradT_excess_alpha ierr')) return
    1791              :          end if
    1792              : 
    1793              :          contains
    1794              : 
    1795           84 :          logical function failed(str)
    1796              :             character (len=*), intent(in) :: str
    1797           84 :             if (ierr == 0) then
    1798           84 :                failed = .false.
    1799              :                return
    1800              :             end if
    1801            0 :             failed = .true.
    1802            0 :             if (s% report_ierr) write(*, *) 'set_start_of_step_info: ' // trim(str)
    1803            0 :             s% result_reason = nonzero_ierr
    1804           21 :          end function failed
    1805              : 
    1806              :       end subroutine set_start_of_step_info
    1807              : 
    1808              : 
    1809           11 :       integer function prepare_for_new_step(s)
    1810              :          use evolve_support, only: new_generation
    1811              :          use chem_def
    1812              :          use star_utils, only: use_xh_to_set_rho_to_dm_div_dV, set_phot_info
    1813              :          use hydro_vars, only: set_vars_if_needed
    1814              : 
    1815              :          type (star_info), pointer :: s
    1816              : 
    1817              :          integer :: ierr, k
    1818           11 :          real(dp) :: force_timestep_min, force_timestep
    1819              :          logical :: trace
    1820              : 
    1821              :          include 'formats'
    1822              : 
    1823           11 :          ierr = 0
    1824           11 :          trace = s% trace_evolve
    1825              : 
    1826           11 :          prepare_for_new_step = keep_going
    1827              : 
    1828           11 :          if (s% dt_next <= 0) then
    1829            0 :             write(*, *) 's% dt_next', s% dt_next
    1830            0 :             prepare_for_new_step = terminate
    1831              :             if ((s% time >= s% max_age*secyer .and. s% max_age > 0) .or. &
    1832            0 :                 (s% time >= s% max_age_in_days*secday .and. s% max_age_in_days > 0) .or. &
    1833              :                 (s% time >= s% max_age_in_seconds .and. s% max_age_in_seconds > 0)) then
    1834            0 :                s% result_reason = result_reason_normal
    1835            0 :                s% termination_code = t_max_age
    1836              :             else
    1837            0 :                s% result_reason = dt_is_zero
    1838            0 :                s% termination_code = t_dt_is_zero
    1839              :             end if
    1840            0 :             return
    1841              :          end if
    1842              : 
    1843           11 :          if (s% dt_next < s% min_timestep_limit) then
    1844            0 :             write(*, *) 's% dt_next', s% dt_next
    1845            0 :             write(*, *) 's% min_timestep_limit', s% min_timestep_limit
    1846              :             prepare_for_new_step = terminate
    1847            0 :             s% termination_code = t_min_timestep_limit
    1848            0 :             s% result_reason = timestep_limits
    1849            0 :             return
    1850              :          end if
    1851              : 
    1852           11 :          if (s% set_rho_to_dm_div_dV .and. .not. (s% u_flag .or. s% RSP_flag)) then
    1853              :             call use_xh_to_set_rho_to_dm_div_dV(s,ierr)
    1854           11 :             if (failed('use_xh_to_set_rho_to_dm_div_dV ierr')) return
    1855              :          end if
    1856              : 
    1857           11 :          if (.not. s% RSP_flag) then  ! store mesh info for following step eps_mdot
    1858        14570 :             do k=1, s% nz
    1859       131031 :                s% prev_mesh_xa(:,k) = s% xa(:,k)
    1860        72795 :                s% prev_mesh_xh(:,k) = s% xh(:,k)
    1861        14559 :                s% prev_mesh_j_rot(k) = s% j_rot(k)
    1862        14559 :                s% prev_mesh_omega(k) = s% omega(k)
    1863        14559 :                s% prev_mesh_dq(k) = s% dq(k)
    1864        14559 :                s% prev_mesh_mlt_vc(k) = s% mlt_vc(k)
    1865        14570 :                s% prev_mesh_species_or_nvar_hydro_changed = .false.
    1866              :             end do
    1867           11 :             s% prev_mesh_nz = s% nz
    1868              :             ! also store ST information for time smoothing
    1869           11 :             if (s% have_ST_start_info) then
    1870            0 :                do k=1, s% nz
    1871            0 :                   s% prev_mesh_D_ST_start(k) = s% D_ST_start(k)
    1872            0 :                   s% prev_mesh_nu_ST_start(k) = s% nu_ST_start(k)
    1873              :                end do
    1874            0 :                s% prev_mesh_have_ST_start_info = .true.
    1875              :             else
    1876           11 :                s% prev_mesh_have_ST_start_info = .false.
    1877              :             end if
    1878              :          end if
    1879              : 
    1880           11 :          if (s% okay_to_remesh) then
    1881           11 :             if (s% rsp_flag .or. .not. s% doing_first_model_of_run) then
    1882              :                call set_start_of_step_info(s, 'before do_mesh', ierr)
    1883           10 :                if (failed('set_start_of_step_info ierr')) return
    1884           10 :                prepare_for_new_step = do_mesh(s)  ! sets s% need_to_setvars = .true. if changes anything
    1885           10 :                if (prepare_for_new_step /= keep_going) return
    1886              :             end if
    1887              :          end if
    1888              : 
    1889           11 :          call set_vars_if_needed(s, s% dt_next, 'prepare_for_new_step', ierr)
    1890           11 :          if (failed('set_vars_if_needed ierr')) return
    1891           11 :          call set_phot_info(s)  ! this sets Teff and other stuff
    1892              : 
    1893              :          call new_generation(s, ierr)
    1894           11 :          if (failed('new_generation ierr')) return
    1895           11 :          s% generations = 2
    1896              : 
    1897           11 :          if ((s% time + s% dt_next) > s% max_age*secyer .and. s% max_age > 0) then
    1898            0 :             s% dt_next = max(0d0, s% max_age*secyer - s% time)
    1899            0 :             if ( s% dt_next == 0d0 ) then
    1900            0 :                write(*,*) 'WARNING: max_age reached'
    1901            0 :                write(*,1) 's% max_age*secyer', s% max_age*secyer
    1902            0 :                write(*,1) 's% time', s% time
    1903            0 :                write(*,1) 's% max_age', s% max_age
    1904              :             end if
    1905              :          else if ((s% time + s% dt_next) > s% max_age_in_seconds &
    1906           11 :                   .and. s% max_age_in_seconds > 0) then
    1907            0 :             s% dt_next = max(0d0, s% max_age_in_seconds - s% time)
    1908              :          else if ((s% time + s% dt_next) > s% max_age_in_days*secday &
    1909           11 :                   .and. s% max_age_in_days > 0) then
    1910            0 :             s% dt_next = max(0d0, s% max_age_in_days*secday - s% time)
    1911              :          end if
    1912              : 
    1913           11 :          s% dt = s% dt_next
    1914              : 
    1915           11 :          force_timestep_min = s% force_timestep_min
    1916           11 :          if (force_timestep_min == 0) &
    1917           11 :             force_timestep_min = secyer*s% force_timestep_min_years
    1918           11 :          if (s% dt < force_timestep_min) then
    1919            0 :             s% dt = min(s% dt*s% force_timestep_min_factor, force_timestep_min)
    1920            0 :             write(*,2) 'force increase in timestep', s% model_number, s% dt
    1921              :          end if
    1922              : 
    1923           11 :          force_timestep = s% force_timestep
    1924           11 :          if (force_timestep == 0) &
    1925           11 :             force_timestep = secyer*s% force_timestep_years
    1926           11 :          if (force_timestep > 0) s% dt = force_timestep
    1927              : 
    1928           11 :          s% dt_start = s% dt
    1929           11 :          s% time_step = s% dt/secyer
    1930              : 
    1931           11 :          if (is_bad(s% dt)) then
    1932            0 :             write(*,1) 's% dt', s% dt
    1933            0 :             call mesa_error(__FILE__,__LINE__,'prepare_for_new_step')
    1934              :          end if
    1935              : 
    1936           11 :          s% retry_cnt = 0
    1937           11 :          s% redo_cnt = 0
    1938              : 
    1939           11 :          s% need_to_save_profiles_now = .false.
    1940           11 :          s% need_to_update_history_now = s% doing_first_model_of_run
    1941              : 
    1942              :          contains
    1943              : 
    1944           43 :          logical function failed(str)
    1945              :             character (len=*), intent(in) :: str
    1946           43 :             if (ierr == 0) then
    1947           43 :                failed = .false.
    1948              :                return
    1949              :             end if
    1950            0 :             failed = .true.
    1951            0 :             prepare_for_new_step = terminate
    1952            0 :             if (s% report_ierr) write(*, *) 'prepare_for_new_step: ' // trim(str)
    1953            0 :             s% result_reason = nonzero_ierr
    1954           11 :          end function failed
    1955              : 
    1956              :       end function prepare_for_new_step
    1957              : 
    1958              : 
    1959           10 :       integer function do_mesh(s)
    1960              :          use adjust_mesh, only: remesh
    1961              :          use adjust_mesh_split_merge, only: remesh_split_merge
    1962              :          use star_utils, only: start_time, update_time
    1963              :          type (star_info), pointer :: s
    1964              :          integer(i8) :: time0
    1965           10 :          real(dp) :: total
    1966              :          include 'formats'
    1967           10 :          do_mesh = keep_going
    1968           10 :          if (.not. s% okay_to_remesh) return
    1969              :          if (s% restore_mesh_on_retry &
    1970           10 :             .and. s% model_number_for_last_retry > s% model_number - s% num_steps_to_hold_mesh_after_retry) return
    1971           10 :          s% need_to_setvars = .true.
    1972           10 :          if (s% doing_timing) call start_time(s, time0, total)
    1973           10 :          if (s% use_split_merge_amr) then
    1974            0 :             do_mesh = remesh_split_merge(s)  ! sets s% need_to_setvars = .true. if changes anything
    1975            0 :             if (do_mesh /= keep_going .and. s% report_ierr) &
    1976            0 :                write(*, *) 'do_mesh: remesh_split_merge failed'
    1977           10 :          else if (.not. s% rsp_flag) then
    1978           10 :             do_mesh = remesh(s)  ! sets s% need_to_setvars = .true. if changes anything
    1979           10 :             if (do_mesh /= keep_going .and. s% report_ierr) &
    1980            0 :                write(*, *) 'do_mesh: remesh failed'
    1981              :          end if
    1982           10 :          if (s% doing_timing) call update_time(s, time0, total, s% time_remesh)
    1983           10 :          if (do_mesh /= keep_going) then
    1984            0 :             s% result_reason = adjust_mesh_failed
    1985            0 :             return
    1986              :          end if
    1987           10 :       end function do_mesh
    1988              : 
    1989              : 
    1990           11 :       integer function prepare_for_new_try(s)
    1991              :          ! return keep_going, terminate, or retry
    1992              :          ! if don't return keep_going, then set result_reason to say why.
    1993           10 :          use net_lib, only: clean_up_fractions
    1994              :          use net, only: get_screening_mode
    1995              :          use hydro_rotation, only: use_xh_to_update_i_rot
    1996              : 
    1997              :          type (star_info), pointer :: s
    1998              : 
    1999              :          integer :: ierr
    2000           11 :          real(dp) :: screening
    2001              : 
    2002              :          include 'formats'
    2003              : 
    2004              :          ierr = 0
    2005           11 :          s% result_reason = result_reason_normal
    2006           11 :          s% termination_code = 0
    2007           11 :          s% solver_iter = 0
    2008           11 :          s% solver_adjust_iter = 0
    2009              : 
    2010           11 :          s% model_number = s% model_number_old + 1
    2011              : 
    2012           11 :          prepare_for_new_try = keep_going
    2013              : 
    2014              :          s% result_reason = result_reason_normal
    2015              :          s% model_number = s% model_number_old + 1
    2016              :          s% termination_code = 0
    2017              :          s% solver_iter = 0
    2018              :          s% solver_adjust_iter = 0
    2019              : 
    2020           11 :          if (.not. s% RSP_flag) then
    2021              : 
    2022           11 :             screening = get_screening_mode(s,ierr)
    2023           11 :             if (ierr /= 0) then
    2024            0 :                write(*,*) 'bad value for screening_mode ' // trim(s% screening_mode)
    2025            0 :                prepare_for_new_try = terminate
    2026            0 :                s% termination_code = t_failed_prepare_for_new_try
    2027            0 :                return
    2028              :             end if
    2029              : 
    2030              :          end if
    2031              : 
    2032           11 :       end function prepare_for_new_try
    2033              : 
    2034              : 
    2035           11 :       integer function pick_next_timestep(id)
    2036              :          ! determine what we want for the next timestep
    2037              :          ! if don't return keep_going, then set result_reason to say why.
    2038           11 :          use timestep, only: timestep_controller
    2039              :          integer, intent(in) :: id
    2040              :          integer :: ierr
    2041              :          type (star_info), pointer :: s
    2042              :          integer :: i, j, n
    2043           11 :          real(dp) :: max_timestep, remaining_years, min_max, prev_max_years
    2044              :          include 'formats'
    2045              : 
    2046           11 :          pick_next_timestep = terminate
    2047           11 :          call get_star_ptr(id, s, ierr)
    2048           11 :          if (ierr /= 0) return
    2049              : 
    2050           11 :          if (s% RSP_flag) then
    2051            0 :             pick_next_timestep = keep_going
    2052            0 :             s% dt_next = s% RSP_dt
    2053            0 :             s% dt_next_unclipped = s% dt_next
    2054            0 :             s% why_Tlim = Tlim_max_timestep
    2055            0 :             return
    2056              :          end if
    2057              : 
    2058           11 :          if (s% trace_evolve) write(*,'(/,a)') 'pick_next_timestep'
    2059              : 
    2060           11 :          if (s% max_years_for_timestep > 0) then
    2061            0 :             max_timestep = secyer*s% max_years_for_timestep
    2062            0 :             if (s% max_timestep > 0 .and. s% max_timestep < max_timestep) &
    2063            0 :                max_timestep = s% max_timestep
    2064              :          else
    2065           11 :             max_timestep = s% max_timestep
    2066              :          end if
    2067              : 
    2068           11 :          pick_next_timestep = timestep_controller(s, max_timestep)
    2069           11 :          if (pick_next_timestep /= keep_going) then
    2070            0 :             if (s% trace_evolve) &
    2071            0 :                write(*,*) 'pick_next_timestep: timestep_controller /= keep_going'
    2072            0 :             return
    2073              :          end if
    2074              : 
    2075           11 :          s% dt_next_unclipped = s% dt_next
    2076              :                ! write out the unclipped timestep in saved models
    2077           11 :          if (s% time < 0 .and. s% time + s% dt_next > 0) then
    2078            0 :             s% dt_next = -s% time
    2079           11 :          else if ((s% time + s% dt_next) > s% max_age*secyer .and. s% max_age > 0) then
    2080            2 :             s% dt_next = max(0d0, s% max_age*secyer - s% time)
    2081              :          else if ((s% time + s% dt_next) > s% max_age_in_days*secday &
    2082            9 :                   .and. s% max_age_in_days > 0) then
    2083            0 :             s% dt_next = max(0d0, s% max_age_in_days*secday - s% time)
    2084              :          else if ((s% time + s% dt_next) > s% max_age_in_seconds &
    2085            9 :                   .and. s% max_age_in_seconds > 0) then
    2086            0 :             s% dt_next = max(0d0, s% max_age_in_seconds - s% time)
    2087            9 :          else if (s% num_adjusted_dt_steps_before_max_age > 0 .and. &
    2088              :                   s% max_years_for_timestep > 0) then
    2089            0 :             if (s% max_age > 0) then
    2090            0 :                remaining_years = s% max_age - s% star_age
    2091            0 :             else if (s% max_age_in_days > 0) then
    2092            0 :                remaining_years = (s% max_age_in_days*secday - s% time)/secyer
    2093            0 :             else if (s% max_age_in_seconds > 0) then
    2094            0 :                remaining_years = (s% max_age_in_seconds - s% time)/secyer
    2095              :             else
    2096            0 :                remaining_years = 1d99
    2097              :             end if
    2098            0 :             if (s% using_revised_max_yr_dt) &
    2099            0 :                s% max_years_for_timestep = s% revised_max_yr_dt
    2100            0 :             n = floor(remaining_years/s% max_years_for_timestep + 1d-6)
    2101            0 :             j = s% num_adjusted_dt_steps_before_max_age
    2102            0 :             if (remaining_years <= s% max_years_for_timestep) then
    2103            0 :                s% max_years_for_timestep = remaining_years
    2104            0 :                s% using_revised_max_yr_dt = .true.
    2105            0 :                s% revised_max_yr_dt = s% max_years_for_timestep
    2106            0 :                s% dt_next = s% max_years_for_timestep*secyer
    2107            0 :                write(*,3) 'remaining steps and years until max age', &
    2108            0 :                   s% model_number, 1, remaining_years
    2109            0 :             else if (n <= j) then
    2110            0 :                prev_max_years = s% max_years_for_timestep
    2111            0 :                i = floor(remaining_years/s% dt_years_for_steps_before_max_age + 1d-6)
    2112            0 :                if ((i+1d-9)*s% dt_years_for_steps_before_max_age < remaining_years) then
    2113            0 :                   s% max_years_for_timestep = remaining_years/(i+1)
    2114              :                else
    2115            0 :                   s% max_years_for_timestep = remaining_years/i
    2116              :                end if
    2117            0 :                min_max = prev_max_years*s% reduction_factor_for_max_timestep
    2118            0 :                if (s% max_years_for_timestep < min_max) &
    2119            0 :                   s% max_years_for_timestep = min_max
    2120            0 :                if (.not. s% using_revised_max_yr_dt) then
    2121            0 :                   s% using_revised_max_yr_dt = .true.
    2122            0 :                   write(*,2) 'begin reducing max timestep prior to max age', &
    2123            0 :                      s% model_number, remaining_years
    2124            0 :                else if (s% revised_max_yr_dt > s% max_years_for_timestep) then
    2125            0 :                   write(*,2) 'reducing max timestep prior to max age', &
    2126            0 :                      s% model_number, remaining_years
    2127            0 :                else if (s% max_years_for_timestep <= &
    2128              :                      s% dt_years_for_steps_before_max_age) then
    2129            0 :                   i = floor(remaining_years/s% max_years_for_timestep + 1d-6)
    2130            0 :                   write(*,3) 'remaining steps and years until max age', &
    2131            0 :                      s% model_number, i, remaining_years
    2132              :                else
    2133            0 :                   write(*,2) 'remaining_years until max age', &
    2134            0 :                      s% model_number, remaining_years
    2135              :                end if
    2136            0 :                s% revised_max_yr_dt = s% max_years_for_timestep
    2137            0 :                if (s% dt_next/secyer > s% max_years_for_timestep) &
    2138            0 :                   s% dt_next = s% max_years_for_timestep*secyer
    2139              :             end if
    2140              : 
    2141              :          end if
    2142              : 
    2143           11 :       end function pick_next_timestep
    2144              : 
    2145              : 
    2146            0 :       integer function prepare_to_redo(id)
    2147           11 :          use evolve_support, only: set_current_to_old
    2148              :          integer, intent(in) :: id
    2149              :          type (star_info), pointer :: s
    2150              :          integer :: ierr
    2151              :          include 'formats'
    2152              :          ierr = 0
    2153            0 :          call get_star_ptr(id, s, ierr)
    2154            0 :          if (ierr /= 0) then
    2155            0 :             prepare_to_redo = terminate
    2156              :             return
    2157              :          end if
    2158            0 :          s% redo_cnt = s% redo_cnt + 1
    2159            0 :          if (s% redo_limit > 0 .and. s% redo_cnt > s% redo_limit) then
    2160            0 :             write(*,2) 'redo_cnt', s% redo_cnt
    2161            0 :             write(*,2) 'redo_limit', s% redo_limit
    2162            0 :             call report_problems(s, '-- too many redos')
    2163            0 :             s% termination_code = t_redo_limit
    2164            0 :             prepare_to_redo = terminate
    2165            0 :             return
    2166              :          end if
    2167            0 :          prepare_to_redo = keep_going
    2168            0 :          if (s% trace_evolve) write(*,'(/,a)') 'prepare_to_redo'
    2169            0 :          call set_current_to_old(s)
    2170            0 :          s% need_to_setvars = .true.
    2171            0 :       end function prepare_to_redo
    2172              : 
    2173              : 
    2174            0 :       integer function prepare_to_retry(id)
    2175            0 :          use evolve_support, only: set_current_to_old
    2176              :          integer, intent(in) :: id
    2177            0 :          real(dp) :: retry_factor
    2178              :          type (star_info), pointer :: s
    2179              :          integer :: ierr, k
    2180              :          include 'formats'
    2181              : 
    2182            0 :          call get_star_ptr(id, s, ierr)
    2183            0 :          if (ierr /= 0) then
    2184            0 :             prepare_to_retry = terminate
    2185              :             return
    2186              :          end if
    2187              : 
    2188            0 :          s% need_to_setvars = .true.
    2189              : 
    2190            0 :          if (s% restore_mesh_on_retry .and. .not. s% RSP_flag) then
    2191            0 :             if (.not. s% prev_mesh_species_or_nvar_hydro_changed) then
    2192            0 :                do k=1, s% prev_mesh_nz
    2193            0 :                   s% xh_old(:,k) = s% prev_mesh_xh(:,k)
    2194            0 :                   s% xa_old(:,k) = s% prev_mesh_xa(:,k)
    2195            0 :                   s% dq_old(k) = s% prev_mesh_dq(k)
    2196            0 :                   s% omega_old(k) = s% prev_mesh_omega(k)
    2197            0 :                   s% j_rot_old(k) = s% prev_mesh_j_rot(k)
    2198            0 :                   s% mlt_vc_old(k) = s% prev_mesh_mlt_vc(k)
    2199              :                end do
    2200            0 :                call normalize_dqs(s, s% prev_mesh_nz, s% dq_old, ierr)
    2201            0 :                if (ierr /= 0) then
    2202            0 :                   prepare_to_retry = terminate
    2203              :                   return
    2204              :                end if
    2205            0 :                s% nz_old = s% prev_mesh_nz
    2206              :             end if
    2207              :          end if
    2208              : 
    2209            0 :          if (s% trace_evolve) write(*,'(/,a)') 'prepare_to_retry'
    2210              : 
    2211            0 :          s% retry_cnt = s% retry_cnt + 1
    2212            0 :          if (s% retry_limit > 0 .and. s% retry_cnt > s% retry_limit) then
    2213            0 :             s% dt_start = sqrt(s% dt*s% dt_start)
    2214            0 :             prepare_to_retry = terminate
    2215            0 :             return
    2216              :          end if
    2217              : 
    2218            0 :          prepare_to_retry = keep_going
    2219              : 
    2220            0 :          retry_factor = s% timestep_factor_for_retries
    2221            0 :          s% dt = s% dt*retry_factor
    2222            0 :          s% time_step = s% dt/secyer
    2223            0 :          if (len_trim(s% retry_message) > 0) then
    2224            0 :             if (s% retry_message_k > 0) then
    2225            0 :                write(*,'(a, 2i8)') ' retry: ' // trim(s% retry_message), s% retry_message_k, s% model_number
    2226              :             else
    2227            0 :                write(*,'(a, i8)') ' retry: ' // trim(s% retry_message), s% model_number
    2228              :             end if
    2229              :          else
    2230            0 :             write(*,'(a, i8)') ' retry', s% model_number
    2231              :             !if (.true.) call mesa_error(__FILE__,__LINE__,'failed to set retry_message')
    2232              :          end if
    2233            0 :          s% retry_message_k = 0
    2234            0 :          if (s% report_ierr) &
    2235            0 :             write(*,'(a50,2i6,3f16.6)') 'retry log10(dt/yr), log10(dt), retry_factor', &
    2236            0 :                s% retry_cnt, s% model_number, log10(s% dt*retry_factor/secyer), &
    2237            0 :                log10(s% dt*retry_factor), retry_factor
    2238            0 :          if (s% dt <= max(s% min_timestep_limit,0d0)) then
    2239            0 :             write(*,1) 'dt', s% dt
    2240            0 :             write(*,1) 'min_timestep_limit', s% min_timestep_limit
    2241            0 :             call report_problems(s, 'dt < min_timestep_limit')
    2242            0 :             prepare_to_retry = terminate
    2243            0 :             s% termination_code = t_min_timestep_limit
    2244            0 :             s% result_reason = timestep_limits
    2245            0 :             return
    2246              :          end if
    2247              : 
    2248            0 :          if (s% max_years_for_timestep > 0) &
    2249            0 :             s% max_timestep = secyer*s% max_years_for_timestep
    2250            0 :          if (s% max_timestep > 0 .and. s% dt > s% max_timestep) then
    2251            0 :             s% dt = s% max_timestep
    2252            0 :             s% time_step = s% dt/secyer
    2253              :          end if
    2254              : 
    2255            0 :          call set_current_to_old(s)
    2256              : 
    2257            0 :          s% num_retries = s% num_retries+1
    2258            0 :          if (s% num_retries > s% max_number_retries .and. s% max_number_retries >= 0) then
    2259            0 :             write(*,2) 'num_retries', s% num_retries
    2260            0 :             write(*,2) 'max_number_retries', s% max_number_retries
    2261            0 :             call report_problems(s, '-- too many retries')
    2262            0 :             s% termination_code = t_max_number_retries
    2263            0 :             prepare_to_retry = terminate; return
    2264              :          end if
    2265              : 
    2266            0 :          s% model_number_for_last_retry = s% model_number
    2267            0 :          if (s% why_Tlim == Tlim_neg_X) then
    2268              :             s% timestep_hold = s% model_number + &
    2269            0 :                max(s% retry_hold, s% neg_mass_fraction_hold)
    2270              :          else
    2271            0 :             s% timestep_hold = s% model_number + s% retry_hold
    2272              :          end if
    2273            0 :          s% why_Tlim = Tlim_retry
    2274              : 
    2275            0 :       end function prepare_to_retry
    2276              : 
    2277              : 
    2278            0 :       subroutine report_problems(s,str)
    2279              :          type (star_info), pointer :: s
    2280              :          character (len=*), intent(in) :: str
    2281            0 :          write(*,*) 'stopping because of problems ' // trim(str)
    2282            0 :       end subroutine report_problems
    2283              : 
    2284              : 
    2285           11 :       integer function finish_step(id, ierr)
    2286              :          ! returns keep_going or terminate
    2287              :          ! if don't return keep_going, then set result_reason to say why.
    2288              :          use evolve_support, only: output
    2289              :          use profile, only: do_save_profiles
    2290              :          use history, only: write_history_info
    2291              :          use utils_lib, only: free_iounit, number_iounits_allocated
    2292              :          use alloc, only: size_work_arrays
    2293              : 
    2294              :          integer, intent(in) :: id
    2295              :          integer, intent(out) :: ierr
    2296              : 
    2297              :          type (star_info), pointer :: s
    2298              :          integer, parameter :: nvals = 1, n_ivals = 0
    2299              :          integer :: nz, current_num_iounits_in_use, prev_num_iounits_in_use
    2300              :          logical :: trace, will_do_photo
    2301              : 
    2302              :          include 'formats'
    2303              : 
    2304           11 :          finish_step = terminate
    2305              : 
    2306           11 :          call get_star_ptr(id, s, ierr)
    2307           11 :          if (ierr /= 0) return
    2308              : 
    2309           11 :          nz = s% nz
    2310           11 :          trace = s% trace_evolve
    2311           11 :          prev_num_iounits_in_use = number_iounits_allocated()
    2312              : 
    2313           11 :          finish_step = keep_going
    2314           11 :          s% result_reason = result_reason_normal
    2315              : 
    2316           11 :          if (s% need_to_save_profiles_now .and. s% write_profiles_flag) then
    2317            1 :             call do_save_profiles(s, ierr)
    2318            1 :             s% need_to_save_profiles_now = .false.
    2319              :          end if
    2320              : 
    2321           11 :          call check(1)
    2322              : 
    2323           11 :          if (s% need_to_update_history_now .and. s% do_history_file) then
    2324              : 
    2325              :             call write_history_info( &
    2326            4 :                s, ierr)
    2327            4 :             if (ierr /= 0) then
    2328            0 :                finish_step = terminate
    2329            0 :                if (s% report_ierr) write(*, *) 'finish_step: write_history_info ierr', ierr
    2330            0 :                s% result_reason = nonzero_ierr
    2331            0 :                return
    2332              :             end if
    2333            4 :             s% need_to_update_history_now = .false.
    2334              :          end if
    2335              : 
    2336           11 :          call check(2)
    2337              : 
    2338           11 :          will_do_photo = .false.
    2339           11 :          if (.not. s% doing_relax) then
    2340           11 :             if(s% photo_interval > 0) then
    2341           11 :                if(mod(s% model_number, s% photo_interval) == 0) will_do_photo = .true.
    2342              :             end if
    2343           11 :             if(s% solver_save_photo_call_number > 0)then
    2344            0 :                if(s% solver_call_number == s% solver_save_photo_call_number - 1) will_do_photo = .true.
    2345              :             end if
    2346              :         end if
    2347              : 
    2348           11 :          if (will_do_photo) then
    2349              : 
    2350            0 :             call output(id, ierr)
    2351              : 
    2352            0 :             if (ierr /= 0) then
    2353            0 :                finish_step = terminate
    2354            0 :                if (s% report_ierr) write(*, *) 'finish_step: output ierr', ierr
    2355            0 :                s% result_reason = nonzero_ierr
    2356            0 :                return
    2357              :             end if
    2358              : 
    2359              :          end if
    2360              : 
    2361           11 :          call check(3)
    2362              : 
    2363           11 :          s% screening_mode_value = -1  ! force a new lookup for next step
    2364           11 :          s% doing_first_model_of_run = .false.
    2365              : 
    2366              :          contains
    2367              : 
    2368           33 :          subroutine check(i)
    2369              :             integer, intent(in) :: i
    2370              :             include 'formats'
    2371              :             !return
    2372              : 
    2373           33 :             current_num_iounits_in_use = number_iounits_allocated()
    2374           33 :             if (current_num_iounits_in_use > 3 .and. &
    2375              :                   current_num_iounits_in_use > prev_num_iounits_in_use) then
    2376            0 :                write(*,2) 's% model_number', s% model_number
    2377            0 :                write(*,2) 'prev_num_iounits_in_use', prev_num_iounits_in_use
    2378            0 :                write(*,2) 'current_num_iounits_in_use', current_num_iounits_in_use
    2379            0 :                write(*,2) 'i', i
    2380            0 :                call mesa_error(__FILE__,__LINE__,'finish_step')
    2381              :             end if
    2382           33 :             prev_num_iounits_in_use = current_num_iounits_in_use
    2383           11 :          end subroutine check
    2384              : 
    2385              :       end function finish_step
    2386              : 
    2387              : 
    2388            0 :       subroutine set_age(id, age, ierr)
    2389              :          integer, intent(in) :: id
    2390              :          real(dp), intent(in) :: age
    2391              :          integer, intent(out) :: ierr
    2392              :          type (star_info), pointer :: s
    2393              :          include 'formats'
    2394            0 :          call get_star_ptr(id, s, ierr)
    2395            0 :          if (ierr /= 0) return
    2396            0 :          write(*,1) 'set_age', age
    2397            0 :          s% time = age*secyer
    2398            0 :          s% star_age = age
    2399              :       end subroutine set_age
    2400              : 
    2401              :       end module evolve
        

Generated by: LCOV version 2.0-1