LCOV - code coverage report
Current view: top level - star/private - adjust_mass.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 5.5 % 749 41
Test Date: 2025-05-08 18:23:42 Functions: 18.8 % 16 3

            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 adjust_mass
      21              : 
      22              :       use star_private_def
      23              :       use const_def, only: dp, i8, ln10, msun, msun, secyer, one_third, four_thirds_pi
      24              :       use utils_lib
      25              : 
      26              :       implicit none
      27              : 
      28              :       private
      29              :       public :: do_adjust_mass
      30              :       public :: compute_prev_mesh_dm
      31              : 
      32              :       logical, parameter :: dbg_adjm = .false.
      33              : 
      34              :       contains
      35              : 
      36           11 :       real(dp) function compute_delta_m(s) result(delta_m)
      37              :          type (star_info), pointer :: s
      38              :          include 'formats'
      39           11 :          delta_m = s% dt*s% mstar_dot
      40              : 
      41           11 :          if (s% super_eddington_wind_mdot /= 0 .and. s% super_eddington_wind_mdot > -s% mstar_dot) then
      42              :             ! NOTE: super_eddington should not be greater than max_wind
      43            0 :             if (s% max_wind > 0 .and. &
      44              :                   s% max_wind*Msun/secyer < s% super_eddington_wind_mdot) then
      45            0 :                s% mstar_dot = -s% max_wind*Msun/secyer
      46              :             else
      47            0 :                s% mstar_dot = -s% super_eddington_wind_mdot
      48              :             end if
      49              :          else if (delta_m == 0 &
      50              :             .or. (delta_m < 0 .and. s% star_mass <= s% min_star_mass_for_loss) &
      51           11 :             .or. (delta_m > 0 .and. s% max_star_mass_for_gain > 0 &
      52              :                   .and. s% star_mass >= s% max_star_mass_for_gain)) then
      53           11 :             s% mstar_dot = 0d0
      54              :          end if
      55              : 
      56           11 :          delta_m = s% dt*s% mstar_dot
      57              : 
      58           11 :          if (is_bad(s% dt)) then
      59            0 :             write(*,1) 's% dt', s% dt
      60            0 :             call mesa_error(__FILE__,__LINE__,'compute_delta_m')
      61              :          end if
      62              : 
      63           11 :          if (is_bad(s% mstar_dot)) then
      64            0 :             write(*,1) 's% mstar_dot', s% mstar_dot
      65            0 :             call mesa_error(__FILE__,__LINE__,'compute_delta_m')
      66              :          end if
      67              : 
      68           11 :          if (is_bad(delta_m)) then
      69            0 :             write(*,1) 'delta_m', delta_m
      70            0 :             call mesa_error(__FILE__,__LINE__,'compute_delta_m')
      71              :          end if
      72              : 
      73           11 :       end function compute_delta_m
      74              : 
      75           11 :       subroutine save_for_eps_mdot(s)
      76              :          use star_utils, only: eval_deltaM_total_energy_integrals
      77              :          type (star_info), pointer :: s
      78              : 
      79              :          integer :: j
      80              : 
      81              :          call eval_deltaM_total_energy_integrals( &
      82              :             s, 1, s% nz, s% mstar, .true., &
      83              :             s% total_energy_profile_before_adjust_mass, &
      84              :             s% total_internal_energy_before_adjust_mass, &
      85              :             s% total_gravitational_energy_before_adjust_mass, &
      86              :             s% total_radial_kinetic_energy_before_adjust_mass, &
      87              :             s% total_rotational_kinetic_energy_before_adjust_mass, &
      88              :             s% total_turbulent_energy_before_adjust_mass, &
      89           11 :             s% total_energy_before_adjust_mass)
      90              : 
      91        13098 :          do j=1,s%nz
      92        13098 :             s% dm_before_adjust_mass(j) = s% dm(j)
      93              :          end do
      94              : 
      95           11 :       end subroutine save_for_eps_mdot
      96              : 
      97              : 
      98              :       ! Reconstruct previous mesh based on what the mass differences should have been.
      99              :       ! This is to deal with the changes in cell mass being small (relatively speaking) at depth.
     100              :       ! That results in differences at the limit of double precision, so we need to go to quad precision.
     101              :       ! However dm and prev_mesh_dm are only known to double precision, whereas the difference between them
     102              :       ! is known to quad precision. So we take dm as given and reconstruct prev_mesh_dm using the difference.
     103            0 :       subroutine compute_prev_mesh_dm(s, prev_mesh_dm, dm, change_in_dm)
     104              :          ! Inputs
     105              :          type (star_info), pointer :: s
     106              : 
     107              :          ! Intermediates
     108              :          integer :: j, nz
     109            0 :          real(dp) :: change_sum
     110              : 
     111              :          ! Outputs
     112              :          real(qp), dimension(:), intent(out) :: prev_mesh_dm, dm, change_in_dm
     113              : 
     114              : 
     115            0 :          nz = s% nz
     116              : 
     117            0 :          change_sum = 0
     118            0 :          do j=1,nz
     119            0 :             dm(j) = s%dm(j)
     120            0 :             prev_mesh_dm(j) = s%dm_before_adjust_mass(j)
     121            0 :             if (j < s%k_below_const_q) then
     122            0 :                change_in_dm(j) = s%adjust_mass_outer_frac_sub1 * prev_mesh_dm(j)
     123            0 :             else if (j < s%k_const_mass) then
     124            0 :                change_in_dm(j) = s%adjust_mass_mid_frac_sub1 * prev_mesh_dm(j)
     125              :             else
     126            0 :                change_in_dm(j) = s%adjust_mass_inner_frac_sub1 * prev_mesh_dm(j)
     127              :             end if
     128            0 :             change_sum = change_sum + change_in_dm(j)
     129            0 :             prev_mesh_dm(j) = dm(j) - change_in_dm(j)
     130              :          end do
     131              : 
     132           11 :       end subroutine compute_prev_mesh_dm
     133              : 
     134              :       ! Updates the radii of cells after adjust mass. Note that the radius appears in many
     135              :       ! places in s. Currently those are: r, r_start, rmid, rmid_start, R2 (r^2), and lnR (log(r)).
     136              :       ! If more of these are added they should also be updated here.
     137            0 :       subroutine update_radius(s)
     138              :          use star_utils, only: store_r_in_xh, get_r_and_lnR_from_xh
     139              :          ! Inputs
     140              :          type (star_info), pointer :: s
     141              : 
     142              :          ! Intermediates
     143              :          integer :: j, nz
     144            0 :          real(dp) :: r_new, vol00, volp1, cell_vol
     145              : 
     146            0 :          nz = s%nz
     147              : 
     148            0 :          vol00 = four_thirds_pi*s% R_center*s% R_center*s% R_center
     149            0 :          do j=nz,1,-1
     150              : 
     151            0 :             volp1 = vol00
     152            0 :             cell_vol = s% dm(j)/s% rho(j)
     153            0 :             vol00 = volp1 + cell_vol
     154              : 
     155            0 :             r_new = exp(log(vol00/four_thirds_pi)*one_third)
     156              : 
     157            0 :             s%r(j) = r_new
     158            0 :             s%r_start(j) = s%r(j)
     159            0 :             s%rmid(j) = r_new
     160            0 :             s%rmid_start(j) = r_new
     161            0 :             call store_r_in_xh(s, j, r_new)
     162            0 :             call get_r_and_lnR_from_xh(s, j, s% r(j), s% lnR(j))
     163            0 :             s% xh_start(s% i_lnR,j) = s% xh(s% i_lnR,j)
     164              : 
     165              :          end do
     166              : 
     167            0 :       end subroutine update_radius
     168              : 
     169           11 :       subroutine do_adjust_mass(s, species, ierr)
     170            0 :          use adjust_xyz, only: get_xa_for_accretion
     171              :          use star_utils, only: report_xa_bad_nums, &
     172              :             start_time, update_time
     173              :          use hydro_rotation, only: set_omega
     174              :          use chem_def
     175              : 
     176              :          type (star_info), pointer :: s
     177              :          integer, intent(in) :: species
     178              :          integer, intent(out) :: ierr
     179              : 
     180              :          real(dp) :: &
     181           22 :             dt, delta_m, old_mstar, new_mstar, total, &
     182           22 :             frac, env_mass, mmax, new_xmstar, old_xmstar, removed, &
     183           33 :             q_for_just_added, xq_for_CpT_absMdot_div_L, sum_dq, dm, sumx
     184              : 
     185          198 :          real(dp), dimension(species) :: xaccrete, mtot_init
     186              :          real(dp), dimension(:), allocatable :: &
     187           11 :             rxm_old, rxm_new, old_cell_mass, new_cell_mass, &
     188           11 :             oldloc, newloc, oldval, newval, xm_old, xm_new, &
     189           11 :             xq_center_old, xq_center_new
     190           11 :          real(dp), dimension(:,:), allocatable :: xa_old
     191           11 :          real(dp), pointer :: work(:)
     192              : 
     193              :          integer :: j, k, l, m, k_const_mass, nz, k_below_just_added, k_newval
     194              :          integer(i8) :: time0
     195           11 :          real(dp) :: partial_xa_mass, region_total_mass
     196           11 :          real(dp) :: starting_j_rot_surf
     197              : 
     198              :          logical, parameter :: dbg = .false.
     199              : 
     200              :          include 'formats'
     201              : 
     202              :          if (dbg) write(*,*) 'do_adjust_mass'
     203              : 
     204           11 :          call save_for_eps_mdot(s)
     205              : 
     206           11 :          ierr = 0
     207              : 
     208           11 :          nz = s% nz
     209           11 :          dt = s% dt
     210              : 
     211              : 
     212           11 :          s% k_const_mass = 1
     213              : 
     214           11 :          s% k_for_test_CpT_absMdot_div_L = 1
     215              : 
     216           11 :          q_for_just_added = 1d0
     217           11 :          s% k_below_just_added = 1
     218              : 
     219              :          ! NOTE: don't assume that vars are all set at this point.
     220              :          ! exceptions: omega, i_rot, j_rot, and total_angular_momentum have been set.
     221              :          ! store surface j_rot, to later adjust angular momentum lost
     222           11 :          if (s% rotation_flag) then
     223            0 :             starting_j_rot_surf = s% j_rot(1)
     224              :          end if
     225              : 
     226           11 :          delta_m = compute_delta_m(s)
     227              : 
     228           11 :          if (delta_m == 0) then
     229              :             return
     230              :          end if
     231              : 
     232            0 :          if (s% doing_timing) call start_time(s, time0, total)
     233              : 
     234            0 :          s% need_to_setvars = .true.
     235              : 
     236            0 :          old_mstar = s% mstar
     237            0 :          old_xmstar = s% xmstar
     238              : 
     239            0 :          new_mstar = old_mstar + delta_m
     240            0 :          new_xmstar = old_xmstar + delta_m
     241              : 
     242            0 :          if (is_bad(new_xmstar)) then
     243            0 :             write(*,1) 'new_xmstar', new_xmstar
     244            0 :             call mesa_error(__FILE__,__LINE__,'do_adjust_mass')
     245              :          end if
     246              : 
     247              :          if (delta_m > 0 .and. s% max_star_mass_for_gain > 0 &
     248            0 :                .and. new_mstar > Msun*s% max_star_mass_for_gain) then
     249            0 :             new_mstar = Msun*s% max_star_mass_for_gain
     250            0 :             delta_m = new_mstar - old_mstar
     251            0 :             s% mstar_dot = delta_m/dt
     252            0 :          else if (delta_m < 0 .and. new_mstar < Msun*s% min_star_mass_for_loss) then
     253            0 :             new_mstar = Msun*s% min_star_mass_for_loss
     254            0 :             delta_m = new_mstar - old_mstar
     255            0 :             s% mstar_dot = delta_m/dt
     256              :          end if
     257              : 
     258            0 :          frac = old_xmstar/new_xmstar
     259            0 :          new_xmstar = old_xmstar/frac
     260            0 :          if (new_xmstar <= 0) then
     261            0 :             ierr = -1
     262            0 :             return
     263              :          end if
     264            0 :          s% xmstar = new_xmstar
     265            0 :          s% mstar = s% xmstar + s% M_center
     266              : 
     267              :          if (dbg_adjm) then
     268              :             env_mass = old_mstar - s% he_core_mass*Msun
     269              :             write(*,'(a40,f26.16)') 'env_mass/old_mstar', env_mass/old_mstar
     270              :             write(*,'(A)')
     271              :             write(*,1) 'delta_m/old_mstar', delta_m/old_mstar
     272              :             write(*,1) 's% he_core_mass*Msun', s% he_core_mass*Msun
     273              :             write(*,1) 'env_mass', env_mass
     274              :             write(*,1) 'delta_m/env_mass', delta_m/env_mass
     275              :             write(*,1) 'log10(abs(delta_m/env_mass))', safe_log10(abs(delta_m/env_mass))
     276              :             write(*,'(A)')
     277              :          end if
     278              : 
     279            0 :          call do_alloc(ierr)
     280            0 :          if (ierr /= 0) return
     281              : 
     282            0 :          do k=1,nz
     283            0 :             old_cell_mass(k) = old_xmstar*s% dq(k)
     284              :          end do
     285            0 :          xm_old(1) = 0
     286            0 :          xq_center_old(1) = 0.5d0*s% dq(1)
     287            0 :          do k=2,nz
     288            0 :             xm_old(k) = xm_old(k-1) + old_cell_mass(k-1)
     289            0 :             xq_center_old(k) = xq_center_old(k-1) + 0.5d0*(s% dq(k-1) + s% dq(k))
     290              :          end do
     291              : 
     292            0 :          s% xa_removed(1:species) = 0
     293            0 :          s% angular_momentum_removed = 0
     294            0 :          s% angular_momentum_added = 0
     295            0 :          if (delta_m < 0) then
     296            0 :             s% angular_momentum_removed = angular_momentum_removed(ierr)
     297            0 :             if (ierr /= 0) then
     298            0 :                call dealloc
     299            0 :                return
     300              :             end if
     301            0 :             removed = -delta_m
     302            0 :             do k=1,nz
     303            0 :                if (xm_old(k) >= removed) then
     304            0 :                   do j=1,species
     305            0 :                      s% xa_removed(j) = s% xa_removed(j)/removed
     306              :                   end do
     307              :                   exit
     308              :                end if
     309            0 :                do j=1,species
     310            0 :                   dm = min(old_cell_mass(k), removed-xm_old(k))
     311            0 :                   s% xa_removed(j) = s% xa_removed(j) + s% xa(j,k)*dm
     312              :                end do
     313              :             end do
     314              :          end if
     315              :          !s% angular_momentum_added is set after j_rot is adjusted in outer layers
     316              : 
     317              :          call revise_q_and_dq( &
     318            0 :             s, nz, old_xmstar, new_xmstar, delta_m, k_const_mass, ierr)
     319            0 :          if (ierr /= 0) then
     320            0 :             s% retry_message = 'revise_q_and_dq failed in adjust mass'
     321            0 :             if (s% report_ierr) write(*,*) s% retry_message
     322            0 :             call dealloc
     323            0 :             return
     324              :          end if
     325              : 
     326            0 :          mtot_init(1:species) = 0
     327            0 :          do k=1,k_const_mass  ! save total mass by species down to where constant
     328            0 :             sumx = 0
     329            0 :             do j=1,species
     330            0 :                s% xa(j,k) = max(0d0, min(1d0, s% xa(j,k)))
     331            0 :                sumx = sumx + s% xa(j,k)
     332              :             end do
     333            0 :             do j=1,species
     334            0 :                s% xa(j,k) = s% xa(j,k)/sumx
     335            0 :                mtot_init(j) = mtot_init(j) + old_cell_mass(k)*s% xa(j,k)
     336              :             end do
     337              :          end do
     338              : 
     339            0 :          do k=1,nz
     340            0 :             new_cell_mass(k) = new_xmstar*s% dq(k)
     341              :          end do
     342              : 
     343            0 :          xm_new(1) = 0
     344            0 :          xq_center_new(1) = 0.5d0*s% dq(1)
     345            0 :          do k=2,nz
     346            0 :             xm_new(k) = xm_new(k-1) + new_cell_mass(k-1)
     347            0 :             xq_center_new(k) = xq_center_new(k-1) + 0.5d0*(s% dq(k-1) + s% dq(k))
     348              :          end do
     349              : 
     350            0 :          xq_for_CpT_absMdot_div_L = abs(delta_m)/new_xmstar
     351            0 :          s% k_for_test_CpT_absMdot_div_L = nz
     352            0 :          sum_dq = 0
     353            0 :          do k = 1, nz
     354            0 :             if (sum_dq >= xq_for_CpT_absMdot_div_L) then
     355            0 :                s% k_for_test_CpT_absMdot_div_L = k; exit
     356              :             end if
     357            0 :             sum_dq = sum_dq + s% dq(k)
     358              :          end do
     359              : 
     360            0 :          if (delta_m > 0) then
     361            0 :             q_for_just_added = old_xmstar/new_xmstar
     362            0 :             s% k_below_just_added = nz
     363            0 :             do k = 1, nz
     364            0 :                if (s% q(k) <= q_for_just_added) then
     365            0 :                   s% k_below_just_added = k; exit
     366              :                end if
     367              :             end do
     368              :          end if
     369              : 
     370            0 :          k_below_just_added = s% k_below_just_added
     371            0 :          k_newval = 1
     372              : 
     373            0 :          do k=1,nz
     374            0 :             do j=1,species
     375            0 :                xa_old(j,k) = s% xa(j,k)
     376              :             end do
     377              :          end do
     378              : 
     379            0 :          if (delta_m < 0) then
     380            0 :             xaccrete(1:species) = 0  ! xaccrete not used when removing mass
     381              :          else  ! set xaccrete for composition of added material
     382            0 :             if (s% accrete_same_as_surface) then
     383            0 :                do j=1,species
     384            0 :                   xaccrete(j) = xa_old(j,1)
     385              :                end do
     386              :             else
     387            0 :                call get_xa_for_accretion(s, xaccrete, ierr)
     388            0 :                if (ierr /= 0) then
     389            0 :                   s% retry_message = 'get_xa_for_accretion failed in adjust mass'
     390            0 :                   if (s% report_ierr) write(*, *) s% retry_message
     391            0 :                   call dealloc
     392            0 :                   return
     393              :                end if
     394              :             end if
     395              :          end if
     396              : 
     397            0 :          mmax = max(old_mstar, new_mstar)
     398              : 
     399              :          ! rxm_old and rxm_new are for interpolating by mass
     400              :          ! but instead of using mass coord, we want to use external mass
     401              :          ! in order to get better accuracy near the surface.
     402              :          ! to simplify this, the zero point is the same for both rxm_old and rxm_new.
     403              :          ! that makes rxm_new = rxm_old for k >= k_const_mass.
     404            0 :          if (delta_m < 0) then
     405            0 :             rxm_old(1) = 0
     406            0 :             rxm_new(1) = -delta_m  ! note that rxm_new(1) > 0 since delta_m < 0
     407              :          else
     408            0 :             rxm_old(1) = delta_m
     409            0 :             rxm_new(1) = 0
     410              :          end if
     411            0 :          do k = 2, nz
     412            0 :             rxm_old(k) = rxm_old(k-1) + old_cell_mass(k-1)
     413            0 :             if (k >= k_const_mass) then
     414            0 :                rxm_new(k) = rxm_old(k)
     415            0 :                new_cell_mass(k) = old_cell_mass(k)
     416              :             else
     417            0 :                rxm_new(k) = rxm_new(k-1) + new_cell_mass(k-1)
     418              :             end if
     419              :          end do
     420              : 
     421              :          call set_xa(s, nz, k_const_mass, species, xa_old, xaccrete, &
     422            0 :             rxm_old, rxm_new, mmax, old_cell_mass, new_cell_mass, ierr)
     423            0 :          if (ierr /= 0) then
     424            0 :             s% retry_message = 'set_xa failed in adjust mass'
     425            0 :             if (s% report_ierr) write(*,*) s% retry_message
     426            0 :             call dealloc
     427            0 :             return
     428              :          end if
     429              : 
     430            0 :          if (s% rotation_flag) then
     431              :             ! update j_rot if have extra angular momentum change
     432              :             call set_omega_adjust_mass( &
     433              :                s, nz, k_const_mass, k_below_just_added, delta_m, &
     434              :                rxm_old, rxm_new, mmax, old_cell_mass, new_cell_mass, &
     435              :                ! reuse these work arrays
     436              :                oldloc, newloc, oldval, newval, xm_old, xm_new, &
     437            0 :                ierr)
     438            0 :             if (ierr /= 0) then
     439            0 :                s% retry_message = 'set_omega_adjust_mass failed in adjust mass'
     440            0 :                if (s% report_ierr) write(*,*) s% retry_message
     441            0 :                call dealloc
     442            0 :                return
     443              :             end if
     444            0 :             if (s% do_adjust_J_lost) then
     445            0 :                call adjust_J_lost(s, k_below_just_added, starting_j_rot_surf, ierr)
     446            0 :                if (ierr /= 0) then
     447            0 :                   s% retry_message = 'do_adjust_J_lost failed in adjust mass'
     448            0 :                   if (s% report_ierr) write(*,*) s% retry_message
     449            0 :                   call dealloc
     450            0 :                   return
     451              :                end if
     452              :             end if
     453            0 :             if (s% D_omega_flag) then
     454              :                call set_D_omega( &
     455              :                   s, nz, k_const_mass, k_newval, &
     456              :                   rxm_old, rxm_new, delta_m, old_xmstar, new_xmstar, &
     457            0 :                   s% D_omega, oldloc, newloc, oldval, newval, work, ierr)
     458            0 :                if (ierr /= 0) then
     459            0 :                   s% retry_message = 'set_D_omega failed in adjust mass'
     460            0 :                   if (s% report_ierr) write(*,*) s% retry_message
     461            0 :                   call dealloc
     462            0 :                   return
     463              :                end if
     464              :             end if
     465            0 :             if (s% am_nu_rot_flag) then
     466              :                call set_D_omega( &  ! reuse the set_D_omega routine to set am_nu_rot
     467              :                   s, nz, k_const_mass, k_newval, &
     468              :                   rxm_old, rxm_new, delta_m, old_xmstar, new_xmstar, &
     469            0 :                   s% am_nu_rot, oldloc, newloc, oldval, newval, work, ierr)
     470            0 :                if (ierr /= 0) then
     471            0 :                   s% retry_message = 'set_am_nu_rot failed in adjust mass'
     472            0 :                   if (s% report_ierr) write(*,*) s% retry_message
     473            0 :                   call dealloc
     474            0 :                   return
     475              :                end if
     476              :             end if
     477              :          end if
     478              : 
     479              :          ! soften outer xa    (Pablo -- this should be the very last step)
     480            0 :          if (s% smooth_outer_xa_big > 0.0d0 .and. s% smooth_outer_xa_small > 0.0d0) then
     481            0 :             m = 1
     482            0 :             do k = 1, s% nz
     483            0 :                if (s% m(1) - s% m(k) > s% smooth_outer_xa_big * s% m(1)) exit
     484            0 :                region_total_mass = 0
     485            0 :                m = k
     486            0 :                do l = k, s% nz
     487            0 :                   if (s% m(k) - s% m(l) > s% smooth_outer_xa_small * s% m(1) * &
     488              :                      (1-(s% m(1) - s% m(k))/(s% smooth_outer_xa_big * s% m(1)))) exit
     489            0 :                   m = l
     490            0 :                   region_total_mass = region_total_mass + s% dm(l)
     491              :                end do
     492            0 :                if (m == k) cycle
     493            0 :                do j=1,s% species
     494              :                   partial_xa_mass = 0
     495            0 :                   do l = k, m
     496            0 :                      partial_xa_mass = partial_xa_mass + s% dm(l) * s% xa(j,l)
     497              :                   end do
     498            0 :                   do l = k, m
     499            0 :                      s% xa(j,l) = partial_xa_mass / region_total_mass
     500              :                   end do
     501              :                end do
     502              :             end do
     503              :             ! fix small errors to ensure xa's add up to unity
     504            0 :             do k=1,m
     505            0 :                frac = 1d0/sum(s% xa(1:s% species,k))
     506            0 :                do j=1,s% species
     507            0 :                   s% xa(j,k) = s% xa(j,k)*frac
     508              :                end do
     509              :             end do
     510              :          end if
     511              : 
     512              : 
     513            0 :          call update_radius(s)
     514              : 
     515              : 
     516            0 :          call dealloc
     517              : 
     518              : 
     519            0 :          if (s% doing_timing) call update_time(s, time0, total, s% time_adjust_mass)
     520              : 
     521              :          if (dbg_adjm) call mesa_error(__FILE__,__LINE__,'debugging: do_adjust_mass')
     522           11 :          if (dbg) write(*,*) 'do_adjust_mass return'
     523              : 
     524              :          contains
     525              : 
     526              : 
     527            0 :          real(dp) function angular_momentum_removed(ierr) result(J)
     528              :             ! when call this, s% j_rot is still for old mass
     529              :             integer, intent(out) :: ierr
     530              :             integer :: k
     531            0 :             real(dp) :: dmm1, dm00, dm, dm_sum, dm_lost
     532              :             include 'formats'
     533            0 :             ierr = 0
     534            0 :             J = 0
     535            0 :             if (.not. s% rotation_flag) return
     536            0 :             dm00 = 0
     537            0 :             dm_sum = 0
     538            0 :             dm_lost = -delta_m
     539            0 :             do k = 1, nz
     540            0 :                dmm1 = dm00
     541            0 :                dm00 = old_cell_mass(k)
     542            0 :                dm = 0.5d0*(dmm1+dm00)
     543            0 :                if (dm_sum + dm > dm_lost) then
     544            0 :                   dm = dm_lost - dm_sum
     545            0 :                   dm_sum = dm_lost
     546              :                else
     547              :                   dm_sum = dm_sum + dm
     548              :                end if
     549            0 :                J = J + dm*s% j_rot(k)
     550            0 :                if (dm_sum == dm_lost) exit
     551              :             end do
     552           11 :          end function angular_momentum_removed
     553              : 
     554              : 
     555              :          real(dp) function eval_total_angular_momentum(s,cell_mass,nz_last) result(J)
     556              :             type (star_info), pointer :: s
     557              :             real(dp) :: cell_mass(:)
     558              :             integer, intent(in) :: nz_last
     559              :             integer :: k
     560              :             real(dp) :: dmm1, dm00, dm
     561              :             include 'formats'
     562              :             J = 0
     563              :             if (.not. s% rotation_flag) return
     564              :             dm00 = 0
     565              :             do k = 1, nz_last
     566              :                dmm1 = dm00
     567              :                dm00 = cell_mass(k)
     568              :                if (k == s% nz) then
     569              :                   dm = 0.5d0*dmm1+dm00
     570              :                else if (k == nz_last) then
     571              :                   dm = 0.5d0*dmm1
     572              :                else
     573              :                   dm = 0.5d0*(dmm1+dm00)
     574              :                end if
     575              :                J = J + dm*s% j_rot(k)
     576              :             end do
     577              :          end function eval_total_angular_momentum
     578              : 
     579            0 :          subroutine do_alloc(ierr)
     580              :             integer, intent(out) :: ierr
     581            0 :             allocate(rxm_old(nz), rxm_new(nz), old_cell_mass(nz), new_cell_mass(nz), &
     582            0 :                xa_old(species,nz), oldloc(nz), newloc(nz), oldval(nz), newval(nz), &
     583            0 :                xm_old(nz), xm_new(nz), xq_center_old(nz), xq_center_new(nz))
     584            0 :             call do_work_arrays(.true.,ierr)
     585            0 :          end subroutine do_alloc
     586              : 
     587            0 :          subroutine dealloc
     588              :             integer :: ierr
     589            0 :             call do_work_arrays(.false.,ierr)
     590              :          end subroutine dealloc
     591              : 
     592            0 :          subroutine do_work_arrays(alloc_flag, ierr)
     593              :             use interp_1d_def
     594              :             use alloc, only: work_array
     595              :             logical, intent(in) :: alloc_flag
     596              :             integer, intent(out) :: ierr
     597              :             logical, parameter :: crit = .false.
     598              :             ierr = 0
     599              :             call work_array(s, alloc_flag, crit, &
     600            0 :                 work, nz*pm_work_size, nz_alloc_extra, 'adjust_mass work', ierr)
     601            0 :             if (ierr /= 0) return
     602            0 :          end subroutine do_work_arrays
     603              : 
     604              :       end subroutine do_adjust_mass
     605              : 
     606              : 
     607            0 :       subroutine revise_q_and_dq( &
     608              :             s, nz, old_xmstar, new_xmstar, delta_m, k_const_mass, ierr)
     609              :          use star_utils, only: get_lnT_from_xh
     610              :          type (star_info), pointer :: s
     611              :          integer, intent(in) :: nz
     612              :          real(dp), intent(in) :: old_xmstar, new_xmstar, delta_m
     613              :          integer, intent(out) :: k_const_mass, ierr
     614              : 
     615              :          integer :: k, kA, kB, j00, jp1
     616            0 :          real(dp) :: lnTlim_A, lnTlim_B, sumdq, &
     617            0 :             mold_o_mnew, lnTmax, lnT_A, lnT_B, &
     618            0 :             xqA, xqB_old, xqB_new, qfrac, frac, dqacc
     619            0 :          real(dp) :: xq(nz)
     620            0 :          real(qp) :: qfrac_qp, frac_qp, mold_o_mnew_qp, q1, q2
     621            0 :          real(qp) :: adjust_mass_outer_frac, adjust_mass_mid_frac, adjust_mass_inner_frac
     622              :          integer, parameter :: min_kA = 5
     623              :          logical :: dbg, flag
     624              :          logical :: okay_to_move_kB_inward
     625              : 
     626              :          include 'formats'
     627              : 
     628            0 :          ierr = 0
     629            0 :          dbg = .false.
     630            0 :          flag = .false.
     631              : 
     632            0 :          if (is_bad(old_xmstar)) then
     633            0 :             write(*,1) 'old_xmstar', old_xmstar
     634            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     635              :          end if
     636              : 
     637            0 :          if (is_bad(new_xmstar)) then
     638            0 :             write(*,1) 'new_xmstar', new_xmstar
     639            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     640              :          end if
     641              : 
     642            0 :          if (is_bad(delta_m)) then
     643            0 :             write(*,1) 'delta_m', delta_m
     644            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     645              :          end if
     646              : 
     647              : 
     648            0 :          okay_to_move_kB_inward = .false.
     649              : 
     650            0 :          lnTlim_A = ln10*s% max_logT_for_k_below_const_q
     651            0 :          lnTlim_B = ln10*s% max_logT_for_k_const_mass
     652              : 
     653            0 :          q1 = old_xmstar
     654            0 :          q2 = new_xmstar
     655            0 :          mold_o_mnew_qp = q1/q2
     656            0 :          mold_o_mnew = mold_o_mnew_qp
     657            0 :          s% max_q_for_k_below_const_q = mold_o_mnew
     658            0 :          dqacc = delta_m / new_xmstar
     659              : 
     660              :          ! might have drifted away from summing to 1 in mesh adjustment, fix up
     661            0 :          sumdq = 0
     662            0 :          do k=1,nz
     663            0 :             sumdq = sumdq + s% dq(k)
     664              :          end do
     665            0 :          frac = 1.0d0/sumdq
     666            0 :          if (is_bad(frac)) then
     667            0 :             write(*,1) 'frac for initial renorm', frac
     668            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     669              :          end if
     670            0 :          do k = 1, nz
     671            0 :             if (is_bad(s% dq(k))) then
     672            0 :                write(*,2) 'bad dq input', s% dq(k)
     673            0 :                call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     674              :             end if
     675            0 :             s% dq(k) = s% dq(k) * frac
     676              :          end do
     677              : 
     678              :          ! will work in xq := 1-q to reduce truncation errors
     679            0 :          xq(1)=0
     680            0 :          do k = 2, nz
     681            0 :             xq(k) = xq(k-1) + s% dq(k-1)
     682              :          end do
     683              : 
     684            0 :          k = maxloc(s% xh(s% i_lnT,1:nz),dim=1)
     685            0 :          lnTmax = get_lnT_from_xh(s, k)
     686            0 :          lnT_A = min(lnTmax, lnTlim_A)
     687              : 
     688            0 :          if (is_bad(s% max_q_for_k_below_const_q)) then
     689            0 :             write(*,*) 's% max_q_for_k_below_const_q', s% max_q_for_k_below_const_q
     690            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     691              :          end if
     692            0 :          if (is_bad(s% min_q_for_k_below_const_q)) then
     693            0 :             write(*,*) 's% min_q_for_k_below_const_q', s% min_q_for_k_below_const_q
     694            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     695              :          end if
     696              : 
     697            0 :          kA = min_kA
     698            0 :          do k = min_kA, nz-1
     699            0 :             kA = k
     700            0 :             if ( (1-xq(k)) > s% max_q_for_k_below_const_q) cycle
     701            0 :             if ( 1.0d0-xq(k) <= s% min_q_for_k_below_const_q) exit
     702            0 :             if (get_lnT_from_xh(s, k) >= lnT_A) exit
     703              :          end do
     704            0 :          xqA = xq(kA)
     705              : 
     706            0 :          lnT_B = min(lnTmax, lnTlim_B)
     707              : 
     708            0 :          if (is_bad(s% max_q_for_k_const_mass)) then
     709            0 :             write(*,*) 's% max_q_for_k_const_mass', s% max_q_for_k_const_mass
     710            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     711              :          end if
     712            0 :          if (is_bad(s% min_q_for_k_const_mass)) then
     713            0 :             write(*,*) 's% min_q_for_k_const_mass', s% min_q_for_k_const_mass
     714            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     715              :          end if
     716              : 
     717            0 :          kB = kA+1
     718            0 :          do k = kB, nz
     719            0 :             kB = k
     720            0 :             if ( (1-xq(k)) > s% max_q_for_k_const_mass) cycle
     721            0 :             if ( (1-xq(k)) <= s% min_q_for_k_const_mass) exit
     722            0 :             if (get_lnT_from_xh(s, k) >= lnT_B) exit
     723              :          end do
     724              : 
     725            0 :          xqB_old = xq(kB)
     726              : 
     727              :          if (dbg_adjm) then
     728              :             write(*,*) 'kA', kA
     729              :             write(*,1) 'xqA', xqA
     730              :             write(*,*) 'kB', kB
     731              :             write(*,1) 'xqB_old', xqB_old
     732              :             write(*,'(A)')
     733              :             write(*,1) 'xqA-xqB_old', xqA-xqB_old
     734              :             write(*,'(A)')
     735              :          end if
     736              : 
     737            0 :          xqB_new = dqacc + xqB_old*mold_o_mnew  ! in order to keep m interior to kB constant
     738              :          ! same as  qB_new = qB_old*mold/mnew, but without the truncation problems
     739              : 
     740            0 :          do  ! make sure qfrac is not too far from 1 by moving kB inward
     741            0 :             q1 = xqB_new - xqA
     742            0 :             q2 = max(1d-99,xqB_old - xqA)
     743            0 :             qfrac_qp = q1/q2
     744            0 :             qfrac = qfrac_qp
     745            0 :             if (kB == nz) exit
     746            0 :             if (kB-kA > 10) then
     747            0 :                if (qfrac > 0.67d0 .and. qfrac < 1.5d0) exit
     748            0 :                if (qfrac > 0.50d0 .and. qfrac < 2.0d0) then
     749            0 :                   j00 = maxloc(s% xa(:,kB),dim=1)  ! most abundant species at kB
     750            0 :                   jp1 = maxloc(s% xa(:,kB+1),dim=1)  ! most abundant species at kB+1
     751            0 :                   if (j00 /= jp1) then  ! change in composition.
     752              :                      if (dbg) write(*,*) 'change in composition.  back up kB.'
     753            0 :                      kB = max(1,kB-5)
     754            0 :                      exit
     755              :                   end if
     756              :                end if
     757              :             end if
     758            0 :             kB = kB+1
     759            0 :             xqB_old = xq(kB)
     760            0 :             xqB_new = dqacc + xqB_old*mold_o_mnew
     761              :          end do
     762              : 
     763              :          ! set new dq's
     764              :          ! s% dq(1:kA-1) unchanged
     765            0 :          s% dq(kA:kB-1) = s% dq(kA:kB-1)*qfrac
     766            0 :          frac_qp = mold_o_mnew_qp
     767            0 :          frac = frac_qp
     768            0 :          if (is_bad(frac)) then
     769            0 :             write(*,1) 'frac for kA:kB-1', frac
     770            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     771              :          end if
     772            0 :          s% dq(kB:nz) = s% dq(kB:nz)*frac
     773              : 
     774            0 :          adjust_mass_outer_frac = 1d0
     775            0 :          adjust_mass_mid_frac = qfrac_qp
     776            0 :          adjust_mass_inner_frac = frac_qp
     777              : 
     778              :          if (dbg_adjm) then
     779              :             write(*,1) 'frac for kb:nz', frac
     780              :             write(*,1) 'qfrac for kA:kB-1', qfrac
     781              :             write(*,1) 'revise_q_and_dq sum dqs', sum(s% dq(1:nz))
     782              :             write(*,2) 'qfrac region', kB, qfrac, s% q(kB), s% lnT(kB)/ln10
     783              :             write(*,2) 'frac region', kA, frac, s% q(kA), s% lnT(kA)/ln10
     784              :             write(*,2) 'kA', kA
     785              :             write(*,2) 'kB', kB
     786              :             write(*,2) 'nz', nz
     787              :             write(*,'(A)')
     788              :             call mesa_error(__FILE__,__LINE__,'adjust_mass')
     789              :          end if
     790              : 
     791              :          ! renorm
     792            0 :          sumdq = 0
     793            0 :          do k=1,nz
     794            0 :             sumdq = sumdq + s% dq(k)
     795              :          end do
     796            0 :          q1 = 1d0
     797            0 :          q2 = sumdq
     798            0 :          frac_qp = q1/q2
     799            0 :          frac = frac_qp
     800            0 :          if (is_bad(frac)) then
     801            0 :             write(*,1) 'frac for renorm', frac
     802            0 :             call mesa_error(__FILE__,__LINE__,'revise_q_and_dq')
     803              :          end if
     804            0 :          do k = 1, nz
     805            0 :             s% dq(k) = s% dq(k) * frac
     806              :          end do
     807              : 
     808            0 :          s% adjust_mass_outer_frac_sub1 = frac_qp*adjust_mass_outer_frac*new_xmstar / old_xmstar - 1.0_qp
     809            0 :          s% adjust_mass_mid_frac_sub1 = frac_qp*adjust_mass_mid_frac*new_xmstar / old_xmstar - 1.0_qp
     810            0 :          s% adjust_mass_inner_frac_sub1 = frac_qp*adjust_mass_inner_frac*new_xmstar / old_xmstar - 1.0_qp
     811              : 
     812              :          ! set q's to match new dq's
     813            0 :          s% q(1) = 1d0
     814            0 :          sumdq = s% dq(1)
     815            0 :          do k = 2, nz-1
     816            0 :             s% q(k) = 1d0 - sumdq
     817            0 :             sumdq = sumdq + s% dq(k)
     818              :          end do
     819            0 :          s% q(nz) = 1d0 - sumdq
     820              : 
     821            0 :          s% dq(nz) = s% q(nz)
     822              : 
     823              :          ! update dm's for new dq's
     824            0 :          do k=1,nz
     825            0 :             s% dm(k) = s% dq(k) * new_xmstar
     826              :          end do
     827              : 
     828            0 :          s% k_below_const_q = kA
     829            0 :          s% k_const_mass = kB
     830            0 :          k_const_mass = kB
     831              : 
     832            0 :       end subroutine revise_q_and_dq
     833              : 
     834              : 
     835            0 :       subroutine set_xa( &
     836            0 :             s, nz, k_const_mass, species, xa_old, xaccrete, &
     837            0 :             old_cell_xbdy, new_cell_xbdy, mmax, old_cell_mass, new_cell_mass, ierr)
     838              :          ! set new values for s% xa(:,:)
     839              :          type (star_info), pointer :: s
     840              :          integer, intent(in) :: nz, k_const_mass, species
     841              :          real(dp), intent(in) :: mmax
     842              :          real(dp), intent(in) :: xa_old(:, :), xaccrete(:)
     843              :          real(dp), dimension(:), intent(in) :: &
     844              :             old_cell_xbdy, new_cell_xbdy, old_cell_mass, new_cell_mass  ! (nz)
     845              :          integer, intent(out) :: ierr
     846              :          integer :: k, j, op_err
     847              :          real(dp), parameter :: max_sum_abs = 10d0
     848              :          real(dp), parameter :: xsum_tol = 1d-2
     849              :          include 'formats'
     850            0 :          ierr = 0
     851              :          if (dbg_adjm) &
     852              :             write(*,2) 'set_xa: k_const_mass', k_const_mass
     853            0 :          if (k_const_mass < nz) then
     854              :             ! for k >= k_const_mass have m_new(k) = m_old(k),
     855              :             ! so no change in xa_new(:,k) for k > k_const_mass
     856            0 :             do k=k_const_mass+1,nz
     857            0 :                do j=1,species
     858            0 :                   s% xa(j,k) = xa_old(j,k)
     859              :                end do
     860              :             end do
     861              :          end if
     862            0 : !$OMP PARALLEL DO PRIVATE(k, op_err) SCHEDULE(dynamic,2)
     863              :          do k = 1, k_const_mass
     864              :             op_err = 0
     865              :             call set1_xa(s, k, nz, species, xa_old, xaccrete, &
     866              :                old_cell_xbdy, new_cell_xbdy, mmax, old_cell_mass, new_cell_mass, op_err)
     867              :             if (op_err /= 0) then
     868              :                if (s% report_ierr) write(*,2) 'set1_xa error', k
     869              :                ierr = op_err
     870              :             end if
     871              :          end do
     872              : !$OMP END PARALLEL DO
     873              : 
     874            0 :       end subroutine set_xa
     875              : 
     876              : 
     877            0 :       subroutine set1_xa(s, k, nz, species, xa_old, xaccrete, &
     878            0 :             old_cell_xbdy, new_cell_xbdy, mmax, old_cell_mass, new_cell_mass, ierr)
     879              :          ! set new values for s% xa(:,k)
     880              :          use num_lib, only: binary_search
     881              :          type (star_info), pointer :: s
     882              :          integer, intent(in) :: k, nz, species
     883              :          real(dp), intent(in) :: mmax
     884              :          real(dp), intent(in) :: xa_old(:,:), xaccrete(:)
     885              :          real(dp), dimension(:), intent(in) :: &
     886              :             old_cell_xbdy, new_cell_xbdy, old_cell_mass, new_cell_mass
     887              :          integer, intent(out) :: ierr
     888              : 
     889            0 :          real(dp) :: msum(species), xm_inner, sumx, &
     890            0 :             xm0, xm1, new_cell_dm, dm_sum, dm, xm_outer
     891              :          integer :: kk, k_outer, j
     892              : 
     893              :          integer, parameter :: k_dbg = -1
     894              :          logical, parameter :: xa_dbg = .false.
     895              : 
     896              :          logical, parameter :: do_not_mix_accretion = .false.
     897              : 
     898              :          logical :: partially_accreted_cell
     899              : 
     900              :          include 'formats'
     901              : 
     902            0 :          ierr = 0
     903            0 :          msum(:) = -1  ! for testing
     904              : 
     905            0 :          xm_outer = new_cell_xbdy(k)
     906            0 :          if (k == nz) then
     907            0 :             new_cell_dm = mmax - xm_outer - s% M_center
     908              :          else
     909            0 :             new_cell_dm = new_cell_mass(k)
     910              :          end if
     911            0 :          xm_inner = xm_outer + new_cell_dm
     912              : 
     913            0 :          dm_sum = 0d0
     914              : 
     915            0 :          partially_accreted_cell = .false.
     916            0 :          if (xm_outer < old_cell_xbdy(1)) then  ! there is some accreted material in new cell
     917            0 :             if (do_not_mix_accretion .or. xm_inner <= old_cell_xbdy(1)) then
     918              :                ! new cell is entirely accreted material
     919              :                !write(*,2) 'new cell is entirely accreted material', k, new_cell_dm
     920            0 :                do j=1,species
     921            0 :                   s% xa(j,k) = xaccrete(j)
     922              :                end do
     923              :                return
     924              :             end if
     925            0 :             dm = min(new_cell_dm, old_cell_xbdy(1) - xm_outer)
     926            0 :             dm_sum = dm
     927            0 :             do j=1,species
     928            0 :                msum(j) = xaccrete(j)*dm
     929              :             end do
     930            0 :             partially_accreted_cell = .true.
     931            0 :             xm_outer = old_cell_xbdy(1)
     932            0 :             k_outer = 1
     933              :          else  ! new cell entirely composed of old material
     934            0 :             msum(:) = 0
     935            0 :             if (xm_outer >= old_cell_xbdy(nz)) then
     936              :                ! new cell contained entirely in old cell nz
     937              :                k_outer = nz
     938              :             else
     939              :                ! binary search for k_outer such that
     940              :                ! xm_outer >= old_cell_xbdy(k_outer)
     941              :                ! and old_cell_xbdy(k_outer+1) > xm_outer
     942            0 :                k_outer = binary_search(nz, old_cell_xbdy, 0, xm_outer)
     943              : 
     944              :                ! check
     945            0 :                if (k_outer <= 0 .or. k_outer > nz) then
     946              : 
     947            0 :                   ierr = -1
     948            0 :                   if (.not. xa_dbg) return
     949              : 
     950              :                   write(*,2) 'k', k
     951              :                   write(*,2) 'k_outer', k_outer
     952              :                   write(*,1) 'xm_outer', xm_outer
     953              :                   write(*,2) 'old_cell_xbdy(1)', 1, old_cell_xbdy(1)
     954              :                   write(*,2) 'old_cell_xbdy(nz)', nz, old_cell_xbdy(nz)
     955              :                   call mesa_error(__FILE__,__LINE__,'debugging: set1_xa')
     956              :                end if
     957              : 
     958            0 :                if (xm_outer < old_cell_xbdy(k_outer)) then
     959              : 
     960            0 :                   ierr = -1
     961            0 :                   if (.not. xa_dbg) return
     962              : 
     963              :                   write(*,*) 'k', k
     964              :                   write(*,*) 'k_outer', k_outer
     965              :                   write(*,1) 'xm_outer', xm_outer
     966              :                   write(*,1) 'old_cell_xbdy(k_outer)', old_cell_xbdy(k_outer)
     967              :                   write(*,*) '(xm_outer < old_cell_xbdy(k_outer))'
     968              :                   call mesa_error(__FILE__,__LINE__,'debugging: set1_xa')
     969              :                end if
     970              : 
     971            0 :                if (k_outer < nz) then
     972            0 :                   if (old_cell_xbdy(k_outer+1) <= xm_outer) then
     973              : 
     974            0 :                      ierr = -1
     975            0 :                      if (.not. xa_dbg) return
     976              : 
     977              :                      write(*,*) 'k', k
     978              :                      write(*,*) 'k_outer', k_outer
     979              :                      write(*,1) 'xm_outer', xm_outer
     980              :                      write(*,1) 'old_cell_xbdy(k_outer+1)', old_cell_xbdy(k_outer+1)
     981              :                      write(*,*) '(old_cell_xbdy(k_outer+1) <= xm_outer)'
     982              :                      call mesa_error(__FILE__,__LINE__,'debugging: set1_xa')
     983              :                   end if
     984              :                end if
     985              : 
     986              :             end if
     987              :          end if
     988              : 
     989            0 :          if (k == -1) then
     990            0 :             ierr = -1
     991            0 :             if (.not. xa_dbg) return
     992              : 
     993              :             write(*,2) 'nz', nz
     994              :             write(*,2) 'k_outer', k_outer
     995              :             write(*,1) 'xm_outer', xm_outer
     996              :             write(*,1) 'xm_inner', xm_inner
     997              :          end if
     998              : 
     999            0 :          do kk = k_outer, nz  ! loop until reach m_inner
    1000            0 :             xm0 = old_cell_xbdy(kk)
    1001              : 
    1002            0 :             if (xm0 >= xm_inner) then
    1003            0 :                if (dm_sum < new_cell_dm .and. kk > 1) then
    1004              :                   ! need to add a bit more from the previous source cell
    1005            0 :                   dm = new_cell_dm - dm_sum
    1006            0 :                   dm_sum = new_cell_dm
    1007            0 :                   do j=1,species
    1008            0 :                      msum(j) = msum(j) + xa_old(j,kk-1)*dm
    1009              :                   end do
    1010              :                end if
    1011              :                exit
    1012              :             end if
    1013              : 
    1014            0 :             if (kk == nz) then
    1015            0 :                xm1 = mmax - s% M_center
    1016              :             else
    1017            0 :                xm1 = old_cell_xbdy(kk+1)
    1018              :             end if
    1019              : 
    1020            0 :             if (xm1 < xm_outer) then
    1021            0 :                ierr = -1
    1022            0 :                if (.not. xa_dbg) return
    1023              :                write(*,'(A)')
    1024              :                write(*,*) 'k', k
    1025              :                write(*,*) 'kk', kk
    1026              :                write(*,1) 'xm1', xm1
    1027              :                write(*,1) 'xm_outer', xm_outer
    1028              :                write(*,*) 'xm1 < xm_outer'
    1029              :                call mesa_error(__FILE__,__LINE__,'debugging: set1_xa')
    1030              :             end if
    1031              : 
    1032            0 :             if (xm0 >= xm_outer .and. xm1 <= xm_inner) then
    1033              :                ! entire old cell kk is in new cell k
    1034              : 
    1035            0 :                dm = old_cell_mass(kk)
    1036            0 :                dm_sum = dm_sum + dm
    1037              : 
    1038            0 :                if (dm_sum > new_cell_dm) then
    1039              :                   ! dm too large -- numerical roundoff problems
    1040            0 :                   dm = dm - (new_cell_dm - dm_sum)
    1041            0 :                   dm_sum = new_cell_dm
    1042              :                end if
    1043              : 
    1044            0 :                do j=1,species
    1045            0 :                   msum(j) = msum(j) + xa_old(j,kk)*dm
    1046              :                end do
    1047              : 
    1048            0 :             else if (xm0 <= xm_outer .and. xm1 >= xm_inner) then
    1049              :                ! entire new cell k is in old cell kk
    1050              :                !  except if it is a partially accreted cell for which xm_outer has been reset
    1051            0 :                if (partially_accreted_cell) then
    1052            0 :                   dm = xm_inner-xm_outer
    1053              :                else
    1054            0 :                   dm = new_cell_mass(k)
    1055              :                end if
    1056            0 :                dm_sum = dm_sum + dm
    1057            0 :                do j=1,species
    1058            0 :                   msum(j) = msum(j) + xa_old(j,kk)*dm
    1059              :                end do
    1060              : 
    1061              :             else  ! only use the part of old cell kk that is in new cell k
    1062              : 
    1063            0 :                if (xm_inner <= xm1) then  ! this is the last part of new cell k
    1064              : 
    1065            0 :                   dm = new_cell_dm - dm_sum
    1066            0 :                   dm_sum = new_cell_dm
    1067              : 
    1068              :                else  ! notice that we avoid this case if possible because of numerical roundoff
    1069              : 
    1070            0 :                   dm = max(0d0, xm1 - xm_outer)
    1071            0 :                   if (dm_sum + dm > new_cell_dm) dm = new_cell_dm - dm_sum
    1072            0 :                   dm_sum = dm_sum + dm
    1073              : 
    1074              :                end if
    1075              : 
    1076            0 :                do j=1,species
    1077            0 :                   msum(j) = msum(j) + xa_old(j,kk)*dm
    1078              :                end do
    1079              : 
    1080            0 :                if (dm <= 0) then
    1081            0 :                   ierr = -1
    1082            0 :                   if (.not. xa_dbg) return
    1083              :                   write(*,*) 'dm <= 0', dm
    1084              :                   call mesa_error(__FILE__,__LINE__,'debugging: set1_xa')
    1085              :                end if
    1086              : 
    1087              :             end if
    1088              : 
    1089            0 :             if (dm_sum >= new_cell_dm) then
    1090              :                exit
    1091              :             end if
    1092              : 
    1093              :          end do
    1094              : 
    1095              :          ! revise and renormalize
    1096            0 :          do j=1,species
    1097            0 :             s% xa(j,k) = msum(j) / new_cell_mass(k)
    1098              :          end do
    1099            0 :          sumx = sum(s% xa(:,k))
    1100              : 
    1101            0 :          sumx = sum(s% xa(:,k))
    1102            0 :          if (sumx <= 0d0) then
    1103            0 :             ierr = -1
    1104            0 :             return
    1105              :          end if
    1106              : 
    1107            0 :          do j=1,species
    1108            0 :             s% xa(j,k) = s% xa(j,k)/sumx
    1109              :          end do
    1110              : 
    1111            0 :       end subroutine set1_xa
    1112              : 
    1113              : 
    1114            0 :       subroutine set_omega_adjust_mass( &
    1115              :             s, nz, k_const_mass, k_below_just_added, delta_m, &
    1116            0 :             old_cell_xbdy, new_cell_xbdy, mmax, old_cell_mass, new_cell_mass, &
    1117              :             ! work arrays (nz)
    1118            0 :             old_xout, new_xout, old_dmbar, new_dmbar, old_j_rot, extra_work, &
    1119              :             ierr)
    1120            0 :          use star_utils, only: total_angular_momentum
    1121              :          type (star_info), pointer :: s
    1122              :          integer, intent(in) :: nz, k_const_mass, k_below_just_added
    1123              :          real(dp), intent(in) :: mmax, delta_m
    1124              :          real(dp), dimension(:), intent(in) :: &
    1125              :             old_cell_xbdy, new_cell_xbdy, old_cell_mass, new_cell_mass  ! (nz)
    1126              :          real(dp), dimension(:) :: &
    1127              :             old_xout, new_xout, old_dmbar, new_dmbar, old_j_rot, extra_work
    1128              :          integer, intent(out) :: ierr
    1129              : 
    1130              :          integer :: k, k0, op_err
    1131              :          logical :: okay
    1132            0 :          real(dp) :: old_j_tot, goal_total_added, actual_total_added, &
    1133            0 :             goal_total, bdy_j, bdy_total, inner_total, outer_total
    1134              : 
    1135              :          include 'formats'
    1136              : 
    1137            0 :          ierr = 0
    1138              : 
    1139            0 :          old_xout(1) = old_cell_xbdy(1)
    1140            0 :          new_xout(1) = new_cell_xbdy(1)
    1141            0 :          old_dmbar(1) = old_cell_mass(1)/2
    1142            0 :          new_dmbar(1) = new_cell_mass(1)/2
    1143            0 :          old_j_rot(1) = s% j_rot(1)
    1144            0 :          do k=2,nz
    1145            0 :             old_xout(k) = old_xout(k-1) + old_dmbar(k-1)
    1146            0 :             new_xout(k) = new_xout(k-1) + new_dmbar(k-1)
    1147            0 :             old_dmbar(k) = (old_cell_mass(k-1) + old_cell_mass(k))/2
    1148            0 :             new_dmbar(k) = (new_cell_mass(k-1) + new_cell_mass(k))/2
    1149            0 :             old_j_rot(k) = s% j_rot(k)
    1150              :          end do
    1151            0 :          old_dmbar(nz) = old_cell_mass(nz-1)/2 + old_cell_mass(nz)
    1152            0 :          new_dmbar(nz) = new_cell_mass(nz-1)/2 + new_cell_mass(nz)
    1153              : 
    1154            0 :          old_j_tot = dot_product(s% j_rot(1:nz),old_dmbar(1:nz))
    1155              : 
    1156            0 :          if (k_below_just_added == 1) then
    1157              :             k0 = 1
    1158              :          else
    1159            0 :             k0 = k_below_just_added + 1
    1160              :          end if
    1161            0 : !$OMP PARALLEL DO PRIVATE(k, op_err) SCHEDULE(dynamic,2)
    1162              :          do k = 1, k_const_mass
    1163              :             if (k < k0) then
    1164              :                cycle
    1165              :             end if
    1166              :             op_err = 0
    1167              :             call set1_omega(s, k, k_below_just_added, nz, &
    1168              :                old_xout, new_xout, mmax, old_dmbar, new_dmbar, old_j_rot, op_err)
    1169              :             if (op_err /= 0) ierr = op_err
    1170              :          end do
    1171              : !$OMP END PARALLEL DO
    1172              : 
    1173            0 :          if (k_below_just_added > 1) then
    1174              :             ! set omega in cells with newly added material
    1175            0 :             if (s% use_accreted_material_j) then
    1176            0 :                actual_total_added = 0d0
    1177            0 :                do k=1,k_below_just_added-2  ! remaining 2 done below
    1178            0 :                   s% j_rot(k) = s% accreted_material_j
    1179            0 :                   call set1_irot(s, k, k_below_just_added, .true.)
    1180            0 :                   s% omega(k) = s% j_rot(k)/s% i_rot(k)% val
    1181            0 :                   actual_total_added = actual_total_added + s% j_rot(k)*new_dmbar(k)
    1182              :                end do
    1183              :                k = k_below_just_added
    1184            0 :                goal_total_added = delta_m*s% accreted_material_j
    1185            0 :                goal_total = old_j_tot + goal_total_added
    1186            0 :                inner_total = dot_product(s% j_rot(k+1:nz),new_dmbar(k+1:nz))
    1187            0 :                outer_total = dot_product(s% j_rot(1:k-2),new_dmbar(1:k-2))
    1188            0 :                bdy_total = goal_total - (inner_total + outer_total)
    1189            0 :                bdy_j = bdy_total/sum(new_dmbar(k-1:k))
    1190            0 :                if (bdy_j <= 0) then
    1191            0 :                   ierr = -1
    1192              :                   return
    1193              :                end if
    1194            0 :                do k=k_below_just_added-1,k_below_just_added
    1195            0 :                   s% j_rot(k) = bdy_j
    1196            0 :                   call set1_irot(s, k, k_below_just_added, .true.)
    1197            0 :                   s% omega(k) = s% j_rot(k)/s% i_rot(k)% val
    1198              :                end do
    1199              :             else  ! use old surface omega in all the new material
    1200            0 :                do k=1,k_below_just_added-1
    1201            0 :                   s% omega(k) = s% omega(k_below_just_added)
    1202            0 :                   call set1_irot(s, k, k_below_just_added, .false.)
    1203            0 :                   s% j_rot(k) = s% omega(k)*s% i_rot(k)% val
    1204              :                end do
    1205              :             end if
    1206              :          end if
    1207              : 
    1208            0 :          okay = .true.
    1209            0 :          do k=1,nz
    1210            0 :             if (is_bad(s% omega(k)) .or. &
    1211            0 :               abs(s% omega(k)) > 1d50) then
    1212            0 :                if (s% report_ierr) then
    1213            0 : !$OMP critical (star_adjust_mass_omega)
    1214            0 :                   write(*,2) 's% omega(k)', k, s% omega(k)
    1215              : !$OMP end critical (star_adjust_mass_omega)
    1216              :                end if
    1217            0 :                if (s% stop_for_bad_nums) then
    1218            0 :                   write(*,2) 's% omega(k)', k, s% omega(k)
    1219            0 :                   call mesa_error(__FILE__,__LINE__,'set_omega_adjust_mass')
    1220              :                end if
    1221              :                okay = .false.
    1222              :             end if
    1223              :          end do
    1224            0 :          if (.not. okay) then
    1225            0 :             write(*,2) 'model_number', s% model_number
    1226            0 :             call mesa_error(__FILE__,__LINE__,'set_omega_adjust_mass')
    1227              :          end if
    1228              : 
    1229            0 :       end subroutine set_omega_adjust_mass
    1230              : 
    1231              : 
    1232            0 :       subroutine set1_irot(s, k, k_below_just_added, jrot_known)  ! using lnR_for_d_dt_const_m
    1233            0 :          use hydro_rotation, only: eval_i_rot, w_div_w_roche_jrot, w_div_w_roche_omega
    1234              :          use star_utils, only: get_r_from_xh
    1235              :          type (star_info), pointer :: s
    1236              :          integer, intent(in) :: k, k_below_just_added
    1237              :          logical, intent(in) :: jrot_known
    1238              : 
    1239              :          real(dp) :: r00
    1240            0 :          real(dp) :: w_div_wcrit_roche
    1241              : 
    1242            0 :          r00 = get_r_from_xh(s,k)
    1243              :          ! The moment of inertia depends
    1244              :          ! on the ratio of rotational frequency to its critical value.
    1245              :          ! This ratio is computed in two different ways depending on whether
    1246              :          ! omega or j_rot is known.
    1247            0 :          if (jrot_known) then
    1248              :             w_div_wcrit_roche = w_div_w_roche_jrot(r00,s% m(k),s% j_rot(k),s% cgrav(k), &
    1249            0 :                s% w_div_wcrit_max, s% w_div_wcrit_max2, s% w_div_wc_flag)
    1250              :          else
    1251              :             w_div_wcrit_roche = w_div_w_roche_omega(r00,s% m(k),s% omega(k),s% cgrav(k), &
    1252            0 :                s% w_div_wcrit_max, s% w_div_wcrit_max2, s% w_div_wc_flag)
    1253              :          end if
    1254              : 
    1255            0 :          call eval_i_rot(s, k, r00, w_div_wcrit_roche, s% i_rot(k))
    1256              : 
    1257            0 :       end subroutine set1_irot
    1258              : 
    1259              : 
    1260              :       ! this works like set1_xa except shifted to cell edge instead of cell center
    1261            0 :       subroutine set1_omega(s, k, k_below_just_added, nz, &
    1262            0 :             old_xout, new_xout, mmax, old_dmbar, new_dmbar, old_j_rot, ierr)
    1263              :          ! set new value for s% omega(k)
    1264            0 :          use num_lib, only: binary_search
    1265              :          type (star_info), pointer :: s
    1266              :          integer, intent(in) :: k, k_below_just_added, nz
    1267              :          real(dp), intent(in) :: mmax
    1268              :          real(dp), dimension(:), intent(in) :: &
    1269              :             old_xout, new_xout, old_dmbar, new_dmbar, old_j_rot
    1270              :          integer, intent(out) :: ierr
    1271              : 
    1272            0 :          real(dp) :: xm_outer, xm_inner, j_tot, xm0, xm1, new_point_dmbar, &
    1273            0 :             dm_sum, dm
    1274              :          integer :: kk, k_outer
    1275              : 
    1276              :          integer, parameter :: k_dbg = -1
    1277              : 
    1278              :          include 'formats'
    1279              : 
    1280            0 :          ierr = 0
    1281              : 
    1282            0 :          xm_outer = new_xout(k)
    1283            0 :          if (k == nz) then
    1284            0 :             new_point_dmbar = mmax - xm_outer - s% M_center
    1285              :          else
    1286            0 :             new_point_dmbar = new_dmbar(k)
    1287              :          end if
    1288            0 :          xm_inner = xm_outer + new_point_dmbar
    1289              : 
    1290            0 :          if (k == k_dbg) then
    1291            0 :             write(*,2) 'xm_outer', k, xm_outer
    1292            0 :             write(*,2) 'xm_inner', k, xm_inner
    1293            0 :             write(*,2) 'new_point_dmbar', k, new_point_dmbar
    1294              :          end if
    1295              : 
    1296              :          !write(*,*)
    1297              :          !write(*,2) 'xm_outer', k, xm_outer
    1298              : 
    1299            0 :          dm_sum = 0d0
    1300              : 
    1301            0 :          if (xm_outer < old_xout(1)) then  ! there is some accreted material in new
    1302            0 :             if (xm_inner <= old_xout(1)) then
    1303              :                ! new is entirely accreted material
    1304              :                !write(*,2) 'new is entirely accreted material', k, new_point_dmbar
    1305            0 :                s% omega(k) = 0
    1306            0 :                return
    1307              :             end if
    1308            0 :             dm = min(new_point_dmbar, old_xout(1) - xm_outer)
    1309            0 :             dm_sum = dm
    1310            0 :             j_tot = 0
    1311            0 :             xm_outer = old_xout(1)
    1312            0 :             k_outer = 1
    1313              :          else  ! new entirely composed of old material
    1314            0 :             if (k == k_dbg) write(*,*) 'new entirely composed of old material'
    1315            0 :             j_tot = 0
    1316            0 :             if (xm_outer >= old_xout(nz)) then
    1317              :                ! new contained entirely in old nz
    1318            0 :                k_outer = nz
    1319              :             else
    1320              :                ! binary search for k_outer such that
    1321              :                ! xm_outer >= old_xout(k_outer)
    1322              :                ! and old_xout(k_outer+1) > xm_outer
    1323            0 :                k_outer = binary_search(nz, old_xout, 0, xm_outer)
    1324              : 
    1325            0 :                if (k == k_dbg) &
    1326            0 :                   write(*,2) 'k_outer', k_outer, old_xout(k_outer), old_xout(k_outer+1)
    1327              : 
    1328              :                ! check
    1329            0 :                if (k_outer <= 0 .or. k_outer > nz) then
    1330            0 :                   ierr = -1
    1331            0 :                   return
    1332              :                end if
    1333              : 
    1334            0 :                if (xm_outer < old_xout(k_outer)) then
    1335            0 :                   ierr = -1
    1336            0 :                   return
    1337              :                end if
    1338              : 
    1339            0 :                if (k_outer < nz) then
    1340            0 :                   if (old_xout(k_outer+1) <= xm_outer) then
    1341            0 :                      ierr = -1
    1342            0 :                      return
    1343              :                   end if
    1344              :                end if
    1345              : 
    1346              :             end if
    1347              :          end if
    1348              : 
    1349            0 :          if (k == -1) then
    1350            0 :             ierr = -1
    1351            0 :             return
    1352              :          end if
    1353              : 
    1354            0 :          do kk = k_outer, nz  ! loop until reach xm_inner
    1355            0 :             xm0 = old_xout(kk)
    1356              : 
    1357              :             if (k == k_dbg) write(*,2) 'kk', kk, old_xout(kk), old_xout(kk+1)
    1358              : 
    1359            0 :             if (xm0 >= xm_inner) then
    1360            0 :                if (dm_sum < new_point_dmbar .and. kk > 1) then
    1361              :                   ! need to add a bit more from the previous source
    1362            0 :                   dm = new_point_dmbar - dm_sum
    1363            0 :                   dm_sum = new_point_dmbar
    1364            0 :                   j_tot = j_tot + old_j_rot(kk-1)*dm
    1365              :                end if
    1366              :                exit
    1367              :             end if
    1368              : 
    1369            0 :             if (kk == nz) then
    1370            0 :                xm1 = mmax - s% M_center
    1371              :             else
    1372            0 :                xm1 = old_xout(kk+1)
    1373              :             end if
    1374              : 
    1375            0 :             if (xm1 < xm_outer) then
    1376            0 :                ierr = -1
    1377            0 :                return
    1378              :             end if
    1379              : 
    1380            0 :             if (xm0 >= xm_outer .and. xm1 <= xm_inner) then  ! entire old kk is in new k
    1381              : 
    1382            0 :                dm = old_dmbar(kk)
    1383            0 :                dm_sum = dm_sum + dm
    1384              : 
    1385            0 :                if (dm_sum > new_point_dmbar) then
    1386              :                   ! dm too large -- numerical roundoff problems
    1387            0 :                   dm = dm - (new_point_dmbar - dm_sum)
    1388            0 :                   dm_sum = new_point_dmbar
    1389              :                end if
    1390              : 
    1391            0 :                j_tot = j_tot + old_j_rot(kk)*dm
    1392              : 
    1393            0 :             else if (xm0 <= xm_outer .and. xm1 >= xm_inner) then  ! entire new k is in old kk
    1394              : 
    1395            0 :                dm = new_dmbar(k)
    1396            0 :                dm_sum = dm_sum + dm
    1397            0 :                j_tot = j_tot + old_j_rot(kk)*dm
    1398              : 
    1399              :             else  ! only use the part of old kk that is in new k
    1400              : 
    1401              :                if (k == k_dbg) then
    1402              :                   write(*,*) 'only use the part of old kk that is in new k', xm_inner <= xm1
    1403              :                   write(*,1) 'xm_outer', xm_outer
    1404              :                   write(*,1) 'xm_inner', xm_inner
    1405              :                   write(*,1) 'xm0', xm0
    1406              :                   write(*,1) 'xm1', xm1
    1407              :                   write(*,1) 'dm_sum', dm_sum
    1408              :                   write(*,1) 'new_point_dmbar', new_point_dmbar
    1409              :                   write(*,1) 'new_point_dmbar - dm_sum', new_point_dmbar - dm_sum
    1410              :                end if
    1411              : 
    1412            0 :                if (xm_inner <= xm1) then  ! this is the last part of new k
    1413              : 
    1414              :                   if (k == k_dbg) write(*,3) 'this is the last part of new k', k, kk
    1415              : 
    1416            0 :                   dm = new_point_dmbar - dm_sum
    1417            0 :                   dm_sum = new_point_dmbar
    1418              : 
    1419              :                else
    1420              :                   ! notice that we avoid this case if possible because of numerical roundoff
    1421              : 
    1422              :                   if (k == k_dbg) write(*,3) 'we avoid this case if possible', k, kk
    1423              : 
    1424            0 :                   dm = max(0d0, xm1 - xm_outer)
    1425            0 :                   if (dm_sum + dm > new_point_dmbar) dm = new_point_dmbar - dm_sum
    1426            0 :                   dm_sum = dm_sum + dm
    1427              : 
    1428              :                end if
    1429              : 
    1430            0 :                j_tot = j_tot + old_j_rot(kk)*dm
    1431              : 
    1432            0 :                if (dm <= 0) then
    1433            0 :                   ierr = -1
    1434            0 :                   return
    1435              :                end if
    1436              : 
    1437              :             end if
    1438              : 
    1439            0 :             if (dm_sum >= new_point_dmbar) then
    1440              :                if (k == k_dbg) then
    1441              :                   write(*,2) 'exit for k', k
    1442              :                   write(*,2) 'dm_sum', kk, dm_sum
    1443              :                   write(*,2) 'new_point_dmbar', kk, new_point_dmbar
    1444              :                end if
    1445            0 :                dm_sum = new_point_dmbar
    1446            0 :                exit
    1447              :             end if
    1448              : 
    1449              :          end do
    1450              : 
    1451            0 :          if (dm_sum /= new_point_dmbar) then
    1452            0 :             if (k == nz) then
    1453            0 :                j_tot = j_tot + old_j_rot(nz)*(new_point_dmbar - dm_sum)
    1454              :             else
    1455            0 :                ierr = -1
    1456            0 :                return
    1457              :             end if
    1458              :          end  if
    1459              : 
    1460            0 :          s% j_rot(k) = j_tot/new_point_dmbar
    1461            0 :          call set1_irot(s, k, k_below_just_added, .true.)
    1462            0 :          s% omega(k) = s% j_rot(k)/s% i_rot(k)% val
    1463              : 
    1464              :          if (k_dbg == k) then
    1465              :             write(*,2) 's% omega(k)', k, s% omega(k)
    1466              :             write(*,2) 's% j_rot(k)', k, s% j_rot(k)
    1467              :             write(*,2) 's% i_rot(k)% val', k, s% i_rot(k)% val
    1468              :             call mesa_error(__FILE__,__LINE__,'debugging: set1_omega')
    1469              :          end if
    1470              : 
    1471            0 :       end subroutine set1_omega
    1472              : 
    1473              :       ! before mix, remove  actual_J_lost - s% angular_momentum_removed
    1474              :       ! then set s% angular_momentum_removed to actual_J_lost
    1475              : 
    1476            0 :       subroutine adjust_J_lost(s, k_below_just_added, starting_j_rot_surf, ierr)
    1477              :          type (star_info), pointer :: s
    1478              :          integer, intent(in) :: k_below_just_added
    1479              :          real(dp), intent(in) :: starting_j_rot_surf
    1480              :          integer, intent(out) :: ierr
    1481              : 
    1482            0 :          real(dp) :: dmm1, dm00, dm, J, mass_lost, j_for_mass_loss, &
    1483            0 :             actual_J_lost, delta_J, frac, qlast, jnew, J_removed
    1484              : 
    1485              :          integer :: k, last_k
    1486              : 
    1487              :          include 'formats'
    1488              : 
    1489            0 :          ierr = 0
    1490              : 
    1491            0 :          mass_lost = s% mstar_old - s% mstar
    1492            0 :          if (mass_lost <= 0) then
    1493            0 :             s% adjust_J_q = 1d0  ! nothing to do
    1494            0 :             return
    1495              :          end if
    1496              : 
    1497              :          ! can use a different j to account for things like wind braking
    1498            0 :          if (s% use_other_j_for_adjust_J_lost) then
    1499            0 :             call s% other_j_for_adjust_J_lost(s% id, starting_j_rot_surf, j_for_mass_loss, ierr)
    1500            0 :             if (ierr /= 0) then
    1501            0 :                write(*,*) "Error in other_j_for_adjust_J_lost"
    1502            0 :                return
    1503              :             end if
    1504              :          else
    1505            0 :             j_for_mass_loss = starting_j_rot_surf
    1506              :          end if
    1507              : 
    1508              :          actual_J_lost = &
    1509              :             s% adjust_J_fraction*mass_lost*j_for_mass_loss + &
    1510            0 :             (1d0 - s% adjust_J_fraction)*s% angular_momentum_removed
    1511            0 :          delta_J = actual_J_lost - s% angular_momentum_removed
    1512              : 
    1513            0 :          if (delta_J == 0d0) then
    1514              :             ! this means the model is not rotating, but with rotation flag on, nothing to do
    1515            0 :             s% adjust_J_q = 1d0
    1516            0 :             return
    1517              :          end if
    1518              : 
    1519            0 :          dm00 = 0
    1520            0 :          J = 0
    1521            0 :          last_k = s% nz
    1522            0 :          do k = 1, s% nz
    1523            0 :             dmm1 = dm00
    1524            0 :             dm00 = s% dm(k)
    1525            0 :             dm = 0.5d0*(dmm1+dm00)
    1526            0 :             J = J + dm*s% j_rot(k)
    1527              :             if (J < s% min_J_div_delta_J*abs(delta_J) &
    1528            0 :                .or. s% q(k) > s% min_q_for_adjust_J_lost) cycle
    1529              :             last_k = k
    1530            0 :             exit
    1531              :          end do
    1532            0 :          if (last_k == s% nz) then
    1533            0 :             ierr = 1
    1534            0 :             write(*,*) "Error in adjust_J_lost: last_q = nz"
    1535            0 :             return
    1536              :          end if
    1537              : 
    1538              :          ! adjust in a manner that distributes the shear
    1539              :          ! at each layer above last_k the specific angular momentum is scaled by a factor
    1540              :          ! (frac(q-qlast)+1), where frac is computed such that the total change in angular momentum
    1541              :          ! matches delta_J
    1542              :          ! NOTE: this could in principle cause counter-rotation depending on the choice of
    1543              :          ! parameters, but since j_rot normally rises steeply towards the surface its unlikely.
    1544            0 :          dm00 = 0
    1545            0 :          frac = 0
    1546            0 :          qlast = s% q(last_k)
    1547            0 :          s% adjust_J_q = qlast
    1548            0 :          do k = 1, last_k-1
    1549            0 :             dmm1 = dm00
    1550            0 :             dm00 = s% dm(k)
    1551            0 :             dm = 0.5d0*(dmm1+dm00)
    1552            0 :             frac = frac + (s% q(k) - qlast)*s% j_rot(k)*dm
    1553              :          end do
    1554            0 :          frac = -delta_J/frac
    1555              : 
    1556            0 :          dm00 = 0
    1557            0 :          J_removed = 0d0
    1558            0 :          do k = 1, last_k-1
    1559            0 :             dmm1 = dm00
    1560            0 :             dm00 = s% dm(k)
    1561            0 :             dm = 0.5d0*(dmm1+dm00)
    1562            0 :             jnew = (frac*(s% q(k)-qlast)+1)*s% j_rot(k)
    1563            0 :             J_removed = J_removed + dm*(s% j_rot(k) - jnew)
    1564            0 :             s% j_rot(k) = jnew
    1565            0 :             call set1_irot(s, k, k_below_just_added, .true.)
    1566            0 :             s% omega(k) = s% j_rot(k)/s% i_rot(k)% val
    1567              :          end do
    1568              : 
    1569            0 :          s% angular_momentum_removed = actual_J_lost
    1570              : 
    1571            0 :       end subroutine adjust_J_lost
    1572              : 
    1573              : 
    1574            0 :       subroutine set_D_omega( &
    1575              :             s, nz, k_const_mass, k_newval, &
    1576            0 :             rxm_old, rxm_new, delta_m, old_xmstar, new_xmstar, &
    1577            0 :             D_omega, oldloc, newloc, oldval, newval, work, ierr)
    1578              :          use interp_1d_lib
    1579              :          use interp_1d_def
    1580              :          type (star_info), pointer :: s
    1581              :          integer, intent(in) :: nz, k_const_mass, k_newval
    1582              :          real(dp), dimension(:), intent(in) :: rxm_old, rxm_new  ! (nz)
    1583              :          real(dp), intent(in) :: delta_m, old_xmstar, new_xmstar
    1584              :          real(dp), dimension(:) :: &
    1585              :             D_omega, oldloc, newloc, oldval, newval
    1586              : 
    1587              :          real(dp), pointer :: work(:)
    1588              : 
    1589              :          integer, intent(out) :: ierr
    1590              : 
    1591              :          integer :: n, nwork, k
    1592              :          logical :: dbg
    1593              : 
    1594              :          include 'formats'
    1595              : 
    1596            0 :          ierr = 0
    1597              : 
    1598            0 :          dbg = .false.
    1599            0 :          n = nz  ! k_const_mass
    1600            0 :          nwork = pm_work_size
    1601              : 
    1602            0 :          oldloc(1) = 0
    1603            0 :          do k=2,n
    1604            0 :             oldloc(k) = rxm_old(k)
    1605              :          end do
    1606            0 :          do k=1,n
    1607            0 :             newloc(k) = rxm_new(k)
    1608            0 :             oldval(k) = D_omega(k)
    1609              :          end do
    1610              : 
    1611              :          call interpolate_vector( &
    1612              :             n, oldloc, n, newloc, oldval, newval, interp_pm, nwork, work, &
    1613            0 :             'adjust_mass set_D_omega', ierr)
    1614            0 :          if (ierr /= 0) return
    1615            0 :          do k=1,k_newval-1
    1616            0 :             D_omega(k) = 0d0
    1617              :          end do
    1618            0 :          do k=k_newval,n
    1619            0 :             D_omega(k) = newval(k)
    1620              :          end do
    1621              : 
    1622            0 :       end subroutine set_D_omega
    1623              : 
    1624              :       end module adjust_mass
        

Generated by: LCOV version 2.0-1